From 18d5669355d27e6ee70512535f073d1b8c912807 Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Thu, 16 Dec 2021 12:31:29 +0100 Subject: [PATCH 001/377] Fix tests for Python 3.10.1 (2) (#11756) Followup to #11752. The syntax error changed between 3.10.0 and 3.10.1. https://bugs.python.org/issue46004 I missed a few the first time around unfortunately. https://bugs.python.org/issue46004 Instead of duplicating the original output, I chose to extend the test syntax introduced with #10404 and added support for == version checks. --- mypy/test/data.py | 20 +++++++++++++++----- test-data/unit/check-errorcodes.test | 4 +--- test-data/unit/fine-grained-blockers.test | 18 +++++++++--------- test-data/unit/parse.test | 4 ++-- 4 files changed, 27 insertions(+), 19 deletions(-) diff --git a/mypy/test/data.py b/mypy/test/data.py index 17cda87c1bd3c..e886b11ffa8e6 100644 --- a/mypy/test/data.py +++ b/mypy/test/data.py @@ -114,9 +114,11 @@ def parse_test_case(case: 'DataDrivenTestCase') -> None: if arg == 'skip-path-normalization': normalize_output = False if arg.startswith("version"): - if arg[7:9] != ">=": + compare_op = arg[7:9] + if compare_op not in {">=", "=="}: raise ValueError( - "{}, line {}: Only >= version checks are currently supported".format( + "{}, line {}: Only >= and == version checks are currently supported" + .format( case.file, item.line ) ) @@ -127,9 +129,17 @@ def parse_test_case(case: 'DataDrivenTestCase') -> None: raise ValueError( '{}, line {}: "{}" is not a valid python version'.format( case.file, item.line, version_str)) - if not sys.version_info >= version: - version_check = False - + if compare_op == ">=": + version_check = sys.version_info >= version + elif compare_op == "==": + if not 1 < len(version) < 4: + raise ValueError( + '{}, line {}: Only minor or patch version checks ' + 'are currently supported with "==": "{}"'.format( + case.file, item.line, version_str + ) + ) + version_check = sys.version_info[:len(version)] == version if version_check: tmp_output = [expand_variables(line) for line in item.data] if os.path.sep == '\\' and normalize_output: diff --git a/test-data/unit/check-errorcodes.test b/test-data/unit/check-errorcodes.test index 1ceafaed8dff8..2f84ee1f4c6e5 100644 --- a/test-data/unit/check-errorcodes.test +++ b/test-data/unit/check-errorcodes.test @@ -34,10 +34,8 @@ reveal_type(1) # N: Revealed type is "Literal[1]?" 1 '' [out] main:1: error: invalid syntax [syntax] -[out version>=3.10] +[out version==3.10.0] main:1: error: invalid syntax. Perhaps you forgot a comma? [syntax] -[out version>=3.10.1] -main:1: error: invalid syntax [syntax] [case testErrorCodeSyntaxError2] def f(): # E: Type signature has too many arguments [syntax] diff --git a/test-data/unit/fine-grained-blockers.test b/test-data/unit/fine-grained-blockers.test index 17a5c42c1128a..66a68115afa53 100644 --- a/test-data/unit/fine-grained-blockers.test +++ b/test-data/unit/fine-grained-blockers.test @@ -156,7 +156,7 @@ class C: a.py:1: error: invalid syntax == main:5: error: Missing positional argument "x" in call to "f" of "C" -[out version>=3.10] +[out version==3.10.0] == a.py:1: error: invalid syntax. Perhaps you forgot a comma? == @@ -176,7 +176,7 @@ main:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missin a.py:1: error: invalid syntax == main:2: error: Too many arguments for "f" -[out version>=3.10] +[out version==3.10.0] main:1: error: Cannot find implementation or library stub for module named "a" main:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports == @@ -259,7 +259,7 @@ a.py:1: error: invalid syntax a.py:1: error: invalid syntax == a.py:2: error: Missing positional argument "x" in call to "f" -[out version>=3.10] +[out version==3.10.0] == a.py:1: error: invalid syntax. Perhaps you forgot a comma? == @@ -330,7 +330,7 @@ a.py:1: error: invalid syntax main:1: error: Cannot find implementation or library stub for module named "a" main:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports b.py:1: error: Cannot find implementation or library stub for module named "a" -[out version>=3.10] +[out version==3.10.0] == a.py:1: error: invalid syntax. Perhaps you forgot a comma? == @@ -358,7 +358,7 @@ a.py:1: error: invalid syntax b.py:1: error: Cannot find implementation or library stub for module named "a" b.py:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports main:1: error: Cannot find implementation or library stub for module named "a" -[out version>=3.10] +[out version==3.10.0] == a.py:1: error: invalid syntax. Perhaps you forgot a comma? == @@ -388,7 +388,7 @@ a.py:1: error: invalid syntax == b.py:2: error: Module has no attribute "f" b.py:3: error: "int" not callable -[out version>=3.10] +[out version==3.10.0] == a.py:1: error: invalid syntax. Perhaps you forgot a comma? == @@ -411,7 +411,7 @@ def f() -> None: pass /test-data/unit/lib-stub/blocker.pyi:2: error: invalid syntax == a.py:1: error: "int" not callable -[out version>=3.10] +[out version==3.10.0] == /test-data/unit/lib-stub/blocker.pyi:2: error: invalid syntax. Perhaps you forgot a comma? == @@ -490,7 +490,7 @@ a.py:1: error: invalid syntax /test-data/unit/lib-stub/blocker.pyi:2: error: invalid syntax == a.py:2: error: "int" not callable -[out version>=3.10] +[out version==3.10.0] == a.py:1: error: invalid syntax. Perhaps you forgot a comma? == @@ -515,7 +515,7 @@ a.py:1: error: invalid syntax == b.py:2: error: Incompatible return value type (got "str", expected "int") == -[out version>=3.10] +[out version==3.10.0] a.py:1: error: invalid syntax. Perhaps you forgot a comma? == b.py:2: error: Incompatible return value type (got "str", expected "int") diff --git a/test-data/unit/parse.test b/test-data/unit/parse.test index 7f3694120b125..ff892ce0ce05a 100644 --- a/test-data/unit/parse.test +++ b/test-data/unit/parse.test @@ -935,7 +935,7 @@ MypyFile:1( x not y [out] main:1: error: invalid syntax -[out version>=3.10] +[out version==3.10.0] main:1: error: invalid syntax. Perhaps you forgot a comma? [case testNotIs] @@ -946,7 +946,7 @@ x not is y # E: invalid syntax 1 ~ 2 [out] main:1: error: invalid syntax -[out version>=3.10] +[out version==3.10.0] main:1: error: invalid syntax. Perhaps you forgot a comma? [case testSliceInList39] From 7869550862caf3389cb3c22e0f05f70b0d411309 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 16 Dec 2021 12:11:08 +0000 Subject: [PATCH 002/377] Update version to 0.930+dev (#11770) This is for the 0.930 release branch. I'll update the master to 0.940+dev afterwards. --- mypy/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/version.py b/mypy/version.py index b45a02330d6ef..715992f849129 100644 --- a/mypy/version.py +++ b/mypy/version.py @@ -5,7 +5,7 @@ # - Release versions have the form "0.NNN". # - Dev versions have the form "0.NNN+dev" (PLUS sign to conform to PEP 440). # - For 1.0 we'll switch back to 1.2.3 form. -__version__ = '0.920+dev' +__version__ = '0.930+dev' base_version = __version__ mypy_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) From 4602c4dad026dcc64cb94d531d5ce4615c7c3a01 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 16 Dec 2021 12:56:20 +0000 Subject: [PATCH 003/377] Update version to 0.940+dev (#11771) --- mypy/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/version.py b/mypy/version.py index 715992f849129..8877d01e5bb82 100644 --- a/mypy/version.py +++ b/mypy/version.py @@ -5,7 +5,7 @@ # - Release versions have the form "0.NNN". # - Dev versions have the form "0.NNN+dev" (PLUS sign to conform to PEP 440). # - For 1.0 we'll switch back to 1.2.3 form. -__version__ = '0.930+dev' +__version__ = '0.940+dev' base_version = __version__ mypy_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) From 5253f7c0214f598bdc8b96e0e90e9dd459a96b25 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Fri, 17 Dec 2021 15:04:05 -0800 Subject: [PATCH 004/377] curses.tigetstr() can return None (#11781) Found by python/typeshed#6620 --- mypy/util.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mypy/util.py b/mypy/util.py index b25f069d845d9..533e9c6bee6e9 100644 --- a/mypy/util.py +++ b/mypy/util.py @@ -566,11 +566,12 @@ def initialize_unix_colors(self) -> bool: under = curses.tigetstr('smul') set_color = curses.tigetstr('setaf') set_eseq = curses.tigetstr('cup') + normal = curses.tigetstr('sgr0') - if not (bold and under and set_color and set_eseq): + if not (bold and under and set_color and set_eseq and normal): return False - self.NORMAL = curses.tigetstr('sgr0').decode() + self.NORMAL = normal.decode() self.BOLD = bold.decode() self.UNDER = under.decode() self.DIM = parse_gray_color(set_eseq) From 63abf4b5b26edb2c7db2a9ff50dfa0e63a43434a Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Sat, 18 Dec 2021 17:29:53 +0300 Subject: [PATCH 005/377] Fixes docs: there's no `semantic_analyzer_pass3` anymore (#11788) --- mypy/build.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/mypy/build.py b/mypy/build.py index 5eebc0a22a85f..f3df5f18f54dd 100644 --- a/mypy/build.py +++ b/mypy/build.py @@ -539,8 +539,6 @@ class BuildManager: modules: Mapping of module ID to MypyFile (shared by the passes) semantic_analyzer: Semantic analyzer, pass 2 - semantic_analyzer_pass3: - Semantic analyzer, pass 3 all_types: Map {Expression: Type} from all modules (enabled by export_types) options: Build options missing_modules: Set of modules that could not be imported encountered so far From 56684e43a14e3782409c47e99bb47191d631a3de Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sun, 19 Dec 2021 15:17:28 -0800 Subject: [PATCH 006/377] [mypy_primer] run using 3.10 (#11798) Co-authored-by: hauntsaninja <> --- .github/workflows/mypy_primer.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/mypy_primer.yml b/.github/workflows/mypy_primer.yml index fcd8b938f2959..88500b698707b 100644 --- a/.github/workflows/mypy_primer.yml +++ b/.github/workflows/mypy_primer.yml @@ -26,7 +26,7 @@ jobs: fetch-depth: 0 - uses: actions/setup-python@v2 with: - python-version: 3.8 + python-version: "3.10" - name: Install dependencies run: | python -m pip install -U pip From 6de254ef00f99ce5284ab947f2dd1179db6d28f6 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Tue, 21 Dec 2021 14:15:31 +0300 Subject: [PATCH 007/377] Enums with annotations and no values are fine to be subclassed (#11579) Closes #11578. Closes #11702. --- mypy/nodes.py | 5 ++ mypy/semanal.py | 70 +++++++++++++++++++++------ test-data/unit/check-enum.test | 46 +++++++++++++++++- test-data/unit/check-incremental.test | 23 +++++++++ 4 files changed, 128 insertions(+), 16 deletions(-) diff --git a/mypy/nodes.py b/mypy/nodes.py index 156d756030ae4..78a018f94a78f 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -840,6 +840,7 @@ def deserialize(cls, data: JsonDict) -> 'Decorator': 'is_classmethod', 'is_property', 'is_settable_property', 'is_suppressed_import', 'is_classvar', 'is_abstract_var', 'is_final', 'final_unset_in_class', 'final_set_in_init', 'explicit_self_type', 'is_ready', 'from_module_getattr', + 'has_explicit_value', ] @@ -870,6 +871,7 @@ class Var(SymbolNode): 'is_suppressed_import', 'explicit_self_type', 'from_module_getattr', + 'has_explicit_value', ) def __init__(self, name: str, type: 'Optional[mypy.types.Type]' = None) -> None: @@ -914,6 +916,9 @@ def __init__(self, name: str, type: 'Optional[mypy.types.Type]' = None) -> None: self.explicit_self_type = False # If True, this is an implicit Var created due to module-level __getattr__. self.from_module_getattr = False + # Var can be created with an explicit value `a = 1` or without one `a: int`, + # we need a way to tell which one is which. + self.has_explicit_value = False @property def name(self) -> str: diff --git a/mypy/semanal.py b/mypy/semanal.py index 9a5076beb6f41..f29965f6ff8f8 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -1552,17 +1552,12 @@ def configure_base_classes(self, elif isinstance(base, Instance): if base.type.is_newtype: self.fail('Cannot subclass "NewType"', defn) - if ( - base.type.is_enum - and base.type.fullname not in ENUM_BASES - and base.type.names - and any(not isinstance(n.node, (FuncBase, Decorator)) - for n in base.type.names.values()) - ): + if self.enum_has_final_values(base): # This means that are trying to subclass a non-default # Enum class, with defined members. This is not possible. # In runtime, it will raise. We need to mark this type as final. # However, methods can be defined on a type: only values can't. + # We also don't count values with annotations only. base.type.is_final = True base_types.append(base) elif isinstance(base, AnyType): @@ -1601,6 +1596,25 @@ def configure_base_classes(self, return self.calculate_class_mro(defn, self.object_type) + def enum_has_final_values(self, base: Instance) -> bool: + if ( + base.type.is_enum + and base.type.fullname not in ENUM_BASES + and base.type.names + and base.type.defn + ): + for sym in base.type.names.values(): + if isinstance(sym.node, (FuncBase, Decorator)): + continue # A method + if not isinstance(sym.node, Var): + return True # Can be a class + if self.is_stub_file or sym.node.has_explicit_value: + # Corner case: assignments like `x: int` are fine in `.py` files. + # But, not is `.pyi` files, because we don't know + # if there's aactually a value or not. + return True + return False + def configure_tuple_base_class(self, defn: ClassDef, base: TupleType, @@ -2040,7 +2054,7 @@ def visit_import_all(self, i: ImportAll) -> None: def visit_assignment_expr(self, s: AssignmentExpr) -> None: s.value.accept(self) - self.analyze_lvalue(s.target, escape_comprehensions=True) + self.analyze_lvalue(s.target, escape_comprehensions=True, has_explicit_value=True) def visit_assignment_stmt(self, s: AssignmentStmt) -> None: self.statement = s @@ -2333,10 +2347,20 @@ def analyze_lvalues(self, s: AssignmentStmt) -> None: assert isinstance(s.unanalyzed_type, UnboundType) if not s.unanalyzed_type.args: explicit = False + + if s.rvalue: + if isinstance(s.rvalue, TempNode): + has_explicit_value = not s.rvalue.no_rhs + else: + has_explicit_value = True + else: + has_explicit_value = False + for lval in s.lvalues: self.analyze_lvalue(lval, explicit_type=explicit, - is_final=s.is_final_def) + is_final=s.is_final_def, + has_explicit_value=has_explicit_value) def apply_dynamic_class_hook(self, s: AssignmentStmt) -> None: if not isinstance(s.rvalue, CallExpr): @@ -2776,7 +2800,8 @@ def analyze_lvalue(self, nested: bool = False, explicit_type: bool = False, is_final: bool = False, - escape_comprehensions: bool = False) -> None: + escape_comprehensions: bool = False, + has_explicit_value: bool = False) -> None: """Analyze an lvalue or assignment target. Args: @@ -2790,7 +2815,11 @@ def analyze_lvalue(self, if escape_comprehensions: assert isinstance(lval, NameExpr), "assignment expression target must be NameExpr" if isinstance(lval, NameExpr): - self.analyze_name_lvalue(lval, explicit_type, is_final, escape_comprehensions) + self.analyze_name_lvalue( + lval, explicit_type, is_final, + escape_comprehensions, + has_explicit_value=has_explicit_value, + ) elif isinstance(lval, MemberExpr): self.analyze_member_lvalue(lval, explicit_type, is_final) if explicit_type and not self.is_self_member_ref(lval): @@ -2814,7 +2843,8 @@ def analyze_name_lvalue(self, lvalue: NameExpr, explicit_type: bool, is_final: bool, - escape_comprehensions: bool) -> None: + escape_comprehensions: bool, + has_explicit_value: bool) -> None: """Analyze an lvalue that targets a name expression. Arguments are similar to "analyze_lvalue". @@ -2844,7 +2874,7 @@ def analyze_name_lvalue(self, if (not existing or isinstance(existing.node, PlaceholderNode)) and not outer: # Define new variable. - var = self.make_name_lvalue_var(lvalue, kind, not explicit_type) + var = self.make_name_lvalue_var(lvalue, kind, not explicit_type, has_explicit_value) added = self.add_symbol(name, var, lvalue, escape_comprehensions=escape_comprehensions) # Only bind expression if we successfully added name to symbol table. if added: @@ -2895,7 +2925,9 @@ def is_alias_for_final_name(self, name: str) -> bool: existing = self.globals.get(orig_name) return existing is not None and is_final_node(existing.node) - def make_name_lvalue_var(self, lvalue: NameExpr, kind: int, inferred: bool) -> Var: + def make_name_lvalue_var( + self, lvalue: NameExpr, kind: int, inferred: bool, has_explicit_value: bool, + ) -> Var: """Return a Var node for an lvalue that is a name expression.""" v = Var(lvalue.name) v.set_line(lvalue) @@ -2910,6 +2942,7 @@ def make_name_lvalue_var(self, lvalue: NameExpr, kind: int, inferred: bool) -> V # fullanme should never stay None v._fullname = lvalue.name v.is_ready = False # Type not inferred yet + v.has_explicit_value = has_explicit_value return v def make_name_lvalue_point_to_existing_def( @@ -2953,7 +2986,14 @@ def analyze_tuple_or_list_lvalue(self, lval: TupleExpr, if len(star_exprs) == 1: star_exprs[0].valid = True for i in items: - self.analyze_lvalue(i, nested=True, explicit_type=explicit_type) + self.analyze_lvalue( + lval=i, + nested=True, + explicit_type=explicit_type, + # Lists and tuples always have explicit values defined: + # `a, b, c = value` + has_explicit_value=True, + ) def analyze_member_lvalue(self, lval: MemberExpr, explicit_type: bool, is_final: bool) -> None: """Analyze lvalue that is a member expression. diff --git a/test-data/unit/check-enum.test b/test-data/unit/check-enum.test index dd94bb6f82eff..a393df0797301 100644 --- a/test-data/unit/check-enum.test +++ b/test-data/unit/check-enum.test @@ -1678,7 +1678,6 @@ class A(Enum): class B(A): pass # E: Cannot inherit from final class "A" [builtins fixtures/bool.pyi] - [case testEnumFinalSpecialProps] # https://github.com/python/mypy/issues/11699 from enum import Enum, IntEnum @@ -1702,3 +1701,48 @@ class EI(IntEnum): E._order_ = 'a' # E: Cannot assign to final attribute "_order_" EI.value = 2 # E: Cannot assign to final attribute "value" [builtins fixtures/bool.pyi] + +[case testEnumNotFinalWithMethodsAndUninitializedValues] +# https://github.com/python/mypy/issues/11578 +from enum import Enum +from typing import Final + +class A(Enum): + x: int + def method(self) -> int: pass +class B(A): + x = 1 # E: Cannot override writable attribute "x" with a final one + +class A1(Enum): + x: int = 1 +class B1(A1): # E: Cannot inherit from final class "A1" + pass + +class A2(Enum): + x = 2 +class B2(A2): # E: Cannot inherit from final class "A2" + pass + +# We leave this `Final` without a value, +# because we need to test annotation only mode: +class A3(Enum): + x: Final[int] # type: ignore +class B3(A3): + x = 1 # E: Cannot override final attribute "x" (previously declared in base class "A3") +[builtins fixtures/bool.pyi] + +[case testEnumNotFinalWithMethodsAndUninitializedValuesStub] +import lib + +[file lib.pyi] +from enum import Enum +class A(Enum): + x: int +class B(A): # E: Cannot inherit from final class "A" + x = 1 # E: Cannot override writable attribute "x" with a final one + +class C(Enum): + x = 1 +class D(C): # E: Cannot inherit from final class "C" + x: int # E: Cannot assign to final name "x" +[builtins fixtures/bool.pyi] diff --git a/test-data/unit/check-incremental.test b/test-data/unit/check-incremental.test index 1d2262ab303d1..ec1dff4977d4e 100644 --- a/test-data/unit/check-incremental.test +++ b/test-data/unit/check-incremental.test @@ -5610,3 +5610,26 @@ class C: pass [rechecked] [stale] + + +[case testEnumAreStillFinalAfterCache] +import a +class Ok(a.RegularEnum): + x = 1 +class NotOk(a.FinalEnum): + x = 1 +[file a.py] +from enum import Enum +class RegularEnum(Enum): + x: int +class FinalEnum(Enum): + x = 1 +[builtins fixtures/isinstance.pyi] +[out] +main:3: error: Cannot override writable attribute "x" with a final one +main:4: error: Cannot inherit from final class "FinalEnum" +main:5: error: Cannot override final attribute "x" (previously declared in base class "FinalEnum") +[out2] +main:3: error: Cannot override writable attribute "x" with a final one +main:4: error: Cannot inherit from final class "FinalEnum" +main:5: error: Cannot override final attribute "x" (previously declared in base class "FinalEnum") From f8cf2e7e5cecabce3d9f38730ccefff7ae5027ee Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Tue, 21 Dec 2021 12:40:38 +0000 Subject: [PATCH 008/377] Allow calling a function with name '_' (#11810) Fixes #11774. The issue has relevant background information in the discussion. It may be worth it to eventually add back some restrictions, but we'd only focus the restrictions on singledispatch functions. This is a quick fix to work around a regression. --- mypy/checkexpr.py | 7 ------- test-data/unit/check-functions.test | 6 ++++++ test-data/unit/check-redefine.test | 3 ++- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 1647339ef2172..dfac5be27d955 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -1,6 +1,5 @@ """Expression type checker. This file is conceptually part of TypeChecker.""" -from mypy.util import unnamed_function from mypy.backports import OrderedDict, nullcontext from contextlib import contextmanager import itertools @@ -347,12 +346,6 @@ def visit_call_expr_inner(self, e: CallExpr, allow_none_return: bool = False) -> and callee_type.implicit): self.msg.untyped_function_call(callee_type, e) - if (isinstance(callee_type, CallableType) - and not callee_type.is_type_obj() - and unnamed_function(callee_type.name)): - self.msg.underscore_function_call(e) - return AnyType(TypeOfAny.from_error) - # Figure out the full name of the callee for plugin lookup. object_type = None member = None diff --git a/test-data/unit/check-functions.test b/test-data/unit/check-functions.test index 6f69a1fe25bc3..bdf75b2dc58c9 100644 --- a/test-data/unit/check-functions.test +++ b/test-data/unit/check-functions.test @@ -2230,6 +2230,12 @@ reveal_type(h) # N: Revealed type is "builtins.function" h(7) # E: Cannot call function of unknown type [builtins fixtures/bool.pyi] +[case testFunctionWithNameUnderscore] +def _(x: int) -> None: pass + +_(1) +_('x') # E: Argument 1 to "_" has incompatible type "str"; expected "int" + -- Positional-only arguments -- ------------------------- diff --git a/test-data/unit/check-redefine.test b/test-data/unit/check-redefine.test index d2229dba470f3..85208df0932aa 100644 --- a/test-data/unit/check-redefine.test +++ b/test-data/unit/check-redefine.test @@ -498,7 +498,8 @@ def _(arg: str): def _(arg: int) -> int: return 'a' # E: Incompatible return value type (got "str", expected "int") -[case testCallingUnderscoreFunctionIsNotAllowed] +[case testCallingUnderscoreFunctionIsNotAllowed-skip] +# Skipped because of https://github.com/python/mypy/issues/11774 def _(arg: str) -> None: pass From 578898dabae9a6c91b8f1081630c91cbe7e6f5be Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Tue, 21 Dec 2021 15:43:10 +0300 Subject: [PATCH 009/377] Documents explicit type aliases (#11800) Refs https://www.python.org/dev/peps/pep-0613/ Co-authored-by: Jelle Zijlstra --- docs/source/common_issues.rst | 53 ++++++++++++++++++++-------------- docs/source/kinds_of_types.rst | 16 +++++++++- 2 files changed, 46 insertions(+), 23 deletions(-) diff --git a/docs/source/common_issues.rst b/docs/source/common_issues.rst index d3c1761bc9947..9d6423137c414 100644 --- a/docs/source/common_issues.rst +++ b/docs/source/common_issues.rst @@ -638,39 +638,48 @@ Mypy has both type aliases and variables with types like ``Type[...]`` and it is 1. Variables with type ``Type[...]`` should be created by assignments with an explicit type annotations: -.. code-block:: python + .. code-block:: python - class A: ... - tp: Type[A] = A + class A: ... + tp: Type[A] = A -2. Aliases are created by assignments without an explicit type: +2. Aliases are created by assignments without an explicit type. -.. code-block:: python + .. code-block:: python + + class A: ... + Alias = A - class A: ... - Alias = A + Or you can also use :pep:`613` and explicit type aliases: + + .. code-block:: python + + from typing import TypeAlias # or `from typing_extensions` before `python3.10` + + class A: ... + Alias: TypeAlias = A 3. The difference is that aliases are completely known statically and can be used in type context (annotations): -.. code-block:: python + .. code-block:: python - class A: ... - class B: ... + class A: ... + class B: ... - if random() > 0.5: - Alias = A - else: - Alias = B # error: Cannot assign multiple types to name "Alias" without an explicit "Type[...]" annotation \ - # error: Incompatible types in assignment (expression has type "Type[B]", variable has type "Type[A]") + if random() > 0.5: + Alias = A + else: + Alias = B # error: Cannot assign multiple types to name "Alias" without an explicit "Type[...]" annotation \ + # error: Incompatible types in assignment (expression has type "Type[B]", variable has type "Type[A]") - tp: Type[object] # tp is a type variable - if random() > 0.5: - tp = A - else: - tp = B # This is OK + tp: Type[object] # tp is a type variable + if random() > 0.5: + tp = A + else: + tp = B # This is OK - def fun1(x: Alias) -> None: ... # This is OK - def fun2(x: tp) -> None: ... # error: Variable "__main__.tp" is not valid as a type + def fun1(x: Alias) -> None: ... # This is OK + def fun2(x: tp) -> None: ... # error: Variable "__main__.tp" is not valid as a type Incompatible overrides ---------------------- diff --git a/docs/source/kinds_of_types.rst b/docs/source/kinds_of_types.rst index 7cdedf6718670..73a6acac1db8d 100644 --- a/docs/source/kinds_of_types.rst +++ b/docs/source/kinds_of_types.rst @@ -362,7 +362,6 @@ is needed: .. code-block:: python - class Container: items: list[str] # No initializer @@ -522,6 +521,21 @@ assigning the type to a variable: another type -- it's equivalent to the target type except for :ref:`generic aliases `. +Since Mypy 0.930 you can also use explicit type aliases which are defined by :pep:`613`. + +Implicit type alias declaration rules create confusion when type aliases involve forward references, +invalid types, or violate other restrictions enforced on type alias declaration. +Because the distinction between an unannotated value and a type alias is implicit, +ambiguous or incorrect type alias declarations implicitly default to a valid value assignment. + +.. code-block:: python + + from typing import TypeAlias # or `from typing_extensions` before `python3.10` + + AliasType: TypeAlias = Union[list[dict[tuple[int, str], set[int]]], tuple[str, list[str]]] + +Explicit type aliases are unambiguous and improve readability. + .. _named-tuples: Named tuples From e7212817aaf2ebfc463f27a12eb1ff1851930cb3 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Wed, 22 Dec 2021 02:03:27 +0300 Subject: [PATCH 010/377] Fixes crash on subclassing `Annotated` without args, refs #11808 (#11814) --- mypy/typeanal.py | 4 +++- test-data/unit/semanal-errors.test | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/mypy/typeanal.py b/mypy/typeanal.py index f7b584eadae87..e29ccfd3c928a 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -1291,7 +1291,9 @@ def visit_unbound_type(self, t: UnboundType) -> TypeVarLikeList: return [] elif node and node.fullname in ('typing_extensions.Literal', 'typing.Literal'): return [] - elif node and node.fullname in ('typing_extensions.Annotated', 'typing.Annotated'): + elif (node + and node.fullname in ('typing_extensions.Annotated', 'typing.Annotated') + and t.args): # Don't query the second argument to Annotated for TypeVars return self.query_types([t.args[0]]) else: diff --git a/test-data/unit/semanal-errors.test b/test-data/unit/semanal-errors.test index e5aea483a210e..f73de64709260 100644 --- a/test-data/unit/semanal-errors.test +++ b/test-data/unit/semanal-errors.test @@ -1435,3 +1435,10 @@ TP = ParamSpec('?') # E: String argument 1 "?" to ParamSpec(...) does not match TP2: int = ParamSpec('TP2') # E: Cannot declare the type of a parameter specification [out] + + +[case testBaseClassAnnotatedWithoutArgs] +# https://github.com/python/mypy/issues/11808 +from typing_extensions import Annotated +# Nest line should not crash: +class A(Annotated): pass # E: Annotated[...] must have exactly one type argument and at least one annotation From 9d5ef72068943e415082c848b74ff4fad9293080 Mon Sep 17 00:00:00 2001 From: StefanM-TT <96481686+StefanM-TT@users.noreply.github.com> Date: Wed, 22 Dec 2021 00:30:12 +0100 Subject: [PATCH 011/377] Fix crash if "_" is in builtins (#11811) allows the definition of "_" as function in builtins (e.g via typeshed). fixes #9802 --- mypy/semanal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index f29965f6ff8f8..a9226d2cdd0c9 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4296,7 +4296,7 @@ def lookup(self, name: str, ctx: Context, assert isinstance(b.node, MypyFile) table = b.node.names if name in table: - if name[0] == "_" and name[1] != "_": + if len(name) > 1 and name[0] == "_" and name[1] != "_": if not suppress_errors: self.name_not_defined(name, ctx) return None From f96446ce2f99a86210b21d39c7aec4b13a8bfc66 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Wed, 22 Dec 2021 10:39:36 +0000 Subject: [PATCH 012/377] Various small documentation updates (#11817) Improve consistency, grammar, formatting and clarity in the documentation. Also some minor content fixes. --- docs/source/class_basics.rst | 22 +- docs/source/command_line.rst | 4 +- docs/source/common_issues.rst | 204 +++++++++--------- docs/source/generics.rst | 48 +++-- docs/source/installed_packages.rst | 7 +- docs/source/kinds_of_types.rst | 42 ++-- docs/source/literal_types.rst | 42 ++-- docs/source/more_types.rst | 6 +- docs/source/stubtest.rst | 20 +- .../source/type_inference_and_annotations.rst | 16 +- 10 files changed, 227 insertions(+), 184 deletions(-) diff --git a/docs/source/class_basics.rst b/docs/source/class_basics.rst index 83177e26aa678..3c12b4b06d9b1 100644 --- a/docs/source/class_basics.rst +++ b/docs/source/class_basics.rst @@ -320,8 +320,8 @@ Slots ***** When a class has explicitly defined -`__slots__ `_ -mypy will check that all attributes assigned to are members of `__slots__`. +`__slots__ `_, +mypy will check that all attributes assigned to are members of ``__slots__``: .. code-block:: python @@ -331,13 +331,19 @@ mypy will check that all attributes assigned to are members of `__slots__`. def __init__(self, name: str, year: int) -> None: self.name = name self.year = year - self.released = True # E: Trying to assign name "released" that is not in "__slots__" of type "Album" + # Error: Trying to assign name "released" that is not in "__slots__" of type "Album" + self.released = True my_album = Album('Songs about Python', 2021) -Mypy will only check attribute assignments against `__slots__` when the following conditions hold: +Mypy will only check attribute assignments against ``__slots__`` when +the following conditions hold: -1. All base classes (except builtin ones) must have explicit ``__slots__`` defined (mirrors CPython's behaviour) -2. ``__slots__`` does not include ``__dict__``, since if ``__slots__`` includes ``__dict__`` - it allows setting any attribute, similar to when ``__slots__`` is not defined (mirrors CPython's behaviour) -3. All values in ``__slots__`` must be statically known. For example, no variables: only string literals. +1. All base classes (except builtin ones) must have explicit + ``__slots__`` defined (this mirrors Python semantics). + +2. ``__slots__`` does not include ``__dict__``. If ``__slots__`` + includes ``__dict__``, arbitrary attributes can be set, similar to + when ``__slots__`` is not defined (this mirrors Python semantics). + +3. All values in ``__slots__`` must be string literals. diff --git a/docs/source/command_line.rst b/docs/source/command_line.rst index 7405ab563e0d6..a729ac2baca0c 100644 --- a/docs/source/command_line.rst +++ b/docs/source/command_line.rst @@ -312,8 +312,8 @@ The following options are available: .. option:: --disallow-any-generics This flag disallows usage of generic types that do not specify explicit - type parameters. For example you can't use a bare ``x: list``, you must say - ``x: list[int]``. + type parameters. For example, you can't use a bare ``x: list``. Instead, you + must always write something like ``x: list[int]``. .. option:: --disallow-subclassing-any diff --git a/docs/source/common_issues.rst b/docs/source/common_issues.rst index 9d6423137c414..c4adc9b563bd6 100644 --- a/docs/source/common_issues.rst +++ b/docs/source/common_issues.rst @@ -26,102 +26,102 @@ No errors reported for obviously wrong code There are several common reasons why obviously wrong code is not flagged as an error. -- **The function containing the error is not annotated.** Functions that - do not have any annotations (neither for any argument nor for the - return type) are not type-checked, and even the most blatant type - errors (e.g. ``2 + 'a'``) pass silently. The solution is to add - annotations. Where that isn't possible, functions without annotations - can be checked using :option:`--check-untyped-defs `. +**The function containing the error is not annotated.** Functions that +do not have any annotations (neither for any argument nor for the +return type) are not type-checked, and even the most blatant type +errors (e.g. ``2 + 'a'``) pass silently. The solution is to add +annotations. Where that isn't possible, functions without annotations +can be checked using :option:`--check-untyped-defs `. - Example: +Example: - .. code-block:: python +.. code-block:: python - def foo(a): - return '(' + a.split() + ')' # No error! + def foo(a): + return '(' + a.split() + ')' # No error! - This gives no error even though ``a.split()`` is "obviously" a list - (the author probably meant ``a.strip()``). The error is reported - once you add annotations: +This gives no error even though ``a.split()`` is "obviously" a list +(the author probably meant ``a.strip()``). The error is reported +once you add annotations: - .. code-block:: python +.. code-block:: python - def foo(a: str) -> str: - return '(' + a.split() + ')' - # error: Unsupported operand types for + ("str" and List[str]) + def foo(a: str) -> str: + return '(' + a.split() + ')' + # error: Unsupported operand types for + ("str" and List[str]) - If you don't know what types to add, you can use ``Any``, but beware: +If you don't know what types to add, you can use ``Any``, but beware: -- **One of the values involved has type 'Any'.** Extending the above - example, if we were to leave out the annotation for ``a``, we'd get - no error: +**One of the values involved has type 'Any'.** Extending the above +example, if we were to leave out the annotation for ``a``, we'd get +no error: - .. code-block:: python +.. code-block:: python - def foo(a) -> str: - return '(' + a.split() + ')' # No error! + def foo(a) -> str: + return '(' + a.split() + ')' # No error! - The reason is that if the type of ``a`` is unknown, the type of - ``a.split()`` is also unknown, so it is inferred as having type - ``Any``, and it is no error to add a string to an ``Any``. +The reason is that if the type of ``a`` is unknown, the type of +``a.split()`` is also unknown, so it is inferred as having type +``Any``, and it is no error to add a string to an ``Any``. - If you're having trouble debugging such situations, - :ref:`reveal_type() ` might come in handy. +If you're having trouble debugging such situations, +:ref:`reveal_type() ` might come in handy. - Note that sometimes library stubs have imprecise type information, - e.g. the :py:func:`pow` builtin returns ``Any`` (see `typeshed issue 285 - `_ for the reason). +Note that sometimes library stubs have imprecise type information, +e.g. the :py:func:`pow` builtin returns ``Any`` (see `typeshed issue 285 +`_ for the reason). -- :py:meth:`__init__ ` **method has no annotated - arguments or return type annotation.** :py:meth:`__init__ ` - is considered fully-annotated **if at least one argument is annotated**, - while mypy will infer the return type as ``None``. - The implication is that, for a :py:meth:`__init__ ` method - that has no argument, you'll have to explicitly annotate the return type - as ``None`` to type-check this :py:meth:`__init__ ` method: +:py:meth:`__init__ ` **method has no annotated +arguments or return type annotation.** :py:meth:`__init__ ` +is considered fully-annotated **if at least one argument is annotated**, +while mypy will infer the return type as ``None``. +The implication is that, for a :py:meth:`__init__ ` method +that has no argument, you'll have to explicitly annotate the return type +as ``None`` to type-check this :py:meth:`__init__ ` method: - .. code-block:: python +.. code-block:: python - def foo(s: str) -> str: - return s - - class A(): - def __init__(self, value: str): # Return type inferred as None, considered as typed method - self.value = value - foo(1) # error: Argument 1 to "foo" has incompatible type "int"; expected "str" - - class B(): - def __init__(self): # No argument is annotated, considered as untyped method - foo(1) # No error! - - class C(): - def __init__(self) -> None: # Must specify return type to type-check - foo(1) # error: Argument 1 to "foo" has incompatible type "int"; expected "str" - -- **Some imports may be silently ignored**. Another source of - unexpected ``Any`` values are the :option:`--ignore-missing-imports - ` and :option:`--follow-imports=skip - ` flags. When you use :option:`--ignore-missing-imports `, - any imported module that cannot be found is silently replaced with - ``Any``. When using :option:`--follow-imports=skip ` the same is true for - modules for which a ``.py`` file is found but that are not specified - on the command line. (If a ``.pyi`` stub is found it is always - processed normally, regardless of the value of - :option:`--follow-imports `.) To help debug the former situation (no - module found at all) leave out :option:`--ignore-missing-imports `; to get - clarity about the latter use :option:`--follow-imports=error `. You can - read up about these and other useful flags in :ref:`command-line`. - -- **A function annotated as returning a non-optional type returns 'None' - and mypy doesn't complain**. + def foo(s: str) -> str: + return s + + class A(): + def __init__(self, value: str): # Return type inferred as None, considered as typed method + self.value = value + foo(1) # error: Argument 1 to "foo" has incompatible type "int"; expected "str" + + class B(): + def __init__(self): # No argument is annotated, considered as untyped method + foo(1) # No error! + + class C(): + def __init__(self) -> None: # Must specify return type to type-check + foo(1) # error: Argument 1 to "foo" has incompatible type "int"; expected "str" + +**Some imports may be silently ignored**. Another source of +unexpected ``Any`` values are the :option:`--ignore-missing-imports +` and :option:`--follow-imports=skip +` flags. When you use :option:`--ignore-missing-imports `, +any imported module that cannot be found is silently replaced with +``Any``. When using :option:`--follow-imports=skip ` the same is true for +modules for which a ``.py`` file is found but that are not specified +on the command line. (If a ``.pyi`` stub is found it is always +processed normally, regardless of the value of +:option:`--follow-imports `.) To help debug the former situation (no +module found at all) leave out :option:`--ignore-missing-imports `; to get +clarity about the latter use :option:`--follow-imports=error `. You can +read up about these and other useful flags in :ref:`command-line`. + +**A function annotated as returning a non-optional type returns 'None' +and mypy doesn't complain**. - .. code-block:: python +.. code-block:: python - def foo() -> str: - return None # No error! + def foo() -> str: + return None # No error! - You may have disabled strict optional checking (see - :ref:`no_strict_optional` for more). +You may have disabled strict optional checking (see +:ref:`no_strict_optional` for more). .. _silencing_checker: @@ -383,10 +383,10 @@ explicit type cast: if index < 0: raise ValueError('No str found') - found = a[index] # Has `object` type, despite the fact that we know it is `str` - return cast(str, found) # So, we need an explicit cast to make mypy happy + found = a[index] # Has type "object", despite the fact that we know it is "str" + return cast(str, found) # We need an explicit cast to make mypy happy -Alternatively, you can use ``assert`` statement together with some +Alternatively, you can use an ``assert`` statement together with some of the supported type inference techniques: .. code-block:: python @@ -396,9 +396,9 @@ of the supported type inference techniques: if index < 0: raise ValueError('No str found') - found = a[index] # Has `object` type, despite the fact that we know it is `str` - assert isinstance(found, str) # Now, `found` will be narrowed to `str` subtype - return found # No need for the explicit `cast()` anymore + found = a[index] # Has type "object", despite the fact that we know it is "str" + assert isinstance(found, str) # Now, "found" will be narrowed to "str" + return found # No need for the explicit "cast()" anymore .. note:: @@ -411,7 +411,7 @@ of the supported type inference techniques: .. note:: - You can read more about type narrowing techniques here. + You can read more about type narrowing techniques :ref:`here `. Type inference in Mypy is designed to work well in common cases, to be predictable and to let the type checker give useful error @@ -634,32 +634,41 @@ You can install the latest development version of mypy from source. Clone the Variables vs type aliases ------------------------- -Mypy has both type aliases and variables with types like ``Type[...]`` and it is important to know their difference. +Mypy has both *type aliases* and variables with types like ``Type[...]``. These are +subtly different, and it's important to understand how they differ to avoid pitfalls. -1. Variables with type ``Type[...]`` should be created by assignments with an explicit type annotations: +1. A variable with type ``Type[...]`` is defined using an assignment with an + explicit type annotation: .. code-block:: python class A: ... tp: Type[A] = A -2. Aliases are created by assignments without an explicit type. +2. You can define a type alias using an assignment without an explicit type annotation + at the top level of a module: .. code-block:: python class A: ... Alias = A - Or you can also use :pep:`613` and explicit type aliases: + You can also use ``TypeAlias`` (:pep:`613`) to define an *explicit type alias*: .. code-block:: python - - from typing import TypeAlias # or `from typing_extensions` before `python3.10` - + + from typing import TypeAlias # "from typing_extensions" in Python 3.9 and earlier + class A: ... Alias: TypeAlias = A -3. The difference is that aliases are completely known statically and can be used in type context (annotations): + You should always use ``TypeAlias`` to define a type alias in a class body or + inside a function. + +The main difference is that the target of an alias is precisely known statically, and this +means that they can be used in type annotations and other *type contexts*. Type aliases +can't be defined conditionally (unless using +:ref:`supported Python version and platform checks `): .. code-block:: python @@ -669,17 +678,18 @@ Mypy has both type aliases and variables with types like ``Type[...]`` and it is if random() > 0.5: Alias = A else: - Alias = B # error: Cannot assign multiple types to name "Alias" without an explicit "Type[...]" annotation \ - # error: Incompatible types in assignment (expression has type "Type[B]", variable has type "Type[A]") + # error: Cannot assign multiple types to name "Alias" without an + # explicit "Type[...]" annotation + Alias = B - tp: Type[object] # tp is a type variable + tp: Type[object] # "tp" is a variable with a type object value if random() > 0.5: tp = A else: tp = B # This is OK - def fun1(x: Alias) -> None: ... # This is OK - def fun2(x: tp) -> None: ... # error: Variable "__main__.tp" is not valid as a type + def fun1(x: Alias) -> None: ... # OK + def fun2(x: tp) -> None: ... # Error: "tp" is not valid as a type Incompatible overrides ---------------------- diff --git a/docs/source/generics.rst b/docs/source/generics.rst index 84582be13f883..7e64aa1814038 100644 --- a/docs/source/generics.rst +++ b/docs/source/generics.rst @@ -77,8 +77,8 @@ Generic class internals *********************** You may wonder what happens at runtime when you index -``Stack``. Actually, indexing ``Stack`` returns essentially a copy -of ``Stack`` that returns instances of the original class on +``Stack``. Indexing ``Stack`` returns a *generic alias* +to ``Stack`` that returns instances of the original class on instantiation: .. code-block:: python @@ -90,11 +90,20 @@ instantiation: >>> print(Stack[int]().__class__) __main__.Stack -For Python 3.8 and lower, note that built-in types :py:class:`list`, -:py:class:`dict` and so on do not support indexing in Python. -This is why we have the aliases :py:class:`~typing.List`, :py:class:`~typing.Dict` -and so on in the :py:mod:`typing` module. Indexing these aliases gives -you a class that directly inherits from the target class in Python: +Generic aliases can be instantiated or subclassed, similar to real +classes, but the above examples illustrate that type variables are +erased at runtime. Generic ``Stack`` instances are just ordinary +Python objects, and they have no extra runtime overhead or magic due +to being generic, other than a metaclass that overloads the indexing +operator. + +Note that in Python 3.8 and lower, the built-in types +:py:class:`list`, :py:class:`dict` and others do not support indexing. +This is why we have the aliases :py:class:`~typing.List`, +:py:class:`~typing.Dict` and so on in the :py:mod:`typing` +module. Indexing these aliases gives you a generic alias that +resembles generic aliases constructed by directly indexing the target +class in more recent versions of Python: .. code-block:: python @@ -103,15 +112,24 @@ you a class that directly inherits from the target class in Python: >>> from typing import List >>> List[int] typing.List[int] - >>> List[int].__bases__ - (, typing.MutableSequence) -Generic types could be instantiated or subclassed as usual classes, -but the above examples illustrate that type variables are erased at -runtime. Generic ``Stack`` instances are just ordinary -Python objects, and they have no extra runtime overhead or magic due -to being generic, other than a metaclass that overloads the indexing -operator. +Note that the generic aliases in ``typing`` don't support constructing +instances: + +.. code-block:: python + + >>> from typing import List + >>> List[int]() + Traceback (most recent call last): + ... + TypeError: Type List cannot be instantiated; use list() instead + +.. note:: + + In Python 3.6 indexing generic types or type aliases results in actual + type objects. This means that generic types in type annotations can + have a significant runtime cost. This was changed in Python 3.7, and + indexing generic types became a cheap operation. .. _generic-subclasses: diff --git a/docs/source/installed_packages.rst b/docs/source/installed_packages.rst index 036185c818e5c..8db113e4ba9e4 100644 --- a/docs/source/installed_packages.rst +++ b/docs/source/installed_packages.rst @@ -178,9 +178,10 @@ the Python 2 stubs in a directory with the suffix ``-python2-stubs``. We recommend that Python 2 and Python 3 stubs are bundled together for simplicity, instead of distributing them separately. -The instructions are enough to ensure that built wheels contains the appropriate -files. However, to ensure inclusion inside the ``sdist`` (``.tar.gz`` archive), -you may also need to modify the inclusion rules in your ``MANIFEST.in``: +The instructions above are enough to ensure that the built wheels +contain the appropriate files. However, to ensure inclusion inside the +``sdist`` (``.tar.gz`` archive), you may also need to modify the +inclusion rules in your ``MANIFEST.in``: .. code-block:: text diff --git a/docs/source/kinds_of_types.rst b/docs/source/kinds_of_types.rst index 73a6acac1db8d..866535949d748 100644 --- a/docs/source/kinds_of_types.rst +++ b/docs/source/kinds_of_types.rst @@ -521,21 +521,25 @@ assigning the type to a variable: another type -- it's equivalent to the target type except for :ref:`generic aliases `. -Since Mypy 0.930 you can also use explicit type aliases which are defined by :pep:`613`. +Since Mypy 0.930 you can also use *explicit type aliases*, which were +introduced in :pep:`613`. -Implicit type alias declaration rules create confusion when type aliases involve forward references, -invalid types, or violate other restrictions enforced on type alias declaration. -Because the distinction between an unannotated value and a type alias is implicit, -ambiguous or incorrect type alias declarations implicitly default to a valid value assignment. +There can be confusion about exactly when an assignment defines an implicit type alias -- +for example, when the alias contains forward references, invalid types, or violates some other +restrictions on type alias declarations. Because the +distinction between an unannotated variable and a type alias is implicit, +ambiguous or incorrect type alias declarations default to defining +a normal variable instead of a type alias. + +Explicit type aliases are unambiguous and can also improve readability by +making the intent clear: .. code-block:: python - from typing import TypeAlias # or `from typing_extensions` before `python3.10` + from typing import TypeAlias # "from typing_extensions" in Python 3.9 and earlier AliasType: TypeAlias = Union[list[dict[tuple[int, str], set[int]]], tuple[str, list[str]]] -Explicit type aliases are unambiguous and improve readability. - .. _named-tuples: Named tuples @@ -578,8 +582,8 @@ Python 3.6 introduced an alternative, class-based syntax for named tuples with t .. note:: - You can use raw ``NamedTuple`` pseudo-class to annotate type - where any ``NamedTuple`` is expected. + You can use the raw ``NamedTuple`` "pseudo-class" in type annotations + if any ``NamedTuple`` object is valid. For example, it can be useful for deserialization: @@ -594,10 +598,12 @@ Python 3.6 introduced an alternative, class-based syntax for named tuples with t deserialize_named_tuple(Point(x=1, y=2)) # ok deserialize_named_tuple(Person(name='Nikita', age=18)) # ok - deserialize_named_tuple((1, 2)) # Argument 1 to "deserialize_named_tuple" has incompatible type "Tuple[int, int]"; expected "NamedTuple" + # Error: Argument 1 to "deserialize_named_tuple" has incompatible type + # "Tuple[int, int]"; expected "NamedTuple" + deserialize_named_tuple((1, 2)) - Note, that behavior is highly experimental, non-standard, - and can be not supported by other type checkers. + Note that this behavior is highly experimental, non-standard, + and may not be supported by other type checkers and IDEs. .. _type-of-class: @@ -743,15 +749,15 @@ type of either :py:class:`Iterator[YieldType] ` or :py:class:`I def squares(n: int) -> Iterator[int]: for i in range(n): yield i * i - + A good rule of thumb is to annotate functions with the most specific return type possible. However, you should also take care to avoid leaking implementation -details into a function's public API. In keeping with these two principles, prefer +details into a function's public API. In keeping with these two principles, prefer :py:class:`Iterator[YieldType] ` over -:py:class:`Iterable[YieldType] ` as the return-type annotation for a -generator function, as it lets mypy know that users are able to call :py:func:`next` on +:py:class:`Iterable[YieldType] ` as the return-type annotation for a +generator function, as it lets mypy know that users are able to call :py:func:`next` on the object returned by the function. Nonetheless, bear in mind that ``Iterable`` may -sometimes be the better option, if you consider it an implementation detail that +sometimes be the better option, if you consider it an implementation detail that ``next()`` can be called on the object returned by your function. If you want your generator to accept values via the :py:meth:`~generator.send` method or return diff --git a/docs/source/literal_types.rst b/docs/source/literal_types.rst index 94eec06236ca9..b1669d01062a8 100644 --- a/docs/source/literal_types.rst +++ b/docs/source/literal_types.rst @@ -142,7 +142,7 @@ as adding an explicit ``Literal[...]`` annotation, it often leads to the same ef in practice. The main cases where the behavior of context-sensitive vs true literal types differ are -when you try using those types in places that are not explicitly expecting a ``Literal[...]``. +when you try using those types in places that are not explicitly expecting a ``Literal[...]``. For example, compare and contrast what happens when you try appending these types to a list: .. code-block:: python @@ -208,7 +208,7 @@ corresponding to some particular index, we can use Literal types like so: # You can also index using unions of literals id_key: Literal["main_id", "backup_id"] - reveal_type(d[id_key]) # Revealed type is "int" + reveal_type(d[id_key]) # Revealed type is "int" .. _tagged_unions: @@ -248,7 +248,7 @@ type. Then, you can discriminate between each kind of TypedDict by checking the # Literal["new-job", "cancel-job"], but the check below will narrow # the type to either Literal["new-job"] or Literal["cancel-job"]. # - # This in turns narrows the type of 'event' to either NewJobEvent + # This in turns narrows the type of 'event' to either NewJobEvent # or CancelJobEvent. if event["tag"] == "new-job": print(event["job_name"]) @@ -289,11 +289,11 @@ using ``isinstance()``: This feature is sometimes called "sum types" or "discriminated union types" in other programming languages. -Exhaustive checks -***************** +Exhaustiveness checks +********************* -One may want to check that some code covers all possible ``Literal`` or ``Enum`` cases, -example: +You may want to check that some code covers all possible +``Literal`` or ``Enum`` cases. Example: .. code-block:: python @@ -306,21 +306,22 @@ example: return True elif x == 'two': return False - raise ValueError('Wrong values passed: {0}'.format(x)) + raise ValueError(f'Invalid value: {x}') assert validate('one') is True assert validate('two') is False -In the code above it is really easy to make a mistake in the future: -by adding a new literal value to ``PossibleValues``, -but not adding its handler to ``validate`` function: +In the code above, it's easy to make a mistake. You can +add a new literal value to ``PossibleValues`` but forget +to handle it in the ``validate`` function: .. code-block:: python PossibleValues = Literal['one', 'two', 'three'] -Mypy won't catch that ``'three'`` is not covered. -However, if you want to have exhaustive check, you need to guard it properly: +Mypy won't catch that ``'three'`` is not covered. If you want mypy to +perform an exhaustiveness check, you need to update your code to use an +``assert_never()`` check: .. code-block:: python @@ -329,8 +330,8 @@ However, if you want to have exhaustive check, you need to guard it properly: PossibleValues = Literal['one', 'two'] def assert_never(value: NoReturn) -> NoReturn: - # This also works in runtime as well: - assert False, 'This code should never be reached, got: {0}'.format(value) + # This also works at runtime as well + assert False, f'This code should never be reached, got: {value}' def validate(x: PossibleValues) -> bool: if x == 'one': @@ -339,22 +340,21 @@ However, if you want to have exhaustive check, you need to guard it properly: return False assert_never(x) -In this case, when adding new values to ``PossibleValues``: +Now if you add a new value to ``PossibleValues`` but don't update ``validate``, +mypy will spot the error: .. code-block:: python PossibleValues = Literal['one', 'two', 'three'] -Mypy will cover you: - -.. code-block:: python - def validate(x: PossibleValues) -> bool: if x == 'one': return True elif x == 'two': return False - assert_never(x) # E: Argument 1 to "assert_never" has incompatible type "Literal['three']"; expected "NoReturn" + # Error: Argument 1 to "assert_never" has incompatible type "Literal['three']"; + # expected "NoReturn" + assert_never(x) Limitations *********** diff --git a/docs/source/more_types.rst b/docs/source/more_types.rst index 11dbef32cbfa6..82a6568afcb29 100644 --- a/docs/source/more_types.rst +++ b/docs/source/more_types.rst @@ -294,10 +294,10 @@ return type by using overloads like so: subtypes, you can use a :ref:`value restriction `. -The default values of a function's arguments don't affect its signature, only +The default values of a function's arguments don't affect its signature -- only the absence or presence of a default value does. So in order to reduce -redundancy it's possible to replace default values in overload definitions with -`...` as a placeholder. +redundancy, it's possible to replace default values in overload definitions with +``...`` as a placeholder: .. code-block:: python diff --git a/docs/source/stubtest.rst b/docs/source/stubtest.rst index 5903de2cf7ca1..828931fbdf2b7 100644 --- a/docs/source/stubtest.rst +++ b/docs/source/stubtest.rst @@ -17,24 +17,24 @@ implementation at runtime. What stubtest does and does not do ********************************** -stubtest will import your code and introspect your code objects at runtime, for -example, by using the capabilities of the :py:mod:`inspect` module. stubtest +Stubtest will import your code and introspect your code objects at runtime, for +example, by using the capabilities of the :py:mod:`inspect` module. Stubtest will then analyse the stub files, and compare the two, pointing out things that differ between stubs and the implementation at runtime. -It's important to be aware of the limitations of this comparison. stubtest will +It's important to be aware of the limitations of this comparison. Stubtest will not make any attempt to statically analyse your actual code and relies only on dynamic runtime introspection (in particular, this approach means stubtest works well with extension modules). However, this means that stubtest has limited visibility; for instance, it cannot tell if a return type of a function is accurately typed in the stubs. -For clarity, here are some more things stubtest does not do: +For clarity, here are some additional things stubtest can't do: -* Type check your code, use ``mypy`` -* Generate stubs, use ``stubgen`` or ``pyright --createstub`` -* Generate stubs based on running your application or test suite, use ``monkeytype`` -* Apply stubs to code to produce inline types, use ``retype`` or ``libcst`` +* Type check your code -- use ``mypy`` instead +* Generate stubs -- use ``stubgen`` or ``pyright --createstub`` instead +* Generate stubs based on running your application or test suite -- use ``monkeytype`` instead +* Apply stubs to code to produce inline types -- use ``retype`` or ``libcst`` instead In summary, stubtest works very well for ensuring basic consistency between stubs and implementation or to check for stub completeness. It's used to @@ -81,11 +81,11 @@ Usage Running stubtest can be as simple as ``stubtest module_to_check``. Run :option:`stubtest --help` for a quick summary of options. -stubtest must be able to import the code to be checked, so make sure that mypy +Subtest must be able to import the code to be checked, so make sure that mypy is installed in the same environment as the library to be tested. In some cases, setting ``PYTHONPATH`` can help stubtest find the code to import. -Similarly, stubtest must be able to find the stubs to be checked. stubtest +Similarly, stubtest must be able to find the stubs to be checked. Stubtest respects the ``MYPYPATH`` environment variable. If you wish to ignore some of stubtest's complaints, stubtest supports a diff --git a/docs/source/type_inference_and_annotations.rst b/docs/source/type_inference_and_annotations.rst index 80b9356cd6817..8150f88e579e4 100644 --- a/docs/source/type_inference_and_annotations.rst +++ b/docs/source/type_inference_and_annotations.rst @@ -95,10 +95,11 @@ Similarly, you can also give an explicit type when creating an empty set: .. note:: - Using type annotations (e.g. `list[int]`) on builtin collections like + Using type arguments (e.g. ``list[int]``) on builtin collections like :py:class:`list`, :py:class:`dict`, :py:class:`tuple`, and :py:class:`set` only works in Python 3.9 and later. For Python 3.8 and earlier, you must use - :py:class:`~typing.List`, :py:class:`~typing.Dict`, etc. + :py:class:`~typing.List` (e.g. ``List[int]``), :py:class:`~typing.Dict`, and + so on. Compatibility of container types @@ -267,19 +268,20 @@ short explanation of the bug. To do that, use this format: app.run(8000) # type: ignore # `run()` now accepts an `int`, as a port -If your error displays an error code, like so: +Mypy displays an error code for each error if you use +:option:`--show-error-codes `: .. code-block:: text error: "str" has no attribute "trim" [attr-defined] -It is possible to add a specific error-code in your ignore comment, like -``# type: ignore[attr-defined]``, to clarify what's being silenced. You can -find more information about error codes here: :ref:`silence-error-codes`. +It is possible to add a specific error-code in your ignore comment (e.g. +``# type: ignore[attr-defined]``) to clarify what's being silenced. You can +find more information about error codes :ref:`here `. Similarly, you can also ignore all mypy checks in a file, by adding a -``# type: ignore`` on the top of the file: +``# type: ignore`` at the top of the file: .. code-block:: python From 1cd6dc9bb34958d086c3cd69676c89295bfb164a Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Wed, 29 Dec 2021 17:42:08 +0300 Subject: [PATCH 013/377] Fix typo in test comment (#11864) --- test-data/unit/semanal-errors.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-data/unit/semanal-errors.test b/test-data/unit/semanal-errors.test index f73de64709260..4b1f4ce00da73 100644 --- a/test-data/unit/semanal-errors.test +++ b/test-data/unit/semanal-errors.test @@ -1440,5 +1440,5 @@ TP2: int = ParamSpec('TP2') # E: Cannot declare the type of a parameter specifi [case testBaseClassAnnotatedWithoutArgs] # https://github.com/python/mypy/issues/11808 from typing_extensions import Annotated -# Nest line should not crash: +# Next line should not crash: class A(Annotated): pass # E: Annotated[...] must have exactly one type argument and at least one annotation From 8d37a8ba5ce994d775ff0c7d5e06c469fb6effc1 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Wed, 29 Dec 2021 20:14:29 +0300 Subject: [PATCH 014/377] Fix glob in .gitattributes for Github stats (#11848) --- .gitattributes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitattributes b/.gitattributes index 13eb5742dbf0a..840ba454b8e38 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,2 @@ # We vendor typeshed from https://github.com/python/typeshed -mypy/typeshed/ linguist-vendored +mypy/typeshed/** linguist-vendored From 3d205764fff2ca792886d84d0a16791dfd33f077 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Wed, 29 Dec 2021 11:54:27 -0600 Subject: [PATCH 015/377] Run mypyc tests against built wheels (#11865) This should catch https://github.com/mypyc/mypyc/issues/912 We never ran mypyc tests against wheels, dating back to https://github.com/python/mypy/tree/783297c9b4ed3b2af9000c3536d6e1be34fed9ea/misc Co-authored-by: hauntsaninja <> --- misc/build_wheel.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/misc/build_wheel.py b/misc/build_wheel.py index 44b40c2e8fed6..4c923279742ea 100644 --- a/misc/build_wheel.py +++ b/misc/build_wheel.py @@ -73,21 +73,19 @@ def create_environ(python_version: str) -> Dict[str, str]: 'MYPY_USE_MYPYC=1 MYPYC_OPT_LEVEL=2 PIP_NO_BUILD_ISOLATION=no' ) - # lxml is slow to build wheels for new releases, so allow installing reqs to fail - # if we failed to install lxml, we'll skip tests, but allow the build to succeed env['CIBW_BEFORE_TEST'] = ( - 'pip install -r {project}/mypy/test-requirements.txt || true' + 'pip install -r {project}/mypy/test-requirements.txt' ) # pytest looks for configuration files in the parent directories of where the tests live. # since we are trying to run the tests from their installed location, we copy those into # the venv. Ew ew ew. env['CIBW_TEST_COMMAND'] = """ - ( ! pip list | grep lxml ) || ( + ( DIR=$(python -c 'import mypy, os; dn = os.path.dirname; print(dn(dn(mypy.__path__[0])))') - && TEST_DIR=$(python -c 'import mypy.test; print(mypy.test.__path__[0])') + && TEST_DIRS=$(python -c 'import mypy.test; import mypyc.test; print(mypy.test.__path__[0], mypyc.test.__path__[0])') && cp '{project}/mypy/pytest.ini' '{project}/mypy/conftest.py' $DIR - && MYPY_TEST_PREFIX='{project}/mypy' pytest $TEST_DIR + && MYPY_TEST_PREFIX='{project}/mypy' pytest $TEST_DIRS ) """.replace('\n', ' ') @@ -95,7 +93,7 @@ def create_environ(python_version: str) -> Dict[str, str]: # previously didn't run any tests on windows wheels, so this is a net win. env['CIBW_TEST_COMMAND_WINDOWS'] = """ bash -c " - ( ! pip list | grep lxml ) || ( + ( DIR=$(python -c 'import mypy, os; dn = os.path.dirname; print(dn(dn(mypy.__path__[0])))') && TEST_DIR=$(python -c 'import mypy.test; print(mypy.test.__path__[0])') && cp '{project}/mypy/pytest.ini' '{project}/mypy/conftest.py' $DIR From 065054826b6c4046b41b2dabb930b51bf2e69490 Mon Sep 17 00:00:00 2001 From: Marti Raudsepp Date: Wed, 29 Dec 2021 20:43:22 +0200 Subject: [PATCH 016/377] Display ellipsis when formatting variadic `tuple[T, ...]` (#11857) Previously variadic tuples were displayed as `builtins.tuple[T]`, which is misleading. That syntax ordinarily indicates a tuple with a single element. This change adds the `...` ellipsis when formatting. The formatting of non-variadic tuples is unchanged (e.g. `Tuple[T, U]`). Fixes #9522 --- mypy/types.py | 8 +++- test-data/unit/check-annotated.test | 2 +- test-data/unit/check-fastparse.test | 8 ++-- test-data/unit/check-generic-alias.test | 8 ++-- test-data/unit/check-generics.test | 6 +-- test-data/unit/check-namedtuple.test | 4 +- test-data/unit/check-overloading.test | 26 +++++------ test-data/unit/check-selftype.test | 8 ++-- test-data/unit/check-serialize.test | 4 +- test-data/unit/check-tuples.test | 62 ++++++++++++------------- test-data/unit/check-type-aliases.test | 2 +- test-data/unit/merge.test | 4 +- test-data/unit/pep561.test | 10 ++-- test-data/unit/pythoneval.test | 2 +- test-data/unit/semanal-classes.test | 2 +- test-data/unit/semanal-python2.test | 2 +- test-data/unit/semanal-types.test | 4 +- 17 files changed, 83 insertions(+), 79 deletions(-) diff --git a/mypy/types.py b/mypy/types.py index 14eefea7dd819..8583f17a30ddc 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -1485,7 +1485,7 @@ class TupleType(ProperType): Instance variables: items: Tuple item types partial_fallback: The (imprecise) underlying instance type that is used - for non-tuple methods. This is generally builtins.tuple[Any] for + for non-tuple methods. This is generally builtins.tuple[Any, ...] for regular tuples, but it's different for named tuples and classes with a tuple base class. Use mypy.typeops.tuple_fallback to calculate the precise fallback type derived from item types. @@ -2203,7 +2203,11 @@ def visit_instance(self, t: Instance) -> str: if t.erased: s += '*' if t.args: - s += '[{}]'.format(self.list_str(t.args)) + if t.type.fullname == 'builtins.tuple': + assert len(t.args) == 1 + s += '[{}, ...]'.format(self.list_str(t.args)) + else: + s += '[{}]'.format(self.list_str(t.args)) if self.id_mapper: s += '<{}>'.format(self.id_mapper.id(t.type)) return s diff --git a/test-data/unit/check-annotated.test b/test-data/unit/check-annotated.test index 68862087d13db..d4309b8ad213e 100644 --- a/test-data/unit/check-annotated.test +++ b/test-data/unit/check-annotated.test @@ -87,7 +87,7 @@ from typing import Tuple from typing_extensions import Annotated Alias = Annotated[Tuple[int, ...], ...] x: Alias -reveal_type(x) # N: Revealed type is "builtins.tuple[builtins.int]" +reveal_type(x) # N: Revealed type is "builtins.tuple[builtins.int, ...]" [builtins fixtures/tuple.pyi] [case testAnnotatedAliasTypeVar] diff --git a/test-data/unit/check-fastparse.test b/test-data/unit/check-fastparse.test index e2dc4f203855c..b30581f0cfd3d 100644 --- a/test-data/unit/check-fastparse.test +++ b/test-data/unit/check-fastparse.test @@ -154,7 +154,7 @@ def f(a, # type: A ): reveal_type(a) # N: Revealed type is "__main__.A" reveal_type(b) # N: Revealed type is "Union[__main__.B, None]" - reveal_type(args) # N: Revealed type is "builtins.tuple[__main__.C]" + reveal_type(args) # N: Revealed type is "builtins.tuple[__main__.C, ...]" reveal_type(d) # N: Revealed type is "Union[__main__.D, None]" reveal_type(e) # N: Revealed type is "__main__.E" reveal_type(kwargs) # N: Revealed type is "builtins.dict[builtins.str, __main__.F]" @@ -179,7 +179,7 @@ def f(a, # type: A # type: (...) -> int reveal_type(a) # N: Revealed type is "__main__.A" reveal_type(b) # N: Revealed type is "Union[__main__.B, None]" - reveal_type(args) # N: Revealed type is "builtins.tuple[__main__.C]" + reveal_type(args) # N: Revealed type is "builtins.tuple[__main__.C, ...]" reveal_type(d) # N: Revealed type is "Union[__main__.D, None]" reveal_type(e) # N: Revealed type is "__main__.E" reveal_type(kwargs) # N: Revealed type is "builtins.dict[builtins.str, __main__.F]" @@ -221,7 +221,7 @@ def f(a, # type: A ): reveal_type(a) # N: Revealed type is "__main__.A" reveal_type(b) # N: Revealed type is "Union[__main__.B, None]" - reveal_type(args) # N: Revealed type is "builtins.tuple[__main__.C]" + reveal_type(args) # N: Revealed type is "builtins.tuple[__main__.C, ...]" [builtins fixtures/dict.pyi] [out] @@ -239,7 +239,7 @@ def f(a, # type: A # type: (...) -> int reveal_type(a) # N: Revealed type is "__main__.A" reveal_type(b) # N: Revealed type is "Union[__main__.B, None]" - reveal_type(args) # N: Revealed type is "builtins.tuple[__main__.C]" + reveal_type(args) # N: Revealed type is "builtins.tuple[__main__.C, ...]" return "not an int" # E: Incompatible return value type (got "str", expected "int") [builtins fixtures/dict.pyi] [out] diff --git a/test-data/unit/check-generic-alias.test b/test-data/unit/check-generic-alias.test index b6060f3922fe9..7000a145e4d16 100644 --- a/test-data/unit/check-generic-alias.test +++ b/test-data/unit/check-generic-alias.test @@ -101,12 +101,12 @@ t11: type[int] reveal_type(t1) # N: Revealed type is "builtins.list[Any]" reveal_type(t2) # N: Revealed type is "builtins.list[builtins.int]" reveal_type(t3) # N: Revealed type is "builtins.list[builtins.str]" -reveal_type(t4) # N: Revealed type is "builtins.tuple[Any]" +reveal_type(t4) # N: Revealed type is "builtins.tuple[Any, ...]" # TODO: ideally these would reveal builtins.tuple reveal_type(t5) # N: Revealed type is "Tuple[builtins.int]" reveal_type(t6) # N: Revealed type is "Tuple[builtins.int, builtins.str]" # TODO: this is incorrect, see #9522 -reveal_type(t7) # N: Revealed type is "builtins.tuple[builtins.int]" +reveal_type(t7) # N: Revealed type is "builtins.tuple[builtins.int, ...]" reveal_type(t8) # N: Revealed type is "builtins.dict[Any, Any]" reveal_type(t9) # N: Revealed type is "builtins.dict[builtins.int, builtins.str]" reveal_type(t10) # N: Revealed type is "builtins.type" @@ -252,13 +252,13 @@ B = tuple[int, str] x: B = (1, 'x') y: B = ('x', 1) # E: Incompatible types in assignment (expression has type "Tuple[str, int]", variable has type "Tuple[int, str]") -reveal_type(tuple[int, ...]()) # N: Revealed type is "builtins.tuple[builtins.int*]" +reveal_type(tuple[int, ...]()) # N: Revealed type is "builtins.tuple[builtins.int*, ...]" [builtins fixtures/tuple.pyi] [case testTypeAliasWithBuiltinTupleInStub] # flags: --python-version 3.6 import m -reveal_type(m.a) # N: Revealed type is "builtins.tuple[builtins.int]" +reveal_type(m.a) # N: Revealed type is "builtins.tuple[builtins.int, ...]" reveal_type(m.b) # N: Revealed type is "Tuple[builtins.int, builtins.str]" [file m.pyi] diff --git a/test-data/unit/check-generics.test b/test-data/unit/check-generics.test index ed0b680e21aa3..61f6f6a7836ba 100644 --- a/test-data/unit/check-generics.test +++ b/test-data/unit/check-generics.test @@ -2073,9 +2073,9 @@ class Base(Generic[T]): return (cls(item),) return cls(item) -reveal_type(Base.make_some) # N: Revealed type is "Overload(def [T] (item: T`1) -> __main__.Base[T`1], def [T] (item: T`1, n: builtins.int) -> builtins.tuple[__main__.Base[T`1]])" +reveal_type(Base.make_some) # N: Revealed type is "Overload(def [T] (item: T`1) -> __main__.Base[T`1], def [T] (item: T`1, n: builtins.int) -> builtins.tuple[__main__.Base[T`1], ...])" reveal_type(Base.make_some(1)) # N: Revealed type is "__main__.Base[builtins.int*]" -reveal_type(Base.make_some(1, 1)) # N: Revealed type is "builtins.tuple[__main__.Base[builtins.int*]]" +reveal_type(Base.make_some(1, 1)) # N: Revealed type is "builtins.tuple[__main__.Base[builtins.int*], ...]" class Sub(Base[str]): ... Sub.make_some(1) # E: No overload variant of "make_some" of "Base" matches argument type "int" \ @@ -2183,7 +2183,7 @@ class C(Generic[T]): class D(C[str]): ... reveal_type(D.get()) # N: Revealed type is "builtins.str*" -reveal_type(D.get(42)) # N: Revealed type is "builtins.tuple[builtins.str*]" +reveal_type(D.get(42)) # N: Revealed type is "builtins.tuple[builtins.str*, ...]" [builtins fixtures/classmethod.pyi] [case testGenericClassMethodAnnotation] diff --git a/test-data/unit/check-namedtuple.test b/test-data/unit/check-namedtuple.test index 440884333c69f..5d28d78013f4c 100644 --- a/test-data/unit/check-namedtuple.test +++ b/test-data/unit/check-namedtuple.test @@ -673,7 +673,7 @@ Node = NamedTuple('Node', [ ('children', Tuple['Node', ...]), # E: Cannot resolve name "Node" (possible cyclic definition) ]) n: Node -reveal_type(n) # N: Revealed type is "Tuple[builtins.str, builtins.tuple[Any], fallback=__main__.Node]" +reveal_type(n) # N: Revealed type is "Tuple[builtins.str, builtins.tuple[Any, ...], fallback=__main__.Node]" [builtins fixtures/tuple.pyi] [case testSelfRefNT2] @@ -689,7 +689,7 @@ class B(NamedTuple): y: int n: A -reveal_type(n) # N: Revealed type is "Tuple[builtins.str, builtins.tuple[Any], fallback=__main__.A]" +reveal_type(n) # N: Revealed type is "Tuple[builtins.str, builtins.tuple[Any, ...], fallback=__main__.A]" [builtins fixtures/tuple.pyi] [case testSelfRefNT3] diff --git a/test-data/unit/check-overloading.test b/test-data/unit/check-overloading.test index d903c895c45c8..d13b5fc4b3e64 100644 --- a/test-data/unit/check-overloading.test +++ b/test-data/unit/check-overloading.test @@ -2589,12 +2589,12 @@ def f(*args): pass i: int reveal_type(f(i)) # N: Revealed type is "Tuple[builtins.int]" reveal_type(f(i, i)) # N: Revealed type is "Tuple[builtins.int, builtins.int]" -reveal_type(f(i, i, i)) # N: Revealed type is "builtins.tuple[builtins.int]" +reveal_type(f(i, i, i)) # N: Revealed type is "builtins.tuple[builtins.int, ...]" -reveal_type(f(*[])) # N: Revealed type is "builtins.tuple[builtins.int]" -reveal_type(f(*[i])) # N: Revealed type is "builtins.tuple[builtins.int]" -reveal_type(f(*[i, i])) # N: Revealed type is "builtins.tuple[builtins.int]" -reveal_type(f(*[i, i, i])) # N: Revealed type is "builtins.tuple[builtins.int]" +reveal_type(f(*[])) # N: Revealed type is "builtins.tuple[builtins.int, ...]" +reveal_type(f(*[i])) # N: Revealed type is "builtins.tuple[builtins.int, ...]" +reveal_type(f(*[i, i])) # N: Revealed type is "builtins.tuple[builtins.int, ...]" +reveal_type(f(*[i, i, i])) # N: Revealed type is "builtins.tuple[builtins.int, ...]" [builtins fixtures/list.pyi] [case testOverloadVarargsSelectionWithTuples] @@ -2608,10 +2608,10 @@ def f(*xs: int) -> Tuple[int, ...]: ... def f(*args): pass i: int -reveal_type(f(*())) # N: Revealed type is "builtins.tuple[builtins.int]" +reveal_type(f(*())) # N: Revealed type is "builtins.tuple[builtins.int, ...]" reveal_type(f(*(i,))) # N: Revealed type is "Tuple[builtins.int]" reveal_type(f(*(i, i))) # N: Revealed type is "Tuple[builtins.int, builtins.int]" -reveal_type(f(*(i, i, i))) # N: Revealed type is "builtins.tuple[builtins.int]" +reveal_type(f(*(i, i, i))) # N: Revealed type is "builtins.tuple[builtins.int, ...]" [builtins fixtures/tuple.pyi] [case testOverloadVarargsSelectionWithNamedTuples] @@ -2631,7 +2631,7 @@ b: B c: C reveal_type(f(*a)) # N: Revealed type is "Tuple[builtins.int, builtins.int]" reveal_type(f(*b)) # N: Revealed type is "Tuple[builtins.int, builtins.int]" -reveal_type(f(*c)) # N: Revealed type is "builtins.tuple[builtins.int]" +reveal_type(f(*c)) # N: Revealed type is "builtins.tuple[builtins.int, ...]" [builtins fixtures/tuple.pyi] [case testOverloadKwargsSelectionWithDict] @@ -2645,10 +2645,10 @@ def f(**xs: int) -> Tuple[int, ...]: ... def f(**kwargs): pass empty: Dict[str, int] -reveal_type(f(**empty)) # N: Revealed type is "builtins.tuple[builtins.int]" -reveal_type(f(**{'x': 4})) # N: Revealed type is "builtins.tuple[builtins.int]" -reveal_type(f(**{'x': 4, 'y': 4})) # N: Revealed type is "builtins.tuple[builtins.int]" -reveal_type(f(**{'a': 4, 'b': 4, 'c': 4})) # N: Revealed type is "builtins.tuple[builtins.int]" +reveal_type(f(**empty)) # N: Revealed type is "builtins.tuple[builtins.int, ...]" +reveal_type(f(**{'x': 4})) # N: Revealed type is "builtins.tuple[builtins.int, ...]" +reveal_type(f(**{'x': 4, 'y': 4})) # N: Revealed type is "builtins.tuple[builtins.int, ...]" +reveal_type(f(**{'a': 4, 'b': 4, 'c': 4})) # N: Revealed type is "builtins.tuple[builtins.int, ...]" [builtins fixtures/dict.pyi] [case testOverloadKwargsSelectionWithTypedDict] @@ -2672,7 +2672,7 @@ c: C reveal_type(f(**a)) # N: Revealed type is "Tuple[builtins.int]" reveal_type(f(**b)) # N: Revealed type is "Tuple[builtins.int, builtins.int]" -reveal_type(f(**c)) # N: Revealed type is "builtins.tuple[builtins.int]" +reveal_type(f(**c)) # N: Revealed type is "builtins.tuple[builtins.int, ...]" [builtins fixtures/dict.pyi] [case testOverloadVarargsAndKwargsSelection] diff --git a/test-data/unit/check-selftype.test b/test-data/unit/check-selftype.test index afd75111743d0..3948d215b192f 100644 --- a/test-data/unit/check-selftype.test +++ b/test-data/unit/check-selftype.test @@ -555,9 +555,9 @@ reveal_type(P) # N: Revealed type is "Overload(def [T] (use_str: Literal[True]) reveal_type(P(use_str=True)) # N: Revealed type is "lib.P[builtins.str]" reveal_type(P(use_str=False)) # N: Revealed type is "lib.P[builtins.int]" -reveal_type(C) # N: Revealed type is "Overload(def [T] (item: T`1, use_tuple: Literal[False]) -> lib.C[T`1], def [T] (item: T`1, use_tuple: Literal[True]) -> lib.C[builtins.tuple[T`1]])" +reveal_type(C) # N: Revealed type is "Overload(def [T] (item: T`1, use_tuple: Literal[False]) -> lib.C[T`1], def [T] (item: T`1, use_tuple: Literal[True]) -> lib.C[builtins.tuple[T`1, ...]])" reveal_type(C(0, use_tuple=False)) # N: Revealed type is "lib.C[builtins.int*]" -reveal_type(C(0, use_tuple=True)) # N: Revealed type is "lib.C[builtins.tuple[builtins.int*]]" +reveal_type(C(0, use_tuple=True)) # N: Revealed type is "lib.C[builtins.tuple[builtins.int*, ...]]" T = TypeVar('T') class SubP(P[T]): @@ -949,9 +949,9 @@ class Other(Base): ... class Double(Sub): ... reveal_type(Other.make()) # N: Revealed type is "__main__.Other*" -reveal_type(Other.make(3)) # N: Revealed type is "builtins.tuple[__main__.Other*]" +reveal_type(Other.make(3)) # N: Revealed type is "builtins.tuple[__main__.Other*, ...]" reveal_type(Double.make()) # N: Revealed type is "__main__.Sub" -reveal_type(Double.make(3)) # N: Revealed type is "builtins.tuple[__main__.Sub]" +reveal_type(Double.make(3)) # N: Revealed type is "builtins.tuple[__main__.Sub, ...]" [file lib.pyi] from typing import overload, TypeVar, Type, Tuple diff --git a/test-data/unit/check-serialize.test b/test-data/unit/check-serialize.test index b34a6c704a27d..3a9d2266dd552 100644 --- a/test-data/unit/check-serialize.test +++ b/test-data/unit/check-serialize.test @@ -1030,8 +1030,8 @@ x: Tuple[int, ...] y: tuple [builtins fixtures/tuple.pyi] [out2] -tmp/a.py:2: note: Revealed type is "builtins.tuple[builtins.int]" -tmp/a.py:3: note: Revealed type is "builtins.tuple[Any]" +tmp/a.py:2: note: Revealed type is "builtins.tuple[builtins.int, ...]" +tmp/a.py:3: note: Revealed type is "builtins.tuple[Any, ...]" [case testSerializeNone] import a diff --git a/test-data/unit/check-tuples.test b/test-data/unit/check-tuples.test index 6c4c63dc5c2d4..b558e1520798c 100644 --- a/test-data/unit/check-tuples.test +++ b/test-data/unit/check-tuples.test @@ -193,7 +193,7 @@ t1[2] # E: Tuple index out of range t1[3] # E: Tuple index out of range t2[1] # E: Tuple index out of range reveal_type(t1[n]) # N: Revealed type is "Union[__main__.A, __main__.B]" -reveal_type(t3[n:]) # N: Revealed type is "builtins.tuple[Union[__main__.A, __main__.B, __main__.C, __main__.D, __main__.E]]" +reveal_type(t3[n:]) # N: Revealed type is "builtins.tuple[Union[__main__.A, __main__.B, __main__.C, __main__.D, __main__.E], ...]" if int(): b = t1[(0)] # E: Incompatible types in assignment (expression has type "A", variable has type "B") @@ -985,15 +985,15 @@ reveal_type(b) # N: Revealed type is "Tuple[builtins.int, builtins.int, builtin [case testTupleWithStarExpr2] a = [1] b = (0, *a) -reveal_type(b) # N: Revealed type is "builtins.tuple[builtins.int*]" +reveal_type(b) # N: Revealed type is "builtins.tuple[builtins.int*, ...]" [builtins fixtures/tuple.pyi] [case testTupleWithStarExpr3] a = [''] b = (0, *a) -reveal_type(b) # N: Revealed type is "builtins.tuple[builtins.object*]" +reveal_type(b) # N: Revealed type is "builtins.tuple[builtins.object*, ...]" c = (*a, '') -reveal_type(c) # N: Revealed type is "builtins.tuple[builtins.str*]" +reveal_type(c) # N: Revealed type is "builtins.tuple[builtins.str*, ...]" [builtins fixtures/tuple.pyi] [case testTupleWithStarExpr4] @@ -1086,12 +1086,12 @@ class B(A): pass fixtup = None # type: Tuple[B, B] vartup_b = None # type: Tuple[B, ...] -reveal_type(fixtup if int() else vartup_b) # N: Revealed type is "builtins.tuple[__main__.B]" -reveal_type(vartup_b if int() else fixtup) # N: Revealed type is "builtins.tuple[__main__.B]" +reveal_type(fixtup if int() else vartup_b) # N: Revealed type is "builtins.tuple[__main__.B, ...]" +reveal_type(vartup_b if int() else fixtup) # N: Revealed type is "builtins.tuple[__main__.B, ...]" vartup_a = None # type: Tuple[A, ...] -reveal_type(fixtup if int() else vartup_a) # N: Revealed type is "builtins.tuple[__main__.A]" -reveal_type(vartup_a if int() else fixtup) # N: Revealed type is "builtins.tuple[__main__.A]" +reveal_type(fixtup if int() else vartup_a) # N: Revealed type is "builtins.tuple[__main__.A, ...]" +reveal_type(vartup_a if int() else fixtup) # N: Revealed type is "builtins.tuple[__main__.A, ...]" [builtins fixtures/tuple.pyi] @@ -1124,12 +1124,12 @@ class A: pass empty = () fixtup = None # type: Tuple[A] -reveal_type(fixtup if int() else empty) # N: Revealed type is "builtins.tuple[__main__.A]" -reveal_type(empty if int() else fixtup) # N: Revealed type is "builtins.tuple[__main__.A]" +reveal_type(fixtup if int() else empty) # N: Revealed type is "builtins.tuple[__main__.A, ...]" +reveal_type(empty if int() else fixtup) # N: Revealed type is "builtins.tuple[__main__.A, ...]" vartup = None # type: Tuple[A, ...] -reveal_type(empty if int() else vartup) # N: Revealed type is "builtins.tuple[__main__.A]" -reveal_type(vartup if int() else empty) # N: Revealed type is "builtins.tuple[__main__.A]" +reveal_type(empty if int() else vartup) # N: Revealed type is "builtins.tuple[__main__.A, ...]" +reveal_type(vartup if int() else empty) # N: Revealed type is "builtins.tuple[__main__.A, ...]" lst = None # type: List[A] reveal_type(empty if int() else lst) # N: Revealed type is "typing.Sequence[__main__.A*]" @@ -1152,8 +1152,8 @@ ntup = None # type: NTup subtup = None # type: SubTuple vartup = None # type: SubVarTuple -reveal_type(ntup if int() else vartup) # N: Revealed type is "builtins.tuple[builtins.int]" -reveal_type(subtup if int() else vartup) # N: Revealed type is "builtins.tuple[builtins.int]" +reveal_type(ntup if int() else vartup) # N: Revealed type is "builtins.tuple[builtins.int, ...]" +reveal_type(subtup if int() else vartup) # N: Revealed type is "builtins.tuple[builtins.int, ...]" [builtins fixtures/tuple.pyi] [out] @@ -1164,14 +1164,14 @@ from typing import Tuple tup1 = None # type: Tuple[bool, int] tup2 = None # type: Tuple[bool] -reveal_type(tup1 if int() else tup2) # N: Revealed type is "builtins.tuple[builtins.int]" -reveal_type(tup2 if int() else tup1) # N: Revealed type is "builtins.tuple[builtins.int]" +reveal_type(tup1 if int() else tup2) # N: Revealed type is "builtins.tuple[builtins.int, ...]" +reveal_type(tup2 if int() else tup1) # N: Revealed type is "builtins.tuple[builtins.int, ...]" -reveal_type(tup1 if int() else ()) # N: Revealed type is "builtins.tuple[builtins.int]" -reveal_type(() if int() else tup1) # N: Revealed type is "builtins.tuple[builtins.int]" +reveal_type(tup1 if int() else ()) # N: Revealed type is "builtins.tuple[builtins.int, ...]" +reveal_type(() if int() else tup1) # N: Revealed type is "builtins.tuple[builtins.int, ...]" -reveal_type(tup2 if int() else ()) # N: Revealed type is "builtins.tuple[builtins.bool]" -reveal_type(() if int() else tup2) # N: Revealed type is "builtins.tuple[builtins.bool]" +reveal_type(tup2 if int() else ()) # N: Revealed type is "builtins.tuple[builtins.bool, ...]" +reveal_type(() if int() else tup2) # N: Revealed type is "builtins.tuple[builtins.bool, ...]" [builtins fixtures/tuple.pyi] [out] @@ -1192,14 +1192,14 @@ tup1 = None # type: NTup1 tup2 = None # type: NTup2 subtup = None # type: SubTuple -reveal_type(tup1 if int() else tup2) # N: Revealed type is "builtins.tuple[builtins.bool]" -reveal_type(tup2 if int() else tup1) # N: Revealed type is "builtins.tuple[builtins.bool]" +reveal_type(tup1 if int() else tup2) # N: Revealed type is "builtins.tuple[builtins.bool, ...]" +reveal_type(tup2 if int() else tup1) # N: Revealed type is "builtins.tuple[builtins.bool, ...]" -reveal_type(tup1 if int() else subtup) # N: Revealed type is "builtins.tuple[builtins.int]" -reveal_type(subtup if int() else tup1) # N: Revealed type is "builtins.tuple[builtins.int]" +reveal_type(tup1 if int() else subtup) # N: Revealed type is "builtins.tuple[builtins.int, ...]" +reveal_type(subtup if int() else tup1) # N: Revealed type is "builtins.tuple[builtins.int, ...]" -reveal_type(tup2 if int() else subtup) # N: Revealed type is "builtins.tuple[builtins.int]" -reveal_type(subtup if int() else tup2) # N: Revealed type is "builtins.tuple[builtins.int]" +reveal_type(tup2 if int() else subtup) # N: Revealed type is "builtins.tuple[builtins.int, ...]" +reveal_type(subtup if int() else tup2) # N: Revealed type is "builtins.tuple[builtins.int, ...]" [builtins fixtures/tuple.pyi] [out] @@ -1263,7 +1263,7 @@ t[y] # E: Invalid tuple index type (actual type "str", expected type "Union[int t = (0, "") x = 0 y = "" -reveal_type(t[x:]) # N: Revealed type is "builtins.tuple[Union[builtins.int, builtins.str]]" +reveal_type(t[x:]) # N: Revealed type is "builtins.tuple[Union[builtins.int, builtins.str], ...]" t[y:] # E: Slice index must be an integer or None [builtins fixtures/tuple.pyi] @@ -1311,7 +1311,7 @@ class CallableTuple(Tuple[str, int]): from typing import Sequence s: Sequence[str] s = tuple() -reveal_type(s) # N: Revealed type is "builtins.tuple[builtins.str]" +reveal_type(s) # N: Revealed type is "builtins.tuple[builtins.str, ...]" [builtins fixtures/tuple.pyi] @@ -1320,7 +1320,7 @@ from typing import Iterable, Tuple x: Iterable[int] = () y: Tuple[int, ...] = (1, 2, 3) x = y -reveal_type(x) # N: Revealed type is "builtins.tuple[builtins.int]" +reveal_type(x) # N: Revealed type is "builtins.tuple[builtins.int, ...]" [builtins fixtures/tuple.pyi] @@ -1481,7 +1481,7 @@ t3 = ('', 1) * 2 reveal_type(t3) # N: Revealed type is "Tuple[builtins.str, builtins.int, builtins.str, builtins.int]" def f() -> Tuple[str, ...]: return ('', ) -reveal_type(f() * 2) # N: Revealed type is "builtins.tuple[builtins.str*]" +reveal_type(f() * 2) # N: Revealed type is "builtins.tuple[builtins.str*, ...]" [builtins fixtures/tuple.pyi] [case testMultiplyTupleByIntegerLiteralReverse] @@ -1494,7 +1494,7 @@ t3 = 2 * ('', 1) reveal_type(t3) # N: Revealed type is "Tuple[builtins.str, builtins.int, builtins.str, builtins.int]" def f() -> Tuple[str, ...]: return ('', ) -reveal_type(2 * f()) # N: Revealed type is "builtins.tuple[builtins.str*]" +reveal_type(2 * f()) # N: Revealed type is "builtins.tuple[builtins.str*, ...]" [builtins fixtures/tuple.pyi] [case testSingleUndefinedTypeAndTuple] diff --git a/test-data/unit/check-type-aliases.test b/test-data/unit/check-type-aliases.test index a697c32d7c49b..eb6c71e8f2268 100644 --- a/test-data/unit/check-type-aliases.test +++ b/test-data/unit/check-type-aliases.test @@ -312,7 +312,7 @@ T = Tuple c: C t: T reveal_type(c) # N: Revealed type is "def (*Any, **Any) -> Any" -reveal_type(t) # N: Revealed type is "builtins.tuple[Any]" +reveal_type(t) # N: Revealed type is "builtins.tuple[Any, ...]" bad: C[int] # E: Bad number of arguments for type alias, expected: 0, given: 1 also_bad: T[int] # E: Bad number of arguments for type alias, expected: 0, given: 1 [builtins fixtures/tuple.pyi] diff --git a/test-data/unit/merge.test b/test-data/unit/merge.test index 836ad87857f85..3eb41c2303ddb 100644 --- a/test-data/unit/merge.test +++ b/test-data/unit/merge.test @@ -665,7 +665,7 @@ TypeInfo<0>( Names()) TypeInfo<2>( Name(target.N) - Bases(builtins.tuple[target.A<0>]<3>) + Bases(builtins.tuple[target.A<0>, ...]<3>) Mro(target.N<2>, builtins.tuple<3>, typing.Sequence<4>, typing.Iterable<5>, builtins.object<1>) Names( _NT<6> @@ -688,7 +688,7 @@ TypeInfo<0>( Names()) TypeInfo<2>( Name(target.N) - Bases(builtins.tuple[target.A<0>]<3>) + Bases(builtins.tuple[target.A<0>, ...]<3>) Mro(target.N<2>, builtins.tuple<3>, typing.Sequence<4>, typing.Iterable<5>, builtins.object<1>) Names( _NT<6> diff --git a/test-data/unit/pep561.test b/test-data/unit/pep561.test index 839ca110b94c8..364414b202e1c 100644 --- a/test-data/unit/pep561.test +++ b/test-data/unit/pep561.test @@ -18,7 +18,7 @@ from typedpkg import dne a = ex(['']) reveal_type(a) [out] -testTypedPkgSimple.py:5: note: Revealed type is "builtins.tuple[builtins.str]" +testTypedPkgSimple.py:5: note: Revealed type is "builtins.tuple[builtins.str, ...]" [case testTypedPkgSimplePackageSearchPath] # pkgs: typedpkg @@ -89,7 +89,7 @@ from typedpkg import dne a = ex(['']) reveal_type(a) [out] -testTypedPkgSimple_python2.py:5: note: Revealed type is "builtins.tuple[builtins.str]" +testTypedPkgSimple_python2.py:5: note: Revealed type is "builtins.tuple[builtins.str, ...]" [case testTypedPkgSimpleEgg] # pkgs: typedpkg; no-pip @@ -98,7 +98,7 @@ from typedpkg import dne a = ex(['']) reveal_type(a) [out] -testTypedPkgSimpleEgg.py:5: note: Revealed type is "builtins.tuple[builtins.str]" +testTypedPkgSimpleEgg.py:5: note: Revealed type is "builtins.tuple[builtins.str, ...]" [case testTypedPkgSimpleEditable] # pkgs: typedpkg; editable @@ -107,7 +107,7 @@ from typedpkg import dne a = ex(['']) reveal_type(a) [out] -testTypedPkgSimpleEditable.py:5: note: Revealed type is "builtins.tuple[builtins.str]" +testTypedPkgSimpleEditable.py:5: note: Revealed type is "builtins.tuple[builtins.str, ...]" [case testTypedPkgSimpleEditableEgg] # pkgs: typedpkg; editable; no-pip @@ -116,7 +116,7 @@ from typedpkg import dne a = ex(['']) reveal_type(a) [out] -testTypedPkgSimpleEditableEgg.py:5: note: Revealed type is "builtins.tuple[builtins.str]" +testTypedPkgSimpleEditableEgg.py:5: note: Revealed type is "builtins.tuple[builtins.str, ...]" [case testTypedPkgNamespaceImportFrom] # pkgs: typedpkg, typedpkg_ns_a diff --git a/test-data/unit/pythoneval.test b/test-data/unit/pythoneval.test index 90588a86d8bf3..9bf511e1aba3c 100644 --- a/test-data/unit/pythoneval.test +++ b/test-data/unit/pythoneval.test @@ -1411,7 +1411,7 @@ accepts_named_tuple(1) accepts_named_tuple((1, 2)) [out] _testNamedTupleTypeInheritanceSpecialCase.py:8: note: Revealed type is "collections.OrderedDict[builtins.str, Any]" -_testNamedTupleTypeInheritanceSpecialCase.py:9: note: Revealed type is "builtins.tuple[builtins.str]" +_testNamedTupleTypeInheritanceSpecialCase.py:9: note: Revealed type is "builtins.tuple[builtins.str, ...]" _testNamedTupleTypeInheritanceSpecialCase.py:10: note: Revealed type is "builtins.dict[builtins.str, Any]" _testNamedTupleTypeInheritanceSpecialCase.py:17: error: Argument 1 to "accepts_named_tuple" has incompatible type "int"; expected "NamedTuple" _testNamedTupleTypeInheritanceSpecialCase.py:18: error: Argument 1 to "accepts_named_tuple" has incompatible type "Tuple[int, int]"; expected "NamedTuple" diff --git a/test-data/unit/semanal-classes.test b/test-data/unit/semanal-classes.test index 3d62fed2b5e76..082a3fe690502 100644 --- a/test-data/unit/semanal-classes.test +++ b/test-data/unit/semanal-classes.test @@ -582,7 +582,7 @@ MypyFile:1( TupleType( Tuple[builtins.int, builtins.str]) BaseType( - builtins.tuple[builtins.object]) + builtins.tuple[builtins.object, ...]) PassStmt:2())) [case testBaseClassFromIgnoredModule] diff --git a/test-data/unit/semanal-python2.test b/test-data/unit/semanal-python2.test index 97264a5dc503c..8bb0f5cf5d9c5 100644 --- a/test-data/unit/semanal-python2.test +++ b/test-data/unit/semanal-python2.test @@ -45,7 +45,7 @@ MypyFile:1( ExpressionStmt:2( CastExpr:2( TupleExpr:2() - builtins.tuple[builtins.int]))) + builtins.tuple[builtins.int, ...]))) [case testTupleArgList_python2] def f(x, (y, z)): diff --git a/test-data/unit/semanal-types.test b/test-data/unit/semanal-types.test index 772de61b59006..1a2eca64a9f2d 100644 --- a/test-data/unit/semanal-types.test +++ b/test-data/unit/semanal-types.test @@ -679,7 +679,7 @@ MypyFile:1( AssignmentStmt:2( NameExpr(t [__main__.t]) NameExpr(None [builtins.None]) - builtins.tuple[Any]) + builtins.tuple[Any, ...]) AssignmentStmt:3( NameExpr(t1 [__main__.t1]) NameExpr(None [builtins.None]) @@ -699,7 +699,7 @@ MypyFile:1( AssignmentStmt:2( NameExpr(t [__main__.t]) NameExpr(None [builtins.None]) - builtins.tuple[builtins.int])) + builtins.tuple[builtins.int, ...])) [case testInvalidTupleType] from typing import Tuple From fe3b625224d0246c90c2a2bca6f293a4586642e9 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" <1330696+mr-c@users.noreply.github.com> Date: Wed, 29 Dec 2021 19:52:07 +0100 Subject: [PATCH 017/377] Skip compiling mypyc/__main__.py (#11862) Fixes https://github.com/mypyc/mypyc/issues/912 Co-authored-by: Shantanu <12621235+hauntsaninja@users.noreply.github.com> --- setup.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/setup.py b/setup.py index 10042279a446d..344fcf94d0cfc 100644 --- a/setup.py +++ b/setup.py @@ -107,6 +107,8 @@ def run(self): )) + ( # Don't want to grab this accidentally os.path.join('mypyc', 'lib-rt', 'setup.py'), + # Uses __file__ at top level https://github.com/mypyc/mypyc/issues/700 + os.path.join('mypyc', '__main__.py'), ) everything = ( From 22d4f1d2356f3858e2de8244531937ab85cac44a Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Wed, 29 Dec 2021 18:04:10 -0600 Subject: [PATCH 018/377] Skip lxml and mypyc external tests against built wheels (#11872) Co-authored-by: hauntsaninja <> --- misc/build_wheel.py | 15 ++++++++++++--- mypy/test/testreports.py | 4 ++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/misc/build_wheel.py b/misc/build_wheel.py index 4c923279742ea..4738115aae26f 100644 --- a/misc/build_wheel.py +++ b/misc/build_wheel.py @@ -73,19 +73,28 @@ def create_environ(python_version: str) -> Dict[str, str]: 'MYPY_USE_MYPYC=1 MYPYC_OPT_LEVEL=2 PIP_NO_BUILD_ISOLATION=no' ) + # lxml doesn't have a wheel for Python 3.10 on the manylinux image we use. + # lxml has historically been slow to support new Pythons as well. env['CIBW_BEFORE_TEST'] = ( - 'pip install -r {project}/mypy/test-requirements.txt' + 'pip install -r <(grep -v lxml {project}/mypy/test-requirements.txt)' ) # pytest looks for configuration files in the parent directories of where the tests live. # since we are trying to run the tests from their installed location, we copy those into # the venv. Ew ew ew. + # We don't run tests that need lxml since we don't install lxml + # We don't run external mypyc tests since there's some issue with compilation on the + # manylinux image we use. env['CIBW_TEST_COMMAND'] = """ ( DIR=$(python -c 'import mypy, os; dn = os.path.dirname; print(dn(dn(mypy.__path__[0])))') - && TEST_DIRS=$(python -c 'import mypy.test; import mypyc.test; print(mypy.test.__path__[0], mypyc.test.__path__[0])') && cp '{project}/mypy/pytest.ini' '{project}/mypy/conftest.py' $DIR - && MYPY_TEST_PREFIX='{project}/mypy' pytest $TEST_DIRS + + && MYPY_TEST_DIR=$(python -c 'import mypy.test; print(mypy.test.__path__[0])') + && MYPY_TEST_PREFIX='{project}/mypy' pytest $MYPY_TEST_DIR -k 'not (reports.test or testreports)' + + && MYPYC_TEST_DIR=$(python -c 'import mypyc.test; print(mypyc.test.__path__[0])') + && pytest $MYPYC_TEST_DIR -k 'not test_external' ) """.replace('\n', ' ') diff --git a/mypy/test/testreports.py b/mypy/test/testreports.py index 84ac3e005bec1..75f24d514431a 100644 --- a/mypy/test/testreports.py +++ b/mypy/test/testreports.py @@ -4,8 +4,6 @@ from mypy.test.helpers import Suite, assert_equal from mypy.report import CoberturaPackage, get_line_rate -import lxml.etree as etree # type: ignore - class CoberturaReportSuite(Suite): def test_get_line_rate(self) -> None: @@ -13,6 +11,8 @@ def test_get_line_rate(self) -> None: assert_equal('0.3333', get_line_rate(1, 3)) def test_as_xml(self) -> None: + import lxml.etree as etree # type: ignore + cobertura_package = CoberturaPackage('foobar') cobertura_package.covered_lines = 21 cobertura_package.total_lines = 42 From 021ac8a9460c5f667e3683e3da71848814eddaba Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Wed, 29 Dec 2021 21:18:33 -0600 Subject: [PATCH 019/377] Fix shell syntax in build_wheel (#11873) Follow up to #11872 The cross repo split makes this a bit of a pain to test. Co-authored-by: hauntsaninja <> --- misc/build_wheel.py | 13 +++++++++---- mypyc/test/config.py | 12 ++++++++---- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/misc/build_wheel.py b/misc/build_wheel.py index 4738115aae26f..b124a11d8c950 100644 --- a/misc/build_wheel.py +++ b/misc/build_wheel.py @@ -75,9 +75,14 @@ def create_environ(python_version: str) -> Dict[str, str]: # lxml doesn't have a wheel for Python 3.10 on the manylinux image we use. # lxml has historically been slow to support new Pythons as well. - env['CIBW_BEFORE_TEST'] = ( - 'pip install -r <(grep -v lxml {project}/mypy/test-requirements.txt)' - ) + env['CIBW_BEFORE_TEST'] = """ + ( + grep -v lxml {project}/mypy/test-requirements.txt > /tmp/test-requirements.txt + && cp {project}/mypy/mypy-requirements.txt /tmp/mypy-requirements.txt + && cp {project}/mypy/build-requirements.txt /tmp/build-requirements.txt + && pip install -r /tmp/test-requirements.txt + ) + """.replace('\n', ' ') # pytest looks for configuration files in the parent directories of where the tests live. # since we are trying to run the tests from their installed location, we copy those into @@ -94,7 +99,7 @@ def create_environ(python_version: str) -> Dict[str, str]: && MYPY_TEST_PREFIX='{project}/mypy' pytest $MYPY_TEST_DIR -k 'not (reports.test or testreports)' && MYPYC_TEST_DIR=$(python -c 'import mypyc.test; print(mypyc.test.__path__[0])') - && pytest $MYPYC_TEST_DIR -k 'not test_external' + && MYPY_TEST_PREFIX='{project}/mypy' pytest $MYPYC_TEST_DIR -k 'not test_external' ) """.replace('\n', ' ') diff --git a/mypyc/test/config.py b/mypyc/test/config.py index 6b2c09d1ebfb7..1158c5c459be8 100644 --- a/mypyc/test/config.py +++ b/mypyc/test/config.py @@ -1,7 +1,11 @@ import os -this_file_dir = os.path.dirname(os.path.realpath(__file__)) -prefix = os.path.dirname(os.path.dirname(this_file_dir)) +provided_prefix = os.getenv('MYPY_TEST_PREFIX', None) +if provided_prefix: + PREFIX = provided_prefix +else: + this_file_dir = os.path.dirname(os.path.realpath(__file__)) + PREFIX = os.path.dirname(os.path.dirname(this_file_dir)) -# Locations of test data files such as test case descriptions (.test). -test_data_prefix = os.path.join(prefix, 'mypyc', 'test-data') +# Location of test data files such as test case descriptions. +test_data_prefix = os.path.join(PREFIX, 'mypyc', 'test-data') From b6c8f0358c2079c9c10bf0fbda1598ed2b18e60b Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Thu, 30 Dec 2021 08:31:38 +0300 Subject: [PATCH 020/377] Fixes regression with `__module__` and similar non-final `Enum` names, refs #11820 (#11823) --- mypy/semanal_enum.py | 2 ++ test-data/unit/check-enum.test | 12 +++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/mypy/semanal_enum.py b/mypy/semanal_enum.py index 5682f66298f6a..c900c5fa790f9 100644 --- a/mypy/semanal_enum.py +++ b/mypy/semanal_enum.py @@ -21,6 +21,8 @@ )) ENUM_SPECIAL_PROPS: Final = frozenset(( 'name', 'value', '_name_', '_value_', '_order_', '__order__', + # Also attributes from `object`: + '__module__', '__annotations__', '__doc__', '__slots__', '__dict__', )) diff --git a/test-data/unit/check-enum.test b/test-data/unit/check-enum.test index a393df0797301..c29ee7b24cf3c 100644 --- a/test-data/unit/check-enum.test +++ b/test-data/unit/check-enum.test @@ -1689,6 +1689,11 @@ class E(Enum): _value_ = 'b2' _order_ = 'X Y' __order__ = 'X Y' + __slots__ = () + __doc__ = 'doc' + __module__ = 'module' + __annotations__ = {'a': int} + __dict__ = {'a': 1} class EI(IntEnum): name = 'a' @@ -1697,10 +1702,15 @@ class EI(IntEnum): _value_ = 2 _order_ = 'X Y' __order__ = 'X Y' + __slots__ = () + __doc__ = 'doc' + __module__ = 'module' + __annotations__ = {'a': int} + __dict__ = {'a': 1} E._order_ = 'a' # E: Cannot assign to final attribute "_order_" EI.value = 2 # E: Cannot assign to final attribute "value" -[builtins fixtures/bool.pyi] +[builtins fixtures/dict.pyi] [case testEnumNotFinalWithMethodsAndUninitializedValues] # https://github.com/python/mypy/issues/11578 From d168b6d091de63995bcdb796085b48dec1292f98 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Thu, 30 Dec 2021 15:41:02 -0600 Subject: [PATCH 021/377] Fix `--no-implicit-reexport` inconsistency (#11707) Fixes #11706 Co-authored-by: hauntsaninja <> --- mypy/semanal.py | 6 +++++- test-data/unit/check-modules.test | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index a9226d2cdd0c9..0c38793d013fa 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -1906,7 +1906,11 @@ def process_imported_symbol(self, fullname: str, module_public: bool, context: ImportBase) -> None: - module_hidden = not module_public and fullname not in self.modules + module_hidden = not module_public and not ( + # `from package import module` should work regardless of whether package + # re-exports module + isinstance(node.node, MypyFile) and fullname in self.modules + ) if isinstance(node.node, PlaceholderNode): if self.final_iteration: diff --git a/test-data/unit/check-modules.test b/test-data/unit/check-modules.test index 071fcf54f2b64..4f0aa83912ea7 100644 --- a/test-data/unit/check-modules.test +++ b/test-data/unit/check-modules.test @@ -1910,6 +1910,24 @@ class C: [builtins fixtures/module.pyi] +[case testReExportChildStubs3] +from util import mod +reveal_type(mod) # N: Revealed type is "def () -> package.mod.mod" + +from util import internal_detail # E: Module "util" has no attribute "internal_detail" + +[file package/__init__.pyi] +from .mod import mod as mod + +[file package/mod.pyi] +class mod: ... + +[file util.pyi] +from package import mod as mod +# stubs require explicit re-export +from package import mod as internal_detail +[builtins fixtures/module.pyi] + [case testNoReExportChildStubs] import mod from mod import C, D # E: Module "mod" has no attribute "C" From 0390485f9732f4d1d7680810c8eff250dba83ba0 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Thu, 30 Dec 2021 15:41:36 -0600 Subject: [PATCH 022/377] Consider import * to be an explicit re-export (#11867) Resolves #11856 Co-authored-by: hauntsaninja <> --- mypy/semanal.py | 8 +++----- test-data/unit/check-flags.test | 14 +------------- 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 0c38793d013fa..087671e6d973c 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -2041,12 +2041,10 @@ def visit_import_all(self, i: ImportAll) -> None: if self.process_import_over_existing_name( name, existing_symbol, node, i): continue - # In stub files, `from x import *` always reexports the symbols. - # In regular files, only if implicit reexports are enabled. - module_public = self.is_stub_file or self.options.implicit_reexport + # `from x import *` always reexports symbols self.add_imported_symbol(name, node, i, - module_public=module_public, - module_hidden=not module_public) + module_public=True, + module_hidden=False) else: # Don't add any dummy symbols for 'from x import *' if 'x' is unknown. diff --git a/test-data/unit/check-flags.test b/test-data/unit/check-flags.test index 02f6b034c512b..8f72a82b0760d 100644 --- a/test-data/unit/check-flags.test +++ b/test-data/unit/check-flags.test @@ -1562,17 +1562,7 @@ __all__ = ('b',) [out] main:2: error: Module "other_module_2" does not explicitly export attribute "a"; implicit reexport disabled -[case testNoImplicitReexportStarConsideredImplicit] -# flags: --no-implicit-reexport -from other_module_2 import a -[file other_module_1.py] -a = 5 -[file other_module_2.py] -from other_module_1 import * -[out] -main:2: error: Module "other_module_2" does not explicitly export attribute "a"; implicit reexport disabled - -[case testNoImplicitReexportStarCanBeReexportedWithAll] +[case testNoImplicitReexportStarConsideredExplicit] # flags: --no-implicit-reexport from other_module_2 import a from other_module_2 import b @@ -1583,8 +1573,6 @@ b = 6 from other_module_1 import * __all__ = ('b',) [builtins fixtures/tuple.pyi] -[out] -main:2: error: Module "other_module_2" does not explicitly export attribute "a"; implicit reexport disabled [case testNoImplicitReexportGetAttr] # flags: --no-implicit-reexport --python-version 3.7 From ee37502badf15c678489ee10e38131cf337b8353 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Fri, 31 Dec 2021 01:01:18 +0300 Subject: [PATCH 023/377] Fixes `__slots__` regression in 0.930 (#11824) Closes #11821 Closes #11827 --- mypy/plugins/dataclasses.py | 9 ++-- test-data/unit/check-dataclasses.test | 66 +++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 3 deletions(-) diff --git a/mypy/plugins/dataclasses.py b/mypy/plugins/dataclasses.py index 6d78bc17e615a..e3daec58922f5 100644 --- a/mypy/plugins/dataclasses.py +++ b/mypy/plugins/dataclasses.py @@ -221,9 +221,12 @@ def add_slots(self, self._ctx.reason, ) return - if info.slots is not None or info.names.get('__slots__'): + + generated_slots = {attr.name for attr in attributes} + if ((info.slots is not None and info.slots != generated_slots) + or info.names.get('__slots__')): # This means we have a slots conflict. - # Class explicitly specifies `__slots__` field. + # Class explicitly specifies a different `__slots__` field. # And `@dataclass(slots=True)` is used. # In runtime this raises a type error. self._ctx.api.fail( @@ -234,7 +237,7 @@ def add_slots(self, ) return - info.slots = {attr.name for attr in attributes} + info.slots = generated_slots def reset_init_only_vars(self, info: TypeInfo, attributes: List[DataclassAttribute]) -> None: """Remove init-only vars from the class and reset init var declarations.""" diff --git a/test-data/unit/check-dataclasses.test b/test-data/unit/check-dataclasses.test index 73476a646c994..80e5f81e110fa 100644 --- a/test-data/unit/check-dataclasses.test +++ b/test-data/unit/check-dataclasses.test @@ -1456,3 +1456,69 @@ class Other: __slots__ = ('x',) x: int [builtins fixtures/dataclasses.pyi] + + +[case testSlotsDefinitionWithTwoPasses1] +# flags: --python-version 3.10 +# https://github.com/python/mypy/issues/11821 +from typing import TypeVar, Protocol, Generic +from dataclasses import dataclass + +C = TypeVar("C", bound="Comparable") + +class Comparable(Protocol): + pass + +V = TypeVar("V", bound=Comparable) + +@dataclass(slots=True) +class Node(Generic[V]): # Error was here + data: V +[builtins fixtures/dataclasses.pyi] + +[case testSlotsDefinitionWithTwoPasses2] +# flags: --python-version 3.10 +from typing import TypeVar, Protocol, Generic +from dataclasses import dataclass + +C = TypeVar("C", bound="Comparable") + +class Comparable(Protocol): + pass + +V = TypeVar("V", bound=Comparable) + +@dataclass(slots=True) # Explicit slots are still not ok: +class Node(Generic[V]): # E: "Node" both defines "__slots__" and is used with "slots=True" + __slots__ = ('data',) + data: V +[builtins fixtures/dataclasses.pyi] + +[case testSlotsDefinitionWithTwoPasses3] +# flags: --python-version 3.10 +from typing import TypeVar, Protocol, Generic +from dataclasses import dataclass + +C = TypeVar("C", bound="Comparable") + +class Comparable(Protocol): + pass + +V = TypeVar("V", bound=Comparable) + +@dataclass(slots=True) # Explicit slots are still not ok, even empty ones: +class Node(Generic[V]): # E: "Node" both defines "__slots__" and is used with "slots=True" + __slots__ = () + data: V +[builtins fixtures/dataclasses.pyi] + +[case testSlotsDefinitionWithTwoPasses4] +# flags: --python-version 3.10 +import dataclasses as dtc + +PublishedMessagesVar = dict[int, 'PublishedMessages'] + +@dtc.dataclass(frozen=True, slots=True) +class PublishedMessages: + left: int +[builtins fixtures/dataclasses.pyi] From dec07872d1d5221c571ed6e7346d6308daf71c18 Mon Sep 17 00:00:00 2001 From: KotlinIsland <65446343+KotlinIsland@users.noreply.github.com> Date: Sat, 1 Jan 2022 10:11:01 +1000 Subject: [PATCH 024/377] Update issue templates with links (#11874) Co-authored-by: KotlinIsland --- .github/ISSUE_TEMPLATE/config.yml | 7 +++++++ .github/ISSUE_TEMPLATE/question.md | 15 --------------- 2 files changed, 7 insertions(+), 15 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/config.yml delete mode 100644 .github/ISSUE_TEMPLATE/question.md diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000000..64a2e6494c1b1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,7 @@ +contact_links: + - about: "Please check the linked documentation page before filing new issues." + name: "Common issues and solutions" + url: "https://mypy.readthedocs.io/en/stable/common_issues.html" + - about: "Please ask and answer any questions on the mypy Gitter." + name: "Questions or Chat" + url: "https://gitter.im/python/typing" diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md deleted file mode 100644 index eccce57a270d4..0000000000000 --- a/.github/ISSUE_TEMPLATE/question.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -name: Questions and Help -about: If you have questions, please check the below links -labels: "question" ---- - -**Questions and Help** - -_Please note that this issue tracker is not a help form and this issue will be closed._ - -Please check here instead: - -- [Website](http://www.mypy-lang.org/) -- [Documentation](https://mypy.readthedocs.io/) -- [Gitter](https://gitter.im/python/typing) From ef07896184fd440f826187f1a98ca2bf50b137b4 Mon Sep 17 00:00:00 2001 From: Oliver Newman <15459200+orn688@users.noreply.github.com> Date: Fri, 31 Dec 2021 19:11:38 -0500 Subject: [PATCH 025/377] Fix typo in command line docs (#11842) --- docs/source/command_line.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/command_line.rst b/docs/source/command_line.rst index a729ac2baca0c..02218e0fbcbde 100644 --- a/docs/source/command_line.rst +++ b/docs/source/command_line.rst @@ -274,7 +274,7 @@ For more information on how to use these flags, see :ref:`version_and_platform_c Disallow dynamic typing *********************** -The ``Any`` type is used represent a value that has a :ref:`dynamic type `. +The ``Any`` type is used to represent a value that has a :ref:`dynamic type `. The ``--disallow-any`` family of flags will disallow various uses of the ``Any`` type in a module -- this lets us strategically disallow the use of dynamic typing in a controlled way. From 1beed9af48bed07033490f8cf2d4e08229450c5f Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Sat, 1 Jan 2022 03:15:24 +0300 Subject: [PATCH 026/377] Remove a lot of unused code (#11698) --- mypy/checker.py | 6 +++--- mypy/git.py | 6 ------ mypy/join.py | 7 +++---- mypy/meet.py | 3 +-- mypy/messages.py | 8 ++------ mypy/plugins/singledispatch.py | 9 --------- mypy/semanal.py | 16 ---------------- mypy/semanal_shared.py | 24 +----------------------- mypy/server/update.py | 7 ------- mypy/subtypes.py | 4 ---- mypy/suggestions.py | 17 ++++++++--------- mypy/typeanal.py | 20 -------------------- mypy/typeops.py | 21 +-------------------- mypy/types.py | 30 ++++++++++++++++++++++++++++-- 14 files changed, 47 insertions(+), 131 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index b90221a0a5a53..95af9e5f01e99 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -63,7 +63,7 @@ from mypy.message_registry import ErrorMessage from mypy.subtypes import ( is_subtype, is_equivalent, is_proper_subtype, is_more_precise, - restrict_subtype_away, is_subtype_ignoring_tvars, is_callable_compatible, + restrict_subtype_away, is_callable_compatible, unify_generic_callable, find_member ) from mypy.constraints import SUPERTYPE_OF @@ -956,7 +956,7 @@ def check_func_def(self, defn: FuncItem, typ: CallableType, name: Optional[str]) if isclass: ref_type = mypy.types.TypeType.make_normalized(ref_type) erased = get_proper_type(erase_to_bound(arg_type)) - if not is_subtype_ignoring_tvars(ref_type, erased): + if not is_subtype(ref_type, erased, ignore_type_params=True): note = None if (isinstance(erased, Instance) and erased.type.is_protocol or isinstance(erased, TypeType) and @@ -1737,7 +1737,7 @@ def erase_override(t: Type) -> Type: if len(order) == len(original.items) and order != sorted(order): self.msg.overload_signature_incompatible_with_supertype( - name, name_in_super, supertype, override, node) + name, name_in_super, supertype, node) emitted_msg = True if not emitted_msg: diff --git a/mypy/git.py b/mypy/git.py index da36ff2cb54ae..8e73b1eeb9c5c 100644 --- a/mypy/git.py +++ b/mypy/git.py @@ -30,9 +30,3 @@ def is_dirty(dir: str) -> bool: """Check whether a git repository has uncommitted changes.""" output = subprocess.check_output(["git", "status", "-uno", "--porcelain"], cwd=dir) return output.strip() != b"" - - -def has_extra_files(dir: str) -> bool: - """Check whether a git repository has untracked files.""" - output = subprocess.check_output(["git", "clean", "--dry-run", "-d"], cwd=dir) - return output.strip() != b"" diff --git a/mypy/join.py b/mypy/join.py index e0d926f3fcf4d..d298b495fdc51 100644 --- a/mypy/join.py +++ b/mypy/join.py @@ -11,7 +11,7 @@ ) from mypy.maptype import map_instance_to_supertype from mypy.subtypes import ( - is_subtype, is_equivalent, is_subtype_ignoring_tvars, is_proper_subtype, + is_subtype, is_equivalent, is_proper_subtype, is_protocol_implementation, find_member ) from mypy.nodes import INVARIANT, COVARIANT, CONTRAVARIANT @@ -72,7 +72,7 @@ def join_instances(self, t: Instance, s: Instance) -> ProperType: assert new_type is not None args.append(new_type) result: ProperType = Instance(t.type, args) - elif t.type.bases and is_subtype_ignoring_tvars(t, s): + elif t.type.bases and is_subtype(t, s, ignore_type_params=True): result = self.join_instances_via_supertype(t, s) else: # Now t is not a subtype of s, and t != s. Now s could be a subtype @@ -402,8 +402,7 @@ def visit_typeddict_type(self, t: TypedDictType) -> ProperType: if (is_equivalent(s_item_type, t_item_type) and (item_name in t.required_keys) == (item_name in self.s.required_keys)) ]) - mapping_value_type = join_type_list(list(items.values())) - fallback = self.s.create_anonymous_fallback(value_type=mapping_value_type) + 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. required_keys = set(items.keys()) & t.required_keys & self.s.required_keys diff --git a/mypy/meet.py b/mypy/meet.py index 644b57afbcbe0..2ea2bc62a660a 100644 --- a/mypy/meet.py +++ b/mypy/meet.py @@ -629,8 +629,7 @@ def visit_typeddict_type(self, t: TypedDictType) -> ProperType: assert t_item_type is not None item_list.append((item_name, t_item_type)) items = OrderedDict(item_list) - mapping_value_type = join.join_type_list(list(items.values())) - fallback = self.s.create_anonymous_fallback(value_type=mapping_value_type) + fallback = self.s.create_anonymous_fallback() required_keys = t.required_keys | self.s.required_keys return TypedDictType(items, required_keys, fallback) elif isinstance(self.s, Instance) and is_subtype(t, self.s): diff --git a/mypy/messages.py b/mypy/messages.py index da284cc88ba43..1e89585000ea1 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -807,7 +807,7 @@ def incompatible_operator_assignment(self, op: str, def overload_signature_incompatible_with_supertype( self, name: str, name_in_super: str, supertype: str, - overload: Overloaded, context: Context) -> None: + context: Context) -> None: target = self.override_target(name, name_in_super, supertype) self.fail('Signature of "{}" incompatible with {}'.format( name, target), context, code=codes.OVERRIDE) @@ -1399,9 +1399,6 @@ def redundant_condition_in_comprehension(self, truthiness: bool, context: Contex def redundant_condition_in_if(self, truthiness: bool, context: Context) -> None: self.redundant_expr("If condition", truthiness, context) - def redundant_condition_in_assert(self, truthiness: bool, context: Context) -> None: - self.redundant_expr("Condition in assert", truthiness, context) - def redundant_expr(self, description: str, truthiness: bool, context: Context) -> None: self.fail("{} is always {}".format(description, str(truthiness).lower()), context, code=codes.REDUNDANT_EXPR) @@ -1855,8 +1852,7 @@ def format_type(typ: Type, verbosity: int = 0) -> str: def format_type_bare(typ: Type, - verbosity: int = 0, - fullnames: Optional[Set[str]] = None) -> str: + verbosity: int = 0) -> str: """ Convert a type to a relatively short string suitable for error messages. diff --git a/mypy/plugins/singledispatch.py b/mypy/plugins/singledispatch.py index 104faa38d1ce9..f4b3d7c19425c 100644 --- a/mypy/plugins/singledispatch.py +++ b/mypy/plugins/singledispatch.py @@ -201,15 +201,6 @@ def call_singledispatch_function_after_register_argument(ctx: MethodContext) -> return ctx.default_return_type -def rename_func(func: CallableType, new_name: CallableType) -> CallableType: - """Return a new CallableType that is `function` with the name of `new_name`""" - if new_name.name is not None: - signature_used = func.with_name(new_name.name) - else: - signature_used = func - return signature_used - - def call_singledispatch_function_callback(ctx: MethodSigContext) -> FunctionLike: """Called for functools._SingleDispatchCallable.__call__""" if not isinstance(ctx.type, Instance): diff --git a/mypy/semanal.py b/mypy/semanal.py index 087671e6d973c..29dfc96c24229 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4979,19 +4979,6 @@ def add_exports(self, exp_or_exps: Union[Iterable[Expression], Expression]) -> N if isinstance(exp, StrExpr): self.all_exports.append(exp.value) - def check_no_global(self, - name: str, - ctx: Context, - is_overloaded_func: bool = False) -> None: - if name in self.globals: - prev_is_overloaded = isinstance(self.globals[name], OverloadedFuncDef) - if is_overloaded_func and prev_is_overloaded: - self.fail("Nonconsecutive overload {} found".format(name), ctx) - elif prev_is_overloaded: - self.fail("Definition of '{}' missing 'overload'".format(name), ctx) - else: - self.name_already_defined(name, ctx, self.globals[name]) - def name_not_defined(self, name: str, ctx: Context, namespace: Optional[str] = None) -> None: incomplete = self.is_incomplete_namespace(namespace or self.cur_mod_id) if (namespace is None @@ -5121,9 +5108,6 @@ def fail(self, assert ctx is not None, msg self.errors.report(ctx.get_line(), ctx.get_column(), msg, blocker=blocker, code=code) - def fail_blocker(self, msg: str, ctx: Context) -> None: - self.fail(msg, ctx, blocker=True) - def note(self, msg: str, ctx: Context, code: Optional[ErrorCode] = None) -> None: if not self.in_checked_function(): return diff --git a/mypy/semanal_shared.py b/mypy/semanal_shared.py index 3638d0878d8f7..85a6779ac9f3b 100644 --- a/mypy/semanal_shared.py +++ b/mypy/semanal_shared.py @@ -7,10 +7,9 @@ from mypy_extensions import trait from mypy.nodes import ( - Context, SymbolTableNode, MypyFile, ImportedName, FuncDef, Node, TypeInfo, Expression, GDEF, + Context, SymbolTableNode, FuncDef, Node, TypeInfo, Expression, SymbolNode, SymbolTable ) -from mypy.util import correct_relative_import from mypy.types import ( Type, FunctionLike, Instance, TupleType, TPDICT_FB_NAMES, ProperType, get_proper_type ) @@ -179,27 +178,6 @@ def is_func_scope(self) -> bool: raise NotImplementedError -def create_indirect_imported_name(file_node: MypyFile, - module: str, - relative: int, - imported_name: str) -> Optional[SymbolTableNode]: - """Create symbol table entry for a name imported from another module. - - These entries act as indirect references. - """ - target_module, ok = correct_relative_import( - file_node.fullname, - relative, - module, - file_node.is_package_init_file()) - if not ok: - return None - target_name = '%s.%s' % (target_module, imported_name) - link = ImportedName(target_name) - # Use GDEF since this refers to a module-level definition. - return SymbolTableNode(GDEF, link) - - def set_callable_name(sig: Type, fdef: FuncDef) -> ProperType: sig = get_proper_type(sig) if isinstance(sig, FunctionLike): diff --git a/mypy/server/update.py b/mypy/server/update.py index e82064c63a11a..2f57001766d57 100644 --- a/mypy/server/update.py +++ b/mypy/server/update.py @@ -485,13 +485,6 @@ def ensure_trees_loaded(manager: BuildManager, graph: Dict[str, State], process_fresh_modules(graph, to_process, manager) -def fix_fg_dependencies(manager: BuildManager, deps: Dict[str, Set[str]]) -> None: - """Populate the dependencies with stuff that build may have missed""" - # This means the root module and typestate - merge_dependencies(manager.load_fine_grained_deps(FAKE_ROOT_MODULE), deps) - # TypeState.add_all_protocol_deps(deps) - - # The result of update_module_isolated when no blockers, with these items: # # - Id of the changed module (can be different from the module argument) diff --git a/mypy/subtypes.py b/mypy/subtypes.py index f90009445b098..cb7f53f0d7cbb 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -154,10 +154,6 @@ def _is_subtype(left: Type, right: Type, ignore_promotions=ignore_promotions)) -def is_subtype_ignoring_tvars(left: Type, right: Type) -> bool: - return is_subtype(left, right, ignore_type_params=True) - - def is_equivalent(a: Type, b: Type, *, ignore_type_params: bool = False, diff --git a/mypy/suggestions.py b/mypy/suggestions.py index 87b54814c6373..af42cca8a2165 100644 --- a/mypy/suggestions.py +++ b/mypy/suggestions.py @@ -344,9 +344,11 @@ def get_args(self, is_method: bool, types.append(arg_types) return types - def get_default_arg_types(self, state: State, fdef: FuncDef) -> List[Optional[Type]]: - return [self.manager.all_types[arg.initializer] if arg.initializer else None - for arg in fdef.arguments] + def get_default_arg_types(self, fdef: FuncDef) -> List[Optional[Type]]: + return [ + self.manager.all_types[arg.initializer] if arg.initializer else None + for arg in fdef.arguments + ] def add_adjustments(self, typs: List[Type]) -> List[Type]: if not self.try_text or self.manager.options.python_version[0] != 2: @@ -441,7 +443,7 @@ def get_suggestion(self, mod: str, node: FuncDef) -> PyAnnotateSignature: guesses = self.get_guesses( is_method, self.get_starting_type(node), - self.get_default_arg_types(graph[mod], node), + self.get_default_arg_types(node), callsites, uses, ) @@ -632,11 +634,8 @@ def try_type(self, func: FuncDef, typ: ProperType) -> List[str]: finally: func.unanalyzed_type = old - def reload(self, state: State, check_errors: bool = False) -> List[str]: - """Recheck the module given by state. - - If check_errors is true, raise an exception if there are errors. - """ + def reload(self, state: State) -> List[str]: + """Recheck the module given by state.""" assert state.path is not None self.fgmanager.flush_cache() return self.fgmanager.update([(state.id, state.path)], []) diff --git a/mypy/typeanal.py b/mypy/typeanal.py index e29ccfd3c928a..8b399bc2c70fe 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -1358,26 +1358,6 @@ def visit_typeddict_type(self, t: TypedDictType) -> bool: return False -def collect_any_types(t: Type) -> List[AnyType]: - """Return all inner `AnyType`s of type t""" - return t.accept(CollectAnyTypesQuery()) - - -class CollectAnyTypesQuery(TypeQuery[List[AnyType]]): - def __init__(self) -> None: - super().__init__(self.combine_lists_strategy) - - def visit_any(self, t: AnyType) -> List[AnyType]: - return [t] - - @classmethod - def combine_lists_strategy(cls, it: Iterable[List[AnyType]]) -> List[AnyType]: - result: List[AnyType] = [] - for l in it: - result.extend(l) - return result - - def collect_all_inner_types(t: Type) -> List[Type]: """ Return all types that `t` contains diff --git a/mypy/typeops.py b/mypy/typeops.py index 9ba170b4b822b..f1d9f2daed553 100644 --- a/mypy/typeops.py +++ b/mypy/typeops.py @@ -12,7 +12,7 @@ from mypy.types import ( TupleType, Instance, FunctionLike, Type, CallableType, TypeVarLikeType, Overloaded, - TypeVarType, UninhabitedType, FormalArgument, UnionType, NoneType, TypedDictType, + TypeVarType, UninhabitedType, FormalArgument, UnionType, NoneType, AnyType, TypeOfAny, TypeType, ProperType, LiteralType, get_proper_type, get_proper_types, copy_type, TypeAliasType, TypeQuery, ParamSpecType ) @@ -44,25 +44,6 @@ def tuple_fallback(typ: TupleType) -> Instance: return Instance(info, [join_type_list(typ.items)]) -def try_getting_instance_fallback(typ: ProperType) -> Optional[Instance]: - """Returns the Instance fallback for this type if one exists. - - Otherwise, returns None. - """ - if isinstance(typ, Instance): - return typ - elif isinstance(typ, TupleType): - return tuple_fallback(typ) - elif isinstance(typ, TypedDictType): - return typ.fallback - elif isinstance(typ, FunctionLike): - return typ.fallback - elif isinstance(typ, LiteralType): - return typ.fallback - else: - return None - - def type_object_type_from_function(signature: FunctionLike, info: TypeInfo, def_info: TypeInfo, diff --git a/mypy/types.py b/mypy/types.py index 8583f17a30ddc..15ae47e341d40 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -903,6 +903,31 @@ class Instance(ProperType): """An instance type of form C[T1, ..., Tn]. The list of type variables may be empty. + + Several types has fallbacks to `Instance`. Why? + Because, for example `TupleTuple` is related to `builtins.tuple` instance. + And `FunctionLike` has `builtins.function` fallback. + This allows us to use types defined + in typeshed for our "special" and more precise types. + + We used to have this helper function to get a fallback from different types. + Note, that it might be incomplete, since it is not used and not updated. + It just illustrates the concept: + + def try_getting_instance_fallback(typ: ProperType) -> Optional[Instance]: + '''Returns the Instance fallback for this type if one exists or None.''' + if isinstance(typ, Instance): + return typ + elif isinstance(typ, TupleType): + return tuple_fallback(typ) + elif isinstance(typ, TypedDictType): + return typ.fallback + elif isinstance(typ, FunctionLike): + return typ.fallback + elif isinstance(typ, LiteralType): + return typ.fallback + return None + """ __slots__ = ('type', 'args', 'erased', 'invalid', 'type_ref', 'last_known_value') @@ -1033,10 +1058,11 @@ class FunctionLike(ProperType): __slots__ = ('fallback',) + fallback: Instance + def __init__(self, line: int = -1, column: int = -1) -> None: super().__init__(line, column) self.can_be_false = False - self.fallback: Instance @abstractmethod def is_type_obj(self) -> bool: pass @@ -1639,7 +1665,7 @@ def copy_modified(self, *, fallback: Optional[Instance] = None, required_keys = self.required_keys return TypedDictType(items, required_keys, fallback, self.line, self.column) - def create_anonymous_fallback(self, *, value_type: Type) -> Instance: + def create_anonymous_fallback(self) -> Instance: anonymous = self.as_anonymous() return anonymous.fallback From 229913e8e31ee2889ad3e2a3f85ffe82b29fa198 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Fri, 31 Dec 2021 18:57:29 -0600 Subject: [PATCH 027/377] Avoid grep on Windows (#11879) Co-authored-by: hauntsaninja <> --- misc/build_wheel.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/misc/build_wheel.py b/misc/build_wheel.py index b124a11d8c950..188660e2eefc3 100644 --- a/misc/build_wheel.py +++ b/misc/build_wheel.py @@ -83,6 +83,8 @@ def create_environ(python_version: str) -> Dict[str, str]: && pip install -r /tmp/test-requirements.txt ) """.replace('\n', ' ') + # lxml currently has wheels on Windows and doesn't have grep, so special case + env['CIBW_BEFORE_TEST_WINDOWS'] = "pip install -r {project}/mypy/test-requirements.txt" # pytest looks for configuration files in the parent directories of where the tests live. # since we are trying to run the tests from their installed location, we copy those into From 6330a41bc396b0137576e0826be3c03343600c4a Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Sat, 1 Jan 2022 20:59:30 +0300 Subject: [PATCH 028/377] Add `.editorconfig` file (#11883) --- .editorconfig | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000000..461d93d21a34b --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*.{py,c,cpp,h,rst,md,yml,json}] +trim_trailing_whitespace = true +insert_final_newline = true +indent_style = space + +[*.{py,c,h,json}] +indent_size = 4 + +[*.yml] +indent_size = 2 From b0c44617426acaaba759b9ad9d3c03d9a237d2af Mon Sep 17 00:00:00 2001 From: James Braza Date: Sun, 2 Jan 2022 02:05:46 -0500 Subject: [PATCH 029/377] Add reports extra to setup.py (#11777) --- docs/source/command_line.rst | 16 ++++++++++++---- docs/source/config_file.rst | 16 ++++++++++++---- setup.py | 6 +++++- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/docs/source/command_line.rst b/docs/source/command_line.rst index 02218e0fbcbde..fb30245794f7e 100644 --- a/docs/source/command_line.rst +++ b/docs/source/command_line.rst @@ -853,13 +853,17 @@ format into the specified directory. Causes mypy to generate a Cobertura XML type checking coverage report. - You must install the `lxml`_ library to generate this report. + To generate this report, you must either manually install the `lxml`_ + library or specify mypy installation with the setuptools extra + ``mypy[reports]``. .. option:: --html-report / --xslt-html-report DIR Causes mypy to generate an HTML type checking coverage report. - You must install the `lxml`_ library to generate this report. + To generate this report, you must either manually install the `lxml`_ + library or specify mypy installation with the setuptools extra + ``mypy[reports]``. .. option:: --linecount-report DIR @@ -881,13 +885,17 @@ format into the specified directory. Causes mypy to generate a text file type checking coverage report. - You must install the `lxml`_ library to generate this report. + To generate this report, you must either manually install the `lxml`_ + library or specify mypy installation with the setuptools extra + ``mypy[reports]``. .. option:: --xml-report DIR Causes mypy to generate an XML type checking coverage report. - You must install the `lxml`_ library to generate this report. + To generate this report, you must either manually install the `lxml`_ + library or specify mypy installation with the setuptools extra + ``mypy[reports]``. Miscellaneous ************* diff --git a/docs/source/config_file.rst b/docs/source/config_file.rst index c34f23d9e169a..11d3a31d13e30 100644 --- a/docs/source/config_file.rst +++ b/docs/source/config_file.rst @@ -820,7 +820,9 @@ format into the specified directory. Causes mypy to generate a Cobertura XML type checking coverage report. - You must install the `lxml`_ library to generate this report. + To generate this report, you must either manually install the `lxml`_ + library or specify mypy installation with the setuptools extra + ``mypy[reports]``. .. confval:: html_report / xslt_html_report @@ -828,7 +830,9 @@ format into the specified directory. Causes mypy to generate an HTML type checking coverage report. - You must install the `lxml`_ library to generate this report. + To generate this report, you must either manually install the `lxml`_ + library or specify mypy installation with the setuptools extra + ``mypy[reports]``. .. confval:: linecount_report @@ -858,7 +862,9 @@ format into the specified directory. Causes mypy to generate a text file type checking coverage report. - You must install the `lxml`_ library to generate this report. + To generate this report, you must either manually install the `lxml`_ + library or specify mypy installation with the setuptools extra + ``mypy[reports]``. .. confval:: xml_report @@ -866,7 +872,9 @@ format into the specified directory. Causes mypy to generate an XML type checking coverage report. - You must install the `lxml`_ library to generate this report. + To generate this report, you must either manually install the `lxml`_ + library or specify mypy installation with the setuptools extra + ``mypy[reports]``. Miscellaneous diff --git a/setup.py b/setup.py index 344fcf94d0cfc..233ad30294c64 100644 --- a/setup.py +++ b/setup.py @@ -201,7 +201,11 @@ def run(self): 'tomli>=1.1.0', ], # Same here. - extras_require={'dmypy': 'psutil >= 4.0', 'python2': 'typed_ast >= 1.4.0, < 2'}, + extras_require={ + 'dmypy': 'psutil >= 4.0', + 'python2': 'typed_ast >= 1.4.0, < 2', + 'reports': 'lxml' + }, python_requires=">=3.6", include_package_data=True, project_urls={ From 2676cd804d0a72eb3fb9282879a8e426a851969b Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sun, 2 Jan 2022 22:03:32 -0600 Subject: [PATCH 030/377] Fix sdist build for editorconfig (#11889) editorconfig was added in #11883 and broke check-manifest in https://github.com/mypyc/mypy_mypyc-wheels/runs/4680413534?check_suite_focus=true Co-authored-by: hauntsaninja <> --- MANIFEST.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MANIFEST.in b/MANIFEST.in index fc657091a3dc7..fe10e22265a67 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -41,7 +41,7 @@ include runtests.py include pytest.ini include LICENSE mypyc/README.md -exclude .gitmodules CONTRIBUTING.md CREDITS ROADMAP.md tox.ini action.yml +exclude .gitmodules CONTRIBUTING.md CREDITS ROADMAP.md tox.ini action.yml .editorconfig global-exclude *.py[cod] global-exclude .DS_Store From 246c9ee7fe1990def9bf3435bf42ef9f201bc0ef Mon Sep 17 00:00:00 2001 From: Matt Bogosian Date: Tue, 4 Jan 2022 11:03:17 -0600 Subject: [PATCH 031/377] Preserves interpreting multi-line strings as a single value for `exclude` in TOML files (#11828) Multiple regexes are expressed as a sequence. Fixes #11825. Co-authored-by: Matthew W Co-authored-by: Shantanu <12621235+hauntsaninja@users.noreply.github.com> --- docs/source/config_file.rst | 35 +++++++++++++++++++++ mypy/config_parser.py | 7 +++++ test-data/unit/cmdline.pyproject.test | 45 +++++++++++++++++++++++++++ 3 files changed, 87 insertions(+) diff --git a/docs/source/config_file.rst b/docs/source/config_file.rst index 11d3a31d13e30..fcd9caede309a 100644 --- a/docs/source/config_file.rst +++ b/docs/source/config_file.rst @@ -214,6 +214,35 @@ section of the command line docs. This option may only be set in the global section (``[mypy]``). + .. note:: + + Note that the TOML equivalent differs slightly. It can be either a single string + (including a multi-line string) -- which is treated as a single regular + expression -- or an array of such strings. The following TOML examples are + equivalent to the above INI example. + + Array of strings: + + .. code-block:: toml + + [tool.mypy] + exclude = [ + "^file1\\.py$", # TOML's double-quoted strings require escaping backslashes + '^file2\.py$', # but TOML's single-quoted strings do not + ] + + A single, multi-line string: + + .. code-block:: toml + + [tool.mypy] + exclude = '''(?x)( + ^file1\.py$ + |^file2\.py$, + )''' + + See :ref:`using-a-pyproject-toml`. + .. confval:: namespace_packages :type: boolean @@ -915,6 +944,8 @@ These options may only be set in the global section (``[mypy]``). Controls how much debug output will be generated. Higher numbers are more verbose. +.. _using-a-pyproject-toml: + Using a pyproject.toml file *************************** @@ -973,6 +1004,10 @@ of your repo (or append it to the end of an existing ``pyproject.toml`` file) an python_version = "2.7" warn_return_any = true warn_unused_configs = true + exclude = [ + '^file1\.py$', # TOML literal string (single-quotes, no escaping necessary) + "^file2\\.py$", # TOML basic string (double-quotes, backslash and other characters need escaping) + ] # mypy per-module options: diff --git a/mypy/config_parser.py b/mypy/config_parser.py index 24e61df0441c0..4185179605c9c 100644 --- a/mypy/config_parser.py +++ b/mypy/config_parser.py @@ -57,6 +57,12 @@ def expand_path(path: str) -> str: return os.path.expandvars(os.path.expanduser(path)) +def str_or_array_as_list(v: Union[str, Sequence[str]]) -> List[str]: + if isinstance(v, str): + return [v.strip()] if v.strip() else [] + return [p.strip() for p in v if p.strip()] + + def split_and_match_files_list(paths: Sequence[str]) -> List[str]: """Take a list of files/directories (with support for globbing through the glob library). @@ -143,6 +149,7 @@ def check_follow_imports(choice: str) -> str: 'disable_error_code': try_split, 'enable_error_code': try_split, 'package_root': try_split, + 'exclude': str_or_array_as_list, }) diff --git a/test-data/unit/cmdline.pyproject.test b/test-data/unit/cmdline.pyproject.test index 83f4745d07867..ea561ed164e75 100644 --- a/test-data/unit/cmdline.pyproject.test +++ b/test-data/unit/cmdline.pyproject.test @@ -80,3 +80,48 @@ def g(a: int) -> int: [out] pyproject.toml: toml config file contains [[tool.mypy.overrides]] sections with conflicting values. Module 'x' has two different values for 'disallow_untyped_defs' == Return code: 0 + +[case testMultilineLiteralExcludePyprojectTOML] +# cmd: mypy x +[file pyproject.toml] +\[tool.mypy] +exclude = '''(?x)( + (^|/)[^/]*skipme_\.py$ + |(^|/)_skipme[^/]*\.py$ +)''' +[file x/__init__.py] +i: int = 0 +[file x/_skipme_please.py] +This isn't even syntatically valid! +[file x/please_skipme_.py] +Neither is this! + +[case testMultilineBasicExcludePyprojectTOML] +# cmd: mypy x +[file pyproject.toml] +\[tool.mypy] +exclude = """(?x)( + (^|/)[^/]*skipme_\\.py$ + |(^|/)_skipme[^/]*\\.py$ +)""" +[file x/__init__.py] +i: int = 0 +[file x/_skipme_please.py] +This isn't even syntatically valid! +[file x/please_skipme_.py] +Neither is this! + +[case testSequenceExcludePyprojectTOML] +# cmd: mypy x +[file pyproject.toml] +\[tool.mypy] +exclude = [ + '(^|/)[^/]*skipme_\.py$', # literal (no escaping) + "(^|/)_skipme[^/]*\\.py$", # basic (backslash needs escaping) +] +[file x/__init__.py] +i: int = 0 +[file x/_skipme_please.py] +This isn't even syntatically valid! +[file x/please_skipme_.py] +Neither is this! From ba0e9d6427fa15a2c3420d4427e88b99514d22f9 Mon Sep 17 00:00:00 2001 From: Matt Bogosian Date: Tue, 4 Jan 2022 11:08:06 -0600 Subject: [PATCH 032/377] Revert to treating exclude in .ini as single string (#11881) Partially reverts #11329 (with respect to `.ini` documentation). Modifies existing unit tests. Fixes #11830. Co-authored-by: Matthew W --- docs/source/config_file.rst | 20 +++++++++++++++----- mypy/config_parser.py | 2 +- test-data/unit/cmdline.test | 7 ++++--- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/docs/source/config_file.rst b/docs/source/config_file.rst index fcd9caede309a..26589e71e86b6 100644 --- a/docs/source/config_file.rst +++ b/docs/source/config_file.rst @@ -197,18 +197,28 @@ section of the command line docs. .. confval:: exclude - :type: newline separated list of regular expressions + :type: regular expression - A newline list of regular expression that matches file names, directory names and paths + A regular expression that matches file names, directory names and paths which mypy should ignore while recursively discovering files to check. Use forward slashes on all platforms. .. code-block:: ini [mypy] - exclude = - ^file1\.py$ - ^file2\.py$ + exclude = (?x)( + ^one\.py$ # files named "one.py" + | two\.pyi$ # or files ending with "two.pyi" + | ^three\. # or files starting with "three." + ) + + Crafting a single regular expression that excludes multiple files while remaining + human-readable can be a challenge. The above example demonstrates one approach. + ``(?x)`` enables the ``VERBOSE`` flag for the subsequent regular expression, which + `ignores most whitespace and supports comments`__. The above is equivalent to: + ``(^one\.py$|two\.pyi$|^three\.)``. + + .. __: https://docs.python.org/3/library/re.html#re.X For more details, see :option:`--exclude `. diff --git a/mypy/config_parser.py b/mypy/config_parser.py index 4185179605c9c..fa57caee14a4c 100644 --- a/mypy/config_parser.py +++ b/mypy/config_parser.py @@ -132,7 +132,7 @@ def check_follow_imports(choice: str) -> str: 'cache_dir': expand_path, 'python_executable': expand_path, 'strict': bool, - 'exclude': lambda s: [p.strip() for p in s.split('\n') if p.strip()], + 'exclude': lambda s: [s.strip()], } # Reuse the ini_config_types and overwrite the diff diff --git a/test-data/unit/cmdline.test b/test-data/unit/cmdline.test index 6fa4d210a8260..690b0cc067098 100644 --- a/test-data/unit/cmdline.test +++ b/test-data/unit/cmdline.test @@ -1354,9 +1354,10 @@ b/bpkg.py:1: error: "int" not callable # cmd: mypy . [file mypy.ini] \[mypy] -exclude = - abc - b +exclude = (?x)( + ^abc/ + |^b/ + ) [file abc/apkg.py] 1() [file b/bpkg.py] From 9c05d3d19de74fc10a51aa5b663e6a38bc6abc73 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Wed, 5 Jan 2022 01:44:28 -0600 Subject: [PATCH 033/377] (minor) Short circuit call to `can_be_type_alias` when using PEP 613 (#11904) When debugging #11887 I realised `can_be_type_alias` can do non-trivial amounts of work. It's unlikely to ever show up on a profile, but reordering the check means we do less work. Changed the order of some other checks for consistency. Co-authored-by: hauntsaninja <> --- mypy/semanal.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 29dfc96c24229..933ba54c358f6 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -2666,7 +2666,7 @@ def check_and_set_up_type_alias(self, s: AssignmentStmt) -> bool: lookup = self.lookup(s.unanalyzed_type.name, s, suppress_errors=True) if lookup and lookup.fullname in ("typing.TypeAlias", "typing_extensions.TypeAlias"): pep_613 = True - if s.unanalyzed_type is not None and not pep_613: + if not pep_613 and s.unanalyzed_type is not None: # Second rule: Explicit type (cls: Type[A] = A) always creates variable, not alias. # unless using PEP 613 `cls: TypeAlias = A` return False @@ -2693,7 +2693,7 @@ def check_and_set_up_type_alias(self, s: AssignmentStmt) -> bool: return False non_global_scope = self.type or self.is_func_scope() - if isinstance(s.rvalue, RefExpr) and non_global_scope and not pep_613: + if not pep_613 and isinstance(s.rvalue, RefExpr) and non_global_scope: # Fourth rule (special case): Non-subscripted right hand side creates a variable # at class and function scopes. For example: # @@ -2706,7 +2706,7 @@ def check_and_set_up_type_alias(self, s: AssignmentStmt) -> bool: # annotations (see the second rule). return False rvalue = s.rvalue - if not self.can_be_type_alias(rvalue) and not pep_613: + if not pep_613 and not self.can_be_type_alias(rvalue): return False if existing and not isinstance(existing.node, (PlaceholderNode, TypeAlias)): From 06afa7cca3b04cc32e5684f0344a6138c7dfa918 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Wed, 5 Jan 2022 11:47:12 -0500 Subject: [PATCH 034/377] Fix regression when a contextmanager yields a generic (#11870) Resolves #11852 --- mypy/plugins/default.py | 5 +- test-data/unit/check-default-plugin.test | 73 ++++++++++-------------- 2 files changed, 33 insertions(+), 45 deletions(-) diff --git a/mypy/plugins/default.py b/mypy/plugins/default.py index 67587090e0ba2..c57c5f9a18d9b 100644 --- a/mypy/plugins/default.py +++ b/mypy/plugins/default.py @@ -15,7 +15,6 @@ from mypy.subtypes import is_subtype from mypy.typeops import make_simplified_union from mypy.checkexpr import is_literal_type_like -from mypy.checker import detach_callable class DefaultPlugin(Plugin): @@ -192,12 +191,12 @@ def contextmanager_callback(ctx: FunctionContext) -> Type: and isinstance(default_return, CallableType)): # The stub signature doesn't preserve information about arguments so # add them back here. - return detach_callable(default_return.copy_modified( + return default_return.copy_modified( arg_types=arg_type.arg_types, arg_kinds=arg_type.arg_kinds, arg_names=arg_type.arg_names, variables=arg_type.variables, - is_ellipsis_args=arg_type.is_ellipsis_args)) + is_ellipsis_args=arg_type.is_ellipsis_args) return ctx.default_return_type diff --git a/test-data/unit/check-default-plugin.test b/test-data/unit/check-default-plugin.test index fc9f132abb62f..aef6d6a71497b 100644 --- a/test-data/unit/check-default-plugin.test +++ b/test-data/unit/check-default-plugin.test @@ -24,56 +24,15 @@ f = g # E: Incompatible types in assignment (expression has type "Callable[[Any, [typing fixtures/typing-medium.pyi] [builtins fixtures/tuple.pyi] -[case testContextManagerWithGenericFunctionAndSendType] -from contextlib import contextmanager -from typing import TypeVar, Generator - -T = TypeVar('T') -S = TypeVar('S') - -@contextmanager -def yield_id(item: T) -> Generator[T, S, None]: - yield item - -reveal_type(yield_id) # N: Revealed type is "def [T] (item: T`-1) -> contextlib.GeneratorContextManager[T`-1]" - -with yield_id(1) as x: - reveal_type(x) # N: Revealed type is "builtins.int*" - -f = yield_id -def g(x, y): pass -f = g # E: Incompatible types in assignment (expression has type "Callable[[Any, Any], Any]", variable has type "Callable[[T], GeneratorContextManager[T]]") -[typing fixtures/typing-medium.pyi] -[builtins fixtures/tuple.pyi] - [case testAsyncContextManagerWithGenericFunction] # flags: --python-version 3.7 from contextlib import asynccontextmanager -from typing import TypeVar, AsyncIterator - -T = TypeVar('T') - -@asynccontextmanager -async def yield_id(item: T) -> AsyncIterator[T]: - yield item - -reveal_type(yield_id) # N: Revealed type is "def [T] (item: T`-1) -> typing.AsyncContextManager[T`-1]" - -async with yield_id(1) as x: - reveal_type(x) # N: Revealed type is "builtins.int*" -[typing fixtures/typing-async.pyi] -[builtins fixtures/tuple.pyi] - -[case testAsyncContextManagerWithGenericFunctionAndSendType] -# flags: --python-version 3.7 -from contextlib import asynccontextmanager from typing import TypeVar, AsyncGenerator T = TypeVar('T') -S = TypeVar('S') @asynccontextmanager -async def yield_id(item: T) -> AsyncGenerator[T, S]: +async def yield_id(item: T) -> AsyncGenerator[T, None]: yield item reveal_type(yield_id) # N: Revealed type is "def [T] (item: T`-1) -> typing.AsyncContextManager[T`-1]" @@ -83,6 +42,36 @@ async with yield_id(1) as x: [typing fixtures/typing-async.pyi] [builtins fixtures/tuple.pyi] +[case testContextManagerReturnsGenericFunction] +import contextlib +from typing import Callable +from typing import Generator +from typing import Iterable +from typing import TypeVar + +TArg = TypeVar('TArg') +TRet = TypeVar('TRet') + +@contextlib.contextmanager +def _thread_mapper(maxsize: int) -> Generator[ + Callable[[Callable[[TArg], TRet], Iterable[TArg]], Iterable[TRet]], + None, None, +]: + # defined inline as there isn't a builtins.map fixture + def my_map(f: Callable[[TArg], TRet], it: Iterable[TArg]) -> Iterable[TRet]: + for x in it: + yield f(x) + + yield my_map + +def identity(x: int) -> int: return x + +with _thread_mapper(1) as m: + lst = list(m(identity, [2, 3])) + reveal_type(lst) # N: Revealed type is "builtins.list[builtins.int*]" +[typing fixtures/typing-medium.pyi] +[builtins fixtures/list.pyi] + [case testContextManagerWithUnspecifiedArguments] from contextlib import contextmanager from typing import Callable, Iterator From 27d2c2212547f137ade8b2098902a8c80ca82f78 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Wed, 5 Jan 2022 10:58:17 -0600 Subject: [PATCH 035/377] [0.931 backport] Fix __reduce__ regression (#11866) Co-authored-by: hauntsaninja <> --- mypy/typeshed/stdlib/builtins.pyi | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/mypy/typeshed/stdlib/builtins.pyi b/mypy/typeshed/stdlib/builtins.pyi index 71efda9b979a1..1b2d3db12c3f9 100644 --- a/mypy/typeshed/stdlib/builtins.pyi +++ b/mypy/typeshed/stdlib/builtins.pyi @@ -100,11 +100,13 @@ class object: def __getattribute__(self, __name: str) -> Any: ... def __delattr__(self, __name: str) -> None: ... def __sizeof__(self) -> int: ... - def __reduce__(self) -> str | Tuple[object, ...]: ... + # return type of pickle methods is rather hard to express in the current type system + # see #6661 and https://docs.python.org/3/library/pickle.html#object.__reduce__ + def __reduce__(self) -> str | Tuple[Any, ...]: ... if sys.version_info >= (3, 8): - def __reduce_ex__(self, __protocol: SupportsIndex) -> str | Tuple[object, ...]: ... + def __reduce_ex__(self, __protocol: SupportsIndex) -> str | Tuple[Any, ...]: ... else: - def __reduce_ex__(self, __protocol: int) -> str | Tuple[object, ...]: ... + def __reduce_ex__(self, __protocol: int) -> str | Tuple[Any, ...]: ... def __dir__(self) -> Iterable[str]: ... def __init_subclass__(cls) -> None: ... From edbc2484d0e6183dc34d2f5d0578b06d773e02e5 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Wed, 5 Jan 2022 23:57:12 +0300 Subject: [PATCH 036/377] Update pythoneval-asyncio.test (#11908) --- test-data/unit/pythoneval-asyncio.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-data/unit/pythoneval-asyncio.test b/test-data/unit/pythoneval-asyncio.test index ffa40a8da68fb..b3400fe6010e7 100644 --- a/test-data/unit/pythoneval-asyncio.test +++ b/test-data/unit/pythoneval-asyncio.test @@ -346,7 +346,7 @@ from typing import Generator, Any import asyncio from asyncio import Future -asyncio.coroutine +@asyncio.coroutine def slow_operation(future: 'Future[int]') -> 'Generator[Any, None, None]': yield from asyncio.sleep(1) future.set_result('42') #Try to set an str as result to a Future[int] From 37886c74fe8b0a40e6427361f3dcb3a9d0d82751 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Thu, 6 Jan 2022 10:59:50 +0300 Subject: [PATCH 037/377] Always allow use of `type[T]` in stubs (#11863) --- mypy/semanal.py | 4 +--- mypy/typeanal.py | 32 ++++++++++++------------- test-data/unit/check-generic-alias.test | 3 +++ 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 933ba54c358f6..b4e0ecb524c0d 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -2631,7 +2631,6 @@ def analyze_alias(self, rvalue: Expression, self.plugin, self.options, self.is_typeshed_stub_file, - allow_new_syntax=self.is_stub_file, allow_placeholder=allow_placeholder, in_dynamic_func=dynamic, global_scope=global_scope) @@ -5169,8 +5168,7 @@ def type_analyzer(self, *, allow_tuple_literal=allow_tuple_literal, report_invalid_types=report_invalid_types, allow_placeholder=allow_placeholder, - allow_required=allow_required, - allow_new_syntax=self.is_stub_file) + allow_required=allow_required) tpan.in_dynamic_func = bool(self.function_stack and self.function_stack[-1].is_dynamic()) tpan.global_scope = not self.type and not self.function_stack return tpan diff --git a/mypy/typeanal.py b/mypy/typeanal.py index 8b399bc2c70fe..0646240a23f96 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -70,7 +70,6 @@ def analyze_type_alias(node: Expression, plugin: Plugin, options: Options, is_typeshed_stub: bool, - allow_new_syntax: bool = False, allow_placeholder: bool = False, in_dynamic_func: bool = False, global_scope: bool = True) -> Optional[Tuple[Type, Set[str]]]: @@ -81,12 +80,12 @@ def analyze_type_alias(node: Expression, Return None otherwise. 'node' must have been semantically analyzed. """ try: - type = expr_to_unanalyzed_type(node, options, allow_new_syntax) + type = expr_to_unanalyzed_type(node, options, api.is_stub_file) except TypeTranslationError: api.fail('Invalid type alias: expression is not a valid type', node) return None analyzer = TypeAnalyser(api, tvar_scope, plugin, options, is_typeshed_stub, - allow_new_syntax=allow_new_syntax, defining_alias=True, + defining_alias=True, allow_placeholder=allow_placeholder) analyzer.in_dynamic_func = in_dynamic_func analyzer.global_scope = global_scope @@ -127,7 +126,6 @@ def __init__(self, is_typeshed_stub: bool, *, defining_alias: bool = False, allow_tuple_literal: bool = False, - allow_new_syntax: bool = False, allow_unbound_tvars: bool = False, allow_placeholder: bool = False, allow_required: bool = False, @@ -144,8 +142,11 @@ def __init__(self, # Positive if we are analyzing arguments of another (outer) type self.nesting_level = 0 # Should we allow new type syntax when targeting older Python versions - # like 'list[int]' or 'X | Y' (allowed in stubs)? - self.allow_new_syntax = allow_new_syntax + # like 'list[int]' or 'X | Y' (allowed in stubs and with `__future__` import)? + self.always_allow_new_syntax = ( + self.api.is_stub_file + or self.api.is_future_flag_set('annotations') + ) # Should we accept unbound type variables (always OK in aliases)? self.allow_unbound_tvars = allow_unbound_tvars or defining_alias # If false, record incomplete ref if we generate PlaceholderType. @@ -202,9 +203,8 @@ def visit_unbound_type_nonoptional(self, t: UnboundType, defining_literal: bool) if hook is not None: return hook(AnalyzeTypeContext(t, t, self)) if (fullname in get_nongen_builtins(self.options.python_version) - and t.args and - not self.allow_new_syntax and - not self.api.is_future_flag_set("annotations")): + and t.args + and not self.always_allow_new_syntax): self.fail(no_subscript_builtin_alias(fullname, propose_alt=not self.defining_alias), t) tvar_def = self.tvar_scope.get_binding(sym) @@ -291,9 +291,8 @@ def try_analyze_special_unbound_type(self, t: UnboundType, fullname: str) -> Opt " in a variable annotation", t) return AnyType(TypeOfAny.from_error) elif (fullname == 'typing.Tuple' or - (fullname == 'builtins.tuple' and (self.options.python_version >= (3, 9) or - self.api.is_future_flag_set('annotations') or - self.allow_new_syntax))): + (fullname == 'builtins.tuple' + and (self.always_allow_new_syntax or self.options.python_version >= (3, 9)))): # Tuple is special because it is involved in builtin import cycle # and may be not ready when used. sym = self.api.lookup_fully_qualified_or_none('builtins.tuple') @@ -326,8 +325,8 @@ def try_analyze_special_unbound_type(self, t: UnboundType, fullname: str) -> Opt elif fullname == 'typing.Callable': return self.analyze_callable_type(t) elif (fullname == 'typing.Type' or - (fullname == 'builtins.type' and (self.options.python_version >= (3, 9) or - self.api.is_future_flag_set('annotations')))): + (fullname == 'builtins.type' + and (self.always_allow_new_syntax or self.options.python_version >= (3, 9)))): if len(t.args) == 0: if fullname == 'typing.Type': any_type = self.get_omitted_any(t) @@ -704,9 +703,8 @@ def visit_star_type(self, t: StarType) -> Type: def visit_union_type(self, t: UnionType) -> Type: if (t.uses_pep604_syntax is True and t.is_evaluated is True - and self.api.is_stub_file is False - and self.options.python_version < (3, 10) - and self.api.is_future_flag_set('annotations') is False): + and not self.always_allow_new_syntax + and not self.options.python_version >= (3, 10)): self.fail("X | Y syntax for unions requires Python 3.10", t) return UnionType(self.anal_array(t.items), t.line) diff --git a/test-data/unit/check-generic-alias.test b/test-data/unit/check-generic-alias.test index 7000a145e4d16..a4c79c9c6f7f2 100644 --- a/test-data/unit/check-generic-alias.test +++ b/test-data/unit/check-generic-alias.test @@ -273,6 +273,8 @@ b: B import m reveal_type(m.a) # N: Revealed type is "builtins.list[builtins.int]" reveal_type(m.b) # N: Revealed type is "builtins.list[builtins.list[builtins.int]]" +m.C # has complex representation, ignored +reveal_type(m.d) # N: Revealed type is "Type[builtins.str]" [file m.pyi] A = list[int] @@ -281,4 +283,5 @@ B = list[list[int]] b: B class C(list[int]): pass +d: type[str] [builtins fixtures/list.pyi] From ce4211618809835a25330f95443a9c06766be197 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Thu, 6 Jan 2022 11:25:17 +0300 Subject: [PATCH 038/377] Handle `NoReturn` type aliases (#11912) --- mypy/semanal.py | 6 ++++++ test-data/unit/check-type-aliases.test | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/mypy/semanal.py b/mypy/semanal.py index b4e0ecb524c0d..853917a9aadfb 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -2247,6 +2247,12 @@ def is_type_ref(self, rv: Expression, bare: bool = False) -> bool: return True # Assignment color = Color['RED'] defines a variable, not an alias. return not rv.node.is_enum + if isinstance(rv.node, Var): + return rv.node.fullname in ( + 'typing.NoReturn', + 'typing_extensions.NoReturn', + 'mypy_extensions.NoReturn', + ) if isinstance(rv, NameExpr): n = self.lookup(rv.name, rv) diff --git a/test-data/unit/check-type-aliases.test b/test-data/unit/check-type-aliases.test index eb6c71e8f2268..cb023fc0ad3ff 100644 --- a/test-data/unit/check-type-aliases.test +++ b/test-data/unit/check-type-aliases.test @@ -50,6 +50,14 @@ def f(x: A) -> None: f(1) f('x') +[case testNoReturnTypeAlias] +# https://github.com/python/mypy/issues/11903 +from typing import NoReturn +Never = NoReturn +a: Never # Used to be an error here + +def f(a: Never): ... +f(5) # E: Argument 1 to "f" has incompatible type "int"; expected "NoReturn" [case testImportUnionAlias] import typing from _m import U From e0a89b75fbefc48bb82c924979a8e1c52d65818e Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Thu, 6 Jan 2022 01:44:10 -0800 Subject: [PATCH 039/377] Fix PEP 585 type aliases in stubs (#11918) Fixes #11859 Co-authored-by: hauntsaninja <> --- mypy/semanal.py | 1 + test-data/unit/check-generic-alias.test | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/mypy/semanal.py b/mypy/semanal.py index 853917a9aadfb..aca1f545c4727 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4091,6 +4091,7 @@ def analyze_type_application(self, expr: IndexExpr) -> None: name = target.type.fullname if (alias.no_args and # this avoids bogus errors for already reported aliases name in get_nongen_builtins(self.options.python_version) and + not self.is_stub_file and not alias.normalized): self.fail(no_subscript_builtin_alias(name, propose_alt=False), expr) # ...or directly. diff --git a/test-data/unit/check-generic-alias.test b/test-data/unit/check-generic-alias.test index a4c79c9c6f7f2..73efbd223c6c7 100644 --- a/test-data/unit/check-generic-alias.test +++ b/test-data/unit/check-generic-alias.test @@ -285,3 +285,14 @@ class C(list[int]): pass d: type[str] [builtins fixtures/list.pyi] + + +[case testTypeAliasWithBuiltinListAliasInStub] +# flags: --python-version 3.6 +import m +reveal_type(m.a()[0]) # N: Revealed type is "builtins.int*" + +[file m.pyi] +List = list +a = List[int] +[builtins fixtures/list.pyi] From e8cf960e8579e5cee2db27212efad4870e5106bd Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Thu, 6 Jan 2022 20:24:34 +0300 Subject: [PATCH 040/377] Stricter None handling with --no-strict-optional (#11717) Closes #11705 --- mypy/checker.py | 13 ++++++------- mypy/typeops.py | 5 ++++- test-data/unit/check-inference.test | 30 +++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 95af9e5f01e99..51aa7a3942fff 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -4550,17 +4550,16 @@ def has_no_custom_eq_checks(t: Type) -> bool: self._check_for_truthy_type(original_vartype, node) vartype = try_expanding_sum_type_to_union(original_vartype, "builtins.bool") - if_type = true_only(vartype) # type: Type - else_type = false_only(vartype) # type: Type - ref = node # type: Expression + if_type = true_only(vartype) + else_type = false_only(vartype) if_map = ( - {ref: if_type} - if not isinstance(get_proper_type(if_type), UninhabitedType) + {node: if_type} + if not isinstance(if_type, UninhabitedType) else None ) else_map = ( - {ref: else_type} - if not isinstance(get_proper_type(else_type), UninhabitedType) + {node: else_type} + if not isinstance(else_type, UninhabitedType) else None ) return if_map, else_map diff --git a/mypy/typeops.py b/mypy/typeops.py index f1d9f2daed553..677b8c7f4decf 100644 --- a/mypy/typeops.py +++ b/mypy/typeops.py @@ -704,7 +704,10 @@ class Status(Enum): typ = get_proper_type(typ) if isinstance(typ, UnionType): - items = [try_expanding_sum_type_to_union(item, target_fullname) for item in typ.items] + items = [ + try_expanding_sum_type_to_union(item, target_fullname) + for item in typ.relevant_items() + ] return make_simplified_union(items, contract_literals=False) elif isinstance(typ, Instance) and typ.type.fullname == target_fullname: if typ.type.is_enum: diff --git a/test-data/unit/check-inference.test b/test-data/unit/check-inference.test index adf4a7b604205..9f9d48b74d5c6 100644 --- a/test-data/unit/check-inference.test +++ b/test-data/unit/check-inference.test @@ -3210,3 +3210,33 @@ def test(seq: List[Union[Iterable, Any]]) -> None: k = [k] reveal_type(k) # N: Revealed type is "builtins.list[Any]" [builtins fixtures/list.pyi] + +[case testRegression11705_Strict] +# flags: --strict-optional +# See: https://github.com/python/mypy/issues/11705 +from typing import Dict, Optional, NamedTuple +class C(NamedTuple): + x: int + +t: Optional[C] +d: Dict[C, bytes] +x = t and d[t] +reveal_type(x) # N: Revealed type is "Union[None, builtins.bytes*]" +if x: + reveal_type(x) # N: Revealed type is "builtins.bytes*" +[builtins fixtures/dict.pyi] + +[case testRegression11705_NoStrict] +# flags: --no-strict-optional +# See: https://github.com/python/mypy/issues/11705 +from typing import Dict, Optional, NamedTuple +class C(NamedTuple): + x: int + +t: Optional[C] +d: Dict[C, bytes] +x = t and d[t] +reveal_type(x) # N: Revealed type is "builtins.bytes*" +if x: + reveal_type(x) # N: Revealed type is "builtins.bytes*" +[builtins fixtures/dict.pyi] From 55bee20f5c73b4a3868f2c350c608cd4ea67bd05 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Fri, 7 Jan 2022 13:10:49 +0300 Subject: [PATCH 041/377] Make `disable_type_names` a context manager (#11716) --- mypy/checkexpr.py | 28 ++++++++++++++++++---------- mypy/checkmember.py | 13 ++++++------- mypy/messages.py | 20 ++++++++++++++------ 3 files changed, 38 insertions(+), 23 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index dfac5be27d955..b1ffbf7a87be1 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -2064,11 +2064,19 @@ def check_union_call(self, arg_names: Optional[Sequence[Optional[str]]], context: Context, arg_messages: MessageBuilder) -> Tuple[Type, Type]: - self.msg.disable_type_names += 1 - results = [self.check_call(subtype, args, arg_kinds, context, arg_names, - arg_messages=arg_messages) - for subtype in callee.relevant_items()] - self.msg.disable_type_names -= 1 + with self.msg.disable_type_names(): + results = [ + self.check_call( + subtype, + args, + arg_kinds, + context, + arg_names, + arg_messages=arg_messages, + ) + for subtype in callee.relevant_items() + ] + return (make_simplified_union([res[0] for res in results]), callee) @@ -2462,11 +2470,11 @@ def check_union_method_call_by_name(self, for typ in base_type.relevant_items(): # Format error messages consistently with # mypy.checkmember.analyze_union_member_access(). - local_errors.disable_type_names += 1 - item, meth_item = self.check_method_call_by_name(method, typ, args, arg_kinds, - context, local_errors, - original_type) - local_errors.disable_type_names -= 1 + with local_errors.disable_type_names(): + item, meth_item = self.check_method_call_by_name( + method, typ, args, arg_kinds, + context, local_errors, original_type, + ) res.append(item) meth_res.append(meth_item) return make_simplified_union(res), make_simplified_union(meth_res) diff --git a/mypy/checkmember.py b/mypy/checkmember.py index c01f52de5a778..1c66320bb562f 100644 --- a/mypy/checkmember.py +++ b/mypy/checkmember.py @@ -311,13 +311,12 @@ def analyze_type_type_member_access(name: str, def analyze_union_member_access(name: str, typ: UnionType, mx: MemberContext) -> Type: - mx.msg.disable_type_names += 1 - results = [] - for subtype in typ.relevant_items(): - # Self types should be bound to every individual item of a union. - item_mx = mx.copy_modified(self_type=subtype) - results.append(_analyze_member_access(name, subtype, item_mx)) - mx.msg.disable_type_names -= 1 + with mx.msg.disable_type_names(): + results = [] + for subtype in typ.relevant_items(): + # Self types should be bound to every individual item of a union. + item_mx = mx.copy_modified(self_type=subtype) + results.append(_analyze_member_access(name, subtype, item_mx)) return make_simplified_union(results) diff --git a/mypy/messages.py b/mypy/messages.py index 1e89585000ea1..cbe389a597e51 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -107,13 +107,13 @@ class MessageBuilder: disable_count = 0 # Hack to deduplicate error messages from union types - disable_type_names = 0 + disable_type_names_count = 0 def __init__(self, errors: Errors, modules: Dict[str, MypyFile]) -> None: self.errors = errors self.modules = modules self.disable_count = 0 - self.disable_type_names = 0 + self.disable_type_names_count = 0 # # Helpers @@ -122,7 +122,7 @@ def __init__(self, errors: Errors, modules: Dict[str, MypyFile]) -> None: def copy(self) -> 'MessageBuilder': new = MessageBuilder(self.errors.copy(), self.modules) new.disable_count = self.disable_count - new.disable_type_names = self.disable_type_names + new.disable_type_names_count = self.disable_type_names_count return new def clean_copy(self) -> 'MessageBuilder': @@ -145,6 +145,14 @@ def disable_errors(self) -> Iterator[None]: finally: self.disable_count -= 1 + @contextmanager + def disable_type_names(self) -> Iterator[None]: + self.disable_type_names_count += 1 + try: + yield + finally: + self.disable_type_names_count -= 1 + def is_errors(self) -> bool: return self.errors.is_errors() @@ -298,7 +306,7 @@ def has_no_attr(self, extra = ' (not iterable)' elif member == '__aiter__': extra = ' (not async iterable)' - if not self.disable_type_names: + if not self.disable_type_names_count: failed = False if isinstance(original_type, Instance) and original_type.type.names: alternatives = set(original_type.type.names.keys()) @@ -380,7 +388,7 @@ def unsupported_operand_types(self, else: right_str = format_type(right_type) - if self.disable_type_names: + if self.disable_type_names_count: msg = 'Unsupported operand types for {} (likely involving Union)'.format(op) else: msg = 'Unsupported operand types for {} ({} and {})'.format( @@ -389,7 +397,7 @@ def unsupported_operand_types(self, def unsupported_left_operand(self, op: str, typ: Type, context: Context) -> None: - if self.disable_type_names: + if self.disable_type_names_count: msg = 'Unsupported left operand type for {} (some union)'.format(op) else: msg = 'Unsupported left operand type for {} ({})'.format( From a0f27b1d1f21bc6c7502374c3a1e2b642758a4bb Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Fri, 7 Jan 2022 13:32:43 +0300 Subject: [PATCH 042/377] Fix crash on `ErasedType` and `covers_at_runtime` (#11924) Closes #11913 Refs #11273 Co-authored-by: Shantanu <12621235+hauntsaninja@users.noreply.github.com> --- mypy/erasetype.py | 3 +-- mypy/subtypes.py | 1 + test-data/unit/check-inference.test | 15 +++++++++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/mypy/erasetype.py b/mypy/erasetype.py index 8acebbd783d86..3301325eb0a18 100644 --- a/mypy/erasetype.py +++ b/mypy/erasetype.py @@ -41,8 +41,7 @@ def visit_uninhabited_type(self, t: UninhabitedType) -> ProperType: return t def visit_erased_type(self, t: ErasedType) -> ProperType: - # Should not get here. - raise RuntimeError() + return t def visit_partial_type(self, t: PartialType) -> ProperType: # Should not get here. diff --git a/mypy/subtypes.py b/mypy/subtypes.py index cb7f53f0d7cbb..2001060001325 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -1167,6 +1167,7 @@ def restrict_subtype_away(t: Type, s: Type, *, ignore_promotions: bool = False) def covers_at_runtime(item: Type, supertype: Type, ignore_promotions: bool) -> bool: """Will isinstance(item, supertype) always return True at runtime?""" item = get_proper_type(item) + supertype = get_proper_type(supertype) # Since runtime type checks will ignore type arguments, erase the types. supertype = erase_type(supertype) diff --git a/test-data/unit/check-inference.test b/test-data/unit/check-inference.test index 9f9d48b74d5c6..4de6e4a76f925 100644 --- a/test-data/unit/check-inference.test +++ b/test-data/unit/check-inference.test @@ -3211,6 +3211,21 @@ def test(seq: List[Union[Iterable, Any]]) -> None: reveal_type(k) # N: Revealed type is "builtins.list[Any]" [builtins fixtures/list.pyi] +[case testErasedTypeRuntimeCoverage] +# https://github.com/python/mypy/issues/11913 +from typing import TypeVar, Type, Generic, Callable, Iterable + +class DataType: ... + +T1 = TypeVar('T1') +T2 = TypeVar("T2", bound=DataType) + +def map(__func: T1) -> None: ... + +def collection_from_dict_value(model: Type[T2]) -> None: + map(lambda i: i if isinstance(i, model) else i) +[builtins fixtures/isinstancelist.pyi] + [case testRegression11705_Strict] # flags: --strict-optional # See: https://github.com/python/mypy/issues/11705 From e40877d4306787acb15985888e1f33ad4bdd9912 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Fri, 7 Jan 2022 14:07:11 +0300 Subject: [PATCH 043/377] stubtest: fix literal type construction (#11931) Co-authored-by: hauntsaninja <> --- mypy/fastparse.py | 15 +------- mypy/fastparse2.py | 3 +- mypy/stubtest.py | 23 +++++++----- mypy/test/teststubtest.py | 78 +++++++++++++++++++++++++++++++++++++++ mypy/util.py | 14 +++++++ 5 files changed, 108 insertions(+), 25 deletions(-) diff --git a/mypy/fastparse.py b/mypy/fastparse.py index 34fe2c0da32d3..f3dd1f0a8fefb 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -40,6 +40,7 @@ from mypy.errors import Errors from mypy.options import Options from mypy.reachability import mark_block_unreachable +from mypy.util import bytes_to_human_readable_repr try: # pull this into a final variable to make mypyc be quiet about the @@ -1638,17 +1639,3 @@ def stringify_name(n: AST) -> Optional[str]: if sv is not None: return "{}.{}".format(sv, n.attr) return None # Can't do it. - - -def bytes_to_human_readable_repr(b: bytes) -> str: - """Converts bytes into some human-readable representation. Unprintable - bytes such as the nul byte are escaped. For example: - - >>> b = bytes([102, 111, 111, 10, 0]) - >>> s = bytes_to_human_readable_repr(b) - >>> print(s) - foo\n\x00 - >>> print(repr(s)) - 'foo\\n\\x00' - """ - return repr(b)[2:-1] diff --git a/mypy/fastparse2.py b/mypy/fastparse2.py index 2d288bf158e5c..bf3c09453ec0a 100644 --- a/mypy/fastparse2.py +++ b/mypy/fastparse2.py @@ -47,10 +47,11 @@ from mypy import message_registry, errorcodes as codes from mypy.errors import Errors from mypy.fastparse import ( - TypeConverter, parse_type_comment, bytes_to_human_readable_repr, parse_type_ignore_tag, + TypeConverter, parse_type_comment, parse_type_ignore_tag, TYPE_IGNORE_PATTERN, INVALID_TYPE_IGNORE ) from mypy.options import Options +from mypy.util import bytes_to_human_readable_repr from mypy.reachability import mark_block_unreachable try: diff --git a/mypy/stubtest.py b/mypy/stubtest.py index 7228afaed446f..0a05cf2104099 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -25,7 +25,7 @@ from mypy import nodes from mypy.config_parser import parse_config_file from mypy.options import Options -from mypy.util import FancyFormatter +from mypy.util import FancyFormatter, bytes_to_human_readable_repr class Missing: @@ -942,6 +942,7 @@ def is_subtype_helper(left: mypy.types.Type, right: mypy.types.Type) -> bool: ): # Pretend Literal[0, 1] is a subtype of bool to avoid unhelpful errors. return True + with mypy.state.strict_optional_set(True): return mypy.subtypes.is_subtype(left, right) @@ -1029,17 +1030,19 @@ def anytype() -> mypy.types.AnyType: return mypy.types.TupleType(items, fallback) fallback = mypy.types.Instance(type_info, [anytype() for _ in type_info.type_vars]) - try: - # Literals are supposed to be only bool, int, str, bytes or enums, but this seems to work - # well (when not using mypyc, for which bytes and enums are also problematic). - return mypy.types.LiteralType( - value=runtime, - fallback=fallback, - ) - except TypeError: - # Ask for forgiveness if we're using mypyc. + + value: Union[bool, int, str] + if isinstance(runtime, bytes): + value = bytes_to_human_readable_repr(runtime) + elif isinstance(runtime, enum.Enum): + value = runtime.name + elif isinstance(runtime, (bool, int, str)): + value = runtime + else: return fallback + return mypy.types.LiteralType(value=value, fallback=fallback) + _all_stubs: Dict[str, nodes.MypyFile] = {} diff --git a/mypy/test/teststubtest.py b/mypy/test/teststubtest.py index e6eb8465c6658..6cc5560043376 100644 --- a/mypy/test/teststubtest.py +++ b/mypy/test/teststubtest.py @@ -750,6 +750,84 @@ def __init__(self, x): pass error="X.__init__" ) + @collect_cases + def test_good_literal(self) -> Iterator[Case]: + yield Case( + stub=r""" + from typing_extensions import Literal + + import enum + class Color(enum.Enum): + RED: int + + NUM: Literal[1] + CHAR: Literal['a'] + FLAG: Literal[True] + NON: Literal[None] + BYT1: Literal[b'abc'] + BYT2: Literal[b'\x90'] + ENUM: Literal[Color.RED] + """, + runtime=r""" + import enum + class Color(enum.Enum): + RED = 3 + + NUM = 1 + CHAR = 'a' + NON = None + FLAG = True + BYT1 = b"abc" + BYT2 = b'\x90' + ENUM = Color.RED + """, + error=None, + ) + + @collect_cases + def test_bad_literal(self) -> Iterator[Case]: + yield Case("from typing_extensions import Literal", "", None) # dummy case + yield Case( + stub="INT_FLOAT_MISMATCH: Literal[1]", + runtime="INT_FLOAT_MISMATCH = 1.0", + error="INT_FLOAT_MISMATCH", + ) + yield Case( + stub="WRONG_INT: Literal[1]", + runtime="WRONG_INT = 2", + error="WRONG_INT", + ) + yield Case( + stub="WRONG_STR: Literal['a']", + runtime="WRONG_STR = 'b'", + error="WRONG_STR", + ) + yield Case( + stub="BYTES_STR_MISMATCH: Literal[b'value']", + runtime="BYTES_STR_MISMATCH = 'value'", + error="BYTES_STR_MISMATCH", + ) + yield Case( + stub="STR_BYTES_MISMATCH: Literal['value']", + runtime="STR_BYTES_MISMATCH = b'value'", + error="STR_BYTES_MISMATCH", + ) + yield Case( + stub="WRONG_BYTES: Literal[b'abc']", + runtime="WRONG_BYTES = b'xyz'", + error="WRONG_BYTES", + ) + yield Case( + stub="WRONG_BOOL_1: Literal[True]", + runtime="WRONG_BOOL_1 = False", + error='WRONG_BOOL_1', + ) + yield Case( + stub="WRONG_BOOL_2: Literal[False]", + runtime="WRONG_BOOL_2 = True", + error='WRONG_BOOL_2', + ) + def remove_color_code(s: str) -> str: return re.sub("\\x1b.*?m", "", s) # this works! diff --git a/mypy/util.py b/mypy/util.py index 533e9c6bee6e9..9f620e823e919 100644 --- a/mypy/util.py +++ b/mypy/util.py @@ -105,6 +105,20 @@ def find_python_encoding(text: bytes, pyversion: Tuple[int, int]) -> Tuple[str, return default_encoding, -1 +def bytes_to_human_readable_repr(b: bytes) -> str: + """Converts bytes into some human-readable representation. Unprintable + bytes such as the nul byte are escaped. For example: + + >>> b = bytes([102, 111, 111, 10, 0]) + >>> s = bytes_to_human_readable_repr(b) + >>> print(s) + foo\n\x00 + >>> print(repr(s)) + 'foo\\n\\x00' + """ + return repr(b)[2:-1] + + class DecodeError(Exception): """Exception raised when a file cannot be decoded due to an unknown encoding type. From 10f6e4dfd4161e0ed7558b9897fab601b3a95fcd Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 7 Jan 2022 14:53:26 +0000 Subject: [PATCH 044/377] Restore removed builtin_type() api method (#11932) It shouldn't be used for new code, but adding it back makes it unnecessary to update existing plugins that no longer worked with mypy 0.930. Related issue: https://github.com/dropbox/sqlalchemy-stubs/issues/232 --- mypy/plugin.py | 6 ++++++ mypy/semanal.py | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/mypy/plugin.py b/mypy/plugin.py index 3772d7039b05a..201ec65748b92 100644 --- a/mypy/plugin.py +++ b/mypy/plugin.py @@ -257,6 +257,12 @@ def named_type(self, fullname: str, """Construct an instance of a builtin type with given type arguments.""" raise NotImplementedError + @abstractmethod + def builtin_type(self, fully_qualified_name: str) -> Instance: + """Legacy function -- use named_type() instead.""" + # NOTE: Do not delete this since many plugins may still use it. + raise NotImplementedError + @abstractmethod def named_type_or_none(self, fullname: str, args: Optional[List[Type]] = None) -> Optional[Instance]: diff --git a/mypy/semanal.py b/mypy/semanal.py index aca1f545c4727..764fb4c363944 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4567,6 +4567,10 @@ def named_type_or_none(self, fullname: str, return Instance(node, args) return Instance(node, [AnyType(TypeOfAny.unannotated)] * len(node.defn.type_vars)) + def builtin_type(self, fully_qualified_name: str) -> Instance: + """Legacy function -- use named_type() instead.""" + return self.named_type(fully_qualified_name) + def lookup_current_scope(self, name: str) -> Optional[SymbolTableNode]: if self.locals[-1] is not None: return self.locals[-1].get(name) From f5ac47fdf5add3f55864949df3b80b1271de8df2 Mon Sep 17 00:00:00 2001 From: Vincent Perez Date: Fri, 7 Jan 2022 18:55:42 +0100 Subject: [PATCH 045/377] Enum now accepts String literals and final values as 2nd arg (#8664) Related #8219 Co-authored-by: Jingchen Ye <97littleleaf11@gmail.com> --- mypy/semanal_enum.py | 18 ++++++++++++++++++ test-data/unit/check-enum.test | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/mypy/semanal_enum.py b/mypy/semanal_enum.py index c900c5fa790f9..bb88b4df47165 100644 --- a/mypy/semanal_enum.py +++ b/mypy/semanal_enum.py @@ -13,6 +13,7 @@ ) from mypy.semanal_shared import SemanticAnalyzerInterface from mypy.options import Options +from mypy.types import get_proper_type, LiteralType # Note: 'enum.EnumMeta' is deliberately excluded from this list. Classes that directly use # enum.EnumMeta do not necessarily automatically have the 'name' and 'value' attributes. @@ -173,6 +174,23 @@ def parse_enum_call_args(self, call: CallExpr, "%s() with dict literal requires string literals" % class_name, call) items.append(key.value) values.append(value) + elif isinstance(args[1], RefExpr) and isinstance(args[1].node, Var): + proper_type = get_proper_type(args[1].node.type) + if (proper_type is not None + and isinstance(proper_type, LiteralType) + and isinstance(proper_type.value, str)): + fields = proper_type.value + for field in fields.replace(',', ' ').split(): + items.append(field) + elif args[1].node.is_final and isinstance(args[1].node.final_value, str): + fields = args[1].node.final_value + for field in fields.replace(',', ' ').split(): + items.append(field) + else: + return self.fail_enum_call_arg( + "%s() expects a string, tuple, list or dict literal as the second argument" % + class_name, + call) else: # TODO: Allow dict(x=1, y=2) as a substitute for {'x': 1, 'y': 2}? return self.fail_enum_call_arg( diff --git a/test-data/unit/check-enum.test b/test-data/unit/check-enum.test index c29ee7b24cf3c..d80cd4822b8ce 100644 --- a/test-data/unit/check-enum.test +++ b/test-data/unit/check-enum.test @@ -11,6 +11,38 @@ m = Medal.gold if int(): m = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "Medal") +-- Creation from Enum call +-- ----------------------- + +[case testEnumCreatedFromStringLiteral] +from enum import Enum +from typing_extensions import Literal + +x: Literal['ANT BEE CAT DOG'] = 'ANT BEE CAT DOG' +Animal = Enum('Animal', x) +reveal_type(Animal.ANT) # N: Revealed type is "Literal[__main__.Animal.ANT]?" +reveal_type(Animal.BEE) # N: Revealed type is "Literal[__main__.Animal.BEE]?" +reveal_type(Animal.CAT) # N: Revealed type is "Literal[__main__.Animal.CAT]?" +reveal_type(Animal.DOG) # N: Revealed type is "Literal[__main__.Animal.DOG]?" + +[builtins fixtures/tuple.pyi] + +[case testEnumCreatedFromFinalValue] +from enum import Enum +from typing_extensions import Final + +x: Final['str'] = 'ANT BEE CAT DOG' +Animal = Enum('Animal', x) +reveal_type(Animal.ANT) # N: Revealed type is "Literal[__main__.Animal.ANT]?" +reveal_type(Animal.BEE) # N: Revealed type is "Literal[__main__.Animal.BEE]?" +reveal_type(Animal.CAT) # N: Revealed type is "Literal[__main__.Animal.CAT]?" +reveal_type(Animal.DOG) # N: Revealed type is "Literal[__main__.Animal.DOG]?" + +[builtins fixtures/tuple.pyi] + +-- Creation from EnumMeta +-- ---------------------- + [case testEnumFromEnumMetaBasics] from enum import EnumMeta class Medal(metaclass=EnumMeta): From 254d41e10a353612d5edfdcb8b23b8e90508830b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tin=20Tvrtkovi=C4=87?= Date: Fri, 7 Jan 2022 19:23:05 +0100 Subject: [PATCH 046/377] attrs namedtuple (#11794) --- mypy/plugin.py | 6 ++++- mypy/plugins/attrs.py | 31 ++++++++++++++++++------ mypy/test/testfinegrained.py | 1 + test-data/unit/check-attr.test | 35 ++++++++++++++++++++++++++- test-data/unit/fine-grained-attr.test | 23 ++++++++++++++++++ 5 files changed, 86 insertions(+), 10 deletions(-) create mode 100644 test-data/unit/fine-grained-attr.test diff --git a/mypy/plugin.py b/mypy/plugin.py index 201ec65748b92..dfa446521548b 100644 --- a/mypy/plugin.py +++ b/mypy/plugin.py @@ -124,7 +124,7 @@ class C: pass from mypy_extensions import trait, mypyc_attr from mypy.nodes import ( - Expression, Context, ClassDef, SymbolTableNode, MypyFile, CallExpr, ArgKind + Expression, Context, ClassDef, SymbolTableNode, MypyFile, CallExpr, ArgKind, TypeInfo ) from mypy.tvar_scope import TypeVarLikeScope from mypy.types import ( @@ -274,6 +274,10 @@ def named_type_or_none(self, fullname: str, """ raise NotImplementedError + @abstractmethod + def basic_new_typeinfo(self, name: str, basetype_or_fallback: Instance, line: int) -> TypeInfo: + raise NotImplementedError + @abstractmethod def parse_bool(self, expr: Expression) -> Optional[bool]: """Parse True/False literals.""" diff --git a/mypy/plugins/attrs.py b/mypy/plugins/attrs.py index 051dae18b96cf..b777bf482e8fd 100644 --- a/mypy/plugins/attrs.py +++ b/mypy/plugins/attrs.py @@ -22,7 +22,7 @@ ) from mypy.types import ( TupleType, Type, AnyType, TypeOfAny, CallableType, NoneType, TypeVarType, - Overloaded, UnionType, FunctionLike, get_proper_type, + Overloaded, UnionType, FunctionLike, Instance, get_proper_type, ) from mypy.typeops import make_simplified_union, map_type_from_supertype from mypy.typevars import fill_typevars @@ -50,6 +50,8 @@ } SELF_TVAR_NAME: Final = "_AT" +MAGIC_ATTR_NAME: Final = "__attrs_attrs__" +MAGIC_ATTR_CLS_NAME: Final = "_AttrsAttributes" # The namedtuple subclass name. class Converter: @@ -302,7 +304,7 @@ def attr_class_maker_callback(ctx: 'mypy.plugin.ClassDefContext', ctx.api.defer() return - _add_attrs_magic_attribute(ctx, raw_attr_types=[info[attr.name].type for attr in attributes]) + _add_attrs_magic_attribute(ctx, [(attr.name, info[attr.name].type) for attr in attributes]) if slots: _add_slots(ctx, attributes) @@ -710,23 +712,36 @@ def _add_init(ctx: 'mypy.plugin.ClassDefContext', attributes: List[Attribute], def _add_attrs_magic_attribute(ctx: 'mypy.plugin.ClassDefContext', - raw_attr_types: 'List[Optional[Type]]') -> None: - attr_name = '__attrs_attrs__' + attrs: 'List[Tuple[str, Optional[Type]]]') -> None: any_type = AnyType(TypeOfAny.explicit) attributes_types: 'List[Type]' = [ ctx.api.named_type_or_none('attr.Attribute', [attr_type or any_type]) or any_type - for attr_type in raw_attr_types + for _, attr_type in attrs ] fallback_type = ctx.api.named_type('builtins.tuple', [ ctx.api.named_type_or_none('attr.Attribute', [any_type]) or any_type, ]) - var = Var(name=attr_name, type=TupleType(attributes_types, fallback=fallback_type)) + + ti = ctx.api.basic_new_typeinfo(MAGIC_ATTR_CLS_NAME, fallback_type, 0) + ti.is_named_tuple = True + for (name, _), attr_type in zip(attrs, attributes_types): + var = Var(name, attr_type) + var.is_property = True + proper_type = get_proper_type(attr_type) + if isinstance(proper_type, Instance): + var.info = proper_type.type + ti.names[name] = SymbolTableNode(MDEF, var, plugin_generated=True) + attributes_type = Instance(ti, []) + + var = Var(name=MAGIC_ATTR_NAME, type=TupleType(attributes_types, fallback=attributes_type)) var.info = ctx.cls.info - var._fullname = ctx.cls.info.fullname + '.' + attr_name - ctx.cls.info.names[attr_name] = SymbolTableNode( + var.is_classvar = True + var._fullname = f"{ctx.cls.fullname}.{MAGIC_ATTR_CLS_NAME}" + ctx.cls.info.names[MAGIC_ATTR_NAME] = SymbolTableNode( kind=MDEF, node=var, plugin_generated=True, + no_serialize=True, ) diff --git a/mypy/test/testfinegrained.py b/mypy/test/testfinegrained.py index ed99b4aeae13a..79507948af14d 100644 --- a/mypy/test/testfinegrained.py +++ b/mypy/test/testfinegrained.py @@ -49,6 +49,7 @@ class FineGrainedSuite(DataSuite): 'fine-grained-modules.test', 'fine-grained-follow-imports.test', 'fine-grained-suggest.test', + 'fine-grained-attr.test', ] # Whether to use the fine-grained cache in the testing. This is overridden diff --git a/test-data/unit/check-attr.test b/test-data/unit/check-attr.test index e7cea6c27b99a..083feb0152e5c 100644 --- a/test-data/unit/check-attr.test +++ b/test-data/unit/check-attr.test @@ -1399,7 +1399,40 @@ class A: b: int = attr.ib() c: str = attr.ib() -reveal_type(A.__attrs_attrs__) # N: Revealed type is "Tuple[attr.Attribute[builtins.int], attr.Attribute[builtins.str]]" +reveal_type(A.__attrs_attrs__) # N: Revealed type is "Tuple[attr.Attribute[builtins.int], attr.Attribute[builtins.str], fallback=__main__.A._AttrsAttributes]" +reveal_type(A.__attrs_attrs__[0]) # N: Revealed type is "attr.Attribute[builtins.int]" +reveal_type(A.__attrs_attrs__.b) # N: Revealed type is "attr.Attribute[builtins.int]" +A.__attrs_attrs__.x # E: "_AttrsAttributes" has no attribute "x" + +[builtins fixtures/attr.pyi] + +[case testAttrsBareClassHasAttributeWithAttributes] +import attr + +@attr.s +class A: + b = attr.ib() + c = attr.ib() + +reveal_type(A.__attrs_attrs__) # N: Revealed type is "Tuple[attr.Attribute[Any], attr.Attribute[Any], fallback=__main__.A._AttrsAttributes]" +reveal_type(A.__attrs_attrs__[0]) # N: Revealed type is "attr.Attribute[Any]" +reveal_type(A.__attrs_attrs__.b) # N: Revealed type is "attr.Attribute[Any]" +A.__attrs_attrs__.x # E: "_AttrsAttributes" has no attribute "x" + +[builtins fixtures/attr.pyi] + +[case testAttrsNGClassHasAttributeWithAttributes] +import attr + +@attr.define +class A: + b: int + c: str + +reveal_type(A.__attrs_attrs__) # N: Revealed type is "Tuple[attr.Attribute[builtins.int], attr.Attribute[builtins.str], fallback=__main__.A._AttrsAttributes]" +reveal_type(A.__attrs_attrs__[0]) # N: Revealed type is "attr.Attribute[builtins.int]" +reveal_type(A.__attrs_attrs__.b) # N: Revealed type is "attr.Attribute[builtins.int]" +A.__attrs_attrs__.x # E: "_AttrsAttributes" has no attribute "x" [builtins fixtures/attr.pyi] diff --git a/test-data/unit/fine-grained-attr.test b/test-data/unit/fine-grained-attr.test new file mode 100644 index 0000000000000..0a54f9a6ea596 --- /dev/null +++ b/test-data/unit/fine-grained-attr.test @@ -0,0 +1,23 @@ +[case updateMagicField] +from attr import Attribute +import m + +def g() -> Attribute[int]: + return m.A.__attrs_attrs__[0] + +[file m.py] +from attr import define + +@define +class A: + a: int +[file m.py.2] +from attr import define + +@define +class A: + a: float +[builtins fixtures/attr.pyi] +[out] +== +main:5: error: Incompatible return value type (got "Attribute[float]", expected "Attribute[int]") From 531a1f0d3df12d6268707f48bbd224e7adf8a262 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Fri, 7 Jan 2022 16:08:11 -0800 Subject: [PATCH 047/377] Remove test samples (#11906) I don't know that these have caught any real issues in the last couple years, however, the standard library ones have been a bit of a pain, most recently in #11905. Jukka was okay removing the stdlib samples two years ago, see #8838 (comment) We now have tooling like mypy primer that runs mypy over a much larger and more varied corpus of code on every PR. The other samples haven't caused me much bother (except for crawl, which I removed in #9375), but except for crawl2, they're all very simple. I don't think they provide us much value, unless they have sentimental or historical value. --- LICENSE | 4 +- mypy/test/testsamples.py | 35 - test-data/samples/bottles.py | 13 - test-data/samples/class.py | 18 - test-data/samples/cmdline.py | 8 - test-data/samples/crawl2.py | 852 -------- test-data/samples/dict.py | 8 - test-data/samples/fib.py | 5 - test-data/samples/files.py | 14 - test-data/samples/for.py | 4 - test-data/samples/generators.py | 24 - test-data/samples/greet.py | 8 - test-data/samples/guess.py | 32 - test-data/samples/hello.py | 2 - test-data/samples/input.py | 3 - test-data/samples/itertool.py | 16 - test-data/samples/readme.txt | 25 - test-data/samples/regexp.py | 7 - test-data/stdlib-samples/3.2/base64.py | 411 ---- test-data/stdlib-samples/3.2/fnmatch.py | 112 - test-data/stdlib-samples/3.2/genericpath.py | 112 - test-data/stdlib-samples/3.2/getopt.py | 220 -- test-data/stdlib-samples/3.2/glob.py | 84 - test-data/stdlib-samples/3.2/posixpath.py | 466 ---- test-data/stdlib-samples/3.2/pprint.py | 380 ---- test-data/stdlib-samples/3.2/random.py | 743 ------- test-data/stdlib-samples/3.2/shutil.py | 790 ------- test-data/stdlib-samples/3.2/tempfile.py | 724 ------- test-data/stdlib-samples/3.2/test/__init__.py | 0 test-data/stdlib-samples/3.2/test/mypy.ini | 2 - .../stdlib-samples/3.2/test/randv2_32.pck | 633 ------ .../stdlib-samples/3.2/test/randv2_64.pck | 633 ------ test-data/stdlib-samples/3.2/test/randv3.pck | 633 ------ .../3.2/test/subprocessdata/fd_status.py | 24 - .../3.2/test/subprocessdata/input_reader.py | 7 - .../3.2/test/subprocessdata/qcat.py | 7 - .../3.2/test/subprocessdata/qgrep.py | 10 - .../test/subprocessdata/sigchild_ignore.py | 6 - test-data/stdlib-samples/3.2/test/support.py | 1602 -------------- .../stdlib-samples/3.2/test/test_base64.py | 267 --- .../stdlib-samples/3.2/test/test_fnmatch.py | 93 - .../3.2/test/test_genericpath.py | 313 --- .../stdlib-samples/3.2/test/test_getopt.py | 190 -- .../stdlib-samples/3.2/test/test_glob.py | 122 -- .../stdlib-samples/3.2/test/test_posixpath.py | 531 ----- .../stdlib-samples/3.2/test/test_pprint.py | 488 ----- .../stdlib-samples/3.2/test/test_random.py | 533 ----- test-data/stdlib-samples/3.2/test/test_set.py | 1884 ----------------- .../stdlib-samples/3.2/test/test_shutil.py | 978 --------- .../stdlib-samples/3.2/test/test_tempfile.py | 1122 ---------- .../stdlib-samples/3.2/test/test_textwrap.py | 601 ------ .../3.2/test/tf_inherit_check.py | 25 - test-data/stdlib-samples/3.2/textwrap.py | 391 ---- 53 files changed, 2 insertions(+), 16213 deletions(-) delete mode 100644 mypy/test/testsamples.py delete mode 100644 test-data/samples/bottles.py delete mode 100644 test-data/samples/class.py delete mode 100644 test-data/samples/cmdline.py delete mode 100644 test-data/samples/crawl2.py delete mode 100644 test-data/samples/dict.py delete mode 100644 test-data/samples/fib.py delete mode 100644 test-data/samples/files.py delete mode 100644 test-data/samples/for.py delete mode 100644 test-data/samples/generators.py delete mode 100644 test-data/samples/greet.py delete mode 100644 test-data/samples/guess.py delete mode 100644 test-data/samples/hello.py delete mode 100644 test-data/samples/input.py delete mode 100644 test-data/samples/itertool.py delete mode 100644 test-data/samples/readme.txt delete mode 100644 test-data/samples/regexp.py delete mode 100644 test-data/stdlib-samples/3.2/base64.py delete mode 100644 test-data/stdlib-samples/3.2/fnmatch.py delete mode 100644 test-data/stdlib-samples/3.2/genericpath.py delete mode 100644 test-data/stdlib-samples/3.2/getopt.py delete mode 100644 test-data/stdlib-samples/3.2/glob.py delete mode 100644 test-data/stdlib-samples/3.2/posixpath.py delete mode 100644 test-data/stdlib-samples/3.2/pprint.py delete mode 100644 test-data/stdlib-samples/3.2/random.py delete mode 100644 test-data/stdlib-samples/3.2/shutil.py delete mode 100644 test-data/stdlib-samples/3.2/tempfile.py delete mode 100644 test-data/stdlib-samples/3.2/test/__init__.py delete mode 100644 test-data/stdlib-samples/3.2/test/mypy.ini delete mode 100644 test-data/stdlib-samples/3.2/test/randv2_32.pck delete mode 100644 test-data/stdlib-samples/3.2/test/randv2_64.pck delete mode 100644 test-data/stdlib-samples/3.2/test/randv3.pck delete mode 100644 test-data/stdlib-samples/3.2/test/subprocessdata/fd_status.py delete mode 100644 test-data/stdlib-samples/3.2/test/subprocessdata/input_reader.py delete mode 100644 test-data/stdlib-samples/3.2/test/subprocessdata/qcat.py delete mode 100644 test-data/stdlib-samples/3.2/test/subprocessdata/qgrep.py delete mode 100644 test-data/stdlib-samples/3.2/test/subprocessdata/sigchild_ignore.py delete mode 100644 test-data/stdlib-samples/3.2/test/support.py delete mode 100644 test-data/stdlib-samples/3.2/test/test_base64.py delete mode 100644 test-data/stdlib-samples/3.2/test/test_fnmatch.py delete mode 100644 test-data/stdlib-samples/3.2/test/test_genericpath.py delete mode 100644 test-data/stdlib-samples/3.2/test/test_getopt.py delete mode 100644 test-data/stdlib-samples/3.2/test/test_glob.py delete mode 100644 test-data/stdlib-samples/3.2/test/test_posixpath.py delete mode 100644 test-data/stdlib-samples/3.2/test/test_pprint.py delete mode 100644 test-data/stdlib-samples/3.2/test/test_random.py delete mode 100644 test-data/stdlib-samples/3.2/test/test_set.py delete mode 100644 test-data/stdlib-samples/3.2/test/test_shutil.py delete mode 100644 test-data/stdlib-samples/3.2/test/test_tempfile.py delete mode 100644 test-data/stdlib-samples/3.2/test/test_textwrap.py delete mode 100644 test-data/stdlib-samples/3.2/test/tf_inherit_check.py delete mode 100644 test-data/stdlib-samples/3.2/textwrap.py diff --git a/LICENSE b/LICENSE index 2e64b704307bf..549ff65756112 100644 --- a/LICENSE +++ b/LICENSE @@ -26,8 +26,8 @@ DEALINGS IN THE SOFTWARE. = = = = = -Portions of mypy and mypyc are licensed under different licenses. The -files under stdlib-samples as well as the files +Portions of mypy and mypyc are licensed under different licenses. +The files mypyc/lib-rt/pythonsupport.h, mypyc/lib-rt/getargs.c and mypyc/lib-rt/getargsfast.c are licensed under the PSF 2 License, reproduced below. diff --git a/mypy/test/testsamples.py b/mypy/test/testsamples.py deleted file mode 100644 index 27b26af16f36c..0000000000000 --- a/mypy/test/testsamples.py +++ /dev/null @@ -1,35 +0,0 @@ -import os.path -from typing import List, Set - -from mypy.test.helpers import Suite, run_mypy - - -class SamplesSuite(Suite): - """Test that we can type check some sample code.""" - - def test_samples(self) -> None: - for f in find_files(os.path.join('test-data', 'samples'), suffix='.py'): - mypy_args = ['--no-strict-optional'] - if f == os.path.join('test-data', 'samples', 'crawl2.py'): - # This test requires 3.5 for async functions - mypy_args.append('--python-version=3.5') - run_mypy(mypy_args + [f]) - - def test_stdlibsamples(self) -> None: - seen: Set[str] = set() - stdlibsamples_dir = os.path.join('test-data', 'stdlib-samples', '3.2', 'test') - modules: List[str] = [] - for f in find_files(stdlibsamples_dir, prefix='test_', suffix='.py'): - if f not in seen: - seen.add(f) - modules.append(f) - if modules: - # TODO: Remove need for --no-strict-optional - run_mypy(['--no-strict-optional', '--platform=linux'] + modules) - - -def find_files(base: str, prefix: str = '', suffix: str = '') -> List[str]: - return [os.path.join(root, f) - for root, dirs, files in os.walk(base) - for f in files - if f.startswith(prefix) and f.endswith(suffix)] diff --git a/test-data/samples/bottles.py b/test-data/samples/bottles.py deleted file mode 100644 index ddf77f59eaa06..0000000000000 --- a/test-data/samples/bottles.py +++ /dev/null @@ -1,13 +0,0 @@ -import typing - -REFRAIN = ''' -%d bottles of beer on the wall, -%d bottles of beer, -take one down, pass it around, -%d bottles of beer on the wall! -''' -bottles_of_beer = 99 -while bottles_of_beer > 1: - print(REFRAIN % (bottles_of_beer, bottles_of_beer, - bottles_of_beer - 1)) - bottles_of_beer -= 1 diff --git a/test-data/samples/class.py b/test-data/samples/class.py deleted file mode 100644 index d2eb4ac0516f9..0000000000000 --- a/test-data/samples/class.py +++ /dev/null @@ -1,18 +0,0 @@ -import typing - - -class BankAccount(object): - def __init__(self, initial_balance: int = 0) -> None: - self.balance = initial_balance - - def deposit(self, amount: int) -> None: - self.balance += amount - - def withdraw(self, amount: int) -> None: - self.balance -= amount - - def overdrawn(self) -> bool: - return self.balance < 0 -my_account = BankAccount(15) -my_account.withdraw(5) -print(my_account.balance) diff --git a/test-data/samples/cmdline.py b/test-data/samples/cmdline.py deleted file mode 100644 index 105c27a305b9d..0000000000000 --- a/test-data/samples/cmdline.py +++ /dev/null @@ -1,8 +0,0 @@ -# This program adds up integers in the command line -import sys -import typing -try: - total = sum(int(arg) for arg in sys.argv[1:]) - print('sum =', total) -except ValueError: - print('Please supply integer arguments') diff --git a/test-data/samples/crawl2.py b/test-data/samples/crawl2.py deleted file mode 100644 index 28b19f38c7c56..0000000000000 --- a/test-data/samples/crawl2.py +++ /dev/null @@ -1,852 +0,0 @@ -#!/usr/bin/env python3.4 - -"""A simple web crawler.""" - -# This is cloned from /examples/crawl.py, -# with type annotations added (PEP 484). -# -# This version (crawl2.) has also been converted to use `async def` + -# `await` (PEP 492). - -import argparse -import asyncio -import cgi -from http.client import BadStatusLine -import logging -import re -import sys -import time -import urllib.parse -from typing import Any, Awaitable, IO, Optional, Sequence, Set, Tuple, List, Dict - - -ARGS = argparse.ArgumentParser(description="Web crawler") -ARGS.add_argument( - '--iocp', action='store_true', dest='iocp', - default=False, help='Use IOCP event loop (Windows only)') -ARGS.add_argument( - '--select', action='store_true', dest='select', - default=False, help='Use Select event loop instead of default') -ARGS.add_argument( - 'roots', nargs='*', - default=[], help='Root URL (may be repeated)') -ARGS.add_argument( - '--max_redirect', action='store', type=int, metavar='N', - default=10, help='Limit redirection chains (for 301, 302 etc.)') -ARGS.add_argument( - '--max_tries', action='store', type=int, metavar='N', - default=4, help='Limit retries on network errors') -ARGS.add_argument( - '--max_tasks', action='store', type=int, metavar='N', - default=100, help='Limit concurrent connections') -ARGS.add_argument( - '--max_pool', action='store', type=int, metavar='N', - default=100, help='Limit connection pool size') -ARGS.add_argument( - '--exclude', action='store', metavar='REGEX', - help='Exclude matching URLs') -ARGS.add_argument( - '--strict', action='store_true', - default=True, help='Strict host matching (default)') -ARGS.add_argument( - '--lenient', action='store_false', dest='strict', - default=False, help='Lenient host matching') -ARGS.add_argument( - '-v', '--verbose', action='count', dest='level', - default=1, help='Verbose logging (repeat for more verbose)') -ARGS.add_argument( - '-q', '--quiet', action='store_const', const=0, dest='level', - default=1, help='Quiet logging (opposite of --verbose)') - - -ESCAPES = [('quot', '"'), - ('gt', '>'), - ('lt', '<'), - ('amp', '&') # Must be last. - ] - - -def unescape(url: str) -> str: - """Turn & into &, and so on. - - This is the inverse of cgi.escape(). - """ - for name, char in ESCAPES: - url = url.replace('&' + name + ';', char) - return url - - -def fix_url(url: str) -> str: - """Prefix a schema-less URL with http://.""" - if '://' not in url: - url = 'http://' + url - return url - - -class Logger: - - def __init__(self, level: int) -> None: - self.level = level - - def _log(self, n: int, args: Sequence[Any]) -> None: - if self.level >= n: - print(*args, file=sys.stderr, flush=True) - - def log(self, n: int, *args: Any) -> None: - self._log(n, args) - - def __call__(self, n: int, *args: Any) -> None: - self._log(n, args) - - -KeyTuple = Tuple[str, int, bool] - - -class ConnectionPool: - """A connection pool. - - To open a connection, use reserve(). To recycle it, use unreserve(). - - The pool is mostly just a mapping from (host, port, ssl) tuples to - lists of Connections. The currently active connections are *not* - in the data structure; get_connection() takes the connection out, - and recycle_connection() puts it back in. To recycle a - connection, call conn.close(recycle=True). - - There are limits to both the overall pool and the per-key pool. - """ - - def __init__(self, log: Logger, max_pool: int = 10, max_tasks: int = 5) -> None: - self.log = log - self.max_pool = max_pool # Overall limit. - self.max_tasks = max_tasks # Per-key limit. - self.loop = asyncio.get_event_loop() - self.connections = {} # type: Dict[KeyTuple, List[Connection]] - self.queue = [] # type: List[Connection] - - def close(self) -> None: - """Close all connections available for reuse.""" - for conns in self.connections.values(): - for conn in conns: - conn.close() - self.connections.clear() - self.queue.clear() - - async def get_connection(self, host: str, port: int, ssl: bool) -> 'Connection': - """Create or reuse a connection.""" - port = port or (443 if ssl else 80) - try: - ipaddrs = await self.loop.getaddrinfo(host, port) - except Exception as exc: - self.log(0, 'Exception %r for (%r, %r)' % (exc, host, port)) - raise - self.log(1, '* %s resolves to %s' % - (host, ', '.join(ip[4][0] for ip in ipaddrs))) - - # Look for a reusable connection. - for _1, _2, _3, _4, (h, p, *_5) in ipaddrs: - key = h, p, ssl - conn = None - conns = self.connections.get(key) - while conns: - conn = conns.pop(0) - self.queue.remove(conn) - if not conns: - del self.connections[key] - if conn.stale(): - self.log(1, 'closing stale connection for', key) - conn.close() # Just in case. - else: - self.log(1, '* Reusing pooled connection', key, - 'FD =', conn.fileno()) - return conn - - # Create a new connection. - conn = Connection(self.log, self, host, port, ssl) - await conn.connect() - self.log(1, '* New connection', conn.key, 'FD =', conn.fileno()) - return conn - - def recycle_connection(self, conn: 'Connection') -> None: - """Make a connection available for reuse. - - This also prunes the pool if it exceeds the size limits. - """ - if conn.stale(): - conn.close() - return - - key = conn.key - conns = self.connections.setdefault(key, []) - conns.append(conn) - self.queue.append(conn) - - if len(conns) <= self.max_tasks and len(self.queue) <= self.max_pool: - return - - # Prune the queue. - - # Close stale connections for this key first. - stale = [conn for conn in conns if conn.stale()] - if stale: - for conn in stale: - conns.remove(conn) - self.queue.remove(conn) - self.log(1, 'closing stale connection for', key) - conn.close() - if not conns: - del self.connections[key] - - # Close oldest connection(s) for this key if limit reached. - while len(conns) > self.max_tasks: - conn = conns.pop(0) - self.queue.remove(conn) - self.log(1, 'closing oldest connection for', key) - conn.close() - - if len(self.queue) <= self.max_pool: - return - - # Close overall stale connections. - stale = [conn for conn in self.queue if conn.stale()] - if stale: - for conn in stale: - conns = self.connections.get(conn.key) - conns.remove(conn) - self.queue.remove(conn) - self.log(1, 'closing stale connection for', key) - conn.close() - - # Close oldest overall connection(s) if limit reached. - while len(self.queue) > self.max_pool: - conn = self.queue.pop(0) - conns = self.connections.get(conn.key) - c = conns.pop(0) - assert conn == c, (conn.key, conn, c, conns) - self.log(1, 'closing overall oldest connection for', conn.key) - conn.close() - - -class Connection: - - def __init__(self, log: Logger, pool: ConnectionPool, host: str, port: int, ssl: bool) -> None: - self.log = log - self.pool = pool - self.host = host - self.port = port - self.ssl = ssl - self.reader = None # type: asyncio.StreamReader - self.writer = None # type: asyncio.StreamWriter - self.key = None # type: KeyTuple - - def stale(self) -> bool: - return self.reader is None or self.reader.at_eof() - - def fileno(self) -> Optional[int]: - writer = self.writer - if writer is not None: - transport = writer.transport - if transport is not None: - sock = transport.get_extra_info('socket') - if sock is not None: - return sock.fileno() - return None - - async def connect(self) -> None: - self.reader, self.writer = await asyncio.open_connection( - self.host, self.port, ssl=self.ssl) - peername = self.writer.get_extra_info('peername') - if peername: - self.host, self.port = peername[:2] - else: - self.log(1, 'NO PEERNAME???', self.host, self.port, self.ssl) - self.key = self.host, self.port, self.ssl - - def close(self, recycle: bool = False) -> None: - if recycle and not self.stale(): - self.pool.recycle_connection(self) - else: - self.writer.close() - self.pool = self.reader = self.writer = None - - -class Request: - """HTTP request. - - Use connect() to open a connection; send_request() to send the - request; get_response() to receive the response headers. - """ - - def __init__(self, log: Logger, url: str, pool: ConnectionPool) -> None: - self.log = log - self.url = url - self.pool = pool - self.parts = urllib.parse.urlparse(self.url) - self.scheme = self.parts.scheme - assert self.scheme in ('http', 'https'), repr(url) - self.ssl = self.parts.scheme == 'https' - self.netloc = self.parts.netloc - self.hostname = self.parts.hostname - self.port = self.parts.port or (443 if self.ssl else 80) - self.path = (self.parts.path or '/') - self.query = self.parts.query - if self.query: - self.full_path = '%s?%s' % (self.path, self.query) - else: - self.full_path = self.path - self.http_version = 'HTTP/1.1' - self.method = 'GET' - self.headers = [] # type: List[Tuple[str, str]] - self.conn = None # type: Connection - - async def connect(self) -> None: - """Open a connection to the server.""" - self.log(1, '* Connecting to %s:%s using %s for %s' % - (self.hostname, self.port, - 'ssl' if self.ssl else 'tcp', - self.url)) - self.conn = await self.pool.get_connection(self.hostname, - self.port, self.ssl) - - def close(self, recycle: bool = False) -> None: - """Close the connection, recycle if requested.""" - if self.conn is not None: - if not recycle: - self.log(1, 'closing connection for', self.conn.key) - self.conn.close(recycle) - self.conn = None - - async def putline(self, line: str) -> None: - """Write a line to the connection. - - Used for the request line and headers. - """ - self.log(2, '>', line) - self.conn.writer.write(line.encode('latin-1') + b'\r\n') - - async def send_request(self) -> None: - """Send the request.""" - request_line = '%s %s %s' % (self.method, self.full_path, - self.http_version) - await self.putline(request_line) - # TODO: What if a header is already set? - self.headers.append(('User-Agent', 'asyncio-example-crawl/0.0')) - self.headers.append(('Host', self.netloc)) - self.headers.append(('Accept', '*/*')) - # self.headers.append(('Accept-Encoding', 'gzip')) - for key, value in self.headers: - line = '%s: %s' % (key, value) - await self.putline(line) - await self.putline('') - - async def get_response(self) -> 'Response': - """Receive the response.""" - response = Response(self.log, self.conn.reader) - await response.read_headers() - return response - - -class Response: - """HTTP response. - - Call read_headers() to receive the request headers. Then check - the status attribute and call get_header() to inspect the headers. - Finally call read() to receive the body. - """ - - def __init__(self, log: Logger, reader: asyncio.StreamReader) -> None: - self.log = log - self.reader = reader - self.http_version = None # type: str # 'HTTP/1.1' - self.status = None # type: int # 200 - self.reason = None # type: str # 'Ok' - self.headers = [] # type: List[Tuple[str, str]] # [('Content-Type', 'text/html')] - - async def getline(self) -> str: - """Read one line from the connection.""" - line = (await self.reader.readline()).decode('latin-1').rstrip() - self.log(2, '<', line) - return line - - async def read_headers(self) -> None: - """Read the response status and the request headers.""" - status_line = await self.getline() - status_parts = status_line.split(None, 2) - if len(status_parts) != 3: - self.log(0, 'bad status_line', repr(status_line)) - raise BadStatusLine(status_line) - self.http_version, status, self.reason = status_parts - self.status = int(status) - while True: - header_line = await self.getline() - if not header_line: - break - # TODO: Continuation lines. - key, value = header_line.split(':', 1) - self.headers.append((key, value.strip())) - - def get_redirect_url(self, default: str = '') -> str: - """Inspect the status and return the redirect url if appropriate.""" - if self.status not in (300, 301, 302, 303, 307): - return default - return self.get_header('Location', default) - - def get_header(self, key: str, default: str = '') -> str: - """Get one header value, using a case insensitive header name.""" - key = key.lower() - for k, v in self.headers: - if k.lower() == key: - return v - return default - - async def read(self) -> bytes: - """Read the response body. - - This honors Content-Length and Transfer-Encoding: chunked. - """ - nbytes = None - for key, value in self.headers: - if key.lower() == 'content-length': - nbytes = int(value) - break - if nbytes is None: - if self.get_header('transfer-encoding').lower() == 'chunked': - self.log(2, 'parsing chunked response') - blocks = [] - while True: - size_header = await self.reader.readline() - if not size_header: - self.log(0, 'premature end of chunked response') - break - self.log(3, 'size_header =', repr(size_header)) - parts = size_header.split(b';') - size = int(parts[0], 16) - if size: - self.log(3, 'reading chunk of', size, 'bytes') - block = await self.reader.readexactly(size) - assert len(block) == size, (len(block), size) - blocks.append(block) - crlf = await self.reader.readline() - assert crlf == b'\r\n', repr(crlf) - if not size: - break - body = b''.join(blocks) - self.log(1, 'chunked response had', len(body), - 'bytes in', len(blocks), 'blocks') - else: - self.log(3, 'reading until EOF') - body = await self.reader.read() - # TODO: Should make sure not to recycle the connection - # in this case. - else: - body = await self.reader.readexactly(nbytes) - return body - - -class Fetcher: - """Logic and state for one URL. - - When found in crawler.busy, this represents a URL to be fetched or - in the process of being fetched; when found in crawler.done, this - holds the results from fetching it. - - This is usually associated with a task. This references the - crawler for the connection pool and to add more URLs to its todo - list. - - Call fetch() to do the fetching, then report() to print the results. - """ - - def __init__(self, log: Logger, url: str, crawler: 'Crawler', - max_redirect: int = 10, max_tries: int = 4) -> None: - self.log = log - self.url = url - self.crawler = crawler - # We don't loop resolving redirects here -- we just use this - # to decide whether to add the redirect URL to crawler.todo. - self.max_redirect = max_redirect - # But we do loop to retry on errors a few times. - self.max_tries = max_tries - # Everything we collect from the response goes here. - self.task = None # type: asyncio.Task - self.exceptions = [] # type: List[Exception] - self.tries = 0 - self.request = None # type: Request - self.response = None # type: Response - self.body = None # type: bytes - self.next_url = None # type: str - self.ctype = None # type: str - self.pdict = None # type: Dict[str, str] - self.encoding = None # type: str - self.urls = None # type: Set[str] - self.new_urls = None # type: Set[str] - - async def fetch(self) -> None: - """Attempt to fetch the contents of the URL. - - If successful, and the data is HTML, extract further links and - add them to the crawler. Redirects are also added back there. - """ - while self.tries < self.max_tries: - self.tries += 1 - self.request = None - try: - self.request = Request(self.log, self.url, self.crawler.pool) - await self.request.connect() - await self.request.send_request() - self.response = await self.request.get_response() - self.body = await self.response.read() - h_conn = self.response.get_header('connection').lower() - if h_conn != 'close': - self.request.close(recycle=True) - self.request = None - if self.tries > 1: - self.log(1, 'try', self.tries, 'for', self.url, 'success') - break - except (BadStatusLine, OSError) as exc: - self.exceptions.append(exc) - self.log(1, 'try', self.tries, 'for', self.url, - 'raised', repr(exc)) - # import pdb; pdb.set_trace() - # Don't reuse the connection in this case. - finally: - if self.request is not None: - self.request.close() - else: - # We never broke out of the while loop, i.e. all tries failed. - self.log(0, 'no success for', self.url, - 'in', self.max_tries, 'tries') - return - next_url = self.response.get_redirect_url() - if next_url: - self.next_url = urllib.parse.urljoin(self.url, next_url) - if self.max_redirect > 0: - self.log(1, 'redirect to', self.next_url, 'from', self.url) - self.crawler.add_url(self.next_url, self.max_redirect - 1) - else: - self.log(0, 'redirect limit reached for', self.next_url, - 'from', self.url) - else: - if self.response.status == 200: - self.ctype = self.response.get_header('content-type') - self.pdict = {} - if self.ctype: - self.ctype, self.pdict = cgi.parse_header(self.ctype) - self.encoding = self.pdict.get('charset', 'utf-8') - if self.ctype == 'text/html': - body = self.body.decode(self.encoding, 'replace') - # Replace href with (?:href|src) to follow image links. - self.urls = set(re.findall(r'(?i)href=["\']?([^\s"\'<>]+)', - body)) - if self.urls: - self.log(1, 'got', len(self.urls), - 'distinct urls from', self.url) - self.new_urls = set() - for url in self.urls: - url = unescape(url) - url = urllib.parse.urljoin(self.url, url) - url, frag = urllib.parse.urldefrag(url) - if self.crawler.add_url(url): - self.new_urls.add(url) - - def report(self, stats: 'Stats', file: IO[str] = None) -> None: - """Print a report on the state for this URL. - - Also update the Stats instance. - """ - if self.task is not None: - if not self.task.done(): - stats.add('pending') - print(self.url, 'pending', file=file) - return - elif self.task.cancelled(): - stats.add('cancelled') - print(self.url, 'cancelled', file=file) - return - elif self.task.exception(): - stats.add('exception') - exc = self.task.exception() - stats.add('exception_' + exc.__class__.__name__) - print(self.url, exc, file=file) - return - if len(self.exceptions) == self.tries: - stats.add('fail') - exc = self.exceptions[-1] - stats.add('fail_' + str(exc.__class__.__name__)) - print(self.url, 'error', exc, file=file) - elif self.next_url: - stats.add('redirect') - print(self.url, self.response.status, 'redirect', self.next_url, - file=file) - elif self.ctype == 'text/html': - stats.add('html') - size = len(self.body or b'') - stats.add('html_bytes', size) - if self.log.level: - print(self.url, self.response.status, - self.ctype, self.encoding, - size, - '%d/%d' % (len(self.new_urls or ()), len(self.urls or ())), - file=file) - elif self.response is None: - print(self.url, 'no response object') - else: - size = len(self.body or b'') - if self.response.status == 200: - stats.add('other') - stats.add('other_bytes', size) - else: - stats.add('error') - stats.add('error_bytes', size) - stats.add('status_%s' % self.response.status) - print(self.url, self.response.status, - self.ctype, self.encoding, - size, - file=file) - - -class Stats: - """Record stats of various sorts.""" - - def __init__(self) -> None: - self.stats = {} # type: Dict[str, int] - - def add(self, key: str, count: int = 1) -> None: - self.stats[key] = self.stats.get(key, 0) + count - - def report(self, file: IO[str] = None) -> None: - for key, count in sorted(self.stats.items()): - print('%10d' % count, key, file=file) - - -class Crawler: - """Crawl a set of URLs. - - This manages three disjoint sets of URLs (todo, busy, done). The - data structures actually store dicts -- the values in todo give - the redirect limit, while the values in busy and done are Fetcher - instances. - """ - def __init__(self, log: Logger, - roots: Set[str], exclude: str = None, strict: bool = True, # What to crawl. - max_redirect: int = 10, max_tries: int = 4, # Per-url limits. - max_tasks: int = 10, max_pool: int = 10, # Global limits. - ) -> None: - self.log = log - self.roots = roots - self.exclude = exclude - self.strict = strict - self.max_redirect = max_redirect - self.max_tries = max_tries - self.max_tasks = max_tasks - self.max_pool = max_pool - self.todo = {} # type: Dict[str, int] - self.busy = {} # type: Dict[str, Fetcher] - self.done = {} # type: Dict[str, Fetcher] - self.pool = ConnectionPool(self.log, max_pool, max_tasks) - self.root_domains = set() # type: Set[str] - for root in roots: - host = urllib.parse.urlparse(root).hostname - if not host: - continue - if re.match(r'\A[\d\.]*\Z', host): - self.root_domains.add(host) - else: - host = host.lower() - if self.strict: - self.root_domains.add(host) - if host.startswith('www.'): - self.root_domains.add(host[4:]) - else: - self.root_domains.add('www.' + host) - else: - parts = host.split('.') - if len(parts) > 2: - host = '.'.join(parts[-2:]) - self.root_domains.add(host) - for root in roots: - self.add_url(root) - self.governor = asyncio.Semaphore(max_tasks) - self.termination = asyncio.Condition() - self.t0 = time.time() - self.t1 = None # type: Optional[float] - - def close(self) -> None: - """Close resources (currently only the pool).""" - self.pool.close() - - def host_okay(self, host: str) -> bool: - """Check if a host should be crawled. - - A literal match (after lowercasing) is always good. For hosts - that don't look like IP addresses, some approximate matches - are okay depending on the strict flag. - """ - host = host.lower() - if host in self.root_domains: - return True - if re.match(r'\A[\d\.]*\Z', host): - return False - if self.strict: - return self._host_okay_strictish(host) - else: - return self._host_okay_lenient(host) - - def _host_okay_strictish(self, host: str) -> bool: - """Check if a host should be crawled, strict-ish version. - - This checks for equality modulo an initial 'www.' component. - """ - if host.startswith('www.'): - if host[4:] in self.root_domains: - return True - else: - if 'www.' + host in self.root_domains: - return True - return False - - def _host_okay_lenient(self, host: str) -> bool: - """Check if a host should be crawled, lenient version. - - This compares the last two components of the host. - """ - parts = host.split('.') - if len(parts) > 2: - host = '.'.join(parts[-2:]) - return host in self.root_domains - - def add_url(self, url: str, max_redirect: int = None) -> bool: - """Add a URL to the todo list if not seen before.""" - if self.exclude and re.search(self.exclude, url): - return False - parsed = urllib.parse.urlparse(url) - if parsed.scheme not in ('http', 'https'): - self.log(2, 'skipping non-http scheme in', url) - return False - host = parsed.hostname - if not self.host_okay(host): - self.log(2, 'skipping non-root host in', url) - return False - if max_redirect is None: - max_redirect = self.max_redirect - if url in self.todo or url in self.busy or url in self.done: - return False - self.log(1, 'adding', url, max_redirect) - self.todo[url] = max_redirect - return True - - async def crawl(self) -> None: - """Run the crawler until all finished.""" - with (await self.termination): - while self.todo or self.busy: - if self.todo: - url, max_redirect = self.todo.popitem() - fetcher = Fetcher(self.log, url, - crawler=self, - max_redirect=max_redirect, - max_tries=self.max_tries, - ) - self.busy[url] = fetcher - fetcher.task = asyncio.Task(self.fetch(fetcher)) - else: - await self.termination.wait() - self.t1 = time.time() - - async def fetch(self, fetcher: Fetcher) -> None: - """Call the Fetcher's fetch(), with a limit on concurrency. - - Once this returns, move the fetcher from busy to done. - """ - url = fetcher.url - with (await self.governor): - try: - await fetcher.fetch() # Fetcher gonna fetch. - finally: - # Force GC of the task, so the error is logged. - fetcher.task = None - with (await self.termination): - self.done[url] = fetcher - del self.busy[url] - self.termination.notify() - - def report(self, file: IO[str] = None) -> None: - """Print a report on all completed URLs.""" - if self.t1 is None: - self.t1 = time.time() - dt = self.t1 - self.t0 - if dt and self.max_tasks: - speed = len(self.done) / dt / self.max_tasks - else: - speed = 0 - stats = Stats() - print('*** Report ***', file=file) - try: - show = [] # type: List[Tuple[str, Fetcher]] - show.extend(self.done.items()) - show.extend(self.busy.items()) - show.sort() - for url, fetcher in show: - fetcher.report(stats, file=file) - except KeyboardInterrupt: - print('\nInterrupted', file=file) - print('Finished', len(self.done), - 'urls in %.3f secs' % dt, - '(max_tasks=%d)' % self.max_tasks, - '(%.3f urls/sec/task)' % speed, - file=file) - stats.report(file=file) - print('Todo:', len(self.todo), file=file) - print('Busy:', len(self.busy), file=file) - print('Done:', len(self.done), file=file) - print('Date:', time.ctime(), 'local time', file=file) - - -def main() -> None: - """Main program. - - Parse arguments, set up event loop, run crawler, print report. - """ - args = ARGS.parse_args() - if not args.roots: - print('Use --help for command line help') - return - - log = Logger(args.level) - - if args.iocp: - if sys.platform == 'win32': - from asyncio import ProactorEventLoop - loop = ProactorEventLoop() # type: ignore - asyncio.set_event_loop(loop) - else: - assert False - elif args.select: - loop = asyncio.SelectorEventLoop() # type: ignore - asyncio.set_event_loop(loop) - else: - loop = asyncio.get_event_loop() # type: ignore - - roots = {fix_url(root) for root in args.roots} - - crawler = Crawler(log, - roots, exclude=args.exclude, - strict=args.strict, - max_redirect=args.max_redirect, - max_tries=args.max_tries, - max_tasks=args.max_tasks, - max_pool=args.max_pool, - ) - try: - loop.run_until_complete(crawler.crawl()) # Crawler gonna crawl. - except KeyboardInterrupt: - sys.stderr.flush() - print('\nInterrupted\n') - finally: - crawler.report() - crawler.close() - loop.close() - - -if __name__ == '__main__': - logging.basicConfig(level=logging.INFO) # type: ignore - main() diff --git a/test-data/samples/dict.py b/test-data/samples/dict.py deleted file mode 100644 index d74a5b5ea01aa..0000000000000 --- a/test-data/samples/dict.py +++ /dev/null @@ -1,8 +0,0 @@ -import typing -prices = {'apple': 0.40, 'banana': 0.50} -my_purchase = { - 'apple': 1, - 'banana': 6} -grocery_bill = sum(prices[fruit] * my_purchase[fruit] - for fruit in my_purchase) -print('I owe the grocer $%.2f' % grocery_bill) diff --git a/test-data/samples/fib.py b/test-data/samples/fib.py deleted file mode 100644 index 26248c866b1f8..0000000000000 --- a/test-data/samples/fib.py +++ /dev/null @@ -1,5 +0,0 @@ -import typing -parents, babies = (1, 1) -while babies < 100: - print('This generation has {0} babies'.format(babies)) - parents, babies = (babies, parents + babies) diff --git a/test-data/samples/files.py b/test-data/samples/files.py deleted file mode 100644 index f540c7c2b6656..0000000000000 --- a/test-data/samples/files.py +++ /dev/null @@ -1,14 +0,0 @@ -# indent your Python code to put into an email -import glob -import typing -# glob supports Unix style pathname extensions -python_files = glob.glob('*.py') -for file_name in sorted(python_files): - print(' ------' + file_name) - - f = open(file_name) - for line in f: - print(' ' + line.rstrip()) - f.close() - - print() diff --git a/test-data/samples/for.py b/test-data/samples/for.py deleted file mode 100644 index f7eeed4efbe6f..0000000000000 --- a/test-data/samples/for.py +++ /dev/null @@ -1,4 +0,0 @@ -import typing -friends = ['john', 'pat', 'gary', 'michael'] -for i, name in enumerate(friends): - print("iteration {iteration} is {name}".format(iteration=i, name=name)) diff --git a/test-data/samples/generators.py b/test-data/samples/generators.py deleted file mode 100644 index 17e94c1bfb45f..0000000000000 --- a/test-data/samples/generators.py +++ /dev/null @@ -1,24 +0,0 @@ -# Prime number sieve with generators - -import itertools -from typing import Iterator - - -def iter_primes() -> Iterator[int]: - # an iterator of all numbers between 2 and +infinity - numbers = itertools.count(2) # type: Iterator[int] - - # generate primes forever - while True: - # get the first number from the iterator (always a prime) - prime = next(numbers) - yield prime - - # this code iteratively builds up a chain of - # filters...slightly tricky, but ponder it a bit - numbers = filter(prime.__rmod__, numbers) - -for p in iter_primes(): - if p > 1000: - break - print(p) diff --git a/test-data/samples/greet.py b/test-data/samples/greet.py deleted file mode 100644 index 47e7626410c31..0000000000000 --- a/test-data/samples/greet.py +++ /dev/null @@ -1,8 +0,0 @@ -import typing - - -def greet(name: str) -> None: - print('Hello', name) -greet('Jack') -greet('Jill') -greet('Bob') diff --git a/test-data/samples/guess.py b/test-data/samples/guess.py deleted file mode 100644 index d3f1cee4edc74..0000000000000 --- a/test-data/samples/guess.py +++ /dev/null @@ -1,32 +0,0 @@ -# "Guess the Number" Game (edited) from http://inventwithpython.com - -import random -import typing - -guesses_made = 0 - -name = input('Hello! What is your name?\n') - -number = random.randint(1, 20) -print('Well, {0}, I am thinking of a number between 1 and 20.'.format(name)) - -while guesses_made < 6: - - guess = int(input('Take a guess: ')) - - guesses_made += 1 - - if guess < number: - print('Your guess is too low.') - - if guess > number: - print('Your guess is too high.') - - if guess == number: - break - -if guess == number: - print('Good job, {0}! You guessed my number in {1} guesses!'.format( - name, guesses_made)) -else: - print('Nope. The number I was thinking of was {0}'.format(number)) diff --git a/test-data/samples/hello.py b/test-data/samples/hello.py deleted file mode 100644 index 6c0b2caa7a601..0000000000000 --- a/test-data/samples/hello.py +++ /dev/null @@ -1,2 +0,0 @@ -import typing -print('Hello, world') diff --git a/test-data/samples/input.py b/test-data/samples/input.py deleted file mode 100644 index cca92336f06bc..0000000000000 --- a/test-data/samples/input.py +++ /dev/null @@ -1,3 +0,0 @@ -import typing -name = input('What is your name?\n') -print('Hi, %s.' % name) diff --git a/test-data/samples/itertool.py b/test-data/samples/itertool.py deleted file mode 100644 index 9ee2475e01fb8..0000000000000 --- a/test-data/samples/itertool.py +++ /dev/null @@ -1,16 +0,0 @@ -from itertools import groupby -import typing -lines = ''' -This is the -first paragraph. - -This is the second. -'''.splitlines() -# Use itertools.groupby and bool to return groups of -# consecutive lines that either have content or don't. -for has_chars, frags in groupby(lines, bool): - if has_chars: - print(' '.join(frags)) -# PRINTS: -# This is the first paragraph. -# This is the second. diff --git a/test-data/samples/readme.txt b/test-data/samples/readme.txt deleted file mode 100644 index 5889a8ee00ca0..0000000000000 --- a/test-data/samples/readme.txt +++ /dev/null @@ -1,25 +0,0 @@ -Mypy Sample Programs --------------------- - -The sample programs use static typing unless otherwise noted in comments. - -Original credits for sample programs: - - fib.py - Python Wiki [1] - for.py - Python Wiki [1] - greet.py - Python Wiki [1] - hello.py - Python Wiki [1] - input.py - Python Wiki [1] - regexp.py - Python Wiki [1] - dict.py - Python Wiki [1] - cmdline.py - Python Wiki [1] - files.py - Python Wiki [1] - bottles.py - Python Wiki [1] - class.py - Python Wiki [1] - guess.py - Python Wiki [1] - generators.py - Python Wiki [1] - itertool.py - Python Wiki [1] - -The sample programs were ported to mypy by Jukka Lehtosalo. - -[1] http://wiki.python.org/moin/SimplePrograms diff --git a/test-data/samples/regexp.py b/test-data/samples/regexp.py deleted file mode 100644 index 6d8d7992d0aed..0000000000000 --- a/test-data/samples/regexp.py +++ /dev/null @@ -1,7 +0,0 @@ -import typing -import re -for test_string in ['555-1212', 'ILL-EGAL']: - if re.match(r'^\d{3}-\d{4}$', test_string): - print(test_string, 'is a valid US local phone number') - else: - print(test_string, 'rejected') diff --git a/test-data/stdlib-samples/3.2/base64.py b/test-data/stdlib-samples/3.2/base64.py deleted file mode 100644 index ef91964905718..0000000000000 --- a/test-data/stdlib-samples/3.2/base64.py +++ /dev/null @@ -1,411 +0,0 @@ -#! /usr/bin/env python3 - -"""RFC 3548: Base16, Base32, Base64 Data Encodings""" - -# Modified 04-Oct-1995 by Jack Jansen to use binascii module -# Modified 30-Dec-2003 by Barry Warsaw to add full RFC 3548 support -# Modified 22-May-2007 by Guido van Rossum to use bytes everywhere - -import re -import struct -import binascii - -from typing import Dict, List, AnyStr, IO - - -__all__ = [ - # Legacy interface exports traditional RFC 1521 Base64 encodings - 'encode', 'decode', 'encodebytes', 'decodebytes', - # Generalized interface for other encodings - 'b64encode', 'b64decode', 'b32encode', 'b32decode', - 'b16encode', 'b16decode', - # Standard Base64 encoding - 'standard_b64encode', 'standard_b64decode', - # Some common Base64 alternatives. As referenced by RFC 3458, see thread - # starting at: - # - # http://zgp.org/pipermail/p2p-hackers/2001-September/000316.html - 'urlsafe_b64encode', 'urlsafe_b64decode', - ] - - -bytes_types = (bytes, bytearray) # Types acceptable as binary data - - -def _translate(s: bytes, altchars: Dict[AnyStr, bytes]) -> bytes: - if not isinstance(s, bytes_types): - raise TypeError("expected bytes, not %s" % s.__class__.__name__) - translation = bytearray(range(256)) - for k, v in altchars.items(): - translation[ord(k)] = v[0] - return s.translate(translation) - - - -# Base64 encoding/decoding uses binascii - -def b64encode(s: bytes, altchars: bytes = None) -> bytes: - """Encode a byte string using Base64. - - s is the byte string to encode. Optional altchars must be a byte - string of length 2 which specifies an alternative alphabet for the - '+' and '/' characters. This allows an application to - e.g. generate url or filesystem safe Base64 strings. - - The encoded byte string is returned. - """ - if not isinstance(s, bytes_types): - raise TypeError("expected bytes, not %s" % s.__class__.__name__) - # Strip off the trailing newline - encoded = binascii.b2a_base64(s)[:-1] - if altchars is not None: - if not isinstance(altchars, bytes_types): - raise TypeError("expected bytes, not %s" - % altchars.__class__.__name__) - assert len(altchars) == 2, repr(altchars) - return _translate(encoded, {'+': altchars[0:1], '/': altchars[1:2]}) - return encoded - - -def b64decode(s: bytes, altchars: bytes = None, - validate: bool = False) -> bytes: - """Decode a Base64 encoded byte string. - - s is the byte string to decode. Optional altchars must be a - string of length 2 which specifies the alternative alphabet used - instead of the '+' and '/' characters. - - The decoded string is returned. A binascii.Error is raised if s is - incorrectly padded. - - If validate is False (the default), non-base64-alphabet characters are - discarded prior to the padding check. If validate is True, - non-base64-alphabet characters in the input result in a binascii.Error. - """ - if not isinstance(s, bytes_types): - raise TypeError("expected bytes, not %s" % s.__class__.__name__) - if altchars is not None: - if not isinstance(altchars, bytes_types): - raise TypeError("expected bytes, not %s" - % altchars.__class__.__name__) - assert len(altchars) == 2, repr(altchars) - s = _translate(s, {chr(altchars[0]): b'+', chr(altchars[1]): b'/'}) - if validate and not re.match(b'^[A-Za-z0-9+/]*={0,2}$', s): - raise binascii.Error('Non-base64 digit found') - return binascii.a2b_base64(s) - - -def standard_b64encode(s: bytes) -> bytes: - """Encode a byte string using the standard Base64 alphabet. - - s is the byte string to encode. The encoded byte string is returned. - """ - return b64encode(s) - -def standard_b64decode(s: bytes) -> bytes: - """Decode a byte string encoded with the standard Base64 alphabet. - - s is the byte string to decode. The decoded byte string is - returned. binascii.Error is raised if the input is incorrectly - padded or if there are non-alphabet characters present in the - input. - """ - return b64decode(s) - -def urlsafe_b64encode(s: bytes) -> bytes: - """Encode a byte string using a url-safe Base64 alphabet. - - s is the byte string to encode. The encoded byte string is - returned. The alphabet uses '-' instead of '+' and '_' instead of - '/'. - """ - return b64encode(s, b'-_') - -def urlsafe_b64decode(s: bytes) -> bytes: - """Decode a byte string encoded with the standard Base64 alphabet. - - s is the byte string to decode. The decoded byte string is - returned. binascii.Error is raised if the input is incorrectly - padded or if there are non-alphabet characters present in the - input. - - The alphabet uses '-' instead of '+' and '_' instead of '/'. - """ - return b64decode(s, b'-_') - - - -# Base32 encoding/decoding must be done in Python -_b32alphabet = { - 0: b'A', 9: b'J', 18: b'S', 27: b'3', - 1: b'B', 10: b'K', 19: b'T', 28: b'4', - 2: b'C', 11: b'L', 20: b'U', 29: b'5', - 3: b'D', 12: b'M', 21: b'V', 30: b'6', - 4: b'E', 13: b'N', 22: b'W', 31: b'7', - 5: b'F', 14: b'O', 23: b'X', - 6: b'G', 15: b'P', 24: b'Y', - 7: b'H', 16: b'Q', 25: b'Z', - 8: b'I', 17: b'R', 26: b'2', - } - -_b32tab = [v[0] for k, v in sorted(_b32alphabet.items())] -_b32rev = dict([(v[0], k) for k, v in _b32alphabet.items()]) - - -def b32encode(s: bytes) -> bytes: - """Encode a byte string using Base32. - - s is the byte string to encode. The encoded byte string is returned. - """ - if not isinstance(s, bytes_types): - raise TypeError("expected bytes, not %s" % s.__class__.__name__) - quanta, leftover = divmod(len(s), 5) - # Pad the last quantum with zero bits if necessary - if leftover: - s = s + bytes(5 - leftover) # Don't use += ! - quanta += 1 - encoded = bytes() - for i in range(quanta): - # c1 and c2 are 16 bits wide, c3 is 8 bits wide. The intent of this - # code is to process the 40 bits in units of 5 bits. So we take the 1 - # leftover bit of c1 and tack it onto c2. Then we take the 2 leftover - # bits of c2 and tack them onto c3. The shifts and masks are intended - # to give us values of exactly 5 bits in width. - c1, c2, c3 = struct.unpack('!HHB', s[i*5:(i+1)*5]) # type: (int, int, int) - c2 += (c1 & 1) << 16 # 17 bits wide - c3 += (c2 & 3) << 8 # 10 bits wide - encoded += bytes([_b32tab[c1 >> 11], # bits 1 - 5 - _b32tab[(c1 >> 6) & 0x1f], # bits 6 - 10 - _b32tab[(c1 >> 1) & 0x1f], # bits 11 - 15 - _b32tab[c2 >> 12], # bits 16 - 20 (1 - 5) - _b32tab[(c2 >> 7) & 0x1f], # bits 21 - 25 (6 - 10) - _b32tab[(c2 >> 2) & 0x1f], # bits 26 - 30 (11 - 15) - _b32tab[c3 >> 5], # bits 31 - 35 (1 - 5) - _b32tab[c3 & 0x1f], # bits 36 - 40 (1 - 5) - ]) - # Adjust for any leftover partial quanta - if leftover == 1: - return encoded[:-6] + b'======' - elif leftover == 2: - return encoded[:-4] + b'====' - elif leftover == 3: - return encoded[:-3] + b'===' - elif leftover == 4: - return encoded[:-1] + b'=' - return encoded - - -def b32decode(s: bytes, casefold: bool = False, map01: bytes = None) -> bytes: - """Decode a Base32 encoded byte string. - - s is the byte string to decode. Optional casefold is a flag - specifying whether a lowercase alphabet is acceptable as input. - For security purposes, the default is False. - - RFC 3548 allows for optional mapping of the digit 0 (zero) to the - letter O (oh), and for optional mapping of the digit 1 (one) to - either the letter I (eye) or letter L (el). The optional argument - map01 when not None, specifies which letter the digit 1 should be - mapped to (when map01 is not None, the digit 0 is always mapped to - the letter O). For security purposes the default is None, so that - 0 and 1 are not allowed in the input. - - The decoded byte string is returned. binascii.Error is raised if - the input is incorrectly padded or if there are non-alphabet - characters present in the input. - """ - if not isinstance(s, bytes_types): - raise TypeError("expected bytes, not %s" % s.__class__.__name__) - quanta, leftover = divmod(len(s), 8) - if leftover: - raise binascii.Error('Incorrect padding') - # Handle section 2.4 zero and one mapping. The flag map01 will be either - # False, or the character to map the digit 1 (one) to. It should be - # either L (el) or I (eye). - if map01 is not None: - if not isinstance(map01, bytes_types): - raise TypeError("expected bytes, not %s" % map01.__class__.__name__) - assert len(map01) == 1, repr(map01) - s = _translate(s, {b'0': b'O', b'1': map01}) - if casefold: - s = s.upper() - # Strip off pad characters from the right. We need to count the pad - # characters because this will tell us how many null bytes to remove from - # the end of the decoded string. - padchars = 0 - mo = re.search(b'(?P[=]*)$', s) - if mo: - padchars = len(mo.group('pad')) - if padchars > 0: - s = s[:-padchars] - # Now decode the full quanta - parts = [] # type: List[bytes] - acc = 0 - shift = 35 - for c in s: - val = _b32rev.get(c) - if val is None: - raise TypeError('Non-base32 digit found') - acc += _b32rev[c] << shift - shift -= 5 - if shift < 0: - parts.append(binascii.unhexlify(bytes('%010x' % acc, "ascii"))) - acc = 0 - shift = 35 - # Process the last, partial quanta - last = binascii.unhexlify(bytes('%010x' % acc, "ascii")) - if padchars == 0: - last = b'' # No characters - elif padchars == 1: - last = last[:-1] - elif padchars == 3: - last = last[:-2] - elif padchars == 4: - last = last[:-3] - elif padchars == 6: - last = last[:-4] - else: - raise binascii.Error('Incorrect padding') - parts.append(last) - return b''.join(parts) - - - -# RFC 3548, Base 16 Alphabet specifies uppercase, but hexlify() returns -# lowercase. The RFC also recommends against accepting input case -# insensitively. -def b16encode(s: bytes) -> bytes: - """Encode a byte string using Base16. - - s is the byte string to encode. The encoded byte string is returned. - """ - if not isinstance(s, bytes_types): - raise TypeError("expected bytes, not %s" % s.__class__.__name__) - return binascii.hexlify(s).upper() - - -def b16decode(s: bytes, casefold: bool = False) -> bytes: - """Decode a Base16 encoded byte string. - - s is the byte string to decode. Optional casefold is a flag - specifying whether a lowercase alphabet is acceptable as input. - For security purposes, the default is False. - - The decoded byte string is returned. binascii.Error is raised if - s were incorrectly padded or if there are non-alphabet characters - present in the string. - """ - if not isinstance(s, bytes_types): - raise TypeError("expected bytes, not %s" % s.__class__.__name__) - if casefold: - s = s.upper() - if re.search(b'[^0-9A-F]', s): - raise binascii.Error('Non-base16 digit found') - return binascii.unhexlify(s) - - - -# Legacy interface. This code could be cleaned up since I don't believe -# binascii has any line length limitations. It just doesn't seem worth it -# though. The files should be opened in binary mode. - -MAXLINESIZE = 76 # Excluding the CRLF -MAXBINSIZE = (MAXLINESIZE//4)*3 - -def encode(input: IO[bytes], output: IO[bytes]) -> None: - """Encode a file; input and output are binary files.""" - while True: - s = input.read(MAXBINSIZE) - if not s: - break - while len(s) < MAXBINSIZE: - ns = input.read(MAXBINSIZE-len(s)) - if not ns: - break - s += ns - line = binascii.b2a_base64(s) - output.write(line) - - -def decode(input: IO[bytes], output: IO[bytes]) -> None: - """Decode a file; input and output are binary files.""" - while True: - line = input.readline() - if not line: - break - s = binascii.a2b_base64(line) - output.write(s) - - -def encodebytes(s: bytes) -> bytes: - """Encode a bytestring into a bytestring containing multiple lines - of base-64 data.""" - if not isinstance(s, bytes_types): - raise TypeError("expected bytes, not %s" % s.__class__.__name__) - pieces = [] # type: List[bytes] - for i in range(0, len(s), MAXBINSIZE): - chunk = s[i : i + MAXBINSIZE] - pieces.append(binascii.b2a_base64(chunk)) - return b"".join(pieces) - -def encodestring(s: bytes) -> bytes: - """Legacy alias of encodebytes().""" - import warnings - warnings.warn("encodestring() is a deprecated alias, use encodebytes()", - DeprecationWarning, 2) - return encodebytes(s) - - -def decodebytes(s: bytes) -> bytes: - """Decode a bytestring of base-64 data into a bytestring.""" - if not isinstance(s, bytes_types): - raise TypeError("expected bytes, not %s" % s.__class__.__name__) - return binascii.a2b_base64(s) - -def decodestring(s: bytes) -> bytes: - """Legacy alias of decodebytes().""" - import warnings - warnings.warn("decodestring() is a deprecated alias, use decodebytes()", - DeprecationWarning, 2) - return decodebytes(s) - - -# Usable as a script... -def main() -> None: - """Small main program""" - import sys, getopt - try: - opts, args = getopt.getopt(sys.argv[1:], 'deut') - except getopt.error as msg: - sys.stdout = sys.stderr - print(msg) - print("""usage: %s [-d|-e|-u|-t] [file|-] - -d, -u: decode - -e: encode (default) - -t: encode and decode string 'Aladdin:open sesame'"""%sys.argv[0]) - sys.exit(2) - func = encode - for o, a in opts: - if o == '-e': func = encode - if o == '-d': func = decode - if o == '-u': func = decode - if o == '-t': test(); return - if args and args[0] != '-': - with open(args[0], 'rb') as f: - func(f, sys.stdout.buffer) - else: - func(sys.stdin.buffer, sys.stdout.buffer) - - -def test() -> None: - s0 = b"Aladdin:open sesame" - print(repr(s0)) - s1 = encodebytes(s0) - print(repr(s1)) - s2 = decodebytes(s1) - print(repr(s2)) - assert s0 == s2 - - -if __name__ == '__main__': - main() diff --git a/test-data/stdlib-samples/3.2/fnmatch.py b/test-data/stdlib-samples/3.2/fnmatch.py deleted file mode 100644 index 3dccb0ce65fcd..0000000000000 --- a/test-data/stdlib-samples/3.2/fnmatch.py +++ /dev/null @@ -1,112 +0,0 @@ -"""Filename matching with shell patterns. - -fnmatch(FILENAME, PATTERN) matches according to the local convention. -fnmatchcase(FILENAME, PATTERN) always takes case in account. - -The functions operate by translating the pattern into a regular -expression. They cache the compiled regular expressions for speed. - -The function translate(PATTERN) returns a regular expression -corresponding to PATTERN. (It does not compile it.) -""" -import os -import posixpath -import re -import functools - -from typing import Iterable, List, AnyStr, Any, Callable, Match - -__all__ = ["filter", "fnmatch", "fnmatchcase", "translate"] - -def fnmatch(name: AnyStr, pat: AnyStr) -> bool: - """Test whether FILENAME matches PATTERN. - - Patterns are Unix shell style: - - * matches everything - ? matches any single character - [seq] matches any character in seq - [!seq] matches any char not in seq - - An initial period in FILENAME is not special. - Both FILENAME and PATTERN are first case-normalized - if the operating system requires it. - If you don't want this, use fnmatchcase(FILENAME, PATTERN). - """ - name = os.path.normcase(name) - pat = os.path.normcase(pat) - return fnmatchcase(name, pat) - -@functools.lru_cache(maxsize=250) -def _compile_pattern(pat: AnyStr, - is_bytes: bool = False) -> Callable[[AnyStr], - Match[AnyStr]]: - if isinstance(pat, bytes): - pat_str = str(pat, 'ISO-8859-1') - res_str = translate(pat_str) - res = bytes(res_str, 'ISO-8859-1') - else: - res = translate(pat) - return re.compile(res).match - -def filter(names: Iterable[AnyStr], pat: AnyStr) -> List[AnyStr]: - """Return the subset of the list NAMES that match PAT.""" - result = [] # type: List[AnyStr] - pat = os.path.normcase(pat) - match = _compile_pattern(pat, isinstance(pat, bytes)) - if os.path is posixpath: - # normcase on posix is NOP. Optimize it away from the loop. - for name in names: - if match(name): - result.append(name) - else: - for name in names: - if match(os.path.normcase(name)): - result.append(name) - return result - -def fnmatchcase(name: AnyStr, pat: AnyStr) -> bool: - """Test whether FILENAME matches PATTERN, including case. - - This is a version of fnmatch() which doesn't case-normalize - its arguments. - """ - match = _compile_pattern(pat, isinstance(pat, bytes)) - return match(name) is not None - -def translate(pat: str) -> str: - """Translate a shell PATTERN to a regular expression. - - There is no way to quote meta-characters. - """ - - i, n = 0, len(pat) - res = '' - while i < n: - c = pat[i] - i = i+1 - if c == '*': - res = res + '.*' - elif c == '?': - res = res + '.' - elif c == '[': - j = i - if j < n and pat[j] == '!': - j = j+1 - if j < n and pat[j] == ']': - j = j+1 - while j < n and pat[j] != ']': - j = j+1 - if j >= n: - res = res + '\\[' - else: - stuff = pat[i:j].replace('\\','\\\\') - i = j+1 - if stuff[0] == '!': - stuff = '^' + stuff[1:] - elif stuff[0] == '^': - stuff = '\\' + stuff - res = '%s[%s]' % (res, stuff) - else: - res = res + re.escape(c) - return res + r'\Z(?ms)' diff --git a/test-data/stdlib-samples/3.2/genericpath.py b/test-data/stdlib-samples/3.2/genericpath.py deleted file mode 100644 index bd1fddf750bf0..0000000000000 --- a/test-data/stdlib-samples/3.2/genericpath.py +++ /dev/null @@ -1,112 +0,0 @@ -""" -Path operations common to more than one OS -Do not use directly. The OS specific modules import the appropriate -functions from this module themselves. -""" -import os -import stat - -from typing import ( - Any as Any_, List as List_, AnyStr as AnyStr_, Tuple as Tuple_ -) - -__all__ = ['commonprefix', 'exists', 'getatime', 'getctime', 'getmtime', - 'getsize', 'isdir', 'isfile'] - - -# Does a path exist? -# This is false for dangling symbolic links on systems that support them. -def exists(path: AnyStr_) -> bool: - """Test whether a path exists. Returns False for broken symbolic links""" - try: - os.stat(path) - except os.error: - return False - return True - - -# This follows symbolic links, so both islink() and isdir() can be true -# for the same path ono systems that support symlinks -def isfile(path: AnyStr_) -> bool: - """Test whether a path is a regular file""" - try: - st = os.stat(path) - except os.error: - return False - return stat.S_ISREG(st.st_mode) - - -# Is a path a directory? -# This follows symbolic links, so both islink() and isdir() -# can be true for the same path on systems that support symlinks -def isdir(s: AnyStr_) -> bool: - """Return true if the pathname refers to an existing directory.""" - try: - st = os.stat(s) - except os.error: - return False - return stat.S_ISDIR(st.st_mode) - - -def getsize(filename: AnyStr_) -> int: - """Return the size of a file, reported by os.stat().""" - return os.stat(filename).st_size - - -def getmtime(filename: AnyStr_) -> float: - """Return the last modification time of a file, reported by os.stat().""" - return os.stat(filename).st_mtime - - -def getatime(filename: AnyStr_) -> float: - """Return the last access time of a file, reported by os.stat().""" - return os.stat(filename).st_atime - - -def getctime(filename: AnyStr_) -> float: - """Return the metadata change time of a file, reported by os.stat().""" - return os.stat(filename).st_ctime - - -# Return the longest prefix of all list elements. -def commonprefix(m: List_[Any_]) -> Any_: - "Given a list of pathnames, returns the longest common leading component" - if not m: return '' - s1 = min(m) - s2 = max(m) - for i, c in enumerate(s1): - if c != s2[i]: - return s1[:i] - return s1 - - -# Split a path in root and extension. -# The extension is everything starting at the last dot in the last -# pathname component; the root is everything before that. -# It is always true that root + ext == p. - -# Generic implementation of splitext, to be parametrized with -# the separators -def _splitext(p: AnyStr_, sep: AnyStr_, altsep: AnyStr_, - extsep: AnyStr_) -> Tuple_[AnyStr_, AnyStr_]: - """Split the extension from a pathname. - - Extension is everything from the last dot to the end, ignoring - leading dots. Returns "(root, ext)"; ext may be empty.""" - # NOTE: This code must work for text and bytes strings. - - sepIndex = p.rfind(sep) - if altsep: - altsepIndex = p.rfind(altsep) - sepIndex = max(sepIndex, altsepIndex) - - dotIndex = p.rfind(extsep) - if dotIndex > sepIndex: - # skip all leading dots - filenameIndex = sepIndex + 1 - while filenameIndex < dotIndex: - if p[filenameIndex:filenameIndex+1] != extsep: - return p[:dotIndex], p[dotIndex:] - filenameIndex += 1 - - return p, p[:0] diff --git a/test-data/stdlib-samples/3.2/getopt.py b/test-data/stdlib-samples/3.2/getopt.py deleted file mode 100644 index 32f5bcec74209..0000000000000 --- a/test-data/stdlib-samples/3.2/getopt.py +++ /dev/null @@ -1,220 +0,0 @@ -"""Parser for command line options. - -This module helps scripts to parse the command line arguments in -sys.argv. It supports the same conventions as the Unix getopt() -function (including the special meanings of arguments of the form `-' -and `--'). Long options similar to those supported by GNU software -may be used as well via an optional third argument. This module -provides two functions and an exception: - -getopt() -- Parse command line options -gnu_getopt() -- Like getopt(), but allow option and non-option arguments -to be intermixed. -GetoptError -- exception (class) raised with 'opt' attribute, which is the -option involved with the exception. -""" - -# Long option support added by Lars Wirzenius . -# -# Gerrit Holl moved the string-based exceptions -# to class-based exceptions. -# -# Peter Åstrand added gnu_getopt(). -# -# TODO for gnu_getopt(): -# -# - GNU getopt_long_only mechanism -# - allow the caller to specify ordering -# - RETURN_IN_ORDER option -# - GNU extension with '-' as first character of option string -# - optional arguments, specified by double colons -# - a option string with a W followed by semicolon should -# treat "-W foo" as "--foo" - -__all__ = ["GetoptError","error","getopt","gnu_getopt"] - -import os - -from typing import List, Tuple, Iterable - -class GetoptError(Exception): - opt = '' - msg = '' - def __init__(self, msg: str, opt: str = '') -> None: - self.msg = msg - self.opt = opt - Exception.__init__(self, msg, opt) - - def __str__(self) -> str: - return self.msg - -error = GetoptError # backward compatibility - -def getopt(args: List[str], shortopts: str, - longopts: Iterable[str] = []) -> Tuple[List[Tuple[str, str]], - List[str]]: - """getopt(args, options[, long_options]) -> opts, args - - Parses command line options and parameter list. args is the - argument list to be parsed, without the leading reference to the - running program. Typically, this means "sys.argv[1:]". shortopts - is the string of option letters that the script wants to - recognize, with options that require an argument followed by a - colon (i.e., the same format that Unix getopt() uses). If - specified, longopts is a list of strings with the names of the - long options which should be supported. The leading '--' - characters should not be included in the option name. Options - which require an argument should be followed by an equal sign - ('='). - - The return value consists of two elements: the first is a list of - (option, value) pairs; the second is the list of program arguments - left after the option list was stripped (this is a trailing slice - of the first argument). Each option-and-value pair returned has - the option as its first element, prefixed with a hyphen (e.g., - '-x'), and the option argument as its second element, or an empty - string if the option has no argument. The options occur in the - list in the same order in which they were found, thus allowing - multiple occurrences. Long and short options may be mixed. - - """ - - opts = [] # type: List[Tuple[str, str]] - if isinstance(longopts, str): - longopts = [longopts] - else: - longopts = list(longopts) - while args and args[0].startswith('-') and args[0] != '-': - if args[0] == '--': - args = args[1:] - break - if args[0].startswith('--'): - opts, args = do_longs(opts, args[0][2:], longopts, args[1:]) - else: - opts, args = do_shorts(opts, args[0][1:], shortopts, args[1:]) - - return opts, args - -def gnu_getopt(args: List[str], shortopts: str, - longopts: Iterable[str] = []) -> Tuple[List[Tuple[str, str]], - List[str]]: - """getopt(args, options[, long_options]) -> opts, args - - This function works like getopt(), except that GNU style scanning - mode is used by default. This means that option and non-option - arguments may be intermixed. The getopt() function stops - processing options as soon as a non-option argument is - encountered. - - If the first character of the option string is `+', or if the - environment variable POSIXLY_CORRECT is set, then option - processing stops as soon as a non-option argument is encountered. - - """ - - opts = [] # type: List[Tuple[str, str]] - prog_args = [] # type: List[str] - if isinstance(longopts, str): - longopts = [longopts] - else: - longopts = list(longopts) - - # Allow options after non-option arguments? - if shortopts.startswith('+'): - shortopts = shortopts[1:] - all_options_first = True - elif os.environ.get("POSIXLY_CORRECT"): - all_options_first = True - else: - all_options_first = False - - while args: - if args[0] == '--': - prog_args += args[1:] - break - - if args[0][:2] == '--': - opts, args = do_longs(opts, args[0][2:], longopts, args[1:]) - elif args[0][:1] == '-' and args[0] != '-': - opts, args = do_shorts(opts, args[0][1:], shortopts, args[1:]) - else: - if all_options_first: - prog_args += args - break - else: - prog_args.append(args[0]) - args = args[1:] - - return opts, prog_args - -def do_longs(opts: List[Tuple[str, str]], opt: str, - longopts: List[str], - args: List[str]) -> Tuple[List[Tuple[str, str]], List[str]]: - try: - i = opt.index('=') - except ValueError: - optarg = None # type: str - else: - opt, optarg = opt[:i], opt[i+1:] - - has_arg, opt = long_has_args(opt, longopts) - if has_arg: - if optarg is None: - if not args: - raise GetoptError('option --%s requires argument' % opt, opt) - optarg, args = args[0], args[1:] - elif optarg is not None: - raise GetoptError('option --%s must not have an argument' % opt, opt) - opts.append(('--' + opt, optarg or '')) - return opts, args - -# Return: -# has_arg? -# full option name -def long_has_args(opt: str, longopts: List[str]) -> Tuple[bool, str]: - possibilities = [o for o in longopts if o.startswith(opt)] - if not possibilities: - raise GetoptError('option --%s not recognized' % opt, opt) - # Is there an exact match? - if opt in possibilities: - return False, opt - elif opt + '=' in possibilities: - return True, opt - # No exact match, so better be unique. - if len(possibilities) > 1: - # XXX since possibilities contains all valid continuations, might be - # nice to work them into the error msg - raise GetoptError('option --%s not a unique prefix' % opt, opt) - assert len(possibilities) == 1 - unique_match = possibilities[0] - has_arg = unique_match.endswith('=') - if has_arg: - unique_match = unique_match[:-1] - return has_arg, unique_match - -def do_shorts(opts: List[Tuple[str, str]], optstring: str, - shortopts: str, args: List[str]) -> Tuple[List[Tuple[str, str]], - List[str]]: - while optstring != '': - opt, optstring = optstring[0], optstring[1:] - if short_has_arg(opt, shortopts): - if optstring == '': - if not args: - raise GetoptError('option -%s requires argument' % opt, - opt) - optstring, args = args[0], args[1:] - optarg, optstring = optstring, '' - else: - optarg = '' - opts.append(('-' + opt, optarg)) - return opts, args - -def short_has_arg(opt: str, shortopts: str) -> bool: - for i in range(len(shortopts)): - if opt == shortopts[i] != ':': - return shortopts.startswith(':', i+1) - raise GetoptError('option -%s not recognized' % opt, opt) - -if __name__ == '__main__': - import sys - print(getopt(sys.argv[1:], "a:b", ["alpha=", "beta"])) diff --git a/test-data/stdlib-samples/3.2/glob.py b/test-data/stdlib-samples/3.2/glob.py deleted file mode 100644 index 0f3d5f5d9a096..0000000000000 --- a/test-data/stdlib-samples/3.2/glob.py +++ /dev/null @@ -1,84 +0,0 @@ -"""Filename globbing utility.""" - -import os -import re -import fnmatch - -from typing import List, Iterator, Iterable, Any, AnyStr - -__all__ = ["glob", "iglob"] - -def glob(pathname: AnyStr) -> List[AnyStr]: - """Return a list of paths matching a pathname pattern. - - The pattern may contain simple shell-style wildcards a la fnmatch. - - """ - return list(iglob(pathname)) - -def iglob(pathname: AnyStr) -> Iterator[AnyStr]: - """Return an iterator which yields the paths matching a pathname pattern. - - The pattern may contain simple shell-style wildcards a la fnmatch. - - """ - if not has_magic(pathname): - if os.path.lexists(pathname): - yield pathname - return - dirname, basename = os.path.split(pathname) - if not dirname: - for name in glob1(None, basename): - yield name - return - if has_magic(dirname): - dirs = iglob(dirname) # type: Iterable[AnyStr] - else: - dirs = [dirname] - if has_magic(basename): - glob_in_dir = glob1 # type: Any - else: - glob_in_dir = glob0 - for dirname in dirs: - for name in glob_in_dir(dirname, basename): - yield os.path.join(dirname, name) - -# These 2 helper functions non-recursively glob inside a literal directory. -# They return a list of basenames. `glob1` accepts a pattern while `glob0` -# takes a literal basename (so it only has to check for its existence). - -def glob1(dirname: AnyStr, pattern: AnyStr) -> List[AnyStr]: - if not dirname: - if isinstance(pattern, bytes): - dirname = bytes(os.curdir, 'ASCII') - else: - dirname = os.curdir - try: - names = os.listdir(dirname) - except os.error: - return [] - if pattern[0] != '.': - names = [x for x in names if x[0] != '.'] - return fnmatch.filter(names, pattern) - -def glob0(dirname: AnyStr, basename: AnyStr) -> List[AnyStr]: - if basename == '': - # `os.path.split()` returns an empty basename for paths ending with a - # directory separator. 'q*x/' should match only directories. - if os.path.isdir(dirname): - return [basename] - else: - if os.path.lexists(os.path.join(dirname, basename)): - return [basename] - return [] - - -magic_check = re.compile('[*?[]') -magic_check_bytes = re.compile(b'[*?[]') - -def has_magic(s: AnyStr) -> bool: - if isinstance(s, bytes): - match = magic_check_bytes.search(s) - else: - match = magic_check.search(s) - return match is not None diff --git a/test-data/stdlib-samples/3.2/posixpath.py b/test-data/stdlib-samples/3.2/posixpath.py deleted file mode 100644 index cf5d59e6a69a5..0000000000000 --- a/test-data/stdlib-samples/3.2/posixpath.py +++ /dev/null @@ -1,466 +0,0 @@ -"""Common operations on Posix pathnames. - -Instead of importing this module directly, import os and refer to -this module as os.path. The "os.path" name is an alias for this -module on Posix systems; on other systems (e.g. Mac, Windows), -os.path provides the same operations in a manner specific to that -platform, and is an alias to another module (e.g. macpath, ntpath). - -Some of this can actually be useful on non-Posix systems too, e.g. -for manipulation of the pathname component of URLs. -""" - -import os -import sys -import stat -import genericpath -from genericpath import * - -from typing import ( - Tuple, BinaryIO, TextIO, Pattern, AnyStr, List, Set, Any, Union, cast -) - -__all__ = ["normcase","isabs","join","splitdrive","split","splitext", - "basename","dirname","commonprefix","getsize","getmtime", - "getatime","getctime","islink","exists","lexists","isdir","isfile", - "ismount", "expanduser","expandvars","normpath","abspath", - "samefile","sameopenfile","samestat", - "curdir","pardir","sep","pathsep","defpath","altsep","extsep", - "devnull","realpath","supports_unicode_filenames","relpath"] - -# Strings representing various path-related bits and pieces. -# These are primarily for export; internally, they are hardcoded. -curdir = '.' -pardir = '..' -extsep = '.' -sep = '/' -pathsep = ':' -defpath = ':/bin:/usr/bin' -altsep = None # type: str -devnull = '/dev/null' - -def _get_sep(path: AnyStr) -> AnyStr: - if isinstance(path, bytes): - return b'/' - else: - return '/' - -# Normalize the case of a pathname. Trivial in Posix, string.lower on Mac. -# On MS-DOS this may also turn slashes into backslashes; however, other -# normalizations (such as optimizing '../' away) are not allowed -# (another function should be defined to do that). - -def normcase(s: AnyStr) -> AnyStr: - """Normalize case of pathname. Has no effect under Posix""" - # TODO: on Mac OS X, this should really return s.lower(). - if not isinstance(s, (bytes, str)): - raise TypeError("normcase() argument must be str or bytes, " - "not '{}'".format(s.__class__.__name__)) - return cast(AnyStr, s) - - -# Return whether a path is absolute. -# Trivial in Posix, harder on the Mac or MS-DOS. - -def isabs(s: AnyStr) -> bool: - """Test whether a path is absolute""" - sep = _get_sep(s) - return s.startswith(sep) - - -# Join pathnames. -# Ignore the previous parts if a part is absolute. -# Insert a '/' unless the first part is empty or already ends in '/'. - -def join(a: AnyStr, *p: AnyStr) -> AnyStr: - """Join two or more pathname components, inserting '/' as needed. - If any component is an absolute path, all previous path components - will be discarded.""" - sep = _get_sep(a) - path = a - for b in p: - if b.startswith(sep): - path = b - elif not path or path.endswith(sep): - path += b - else: - path += sep + b - return path - - -# Split a path in head (everything up to the last '/') and tail (the -# rest). If the path ends in '/', tail will be empty. If there is no -# '/' in the path, head will be empty. -# Trailing '/'es are stripped from head unless it is the root. - -def split(p: AnyStr) -> Tuple[AnyStr, AnyStr]: - """Split a pathname. Returns tuple "(head, tail)" where "tail" is - everything after the final slash. Either part may be empty.""" - sep = _get_sep(p) - i = p.rfind(sep) + 1 - head, tail = p[:i], p[i:] - if head and head != sep*len(head): - head = head.rstrip(sep) - return head, tail - - -# Split a path in root and extension. -# The extension is everything starting at the last dot in the last -# pathname component; the root is everything before that. -# It is always true that root + ext == p. - -def splitext(p: AnyStr) -> Tuple[AnyStr, AnyStr]: - if isinstance(p, bytes): - sep = b'/' - extsep = b'.' - else: - sep = '/' - extsep = '.' - return genericpath._splitext(p, sep, None, extsep) -splitext.__doc__ = genericpath._splitext.__doc__ - -# Split a pathname into a drive specification and the rest of the -# path. Useful on DOS/Windows/NT; on Unix, the drive is always empty. - -def splitdrive(p: AnyStr) -> Tuple[AnyStr, AnyStr]: - """Split a pathname into drive and path. On Posix, drive is always - empty.""" - return p[:0], p - - -# Return the tail (basename) part of a path, same as split(path)[1]. - -def basename(p: AnyStr) -> AnyStr: - """Returns the final component of a pathname""" - sep = _get_sep(p) - i = p.rfind(sep) + 1 - return p[i:] - - -# Return the head (dirname) part of a path, same as split(path)[0]. - -def dirname(p: AnyStr) -> AnyStr: - """Returns the directory component of a pathname""" - sep = _get_sep(p) - i = p.rfind(sep) + 1 - head = p[:i] - if head and head != sep*len(head): - head = head.rstrip(sep) - return head - - -# Is a path a symbolic link? -# This will always return false on systems where os.lstat doesn't exist. - -def islink(path: AnyStr) -> bool: - """Test whether a path is a symbolic link""" - try: - st = os.lstat(path) - except (os.error, AttributeError): - return False - return stat.S_ISLNK(st.st_mode) - -# Being true for dangling symbolic links is also useful. - -def lexists(path: AnyStr) -> bool: - """Test whether a path exists. Returns True for broken symbolic links""" - try: - os.lstat(path) - except os.error: - return False - return True - - -# Are two filenames really pointing to the same file? - -def samefile(f1: AnyStr, f2: AnyStr) -> bool: - """Test whether two pathnames reference the same actual file""" - s1 = os.stat(f1) - s2 = os.stat(f2) - return samestat(s1, s2) - - -# Are two open files really referencing the same file? -# (Not necessarily the same file descriptor!) - -def sameopenfile(fp1: int, fp2: int) -> bool: - """Test whether two open file objects reference the same file""" - s1 = os.fstat(fp1) - s2 = os.fstat(fp2) - return samestat(s1, s2) - - -# Are two stat buffers (obtained from stat, fstat or lstat) -# describing the same file? - -def samestat(s1: os.stat_result, s2: os.stat_result) -> bool: - """Test whether two stat buffers reference the same file""" - return s1.st_ino == s2.st_ino and \ - s1.st_dev == s2.st_dev - - -# Is a path a mount point? -# (Does this work for all UNIXes? Is it even guaranteed to work by Posix?) - -def ismount(path: AnyStr) -> bool: - """Test whether a path is a mount point""" - if islink(path): - # A symlink can never be a mount point - return False - try: - s1 = os.lstat(path) - if isinstance(path, bytes): - parent = join(path, b'..') - else: - parent = join(path, '..') - s2 = os.lstat(parent) - except os.error: - return False # It doesn't exist -- so not a mount point :-) - dev1 = s1.st_dev - dev2 = s2.st_dev - if dev1 != dev2: - return True # path/.. on a different device as path - ino1 = s1.st_ino - ino2 = s2.st_ino - if ino1 == ino2: - return True # path/.. is the same i-node as path - return False - - -# Expand paths beginning with '~' or '~user'. -# '~' means $HOME; '~user' means that user's home directory. -# If the path doesn't begin with '~', or if the user or $HOME is unknown, -# the path is returned unchanged (leaving error reporting to whatever -# function is called with the expanded path as argument). -# See also module 'glob' for expansion of *, ? and [...] in pathnames. -# (A function should also be defined to do full *sh-style environment -# variable expansion.) - -def expanduser(path: AnyStr) -> AnyStr: - """Expand ~ and ~user constructions. If user or $HOME is unknown, - do nothing.""" - if isinstance(path, bytes): - tilde = b'~' - else: - tilde = '~' - if not path.startswith(tilde): - return path - sep = _get_sep(path) - i = path.find(sep, 1) - if i < 0: - i = len(path) - if i == 1: - userhome = None # type: Union[str, bytes] - if 'HOME' not in os.environ: - import pwd - userhome = pwd.getpwuid(os.getuid()).pw_dir - else: - userhome = os.environ['HOME'] - else: - import pwd - name = path[1:i] # type: Union[str, bytes] - if isinstance(name, bytes): - name = str(name, 'ASCII') - try: - pwent = pwd.getpwnam(name) - except KeyError: - return path - userhome = pwent.pw_dir - if isinstance(path, bytes): - userhome = os.fsencode(userhome) - root = b'/' - else: - root = '/' - userhome = userhome.rstrip(root) - return (userhome + path[i:]) or root - - -# Expand paths containing shell variable substitutions. -# This expands the forms $variable and ${variable} only. -# Non-existent variables are left unchanged. - -_varprog = None # type: Pattern[str] -_varprogb = None # type: Pattern[bytes] - -def expandvars(path: AnyStr) -> AnyStr: - """Expand shell variables of form $var and ${var}. Unknown variables - are left unchanged.""" - global _varprog, _varprogb - if isinstance(path, bytes): - if b'$' not in path: - return path - if not _varprogb: - import re - _varprogb = re.compile(br'\$(\w+|\{[^}]*\})', re.ASCII) - search = _varprogb.search - start = b'{' - end = b'}' - else: - if '$' not in path: - return path - if not _varprog: - import re - _varprog = re.compile(r'\$(\w+|\{[^}]*\})', re.ASCII) - search = _varprog.search - start = '{' - end = '}' - i = 0 - while True: - m = search(path, i) - if not m: - break - i, j = m.span(0) - name = None # type: Union[str, bytes] - name = m.group(1) - if name.startswith(start) and name.endswith(end): - name = name[1:-1] - if isinstance(name, bytes): - name = str(name, 'ASCII') - if name in os.environ: - tail = path[j:] - value = None # type: Union[str, bytes] - value = os.environ[name] - if isinstance(path, bytes): - value = value.encode('ASCII') - path = path[:i] + value - i = len(path) - path += tail - else: - i = j - return path - - -# Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B. -# It should be understood that this may change the meaning of the path -# if it contains symbolic links! - -def normpath(path: AnyStr) -> AnyStr: - """Normalize path, eliminating double slashes, etc.""" - if isinstance(path, bytes): - sep = b'/' - empty = b'' - dot = b'.' - dotdot = b'..' - else: - sep = '/' - empty = '' - dot = '.' - dotdot = '..' - if path == empty: - return dot - initial_slashes = path.startswith(sep) # type: int - # POSIX allows one or two initial slashes, but treats three or more - # as single slash. - if (initial_slashes and - path.startswith(sep*2) and not path.startswith(sep*3)): - initial_slashes = 2 - comps = path.split(sep) - new_comps = [] # type: List[AnyStr] - for comp in comps: - if comp in (empty, dot): - continue - if (comp != dotdot or (not initial_slashes and not new_comps) or - (new_comps and new_comps[-1] == dotdot)): - new_comps.append(comp) - elif new_comps: - new_comps.pop() - comps = new_comps - path = sep.join(comps) - if initial_slashes: - path = sep*initial_slashes + path - return path or dot - - -def abspath(path: AnyStr) -> AnyStr: - """Return an absolute path.""" - if not isabs(path): - if isinstance(path, bytes): - cwd = os.getcwdb() - else: - cwd = os.getcwd() - path = join(cwd, path) - return normpath(path) - - -# Return a canonical path (i.e. the absolute location of a file on the -# filesystem). - -def realpath(filename: AnyStr) -> AnyStr: - """Return the canonical path of the specified filename, eliminating any -symbolic links encountered in the path.""" - if isinstance(filename, bytes): - sep = b'/' - empty = b'' - else: - sep = '/' - empty = '' - if isabs(filename): - bits = [sep] + filename.split(sep)[1:] - else: - bits = [empty] + filename.split(sep) - - for i in range(2, len(bits)+1): - component = join(*bits[0:i]) - # Resolve symbolic links. - if islink(component): - resolved = _resolve_link(component) - if resolved is None: - # Infinite loop -- return original component + rest of the path - return abspath(join(*([component] + bits[i:]))) - else: - newpath = join(*([resolved] + bits[i:])) - return realpath(newpath) - - return abspath(filename) - - -def _resolve_link(path: AnyStr) -> AnyStr: - """Internal helper function. Takes a path and follows symlinks - until we either arrive at something that isn't a symlink, or - encounter a path we've seen before (meaning that there's a loop). - """ - paths_seen = set() # type: Set[AnyStr] - while islink(path): - if path in paths_seen: - # Already seen this path, so we must have a symlink loop - return None - paths_seen.add(path) - # Resolve where the link points to - resolved = os.readlink(path) - if not isabs(resolved): - dir = dirname(path) - path = normpath(join(dir, resolved)) - else: - path = normpath(resolved) - return path - -supports_unicode_filenames = (sys.platform == 'darwin') - -def relpath(path: AnyStr, start: AnyStr = None) -> AnyStr: - """Return a relative version of a path""" - - if not path: - raise ValueError("no path specified") - - if isinstance(path, bytes): - curdir = b'.' - sep = b'/' - pardir = b'..' - else: - curdir = '.' - sep = '/' - pardir = '..' - - if start is None: - start = curdir - - start_list = [x for x in abspath(start).split(sep) if x] - path_list = [x for x in abspath(path).split(sep) if x] - - # Work out how much of the filepath is shared by start and path. - i = len(commonprefix([start_list, path_list])) - - rel_list = [pardir] * (len(start_list)-i) + path_list[i:] - if not rel_list: - return curdir - return join(*rel_list) diff --git a/test-data/stdlib-samples/3.2/pprint.py b/test-data/stdlib-samples/3.2/pprint.py deleted file mode 100644 index 650c1a3b5afe3..0000000000000 --- a/test-data/stdlib-samples/3.2/pprint.py +++ /dev/null @@ -1,380 +0,0 @@ -# Author: Fred L. Drake, Jr. -# fdrake@acm.org -# -# This is a simple little module I wrote to make life easier. I didn't -# see anything quite like it in the library, though I may have overlooked -# something. I wrote this when I was trying to read some heavily nested -# tuples with fairly non-descriptive content. This is modeled very much -# after Lisp/Scheme - style pretty-printing of lists. If you find it -# useful, thank small children who sleep at night. - -"""Support to pretty-print lists, tuples, & dictionaries recursively. - -Very simple, but useful, especially in debugging data structures. - -Classes -------- - -PrettyPrinter() - Handle pretty-printing operations onto a stream using a configured - set of formatting parameters. - -Functions ---------- - -pformat() - Format a Python object into a pretty-printed representation. - -pprint() - Pretty-print a Python object to a stream [default is sys.stdout]. - -saferepr() - Generate a 'standard' repr()-like value, but protect against recursive - data structures. - -""" - -import sys as _sys -from collections import OrderedDict as _OrderedDict -from io import StringIO as _StringIO - -from typing import Any, Tuple, Dict, TextIO, cast, List - -__all__ = ["pprint","pformat","isreadable","isrecursive","saferepr", - "PrettyPrinter"] - -# cache these for faster access: -_commajoin = ", ".join -_id = id -_len = len -_type = type - - -def pprint(object: object, stream: TextIO = None, indent: int = 1, - width: int = 80, depth: int = None) -> None: - """Pretty-print a Python object to a stream [default is sys.stdout].""" - printer = PrettyPrinter( - stream=stream, indent=indent, width=width, depth=depth) - printer.pprint(object) - -def pformat(object: object, indent: int = 1, width: int = 80, - depth: int = None) -> str: - """Format a Python object into a pretty-printed representation.""" - return PrettyPrinter(indent=indent, width=width, depth=depth).pformat(object) - -def saferepr(object: object) -> str: - """Version of repr() which can handle recursive data structures.""" - return _safe_repr(object, {}, None, 0)[0] - -def isreadable(object: object) -> bool: - """Determine if saferepr(object) is readable by eval().""" - return _safe_repr(object, {}, None, 0)[1] - -def isrecursive(object: object) -> bool: - """Determine if object requires a recursive representation.""" - return _safe_repr(object, {}, None, 0)[2] - -class _safe_key: - """Helper function for key functions when sorting unorderable objects. - - The wrapped-object will fallback to an Py2.x style comparison for - unorderable types (sorting first comparing the type name and then by - the obj ids). Does not work recursively, so dict.items() must have - _safe_key applied to both the key and the value. - - """ - - __slots__ = ['obj'] - - def __init__(self, obj: Any) -> None: - self.obj = obj - - def __lt__(self, other: Any) -> Any: - rv = self.obj.__lt__(other.obj) # type: Any - if rv is NotImplemented: - rv = (str(type(self.obj)), id(self.obj)) < \ - (str(type(other.obj)), id(other.obj)) - return rv - -def _safe_tuple(t: Tuple[Any, Any]) -> Tuple[_safe_key, _safe_key]: - "Helper function for comparing 2-tuples" - return _safe_key(t[0]), _safe_key(t[1]) - -class PrettyPrinter: - def __init__(self, indent: int = 1, width: int = 80, depth: int = None, - stream: TextIO = None) -> None: - """Handle pretty printing operations onto a stream using a set of - configured parameters. - - indent - Number of spaces to indent for each level of nesting. - - width - Attempted maximum number of columns in the output. - - depth - The maximum depth to print out nested structures. - - stream - The desired output stream. If omitted (or false), the standard - output stream available at construction will be used. - - """ - indent = int(indent) - width = int(width) - assert indent >= 0, "indent must be >= 0" - assert depth is None or depth > 0, "depth must be > 0" - assert width, "width must be != 0" - self._depth = depth - self._indent_per_level = indent - self._width = width - if stream is not None: - self._stream = stream - else: - self._stream = _sys.stdout - - def pprint(self, object: object) -> None: - self._format(object, self._stream, 0, 0, {}, 0) - self._stream.write("\n") - - def pformat(self, object: object) -> str: - sio = _StringIO() - self._format(object, sio, 0, 0, {}, 0) - return sio.getvalue() - - def isrecursive(self, object: object) -> int: - return self.format(object, {}, 0, 0)[2] - - def isreadable(self, object: object) -> int: - s, readable, recursive = self.format(object, {}, 0, 0) - return readable and not recursive - - def _format(self, object: object, stream: TextIO, indent: int, - allowance: int, context: Dict[int, int], level: int) -> None: - level = level + 1 - objid = _id(object) - if objid in context: - stream.write(_recursion(object)) - self._recursive = True - self._readable = False - return - rep = self._repr(object, context, level - 1) - typ = _type(object) - sepLines = _len(rep) > (self._width - 1 - indent - allowance) - write = stream.write - - if self._depth and level > self._depth: - write(rep) - return - - if sepLines: - r = getattr(typ, "__repr__", None) - if isinstance(object, dict): - write('{') - if self._indent_per_level > 1: - write((self._indent_per_level - 1) * ' ') - length = _len(object) - if length: - context[objid] = 1 - indent = indent + self._indent_per_level - if issubclass(typ, _OrderedDict): - items = list(object.items()) - else: - items = sorted(object.items(), key=_safe_tuple) - key, ent = items[0] - rep = self._repr(key, context, level) - write(rep) - write(': ') - self._format(ent, stream, indent + _len(rep) + 2, - allowance + 1, context, level) - if length > 1: - for key, ent in items[1:]: - rep = self._repr(key, context, level) - write(',\n%s%s: ' % (' '*indent, rep)) - self._format(ent, stream, indent + _len(rep) + 2, - allowance + 1, context, level) - indent = indent - self._indent_per_level - del context[objid] - write('}') - return - - if ((issubclass(typ, list) and r is list.__repr__) or - (issubclass(typ, tuple) and r is tuple.__repr__) or - (issubclass(typ, set) and r is set.__repr__) or - (issubclass(typ, frozenset) and r is frozenset.__repr__) - ): - anyobj = cast(Any, object) # TODO Collection? - length = _len(anyobj) - if issubclass(typ, list): - write('[') - endchar = ']' - lst = anyobj - elif issubclass(typ, set): - if not length: - write('set()') - return - write('{') - endchar = '}' - lst = sorted(anyobj, key=_safe_key) - elif issubclass(typ, frozenset): - if not length: - write('frozenset()') - return - write('frozenset({') - endchar = '})' - lst = sorted(anyobj, key=_safe_key) - indent += 10 - else: - write('(') - endchar = ')' - lst = list(anyobj) - if self._indent_per_level > 1: - write((self._indent_per_level - 1) * ' ') - if length: - context[objid] = 1 - indent = indent + self._indent_per_level - self._format(lst[0], stream, indent, allowance + 1, - context, level) - if length > 1: - for ent in lst[1:]: - write(',\n' + ' '*indent) - self._format(ent, stream, indent, - allowance + 1, context, level) - indent = indent - self._indent_per_level - del context[objid] - if issubclass(typ, tuple) and length == 1: - write(',') - write(endchar) - return - - write(rep) - - def _repr(self, object: object, context: Dict[int, int], - level: int) -> str: - repr, readable, recursive = self.format(object, context.copy(), - self._depth, level) - if not readable: - self._readable = False - if recursive: - self._recursive = True - return repr - - def format(self, object: object, context: Dict[int, int], - maxlevels: int, level: int) -> Tuple[str, int, int]: - """Format object for a specific context, returning a string - and flags indicating whether the representation is 'readable' - and whether the object represents a recursive construct. - """ - return _safe_repr(object, context, maxlevels, level) - - -# Return triple (repr_string, isreadable, isrecursive). - -def _safe_repr(object: object, context: Dict[int, int], - maxlevels: int, level: int) -> Tuple[str, bool, bool]: - typ = _type(object) - if typ is str: - s = cast(str, object) - if 'locale' not in _sys.modules: - return repr(object), True, False - if "'" in s and '"' not in s: - closure = '"' - quotes = {'"': '\\"'} - else: - closure = "'" - quotes = {"'": "\\'"} - qget = quotes.get - sio = _StringIO() - write = sio.write - for char in s: - if char.isalpha(): - write(char) - else: - write(qget(char, repr(char)[1:-1])) - return ("%s%s%s" % (closure, sio.getvalue(), closure)), True, False - - r = getattr(typ, "__repr__", None) - if issubclass(typ, dict) and r is dict.__repr__: - if not object: - return "{}", True, False - objid = _id(object) - if maxlevels and level >= maxlevels: - return "{...}", False, objid in context - if objid in context: - return _recursion(object), False, True - context[objid] = 1 - readable = True - recursive = False - components = [] # type: List[str] - append = components.append - level += 1 - saferepr = _safe_repr - items = sorted((cast(dict, object)).items(), key=_safe_tuple) - for k, v in items: - krepr, kreadable, krecur = saferepr(k, context, maxlevels, level) - vrepr, vreadable, vrecur = saferepr(v, context, maxlevels, level) - append("%s: %s" % (krepr, vrepr)) - readable = readable and kreadable and vreadable - if krecur or vrecur: - recursive = True - del context[objid] - return "{%s}" % _commajoin(components), readable, recursive - - if (issubclass(typ, list) and r is list.__repr__) or \ - (issubclass(typ, tuple) and r is tuple.__repr__): - anyobj = cast(Any, object) # TODO Sequence? - if issubclass(typ, list): - if not object: - return "[]", True, False - format = "[%s]" - elif _len(anyobj) == 1: - format = "(%s,)" - else: - if not object: - return "()", True, False - format = "(%s)" - objid = _id(object) - if maxlevels and level >= maxlevels: - return format % "...", False, objid in context - if objid in context: - return _recursion(object), False, True - context[objid] = 1 - readable = True - recursive = False - components = [] - append = components.append - level += 1 - for o in anyobj: - orepr, oreadable, orecur = _safe_repr(o, context, maxlevels, level) - append(orepr) - if not oreadable: - readable = False - if orecur: - recursive = True - del context[objid] - return format % _commajoin(components), readable, recursive - - rep = repr(object) - return rep, bool(rep and not rep.startswith('<')), False - - -def _recursion(object: object) -> str: - return ("" - % (_type(object).__name__, _id(object))) - - -def _perfcheck(object: object = None) -> None: - import time - if object is None: - object = [("string", (1, 2), [3, 4], {5: 6, 7: 8})] * 100000 - p = PrettyPrinter() - t1 = time.time() - _safe_repr(object, {}, None, 0) - t2 = time.time() - p.pformat(object) - t3 = time.time() - print("_safe_repr:", t2 - t1) - print("pformat:", t3 - t2) - -if __name__ == "__main__": - _perfcheck() diff --git a/test-data/stdlib-samples/3.2/random.py b/test-data/stdlib-samples/3.2/random.py deleted file mode 100644 index 82bda03f7e53e..0000000000000 --- a/test-data/stdlib-samples/3.2/random.py +++ /dev/null @@ -1,743 +0,0 @@ -"""Random variable generators. - - integers - -------- - uniform within range - - sequences - --------- - pick random element - pick random sample - generate random permutation - - distributions on the real line: - ------------------------------ - uniform - triangular - normal (Gaussian) - lognormal - negative exponential - gamma - beta - pareto - Weibull - - distributions on the circle (angles 0 to 2pi) - --------------------------------------------- - circular uniform - von Mises - -General notes on the underlying Mersenne Twister core generator: - -* The period is 2**19937-1. -* It is one of the most extensively tested generators in existence. -* The random() method is implemented in C, executes in a single Python step, - and is, therefore, threadsafe. - -""" - -from warnings import warn as _warn -from types import MethodType as _MethodType, BuiltinMethodType as _BuiltinMethodType -from math import log as _log, exp as _exp, pi as _pi, e as _e, ceil as _ceil -from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin -from os import urandom as _urandom -from collections.abc import Set as _Set, Sequence as _Sequence -from hashlib import sha512 as _sha512 - -from typing import ( - Any, TypeVar, Iterable, Sequence, List, Callable, Set, cast, SupportsInt, Union -) - -__all__ = ["Random","seed","random","uniform","randint","choice","sample", - "randrange","shuffle","normalvariate","lognormvariate", - "expovariate","vonmisesvariate","gammavariate","triangular", - "gauss","betavariate","paretovariate","weibullvariate", - "getstate","setstate", "getrandbits", - "SystemRandom"] - -NV_MAGICCONST = 4 * _exp(-0.5)/_sqrt(2.0) -TWOPI = 2.0*_pi -LOG4 = _log(4.0) -SG_MAGICCONST = 1.0 + _log(4.5) -BPF = 53 # Number of bits in a float -RECIP_BPF = 2**-BPF # type: float - - -# Translated by Guido van Rossum from C source provided by -# Adrian Baddeley. Adapted by Raymond Hettinger for use with -# the Mersenne Twister and os.urandom() core generators. - -import _random - -T = TypeVar('T') - -class Random(_random.Random): - """Random number generator base class used by bound module functions. - - Used to instantiate instances of Random to get generators that don't - share state. - - Class Random can also be subclassed if you want to use a different basic - generator of your own devising: in that case, override the following - methods: random(), seed(), getstate(), and setstate(). - Optionally, implement a getrandbits() method so that randrange() - can cover arbitrarily large ranges. - - """ - - VERSION = 3 # used by getstate/setstate - gauss_next = 0.0 - - def __init__(self, x: object = None) -> None: - """Initialize an instance. - - Optional argument x controls seeding, as for Random.seed(). - """ - - self.seed(x) - self.gauss_next = None - - def seed(self, a: Any = None, version: int = 2) -> None: - """Initialize internal state from hashable object. - - None or no argument seeds from current time or from an operating - system specific randomness source if available. - - For version 2 (the default), all of the bits are used if *a *is a str, - bytes, or bytearray. For version 1, the hash() of *a* is used instead. - - If *a* is an int, all bits are used. - - """ - - if a is None: - try: - a = int.from_bytes(_urandom(32), 'big') - except NotImplementedError: - import time - a = int(time.time() * 256) # use fractional seconds - - if version == 2: - if isinstance(a, (str, bytes, bytearray)): - if isinstance(a, str): - a = a.encode() - a += _sha512(a).digest() - a = int.from_bytes(a, 'big') - - super().seed(a) - self.gauss_next = None - - def getstate(self) -> tuple: - """Return internal state; can be passed to setstate() later.""" - return self.VERSION, super().getstate(), self.gauss_next - - def setstate(self, state: tuple) -> None: - """Restore internal state from object returned by getstate().""" - version = state[0] - if version == 3: - version, internalstate, self.gauss_next = state - super().setstate(internalstate) - elif version == 2: - version, internalstate, self.gauss_next = state - # In version 2, the state was saved as signed ints, which causes - # inconsistencies between 32/64-bit systems. The state is - # really unsigned 32-bit ints, so we convert negative ints from - # version 2 to positive longs for version 3. - try: - internalstate = tuple(x % (2**32) for x in internalstate) - except ValueError as e: - raise TypeError() - super().setstate(internalstate) - else: - raise ValueError("state with version %s passed to " - "Random.setstate() of version %s" % - (version, self.VERSION)) - -## ---- Methods below this point do not need to be overridden when -## ---- subclassing for the purpose of using a different core generator. - -## -------------------- pickle support ------------------- - - def __getstate__(self) -> object: # for pickle - return self.getstate() - - def __setstate__(self, state: Any) -> None: # for pickle - self.setstate(state) - - def __reduce__(self) -> tuple: - return self.__class__, (), self.getstate() - -## -------------------- integer methods ------------------- - - def randrange(self, start: SupportsInt, stop: SupportsInt = None, - step: int = 1, int: Callable[[SupportsInt], - int] = int) -> int: - """Choose a random item from range(start, stop[, step]). - - This fixes the problem with randint() which includes the - endpoint; in Python this is usually not what you want. - - Do not supply the 'int' argument. - """ - - # This code is a bit messy to make it fast for the - # common case while still doing adequate error checking. - istart = int(start) - if istart != start: - raise ValueError("non-integer arg 1 for randrange()") - if stop is None: - if istart > 0: - return self._randbelow(istart) - raise ValueError("empty range for randrange()") - - # stop argument supplied. - istop = int(stop) - if istop != stop: - raise ValueError("non-integer stop for randrange()") - width = istop - istart - if step == 1 and width > 0: - return istart + self._randbelow(width) - if step == 1: - raise ValueError("empty range for randrange() (%d,%d, %d)" % (istart, istop, width)) - - # Non-unit step argument supplied. - istep = int(step) - if istep != step: - raise ValueError("non-integer step for randrange()") - if istep > 0: - n = (width + istep - 1) // istep - elif istep < 0: - n = (width + istep + 1) // istep - else: - raise ValueError("zero step for randrange()") - - if n <= 0: - raise ValueError("empty range for randrange()") - - return istart + istep*self._randbelow(n) - - def randint(self, a: int, b: int) -> int: - """Return random integer in range [a, b], including both end points. - """ - - return self.randrange(a, b+1) - - def _randbelow(self, n: int, int: Callable[[float], int] = int, - maxsize: int = 1< int: - "Return a random int in the range [0,n). Raises ValueError if n==0." - - getrandbits = self.getrandbits - # Only call self.getrandbits if the original random() builtin method - # has not been overridden or if a new getrandbits() was supplied. - if type(self.random) is BuiltinMethod or type(getrandbits) is Method: - k = n.bit_length() # don't use (n-1) here because n can be 1 - r = getrandbits(k) # 0 <= r < 2**k - while r >= n: - r = getrandbits(k) - return r - # There's an overridden random() method but no new getrandbits() method, - # so we can only use random() from here. - random = self.random - if n >= maxsize: - _warn("Underlying random() generator does not supply \n" - "enough bits to choose from a population range this large.\n" - "To remove the range limitation, add a getrandbits() method.") - return int(random() * n) - rem = maxsize % n - limit = (maxsize - rem) / maxsize # int(limit * maxsize) % n == 0 - s = random() - while s >= limit: - s = random() - return int(s*maxsize) % n - -## -------------------- sequence methods ------------------- - - def choice(self, seq: Sequence[T]) -> T: - """Choose a random element from a non-empty sequence.""" - try: - i = self._randbelow(len(seq)) - except ValueError: - raise IndexError('Cannot choose from an empty sequence') - return seq[i] - - def shuffle(self, x: List[T], - random: Callable[[], float] = None, - int: Callable[[float], int] = int) -> None: - """x, random=random.random -> shuffle list x in place; return None. - - Optional arg random is a 0-argument function returning a random - float in [0.0, 1.0); by default, the standard random.random. - """ - - randbelow = self._randbelow - for i in reversed(range(1, len(x))): - # pick an element in x[:i+1] with which to exchange x[i] - j = randbelow(i+1) if random is None else int(random() * (i+1)) - x[i], x[j] = x[j], x[i] - - def sample(self, population: Union[_Set[T], _Sequence[T]], k: int) -> List[T]: - """Chooses k unique random elements from a population sequence or set. - - Returns a new list containing elements from the population while - leaving the original population unchanged. The resulting list is - in selection order so that all sub-slices will also be valid random - samples. This allows raffle winners (the sample) to be partitioned - into grand prize and second place winners (the subslices). - - Members of the population need not be hashable or unique. If the - population contains repeats, then each occurrence is a possible - selection in the sample. - - To choose a sample in a range of integers, use range as an argument. - This is especially fast and space efficient for sampling from a - large population: sample(range(10000000), 60) - """ - - # Sampling without replacement entails tracking either potential - # selections (the pool) in a list or previous selections in a set. - - # When the number of selections is small compared to the - # population, then tracking selections is efficient, requiring - # only a small set and an occasional reselection. For - # a larger number of selections, the pool tracking method is - # preferred since the list takes less space than the - # set and it doesn't suffer from frequent reselections. - - if isinstance(population, _Set): - population = list(population) - if not isinstance(population, _Sequence): - raise TypeError("Population must be a sequence or set. For dicts, use list(d).") - randbelow = self._randbelow - n = len(population) - if not (0 <= k and k <= n): - raise ValueError("Sample larger than population") - result = [cast(T, None)] * k - setsize = 21 # size of a small set minus size of an empty list - if k > 5: - setsize += 4 ** _ceil(_log(k * 3, 4)) # table size for big sets - if n <= setsize: - # An n-length list is smaller than a k-length set - pool = list(population) - for i in range(k): # invariant: non-selected at [0,n-i) - j = randbelow(n-i) - result[i] = pool[j] - pool[j] = pool[n-i-1] # move non-selected item into vacancy - else: - selected = set() # type: Set[int] - selected_add = selected.add - for i in range(k): - j = randbelow(n) - while j in selected: - j = randbelow(n) - selected_add(j) - result[i] = population[j] - return result - -## -------------------- real-valued distributions ------------------- - -## -------------------- uniform distribution ------------------- - - def uniform(self, a: float, b: float) -> float: - "Get a random number in the range [a, b) or [a, b] depending on rounding." - return a + (b-a) * self.random() - -## -------------------- triangular -------------------- - - def triangular(self, low: float = 0.0, high: float = 1.0, - mode: float = None) -> float: - """Triangular distribution. - - Continuous distribution bounded by given lower and upper limits, - and having a given mode value in-between. - - http://en.wikipedia.org/wiki/Triangular_distribution - - """ - u = self.random() - c = 0.5 if mode is None else (mode - low) / (high - low) - if u > c: - u = 1.0 - u - c = 1.0 - c - low, high = high, low - return low + (high - low) * (u * c) ** 0.5 - -## -------------------- normal distribution -------------------- - - def normalvariate(self, mu: float, sigma: float) -> float: - """Normal distribution. - - mu is the mean, and sigma is the standard deviation. - - """ - # mu = mean, sigma = standard deviation - - # Uses Kinderman and Monahan method. Reference: Kinderman, - # A.J. and Monahan, J.F., "Computer generation of random - # variables using the ratio of uniform deviates", ACM Trans - # Math Software, 3, (1977), pp257-260. - - random = self.random - while 1: - u1 = random() - u2 = 1.0 - random() - z = NV_MAGICCONST*(u1-0.5)/u2 - zz = z*z/4.0 - if zz <= -_log(u2): - break - return mu + z*sigma - -## -------------------- lognormal distribution -------------------- - - def lognormvariate(self, mu: float, sigma: float) -> float: - """Log normal distribution. - - If you take the natural logarithm of this distribution, you'll get a - normal distribution with mean mu and standard deviation sigma. - mu can have any value, and sigma must be greater than zero. - - """ - return _exp(self.normalvariate(mu, sigma)) - -## -------------------- exponential distribution -------------------- - - def expovariate(self, lambd: float) -> float: - """Exponential distribution. - - lambd is 1.0 divided by the desired mean. It should be - nonzero. (The parameter would be called "lambda", but that is - a reserved word in Python.) Returned values range from 0 to - positive infinity if lambd is positive, and from negative - infinity to 0 if lambd is negative. - - """ - # lambd: rate lambd = 1/mean - # ('lambda' is a Python reserved word) - - # we use 1-random() instead of random() to preclude the - # possibility of taking the log of zero. - return -_log(1.0 - self.random())/lambd - -## -------------------- von Mises distribution -------------------- - - def vonmisesvariate(self, mu: float, kappa: float) -> float: - """Circular data distribution. - - mu is the mean angle, expressed in radians between 0 and 2*pi, and - kappa is the concentration parameter, which must be greater than or - equal to zero. If kappa is equal to zero, this distribution reduces - to a uniform random angle over the range 0 to 2*pi. - - """ - # mu: mean angle (in radians between 0 and 2*pi) - # kappa: concentration parameter kappa (>= 0) - # if kappa = 0 generate uniform random angle - - # Based upon an algorithm published in: Fisher, N.I., - # "Statistical Analysis of Circular Data", Cambridge - # University Press, 1993. - - # Thanks to Magnus Kessler for a correction to the - # implementation of step 4. - - random = self.random - if kappa <= 1e-6: - return TWOPI * random() - - a = 1.0 + _sqrt(1.0 + 4.0 * kappa * kappa) - b = (a - _sqrt(2.0 * a))/(2.0 * kappa) - r = (1.0 + b * b)/(2.0 * b) - - while 1: - u1 = random() - - z = _cos(_pi * u1) - f = (1.0 + r * z)/(r + z) - c = kappa * (r - f) - - u2 = random() - - if u2 < c * (2.0 - c) or u2 <= c * _exp(1.0 - c): - break - - u3 = random() - if u3 > 0.5: - theta = (mu % TWOPI) + _acos(f) - else: - theta = (mu % TWOPI) - _acos(f) - - return theta - -## -------------------- gamma distribution -------------------- - - def gammavariate(self, alpha: float, beta: float) -> float: - """Gamma distribution. Not the gamma function! - - Conditions on the parameters are alpha > 0 and beta > 0. - - The probability distribution function is: - - x ** (alpha - 1) * math.exp(-x / beta) - pdf(x) = -------------------------------------- - math.gamma(alpha) * beta ** alpha - - """ - - # alpha > 0, beta > 0, mean is alpha*beta, variance is alpha*beta**2 - - # Warning: a few older sources define the gamma distribution in terms - # of alpha > -1.0 - if alpha <= 0.0 or beta <= 0.0: - raise ValueError('gammavariate: alpha and beta must be > 0.0') - - random = self.random - if alpha > 1.0: - - # Uses R.C.H. Cheng, "The generation of Gamma - # variables with non-integral shape parameters", - # Applied Statistics, (1977), 26, No. 1, p71-74 - - ainv = _sqrt(2.0 * alpha - 1.0) - bbb = alpha - LOG4 - ccc = alpha + ainv - - while 1: - u1 = random() - if not (1e-7 < u1 and u1 < .9999999): - continue - u2 = 1.0 - random() - v = _log(u1/(1.0-u1))/ainv - x = alpha*_exp(v) - z = u1*u1*u2 - r = bbb+ccc*v-x - if r + SG_MAGICCONST - 4.5*z >= 0.0 or r >= _log(z): - return x * beta - - elif alpha == 1.0: - # expovariate(1) - u = random() - while u <= 1e-7: - u = random() - return -_log(u) * beta - - else: # alpha is between 0 and 1 (exclusive) - - # Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle - - while 1: - u = random() - b = (_e + alpha)/_e - p = b*u - if p <= 1.0: - x = p ** (1.0/alpha) - else: - x = -_log((b-p)/alpha) - u1 = random() - if p > 1.0: - if u1 <= x ** (alpha - 1.0): - break - elif u1 <= _exp(-x): - break - return x * beta - -## -------------------- Gauss (faster alternative) -------------------- - - def gauss(self, mu: float, sigma: float) -> float: - """Gaussian distribution. - - mu is the mean, and sigma is the standard deviation. This is - slightly faster than the normalvariate() function. - - Not thread-safe without a lock around calls. - - """ - - # When x and y are two variables from [0, 1), uniformly - # distributed, then - # - # cos(2*pi*x)*sqrt(-2*log(1-y)) - # sin(2*pi*x)*sqrt(-2*log(1-y)) - # - # are two *independent* variables with normal distribution - # (mu = 0, sigma = 1). - # (Lambert Meertens) - # (corrected version; bug discovered by Mike Miller, fixed by LM) - - # Multithreading note: When two threads call this function - # simultaneously, it is possible that they will receive the - # same return value. The window is very small though. To - # avoid this, you have to use a lock around all calls. (I - # didn't want to slow this down in the serial case by using a - # lock here.) - - random = self.random - z = self.gauss_next - self.gauss_next = None - if z is None: - x2pi = random() * TWOPI - g2rad = _sqrt(-2.0 * _log(1.0 - random())) - z = _cos(x2pi) * g2rad - self.gauss_next = _sin(x2pi) * g2rad - - return mu + z*sigma - -## -------------------- beta -------------------- -## See -## http://mail.python.org/pipermail/python-bugs-list/2001-January/003752.html -## for Ivan Frohne's insightful analysis of why the original implementation: -## -## def betavariate(self, alpha, beta): -## # Discrete Event Simulation in C, pp 87-88. -## -## y = self.expovariate(alpha) -## z = self.expovariate(1.0/beta) -## return z/(y+z) -## -## was dead wrong, and how it probably got that way. - - def betavariate(self, alpha: float, beta: float) -> 'float': - """Beta distribution. - - Conditions on the parameters are alpha > 0 and beta > 0. - Returned values range between 0 and 1. - - """ - - # This version due to Janne Sinkkonen, and matches all the std - # texts (e.g., Knuth Vol 2 Ed 3 pg 134 "the beta distribution"). - y = self.gammavariate(alpha, 1.) - if y == 0: - return 0.0 - else: - return y / (y + self.gammavariate(beta, 1.)) - -## -------------------- Pareto -------------------- - - def paretovariate(self, alpha: float) -> float: - """Pareto distribution. alpha is the shape parameter.""" - # Jain, pg. 495 - - u = 1.0 - self.random() - return 1.0 / u ** (1.0/alpha) - -## -------------------- Weibull -------------------- - - def weibullvariate(self, alpha: float, beta: float) -> float: - """Weibull distribution. - - alpha is the scale parameter and beta is the shape parameter. - - """ - # Jain, pg. 499; bug fix courtesy Bill Arms - - u = 1.0 - self.random() - return alpha * (-_log(u)) ** (1.0/beta) - -## --------------- Operating System Random Source ------------------ - -class SystemRandom(Random): - """Alternate random number generator using sources provided - by the operating system (such as /dev/urandom on Unix or - CryptGenRandom on Windows). - - Not available on all systems (see os.urandom() for details). - """ - - def random(self) -> float: - """Get the next random number in the range [0.0, 1.0).""" - return (int.from_bytes(_urandom(7), 'big') >> 3) * RECIP_BPF - - def getrandbits(self, k: int) -> int: - """getrandbits(k) -> x. Generates a long int with k random bits.""" - if k <= 0: - raise ValueError('number of bits must be greater than zero') - if k != int(k): - raise TypeError('number of bits should be an integer') - numbytes = (k + 7) // 8 # bits / 8 and rounded up - x = int.from_bytes(_urandom(numbytes), 'big') - return x >> (numbytes * 8 - k) # trim excess bits - - def seed(self, a: object = None, version: int = None) -> None: - "Stub method. Not used for a system random number generator." - return - - def _notimplemented(self, *args: Any, **kwds: Any) -> Any: - "Method should not be called for a system random number generator." - raise NotImplementedError('System entropy source does not have state.') - getstate = setstate = _notimplemented - -# Create one instance, seeded from current time, and export its methods -# as module-level functions. The functions share state across all uses -#(both in the user's code and in the Python libraries), but that's fine -# for most programs and is easier for the casual user than making them -# instantiate their own Random() instance. - -_inst = Random() -seed = _inst.seed -random = _inst.random -uniform = _inst.uniform -triangular = _inst.triangular -randint = _inst.randint -choice = _inst.choice -randrange = _inst.randrange -sample = _inst.sample -shuffle = _inst.shuffle -normalvariate = _inst.normalvariate -lognormvariate = _inst.lognormvariate -expovariate = _inst.expovariate -vonmisesvariate = _inst.vonmisesvariate -gammavariate = _inst.gammavariate -gauss = _inst.gauss -betavariate = _inst.betavariate -paretovariate = _inst.paretovariate -weibullvariate = _inst.weibullvariate -getstate = _inst.getstate -setstate = _inst.setstate -getrandbits = _inst.getrandbits - -## -------------------- test program -------------------- - -def _test_generator(n: int, func: Any, args: tuple) -> None: - import time - print(n, 'times', func.__name__) - total = 0.0 - sqsum = 0.0 - smallest = 1e10 - largest = -1e10 - t0 = time.time() - for i in range(n): - x = func(*args) # type: float - total += x - sqsum = sqsum + x*x - smallest = min(x, smallest) - largest = max(x, largest) - t1 = time.time() - print(round(t1-t0, 3), 'sec,', end=' ') - avg = total/n - stddev = _sqrt(sqsum/n - avg*avg) - print('avg %g, stddev %g, min %g, max %g' % \ - (avg, stddev, smallest, largest)) - - -def _test(N: int = 2000) -> None: - _test_generator(N, random, ()) - _test_generator(N, normalvariate, (0.0, 1.0)) - _test_generator(N, lognormvariate, (0.0, 1.0)) - _test_generator(N, vonmisesvariate, (0.0, 1.0)) - _test_generator(N, gammavariate, (0.01, 1.0)) - _test_generator(N, gammavariate, (0.1, 1.0)) - _test_generator(N, gammavariate, (0.1, 2.0)) - _test_generator(N, gammavariate, (0.5, 1.0)) - _test_generator(N, gammavariate, (0.9, 1.0)) - _test_generator(N, gammavariate, (1.0, 1.0)) - _test_generator(N, gammavariate, (2.0, 1.0)) - _test_generator(N, gammavariate, (20.0, 1.0)) - _test_generator(N, gammavariate, (200.0, 1.0)) - _test_generator(N, gauss, (0.0, 1.0)) - _test_generator(N, betavariate, (3.0, 3.0)) - _test_generator(N, triangular, (0.0, 1.0, 1.0/3.0)) - -if __name__ == '__main__': - _test() diff --git a/test-data/stdlib-samples/3.2/shutil.py b/test-data/stdlib-samples/3.2/shutil.py deleted file mode 100644 index bcefb77879526..0000000000000 --- a/test-data/stdlib-samples/3.2/shutil.py +++ /dev/null @@ -1,790 +0,0 @@ -"""Utility functions for copying and archiving files and directory trees. - -XXX The functions here don't copy the resource fork or other metadata on Mac. - -""" - -import os -import sys -import stat -from os.path import abspath -import fnmatch -import collections -import errno -import tarfile -import builtins - -from typing import ( - Any, AnyStr, IO, List, Iterable, Callable, Tuple, Dict, Sequence, cast -) -from types import TracebackType - -try: - import bz2 - _BZ2_SUPPORTED = True -except ImportError: - _BZ2_SUPPORTED = False - -try: - from pwd import getpwnam as _getpwnam - getpwnam = _getpwnam -except ImportError: - getpwnam = None - -try: - from grp import getgrnam as _getgrnam - getgrnam = _getgrnam -except ImportError: - getgrnam = None - -__all__ = ["copyfileobj", "copyfile", "copymode", "copystat", "copy", "copy2", - "copytree", "move", "rmtree", "Error", "SpecialFileError", - "ExecError", "make_archive", "get_archive_formats", - "register_archive_format", "unregister_archive_format", - "get_unpack_formats", "register_unpack_format", - "unregister_unpack_format", "unpack_archive", "ignore_patterns"] - -class Error(EnvironmentError): - pass - -class SpecialFileError(EnvironmentError): - """Raised when trying to do a kind of operation (e.g. copying) which is - not supported on a special file (e.g. a named pipe)""" - -class ExecError(EnvironmentError): - """Raised when a command could not be executed""" - -class ReadError(EnvironmentError): - """Raised when an archive cannot be read""" - -class RegistryError(Exception): - """Raised when a registry operation with the archiving - and unpacking registeries fails""" - - -if sys.platform == "win32": - _WindowsError = WindowsError -else: - _WindowsError = None - - -# Function aliases to be patched in test cases -rename = os.rename -open = builtins.open - - -def copyfileobj(fsrc: IO[AnyStr], fdst: IO[AnyStr], - length: int = 16*1024) -> None: - """copy data from file-like object fsrc to file-like object fdst""" - while 1: - buf = fsrc.read(length) - if not buf: - break - fdst.write(buf) - -def _samefile(src: str, dst: str) -> bool: - # Macintosh, Unix. - if hasattr(os.path, 'samefile'): - try: - return os.path.samefile(src, dst) - except OSError: - return False - - # All other platforms: check for same pathname. - return (os.path.normcase(os.path.abspath(src)) == - os.path.normcase(os.path.abspath(dst))) - -def copyfile(src: str, dst: str) -> None: - """Copy data from src to dst""" - if _samefile(src, dst): - raise Error("`%s` and `%s` are the same file" % (src, dst)) - - for fn in [src, dst]: - try: - st = os.stat(fn) - except OSError: - # File most likely does not exist - pass - else: - # XXX What about other special files? (sockets, devices...) - if stat.S_ISFIFO(st.st_mode): - raise SpecialFileError("`%s` is a named pipe" % fn) - - with open(src, 'rb') as fsrc: - with open(dst, 'wb') as fdst: - copyfileobj(fsrc, fdst) - -def copymode(src: str, dst: str) -> None: - """Copy mode bits from src to dst""" - if hasattr(os, 'chmod'): - st = os.stat(src) - mode = stat.S_IMODE(st.st_mode) - os.chmod(dst, mode) - -def copystat(src: str, dst: str) -> None: - """Copy all stat info (mode bits, atime, mtime, flags) from src to dst""" - st = os.stat(src) - mode = stat.S_IMODE(st.st_mode) - if hasattr(os, 'utime'): - os.utime(dst, (st.st_atime, st.st_mtime)) - if hasattr(os, 'chmod'): - os.chmod(dst, mode) - if hasattr(os, 'chflags') and hasattr(st, 'st_flags'): - try: - os.chflags(dst, st.st_flags) - except OSError as why: - if (not hasattr(errno, 'EOPNOTSUPP') or - why.errno != errno.EOPNOTSUPP): - raise - -def copy(src: str, dst: str) -> None: - """Copy data and mode bits ("cp src dst"). - - The destination may be a directory. - - """ - if os.path.isdir(dst): - dst = os.path.join(dst, os.path.basename(src)) - copyfile(src, dst) - copymode(src, dst) - -def copy2(src: str, dst: str) -> None: - """Copy data and all stat info ("cp -p src dst"). - - The destination may be a directory. - - """ - if os.path.isdir(dst): - dst = os.path.join(dst, os.path.basename(src)) - copyfile(src, dst) - copystat(src, dst) - -def ignore_patterns(*patterns: str) -> Callable[[str, List[str]], - Iterable[str]]: - """Function that can be used as copytree() ignore parameter. - - Patterns is a sequence of glob-style patterns - that are used to exclude files""" - def _ignore_patterns(path: str, names: List[str]) -> Iterable[str]: - ignored_names = [] # type: List[str] - for pattern in patterns: - ignored_names.extend(fnmatch.filter(names, pattern)) - return set(ignored_names) - return _ignore_patterns - -def copytree(src: str, dst: str, symlinks: bool = False, - ignore: Callable[[str, List[str]], Iterable[str]] = None, - copy_function: Callable[[str, str], None] = copy2, - ignore_dangling_symlinks: bool = False) -> None: - """Recursively copy a directory tree. - - The destination directory must not already exist. - If exception(s) occur, an Error is raised with a list of reasons. - - If the optional symlinks flag is true, symbolic links in the - source tree result in symbolic links in the destination tree; if - it is false, the contents of the files pointed to by symbolic - links are copied. If the file pointed by the symlink doesn't - exist, an exception will be added in the list of errors raised in - an Error exception at the end of the copy process. - - You can set the optional ignore_dangling_symlinks flag to true if you - want to silence this exception. Notice that this has no effect on - platforms that don't support os.symlink. - - The optional ignore argument is a callable. If given, it - is called with the `src` parameter, which is the directory - being visited by copytree(), and `names` which is the list of - `src` contents, as returned by os.listdir(): - - callable(src, names) -> ignored_names - - Since copytree() is called recursively, the callable will be - called once for each directory that is copied. It returns a - list of names relative to the `src` directory that should - not be copied. - - The optional copy_function argument is a callable that will be used - to copy each file. It will be called with the source path and the - destination path as arguments. By default, copy2() is used, but any - function that supports the same signature (like copy()) can be used. - - """ - names = os.listdir(src) - if ignore is not None: - ignored_names = ignore(src, names) - else: - ignored_names = set() - - os.makedirs(dst) - errors = [] # type: List[Tuple[str, str, str]] - for name in names: - if name in ignored_names: - continue - srcname = os.path.join(src, name) - dstname = os.path.join(dst, name) - try: - if os.path.islink(srcname): - linkto = os.readlink(srcname) - if symlinks: - os.symlink(linkto, dstname) - else: - # ignore dangling symlink if the flag is on - if not os.path.exists(linkto) and ignore_dangling_symlinks: - continue - # otherwise let the copy occurs. copy2 will raise an error - copy_function(srcname, dstname) - elif os.path.isdir(srcname): - copytree(srcname, dstname, symlinks, ignore, copy_function) - else: - # Will raise a SpecialFileError for unsupported file types - copy_function(srcname, dstname) - # catch the Error from the recursive copytree so that we can - # continue with other files - except Error as err: - errors.extend(err.args[0]) - except EnvironmentError as why: - errors.append((srcname, dstname, str(why))) - try: - copystat(src, dst) - except OSError as why: - if _WindowsError is not None and isinstance(why, _WindowsError): - # Copying file access times may fail on Windows - pass - else: - errors.append((src, dst, str(why))) - if errors: - raise Error(errors) - -def rmtree(path: str, ignore_errors: bool = False, - onerror: Callable[[Any, str, Tuple[type, BaseException, TracebackType]], - None] = None) -> None: - """Recursively delete a directory tree. - - If ignore_errors is set, errors are ignored; otherwise, if onerror - is set, it is called to handle the error with arguments (func, - path, exc_info) where func is os.listdir, os.remove, or os.rmdir; - path is the argument to that function that caused it to fail; and - exc_info is a tuple returned by sys.exc_info(). If ignore_errors - is false and onerror is None, an exception is raised. - - """ - if ignore_errors: - def _onerror(x: Any, y: str, - z: Tuple[type, BaseException, TracebackType]) -> None: - pass - onerror = _onerror - elif onerror is None: - def __onerror(x: Any, y: str, - z: Tuple[type, BaseException, TracebackType]) -> None: - raise - onerror = __onerror - try: - if os.path.islink(path): - # symlinks to directories are forbidden, see bug #1669 - raise OSError("Cannot call rmtree on a symbolic link") - except OSError: - onerror(os.path.islink, path, sys.exc_info()) - # can't continue even if onerror hook returns - return - names = [] # type: List[str] - try: - names = os.listdir(path) - except os.error as err: - onerror(os.listdir, path, sys.exc_info()) - for name in names: - fullname = os.path.join(path, name) - try: - mode = os.lstat(fullname).st_mode - except os.error: - mode = 0 - if stat.S_ISDIR(mode): - rmtree(fullname, ignore_errors, onerror) - else: - try: - os.remove(fullname) - except os.error as err: - onerror(os.remove, fullname, sys.exc_info()) - try: - os.rmdir(path) - except os.error: - onerror(os.rmdir, path, sys.exc_info()) - - -def _basename(path: str) -> str: - # A basename() variant which first strips the trailing slash, if present. - # Thus we always get the last component of the path, even for directories. - return os.path.basename(path.rstrip(os.path.sep)) - -def move(src: str, dst: str) -> None: - """Recursively move a file or directory to another location. This is - similar to the Unix "mv" command. - - If the destination is a directory or a symlink to a directory, the source - is moved inside the directory. The destination path must not already - exist. - - If the destination already exists but is not a directory, it may be - overwritten depending on os.rename() semantics. - - If the destination is on our current filesystem, then rename() is used. - Otherwise, src is copied to the destination and then removed. - A lot more could be done here... A look at a mv.c shows a lot of - the issues this implementation glosses over. - - """ - real_dst = dst - if os.path.isdir(dst): - if _samefile(src, dst): - # We might be on a case insensitive filesystem, - # perform the rename anyway. - os.rename(src, dst) - return - - real_dst = os.path.join(dst, _basename(src)) - if os.path.exists(real_dst): - raise Error("Destination path '%s' already exists" % real_dst) - try: - os.rename(src, real_dst) - except OSError as exc: - if os.path.isdir(src): - if _destinsrc(src, dst): - raise Error("Cannot move a directory '%s' into itself '%s'." % (src, dst)) - copytree(src, real_dst, symlinks=True) - rmtree(src) - else: - copy2(src, real_dst) - os.unlink(src) - -def _destinsrc(src: str, dst: str) -> bool: - src = abspath(src) - dst = abspath(dst) - if not src.endswith(os.path.sep): - src += os.path.sep - if not dst.endswith(os.path.sep): - dst += os.path.sep - return dst.startswith(src) - -def _get_gid(name: str) -> int: - """Returns a gid, given a group name.""" - if getgrnam is None or name is None: - return None - try: - result = getgrnam(name) - except KeyError: - result = None - if result is not None: - return result.gr_gid - return None - -def _get_uid(name: str) -> int: - """Returns an uid, given a user name.""" - if getpwnam is None or name is None: - return None - try: - result = getpwnam(name) - except KeyError: - result = None - if result is not None: - return result.pw_uid - return None - -def _make_tarball(base_name: str, base_dir: str, compress: str = "gzip", - verbose: bool = False, dry_run: bool = False, - owner: str = None, group: str = None, - logger: Any = None) -> str: - """Create a (possibly compressed) tar file from all the files under - 'base_dir'. - - 'compress' must be "gzip" (the default), "bzip2", or None. - - 'owner' and 'group' can be used to define an owner and a group for the - archive that is being built. If not provided, the current owner and group - will be used. - - The output tar file will be named 'base_name' + ".tar", possibly plus - the appropriate compression extension (".gz", or ".bz2"). - - Returns the output filename. - """ - tar_compression = {'gzip': 'gz', None: ''} - compress_ext = {'gzip': '.gz'} - - if _BZ2_SUPPORTED: - tar_compression['bzip2'] = 'bz2' - compress_ext['bzip2'] = '.bz2' - - # flags for compression program, each element of list will be an argument - if compress is not None and compress not in compress_ext.keys(): - raise ValueError("bad value for 'compress', or compression format not " - "supported : {0}".format(compress)) - - archive_name = base_name + '.tar' + compress_ext.get(compress, '') - archive_dir = os.path.dirname(archive_name) - - if not os.path.exists(archive_dir): - if logger is not None: - logger.info("creating %s", archive_dir) - if not dry_run: - os.makedirs(archive_dir) - - # creating the tarball - if logger is not None: - logger.info('Creating tar archive') - - uid = _get_uid(owner) - gid = _get_gid(group) - - def _set_uid_gid(tarinfo): - if gid is not None: - tarinfo.gid = gid - tarinfo.gname = group - if uid is not None: - tarinfo.uid = uid - tarinfo.uname = owner - return tarinfo - - if not dry_run: - tar = tarfile.open(archive_name, 'w|%s' % tar_compression[compress]) - try: - tar.add(base_dir, filter=_set_uid_gid) - finally: - tar.close() - - return archive_name - -def _call_external_zip(base_dir: str, zip_filename: str, verbose: bool = False, - dry_run: bool = False) -> None: - # XXX see if we want to keep an external call here - if verbose: - zipoptions = "-r" - else: - zipoptions = "-rq" - from distutils.errors import DistutilsExecError - from distutils.spawn import spawn - try: - spawn(["zip", zipoptions, zip_filename, base_dir], dry_run=dry_run) - except DistutilsExecError: - # XXX really should distinguish between "couldn't find - # external 'zip' command" and "zip failed". - raise ExecError(("unable to create zip file '%s': " - "could neither import the 'zipfile' module nor " - "find a standalone zip utility") % zip_filename) - -def _make_zipfile(base_name: str, base_dir: str, verbose: bool = False, - dry_run: bool = False, logger: Any = None) -> str: - """Create a zip file from all the files under 'base_dir'. - - The output zip file will be named 'base_name' + ".zip". Uses either the - "zipfile" Python module (if available) or the InfoZIP "zip" utility - (if installed and found on the default search path). If neither tool is - available, raises ExecError. Returns the name of the output zip - file. - """ - zip_filename = base_name + ".zip" - archive_dir = os.path.dirname(base_name) - - if not os.path.exists(archive_dir): - if logger is not None: - logger.info("creating %s", archive_dir) - if not dry_run: - os.makedirs(archive_dir) - - # If zipfile module is not available, try spawning an external 'zip' - # command. - try: - import zipfile - except ImportError: - zipfile = None - - if zipfile is None: - _call_external_zip(base_dir, zip_filename, verbose, dry_run) - else: - if logger is not None: - logger.info("creating '%s' and adding '%s' to it", - zip_filename, base_dir) - - if not dry_run: - zip = zipfile.ZipFile(zip_filename, "w", - compression=zipfile.ZIP_DEFLATED) - - for dirpath, dirnames, filenames in os.walk(base_dir): - for name in filenames: - path = os.path.normpath(os.path.join(dirpath, name)) - if os.path.isfile(path): - zip.write(path, path) - if logger is not None: - logger.info("adding '%s'", path) - zip.close() - - return zip_filename - -_ARCHIVE_FORMATS = { - 'gztar': (_make_tarball, [('compress', 'gzip')], "gzip'ed tar-file"), - 'tar': (_make_tarball, [('compress', None)], "uncompressed tar file"), - 'zip': (_make_zipfile, [],"ZIP file") - } # type: Dict[str, Tuple[Any, Sequence[Tuple[str, str]], str]] - -if _BZ2_SUPPORTED: - _ARCHIVE_FORMATS['bztar'] = (_make_tarball, [('compress', 'bzip2')], - "bzip2'ed tar-file") - -def get_archive_formats() -> List[Tuple[str, str]]: - """Returns a list of supported formats for archiving and unarchiving. - - Each element of the returned sequence is a tuple (name, description) - """ - formats = [(name, registry[2]) for name, registry in - _ARCHIVE_FORMATS.items()] - formats.sort() - return formats - -def register_archive_format(name: str, function: Any, - extra_args: Sequence[Tuple[str, Any]] = None, - description: str = '') -> None: - """Registers an archive format. - - name is the name of the format. function is the callable that will be - used to create archives. If provided, extra_args is a sequence of - (name, value) tuples that will be passed as arguments to the callable. - description can be provided to describe the format, and will be returned - by the get_archive_formats() function. - """ - if extra_args is None: - extra_args = [] - if not callable(function): - raise TypeError('The %s object is not callable' % function) - if not isinstance(extra_args, (tuple, list)): - raise TypeError('extra_args needs to be a sequence') - for element in extra_args: - if not isinstance(element, (tuple, list)) or len(cast(tuple, element)) !=2 : - raise TypeError('extra_args elements are : (arg_name, value)') - - _ARCHIVE_FORMATS[name] = (function, extra_args, description) - -def unregister_archive_format(name: str) -> None: - del _ARCHIVE_FORMATS[name] - -def make_archive(base_name: str, format: str, root_dir: str = None, - base_dir: str = None, verbose: bool = False, - dry_run: bool = False, owner: str = None, - group: str = None, logger: Any = None) -> str: - """Create an archive file (eg. zip or tar). - - 'base_name' is the name of the file to create, minus any format-specific - extension; 'format' is the archive format: one of "zip", "tar", "bztar" - or "gztar". - - 'root_dir' is a directory that will be the root directory of the - archive; ie. we typically chdir into 'root_dir' before creating the - archive. 'base_dir' is the directory where we start archiving from; - ie. 'base_dir' will be the common prefix of all files and - directories in the archive. 'root_dir' and 'base_dir' both default - to the current directory. Returns the name of the archive file. - - 'owner' and 'group' are used when creating a tar archive. By default, - uses the current owner and group. - """ - save_cwd = os.getcwd() - if root_dir is not None: - if logger is not None: - logger.debug("changing into '%s'", root_dir) - base_name = os.path.abspath(base_name) - if not dry_run: - os.chdir(root_dir) - - if base_dir is None: - base_dir = os.curdir - - kwargs = {'dry_run': dry_run, 'logger': logger} - - try: - format_info = _ARCHIVE_FORMATS[format] - except KeyError: - raise ValueError("unknown archive format '%s'" % format) - - func = format_info[0] - for arg, val in format_info[1]: - kwargs[arg] = val - - if format != 'zip': - kwargs['owner'] = owner - kwargs['group'] = group - - try: - filename = func(base_name, base_dir, **kwargs) - finally: - if root_dir is not None: - if logger is not None: - logger.debug("changing back to '%s'", save_cwd) - os.chdir(save_cwd) - - return filename - - -def get_unpack_formats() -> List[Tuple[str, List[str], str]]: - """Returns a list of supported formats for unpacking. - - Each element of the returned sequence is a tuple - (name, extensions, description) - """ - formats = [(name, info[0], info[3]) for name, info in - _UNPACK_FORMATS.items()] - formats.sort() - return formats - -def _check_unpack_options(extensions: List[str], function: Any, - extra_args: Sequence[Tuple[str, Any]]) -> None: - """Checks what gets registered as an unpacker.""" - # first make sure no other unpacker is registered for this extension - existing_extensions = {} # type: Dict[str, str] - for name, info in _UNPACK_FORMATS.items(): - for ext in info[0]: - existing_extensions[ext] = name - - for extension in extensions: - if extension in existing_extensions: - msg = '%s is already registered for "%s"' - raise RegistryError(msg % (extension, - existing_extensions[extension])) - - if not callable(function): - raise TypeError('The registered function must be a callable') - - -def register_unpack_format(name: str, extensions: List[str], function: Any, - extra_args: Sequence[Tuple[str, Any]] = None, - description: str = '') -> None: - """Registers an unpack format. - - `name` is the name of the format. `extensions` is a list of extensions - corresponding to the format. - - `function` is the callable that will be - used to unpack archives. The callable will receive archives to unpack. - If it's unable to handle an archive, it needs to raise a ReadError - exception. - - If provided, `extra_args` is a sequence of - (name, value) tuples that will be passed as arguments to the callable. - description can be provided to describe the format, and will be returned - by the get_unpack_formats() function. - """ - if extra_args is None: - extra_args = [] - _check_unpack_options(extensions, function, extra_args) - _UNPACK_FORMATS[name] = extensions, function, extra_args, description - -def unregister_unpack_format(name: str) -> None: - """Removes the pack format from the registry.""" - del _UNPACK_FORMATS[name] - -def _ensure_directory(path: str) -> None: - """Ensure that the parent directory of `path` exists""" - dirname = os.path.dirname(path) - if not os.path.isdir(dirname): - os.makedirs(dirname) - -def _unpack_zipfile(filename: str, extract_dir: str) -> None: - """Unpack zip `filename` to `extract_dir` - """ - try: - import zipfile - except ImportError: - raise ReadError('zlib not supported, cannot unpack this archive.') - - if not zipfile.is_zipfile(filename): - raise ReadError("%s is not a zip file" % filename) - - zip = zipfile.ZipFile(filename) - try: - for info in zip.infolist(): - name = info.filename - - # don't extract absolute paths or ones with .. in them - if name.startswith('/') or '..' in name: - continue - - target = os.path.join(extract_dir, *name.split('/')) - if not target: - continue - - _ensure_directory(target) - if not name.endswith('/'): - # file - data = zip.read(info.filename) - f = open(target,'wb') - try: - f.write(data) - finally: - f.close() - del data - finally: - zip.close() - -def _unpack_tarfile(filename: str, extract_dir: str) -> None: - """Unpack tar/tar.gz/tar.bz2 `filename` to `extract_dir` - """ - try: - tarobj = tarfile.open(filename) - except tarfile.TarError: - raise ReadError( - "%s is not a compressed or uncompressed tar file" % filename) - try: - tarobj.extractall(extract_dir) - finally: - tarobj.close() - -_UNPACK_FORMATS = { - 'gztar': (['.tar.gz', '.tgz'], _unpack_tarfile, [], "gzip'ed tar-file"), - 'tar': (['.tar'], _unpack_tarfile, [], "uncompressed tar file"), - 'zip': (['.zip'], _unpack_zipfile, [], "ZIP file") - } # type: Dict[str, Tuple[List[str], Any, Sequence[Tuple[str, Any]], str]] - -if _BZ2_SUPPORTED: - _UNPACK_FORMATS['bztar'] = (['.bz2'], _unpack_tarfile, [], - "bzip2'ed tar-file") - -def _find_unpack_format(filename: str) -> str: - for name, info in _UNPACK_FORMATS.items(): - for extension in info[0]: - if filename.endswith(extension): - return name - return None - -def unpack_archive(filename: str, extract_dir: str = None, - format: str = None) -> None: - """Unpack an archive. - - `filename` is the name of the archive. - - `extract_dir` is the name of the target directory, where the archive - is unpacked. If not provided, the current working directory is used. - - `format` is the archive format: one of "zip", "tar", or "gztar". Or any - other registered format. If not provided, unpack_archive will use the - filename extension and see if an unpacker was registered for that - extension. - - In case none is found, a ValueError is raised. - """ - if extract_dir is None: - extract_dir = os.getcwd() - - if format is not None: - try: - format_info = _UNPACK_FORMATS[format] - except KeyError: - raise ValueError("Unknown unpack format '{0}'".format(format)) - - func = format_info[1] - func(filename, extract_dir, **dict(format_info[2])) - else: - # we need to look at the registered unpackers supported extensions - format = _find_unpack_format(filename) - if format is None: - raise ReadError("Unknown archive format '{0}'".format(filename)) - - func = _UNPACK_FORMATS[format][1] - kwargs = dict(_UNPACK_FORMATS[format][2]) - func(filename, extract_dir, **kwargs) diff --git a/test-data/stdlib-samples/3.2/tempfile.py b/test-data/stdlib-samples/3.2/tempfile.py deleted file mode 100644 index fa4059276fcb7..0000000000000 --- a/test-data/stdlib-samples/3.2/tempfile.py +++ /dev/null @@ -1,724 +0,0 @@ -"""Temporary files. - -This module provides generic, low- and high-level interfaces for -creating temporary files and directories. The interfaces listed -as "safe" just below can be used without fear of race conditions. -Those listed as "unsafe" cannot, and are provided for backward -compatibility only. - -This module also provides some data items to the user: - - TMP_MAX - maximum number of names that will be tried before - giving up. - template - the default prefix for all temporary names. - You may change this to control the default prefix. - tempdir - If this is set to a string before the first use of - any routine from this module, it will be considered as - another candidate location to store temporary files. -""" - -__all__ = [ - "NamedTemporaryFile", "TemporaryFile", # high level safe interfaces - "SpooledTemporaryFile", "TemporaryDirectory", - "mkstemp", "mkdtemp", # low level safe interfaces - "mktemp", # deprecated unsafe interface - "TMP_MAX", "gettempprefix", # constants - "tempdir", "gettempdir" - ] - - -# Imports. - -import warnings as _warnings -import sys as _sys -import io as _io -import os as _os -import errno as _errno -from random import Random as _Random - -from typing import ( - Any as _Any, Callable as _Callable, Iterator as _Iterator, - List as _List, Tuple as _Tuple, Dict as _Dict, Iterable as _Iterable, - IO as _IO, cast as _cast, Optional as _Optional, Type as _Type, -) -from typing_extensions import Literal -from types import TracebackType as _TracebackType - -try: - import fcntl as _fcntl -except ImportError: - def _set_cloexec(fd: int) -> None: - pass -else: - def _set_cloexec(fd: int) -> None: - try: - flags = _fcntl.fcntl(fd, _fcntl.F_GETFD, 0) - except IOError: - pass - else: - # flags read successfully, modify - flags |= _fcntl.FD_CLOEXEC - _fcntl.fcntl(fd, _fcntl.F_SETFD, flags) - - -try: - import _thread - _allocate_lock = _thread.allocate_lock # type: _Callable[[], _Any] -except ImportError: - import _dummy_thread - _allocate_lock = _dummy_thread.allocate_lock - -_text_openflags = _os.O_RDWR | _os.O_CREAT | _os.O_EXCL -if hasattr(_os, 'O_NOINHERIT'): - _text_openflags |= _os.O_NOINHERIT -if hasattr(_os, 'O_NOFOLLOW'): - _text_openflags |= _os.O_NOFOLLOW - -_bin_openflags = _text_openflags -if hasattr(_os, 'O_BINARY'): - _bin_openflags |= _os.O_BINARY - -if hasattr(_os, 'TMP_MAX'): - TMP_MAX = _os.TMP_MAX -else: - TMP_MAX = 10000 - -template = "tmp" - -# Internal routines. - -_once_lock = _allocate_lock() - -if hasattr(_os, "lstat"): - _stat = _os.lstat # type: _Callable[[str], object] -elif hasattr(_os, "stat"): - _stat = _os.stat -else: - # Fallback. All we need is something that raises os.error if the - # file doesn't exist. - def __stat(fn: str) -> object: - try: - f = open(fn) - except IOError: - raise _os.error() - f.close() - return None - _stat = __stat - -def _exists(fn: str) -> bool: - try: - _stat(fn) - except _os.error: - return False - else: - return True - -class _RandomNameSequence(_Iterator[str]): - """An instance of _RandomNameSequence generates an endless - sequence of unpredictable strings which can safely be incorporated - into file names. Each string is six characters long. Multiple - threads can safely use the same instance at the same time. - - _RandomNameSequence is an iterator.""" - - characters = "abcdefghijklmnopqrstuvwxyz0123456789_" - - @property - def rng(self) -> _Random: - cur_pid = _os.getpid() - if cur_pid != getattr(self, '_rng_pid', None): - self._rng = _Random() - self._rng_pid = cur_pid - return self._rng - - def __iter__(self) -> _Iterator[str]: - return self - - def __next__(self) -> str: - c = self.characters - choose = self.rng.choice - letters = [choose(c) for dummy in "123456"] - return ''.join(letters) - -def _candidate_tempdir_list() -> _List[str]: - """Generate a list of candidate temporary directories which - _get_default_tempdir will try.""" - - dirlist = [] # type: _List[str] - - # First, try the environment. - for envname in 'TMPDIR', 'TEMP', 'TMP': - dirname = _os.getenv(envname) - if dirname: dirlist.append(dirname) - - # Failing that, try OS-specific locations. - if _os.name == 'nt': - dirlist.extend([ r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ]) - else: - dirlist.extend([ '/tmp', '/var/tmp', '/usr/tmp' ]) - - # As a last resort, the current directory. - try: - dirlist.append(_os.getcwd()) - except (AttributeError, _os.error): - dirlist.append(_os.curdir) - - return dirlist - -def _get_default_tempdir() -> str: - """Calculate the default directory to use for temporary files. - This routine should be called exactly once. - - We determine whether or not a candidate temp dir is usable by - trying to create and write to a file in that directory. If this - is successful, the test file is deleted. To prevent denial of - service, the name of the test file must be randomized.""" - - namer = _RandomNameSequence() - dirlist = _candidate_tempdir_list() - - for dir in dirlist: - if dir != _os.curdir: - dir = _os.path.normcase(_os.path.abspath(dir)) - # Try only a few names per directory. - for seq in range(100): - name = next(namer) - filename = _os.path.join(dir, name) - try: - fd = _os.open(filename, _bin_openflags, 0o600) - fp = _io.open(fd, 'wb') - fp.write(b'blat') - fp.close() - _os.unlink(filename) - fp = fd = None - return dir - except (OSError, IOError) as e: - if e.args[0] != _errno.EEXIST: - break # no point trying more names in this directory - pass - raise IOError(_errno.ENOENT, - "No usable temporary directory found in %s" % dirlist) - -_name_sequence = None # type: _RandomNameSequence - -def _get_candidate_names() -> _RandomNameSequence: - """Common setup sequence for all user-callable interfaces.""" - - global _name_sequence - if _name_sequence is None: - _once_lock.acquire() - try: - if _name_sequence is None: - _name_sequence = _RandomNameSequence() - finally: - _once_lock.release() - return _name_sequence - - -def _mkstemp_inner(dir: str, pre: str, suf: str, - flags: int) -> _Tuple[int, str]: - """Code common to mkstemp, TemporaryFile, and NamedTemporaryFile.""" - - names = _get_candidate_names() - - for seq in range(TMP_MAX): - name = next(names) - file = _os.path.join(dir, pre + name + suf) - try: - fd = _os.open(file, flags, 0o600) - _set_cloexec(fd) - return (fd, _os.path.abspath(file)) - except OSError as e: - if e.errno == _errno.EEXIST: - continue # try again - raise - - raise IOError(_errno.EEXIST, "No usable temporary file name found") - - -# User visible interfaces. - -def gettempprefix() -> str: - """Accessor for tempdir.template.""" - return template - -tempdir = None # type: str - -def gettempdir() -> str: - """Accessor for tempfile.tempdir.""" - global tempdir - if tempdir is None: - _once_lock.acquire() - try: - if tempdir is None: - tempdir = _get_default_tempdir() - finally: - _once_lock.release() - return tempdir - -def mkstemp(suffix: str = "", prefix: str = template, dir: str = None, - text: bool = False) -> _Tuple[int, str]: - """User-callable function to create and return a unique temporary - file. The return value is a pair (fd, name) where fd is the - file descriptor returned by os.open, and name is the filename. - - If 'suffix' is specified, the file name will end with that suffix, - otherwise there will be no suffix. - - If 'prefix' is specified, the file name will begin with that prefix, - otherwise a default prefix is used. - - If 'dir' is specified, the file will be created in that directory, - otherwise a default directory is used. - - If 'text' is specified and true, the file is opened in text - mode. Else (the default) the file is opened in binary mode. On - some operating systems, this makes no difference. - - The file is readable and writable only by the creating user ID. - If the operating system uses permission bits to indicate whether a - file is executable, the file is executable by no one. The file - descriptor is not inherited by children of this process. - - Caller is responsible for deleting the file when done with it. - """ - - if dir is None: - dir = gettempdir() - - if text: - flags = _text_openflags - else: - flags = _bin_openflags - - return _mkstemp_inner(dir, prefix, suffix, flags) - - -def mkdtemp(suffix: str = "", prefix: str = template, dir: str = None) -> str: - """User-callable function to create and return a unique temporary - directory. The return value is the pathname of the directory. - - Arguments are as for mkstemp, except that the 'text' argument is - not accepted. - - The directory is readable, writable, and searchable only by the - creating user. - - Caller is responsible for deleting the directory when done with it. - """ - - if dir is None: - dir = gettempdir() - - names = _get_candidate_names() - - for seq in range(TMP_MAX): - name = next(names) - file = _os.path.join(dir, prefix + name + suffix) - try: - _os.mkdir(file, 0o700) - return file - except OSError as e: - if e.errno == _errno.EEXIST: - continue # try again - raise - - raise IOError(_errno.EEXIST, "No usable temporary directory name found") - -def mktemp(suffix: str = "", prefix: str = template, dir: str = None) -> str: - """User-callable function to return a unique temporary file name. The - file is not created. - - Arguments are as for mkstemp, except that the 'text' argument is - not accepted. - - This function is unsafe and should not be used. The file name - refers to a file that did not exist at some point, but by the time - you get around to creating it, someone else may have beaten you to - the punch. - """ - -## from warnings import warn as _warn -## _warn("mktemp is a potential security risk to your program", -## RuntimeWarning, stacklevel=2) - - if dir is None: - dir = gettempdir() - - names = _get_candidate_names() - for seq in range(TMP_MAX): - name = next(names) - file = _os.path.join(dir, prefix + name + suffix) - if not _exists(file): - return file - - raise IOError(_errno.EEXIST, "No usable temporary filename found") - - -class _TemporaryFileWrapper: - """Temporary file wrapper - - This class provides a wrapper around files opened for - temporary use. In particular, it seeks to automatically - remove the file when it is no longer needed. - """ - - def __init__(self, file: _IO[_Any], name: str, - delete: bool = True) -> None: - self.file = file - self.name = name - self.close_called = False - self.delete = delete - - if _os.name != 'nt': - # Cache the unlinker so we don't get spurious errors at - # shutdown when the module-level "os" is None'd out. Note - # that this must be referenced as self.unlink, because the - # name TemporaryFileWrapper may also get None'd out before - # __del__ is called. - self.unlink = _os.unlink - - def __getattr__(self, name: str) -> _Any: - # Attribute lookups are delegated to the underlying file - # and cached for non-numeric results - # (i.e. methods are cached, closed and friends are not) - file = _cast(_Any, self).__dict__['file'] # type: _IO[_Any] - a = getattr(file, name) - if not isinstance(a, int): - setattr(self, name, a) - return a - - # The underlying __enter__ method returns the wrong object - # (self.file) so override it to return the wrapper - def __enter__(self) -> '_TemporaryFileWrapper': - self.file.__enter__() - return self - - # iter() doesn't use __getattr__ to find the __iter__ method - def __iter__(self) -> _Iterator[_Any]: - return iter(self.file) - - # NT provides delete-on-close as a primitive, so we don't need - # the wrapper to do anything special. We still use it so that - # file.name is useful (i.e. not "(fdopen)") with NamedTemporaryFile. - if _os.name != 'nt': - def close(self) -> None: - if not self.close_called: - self.close_called = True - self.file.close() - if self.delete: - self.unlink(self.name) - - def __del__(self) -> None: - self.close() - - # Need to trap __exit__ as well to ensure the file gets - # deleted when used in a with statement - def __exit__(self, exc: _Type[BaseException], value: BaseException, - tb: _Optional[_TracebackType]) -> bool: - result = self.file.__exit__(exc, value, tb) - self.close() - return result - else: - def __exit__(self, # type: ignore[misc] - exc: _Type[BaseException], - value: BaseException, - tb: _Optional[_TracebackType]) -> Literal[False]: - self.file.__exit__(exc, value, tb) - return False - - -def NamedTemporaryFile(mode: str = 'w+b', buffering: int = -1, - encoding: str = None, newline: str = None, - suffix: str = "", prefix: str = template, - dir: str = None, delete: bool = True) -> _IO[_Any]: - """Create and return a temporary file. - Arguments: - 'prefix', 'suffix', 'dir' -- as for mkstemp. - 'mode' -- the mode argument to io.open (default "w+b"). - 'buffering' -- the buffer size argument to io.open (default -1). - 'encoding' -- the encoding argument to io.open (default None) - 'newline' -- the newline argument to io.open (default None) - 'delete' -- whether the file is deleted on close (default True). - The file is created as mkstemp() would do it. - - Returns an object with a file-like interface; the name of the file - is accessible as file.name. The file will be automatically deleted - when it is closed unless the 'delete' argument is set to False. - """ - - if dir is None: - dir = gettempdir() - - flags = _bin_openflags - - # Setting O_TEMPORARY in the flags causes the OS to delete - # the file when it is closed. This is only supported by Windows. - if _os.name == 'nt' and delete: - flags |= _os.O_TEMPORARY - - (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags) - file = _io.open(fd, mode, buffering=buffering, - newline=newline, encoding=encoding) - - return _cast(_IO[_Any], _TemporaryFileWrapper(file, name, delete)) - -if _os.name != 'posix' or _sys.platform == 'cygwin': - # On non-POSIX and Cygwin systems, assume that we cannot unlink a file - # while it is open. - TemporaryFile = NamedTemporaryFile - -else: - def _TemporaryFile(mode: str = 'w+b', buffering: int = -1, - encoding: str = None, newline: str = None, - suffix: str = "", prefix: str = template, - dir: str = None, delete: bool = True) -> _IO[_Any]: - """Create and return a temporary file. - Arguments: - 'prefix', 'suffix', 'dir' -- as for mkstemp. - 'mode' -- the mode argument to io.open (default "w+b"). - 'buffering' -- the buffer size argument to io.open (default -1). - 'encoding' -- the encoding argument to io.open (default None) - 'newline' -- the newline argument to io.open (default None) - The file is created as mkstemp() would do it. - - Returns an object with a file-like interface. The file has no - name, and will cease to exist when it is closed. - """ - - if dir is None: - dir = gettempdir() - - flags = _bin_openflags - - (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags) - try: - _os.unlink(name) - return _io.open(fd, mode, buffering=buffering, - newline=newline, encoding=encoding) - except: - _os.close(fd) - raise - TemporaryFile = _TemporaryFile - -class SpooledTemporaryFile: - """Temporary file wrapper, specialized to switch from - StringIO to a real file when it exceeds a certain size or - when a fileno is needed. - """ - _rolled = False - _file = None # type: _Any # BytesIO, StringIO or TemporaryFile - - def __init__(self, max_size: int = 0, mode: str = 'w+b', - buffering: int = -1, encoding: str = None, - newline: str = None, suffix: str = "", - prefix: str = template, dir: str = None) -> None: - if 'b' in mode: - self._file = _io.BytesIO() - else: - # Setting newline="\n" avoids newline translation; - # this is important because otherwise on Windows we'd - # hget double newline translation upon rollover(). - self._file = _io.StringIO(newline="\n") - self._max_size = max_size - self._rolled = False - self._TemporaryFileArgs = { - 'mode': mode, 'buffering': buffering, - 'suffix': suffix, 'prefix': prefix, - 'encoding': encoding, 'newline': newline, - 'dir': dir} # type: _Dict[str, _Any] - - def _check(self, file: _IO[_Any]) -> None: - if self._rolled: return - max_size = self._max_size - if max_size and file.tell() > max_size: - self.rollover() - - def rollover(self) -> None: - if self._rolled: return - file = self._file - newfile = self._file = TemporaryFile(**self._TemporaryFileArgs) - self._TemporaryFileArgs = None - - newfile.write(file.getvalue()) - newfile.seek(file.tell(), 0) - - self._rolled = True - - # The method caching trick from NamedTemporaryFile - # won't work here, because _file may change from a - # _StringIO instance to a real file. So we list - # all the methods directly. - - # Context management protocol - def __enter__(self) -> 'SpooledTemporaryFile': - if self._file.closed: - raise ValueError("Cannot enter context with closed file") - return self - - def __exit__(self, exc: type, value: BaseException, - tb: _TracebackType) -> Literal[False]: - self._file.close() - return False - - # file protocol - def __iter__(self) -> _Iterable[_Any]: - return self._file.__iter__() - - def close(self) -> None: - self._file.close() - - @property - def closed(self) -> bool: - return self._file.closed - - @property - def encoding(self) -> str: - return self._file.encoding - - def fileno(self) -> int: - self.rollover() - return self._file.fileno() - - def flush(self) -> None: - self._file.flush() - - def isatty(self) -> bool: - return self._file.isatty() - - @property - def mode(self) -> str: - return self._file.mode - - @property - def name(self) -> str: - return self._file.name - - @property - def newlines(self) -> _Any: - return self._file.newlines - - #def next(self): - # return self._file.next - - def read(self, n: int = -1) -> _Any: - return self._file.read(n) - - def readline(self, limit: int = -1) -> _Any: - return self._file.readline(limit) - - def readlines(self, *args) -> _List[_Any]: - return self._file.readlines(*args) - - def seek(self, offset: int, whence: int = 0) -> None: - self._file.seek(offset, whence) - - @property - def softspace(self) -> bool: - return self._file.softspace - - def tell(self) -> int: - return self._file.tell() - - def truncate(self) -> None: - self._file.truncate() - - def write(self, s: _Any) -> int: - file = self._file # type: _IO[_Any] - rv = file.write(s) - self._check(file) - return rv - - def writelines(self, iterable: _Iterable[_Any]) -> None: - file = self._file # type: _IO[_Any] - file.writelines(iterable) - self._check(file) - - #def xreadlines(self, *args) -> _Any: - # return self._file.xreadlines(*args) - - -class TemporaryDirectory(object): - """Create and return a temporary directory. This has the same - behavior as mkdtemp but can be used as a context manager. For - example: - - with TemporaryDirectory() as tmpdir: - ... - - Upon exiting the context, the directory and everything contained - in it are removed. - """ - - def __init__(self, suffix: str = "", prefix: str = template, - dir: str = None) -> None: - self._closed = False - self.name = None # type: str # Handle mkdtemp throwing an exception - self.name = mkdtemp(suffix, prefix, dir) - - # XXX (ncoghlan): The following code attempts to make - # this class tolerant of the module nulling out process - # that happens during CPython interpreter shutdown - # Alas, it doesn't actually manage it. See issue #10188 - self._listdir = _os.listdir - self._path_join = _os.path.join - self._isdir = _os.path.isdir - self._islink = _os.path.islink - self._remove = _os.remove - self._rmdir = _os.rmdir - self._os_error = _os.error - self._warn = _warnings.warn - - def __repr__(self) -> str: - return "<{} {!r}>".format(self.__class__.__name__, self.name) - - def __enter__(self) -> str: - return self.name - - def cleanup(self, _warn: bool = False) -> None: - if self.name and not self._closed: - try: - self._rmtree(self.name) - except (TypeError, AttributeError) as ex: - # Issue #10188: Emit a warning on stderr - # if the directory could not be cleaned - # up due to missing globals - if "None" not in str(ex): - raise - print("ERROR: {!r} while cleaning up {!r}".format(ex, self,), - file=_sys.stderr) - return - self._closed = True - if _warn: - self._warn("Implicitly cleaning up {!r}".format(self), - ResourceWarning) - - def __exit__(self, exc: type, value: BaseException, - tb: _TracebackType) -> Literal[False]: - self.cleanup() - return False - - def __del__(self) -> None: - # Issue a ResourceWarning if implicit cleanup needed - self.cleanup(_warn=True) - - def _rmtree(self, path: str) -> None: - # Essentially a stripped down version of shutil.rmtree. We can't - # use globals because they may be None'ed out at shutdown. - for name in self._listdir(path): - fullname = self._path_join(path, name) - try: - isdir = self._isdir(fullname) and not self._islink(fullname) - except self._os_error: - isdir = False - if isdir: - self._rmtree(fullname) - else: - try: - self._remove(fullname) - except self._os_error: - pass - try: - self._rmdir(path) - except self._os_error: - pass diff --git a/test-data/stdlib-samples/3.2/test/__init__.py b/test-data/stdlib-samples/3.2/test/__init__.py deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/test-data/stdlib-samples/3.2/test/mypy.ini b/test-data/stdlib-samples/3.2/test/mypy.ini deleted file mode 100644 index 90a0e394b258f..0000000000000 --- a/test-data/stdlib-samples/3.2/test/mypy.ini +++ /dev/null @@ -1,2 +0,0 @@ -[mypy] -mypy_path = .. diff --git a/test-data/stdlib-samples/3.2/test/randv2_32.pck b/test-data/stdlib-samples/3.2/test/randv2_32.pck deleted file mode 100644 index 587ab241091ec..0000000000000 --- a/test-data/stdlib-samples/3.2/test/randv2_32.pck +++ /dev/null @@ -1,633 +0,0 @@ -crandom -Random -p0 -(tRp1 -(I2 -(I-2147483648 -I-845974985 -I-1294090086 -I1193659239 -I-1849481736 -I-946579732 -I-34406770 -I1749049471 -I1997774682 -I1432026457 -I1288127073 -I-943175655 -I-1718073964 -I339993548 -I-1045260575 -I582505037 -I-1555108250 -I-1114765620 -I1578648750 -I-350384412 -I-20845848 -I-288255314 -I738790953 -I1901249641 -I1999324672 -I-277361068 -I-1515885839 -I2061761596 -I-809068089 -I1287981136 -I258129492 -I-6303745 -I-765148337 -I1090344911 -I1653434703 -I-1242923628 -I1639171313 -I-1870042660 -I-1655014050 -I345609048 -I2093410138 -I1963263374 -I-2122098342 -I1336859961 -I-810942729 -I945857753 -I2103049942 -I623922684 -I1418349549 -I690877342 -I754973107 -I-1605111847 -I1607137813 -I-1704917131 -I1317536428 -I1714882872 -I-1665385120 -I1823694397 -I-1790836866 -I-1696724812 -I-603979847 -I-498599394 -I-341265291 -I927388804 -I1778562135 -I1716895781 -I1023198122 -I1726145967 -I941955525 -I1240148950 -I-1929634545 -I-1288147083 -I-519318335 -I754559777 -I-707571958 -I374604022 -I420424061 -I-1095443486 -I1621934944 -I-1220502522 -I-140049608 -I-918917122 -I304341024 -I-1637446057 -I-353934485 -I1973436235 -I433380241 -I-686759465 -I-2111563154 -I-573422032 -I804304541 -I1513063483 -I1417381689 -I-804778729 -I211756408 -I544537322 -I890881641 -I150378374 -I1765739392 -I1011604116 -I584889095 -I1400520554 -I413747808 -I-1741992587 -I-1882421574 -I-1373001903 -I-1885348538 -I903819480 -I1083220038 -I-1318105424 -I1740421404 -I1693089625 -I775965557 -I1319608037 -I-2127475785 -I-367562895 -I-1416273451 -I1693000327 -I-1217438421 -I834405522 -I-128287275 -I864057548 -I-973917356 -I7304111 -I1712253182 -I1353897741 -I672982288 -I1778575559 -I-403058377 -I-38540378 -I-1393713496 -I13193171 -I1127196200 -I205176472 -I-2104790506 -I299985416 -I1403541685 -I-1018270667 -I-1980677490 -I-1182625797 -I1637015181 -I-1795357414 -I1514413405 -I-924516237 -I-1841873650 -I-1014591269 -I1576616065 -I-1319103135 -I-120847840 -I2062259778 -I-9285070 -I1160890300 -I-575137313 -I-1509108275 -I46701926 -I-287560914 -I-256824960 -I577558250 -I900598310 -I944607867 -I2121154920 -I-1170505192 -I-1347170575 -I77247778 -I-1899015765 -I1234103327 -I1027053658 -I1934632322 -I-792031234 -I1147322536 -I1290655117 -I1002059715 -I1325898538 -I896029793 -I-790940694 -I-980470721 -I-1922648255 -I-951672814 -I291543943 -I1158740218 -I-1959023736 -I-1977185236 -I1527900076 -I514104195 -I-814154113 -I-593157883 -I-1023704660 -I1285688377 -I-2117525386 -I768954360 -I-38676846 -I-799848659 -I-1305517259 -I-1938213641 -I-462146758 -I-1663302892 -I1899591069 -I-22935388 -I-275856976 -I-443736893 -I-739441156 -I93862068 -I-838105669 -I1735629845 -I-817484206 -I280814555 -I1753547179 -I1811123479 -I1974543632 -I-48447465 -I-642694345 -I-531149613 -I518698953 -I-221642627 -I-686519187 -I776644303 -I257774400 -I-1499134857 -I-1055273455 -I-237023943 -I1981752330 -I-917671662 -I-372905983 -I1588058420 -I1171936660 -I-1730977121 -I1360028989 -I1769469287 -I1910709542 -I-852692959 -I1396944667 -I-1723999155 -I-310975435 -I-1965453954 -I-1636858570 -I2005650794 -I680293715 -I1355629386 -I844514684 -I-1909152807 -I-808646074 -I1936510018 -I1134413810 -I-143411047 -I-1478436304 -I1394969244 -I-1170110660 -I1963112086 -I-1518351049 -I-1506287443 -I-455023090 -I-855366028 -I-1746785568 -I933990882 -I-703625141 -I-285036872 -I188277905 -I1471578620 -I-981382835 -I-586974220 -I945619758 -I1608778444 -I-1708548066 -I-1897629320 -I-42617810 -I-836840790 -I539154487 -I-235706962 -I332074418 -I-575700589 -I1534608003 -I632116560 -I-1819760653 -I642052958 -I-722391771 -I-1104719475 -I-1196847084 -I582413973 -I1563394876 -I642007944 -I108989456 -I361625014 -I677308625 -I-1806529496 -I-959050708 -I-1858251070 -I-216069832 -I701624579 -I501238033 -I12287030 -I1895107107 -I2089098638 -I-874806230 -I1236279203 -I563718890 -I-544352489 -I-1879707498 -I1767583393 -I-1776604656 -I-693294301 -I-88882831 -I169303357 -I1299196152 -I-1122791089 -I-379157172 -I1934671851 -I1575736961 -I-19573174 -I-1401511009 -I9305167 -I-1115174467 -I1670735537 -I1226436501 -I-2004524535 -I1767463878 -I-1722855079 -I-559413926 -I1529810851 -I1201272087 -I-1297130971 -I-1188149982 -I1396557188 -I-370358342 -I-1006619702 -I1600942463 -I906087130 -I-76991909 -I2069580179 -I-1674195181 -I-2098404729 -I-940972459 -I-573399187 -I-1930386277 -I-721311199 -I-647834744 -I1452181671 -I688681916 -I1812793731 -I1704380620 -I-1389615179 -I866287837 -I-1435265007 -I388400782 -I-147986600 -I-1613598851 -I-1040347408 -I782063323 -I-239282031 -I-575966722 -I-1865208174 -I-481365146 -I579572803 -I-1239481494 -I335361280 -I-429722947 -I1881772789 -I1908103808 -I1653690013 -I-1668588344 -I1933787953 -I-2033480609 -I22162797 -I-1516527040 -I-461232482 -I-16201372 -I-2043092030 -I114990337 -I-1524090084 -I1456374020 -I458606440 -I-1928083218 -I227773125 -I-1129028159 -I1678689 -I1575896907 -I-1792935220 -I-151387575 -I64084088 -I-95737215 -I1337335688 -I-1963466345 -I1243315130 -I-1798518411 -I-546013212 -I-607065396 -I1219824160 -I1715218469 -I-1368163783 -I1701552913 -I-381114888 -I1068821717 -I266062971 -I-2066513172 -I1767407229 -I-780936414 -I-705413443 -I-1256268847 -I1646874149 -I1107690353 -I839133072 -I67001749 -I860763503 -I884880613 -I91977084 -I755371933 -I420745153 -I-578480690 -I-1520193551 -I1011369331 -I-99754575 -I-733141064 -I-500598588 -I1081124271 -I-1341266575 -I921002612 -I-848852487 -I-1904467341 -I-1294256973 -I-94074714 -I-1778758498 -I-1401188547 -I2101830578 -I2058864877 -I-272875991 -I-1375854779 -I-1332937870 -I619425525 -I-1034529639 -I-36454393 -I-2030499985 -I-1637127500 -I-1408110287 -I-2108625749 -I-961007436 -I1475654951 -I-791946251 -I1667792115 -I1818978830 -I1897980514 -I1959546477 -I-74478911 -I-508643347 -I461594399 -I538802715 -I-2094970071 -I-2076660253 -I1091358944 -I1944029246 -I-343957436 -I-1915845022 -I1237620188 -I1144125174 -I1522190520 -I-670252952 -I-19469226 -I675626510 -I758750096 -I909724354 -I-1846259652 -I544669343 -I445182495 -I-821519930 -I-1124279685 -I-1668995122 -I1653284793 -I-678555151 -I-687513207 -I1558259445 -I-1978866839 -I1558835601 -I1732138472 -I-1904793363 -I620020296 -I1562597874 -I1942617227 -I-549632552 -I721603795 -I417978456 -I-1355281522 -I-538065208 -I-1079523196 -I187375699 -I449064972 -I1018083947 -I1632388882 -I-493269866 -I92769041 -I1477146750 -I1782708404 -I444873376 -I1085851104 -I-6823272 -I-1302251853 -I1602050688 -I-1042187824 -I287161745 -I-1972094479 -I103271491 -I2131619773 -I-2064115870 -I766815498 -I990861458 -I-1664407378 -I1083746756 -I-1018331904 -I-677315687 -I-951670647 -I-952356874 -I451460609 -I-818615564 -I851439508 -I656362634 -I-1351240485 -I823378078 -I1985597385 -I597757740 -I-1512303057 -I1590872798 -I1108424213 -I818850898 -I-1368594306 -I-201107761 -I1793370378 -I1247597611 -I-1594326264 -I-601653890 -I427642759 -I248322113 -I-292545338 -I1708985870 -I1917042771 -I429354503 -I-478470329 -I793960014 -I369939133 -I1728189157 -I-518963626 -I-278523974 -I-1877289696 -I-2088617658 -I-1367940049 -I-62295925 -I197975119 -I-252900777 -I803430539 -I485759441 -I-528283480 -I-1287443963 -I-478617444 -I-861906946 -I-649095555 -I-893184337 -I2050571322 -I803433133 -I1629574571 -I1649720417 -I-2050225209 -I1208598977 -I720314344 -I-615166251 -I-835077127 -I-1405372429 -I995698064 -I148123240 -I-943016676 -I-594609622 -I-1381596711 -I1017195301 -I-1268893013 -I-1815985179 -I-1393570351 -I-870027364 -I-476064472 -I185582645 -I569863326 -I1098584267 -I-1599147006 -I-485054391 -I-852098365 -I1477320135 -I222316762 -I-1515583064 -I-935051367 -I393383063 -I819617226 -I722921837 -I-1241806499 -I-1358566385 -I1666813591 -I1333875114 -I-1663688317 -I-47254623 -I-885800726 -I307388991 -I-1219459496 -I1374870300 -I2132047877 -I-1385624198 -I-245139206 -I1015139214 -I-926198559 -I1969798868 -I-1950480619 -I-559193432 -I-1256446518 -I-1983476981 -I790179655 -I1004289659 -I1541827617 -I1555805575 -I501127333 -I-1123446797 -I-453230915 -I2035104883 -I1296122398 -I-1843698604 -I-715464588 -I337143971 -I-1972119192 -I606777909 -I726977302 -I-1149501872 -I-1963733522 -I-1797504644 -I624 -tp2 -Ntp3 -b. \ No newline at end of file diff --git a/test-data/stdlib-samples/3.2/test/randv2_64.pck b/test-data/stdlib-samples/3.2/test/randv2_64.pck deleted file mode 100644 index 090dd6fd19682..0000000000000 --- a/test-data/stdlib-samples/3.2/test/randv2_64.pck +++ /dev/null @@ -1,633 +0,0 @@ -crandom -Random -p0 -(tRp1 -(I2 -(I2147483648 -I1812115682 -I2741755497 -I1028055730 -I809166036 -I2773628650 -I62321950 -I535290043 -I349877800 -I976167039 -I2490696940 -I3631326955 -I2107991114 -I2941205793 -I3199611605 -I1871971556 -I1456108540 -I2984591044 -I140836801 -I4203227310 -I3652722980 -I4031971234 -I555769760 -I697301296 -I2347638880 -I3302335858 -I320255162 -I2553586608 -I1570224361 -I2838780912 -I2315834918 -I2351348158 -I3545433015 -I2292018579 -I1177569331 -I758497559 -I2913311175 -I1014948880 -I1793619243 -I3982451053 -I3850988342 -I2393984324 -I1583100093 -I3144742543 -I3655047493 -I3507532385 -I3094515442 -I350042434 -I2455294844 -I1038739312 -I313809152 -I189433072 -I1653165452 -I4186650593 -I19281455 -I2589680619 -I4145931590 -I4283266118 -I636283172 -I943618337 -I3170184633 -I2308766231 -I634615159 -I538152647 -I2079576891 -I1029442616 -I3410689412 -I1370292761 -I1071718978 -I2139496322 -I1876699543 -I3485866187 -I3157490130 -I1633105386 -I1453253160 -I3841322080 -I3789608924 -I4110770792 -I95083673 -I931354627 -I2065389591 -I3448339827 -I3348204577 -I3263528560 -I2411324590 -I4003055026 -I1869670093 -I2737231843 -I4150701155 -I2689667621 -I2993263224 -I3239890140 -I1191430483 -I1214399779 -I3623428533 -I1817058866 -I3052274451 -I326030082 -I1505129312 -I2306812262 -I1349150363 -I1099127895 -I2543465574 -I2396380193 -I503926466 -I1607109730 -I3451716817 -I58037114 -I4290081119 -I947517597 -I3083440186 -I520522630 -I2948962496 -I4184319574 -I2957636335 -I668374201 -I2325446473 -I472785314 -I3791932366 -I573017189 -I2185725379 -I1262251492 -I3525089379 -I2951262653 -I1305347305 -I940958122 -I3343754566 -I359371744 -I3874044973 -I396897232 -I147188248 -I716683703 -I4013880315 -I1133359586 -I1794612249 -I3480815192 -I3988787804 -I1729355809 -I573408542 -I1419310934 -I1770030447 -I3552845567 -I1693976502 -I1271189893 -I2298236738 -I2049219027 -I3464198070 -I1233574082 -I1007451781 -I1838253750 -I687096593 -I1131375603 -I1223013895 -I1490478435 -I339265439 -I4232792659 -I491538536 -I2816256769 -I1044097522 -I2566227049 -I748762793 -I1511830494 -I3593259822 -I4121279213 -I3735541309 -I3609794797 -I1939942331 -I377570434 -I1437957554 -I1831285696 -I55062811 -I2046783110 -I1303902283 -I1838349877 -I420993556 -I1256392560 -I2795216506 -I2783687924 -I3322303169 -I512794749 -I308405826 -I517164429 -I3320436022 -I1328403632 -I2269184746 -I3729522810 -I3304314450 -I2238756124 -I1690581361 -I3813277532 -I4119706879 -I2659447875 -I388818978 -I2064580814 -I1586227676 -I2627522685 -I2017792269 -I547928109 -I859107450 -I1062238929 -I858886237 -I3795783146 -I4173914756 -I3835915965 -I3329504821 -I3494579904 -I838863205 -I3399734724 -I4247387481 -I3618414834 -I2984433798 -I2165205561 -I4260685684 -I3045904244 -I3450093836 -I3597307595 -I3215851166 -I3162801328 -I2558283799 -I950068105 -I1829664117 -I3108542987 -I2378860527 -I790023460 -I280087750 -I1171478018 -I2333653728 -I3976932140 -I896746152 -I1802494195 -I1232873794 -I2749440836 -I2032037296 -I2012091682 -I1296131034 -I3892133385 -I908161334 -I2296791795 -I548169794 -I696265 -I893156828 -I426904709 -I3565374535 -I2655906825 -I2792178515 -I2406814632 -I4038847579 -I3123934642 -I2197503004 -I3535032597 -I2266216689 -I2117613462 -I1787448518 -I1875089416 -I2037165384 -I1140676321 -I3606296464 -I3229138231 -I2458267132 -I1874651171 -I3331900867 -I1000557654 -I1432861701 -I473636323 -I2691783927 -I1871437447 -I1328016401 -I4118690062 -I449467602 -I681789035 -I864889442 -I1200888928 -I75769445 -I4008690037 -I2464577667 -I4167795823 -I3070097648 -I2579174882 -I1216886568 -I3810116343 -I2249507485 -I3266903480 -I3671233480 -I100191658 -I3087121334 -I365063087 -I3821275176 -I2165052848 -I1282465245 -I3601570637 -I3132413236 -I2780570459 -I3222142917 -I3129794692 -I2611590811 -I947031677 -I2991908938 -I750997949 -I3632575131 -I1632014461 -I2846484755 -I2347261779 -I2903959448 -I1397316686 -I1904578392 -I774649578 -I3164598558 -I2429587609 -I738244516 -I1563304975 -I1399317414 -I1021316297 -I3187933234 -I2126780757 -I4011907847 -I4095169219 -I3358010054 -I2729978247 -I3736811646 -I3009656410 -I2893043637 -I4027447385 -I1239610110 -I1488806900 -I2674866844 -I442876374 -I2853687260 -I2785921005 -I3151378528 -I1180567 -I2803146964 -I982221759 -I2192919417 -I3087026181 -I2480838002 -I738452921 -I687986185 -I3049371676 -I3636492954 -I3468311299 -I2379621102 -I788988633 -I1643210601 -I2983998168 -I2492730801 -I2586048705 -I604073029 -I4121082815 -I1496476928 -I2972357110 -I2663116968 -I2642628592 -I2116052039 -I487186279 -I2577680328 -I3974766614 -I730776636 -I3842528855 -I1929093695 -I44626622 -I3989908833 -I1695426222 -I3675479382 -I3051784964 -I1514876613 -I1254036595 -I2420450649 -I3034377361 -I2332990590 -I1535175126 -I185834384 -I1107372900 -I1707278185 -I1286285295 -I3332574225 -I2785672437 -I883170645 -I2005666473 -I3403131327 -I4122021352 -I1464032858 -I3702576112 -I260554598 -I1837731650 -I2594435345 -I75771049 -I2012484289 -I3058649775 -I29979703 -I3861335335 -I2506495152 -I3786448704 -I442947790 -I2582724774 -I4291336243 -I2568189843 -I1923072690 -I1121589611 -I837696302 -I3284631720 -I3865021324 -I3576453165 -I2559531629 -I1459231762 -I3506550036 -I3754420159 -I2622000757 -I124228596 -I1084328605 -I1692830753 -I547273558 -I674282621 -I655259103 -I3188629610 -I490502174 -I2081001293 -I3191330704 -I4109943593 -I1859948504 -I3163806460 -I508833168 -I1256371033 -I2709253790 -I2068956572 -I3092842814 -I3913926529 -I2039638759 -I981982529 -I536094190 -I368855295 -I51993975 -I1597480732 -I4058175522 -I2155896702 -I3196251991 -I1081913893 -I3952353788 -I3545548108 -I2370669647 -I2206572308 -I2576392991 -I1732303374 -I1153136290 -I537641955 -I1738691747 -I3232854186 -I2539632206 -I2829760278 -I3058187853 -I1202425792 -I3762361970 -I2863949342 -I2640635867 -I376638744 -I1857679757 -I330798087 -I1457400505 -I1135610046 -I606400715 -I1859536026 -I509811335 -I529772308 -I2579273244 -I1890382004 -I3959908876 -I2612335971 -I2834052227 -I1434475986 -I3684202717 -I4015011345 -I582567852 -I3689969571 -I3934753460 -I3034960691 -I208573292 -I4004113742 -I3992904842 -I2587153719 -I3529179079 -I1565424987 -I779130678 -I1048582935 -I3213591622 -I3607793434 -I3951254937 -I2047811901 -I7508850 -I248544605 -I4210090324 -I2331490884 -I70057213 -I776474945 -I1345528889 -I3290403612 -I1664955269 -I1533143116 -I545003424 -I4141564478 -I1257326139 -I868843601 -I2337603029 -I1918131449 -I1843439523 -I1125519035 -I673340118 -I421408852 -I1520454906 -I1804722630 -I3621254196 -I2329968000 -I39464672 -I430583134 -I294026512 -I53978525 -I2892276105 -I1418863764 -I3419054451 -I1391595797 -I3544981798 -I4191780858 -I825672357 -I2972000844 -I1571305069 -I4231982845 -I3611916419 -I3045163168 -I2982349733 -I278572141 -I4215338078 -I839860504 -I1819151779 -I1412347479 -I1386770353 -I3914589491 -I3783104977 -I4124296733 -I830546258 -I89825624 -I4110601328 -I2545483429 -I300600527 -I516641158 -I3693021034 -I2852912854 -I3240039868 -I4167407959 -I1479557946 -I3621188804 -I1391590944 -I3578441128 -I1227055556 -I406898396 -I3064054983 -I25835338 -I402664165 -I4097682779 -I2106728012 -I203613622 -I3045467686 -I1381726438 -I3798670110 -I1342314961 -I3552497361 -I535913619 -I2625787583 -I1606574307 -I1101269630 -I1950513752 -I1121355862 -I3586816903 -I438529984 -I2473182121 -I1229997203 -I405445940 -I1695535315 -I427014336 -I3916768430 -I392298359 -I1884642868 -I1244730821 -I741058080 -I567479957 -I3527621168 -I3191971011 -I3267069104 -I4108668146 -I1520795587 -I166581006 -I473794477 -I1562126550 -I929843010 -I889533294 -I1266556608 -I874518650 -I3520162092 -I3013765049 -I4220231414 -I547246449 -I3998093769 -I3737193746 -I3872944207 -I793651876 -I2606384318 -I875991012 -I1394836334 -I4102011644 -I854380426 -I2618666767 -I2568302000 -I1995512132 -I229491093 -I2673500286 -I3364550739 -I3836923416 -I243656987 -I3944388983 -I4064949677 -I1416956378 -I1703244487 -I3990798829 -I2023425781 -I3926702214 -I1229015501 -I3174247824 -I624 -tp2 -Ntp3 -b. \ No newline at end of file diff --git a/test-data/stdlib-samples/3.2/test/randv3.pck b/test-data/stdlib-samples/3.2/test/randv3.pck deleted file mode 100644 index 09fc38b1a8767..0000000000000 --- a/test-data/stdlib-samples/3.2/test/randv3.pck +++ /dev/null @@ -1,633 +0,0 @@ -crandom -Random -p0 -(tRp1 -(I3 -(L2147483648L -L994081831L -L2806287265L -L2228999830L -L3396498069L -L2956805457L -L3273927761L -L920726507L -L1862624492L -L2921292485L -L1779526843L -L2469105503L -L251696293L -L1254390717L -L779197080L -L3165356830L -L2007365218L -L1870028812L -L2896519363L -L1855578438L -L979518416L -L3481710246L -L3191861507L -L3993006593L -L2967971479L -L3353342753L -L3576782572L -L339685558L -L2367675732L -L116208555L -L1220054437L -L486597056L -L1912115141L -L1037044792L -L4096904723L -L3409146175L -L3701651227L -L315824610L -L4138604583L -L1385764892L -L191878900L -L2320582219L -L3420677494L -L2776503169L -L1148247403L -L829555069L -L902064012L -L2934642741L -L2477108577L -L2583928217L -L1658612579L -L2865447913L -L129147346L -L3691171887L -L1569328110L -L1372860143L -L1054139183L -L1617707080L -L69020592L -L3810271603L -L1853953416L -L3499803073L -L1027545027L -L3229043605L -L250848720L -L3324932626L -L3537002962L -L2494323345L -L3238103962L -L4147541579L -L3636348186L -L3025455083L -L2678771977L -L584700256L -L3461826909L -L854511420L -L943463552L -L3609239025L -L3977577989L -L253070090L -L777394544L -L2144086567L -L1092947992L -L854327284L -L2222750082L -L360183510L -L1312466483L -L3227531091L -L2235022500L -L3013060530L -L2541091298L -L3480126342L -L1839762775L -L2632608190L -L1108889403L -L3045050923L -L731513126L -L3505436788L -L3062762017L -L1667392680L -L1354126500L -L1143573930L -L2816645702L -L2100356873L -L2817679106L -L1210746010L -L2409915248L -L2910119964L -L2309001420L -L220351824L -L3667352871L -L3993148590L -L2886160232L -L4239393701L -L1189270581L -L3067985541L -L147374573L -L2355164869L -L3696013550L -L4227037846L -L1905112743L -L3312843689L -L2930678266L -L1828795355L -L76933594L -L3987100796L -L1288361435L -L3464529151L -L965498079L -L1444623093L -L1372893415L -L1536235597L -L1341994850L -L963594758L -L2115295754L -L982098685L -L1053433904L -L2078469844L -L3059765792L -L1753606181L -L2130171254L -L567588194L -L529629426L -L3621523534L -L3027576564L -L1176438083L -L4096287858L -L1168574683L -L1425058962L -L1429631655L -L2902106759L -L761900641L -L1329183956L -L1947050932L -L447490289L -L3282516276L -L200037389L -L921868197L -L3331403999L -L4088760249L -L2188326318L -L288401961L -L1360802675L -L314302808L -L3314639210L -L3749821203L -L2286081570L -L2768939062L -L3200541016L -L2133495482L -L385029880L -L4217232202L -L3171617231L -L1660846653L -L2459987621L -L2691776124L -L4225030408L -L3595396773L -L1103680661L -L539064057L -L1492841101L -L166195394L -L757973658L -L533893054L -L2784879594L -L1021821883L -L2350548162L -L176852116L -L3503166025L -L148079914L -L1633466236L -L2773090165L -L1162846701L -L3575737795L -L1624178239L -L2454894710L -L3014691938L -L526355679L -L1870824081L -L3362425857L -L3907566665L -L3462563184L -L2229112004L -L4203735748L -L1557442481L -L924133999L -L1906634214L -L880459727L -L4065895870L -L141426254L -L1258450159L -L3243115027L -L1574958840L -L313939294L -L3055664260L -L3459714255L -L531778790L -L509505506L -L1620227491L -L2675554942L -L2516509560L -L3797299887L -L237135890L -L3203142213L -L1087745310L -L1897151854L -L3936590041L -L132765167L -L2385908063L -L1360600289L -L3574567769L -L2752788114L -L2644228966L -L2377705183L -L601277909L -L4046480498L -L324401408L -L3279931760L -L2227059377L -L1538827493L -L4220532064L -L478044564L -L2917117761L -L635492832L -L2319763261L -L795944206L -L1820473234L -L1673151409L -L1404095402L -L1661067505L -L3217106938L -L2406310683L -L1931309248L -L2458622868L -L3323670524L -L3266852755L -L240083943L -L3168387397L -L607722198L -L1256837690L -L3608124913L -L4244969357L -L1289959293L -L519750328L -L3229482463L -L1105196988L -L1832684479L -L3761037224L -L2363631822L -L3297957711L -L572766355L -L1195822137L -L2239207981L -L2034241203L -L163540514L -L288160255L -L716403680L -L4019439143L -L1536281935L -L2345100458L -L2786059178L -L2822232109L -L987025395L -L3061166559L -L490422513L -L2551030115L -L2638707620L -L1344728502L -L714108911L -L2831719700L -L2188615369L -L373509061L -L1351077504L -L3136217056L -L783521095L -L2554949468L -L2662499550L -L1203826951L -L1379632388L -L1918858985L -L607465976L -L1980450237L -L3540079211L -L3397813410L -L2913309266L -L2289572621L -L4133935327L -L4166227663L -L3371801704L -L3065474909L -L3580562343L -L3832172378L -L2556130719L -L310473705L -L3734014346L -L2490413810L -L347233056L -L526668037L -L1158393656L -L544329703L -L2150085419L -L3914038146L -L1060237586L -L4159394837L -L113205121L -L309966775L -L4098784465L -L3635222960L -L2417516569L -L2089579233L -L1725807541L -L2728122526L -L2365836523L -L2504078522L -L1443946869L -L2384171411L -L997046534L -L3249131657L -L1699875986L -L3618097146L -L1716038224L -L2629818607L -L2929217876L -L1367250314L -L1726434951L -L1388496325L -L2107602181L -L2822366842L -L3052979190L -L3796798633L -L1543813381L -L959000121L -L1363845999L -L2952528150L -L874184932L -L1888387194L -L2328695295L -L3442959855L -L841805947L -L1087739275L -L3230005434L -L3045399265L -L1161817318L -L2898673139L -L860011094L -L940539782L -L1297818080L -L4243941623L -L1577613033L -L4204131887L -L3819057225L -L1969439558L -L3297963932L -L241874069L -L3517033453L -L2295345664L -L1098911422L -L886955008L -L1477397621L -L4279347332L -L3616558791L -L2384411957L -L742537731L -L764221540L -L2871698900L -L3530636393L -L691256644L -L758730966L -L1717773090L -L2751856377L -L3188484000L -L3767469670L -L1623863053L -L3533236793L -L4099284176L -L723921107L -L310594036L -L223978745L -L2266565776L -L201843303L -L2969968546L -L3351170888L -L3465113624L -L2712246712L -L1521383057L -L2384461798L -L216357551L -L2167301975L -L3144653194L -L2781220155L -L3620747666L -L95971265L -L4255400243L -L59999757L -L4174273472L -L3974511524L -L1007123950L -L3112477628L -L806461512L -L3148074008L -L528352882L -L2545979588L -L2562281969L -L3010249477L -L1886331611L -L3210656433L -L1034099976L -L2906893579L -L1197048779L -L1870004401L -L3898300490L -L2686856402L -L3975723478L -L613043532L -L2565674353L -L3760045310L -L3468984376L -L4126258L -L303855424L -L3988963552L -L276256796L -L544071807L -L1023872062L -L1747461519L -L1975571260L -L4033766958L -L2946555557L -L1492957796L -L958271685L -L46480515L -L907760635L -L1306626357L -L819652378L -L1172300279L -L1116851319L -L495601075L -L1157715330L -L534220108L -L377320028L -L1672286106L -L2066219284L -L1842386355L -L2546059464L -L1839457336L -L3476194446L -L3050550028L -L594705582L -L1905813535L -L1813033412L -L2700858157L -L169067972L -L4252889045L -L1921944555L -L497671474L -L210143935L -L2688398489L -L325158375L -L3450846447L -L891760597L -L712802536L -L1132557436L -L1417044075L -L1639889660L -L1746379970L -L1478741647L -L2817563486L -L2573612532L -L4266444457L -L2911601615L -L804745411L -L2207254652L -L1189140646L -L3829725111L -L3637367348L -L1944731747L -L2193440343L -L1430195413L -L1173515229L -L1582618217L -L2070767037L -L247908936L -L1460675439L -L556001596L -L327629335L -L1036133876L -L4228129605L -L999174048L -L3635804039L -L1416550481L -L1270540269L -L4280743815L -L39607659L -L1552540623L -L2762294062L -L504137289L -L4117044239L -L1417130225L -L1342970056L -L1755716449L -L1169447322L -L2731401356L -L2319976745L -L2869221479L -L23972655L -L2251495389L -L1429860878L -L3728135992L -L4241432973L -L3698275076L -L216416432L -L4040046960L -L246077176L -L894675685L -L3932282259L -L3097205100L -L2128818650L -L1319010656L -L1601974009L -L2552960957L -L3554016055L -L4209395641L -L2013340102L -L3370447801L -L2307272002L -L1795091354L -L202109401L -L988345070L -L2514870758L -L1132726850L -L582746224L -L3112305421L -L1843020683L -L3600189223L -L1101349165L -L4211905855L -L2866677581L -L2881621130L -L4165324109L -L4238773191L -L3635649550L -L2670481044L -L2996248219L -L1676992480L -L3473067050L -L4205793699L -L4019490897L -L1579990481L -L1899617990L -L1136347713L -L1802842268L -L3591752960L -L1197308739L -L433629786L -L4032142790L -L3148041979L -L3312138845L -L3896860449L -L3298182567L -L907605170L -L1658664067L -L2682980313L -L2523523173L -L1208722103L -L3808530363L -L1079003946L -L4282402864L -L2041010073L -L2667555071L -L688018180L -L1405121012L -L4167994076L -L3504695336L -L1923944749L -L1143598790L -L3936268898L -L3606243846L -L1017420080L -L4026211169L -L596529763L -L1844259624L -L2840216282L -L2673807759L -L3407202575L -L2737971083L -L4075423068L -L3684057432L -L3146627241L -L599650513L -L69773114L -L1257035919L -L807485291L -L2376230687L -L3036593147L -L2642411658L -L106080044L -L2199622729L -L291834511L -L2697611361L -L11689733L -L625123952L -L3226023062L -L3229663265L -L753059444L -L2843610189L -L624L -tp2 -Ntp3 -b. \ No newline at end of file diff --git a/test-data/stdlib-samples/3.2/test/subprocessdata/fd_status.py b/test-data/stdlib-samples/3.2/test/subprocessdata/fd_status.py deleted file mode 100644 index 1f61e13a34562..0000000000000 --- a/test-data/stdlib-samples/3.2/test/subprocessdata/fd_status.py +++ /dev/null @@ -1,24 +0,0 @@ -"""When called as a script, print a comma-separated list of the open -file descriptors on stdout.""" - -import errno -import os - -try: - _MAXFD = os.sysconf("SC_OPEN_MAX") -except: - _MAXFD = 256 - -if __name__ == "__main__": - fds = [] - for fd in range(0, _MAXFD): - try: - st = os.fstat(fd) - except OSError as e: - if e.errno == errno.EBADF: - continue - raise - # Ignore Solaris door files - if st.st_mode & 0xF000 != 0xd000: - fds.append(fd) - print(','.join(map(str, fds))) diff --git a/test-data/stdlib-samples/3.2/test/subprocessdata/input_reader.py b/test-data/stdlib-samples/3.2/test/subprocessdata/input_reader.py deleted file mode 100644 index 1dc3191ad183f..0000000000000 --- a/test-data/stdlib-samples/3.2/test/subprocessdata/input_reader.py +++ /dev/null @@ -1,7 +0,0 @@ -"""When called as a script, consumes the input""" - -import sys - -if __name__ == "__main__": - for line in sys.stdin: - pass diff --git a/test-data/stdlib-samples/3.2/test/subprocessdata/qcat.py b/test-data/stdlib-samples/3.2/test/subprocessdata/qcat.py deleted file mode 100644 index fe6f9db25c970..0000000000000 --- a/test-data/stdlib-samples/3.2/test/subprocessdata/qcat.py +++ /dev/null @@ -1,7 +0,0 @@ -"""When ran as a script, simulates cat with no arguments.""" - -import sys - -if __name__ == "__main__": - for line in sys.stdin: - sys.stdout.write(line) diff --git a/test-data/stdlib-samples/3.2/test/subprocessdata/qgrep.py b/test-data/stdlib-samples/3.2/test/subprocessdata/qgrep.py deleted file mode 100644 index 69906379a9b38..0000000000000 --- a/test-data/stdlib-samples/3.2/test/subprocessdata/qgrep.py +++ /dev/null @@ -1,10 +0,0 @@ -"""When called with a single argument, simulated fgrep with a single -argument and no options.""" - -import sys - -if __name__ == "__main__": - pattern = sys.argv[1] - for line in sys.stdin: - if pattern in line: - sys.stdout.write(line) diff --git a/test-data/stdlib-samples/3.2/test/subprocessdata/sigchild_ignore.py b/test-data/stdlib-samples/3.2/test/subprocessdata/sigchild_ignore.py deleted file mode 100644 index 6072aece28a89..0000000000000 --- a/test-data/stdlib-samples/3.2/test/subprocessdata/sigchild_ignore.py +++ /dev/null @@ -1,6 +0,0 @@ -import signal, subprocess, sys -# On Linux this causes os.waitpid to fail with OSError as the OS has already -# reaped our child process. The wait() passing the OSError on to the caller -# and causing us to exit with an error is what we are testing against. -signal.signal(signal.SIGCHLD, signal.SIG_IGN) -subprocess.Popen([sys.executable, '-c', 'print("albatross")']).wait() diff --git a/test-data/stdlib-samples/3.2/test/support.py b/test-data/stdlib-samples/3.2/test/support.py deleted file mode 100644 index 88ce10cd74a94..0000000000000 --- a/test-data/stdlib-samples/3.2/test/support.py +++ /dev/null @@ -1,1602 +0,0 @@ -"""Supporting definitions for the Python regression tests.""" - -if __name__ != 'test.support': - raise ImportError('support must be imported from the test package') - -import contextlib -import errno -import functools -import gc -import socket -import sys -import os -import platform -import shutil -import warnings -import unittest -import importlib -import collections -import re -import subprocess -import imp -import time -import sysconfig -import fnmatch -import logging.handlers - -import _thread, threading -from typing import Any, Dict, cast -#try: -# import multiprocessing.process -#except ImportError: -# multiprocessing = None - - -__all__ = [ - "Error", "TestFailed", "ResourceDenied", "import_module", - "verbose", "use_resources", "max_memuse", "record_original_stdout", - "get_original_stdout", "unload", "unlink", "rmtree", "forget", - "is_resource_enabled", "requires", "requires_mac_ver", - "find_unused_port", "bind_port", - "fcmp", "is_jython", "TESTFN", "HOST", "FUZZ", "SAVEDCWD", "temp_cwd", - "findfile", "sortdict", "check_syntax_error", "open_urlresource", - "check_warnings", "CleanImport", "EnvironmentVarGuard", - "TransientResource", "captured_output", "captured_stdout", - "captured_stdin", "captured_stderr", - "time_out", "socket_peer_reset", "ioerror_peer_reset", - "run_with_locale", 'temp_umask', "transient_internet", - "set_memlimit", "bigmemtest", "bigaddrspacetest", "BasicTestRunner", - "run_unittest", "run_doctest", "threading_setup", "threading_cleanup", - "reap_children", "cpython_only", "check_impl_detail", "get_attribute", - "swap_item", "swap_attr", "requires_IEEE_754", - "TestHandler", "Matcher", "can_symlink", "skip_unless_symlink", - "import_fresh_module", "failfast", - ] - -class Error(Exception): - """Base class for regression test exceptions.""" - -class TestFailed(Error): - """Test failed.""" - -class ResourceDenied(unittest.SkipTest): - """Test skipped because it requested a disallowed resource. - - This is raised when a test calls requires() for a resource that - has not be enabled. It is used to distinguish between expected - and unexpected skips. - """ - -@contextlib.contextmanager -def _ignore_deprecated_imports(ignore=True): - """Context manager to suppress package and module deprecation - warnings when importing them. - - If ignore is False, this context manager has no effect.""" - if ignore: - with warnings.catch_warnings(): - warnings.filterwarnings("ignore", ".+ (module|package)", - DeprecationWarning) - yield None - else: - yield None - - -def import_module(name, deprecated=False): - """Import and return the module to be tested, raising SkipTest if - it is not available. - - If deprecated is True, any module or package deprecation messages - will be suppressed.""" - with _ignore_deprecated_imports(deprecated): - try: - return importlib.import_module(name) - except ImportError as msg: - raise unittest.SkipTest(str(msg)) - - -def _save_and_remove_module(name, orig_modules): - """Helper function to save and remove a module from sys.modules - - Raise ImportError if the module can't be imported.""" - # try to import the module and raise an error if it can't be imported - if name not in sys.modules: - __import__(name) - del sys.modules[name] - for modname in list(sys.modules): - if modname == name or modname.startswith(name + '.'): - orig_modules[modname] = sys.modules[modname] - del sys.modules[modname] - -def _save_and_block_module(name, orig_modules): - """Helper function to save and block a module in sys.modules - - Return True if the module was in sys.modules, False otherwise.""" - saved = True - try: - orig_modules[name] = sys.modules[name] - except KeyError: - saved = False - sys.modules[name] = None - return saved - - -def import_fresh_module(name, fresh=(), blocked=(), deprecated=False): - """Imports and returns a module, deliberately bypassing the sys.modules cache - and importing a fresh copy of the module. Once the import is complete, - the sys.modules cache is restored to its original state. - - Modules named in fresh are also imported anew if needed by the import. - If one of these modules can't be imported, None is returned. - - Importing of modules named in blocked is prevented while the fresh import - takes place. - - If deprecated is True, any module or package deprecation messages - will be suppressed.""" - # NOTE: test_heapq, test_json and test_warnings include extra sanity checks - # to make sure that this utility function is working as expected - with _ignore_deprecated_imports(deprecated): - # Keep track of modules saved for later restoration as well - # as those which just need a blocking entry removed - orig_modules = {} - names_to_remove = [] - _save_and_remove_module(name, orig_modules) - try: - for fresh_name in fresh: - _save_and_remove_module(fresh_name, orig_modules) - for blocked_name in blocked: - if not _save_and_block_module(blocked_name, orig_modules): - names_to_remove.append(blocked_name) - fresh_module = importlib.import_module(name) - except ImportError: - fresh_module = None - finally: - for orig_name, module in orig_modules.items(): - sys.modules[orig_name] = module - for name_to_remove in names_to_remove: - del sys.modules[name_to_remove] - return fresh_module - - -def get_attribute(obj, name): - """Get an attribute, raising SkipTest if AttributeError is raised.""" - try: - attribute = getattr(obj, name) - except AttributeError: - raise unittest.SkipTest("module %s has no attribute %s" % ( - obj.__name__, name)) - else: - return attribute - -verbose = 1 # Flag set to 0 by regrtest.py -use_resources = None # type: Any # Flag set to [] by regrtest.py -max_memuse = 0 # Disable bigmem tests (they will still be run with - # small sizes, to make sure they work.) -real_max_memuse = 0 -failfast = False -match_tests = None # type: Any - -# _original_stdout is meant to hold stdout at the time regrtest began. -# This may be "the real" stdout, or IDLE's emulation of stdout, or whatever. -# The point is to have some flavor of stdout the user can actually see. -_original_stdout = None # type: 'Any' -def record_original_stdout(stdout): - global _original_stdout - _original_stdout = stdout - -def get_original_stdout(): - return _original_stdout or sys.stdout - -def unload(name): - try: - del sys.modules[name] - except KeyError: - pass - -def unlink(filename): - try: - os.unlink(filename) - except OSError as error: - # The filename need not exist. - if error.errno not in (errno.ENOENT, errno.ENOTDIR): - raise - -def rmtree(path): - try: - shutil.rmtree(path) - except OSError as error: - # Unix returns ENOENT, Windows returns ESRCH. - if error.errno not in (errno.ENOENT, errno.ESRCH): - raise - -def make_legacy_pyc(source): - """Move a PEP 3147 pyc/pyo file to its legacy pyc/pyo location. - - The choice of .pyc or .pyo extension is done based on the __debug__ flag - value. - - :param source: The file system path to the source file. The source file - does not need to exist, however the PEP 3147 pyc file must exist. - :return: The file system path to the legacy pyc file. - """ - pyc_file = imp.cache_from_source(source) - up_one = os.path.dirname(os.path.abspath(source)) - if __debug__: - ch = 'c' - else: - ch = 'o' - legacy_pyc = os.path.join(up_one, source + ch) - os.rename(pyc_file, legacy_pyc) - return legacy_pyc - -def forget(modname): - """'Forget' a module was ever imported. - - This removes the module from sys.modules and deletes any PEP 3147 or - legacy .pyc and .pyo files. - """ - unload(modname) - for dirname in sys.path: - source = os.path.join(dirname, modname + '.py') - # It doesn't matter if they exist or not, unlink all possible - # combinations of PEP 3147 and legacy pyc and pyo files. - unlink(source + 'c') - unlink(source + 'o') - unlink(imp.cache_from_source(source, debug_override=True)) - unlink(imp.cache_from_source(source, debug_override=False)) - -# On some platforms, should not run gui test even if it is allowed -# in `use_resources'. -#if sys.platform.startswith('win'): - #import ctypes - #import ctypes.wintypes - #def _is_gui_available(): - # UOI_FLAGS = 1 - # WSF_VISIBLE = 0x0001 - # class USEROBJECTFLAGS(ctypes.Structure): - # _fields_ = [("fInherit", ctypes.wintypes.BOOL), - # ("fReserved", ctypes.wintypes.BOOL), - # ("dwFlags", ctypes.wintypes.DWORD)] - # dll = ctypes.windll.user32 - # h = dll.GetProcessWindowStation() - # if not h: - # raise ctypes.WinError() - # uof = USEROBJECTFLAGS() - # needed = ctypes.wintypes.DWORD() - # res = dll.GetUserObjectInformationW(h, - # UOI_FLAGS, - # ctypes.byref(uof), - # ctypes.sizeof(uof), - # ctypes.byref(needed)) - # if not res: - # raise ctypes.WinError() - # return bool(uof.dwFlags & WSF_VISIBLE) -#else: -def _is_gui_available(): - return True - -def is_resource_enabled(resource): - """Test whether a resource is enabled. Known resources are set by - regrtest.py.""" - return use_resources is not None and resource in use_resources - -def requires(resource, msg=None): - """Raise ResourceDenied if the specified resource is not available. - - If the caller's module is __main__ then automatically return True. The - possibility of False being returned occurs when regrtest.py is - executing. - """ - if resource == 'gui' and not _is_gui_available(): - raise unittest.SkipTest("Cannot use the 'gui' resource") - # see if the caller's module is __main__ - if so, treat as if - # the resource was set - if sys._getframe(1).f_globals.get("__name__") == "__main__": - return - if not is_resource_enabled(resource): - if msg is None: - msg = "Use of the `%s' resource not enabled" % resource - raise ResourceDenied(msg) - -def requires_mac_ver(*min_version): - """Decorator raising SkipTest if the OS is Mac OS X and the OS X - version if less than min_version. - - For example, @requires_mac_ver(10, 5) raises SkipTest if the OS X version - is lesser than 10.5. - """ - def decorator(func): - @functools.wraps(func) - def wrapper(*args, **kw): - if sys.platform == 'darwin': - version_txt = platform.mac_ver()[0] - try: - version = tuple(map(int, version_txt.split('.'))) - except ValueError: - pass - else: - if version < min_version: - min_version_txt = '.'.join(map(str, min_version)) - raise unittest.SkipTest( - "Mac OS X %s or higher required, not %s" - % (min_version_txt, version_txt)) - return func(*args, **kw) - wrapper.min_version = min_version - return wrapper - return decorator - -HOST = 'localhost' - -def find_unused_port(family=socket.AF_INET, socktype=socket.SOCK_STREAM): - """Returns an unused port that should be suitable for binding. This is - achieved by creating a temporary socket with the same family and type as - the 'sock' parameter (default is AF_INET, SOCK_STREAM), and binding it to - the specified host address (defaults to 0.0.0.0) with the port set to 0, - eliciting an unused ephemeral port from the OS. The temporary socket is - then closed and deleted, and the ephemeral port is returned. - - Either this method or bind_port() should be used for any tests where a - server socket needs to be bound to a particular port for the duration of - the test. Which one to use depends on whether the calling code is creating - a python socket, or if an unused port needs to be provided in a constructor - or passed to an external program (i.e. the -accept argument to openssl's - s_server mode). Always prefer bind_port() over find_unused_port() where - possible. Hard coded ports should *NEVER* be used. As soon as a server - socket is bound to a hard coded port, the ability to run multiple instances - of the test simultaneously on the same host is compromised, which makes the - test a ticking time bomb in a buildbot environment. On Unix buildbots, this - may simply manifest as a failed test, which can be recovered from without - intervention in most cases, but on Windows, the entire python process can - completely and utterly wedge, requiring someone to log in to the buildbot - and manually kill the affected process. - - (This is easy to reproduce on Windows, unfortunately, and can be traced to - the SO_REUSEADDR socket option having different semantics on Windows versus - Unix/Linux. On Unix, you can't have two AF_INET SOCK_STREAM sockets bind, - listen and then accept connections on identical host/ports. An EADDRINUSE - socket.error will be raised at some point (depending on the platform and - the order bind and listen were called on each socket). - - However, on Windows, if SO_REUSEADDR is set on the sockets, no EADDRINUSE - will ever be raised when attempting to bind two identical host/ports. When - accept() is called on each socket, the second caller's process will steal - the port from the first caller, leaving them both in an awkwardly wedged - state where they'll no longer respond to any signals or graceful kills, and - must be forcibly killed via OpenProcess()/TerminateProcess(). - - The solution on Windows is to use the SO_EXCLUSIVEADDRUSE socket option - instead of SO_REUSEADDR, which effectively affords the same semantics as - SO_REUSEADDR on Unix. Given the propensity of Unix developers in the Open - Source world compared to Windows ones, this is a common mistake. A quick - look over OpenSSL's 0.9.8g source shows that they use SO_REUSEADDR when - openssl.exe is called with the 's_server' option, for example. See - http://bugs.python.org/issue2550 for more info. The following site also - has a very thorough description about the implications of both REUSEADDR - and EXCLUSIVEADDRUSE on Windows: - http://msdn2.microsoft.com/en-us/library/ms740621(VS.85).aspx) - - XXX: although this approach is a vast improvement on previous attempts to - elicit unused ports, it rests heavily on the assumption that the ephemeral - port returned to us by the OS won't immediately be dished back out to some - other process when we close and delete our temporary socket but before our - calling code has a chance to bind the returned port. We can deal with this - issue if/when we come across it. - """ - - tempsock = socket.socket(family, socktype) - port = bind_port(tempsock) - tempsock.close() - #del tempsock - return port - -def bind_port(sock, host=HOST): - """Bind the socket to a free port and return the port number. Relies on - ephemeral ports in order to ensure we are using an unbound port. This is - important as many tests may be running simultaneously, especially in a - buildbot environment. This method raises an exception if the sock.family - is AF_INET and sock.type is SOCK_STREAM, *and* the socket has SO_REUSEADDR - or SO_REUSEPORT set on it. Tests should *never* set these socket options - for TCP/IP sockets. The only case for setting these options is testing - multicasting via multiple UDP sockets. - - Additionally, if the SO_EXCLUSIVEADDRUSE socket option is available (i.e. - on Windows), it will be set on the socket. This will prevent anyone else - from bind()'ing to our host/port for the duration of the test. - """ - - if sock.family == socket.AF_INET and sock.type == socket.SOCK_STREAM: - if hasattr(socket, 'SO_REUSEADDR'): - if sock.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR) == 1: - raise TestFailed("tests should never set the SO_REUSEADDR " \ - "socket option on TCP/IP sockets!") - if hasattr(socket, 'SO_REUSEPORT'): - if sock.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT) == 1: - raise TestFailed("tests should never set the SO_REUSEPORT " \ - "socket option on TCP/IP sockets!") - if hasattr(socket, 'SO_EXCLUSIVEADDRUSE'): - sock.setsockopt(socket.SOL_SOCKET, socket.SO_EXCLUSIVEADDRUSE, 1) - - sock.bind((host, 0)) - port = sock.getsockname()[1] - return port - -FUZZ = 1e-6 - -def fcmp(x, y): # fuzzy comparison function - if isinstance(x, float) or isinstance(y, float): - try: - fuzz = (abs(x) + abs(y)) * FUZZ - if abs(x-y) <= fuzz: - return 0 - except: - pass - elif type(x) == type(y) and isinstance(x, (tuple, list)): - for i in range(min(len(x), len(y))): - outcome = fcmp(x[i], y[i]) - if outcome != 0: - return outcome - return (len(x) > len(y)) - (len(x) < len(y)) - return (x > y) - (x < y) - -# decorator for skipping tests on non-IEEE 754 platforms -requires_IEEE_754 = unittest.skipUnless( - cast(Any, float).__getformat__("double").startswith("IEEE"), - "test requires IEEE 754 doubles") - -is_jython = sys.platform.startswith('java') - -TESTFN = '' -# Filename used for testing -if os.name == 'java': - # Jython disallows @ in module names - TESTFN = '$test' -else: - TESTFN = '@test' - -# Disambiguate TESTFN for parallel testing, while letting it remain a valid -# module name. -TESTFN = "{}_{}_tmp".format(TESTFN, os.getpid()) - - -# TESTFN_UNICODE is a non-ascii filename -TESTFN_UNICODE = TESTFN + "-\xe0\xf2\u0258\u0141\u011f" -if sys.platform == 'darwin': - # In Mac OS X's VFS API file names are, by definition, canonically - # decomposed Unicode, encoded using UTF-8. See QA1173: - # http://developer.apple.com/mac/library/qa/qa2001/qa1173.html - import unicodedata - TESTFN_UNICODE = unicodedata.normalize('NFD', TESTFN_UNICODE) -TESTFN_ENCODING = sys.getfilesystemencoding() - -# TESTFN_UNENCODABLE is a filename (str type) that should *not* be able to be -# encoded by the filesystem encoding (in strict mode). It can be None if we -# cannot generate such filename. -TESTFN_UNENCODABLE = None # type: Any -if sys.platform == "win32": - # skip win32s (0) or Windows 9x/ME (1) - if sys.getwindowsversion().platform >= 2: - # Different kinds of characters from various languages to minimize the - # probability that the whole name is encodable to MBCS (issue #9819) - TESTFN_UNENCODABLE = TESTFN + "-\u5171\u0141\u2661\u0363\uDC80" - try: - TESTFN_UNENCODABLE.encode(TESTFN_ENCODING) - except UnicodeEncodeError: - pass - else: - print('WARNING: The filename %r CAN be encoded by the filesystem encoding (%s). ' - 'Unicode filename tests may not be effective' - % (TESTFN_UNENCODABLE, TESTFN_ENCODING)) - TESTFN_UNENCODABLE = None -# Mac OS X denies unencodable filenames (invalid utf-8) -elif sys.platform != 'darwin': - try: - # ascii and utf-8 cannot encode the byte 0xff - b'\xff'.decode(TESTFN_ENCODING) - except UnicodeDecodeError: - # 0xff will be encoded using the surrogate character u+DCFF - TESTFN_UNENCODABLE = TESTFN \ - + b'-\xff'.decode(TESTFN_ENCODING, 'surrogateescape') - else: - # File system encoding (eg. ISO-8859-* encodings) can encode - # the byte 0xff. Skip some unicode filename tests. - pass - -# Save the initial cwd -SAVEDCWD = os.getcwd() - -@contextlib.contextmanager -def temp_cwd(name='tempcwd', quiet=False, path=None): - """ - Context manager that temporarily changes the CWD. - - An existing path may be provided as *path*, in which case this - function makes no changes to the file system. - - Otherwise, the new CWD is created in the current directory and it's - named *name*. If *quiet* is False (default) and it's not possible to - create or change the CWD, an error is raised. If it's True, only a - warning is raised and the original CWD is used. - """ - saved_dir = os.getcwd() - is_temporary = False - if path is None: - path = name - try: - os.mkdir(name) - is_temporary = True - except OSError: - if not quiet: - raise - warnings.warn('tests may fail, unable to create temp CWD ' + name, - RuntimeWarning, stacklevel=3) - try: - os.chdir(path) - except OSError: - if not quiet: - raise - warnings.warn('tests may fail, unable to change the CWD to ' + name, - RuntimeWarning, stacklevel=3) - try: - yield os.getcwd() - finally: - os.chdir(saved_dir) - if is_temporary: - rmtree(name) - - -@contextlib.contextmanager -def temp_umask(umask): - """Context manager that temporarily sets the process umask.""" - oldmask = os.umask(umask) - try: - yield None - finally: - os.umask(oldmask) - - -def findfile(file, here=__file__, subdir=None): - """Try to find a file on sys.path and the working directory. If it is not - found the argument passed to the function is returned (this does not - necessarily signal failure; could still be the legitimate path).""" - if os.path.isabs(file): - return file - if subdir is not None: - file = os.path.join(subdir, file) - path = sys.path - path = [os.path.dirname(here)] + path - for dn in path: - fn = os.path.join(dn, file) - if os.path.exists(fn): return fn - return file - -def sortdict(dict): - "Like repr(dict), but in sorted order." - items = sorted(dict.items()) - reprpairs = ["%r: %r" % pair for pair in items] - withcommas = ", ".join(reprpairs) - return "{%s}" % withcommas - -def make_bad_fd(): - """ - Create an invalid file descriptor by opening and closing a file and return - its fd. - """ - file = open(TESTFN, "wb") - try: - return file.fileno() - finally: - file.close() - unlink(TESTFN) - -def check_syntax_error(testcase, statement): - raise NotImplementedError('no compile built-in') - #testcase.assertRaises(SyntaxError, compile, statement, - # '', 'exec') - -def open_urlresource(url, *args, **kw): - from urllib import request, parse - - check = kw.pop('check', None) - - filename = parse.urlparse(url)[2].split('/')[-1] # '/': it's URL! - - fn = os.path.join(os.path.dirname(__file__), "data", filename) - - def check_valid_file(fn): - f = open(fn, *args, **kw) - if check is None: - return f - elif check(f): - f.seek(0) - return f - f.close() - - if os.path.exists(fn): - f = check_valid_file(fn) - if f is not None: - return f - unlink(fn) - - # Verify the requirement before downloading the file - requires('urlfetch') - - print('\tfetching %s ...' % url, file=get_original_stdout()) - f = request.urlopen(url, timeout=15) - try: - with open(fn, "wb") as out: - s = f.read() - while s: - out.write(s) - s = f.read() - finally: - f.close() - - f = check_valid_file(fn) - if f is not None: - return f - raise TestFailed('invalid resource "%s"' % fn) - - -class WarningsRecorder(object): - """Convenience wrapper for the warnings list returned on - entry to the warnings.catch_warnings() context manager. - """ - def __init__(self, warnings_list): - self._warnings = warnings_list - self._last = 0 - - def __getattr__(self, attr): - if len(self._warnings) > self._last: - return getattr(self._warnings[-1], attr) - elif attr in warnings.WarningMessage._WARNING_DETAILS: - return None - raise AttributeError("%r has no attribute %r" % (self, attr)) - - #@property - #def warnings(self): - # return self._warnings[self._last:] - - def reset(self): - self._last = len(self._warnings) - - -def _filterwarnings(filters, quiet=False): - """Catch the warnings, then check if all the expected - warnings have been raised and re-raise unexpected warnings. - If 'quiet' is True, only re-raise the unexpected warnings. - """ - # Clear the warning registry of the calling module - # in order to re-raise the warnings. - frame = sys._getframe(2) - registry = frame.f_globals.get('__warningregistry__') - if registry: - registry.clear() - with warnings.catch_warnings(record=True) as w: - # Set filter "always" to record all warnings. Because - # test_warnings swap the module, we need to look up in - # the sys.modules dictionary. - sys.modules['warnings'].simplefilter("always") - yield WarningsRecorder(w) - # Filter the recorded warnings - reraise = list(w) - missing = [] - for msg, cat in filters: - seen = False - for w in reraise[:]: - warning = w.message - # Filter out the matching messages - if (re.match(msg, str(warning), re.I) and - issubclass(warning.__class__, cat)): - seen = True - reraise.remove(w) - if not seen and not quiet: - # This filter caught nothing - missing.append((msg, cat.__name__)) - if reraise: - raise AssertionError("unhandled warning %s" % reraise[0]) - if missing: - raise AssertionError("filter (%r, %s) did not catch any warning" % - missing[0]) - - -@contextlib.contextmanager -def check_warnings(*filters, **kwargs): - """Context manager to silence warnings. - - Accept 2-tuples as positional arguments: - ("message regexp", WarningCategory) - - Optional argument: - - if 'quiet' is True, it does not fail if a filter catches nothing - (default True without argument, - default False if some filters are defined) - - Without argument, it defaults to: - check_warnings(("", Warning), quiet=True) - """ - quiet = kwargs.get('quiet') - if not filters: - filters = (("", Warning),) - # Preserve backward compatibility - if quiet is None: - quiet = True - return _filterwarnings(filters, quiet) - - -class CleanImport(object): - """Context manager to force import to return a new module reference. - - This is useful for testing module-level behaviours, such as - the emission of a DeprecationWarning on import. - - Use like this: - - with CleanImport("foo"): - importlib.import_module("foo") # new reference - """ - - def __init__(self, *module_names): - self.original_modules = sys.modules.copy() - for module_name in module_names: - if module_name in sys.modules: - module = sys.modules[module_name] - # It is possible that module_name is just an alias for - # another module (e.g. stub for modules renamed in 3.x). - # In that case, we also need delete the real module to clear - # the import cache. - if module.__name__ != module_name: - del sys.modules[module.__name__] - del sys.modules[module_name] - - def __enter__(self): - return self - - def __exit__(self, *ignore_exc): - sys.modules.update(self.original_modules) - - -class EnvironmentVarGuard(dict): - - """Class to help protect the environment variable properly. Can be used as - a context manager.""" - - def __init__(self): - self._environ = os.environ - self._changed = {} - - def __getitem__(self, envvar): - return self._environ[envvar] - - def __setitem__(self, envvar, value): - # Remember the initial value on the first access - if envvar not in self._changed: - self._changed[envvar] = self._environ.get(envvar) - self._environ[envvar] = value - - def __delitem__(self, envvar): - # Remember the initial value on the first access - if envvar not in self._changed: - self._changed[envvar] = self._environ.get(envvar) - if envvar in self._environ: - del self._environ[envvar] - - def keys(self): - return self._environ.keys() - - def __iter__(self): - return iter(self._environ) - - def __len__(self): - return len(self._environ) - - def set(self, envvar, value): - self[envvar] = value - - def unset(self, envvar): - del self[envvar] - - def __enter__(self): - return self - - def __exit__(self, *ignore_exc): - for k, v in self._changed.items(): - if v is None: - if k in self._environ: - del self._environ[k] - else: - self._environ[k] = v - os.environ = self._environ - - -class DirsOnSysPath(object): - """Context manager to temporarily add directories to sys.path. - - This makes a copy of sys.path, appends any directories given - as positional arguments, then reverts sys.path to the copied - settings when the context ends. - - Note that *all* sys.path modifications in the body of the - context manager, including replacement of the object, - will be reverted at the end of the block. - """ - - def __init__(self, *paths): - self.original_value = sys.path[:] - self.original_object = sys.path - sys.path.extend(paths) - - def __enter__(self): - return self - - def __exit__(self, *ignore_exc): - sys.path = self.original_object - sys.path[:] = self.original_value - - -class TransientResource(object): - - """Raise ResourceDenied if an exception is raised while the context manager - is in effect that matches the specified exception and attributes.""" - - def __init__(self, exc, **kwargs): - self.exc = exc - self.attrs = kwargs - - def __enter__(self): - return self - - def __exit__(self, type_=None, value=None, traceback=None): - """If type_ is a subclass of self.exc and value has attributes matching - self.attrs, raise ResourceDenied. Otherwise let the exception - propagate (if any).""" - if type_ is not None and issubclass(self.exc, type_): - for attr, attr_value in self.attrs.items(): - if not hasattr(value, attr): - break - if getattr(value, attr) != attr_value: - break - else: - raise ResourceDenied("an optional resource is not available") - -# Context managers that raise ResourceDenied when various issues -# with the Internet connection manifest themselves as exceptions. -# XXX deprecate these and use transient_internet() instead -time_out = TransientResource(IOError, errno=errno.ETIMEDOUT) -socket_peer_reset = TransientResource(socket.error, errno=errno.ECONNRESET) -ioerror_peer_reset = TransientResource(IOError, errno=errno.ECONNRESET) - - -@contextlib.contextmanager -def transient_internet(resource_name, *, timeout=30.0, errnos=()): - """Return a context manager that raises ResourceDenied when various issues - with the Internet connection manifest themselves as exceptions.""" - default_errnos = [ - ('ECONNREFUSED', 111), - ('ECONNRESET', 104), - ('EHOSTUNREACH', 113), - ('ENETUNREACH', 101), - ('ETIMEDOUT', 110), - ] - default_gai_errnos = [ - ('EAI_AGAIN', -3), - ('EAI_FAIL', -4), - ('EAI_NONAME', -2), - ('EAI_NODATA', -5), - # Encountered when trying to resolve IPv6-only hostnames - ('WSANO_DATA', 11004), - ] - - denied = ResourceDenied("Resource '%s' is not available" % resource_name) - captured_errnos = errnos - gai_errnos = [] - if not captured_errnos: - captured_errnos = [getattr(errno, name, num) - for name, num in default_errnos] - gai_errnos = [getattr(socket, name, num) - for name, num in default_gai_errnos] - - def filter_error(err): - n = getattr(err, 'errno', None) - if (isinstance(err, socket.timeout) or - (isinstance(err, socket.gaierror) and n in gai_errnos) or - n in captured_errnos): - if not verbose: - sys.stderr.write(denied.args[0] + "\n") - raise denied from err - - old_timeout = socket.getdefaulttimeout() - try: - if timeout is not None: - socket.setdefaulttimeout(timeout) - yield None - except IOError as err: - # urllib can wrap original socket errors multiple times (!), we must - # unwrap to get at the original error. - while True: - a = err.args - if len(a) >= 1 and isinstance(a[0], IOError): - err = a[0] - # The error can also be wrapped as args[1]: - # except socket.error as msg: - # raise IOError('socket error', msg).with_traceback(sys.exc_info()[2]) - elif len(a) >= 2 and isinstance(a[1], IOError): - err = a[1] - else: - break - filter_error(err) - raise - # XXX should we catch generic exceptions and look for their - # __cause__ or __context__? - finally: - socket.setdefaulttimeout(old_timeout) - - -@contextlib.contextmanager -def captured_output(stream_name): - """Return a context manager used by captured_stdout/stdin/stderr - that temporarily replaces the sys stream *stream_name* with a StringIO.""" - import io - orig_stdout = getattr(sys, stream_name) - setattr(sys, stream_name, io.StringIO()) - try: - yield getattr(sys, stream_name) - finally: - setattr(sys, stream_name, orig_stdout) - -def captured_stdout(): - """Capture the output of sys.stdout: - - with captured_stdout() as s: - print("hello") - self.assertEqual(s.getvalue(), "hello") - """ - return captured_output("stdout") - -def captured_stderr(): - return captured_output("stderr") - -def captured_stdin(): - return captured_output("stdin") - - -def gc_collect(): - """Force as many objects as possible to be collected. - - In non-CPython implementations of Python, this is needed because timely - deallocation is not guaranteed by the garbage collector. (Even in CPython - this can be the case in case of reference cycles.) This means that __del__ - methods may be called later than expected and weakrefs may remain alive for - longer than expected. This function tries its best to force all garbage - objects to disappear. - """ - gc.collect() - if is_jython: - time.sleep(0.1) - gc.collect() - gc.collect() - - -def python_is_optimized(): - """Find if Python was built with optimizations.""" - cflags = sysconfig.get_config_var('PY_CFLAGS') or '' - final_opt = "" - for opt in cflags.split(): - if opt.startswith('-O'): - final_opt = opt - return final_opt and final_opt != '-O0' - - -#======================================================================= -# Decorator for running a function in a different locale, correctly resetting -# it afterwards. - -def run_with_locale(catstr, *locales): - def decorator(func): - def inner(*args, **kwds): - try: - import locale - category = getattr(locale, catstr) - orig_locale = locale.setlocale(category) - except AttributeError: - # if the test author gives us an invalid category string - raise - except: - # cannot retrieve original locale, so do nothing - locale = orig_locale = None - else: - for loc in locales: - try: - locale.setlocale(category, loc) - break - except: - pass - - # now run the function, resetting the locale on exceptions - try: - return func(*args, **kwds) - finally: - if locale and orig_locale: - locale.setlocale(category, orig_locale) - inner.__name__ = func.__name__ - inner.__doc__ = func.__doc__ - return inner - return decorator - -#======================================================================= -# Big-memory-test support. Separate from 'resources' because memory use -# should be configurable. - -# Some handy shorthands. Note that these are used for byte-limits as well -# as size-limits, in the various bigmem tests -_1M = 1024*1024 -_1G = 1024 * _1M -_2G = 2 * _1G -_4G = 4 * _1G - -MAX_Py_ssize_t = sys.maxsize - -def set_memlimit(limit): - global max_memuse - global real_max_memuse - sizes = { - 'k': 1024, - 'm': _1M, - 'g': _1G, - 't': 1024*_1G, - } - m = re.match(r'(\d+(\.\d+)?) (K|M|G|T)b?$', limit, - re.IGNORECASE | re.VERBOSE) - if m is None: - raise ValueError('Invalid memory limit %r' % (limit,)) - memlimit = int(float(m.group(1)) * sizes[m.group(3).lower()]) - real_max_memuse = memlimit - if memlimit > MAX_Py_ssize_t: - memlimit = MAX_Py_ssize_t - if memlimit < _2G - 1: - raise ValueError('Memory limit %r too low to be useful' % (limit,)) - max_memuse = memlimit - -def _memory_watchdog(start_evt, finish_evt, period=10.0): - """A function which periodically watches the process' memory consumption - and prints it out. - """ - # XXX: because of the GIL, and because the very long operations tested - # in most bigmem tests are uninterruptible, the loop below gets woken up - # much less often than expected. - # The polling code should be rewritten in raw C, without holding the GIL, - # and push results onto an anonymous pipe. - try: - page_size = os.sysconf('SC_PAGESIZE') - except (ValueError, AttributeError): - try: - page_size = os.sysconf('SC_PAGE_SIZE') - except (ValueError, AttributeError): - page_size = 4096 - procfile = '/proc/{pid}/statm'.format(pid=os.getpid()) - try: - f = open(procfile, 'rb') - except IOError as e: - warnings.warn('/proc not available for stats: {}'.format(e), - RuntimeWarning) - sys.stderr.flush() - return - with f: - start_evt.set() - old_data = -1 - while not finish_evt.wait(period): - f.seek(0) - statm = f.read().decode('ascii') - data = int(statm.split()[5]) - if data != old_data: - old_data = data - print(" ... process data size: {data:.1f}G" - .format(data=data * page_size / (1024 ** 3))) - -def bigmemtest(size, memuse, dry_run=True): - """Decorator for bigmem tests. - - 'minsize' is the minimum useful size for the test (in arbitrary, - test-interpreted units.) 'memuse' is the number of 'bytes per size' for - the test, or a good estimate of it. - - if 'dry_run' is False, it means the test doesn't support dummy runs - when -M is not specified. - """ - def decorator(f): - def wrapper(self): - size = wrapper.size - memuse = wrapper.memuse - if not real_max_memuse: - maxsize = 5147 - else: - maxsize = size - - if ((real_max_memuse or not dry_run) - and real_max_memuse < maxsize * memuse): - raise unittest.SkipTest( - "not enough memory: %.1fG minimum needed" - % (size * memuse / (1024 ** 3))) - - if real_max_memuse and verbose and threading: - print() - print(" ... expected peak memory use: {peak:.1f}G" - .format(peak=size * memuse / (1024 ** 3))) - sys.stdout.flush() - start_evt = threading.Event() - finish_evt = threading.Event() - t = threading.Thread(target=_memory_watchdog, - args=(start_evt, finish_evt, 0.5)) - t.daemon = True - t.start() - start_evt.set() - else: - t = None - - try: - return f(self, maxsize) - finally: - if t: - finish_evt.set() - t.join() - - wrapper.size = size - wrapper.memuse = memuse - return wrapper - return decorator - -def bigaddrspacetest(f): - """Decorator for tests that fill the address space.""" - def wrapper(self): - if max_memuse < MAX_Py_ssize_t: - if MAX_Py_ssize_t >= 2**63 - 1 and max_memuse >= 2**31: - raise unittest.SkipTest( - "not enough memory: try a 32-bit build instead") - else: - raise unittest.SkipTest( - "not enough memory: %.1fG minimum needed" - % (MAX_Py_ssize_t / (1024 ** 3))) - else: - return f(self) - return wrapper - -#======================================================================= -# unittest integration. - -class BasicTestRunner: - def run(self, test): - result = unittest.TestResult() - test(result) - return result - -def _id(obj): - return obj - -def requires_resource(resource): - if resource == 'gui' and not _is_gui_available(): - return unittest.skip("resource 'gui' is not available") - if is_resource_enabled(resource): - return _id - else: - return unittest.skip("resource {0!r} is not enabled".format(resource)) - -def cpython_only(test): - """ - Decorator for tests only applicable on CPython. - """ - return impl_detail(cpython=True)(test) - -def impl_detail(msg=None, **guards): - if check_impl_detail(**guards): - return _id - if msg is None: - guardnames, default = _parse_guards(guards) - if default: - msg = "implementation detail not available on {0}" - else: - msg = "implementation detail specific to {0}" - guardnames = sorted(guardnames.keys()) - msg = msg.format(' or '.join(guardnames)) - return unittest.skip(msg) - -def _parse_guards(guards): - # Returns a tuple ({platform_name: run_me}, default_value) - if not guards: - return ({'cpython': True}, False) - is_true = list(guards.values())[0] - assert list(guards.values()) == [is_true] * len(guards) # all True or all False - return (guards, not is_true) - -# Use the following check to guard CPython's implementation-specific tests -- -# or to run them only on the implementation(s) guarded by the arguments. -def check_impl_detail(**guards): - """This function returns True or False depending on the host platform. - Examples: - if check_impl_detail(): # only on CPython (default) - if check_impl_detail(jython=True): # only on Jython - if check_impl_detail(cpython=False): # everywhere except on CPython - """ - guards, default = _parse_guards(guards) - return guards.get(platform.python_implementation().lower(), default) - - -def _filter_suite(suite, pred): - """Recursively filter test cases in a suite based on a predicate.""" - newtests = [] - for test in suite._tests: - if isinstance(test, unittest.TestSuite): - _filter_suite(test, pred) - newtests.append(test) - else: - if pred(test): - newtests.append(test) - suite._tests = newtests - - -def _run_suite(suite): - """Run tests from a unittest.TestSuite-derived class.""" - if verbose: - runner = unittest.TextTestRunner(sys.stdout, verbosity=2, - failfast=failfast) - else: - runner = BasicTestRunner() - - result = runner.run(suite) - if not result.wasSuccessful(): - if len(result.errors) == 1 and not result.failures: - err = result.errors[0][1] - elif len(result.failures) == 1 and not result.errors: - err = result.failures[0][1] - else: - err = "multiple errors occurred" - if not verbose: err += "; run in verbose mode for details" - raise TestFailed(err) - - -def run_unittest(*classes): - """Run tests from unittest.TestCase-derived classes.""" - valid_types = (unittest.TestSuite, unittest.TestCase) - suite = unittest.TestSuite() - for cls in classes: - if isinstance(cls, str): - if cls in sys.modules: - suite.addTest(unittest.findTestCases(sys.modules[cls])) - else: - raise ValueError("str arguments must be keys in sys.modules") - elif isinstance(cls, valid_types): - suite.addTest(cls) - else: - suite.addTest(unittest.makeSuite(cls)) - def case_pred(test): - if match_tests is None: - return True - for name in test.id().split("."): - if fnmatch.fnmatchcase(name, match_tests): - return True - return False - _filter_suite(suite, case_pred) - _run_suite(suite) - - -#======================================================================= -# doctest driver. - -def run_doctest(module, verbosity=None): - """Run doctest on the given module. Return (#failures, #tests). - - If optional argument verbosity is not specified (or is None), pass - support's belief about verbosity on to doctest. Else doctest's - usual behavior is used (it searches sys.argv for -v). - """ - - import doctest - - if verbosity is None: - verbosity = verbose - else: - verbosity = None - - f, t = doctest.testmod(module, verbose=verbosity) - if f: - raise TestFailed("%d of %d doctests failed" % (f, t)) - if verbose: - print('doctest (%s) ... %d tests with zero failures' % - (module.__name__, t)) - return f, t - - -#======================================================================= -# Support for saving and restoring the imported modules. - -def modules_setup(): - return sys.modules.copy(), - -def modules_cleanup(oldmodules): - # Encoders/decoders are registered permanently within the internal - # codec cache. If we destroy the corresponding modules their - # globals will be set to None which will trip up the cached functions. - encodings = [(k, v) for k, v in sys.modules.items() - if k.startswith('encodings.')] - sys.modules.clear() - sys.modules.update(encodings) - # XXX: This kind of problem can affect more than just encodings. In particular - # extension modules (such as _ssl) don't cope with reloading properly. - # Really, test modules should be cleaning out the test specific modules they - # know they added (ala test_runpy) rather than relying on this function (as - # test_importhooks and test_pkg do currently). - # Implicitly imported *real* modules should be left alone (see issue 10556). - sys.modules.update(oldmodules) - -#======================================================================= -# Threading support to prevent reporting refleaks when running regrtest.py -R - -# NOTE: we use thread._count() rather than threading.enumerate() (or the -# moral equivalent thereof) because a threading.Thread object is still alive -# until its __bootstrap() method has returned, even after it has been -# unregistered from the threading module. -# thread._count(), on the other hand, only gets decremented *after* the -# __bootstrap() method has returned, which gives us reliable reference counts -# at the end of a test run. - -def threading_setup(): - if _thread: - return _thread._count(), threading._dangling.copy() - else: - return 1, () - -def threading_cleanup(*original_values): - if not _thread: - return - _MAX_COUNT = 10 - for count in range(_MAX_COUNT): - values = _thread._count(), threading._dangling - if values == original_values: - break - time.sleep(0.1) - gc_collect() - # XXX print a warning in case of failure? - -def reap_threads(func): - """Use this function when threads are being used. This will - ensure that the threads are cleaned up even when the test fails. - If threading is unavailable this function does nothing. - """ - if not _thread: - return func - - @functools.wraps(func) - def decorator(*args): - key = threading_setup() - try: - return func(*args) - finally: - threading_cleanup(*key) - return decorator - -def reap_children(): - """Use this function at the end of test_main() whenever sub-processes - are started. This will help ensure that no extra children (zombies) - stick around to hog resources and create problems when looking - for refleaks. - """ - - # Reap all our dead child processes so we don't leave zombies around. - # These hog resources and might be causing some of the buildbots to die. - if hasattr(os, 'waitpid'): - any_process = -1 - while True: - try: - # This will raise an exception on Windows. That's ok. - pid, status = os.waitpid(any_process, os.WNOHANG) - if pid == 0: - break - except: - break - -@contextlib.contextmanager -def swap_attr(obj, attr, new_val): - """Temporary swap out an attribute with a new object. - - Usage: - with swap_attr(obj, "attr", 5): - ... - - This will set obj.attr to 5 for the duration of the with: block, - restoring the old value at the end of the block. If `attr` doesn't - exist on `obj`, it will be created and then deleted at the end of the - block. - """ - if hasattr(obj, attr): - real_val = getattr(obj, attr) - setattr(obj, attr, new_val) - try: - yield None - finally: - setattr(obj, attr, real_val) - else: - setattr(obj, attr, new_val) - try: - yield None - finally: - delattr(obj, attr) - -@contextlib.contextmanager -def swap_item(obj, item, new_val): - """Temporary swap out an item with a new object. - - Usage: - with swap_item(obj, "item", 5): - ... - - This will set obj["item"] to 5 for the duration of the with: block, - restoring the old value at the end of the block. If `item` doesn't - exist on `obj`, it will be created and then deleted at the end of the - block. - """ - if item in obj: - real_val = obj[item] - obj[item] = new_val - try: - yield None - finally: - obj[item] = real_val - else: - obj[item] = new_val - try: - yield None - finally: - del obj[item] - -def strip_python_stderr(stderr): - """Strip the stderr of a Python process from potential debug output - emitted by the interpreter. - - This will typically be run on the result of the communicate() method - of a subprocess.Popen object. - """ - stderr = re.sub(br"\[\d+ refs\]\r?\n?$", b"", stderr).strip() - return stderr - -def args_from_interpreter_flags(): - """Return a list of command-line arguments reproducing the current - settings in sys.flags.""" - flag_opt_map = { - 'bytes_warning': 'b', - 'dont_write_bytecode': 'B', - 'hash_randomization': 'R', - 'ignore_environment': 'E', - 'no_user_site': 's', - 'no_site': 'S', - 'optimize': 'O', - 'verbose': 'v', - } - args = [] - for flag, opt in flag_opt_map.items(): - v = getattr(sys.flags, flag) - if v > 0: - args.append('-' + opt * v) - return args - -#============================================================ -# Support for assertions about logging. -#============================================================ - -class TestHandler(logging.handlers.BufferingHandler): - def __init__(self, matcher): - # BufferingHandler takes a "capacity" argument - # so as to know when to flush. As we're overriding - # shouldFlush anyway, we can set a capacity of zero. - # You can call flush() manually to clear out the - # buffer. - logging.handlers.BufferingHandler.__init__(self, 0) - self.matcher = matcher - - def shouldFlush(self, record): - return False - - def emit(self, record): - self.format(record) - self.buffer.append(record.__dict__) - - def matches(self, **kwargs): - """ - Look for a saved dict whose keys/values match the supplied arguments. - """ - result = False - for d in self.buffer: - if self.matcher.matches(d, **kwargs): - result = True - break - return result - -class Matcher(object): - - _partial_matches = ('msg', 'message') - - def matches(self, d, **kwargs): - """ - Try to match a single dict with the supplied arguments. - - Keys whose values are strings and which are in self._partial_matches - will be checked for partial (i.e. substring) matches. You can extend - this scheme to (for example) do regular expression matching, etc. - """ - result = True - for k in kwargs: - v = kwargs[k] - dv = d.get(k) - if not self.match_value(k, dv, v): - result = False - break - return result - - def match_value(self, k, dv, v): - """ - Try to match a single stored value (dv) with a supplied value (v). - """ - if type(v) != type(dv): - result = False - elif type(dv) is not str or k not in self._partial_matches: - result = (v == dv) - else: - result = dv.find(v) >= 0 - return result - - -_can_symlink = None # type: Any -def can_symlink(): - global _can_symlink - if _can_symlink is not None: - return _can_symlink - symlink_path = TESTFN + "can_symlink" - try: - os.symlink(TESTFN, symlink_path) - can = True - except (OSError, NotImplementedError, AttributeError): - can = False - else: - os.remove(symlink_path) - _can_symlink = can - return can - -def skip_unless_symlink(test): - """Skip decorator for tests that require functional symlink""" - ok = can_symlink() - msg = "Requires functional symlink implementation" - if ok: - return test - else: - return unittest.skip(msg)(test) - -def patch(test_instance, object_to_patch, attr_name, new_value): - """Override 'object_to_patch'.'attr_name' with 'new_value'. - - Also, add a cleanup procedure to 'test_instance' to restore - 'object_to_patch' value for 'attr_name'. - The 'attr_name' should be a valid attribute for 'object_to_patch'. - - """ - # check that 'attr_name' is a real attribute for 'object_to_patch' - # will raise AttributeError if it does not exist - getattr(object_to_patch, attr_name) - - # keep a copy of the old value - attr_is_local = False - try: - old_value = object_to_patch.__dict__[attr_name] - except (AttributeError, KeyError): - old_value = getattr(object_to_patch, attr_name, None) - else: - attr_is_local = True - - # restore the value when the test is done - def cleanup(): - if attr_is_local: - setattr(object_to_patch, attr_name, old_value) - else: - delattr(object_to_patch, attr_name) - - test_instance.addCleanup(cleanup) - - # actually override the attribute - setattr(object_to_patch, attr_name, new_value) diff --git a/test-data/stdlib-samples/3.2/test/test_base64.py b/test-data/stdlib-samples/3.2/test/test_base64.py deleted file mode 100644 index 9e4dcf5544ed4..0000000000000 --- a/test-data/stdlib-samples/3.2/test/test_base64.py +++ /dev/null @@ -1,267 +0,0 @@ -import unittest -from test import support -import base64 -import binascii -import sys -import subprocess - -from typing import Any - - - -class LegacyBase64TestCase(unittest.TestCase): - def test_encodebytes(self) -> None: - eq = self.assertEqual - eq(base64.encodebytes(b"www.python.org"), b"d3d3LnB5dGhvbi5vcmc=\n") - eq(base64.encodebytes(b"a"), b"YQ==\n") - eq(base64.encodebytes(b"ab"), b"YWI=\n") - eq(base64.encodebytes(b"abc"), b"YWJj\n") - eq(base64.encodebytes(b""), b"") - eq(base64.encodebytes(b"abcdefghijklmnopqrstuvwxyz" - b"ABCDEFGHIJKLMNOPQRSTUVWXYZ" - b"0123456789!@#0^&*();:<>,. []{}"), - b"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE" - b"RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0\nNT" - b"Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ==\n") - self.assertRaises(TypeError, base64.encodebytes, "") - - def test_decodebytes(self) -> None: - eq = self.assertEqual - eq(base64.decodebytes(b"d3d3LnB5dGhvbi5vcmc=\n"), b"www.python.org") - eq(base64.decodebytes(b"YQ==\n"), b"a") - eq(base64.decodebytes(b"YWI=\n"), b"ab") - eq(base64.decodebytes(b"YWJj\n"), b"abc") - eq(base64.decodebytes(b"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE" - b"RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0\nNT" - b"Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ==\n"), - b"abcdefghijklmnopqrstuvwxyz" - b"ABCDEFGHIJKLMNOPQRSTUVWXYZ" - b"0123456789!@#0^&*();:<>,. []{}") - eq(base64.decodebytes(b''), b'') - self.assertRaises(TypeError, base64.decodebytes, "") - - def test_encode(self) -> None: - eq = self.assertEqual - from io import BytesIO - infp = BytesIO(b'abcdefghijklmnopqrstuvwxyz' - b'ABCDEFGHIJKLMNOPQRSTUVWXYZ' - b'0123456789!@#0^&*();:<>,. []{}') - outfp = BytesIO() - base64.encode(infp, outfp) - eq(outfp.getvalue(), - b'YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE' - b'RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0\nNT' - b'Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ==\n') - - def test_decode(self) -> None: - from io import BytesIO - infp = BytesIO(b'd3d3LnB5dGhvbi5vcmc=') - outfp = BytesIO() - base64.decode(infp, outfp) - self.assertEqual(outfp.getvalue(), b'www.python.org') - - -class BaseXYTestCase(unittest.TestCase): - def test_b64encode(self) -> None: - eq = self.assertEqual - # Test default alphabet - eq(base64.b64encode(b"www.python.org"), b"d3d3LnB5dGhvbi5vcmc=") - eq(base64.b64encode(b'\x00'), b'AA==') - eq(base64.b64encode(b"a"), b"YQ==") - eq(base64.b64encode(b"ab"), b"YWI=") - eq(base64.b64encode(b"abc"), b"YWJj") - eq(base64.b64encode(b""), b"") - eq(base64.b64encode(b"abcdefghijklmnopqrstuvwxyz" - b"ABCDEFGHIJKLMNOPQRSTUVWXYZ" - b"0123456789!@#0^&*();:<>,. []{}"), - b"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE" - b"RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NT" - b"Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ==") - # Test with arbitrary alternative characters - eq(base64.b64encode(b'\xd3V\xbeo\xf7\x1d', altchars=b'*$'), b'01a*b$cd') - # Check if passing a str object raises an error - self.assertRaises(TypeError, base64.b64encode, "") - self.assertRaises(TypeError, base64.b64encode, b"", altchars="") - # Test standard alphabet - eq(base64.standard_b64encode(b"www.python.org"), b"d3d3LnB5dGhvbi5vcmc=") - eq(base64.standard_b64encode(b"a"), b"YQ==") - eq(base64.standard_b64encode(b"ab"), b"YWI=") - eq(base64.standard_b64encode(b"abc"), b"YWJj") - eq(base64.standard_b64encode(b""), b"") - eq(base64.standard_b64encode(b"abcdefghijklmnopqrstuvwxyz" - b"ABCDEFGHIJKLMNOPQRSTUVWXYZ" - b"0123456789!@#0^&*();:<>,. []{}"), - b"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE" - b"RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NT" - b"Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ==") - # Check if passing a str object raises an error - self.assertRaises(TypeError, base64.standard_b64encode, "") - self.assertRaises(TypeError, base64.standard_b64encode, b"", altchars="") - # Test with 'URL safe' alternative characters - eq(base64.urlsafe_b64encode(b'\xd3V\xbeo\xf7\x1d'), b'01a-b_cd') - # Check if passing a str object raises an error - self.assertRaises(TypeError, base64.urlsafe_b64encode, "") - - def test_b64decode(self) -> None: - eq = self.assertEqual - eq(base64.b64decode(b"d3d3LnB5dGhvbi5vcmc="), b"www.python.org") - eq(base64.b64decode(b'AA=='), b'\x00') - eq(base64.b64decode(b"YQ=="), b"a") - eq(base64.b64decode(b"YWI="), b"ab") - eq(base64.b64decode(b"YWJj"), b"abc") - eq(base64.b64decode(b"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE" - b"RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0\nNT" - b"Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ=="), - b"abcdefghijklmnopqrstuvwxyz" - b"ABCDEFGHIJKLMNOPQRSTUVWXYZ" - b"0123456789!@#0^&*();:<>,. []{}") - eq(base64.b64decode(b''), b'') - # Test with arbitrary alternative characters - eq(base64.b64decode(b'01a*b$cd', altchars=b'*$'), b'\xd3V\xbeo\xf7\x1d') - # Check if passing a str object raises an error - self.assertRaises(TypeError, base64.b64decode, "") - self.assertRaises(TypeError, base64.b64decode, b"", altchars="") - # Test standard alphabet - eq(base64.standard_b64decode(b"d3d3LnB5dGhvbi5vcmc="), b"www.python.org") - eq(base64.standard_b64decode(b"YQ=="), b"a") - eq(base64.standard_b64decode(b"YWI="), b"ab") - eq(base64.standard_b64decode(b"YWJj"), b"abc") - eq(base64.standard_b64decode(b""), b"") - eq(base64.standard_b64decode(b"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE" - b"RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NT" - b"Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ=="), - b"abcdefghijklmnopqrstuvwxyz" - b"ABCDEFGHIJKLMNOPQRSTUVWXYZ" - b"0123456789!@#0^&*();:<>,. []{}") - # Check if passing a str object raises an error - self.assertRaises(TypeError, base64.standard_b64decode, "") - self.assertRaises(TypeError, base64.standard_b64decode, b"", altchars="") - # Test with 'URL safe' alternative characters - eq(base64.urlsafe_b64decode(b'01a-b_cd'), b'\xd3V\xbeo\xf7\x1d') - self.assertRaises(TypeError, base64.urlsafe_b64decode, "") - - def test_b64decode_padding_error(self) -> None: - self.assertRaises(binascii.Error, base64.b64decode, b'abc') - - def test_b64decode_invalid_chars(self) -> None: - # issue 1466065: Test some invalid characters. - tests = ((b'%3d==', b'\xdd'), - (b'$3d==', b'\xdd'), - (b'[==', b''), - (b'YW]3=', b'am'), - (b'3{d==', b'\xdd'), - (b'3d}==', b'\xdd'), - (b'@@', b''), - (b'!', b''), - (b'YWJj\nYWI=', b'abcab')) - for bstr, res in tests: - self.assertEqual(base64.b64decode(bstr), res) - with self.assertRaises(binascii.Error): - base64.b64decode(bstr, validate=True) - - def test_b32encode(self) -> None: - eq = self.assertEqual - eq(base64.b32encode(b''), b'') - eq(base64.b32encode(b'\x00'), b'AA======') - eq(base64.b32encode(b'a'), b'ME======') - eq(base64.b32encode(b'ab'), b'MFRA====') - eq(base64.b32encode(b'abc'), b'MFRGG===') - eq(base64.b32encode(b'abcd'), b'MFRGGZA=') - eq(base64.b32encode(b'abcde'), b'MFRGGZDF') - self.assertRaises(TypeError, base64.b32encode, "") - - def test_b32decode(self) -> None: - eq = self.assertEqual - eq(base64.b32decode(b''), b'') - eq(base64.b32decode(b'AA======'), b'\x00') - eq(base64.b32decode(b'ME======'), b'a') - eq(base64.b32decode(b'MFRA===='), b'ab') - eq(base64.b32decode(b'MFRGG==='), b'abc') - eq(base64.b32decode(b'MFRGGZA='), b'abcd') - eq(base64.b32decode(b'MFRGGZDF'), b'abcde') - self.assertRaises(TypeError, base64.b32decode, "") - - def test_b32decode_casefold(self) -> None: - eq = self.assertEqual - eq(base64.b32decode(b'', True), b'') - eq(base64.b32decode(b'ME======', True), b'a') - eq(base64.b32decode(b'MFRA====', True), b'ab') - eq(base64.b32decode(b'MFRGG===', True), b'abc') - eq(base64.b32decode(b'MFRGGZA=', True), b'abcd') - eq(base64.b32decode(b'MFRGGZDF', True), b'abcde') - # Lower cases - eq(base64.b32decode(b'me======', True), b'a') - eq(base64.b32decode(b'mfra====', True), b'ab') - eq(base64.b32decode(b'mfrgg===', True), b'abc') - eq(base64.b32decode(b'mfrggza=', True), b'abcd') - eq(base64.b32decode(b'mfrggzdf', True), b'abcde') - # Expected exceptions - self.assertRaises(TypeError, base64.b32decode, b'me======') - # Mapping zero and one - eq(base64.b32decode(b'MLO23456'), b'b\xdd\xad\xf3\xbe') - eq(base64.b32decode(b'M1023456', map01=b'L'), b'b\xdd\xad\xf3\xbe') - eq(base64.b32decode(b'M1023456', map01=b'I'), b'b\x1d\xad\xf3\xbe') - self.assertRaises(TypeError, base64.b32decode, b"", map01="") - - def test_b32decode_error(self) -> None: - self.assertRaises(binascii.Error, base64.b32decode, b'abc') - self.assertRaises(binascii.Error, base64.b32decode, b'ABCDEF==') - - def test_b16encode(self) -> None: - eq = self.assertEqual - eq(base64.b16encode(b'\x01\x02\xab\xcd\xef'), b'0102ABCDEF') - eq(base64.b16encode(b'\x00'), b'00') - self.assertRaises(TypeError, base64.b16encode, "") - - def test_b16decode(self) -> None: - eq = self.assertEqual - eq(base64.b16decode(b'0102ABCDEF'), b'\x01\x02\xab\xcd\xef') - eq(base64.b16decode(b'00'), b'\x00') - # Lower case is not allowed without a flag - self.assertRaises(binascii.Error, base64.b16decode, b'0102abcdef') - # Case fold - eq(base64.b16decode(b'0102abcdef', True), b'\x01\x02\xab\xcd\xef') - self.assertRaises(TypeError, base64.b16decode, "") - - def test_ErrorHeritage(self) -> None: - self.assertTrue(issubclass(binascii.Error, ValueError)) - - - -class TestMain(unittest.TestCase): - def get_output(self, *args_tuple: str, **options: Any) -> Any: - args = [sys.executable, '-m', 'base64'] + list(args_tuple) - return subprocess.check_output(args, **options) - - def test_encode_decode(self) -> None: - output = self.get_output('-t') - self.assertSequenceEqual(output.splitlines(), [ - b"b'Aladdin:open sesame'", - br"b'QWxhZGRpbjpvcGVuIHNlc2FtZQ==\n'", - b"b'Aladdin:open sesame'", - ]) - - def test_encode_file(self) -> None: - with open(support.TESTFN, 'wb') as fp: - fp.write(b'a\xffb\n') - - output = self.get_output('-e', support.TESTFN) - self.assertEqual(output.rstrip(), b'Yf9iCg==') - - with open(support.TESTFN, 'rb') as fp: - output = self.get_output('-e', stdin=fp) - self.assertEqual(output.rstrip(), b'Yf9iCg==') - - def test_decode(self) -> None: - with open(support.TESTFN, 'wb') as fp: - fp.write(b'Yf9iCg==') - output = self.get_output('-d', support.TESTFN) - self.assertEqual(output.rstrip(), b'a\xffb') - - - -def test_main() -> None: - support.run_unittest(__name__) - -if __name__ == '__main__': - test_main() diff --git a/test-data/stdlib-samples/3.2/test/test_fnmatch.py b/test-data/stdlib-samples/3.2/test/test_fnmatch.py deleted file mode 100644 index b5309c118be02..0000000000000 --- a/test-data/stdlib-samples/3.2/test/test_fnmatch.py +++ /dev/null @@ -1,93 +0,0 @@ -"""Test cases for the fnmatch module.""" - -from test import support -import unittest - -from fnmatch import fnmatch, fnmatchcase, translate, filter - -from typing import Any, AnyStr, Callable - -class FnmatchTestCase(unittest.TestCase): - - def check_match(self, filename: AnyStr, pattern: AnyStr, - should_match: int = 1, - fn: Any = fnmatch) -> None: # see #270 - if should_match: - self.assertTrue(fn(filename, pattern), - "expected %r to match pattern %r" - % (filename, pattern)) - else: - self.assertTrue(not fn(filename, pattern), - "expected %r not to match pattern %r" - % (filename, pattern)) - - def test_fnmatch(self) -> None: - check = self.check_match - check('abc', 'abc') - check('abc', '?*?') - check('abc', '???*') - check('abc', '*???') - check('abc', '???') - check('abc', '*') - check('abc', 'ab[cd]') - check('abc', 'ab[!de]') - check('abc', 'ab[de]', 0) - check('a', '??', 0) - check('a', 'b', 0) - - # these test that '\' is handled correctly in character sets; - # see SF bug #409651 - check('\\', r'[\]') - check('a', r'[!\]') - check('\\', r'[!\]', 0) - - # test that filenames with newlines in them are handled correctly. - # http://bugs.python.org/issue6665 - check('foo\nbar', 'foo*') - check('foo\nbar\n', 'foo*') - check('\nfoo', 'foo*', False) - check('\n', '*') - - def test_mix_bytes_str(self) -> None: - self.assertRaises(TypeError, fnmatch, 'test', b'*') - self.assertRaises(TypeError, fnmatch, b'test', '*') - self.assertRaises(TypeError, fnmatchcase, 'test', b'*') - self.assertRaises(TypeError, fnmatchcase, b'test', '*') - - def test_fnmatchcase(self) -> None: - check = self.check_match - check('AbC', 'abc', 0, fnmatchcase) - check('abc', 'AbC', 0, fnmatchcase) - - def test_bytes(self) -> None: - self.check_match(b'test', b'te*') - self.check_match(b'test\xff', b'te*\xff') - self.check_match(b'foo\nbar', b'foo*') - -class TranslateTestCase(unittest.TestCase): - - def test_translate(self) -> None: - self.assertEqual(translate('*'), r'.*\Z(?ms)') - self.assertEqual(translate('?'), r'.\Z(?ms)') - self.assertEqual(translate('a?b*'), r'a.b.*\Z(?ms)') - self.assertEqual(translate('[abc]'), r'[abc]\Z(?ms)') - self.assertEqual(translate('[]]'), r'[]]\Z(?ms)') - self.assertEqual(translate('[!x]'), r'[^x]\Z(?ms)') - self.assertEqual(translate('[^x]'), r'[\\^x]\Z(?ms)') - self.assertEqual(translate('[x'), r'\\[x\Z(?ms)') - - -class FilterTestCase(unittest.TestCase): - - def test_filter(self) -> None: - self.assertEqual(filter(['a', 'b'], 'a'), ['a']) - - -def test_main() -> None: - support.run_unittest(FnmatchTestCase, - TranslateTestCase, - FilterTestCase) - - -if __name__ == "__main__": - test_main() diff --git a/test-data/stdlib-samples/3.2/test/test_genericpath.py b/test-data/stdlib-samples/3.2/test/test_genericpath.py deleted file mode 100644 index df0e10701d393..0000000000000 --- a/test-data/stdlib-samples/3.2/test/test_genericpath.py +++ /dev/null @@ -1,313 +0,0 @@ -""" -Tests common to genericpath, macpath, ntpath and posixpath -""" - -import unittest -from test import support -import os - -import genericpath -import imp -imp.reload(genericpath) # Make sure we are using the local copy - -import sys -from typing import Any, List - - -def safe_rmdir(dirname: str) -> None: - try: - os.rmdir(dirname) - except OSError: - pass - - -class GenericTest(unittest.TestCase): - # The path module to be tested - pathmodule = genericpath # type: Any - common_attributes = ['commonprefix', 'getsize', 'getatime', 'getctime', - 'getmtime', 'exists', 'isdir', 'isfile'] - attributes = [] # type: List[str] - - def test_no_argument(self) -> None: - for attr in self.common_attributes + self.attributes: - with self.assertRaises(TypeError): - getattr(self.pathmodule, attr)() - self.fail("{}.{}() did not raise a TypeError" - .format(self.pathmodule.__name__, attr)) - - def test_commonprefix(self) -> None: - commonprefix = self.pathmodule.commonprefix - self.assertEqual( - commonprefix([]), - "" - ) - self.assertEqual( - commonprefix(["/home/swenson/spam", "/home/swen/spam"]), - "/home/swen" - ) - self.assertEqual( - commonprefix(["/home/swen/spam", "/home/swen/eggs"]), - "/home/swen/" - ) - self.assertEqual( - commonprefix(["/home/swen/spam", "/home/swen/spam"]), - "/home/swen/spam" - ) - self.assertEqual( - commonprefix(["home:swenson:spam", "home:swen:spam"]), - "home:swen" - ) - self.assertEqual( - commonprefix([":home:swen:spam", ":home:swen:eggs"]), - ":home:swen:" - ) - self.assertEqual( - commonprefix([":home:swen:spam", ":home:swen:spam"]), - ":home:swen:spam" - ) - - self.assertEqual( - commonprefix([b"/home/swenson/spam", b"/home/swen/spam"]), - b"/home/swen" - ) - self.assertEqual( - commonprefix([b"/home/swen/spam", b"/home/swen/eggs"]), - b"/home/swen/" - ) - self.assertEqual( - commonprefix([b"/home/swen/spam", b"/home/swen/spam"]), - b"/home/swen/spam" - ) - self.assertEqual( - commonprefix([b"home:swenson:spam", b"home:swen:spam"]), - b"home:swen" - ) - self.assertEqual( - commonprefix([b":home:swen:spam", b":home:swen:eggs"]), - b":home:swen:" - ) - self.assertEqual( - commonprefix([b":home:swen:spam", b":home:swen:spam"]), - b":home:swen:spam" - ) - - testlist = ['', 'abc', 'Xbcd', 'Xb', 'XY', 'abcd', - 'aXc', 'abd', 'ab', 'aX', 'abcX'] - for s1 in testlist: - for s2 in testlist: - p = commonprefix([s1, s2]) - self.assertTrue(s1.startswith(p)) - self.assertTrue(s2.startswith(p)) - if s1 != s2: - n = len(p) - self.assertNotEqual(s1[n:n+1], s2[n:n+1]) - - def test_getsize(self) -> None: - f = open(support.TESTFN, "wb") - try: - f.write(b"foo") - f.close() - self.assertEqual(self.pathmodule.getsize(support.TESTFN), 3) - finally: - if not f.closed: - f.close() - support.unlink(support.TESTFN) - - def test_time(self) -> None: - f = open(support.TESTFN, "wb") - try: - f.write(b"foo") - f.close() - f = open(support.TESTFN, "ab") - f.write(b"bar") - f.close() - f = open(support.TESTFN, "rb") - d = f.read() - f.close() - self.assertEqual(d, b"foobar") - - self.assertLessEqual( - self.pathmodule.getctime(support.TESTFN), - self.pathmodule.getmtime(support.TESTFN) - ) - finally: - if not f.closed: - f.close() - support.unlink(support.TESTFN) - - def test_exists(self) -> None: - self.assertIs(self.pathmodule.exists(support.TESTFN), False) - f = open(support.TESTFN, "wb") - try: - f.write(b"foo") - f.close() - self.assertIs(self.pathmodule.exists(support.TESTFN), True) - if not self.pathmodule == genericpath: - self.assertIs(self.pathmodule.lexists(support.TESTFN), - True) - finally: - if not f.closed: - f.close() - support.unlink(support.TESTFN) - - def test_isdir(self) -> None: - self.assertIs(self.pathmodule.isdir(support.TESTFN), False) - f = open(support.TESTFN, "wb") - try: - f.write(b"foo") - f.close() - self.assertIs(self.pathmodule.isdir(support.TESTFN), False) - os.remove(support.TESTFN) - os.mkdir(support.TESTFN) - self.assertIs(self.pathmodule.isdir(support.TESTFN), True) - os.rmdir(support.TESTFN) - finally: - if not f.closed: - f.close() - support.unlink(support.TESTFN) - safe_rmdir(support.TESTFN) - - def test_isfile(self) -> None: - self.assertIs(self.pathmodule.isfile(support.TESTFN), False) - f = open(support.TESTFN, "wb") - try: - f.write(b"foo") - f.close() - self.assertIs(self.pathmodule.isfile(support.TESTFN), True) - os.remove(support.TESTFN) - os.mkdir(support.TESTFN) - self.assertIs(self.pathmodule.isfile(support.TESTFN), False) - os.rmdir(support.TESTFN) - finally: - if not f.closed: - f.close() - support.unlink(support.TESTFN) - safe_rmdir(support.TESTFN) - - -# Following TestCase is not supposed to be run from test_genericpath. -# It is inherited by other test modules (macpath, ntpath, posixpath). - -class CommonTest(GenericTest): - # The path module to be tested - pathmodule = None # type: Any - common_attributes = GenericTest.common_attributes + [ - # Properties - 'curdir', 'pardir', 'extsep', 'sep', - 'pathsep', 'defpath', 'altsep', 'devnull', - # Methods - 'normcase', 'splitdrive', 'expandvars', 'normpath', 'abspath', - 'join', 'split', 'splitext', 'isabs', 'basename', 'dirname', - 'lexists', 'islink', 'ismount', 'expanduser', 'normpath', 'realpath', - ] - - def test_normcase(self) -> None: - normcase = self.pathmodule.normcase - # check that normcase() is idempotent - for p in ["FoO/./BaR", b"FoO/./BaR"]: - p = normcase(p) - self.assertEqual(p, normcase(p)) - - self.assertEqual(normcase(''), '') - self.assertEqual(normcase(b''), b'') - - # check that normcase raises a TypeError for invalid types - for path in (None, True, 0, 2.5, [], bytearray(b''), {'o','o'}): - self.assertRaises(TypeError, normcase, path) - - def test_splitdrive(self) -> None: - # splitdrive for non-NT paths - splitdrive = self.pathmodule.splitdrive - self.assertEqual(splitdrive("/foo/bar"), ("", "/foo/bar")) - self.assertEqual(splitdrive("foo:bar"), ("", "foo:bar")) - self.assertEqual(splitdrive(":foo:bar"), ("", ":foo:bar")) - - self.assertEqual(splitdrive(b"/foo/bar"), (b"", b"/foo/bar")) - self.assertEqual(splitdrive(b"foo:bar"), (b"", b"foo:bar")) - self.assertEqual(splitdrive(b":foo:bar"), (b"", b":foo:bar")) - - def test_expandvars(self) -> None: - if self.pathmodule.__name__ == 'macpath': - self.skipTest('macpath.expandvars is a stub') - expandvars = self.pathmodule.expandvars - with support.EnvironmentVarGuard() as env: - env.clear() - env["foo"] = "bar" - env["{foo"] = "baz1" - env["{foo}"] = "baz2" - self.assertEqual(expandvars("foo"), "foo") - self.assertEqual(expandvars("$foo bar"), "bar bar") - self.assertEqual(expandvars("${foo}bar"), "barbar") - self.assertEqual(expandvars("$[foo]bar"), "$[foo]bar") - self.assertEqual(expandvars("$bar bar"), "$bar bar") - self.assertEqual(expandvars("$?bar"), "$?bar") - self.assertEqual(expandvars("${foo}bar"), "barbar") - self.assertEqual(expandvars("$foo}bar"), "bar}bar") - self.assertEqual(expandvars("${foo"), "${foo") - self.assertEqual(expandvars("${{foo}}"), "baz1}") - self.assertEqual(expandvars("$foo$foo"), "barbar") - self.assertEqual(expandvars("$bar$bar"), "$bar$bar") - - self.assertEqual(expandvars(b"foo"), b"foo") - self.assertEqual(expandvars(b"$foo bar"), b"bar bar") - self.assertEqual(expandvars(b"${foo}bar"), b"barbar") - self.assertEqual(expandvars(b"$[foo]bar"), b"$[foo]bar") - self.assertEqual(expandvars(b"$bar bar"), b"$bar bar") - self.assertEqual(expandvars(b"$?bar"), b"$?bar") - self.assertEqual(expandvars(b"${foo}bar"), b"barbar") - self.assertEqual(expandvars(b"$foo}bar"), b"bar}bar") - self.assertEqual(expandvars(b"${foo"), b"${foo") - self.assertEqual(expandvars(b"${{foo}}"), b"baz1}") - self.assertEqual(expandvars(b"$foo$foo"), b"barbar") - self.assertEqual(expandvars(b"$bar$bar"), b"$bar$bar") - - def test_abspath(self) -> None: - self.assertIn("foo", self.pathmodule.abspath("foo")) - self.assertIn(b"foo", self.pathmodule.abspath(b"foo")) - - # Abspath returns bytes when the arg is bytes - for path in (b'', b'foo', b'f\xf2\xf2', b'/foo', b'C:\\'): - self.assertIsInstance(self.pathmodule.abspath(path), bytes) - - def test_realpath(self) -> None: - self.assertIn("foo", self.pathmodule.realpath("foo")) - self.assertIn(b"foo", self.pathmodule.realpath(b"foo")) - - def test_normpath_issue5827(self) -> None: - # Make sure normpath preserves unicode - for path in ('', '.', '/', '\\', '///foo/.//bar//'): - self.assertIsInstance(self.pathmodule.normpath(path), str) - - def test_abspath_issue3426(self) -> None: - # Check that abspath returns unicode when the arg is unicode - # with both ASCII and non-ASCII cwds. - abspath = self.pathmodule.abspath - for path in ('', 'fuu', 'f\xf9\xf9', '/fuu', 'U:\\'): - self.assertIsInstance(abspath(path), str) - - unicwd = '\xe7w\xf0' - try: - fsencoding = support.TESTFN_ENCODING or "ascii" - unicwd.encode(fsencoding) - except (AttributeError, UnicodeEncodeError): - # FS encoding is probably ASCII - pass - else: - with support.temp_cwd(unicwd): - for path in ('', 'fuu', 'f\xf9\xf9', '/fuu', 'U:\\'): - self.assertIsInstance(abspath(path), str) - - @unittest.skipIf(sys.platform == 'darwin', - "Mac OS X denies the creation of a directory with an invalid utf8 name") - def test_nonascii_abspath(self) -> None: - # Test non-ASCII, non-UTF8 bytes in the path. - with support.temp_cwd(b'\xe7w\xf0'): - self.test_abspath() - - -def test_main() -> None: - support.run_unittest(GenericTest) - - -if __name__=="__main__": - test_main() diff --git a/test-data/stdlib-samples/3.2/test/test_getopt.py b/test-data/stdlib-samples/3.2/test/test_getopt.py deleted file mode 100644 index 33205521ebd2c..0000000000000 --- a/test-data/stdlib-samples/3.2/test/test_getopt.py +++ /dev/null @@ -1,190 +0,0 @@ -# test_getopt.py -# David Goodger 2000-08-19 - -from test.support import verbose, run_doctest, run_unittest, EnvironmentVarGuard -import unittest - -import getopt - -from typing import cast, Any - -sentinel = object() - -class GetoptTests(unittest.TestCase): - def setUp(self) -> None: - self.env = EnvironmentVarGuard() - if "POSIXLY_CORRECT" in self.env: - del self.env["POSIXLY_CORRECT"] - - def tearDown(self) -> None: - self.env.__exit__() - del self.env - - def assertError(self, *args: Any, **kwargs: Any) -> None: - # JLe: work around mypy bug #229 - cast(Any, self.assertRaises)(getopt.GetoptError, *args, **kwargs) - - def test_short_has_arg(self) -> None: - self.assertTrue(getopt.short_has_arg('a', 'a:')) - self.assertFalse(getopt.short_has_arg('a', 'a')) - self.assertError(getopt.short_has_arg, 'a', 'b') - - def test_long_has_args(self) -> None: - has_arg, option = getopt.long_has_args('abc', ['abc=']) - self.assertTrue(has_arg) - self.assertEqual(option, 'abc') - - has_arg, option = getopt.long_has_args('abc', ['abc']) - self.assertFalse(has_arg) - self.assertEqual(option, 'abc') - - has_arg, option = getopt.long_has_args('abc', ['abcd']) - self.assertFalse(has_arg) - self.assertEqual(option, 'abcd') - - self.assertError(getopt.long_has_args, 'abc', ['def']) - self.assertError(getopt.long_has_args, 'abc', []) - self.assertError(getopt.long_has_args, 'abc', ['abcd','abcde']) - - def test_do_shorts(self) -> None: - opts, args = getopt.do_shorts([], 'a', 'a', []) - self.assertEqual(opts, [('-a', '')]) - self.assertEqual(args, []) - - opts, args = getopt.do_shorts([], 'a1', 'a:', []) - self.assertEqual(opts, [('-a', '1')]) - self.assertEqual(args, []) - - #opts, args = getopt.do_shorts([], 'a=1', 'a:', []) - #self.assertEqual(opts, [('-a', '1')]) - #self.assertEqual(args, []) - - opts, args = getopt.do_shorts([], 'a', 'a:', ['1']) - self.assertEqual(opts, [('-a', '1')]) - self.assertEqual(args, []) - - opts, args = getopt.do_shorts([], 'a', 'a:', ['1', '2']) - self.assertEqual(opts, [('-a', '1')]) - self.assertEqual(args, ['2']) - - self.assertError(getopt.do_shorts, [], 'a1', 'a', []) - self.assertError(getopt.do_shorts, [], 'a', 'a:', []) - - def test_do_longs(self) -> None: - opts, args = getopt.do_longs([], 'abc', ['abc'], []) - self.assertEqual(opts, [('--abc', '')]) - self.assertEqual(args, []) - - opts, args = getopt.do_longs([], 'abc=1', ['abc='], []) - self.assertEqual(opts, [('--abc', '1')]) - self.assertEqual(args, []) - - opts, args = getopt.do_longs([], 'abc=1', ['abcd='], []) - self.assertEqual(opts, [('--abcd', '1')]) - self.assertEqual(args, []) - - opts, args = getopt.do_longs([], 'abc', ['ab', 'abc', 'abcd'], []) - self.assertEqual(opts, [('--abc', '')]) - self.assertEqual(args, []) - - # Much like the preceding, except with a non-alpha character ("-") in - # option name that precedes "="; failed in - # http://python.org/sf/126863 - opts, args = getopt.do_longs([], 'foo=42', ['foo-bar', 'foo=',], []) - self.assertEqual(opts, [('--foo', '42')]) - self.assertEqual(args, []) - - self.assertError(getopt.do_longs, [], 'abc=1', ['abc'], []) - self.assertError(getopt.do_longs, [], 'abc', ['abc='], []) - - def test_getopt(self) -> None: - # note: the empty string between '-a' and '--beta' is significant: - # it simulates an empty string option argument ('-a ""') on the - # command line. - cmdline = ['-a', '1', '-b', '--alpha=2', '--beta', '-a', '3', '-a', - '', '--beta', 'arg1', 'arg2'] - - opts, args = getopt.getopt(cmdline, 'a:b', ['alpha=', 'beta']) - self.assertEqual(opts, [('-a', '1'), ('-b', ''), - ('--alpha', '2'), ('--beta', ''), - ('-a', '3'), ('-a', ''), ('--beta', '')]) - # Note ambiguity of ('-b', '') and ('-a', '') above. This must be - # accounted for in the code that calls getopt(). - self.assertEqual(args, ['arg1', 'arg2']) - - self.assertError(getopt.getopt, cmdline, 'a:b', ['alpha', 'beta']) - - def test_gnu_getopt(self) -> None: - # Test handling of GNU style scanning mode. - cmdline = ['-a', 'arg1', '-b', '1', '--alpha', '--beta=2'] - - # GNU style - opts, args = getopt.gnu_getopt(cmdline, 'ab:', ['alpha', 'beta=']) - self.assertEqual(args, ['arg1']) - self.assertEqual(opts, [('-a', ''), ('-b', '1'), - ('--alpha', ''), ('--beta', '2')]) - - # recognize "-" as an argument - opts, args = getopt.gnu_getopt(['-a', '-', '-b', '-'], 'ab:', []) - self.assertEqual(args, ['-']) - self.assertEqual(opts, [('-a', ''), ('-b', '-')]) - - # Posix style via + - opts, args = getopt.gnu_getopt(cmdline, '+ab:', ['alpha', 'beta=']) - self.assertEqual(opts, [('-a', '')]) - self.assertEqual(args, ['arg1', '-b', '1', '--alpha', '--beta=2']) - - # Posix style via POSIXLY_CORRECT - self.env["POSIXLY_CORRECT"] = "1" - opts, args = getopt.gnu_getopt(cmdline, 'ab:', ['alpha', 'beta=']) - self.assertEqual(opts, [('-a', '')]) - self.assertEqual(args, ['arg1', '-b', '1', '--alpha', '--beta=2']) - - def test_libref_examples(self) -> None: - s = """ - Examples from the Library Reference: Doc/lib/libgetopt.tex - - An example using only Unix style options: - - - >>> import getopt - >>> args = '-a -b -cfoo -d bar a1 a2'.split() - >>> args - ['-a', '-b', '-cfoo', '-d', 'bar', 'a1', 'a2'] - >>> optlist, args = getopt.getopt(args, 'abc:d:') - >>> optlist - [('-a', ''), ('-b', ''), ('-c', 'foo'), ('-d', 'bar')] - >>> args - ['a1', 'a2'] - - Using long option names is equally easy: - - - >>> s = '--condition=foo --testing --output-file abc.def -x a1 a2' - >>> args = s.split() - >>> args - ['--condition=foo', '--testing', '--output-file', 'abc.def', '-x', 'a1', 'a2'] - >>> optlist, args = getopt.getopt(args, 'x', [ - ... 'condition=', 'output-file=', 'testing']) - >>> optlist - [('--condition', 'foo'), ('--testing', ''), ('--output-file', 'abc.def'), ('-x', '')] - >>> args - ['a1', 'a2'] - """ - - import types - m = types.ModuleType("libreftest", s) - run_doctest(m, verbose) - - def test_issue4629(self) -> None: - longopts, shortopts = getopt.getopt(['--help='], '', ['help=']) - self.assertEqual(longopts, [('--help', '')]) - longopts, shortopts = getopt.getopt(['--help=x'], '', ['help=']) - self.assertEqual(longopts, [('--help', 'x')]) - self.assertRaises(getopt.GetoptError, getopt.getopt, ['--help='], '', ['help']) - -def test_main() -> None: - run_unittest(GetoptTests) - -if __name__ == "__main__": - test_main() diff --git a/test-data/stdlib-samples/3.2/test/test_glob.py b/test-data/stdlib-samples/3.2/test/test_glob.py deleted file mode 100644 index 08c8932c57599..0000000000000 --- a/test-data/stdlib-samples/3.2/test/test_glob.py +++ /dev/null @@ -1,122 +0,0 @@ -import unittest -from test.support import run_unittest, TESTFN, skip_unless_symlink, can_symlink -import glob -import os -import shutil - -from typing import TypeVar, Iterable, List, cast - -T = TypeVar('T') - -class GlobTests(unittest.TestCase): - - tempdir = '' - - # JLe: work around mypy issue #231 - def norm(self, first: str, *parts: str) -> str: - return os.path.normpath(os.path.join(self.tempdir, first, *parts)) - - def mktemp(self, *parts: str) -> None: - filename = self.norm(*parts) - base, file = os.path.split(filename) - if not os.path.exists(base): - os.makedirs(base) - f = open(filename, 'w') - f.close() - - def setUp(self) -> None: - self.tempdir = TESTFN+"_dir" - self.mktemp('a', 'D') - self.mktemp('aab', 'F') - self.mktemp('aaa', 'zzzF') - self.mktemp('ZZZ') - self.mktemp('a', 'bcd', 'EF') - self.mktemp('a', 'bcd', 'efg', 'ha') - if can_symlink(): - os.symlink(self.norm('broken'), self.norm('sym1')) - os.symlink(self.norm('broken'), self.norm('sym2')) - - def tearDown(self) -> None: - shutil.rmtree(self.tempdir) - - def glob(self, *parts: str) -> List[str]: - if len(parts) == 1: - pattern = parts[0] - else: - pattern = os.path.join(*parts) - p = os.path.join(self.tempdir, pattern) - res = glob.glob(p) - self.assertEqual(list(glob.iglob(p)), res) - return res - - def assertSequencesEqual_noorder(self, l1: Iterable[T], - l2: Iterable[T]) -> None: - self.assertEqual(set(l1), set(l2)) - - def test_glob_literal(self) -> None: - eq = self.assertSequencesEqual_noorder - eq(self.glob('a'), [self.norm('a')]) - eq(self.glob('a', 'D'), [self.norm('a', 'D')]) - eq(self.glob('aab'), [self.norm('aab')]) - eq(self.glob('zymurgy'), cast(List[str], [])) # JLe: work around #230 - - # test return types are unicode, but only if os.listdir - # returns unicode filenames - uniset = set([str]) - tmp = os.listdir('.') - if set(type(x) for x in tmp) == uniset: - u1 = glob.glob('*') - u2 = glob.glob('./*') - self.assertEqual(set(type(r) for r in u1), uniset) - self.assertEqual(set(type(r) for r in u2), uniset) - - def test_glob_one_directory(self) -> None: - eq = self.assertSequencesEqual_noorder - eq(self.glob('a*'), map(self.norm, ['a', 'aab', 'aaa'])) - eq(self.glob('*a'), map(self.norm, ['a', 'aaa'])) - eq(self.glob('aa?'), map(self.norm, ['aaa', 'aab'])) - eq(self.glob('aa[ab]'), map(self.norm, ['aaa', 'aab'])) - eq(self.glob('*q'), cast(List[str], [])) # JLe: work around #230 - - def test_glob_nested_directory(self) -> None: - eq = self.assertSequencesEqual_noorder - if os.path.normcase("abCD") == "abCD": - # case-sensitive filesystem - eq(self.glob('a', 'bcd', 'E*'), [self.norm('a', 'bcd', 'EF')]) - else: - # case insensitive filesystem - eq(self.glob('a', 'bcd', 'E*'), [self.norm('a', 'bcd', 'EF'), - self.norm('a', 'bcd', 'efg')]) - eq(self.glob('a', 'bcd', '*g'), [self.norm('a', 'bcd', 'efg')]) - - def test_glob_directory_names(self) -> None: - eq = self.assertSequencesEqual_noorder - eq(self.glob('*', 'D'), [self.norm('a', 'D')]) - eq(self.glob('*', '*a'), cast(List[str], [])) # JLe: work around #230 - eq(self.glob('a', '*', '*', '*a'), - [self.norm('a', 'bcd', 'efg', 'ha')]) - eq(self.glob('?a?', '*F'), map(self.norm, [os.path.join('aaa', 'zzzF'), - os.path.join('aab', 'F')])) - - def test_glob_directory_with_trailing_slash(self) -> None: - # We are verifying that when there is wildcard pattern which - # ends with os.sep doesn't blow up. - res = glob.glob(self.tempdir + '*' + os.sep) - self.assertEqual(len(res), 1) - # either of these results are reasonable - self.assertIn(res[0], [self.tempdir, self.tempdir + os.sep]) - - @skip_unless_symlink - def test_glob_broken_symlinks(self) -> None: - eq = self.assertSequencesEqual_noorder - eq(self.glob('sym*'), [self.norm('sym1'), self.norm('sym2')]) - eq(self.glob('sym1'), [self.norm('sym1')]) - eq(self.glob('sym2'), [self.norm('sym2')]) - - -def test_main() -> None: - run_unittest(GlobTests) - - -if __name__ == "__main__": - test_main() diff --git a/test-data/stdlib-samples/3.2/test/test_posixpath.py b/test-data/stdlib-samples/3.2/test/test_posixpath.py deleted file mode 100644 index de98975ad92eb..0000000000000 --- a/test-data/stdlib-samples/3.2/test/test_posixpath.py +++ /dev/null @@ -1,531 +0,0 @@ -import unittest -from test import support, test_genericpath - -import posixpath -import genericpath - -import imp -imp.reload(posixpath) # Make sure we are using the local copy -imp.reload(genericpath) - -import os -import sys -from posixpath import realpath, abspath, dirname, basename - -import posix -from typing import cast, Any, TypeVar, Callable - -T = TypeVar('T') - -# An absolute path to a temporary filename for testing. We can't rely on TESTFN -# being an absolute path, so we need this. - -ABSTFN = abspath(support.TESTFN) - -def skip_if_ABSTFN_contains_backslash( - test: Callable[[T], None]) -> Callable[[T], None]: - """ - On Windows, posixpath.abspath still returns paths with backslashes - instead of posix forward slashes. If this is the case, several tests - fail, so skip them. - """ - found_backslash = '\\' in ABSTFN - msg = "ABSTFN is not a posix path - tests fail" - return [test, unittest.skip(msg)(test)][found_backslash] - -def safe_rmdir(dirname: str) -> None: - try: - os.rmdir(dirname) - except OSError: - pass - -class PosixPathTest(unittest.TestCase): - - def setUp(self) -> None: - self.tearDown() - - def tearDown(self) -> None: - for suffix in ["", "1", "2"]: - support.unlink(support.TESTFN + suffix) - safe_rmdir(support.TESTFN + suffix) - - def test_join(self) -> None: - self.assertEqual(posixpath.join("/foo", "bar", "/bar", "baz"), - "/bar/baz") - self.assertEqual(posixpath.join("/foo", "bar", "baz"), "/foo/bar/baz") - self.assertEqual(posixpath.join("/foo/", "bar/", "baz/"), - "/foo/bar/baz/") - - self.assertEqual(posixpath.join(b"/foo", b"bar", b"/bar", b"baz"), - b"/bar/baz") - self.assertEqual(posixpath.join(b"/foo", b"bar", b"baz"), - b"/foo/bar/baz") - self.assertEqual(posixpath.join(b"/foo/", b"bar/", b"baz/"), - b"/foo/bar/baz/") - - self.assertRaises(TypeError, posixpath.join, b"bytes", "str") - self.assertRaises(TypeError, posixpath.join, "str", b"bytes") - - def test_split(self) -> None: - self.assertEqual(posixpath.split("/foo/bar"), ("/foo", "bar")) - self.assertEqual(posixpath.split("/"), ("/", "")) - self.assertEqual(posixpath.split("foo"), ("", "foo")) - self.assertEqual(posixpath.split("////foo"), ("////", "foo")) - self.assertEqual(posixpath.split("//foo//bar"), ("//foo", "bar")) - - self.assertEqual(posixpath.split(b"/foo/bar"), (b"/foo", b"bar")) - self.assertEqual(posixpath.split(b"/"), (b"/", b"")) - self.assertEqual(posixpath.split(b"foo"), (b"", b"foo")) - self.assertEqual(posixpath.split(b"////foo"), (b"////", b"foo")) - self.assertEqual(posixpath.split(b"//foo//bar"), (b"//foo", b"bar")) - - def splitextTest(self, path: str, filename: str, ext: str) -> None: - self.assertEqual(posixpath.splitext(path), (filename, ext)) - self.assertEqual(posixpath.splitext("/" + path), ("/" + filename, ext)) - self.assertEqual(posixpath.splitext("abc/" + path), - ("abc/" + filename, ext)) - self.assertEqual(posixpath.splitext("abc.def/" + path), - ("abc.def/" + filename, ext)) - self.assertEqual(posixpath.splitext("/abc.def/" + path), - ("/abc.def/" + filename, ext)) - self.assertEqual(posixpath.splitext(path + "/"), - (filename + ext + "/", "")) - - pathb = bytes(path, "ASCII") - filenameb = bytes(filename, "ASCII") - extb = bytes(ext, "ASCII") - - self.assertEqual(posixpath.splitext(pathb), (filenameb, extb)) - self.assertEqual(posixpath.splitext(b"/" + pathb), - (b"/" + filenameb, extb)) - self.assertEqual(posixpath.splitext(b"abc/" + pathb), - (b"abc/" + filenameb, extb)) - self.assertEqual(posixpath.splitext(b"abc.def/" + pathb), - (b"abc.def/" + filenameb, extb)) - self.assertEqual(posixpath.splitext(b"/abc.def/" + pathb), - (b"/abc.def/" + filenameb, extb)) - self.assertEqual(posixpath.splitext(pathb + b"/"), - (filenameb + extb + b"/", b"")) - - def test_splitext(self) -> None: - self.splitextTest("foo.bar", "foo", ".bar") - self.splitextTest("foo.boo.bar", "foo.boo", ".bar") - self.splitextTest("foo.boo.biff.bar", "foo.boo.biff", ".bar") - self.splitextTest(".csh.rc", ".csh", ".rc") - self.splitextTest("nodots", "nodots", "") - self.splitextTest(".cshrc", ".cshrc", "") - self.splitextTest("...manydots", "...manydots", "") - self.splitextTest("...manydots.ext", "...manydots", ".ext") - self.splitextTest(".", ".", "") - self.splitextTest("..", "..", "") - self.splitextTest("........", "........", "") - self.splitextTest("", "", "") - - def test_isabs(self) -> None: - self.assertIs(posixpath.isabs(""), False) - self.assertIs(posixpath.isabs("/"), True) - self.assertIs(posixpath.isabs("/foo"), True) - self.assertIs(posixpath.isabs("/foo/bar"), True) - self.assertIs(posixpath.isabs("foo/bar"), False) - - self.assertIs(posixpath.isabs(b""), False) - self.assertIs(posixpath.isabs(b"/"), True) - self.assertIs(posixpath.isabs(b"/foo"), True) - self.assertIs(posixpath.isabs(b"/foo/bar"), True) - self.assertIs(posixpath.isabs(b"foo/bar"), False) - - def test_basename(self) -> None: - self.assertEqual(posixpath.basename("/foo/bar"), "bar") - self.assertEqual(posixpath.basename("/"), "") - self.assertEqual(posixpath.basename("foo"), "foo") - self.assertEqual(posixpath.basename("////foo"), "foo") - self.assertEqual(posixpath.basename("//foo//bar"), "bar") - - self.assertEqual(posixpath.basename(b"/foo/bar"), b"bar") - self.assertEqual(posixpath.basename(b"/"), b"") - self.assertEqual(posixpath.basename(b"foo"), b"foo") - self.assertEqual(posixpath.basename(b"////foo"), b"foo") - self.assertEqual(posixpath.basename(b"//foo//bar"), b"bar") - - def test_dirname(self) -> None: - self.assertEqual(posixpath.dirname("/foo/bar"), "/foo") - self.assertEqual(posixpath.dirname("/"), "/") - self.assertEqual(posixpath.dirname("foo"), "") - self.assertEqual(posixpath.dirname("////foo"), "////") - self.assertEqual(posixpath.dirname("//foo//bar"), "//foo") - - self.assertEqual(posixpath.dirname(b"/foo/bar"), b"/foo") - self.assertEqual(posixpath.dirname(b"/"), b"/") - self.assertEqual(posixpath.dirname(b"foo"), b"") - self.assertEqual(posixpath.dirname(b"////foo"), b"////") - self.assertEqual(posixpath.dirname(b"//foo//bar"), b"//foo") - - def test_islink(self) -> None: - self.assertIs(posixpath.islink(support.TESTFN + "1"), False) - self.assertIs(posixpath.lexists(support.TESTFN + "2"), False) - f = open(support.TESTFN + "1", "wb") - try: - f.write(b"foo") - f.close() - self.assertIs(posixpath.islink(support.TESTFN + "1"), False) - if support.can_symlink(): - os.symlink(support.TESTFN + "1", support.TESTFN + "2") - self.assertIs(posixpath.islink(support.TESTFN + "2"), True) - os.remove(support.TESTFN + "1") - self.assertIs(posixpath.islink(support.TESTFN + "2"), True) - self.assertIs(posixpath.exists(support.TESTFN + "2"), False) - self.assertIs(posixpath.lexists(support.TESTFN + "2"), True) - finally: - if not f.closed: - f.close() - - @staticmethod - def _create_file(filename: str) -> None: - with open(filename, 'wb') as f: - f.write(b'foo') - - def test_samefile(self) -> None: - test_fn = support.TESTFN + "1" - self._create_file(test_fn) - self.assertTrue(posixpath.samefile(test_fn, test_fn)) - self.assertRaises(TypeError, posixpath.samefile) - - @unittest.skipIf( - sys.platform.startswith('win'), - "posixpath.samefile does not work on links in Windows") - @unittest.skipUnless(hasattr(os, "symlink"), - "Missing symlink implementation") - def test_samefile_on_links(self) -> None: - test_fn1 = support.TESTFN + "1" - test_fn2 = support.TESTFN + "2" - self._create_file(test_fn1) - - os.symlink(test_fn1, test_fn2) - self.assertTrue(posixpath.samefile(test_fn1, test_fn2)) - os.remove(test_fn2) - - self._create_file(test_fn2) - self.assertFalse(posixpath.samefile(test_fn1, test_fn2)) - - - def test_samestat(self) -> None: - test_fn = support.TESTFN + "1" - self._create_file(test_fn) - test_fns = [test_fn]*2 - stats = map(os.stat, test_fns) - self.assertTrue(posixpath.samestat(*stats)) - - @unittest.skipIf( - sys.platform.startswith('win'), - "posixpath.samestat does not work on links in Windows") - @unittest.skipUnless(hasattr(os, "symlink"), - "Missing symlink implementation") - def test_samestat_on_links(self) -> None: - test_fn1 = support.TESTFN + "1" - test_fn2 = support.TESTFN + "2" - self._create_file(test_fn1) - test_fns = [test_fn1, test_fn2] - cast(Any, os.symlink)(*test_fns) - stats = map(os.stat, test_fns) - self.assertTrue(posixpath.samestat(*stats)) - os.remove(test_fn2) - - self._create_file(test_fn2) - stats = map(os.stat, test_fns) - self.assertFalse(posixpath.samestat(*stats)) - - self.assertRaises(TypeError, posixpath.samestat) - - def test_ismount(self) -> None: - self.assertIs(posixpath.ismount("/"), True) - self.assertIs(posixpath.ismount(b"/"), True) - - def test_ismount_non_existent(self) -> None: - # Non-existent mountpoint. - self.assertIs(posixpath.ismount(ABSTFN), False) - try: - os.mkdir(ABSTFN) - self.assertIs(posixpath.ismount(ABSTFN), False) - finally: - safe_rmdir(ABSTFN) - - @unittest.skipUnless(support.can_symlink(), - "Test requires symlink support") - def test_ismount_symlinks(self) -> None: - # Symlinks are never mountpoints. - try: - os.symlink("/", ABSTFN) - self.assertIs(posixpath.ismount(ABSTFN), False) - finally: - os.unlink(ABSTFN) - - @unittest.skipIf(posix is None, "Test requires posix module") - def test_ismount_different_device(self) -> None: - # Simulate the path being on a different device from its parent by - # mocking out st_dev. - save_lstat = os.lstat - def fake_lstat(path): - st_ino = 0 - st_dev = 0 - if path == ABSTFN: - st_dev = 1 - st_ino = 1 - return posix.stat_result((0, st_ino, st_dev, 0, 0, 0, 0, 0, 0, 0)) - try: - setattr(os, 'lstat', fake_lstat) # mypy: can't modify os directly - self.assertIs(posixpath.ismount(ABSTFN), True) - finally: - setattr(os, 'lstat', save_lstat) - - def test_expanduser(self) -> None: - self.assertEqual(posixpath.expanduser("foo"), "foo") - self.assertEqual(posixpath.expanduser(b"foo"), b"foo") - try: - import pwd - except ImportError: - pass - else: - self.assertIsInstance(posixpath.expanduser("~/"), str) - self.assertIsInstance(posixpath.expanduser(b"~/"), bytes) - # if home directory == root directory, this test makes no sense - if posixpath.expanduser("~") != '/': - self.assertEqual( - posixpath.expanduser("~") + "/", - posixpath.expanduser("~/") - ) - self.assertEqual( - posixpath.expanduser(b"~") + b"/", - posixpath.expanduser(b"~/") - ) - self.assertIsInstance(posixpath.expanduser("~root/"), str) - self.assertIsInstance(posixpath.expanduser("~foo/"), str) - self.assertIsInstance(posixpath.expanduser(b"~root/"), bytes) - self.assertIsInstance(posixpath.expanduser(b"~foo/"), bytes) - - with support.EnvironmentVarGuard() as env: - env['HOME'] = '/' - self.assertEqual(posixpath.expanduser("~"), "/") - # expanduser should fall back to using the password database - del env['HOME'] - home = pwd.getpwuid(os.getuid()).pw_dir - self.assertEqual(posixpath.expanduser("~"), home) - - def test_normpath(self) -> None: - self.assertEqual(posixpath.normpath(""), ".") - self.assertEqual(posixpath.normpath("/"), "/") - self.assertEqual(posixpath.normpath("//"), "//") - self.assertEqual(posixpath.normpath("///"), "/") - self.assertEqual(posixpath.normpath("///foo/.//bar//"), "/foo/bar") - self.assertEqual(posixpath.normpath("///foo/.//bar//.//..//.//baz"), - "/foo/baz") - self.assertEqual(posixpath.normpath("///..//./foo/.//bar"), "/foo/bar") - - self.assertEqual(posixpath.normpath(b""), b".") - self.assertEqual(posixpath.normpath(b"/"), b"/") - self.assertEqual(posixpath.normpath(b"//"), b"//") - self.assertEqual(posixpath.normpath(b"///"), b"/") - self.assertEqual(posixpath.normpath(b"///foo/.//bar//"), b"/foo/bar") - self.assertEqual(posixpath.normpath(b"///foo/.//bar//.//..//.//baz"), - b"/foo/baz") - self.assertEqual(posixpath.normpath(b"///..//./foo/.//bar"), - b"/foo/bar") - - @unittest.skipUnless(hasattr(os, "symlink"), - "Missing symlink implementation") - @skip_if_ABSTFN_contains_backslash - def test_realpath_basic(self) -> None: - # Basic operation. - try: - os.symlink(ABSTFN+"1", ABSTFN) - self.assertEqual(realpath(ABSTFN), ABSTFN+"1") - finally: - support.unlink(ABSTFN) - - @unittest.skipUnless(hasattr(os, "symlink"), - "Missing symlink implementation") - @skip_if_ABSTFN_contains_backslash - def test_realpath_relative(self) -> None: - try: - os.symlink(posixpath.relpath(ABSTFN+"1"), ABSTFN) - self.assertEqual(realpath(ABSTFN), ABSTFN+"1") - finally: - support.unlink(ABSTFN) - - @unittest.skipUnless(hasattr(os, "symlink"), - "Missing symlink implementation") - @skip_if_ABSTFN_contains_backslash - def test_realpath_symlink_loops(self) -> None: - # Bug #930024, return the path unchanged if we get into an infinite - # symlink loop. - try: - old_path = abspath('.') - os.symlink(ABSTFN, ABSTFN) - self.assertEqual(realpath(ABSTFN), ABSTFN) - - os.symlink(ABSTFN+"1", ABSTFN+"2") - os.symlink(ABSTFN+"2", ABSTFN+"1") - self.assertEqual(realpath(ABSTFN+"1"), ABSTFN+"1") - self.assertEqual(realpath(ABSTFN+"2"), ABSTFN+"2") - - # Test using relative path as well. - os.chdir(dirname(ABSTFN)) - self.assertEqual(realpath(basename(ABSTFN)), ABSTFN) - finally: - os.chdir(old_path) - support.unlink(ABSTFN) - support.unlink(ABSTFN+"1") - support.unlink(ABSTFN+"2") - - @unittest.skipUnless(hasattr(os, "symlink"), - "Missing symlink implementation") - @skip_if_ABSTFN_contains_backslash - def test_realpath_resolve_parents(self) -> None: - # We also need to resolve any symlinks in the parents of a relative - # path passed to realpath. E.g.: current working directory is - # /usr/doc with 'doc' being a symlink to /usr/share/doc. We call - # realpath("a"). This should return /usr/share/doc/a/. - try: - old_path = abspath('.') - os.mkdir(ABSTFN) - os.mkdir(ABSTFN + "/y") - os.symlink(ABSTFN + "/y", ABSTFN + "/k") - - os.chdir(ABSTFN + "/k") - self.assertEqual(realpath("a"), ABSTFN + "/y/a") - finally: - os.chdir(old_path) - support.unlink(ABSTFN + "/k") - safe_rmdir(ABSTFN + "/y") - safe_rmdir(ABSTFN) - - @unittest.skipUnless(hasattr(os, "symlink"), - "Missing symlink implementation") - @skip_if_ABSTFN_contains_backslash - def test_realpath_resolve_before_normalizing(self) -> None: - # Bug #990669: Symbolic links should be resolved before we - # normalize the path. E.g.: if we have directories 'a', 'k' and 'y' - # in the following hierarchy: - # a/k/y - # - # and a symbolic link 'link-y' pointing to 'y' in directory 'a', - # then realpath("link-y/..") should return 'k', not 'a'. - try: - old_path = abspath('.') - os.mkdir(ABSTFN) - os.mkdir(ABSTFN + "/k") - os.mkdir(ABSTFN + "/k/y") - os.symlink(ABSTFN + "/k/y", ABSTFN + "/link-y") - - # Absolute path. - self.assertEqual(realpath(ABSTFN + "/link-y/.."), ABSTFN + "/k") - # Relative path. - os.chdir(dirname(ABSTFN)) - self.assertEqual(realpath(basename(ABSTFN) + "/link-y/.."), - ABSTFN + "/k") - finally: - os.chdir(old_path) - support.unlink(ABSTFN + "/link-y") - safe_rmdir(ABSTFN + "/k/y") - safe_rmdir(ABSTFN + "/k") - safe_rmdir(ABSTFN) - - @unittest.skipUnless(hasattr(os, "symlink"), - "Missing symlink implementation") - @skip_if_ABSTFN_contains_backslash - def test_realpath_resolve_first(self) -> None: - # Bug #1213894: The first component of the path, if not absolute, - # must be resolved too. - - try: - old_path = abspath('.') - os.mkdir(ABSTFN) - os.mkdir(ABSTFN + "/k") - os.symlink(ABSTFN, ABSTFN + "link") - os.chdir(dirname(ABSTFN)) - - base = basename(ABSTFN) - self.assertEqual(realpath(base + "link"), ABSTFN) - self.assertEqual(realpath(base + "link/k"), ABSTFN + "/k") - finally: - os.chdir(old_path) - support.unlink(ABSTFN + "link") - safe_rmdir(ABSTFN + "/k") - safe_rmdir(ABSTFN) - - def test_relpath(self) -> None: - real_getcwd = os.getcwd - # mypy: can't modify os directly - setattr(os, 'getcwd', lambda: r"/home/user/bar") - try: - curdir = os.path.split(os.getcwd())[-1] - self.assertRaises(ValueError, posixpath.relpath, "") - self.assertEqual(posixpath.relpath("a"), "a") - self.assertEqual(posixpath.relpath(posixpath.abspath("a")), "a") - self.assertEqual(posixpath.relpath("a/b"), "a/b") - self.assertEqual(posixpath.relpath("../a/b"), "../a/b") - self.assertEqual(posixpath.relpath("a", "../b"), "../"+curdir+"/a") - self.assertEqual(posixpath.relpath("a/b", "../c"), - "../"+curdir+"/a/b") - self.assertEqual(posixpath.relpath("a", "b/c"), "../../a") - self.assertEqual(posixpath.relpath("a", "a"), ".") - self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x/y/z"), '../../../foo/bar/bat') - self.assertEqual(posixpath.relpath("/foo/bar/bat", "/foo/bar"), 'bat') - self.assertEqual(posixpath.relpath("/foo/bar/bat", "/"), 'foo/bar/bat') - self.assertEqual(posixpath.relpath("/", "/foo/bar/bat"), '../../..') - self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x"), '../foo/bar/bat') - self.assertEqual(posixpath.relpath("/x", "/foo/bar/bat"), '../../../x') - self.assertEqual(posixpath.relpath("/", "/"), '.') - self.assertEqual(posixpath.relpath("/a", "/a"), '.') - self.assertEqual(posixpath.relpath("/a/b", "/a/b"), '.') - finally: - setattr(os, 'getcwd', real_getcwd) - - def test_relpath_bytes(self) -> None: - real_getcwdb = os.getcwdb - # mypy: can't modify os directly - setattr(os, 'getcwdb', lambda: br"/home/user/bar") - try: - curdir = os.path.split(os.getcwdb())[-1] - self.assertRaises(ValueError, posixpath.relpath, b"") - self.assertEqual(posixpath.relpath(b"a"), b"a") - self.assertEqual(posixpath.relpath(posixpath.abspath(b"a")), b"a") - self.assertEqual(posixpath.relpath(b"a/b"), b"a/b") - self.assertEqual(posixpath.relpath(b"../a/b"), b"../a/b") - self.assertEqual(posixpath.relpath(b"a", b"../b"), - b"../"+curdir+b"/a") - self.assertEqual(posixpath.relpath(b"a/b", b"../c"), - b"../"+curdir+b"/a/b") - self.assertEqual(posixpath.relpath(b"a", b"b/c"), b"../../a") - self.assertEqual(posixpath.relpath(b"a", b"a"), b".") - self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x/y/z"), b'../../../foo/bar/bat') - self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/foo/bar"), b'bat') - self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/"), b'foo/bar/bat') - self.assertEqual(posixpath.relpath(b"/", b"/foo/bar/bat"), b'../../..') - self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x"), b'../foo/bar/bat') - self.assertEqual(posixpath.relpath(b"/x", b"/foo/bar/bat"), b'../../../x') - self.assertEqual(posixpath.relpath(b"/", b"/"), b'.') - self.assertEqual(posixpath.relpath(b"/a", b"/a"), b'.') - self.assertEqual(posixpath.relpath(b"/a/b", b"/a/b"), b'.') - - self.assertRaises(TypeError, posixpath.relpath, b"bytes", "str") - self.assertRaises(TypeError, posixpath.relpath, "str", b"bytes") - finally: - setattr(os, 'getcwdb', real_getcwdb) - - def test_sameopenfile(self) -> None: - fname = support.TESTFN + "1" - with open(fname, "wb") as a, open(fname, "wb") as b: - self.assertTrue(posixpath.sameopenfile(a.fileno(), b.fileno())) - - -class PosixCommonTest(test_genericpath.CommonTest): - pathmodule = posixpath - attributes = ['relpath', 'samefile', 'sameopenfile', 'samestat'] - - -def test_main() -> None: - support.run_unittest(PosixPathTest, PosixCommonTest) - - -if __name__=="__main__": - test_main() diff --git a/test-data/stdlib-samples/3.2/test/test_pprint.py b/test-data/stdlib-samples/3.2/test/test_pprint.py deleted file mode 100644 index cf54ebde6adcc..0000000000000 --- a/test-data/stdlib-samples/3.2/test/test_pprint.py +++ /dev/null @@ -1,488 +0,0 @@ -import pprint -import test.support -import unittest -import test.test_set -import random -import collections -import itertools - -from typing import List, Any, Dict, Tuple, cast, Callable - -# list, tuple and dict subclasses that do or don't overwrite __repr__ -class list2(list): - pass - -class list3(list): - def __repr__(self) -> str: - return list.__repr__(self) - -class tuple2(tuple): - pass - -class tuple3(tuple): - def __repr__(self) -> str: - return tuple.__repr__(self) - -class dict2(dict): - pass - -class dict3(dict): - def __repr__(self) -> str: - return dict.__repr__(self) - -class Unorderable: - def __repr__(self) -> str: - return str(id(self)) - -class QueryTestCase(unittest.TestCase): - - def setUp(self) -> None: - self.a = list(range(100)) # type: List[Any] - self.b = list(range(200)) # type: List[Any] - self.a[-12] = self.b - - def test_basic(self) -> None: - # Verify .isrecursive() and .isreadable() w/o recursion - pp = pprint.PrettyPrinter() - for safe in (2, 2.0, complex(0.0, 2.0), "abc", [3], (2,2), {3: 3}, "yaddayadda", - self.a, self.b): - # module-level convenience functions - self.assertFalse(pprint.isrecursive(safe), - "expected not isrecursive for %r" % (safe,)) - self.assertTrue(pprint.isreadable(safe), - "expected isreadable for %r" % (safe,)) - # PrettyPrinter methods - self.assertFalse(pp.isrecursive(safe), - "expected not isrecursive for %r" % (safe,)) - self.assertTrue(pp.isreadable(safe), - "expected isreadable for %r" % (safe,)) - - def test_knotted(self) -> None: - # Verify .isrecursive() and .isreadable() w/ recursion - # Tie a knot. - self.b[67] = self.a - # Messy dict. - self.d = {} # type: Dict[int, dict] - self.d[0] = self.d[1] = self.d[2] = self.d - - pp = pprint.PrettyPrinter() - - for icky in self.a, self.b, self.d, (self.d, self.d): - self.assertTrue(pprint.isrecursive(icky), "expected isrecursive") - self.assertFalse(pprint.isreadable(icky), "expected not isreadable") - self.assertTrue(pp.isrecursive(icky), "expected isrecursive") - self.assertFalse(pp.isreadable(icky), "expected not isreadable") - - # Break the cycles. - self.d.clear() - del self.a[:] - del self.b[:] - - for safe in self.a, self.b, self.d, (self.d, self.d): - # module-level convenience functions - self.assertFalse(pprint.isrecursive(safe), - "expected not isrecursive for %r" % (safe,)) - self.assertTrue(pprint.isreadable(safe), - "expected isreadable for %r" % (safe,)) - # PrettyPrinter methods - self.assertFalse(pp.isrecursive(safe), - "expected not isrecursive for %r" % (safe,)) - self.assertTrue(pp.isreadable(safe), - "expected isreadable for %r" % (safe,)) - - def test_unreadable(self) -> None: - # Not recursive but not readable anyway - pp = pprint.PrettyPrinter() - for unreadable in type(3), pprint, pprint.isrecursive: - # module-level convenience functions - self.assertFalse(pprint.isrecursive(unreadable), - "expected not isrecursive for %r" % (unreadable,)) - self.assertFalse(pprint.isreadable(unreadable), - "expected not isreadable for %r" % (unreadable,)) - # PrettyPrinter methods - self.assertFalse(pp.isrecursive(unreadable), - "expected not isrecursive for %r" % (unreadable,)) - self.assertFalse(pp.isreadable(unreadable), - "expected not isreadable for %r" % (unreadable,)) - - def test_same_as_repr(self) -> None: - # Simple objects, small containers and classes that overwrite __repr__ - # For those the result should be the same as repr(). - # Ahem. The docs don't say anything about that -- this appears to - # be testing an implementation quirk. Starting in Python 2.5, it's - # not true for dicts: pprint always sorts dicts by key now; before, - # it sorted a dict display if and only if the display required - # multiple lines. For that reason, dicts with more than one element - # aren't tested here. - for simple in (0, 0, complex(0.0), 0.0, "", b"", - (), tuple2(), tuple3(), - [], list2(), list3(), - {}, dict2(), dict3(), - self.assertTrue, pprint, - -6, -6, complex(-6.,-6.), -1.5, "x", b"x", (3,), [3], {3: 6}, - (1,2), [3,4], {5: 6}, - tuple2((1,2)), tuple3((1,2)), tuple3(range(100)), # type: ignore - [3,4], list2(cast(Any, [3,4])), list3(cast(Any, [3,4])), - list3(cast(Any, range(100))), dict2(cast(Any, {5: 6})), - dict3(cast(Any, {5: 6})), # JLe: work around mypy issue #233 - range(10, -11, -1) - ): - native = repr(simple) - for function in "pformat", "saferepr": - f = getattr(pprint, function) - got = f(simple) - self.assertEqual(native, got, - "expected %s got %s from pprint.%s" % - (native, got, function)) - - def test_basic_line_wrap(self) -> None: - # verify basic line-wrapping operation - o = {'RPM_cal': 0, - 'RPM_cal2': 48059, - 'Speed_cal': 0, - 'controldesk_runtime_us': 0, - 'main_code_runtime_us': 0, - 'read_io_runtime_us': 0, - 'write_io_runtime_us': 43690} - exp = """\ -{'RPM_cal': 0, - 'RPM_cal2': 48059, - 'Speed_cal': 0, - 'controldesk_runtime_us': 0, - 'main_code_runtime_us': 0, - 'read_io_runtime_us': 0, - 'write_io_runtime_us': 43690}""" - # JLe: work around mypy issue #232 - for type in cast(List[Any], [dict, dict2]): - self.assertEqual(pprint.pformat(type(o)), exp) - - o2 = range(100) - exp = '[%s]' % ',\n '.join(map(str, o2)) - for type in cast(List[Any], [list, list2]): - self.assertEqual(pprint.pformat(type(o2)), exp) - - o3 = tuple(range(100)) - exp = '(%s)' % ',\n '.join(map(str, o3)) - for type in cast(List[Any], [tuple, tuple2]): - self.assertEqual(pprint.pformat(type(o3)), exp) - - # indent parameter - o4 = range(100) - exp = '[ %s]' % ',\n '.join(map(str, o4)) - for type in cast(List[Any], [list, list2]): - self.assertEqual(pprint.pformat(type(o4), indent=4), exp) - - def test_nested_indentations(self) -> None: - o1 = list(range(10)) - o2 = {'first':1, 'second':2, 'third':3} - o = [o1, o2] - expected = """\ -[ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], - { 'first': 1, - 'second': 2, - 'third': 3}]""" - self.assertEqual(pprint.pformat(o, indent=4, width=42), expected) - - def test_sorted_dict(self) -> None: - # Starting in Python 2.5, pprint sorts dict displays by key regardless - # of how small the dictionary may be. - # Before the change, on 32-bit Windows pformat() gave order - # 'a', 'c', 'b' here, so this test failed. - d = {'a': 1, 'b': 1, 'c': 1} - self.assertEqual(pprint.pformat(d), "{'a': 1, 'b': 1, 'c': 1}") - self.assertEqual(pprint.pformat([d, d]), - "[{'a': 1, 'b': 1, 'c': 1}, {'a': 1, 'b': 1, 'c': 1}]") - - # The next one is kind of goofy. The sorted order depends on the - # alphabetic order of type names: "int" < "str" < "tuple". Before - # Python 2.5, this was in the test_same_as_repr() test. It's worth - # keeping around for now because it's one of few tests of pprint - # against a crazy mix of types. - self.assertEqual(pprint.pformat({"xy\tab\n": (3,), 5: [[]], (): {}}), - r"{5: [[]], 'xy\tab\n': (3,), (): {}}") - - def test_ordered_dict(self) -> None: - words = 'the quick brown fox jumped over a lazy dog'.split() - d = collections.OrderedDict(zip(words, itertools.count())) - self.assertEqual(pprint.pformat(d), -"""\ -{'the': 0, - 'quick': 1, - 'brown': 2, - 'fox': 3, - 'jumped': 4, - 'over': 5, - 'a': 6, - 'lazy': 7, - 'dog': 8}""") - def test_subclassing(self) -> None: - o = {'names with spaces': 'should be presented using repr()', - 'others.should.not.be': 'like.this'} - exp = """\ -{'names with spaces': 'should be presented using repr()', - others.should.not.be: like.this}""" - self.assertEqual(DottedPrettyPrinter().pformat(o), exp) - - @test.support.cpython_only - def test_set_reprs(self) -> None: - # This test creates a complex arrangement of frozensets and - # compares the pretty-printed repr against a string hard-coded in - # the test. The hard-coded repr depends on the sort order of - # frozensets. - # - # However, as the docs point out: "Since sets only define - # partial ordering (subset relationships), the output of the - # list.sort() method is undefined for lists of sets." - # - # In a nutshell, the test assumes frozenset({0}) will always - # sort before frozenset({1}), but: - # - # >>> frozenset({0}) < frozenset({1}) - # False - # >>> frozenset({1}) < frozenset({0}) - # False - # - # Consequently, this test is fragile and - # implementation-dependent. Small changes to Python's sort - # algorithm cause the test to fail when it should pass. - - self.assertEqual(pprint.pformat(set()), 'set()') - self.assertEqual(pprint.pformat(set(range(3))), '{0, 1, 2}') - self.assertEqual(pprint.pformat(frozenset()), 'frozenset()') - self.assertEqual(pprint.pformat(frozenset(range(3))), 'frozenset({0, 1, 2})') - cube_repr_tgt = """\ -{frozenset(): frozenset({frozenset({2}), frozenset({0}), frozenset({1})}), - frozenset({0}): frozenset({frozenset(), - frozenset({0, 2}), - frozenset({0, 1})}), - frozenset({1}): frozenset({frozenset(), - frozenset({1, 2}), - frozenset({0, 1})}), - frozenset({2}): frozenset({frozenset(), - frozenset({1, 2}), - frozenset({0, 2})}), - frozenset({1, 2}): frozenset({frozenset({2}), - frozenset({1}), - frozenset({0, 1, 2})}), - frozenset({0, 2}): frozenset({frozenset({2}), - frozenset({0}), - frozenset({0, 1, 2})}), - frozenset({0, 1}): frozenset({frozenset({0}), - frozenset({1}), - frozenset({0, 1, 2})}), - frozenset({0, 1, 2}): frozenset({frozenset({1, 2}), - frozenset({0, 2}), - frozenset({0, 1})})}""" - cube = test.test_set.cube(3) - self.assertEqual(pprint.pformat(cube), cube_repr_tgt) - cubo_repr_tgt = """\ -{frozenset({frozenset({0, 2}), frozenset({0})}): frozenset({frozenset({frozenset({0, - 2}), - frozenset({0, - 1, - 2})}), - frozenset({frozenset({0}), - frozenset({0, - 1})}), - frozenset({frozenset(), - frozenset({0})}), - frozenset({frozenset({2}), - frozenset({0, - 2})})}), - frozenset({frozenset({0, 1}), frozenset({1})}): frozenset({frozenset({frozenset({0, - 1}), - frozenset({0, - 1, - 2})}), - frozenset({frozenset({0}), - frozenset({0, - 1})}), - frozenset({frozenset({1}), - frozenset({1, - 2})}), - frozenset({frozenset(), - frozenset({1})})}), - frozenset({frozenset({1, 2}), frozenset({1})}): frozenset({frozenset({frozenset({1, - 2}), - frozenset({0, - 1, - 2})}), - frozenset({frozenset({2}), - frozenset({1, - 2})}), - frozenset({frozenset(), - frozenset({1})}), - frozenset({frozenset({1}), - frozenset({0, - 1})})}), - frozenset({frozenset({1, 2}), frozenset({2})}): frozenset({frozenset({frozenset({1, - 2}), - frozenset({0, - 1, - 2})}), - frozenset({frozenset({1}), - frozenset({1, - 2})}), - frozenset({frozenset({2}), - frozenset({0, - 2})}), - frozenset({frozenset(), - frozenset({2})})}), - frozenset({frozenset(), frozenset({0})}): frozenset({frozenset({frozenset({0}), - frozenset({0, - 1})}), - frozenset({frozenset({0}), - frozenset({0, - 2})}), - frozenset({frozenset(), - frozenset({1})}), - frozenset({frozenset(), - frozenset({2})})}), - frozenset({frozenset(), frozenset({1})}): frozenset({frozenset({frozenset(), - frozenset({0})}), - frozenset({frozenset({1}), - frozenset({1, - 2})}), - frozenset({frozenset(), - frozenset({2})}), - frozenset({frozenset({1}), - frozenset({0, - 1})})}), - frozenset({frozenset({2}), frozenset()}): frozenset({frozenset({frozenset({2}), - frozenset({1, - 2})}), - frozenset({frozenset(), - frozenset({0})}), - frozenset({frozenset(), - frozenset({1})}), - frozenset({frozenset({2}), - frozenset({0, - 2})})}), - frozenset({frozenset({0, 1, 2}), frozenset({0, 1})}): frozenset({frozenset({frozenset({1, - 2}), - frozenset({0, - 1, - 2})}), - frozenset({frozenset({0, - 2}), - frozenset({0, - 1, - 2})}), - frozenset({frozenset({0}), - frozenset({0, - 1})}), - frozenset({frozenset({1}), - frozenset({0, - 1})})}), - frozenset({frozenset({0}), frozenset({0, 1})}): frozenset({frozenset({frozenset(), - frozenset({0})}), - frozenset({frozenset({0, - 1}), - frozenset({0, - 1, - 2})}), - frozenset({frozenset({0}), - frozenset({0, - 2})}), - frozenset({frozenset({1}), - frozenset({0, - 1})})}), - frozenset({frozenset({2}), frozenset({0, 2})}): frozenset({frozenset({frozenset({0, - 2}), - frozenset({0, - 1, - 2})}), - frozenset({frozenset({2}), - frozenset({1, - 2})}), - frozenset({frozenset({0}), - frozenset({0, - 2})}), - frozenset({frozenset(), - frozenset({2})})}), - frozenset({frozenset({0, 1, 2}), frozenset({0, 2})}): frozenset({frozenset({frozenset({1, - 2}), - frozenset({0, - 1, - 2})}), - frozenset({frozenset({0, - 1}), - frozenset({0, - 1, - 2})}), - frozenset({frozenset({0}), - frozenset({0, - 2})}), - frozenset({frozenset({2}), - frozenset({0, - 2})})}), - frozenset({frozenset({1, 2}), frozenset({0, 1, 2})}): frozenset({frozenset({frozenset({0, - 2}), - frozenset({0, - 1, - 2})}), - frozenset({frozenset({0, - 1}), - frozenset({0, - 1, - 2})}), - frozenset({frozenset({2}), - frozenset({1, - 2})}), - frozenset({frozenset({1}), - frozenset({1, - 2})})})}""" - - cubo = test.test_set.linegraph(cube) - self.assertEqual(pprint.pformat(cubo), cubo_repr_tgt) - - def test_depth(self) -> None: - nested_tuple = (1, (2, (3, (4, (5, 6))))) - nested_dict = {1: {2: {3: {4: {5: {6: 6}}}}}} - nested_list = [1, [2, [3, [4, [5, [6, []]]]]]] - self.assertEqual(pprint.pformat(nested_tuple), repr(nested_tuple)) - self.assertEqual(pprint.pformat(nested_dict), repr(nested_dict)) - self.assertEqual(pprint.pformat(nested_list), repr(nested_list)) - - lv1_tuple = '(1, (...))' - lv1_dict = '{1: {...}}' - lv1_list = '[1, [...]]' - self.assertEqual(pprint.pformat(nested_tuple, depth=1), lv1_tuple) - self.assertEqual(pprint.pformat(nested_dict, depth=1), lv1_dict) - self.assertEqual(pprint.pformat(nested_list, depth=1), lv1_list) - - def test_sort_unorderable_values(self) -> None: - # Issue 3976: sorted pprints fail for unorderable values. - n = 20 - keys = [Unorderable() for i in range(n)] - random.shuffle(keys) - skeys = sorted(keys, key=id) - clean = lambda s: s.replace(' ', '').replace('\n','') # type: Callable[[str], str] - - self.assertEqual(clean(pprint.pformat(set(keys))), - '{' + ','.join(map(repr, skeys)) + '}') - self.assertEqual(clean(pprint.pformat(frozenset(keys))), - 'frozenset({' + ','.join(map(repr, skeys)) + '})') - self.assertEqual(clean(pprint.pformat(dict.fromkeys(keys))), - '{' + ','.join('%r:None' % k for k in skeys) + '}') - -class DottedPrettyPrinter(pprint.PrettyPrinter): - - def format(self, object: object, context: Dict[int, Any], maxlevels: int, - level: int) -> Tuple[str, int, int]: - if isinstance(object, str): - if ' ' in object: - return repr(object), 1, 0 - else: - return object, 0, 0 - else: - return pprint.PrettyPrinter.format( - self, object, context, maxlevels, level) - - -def test_main() -> None: - test.support.run_unittest(QueryTestCase) - - -if __name__ == "__main__": - test_main() diff --git a/test-data/stdlib-samples/3.2/test/test_random.py b/test-data/stdlib-samples/3.2/test/test_random.py deleted file mode 100644 index 5989ceeee2bbb..0000000000000 --- a/test-data/stdlib-samples/3.2/test/test_random.py +++ /dev/null @@ -1,533 +0,0 @@ -#!/usr/bin/env python3 - -import unittest -import random -import time -import pickle -import warnings -from math import log, exp, pi, fsum, sin -from test import support - -from typing import Any, Dict, List, Callable, Generic, TypeVar, cast - -RT = TypeVar('RT', random.Random, random.SystemRandom) - -class TestBasicOps(unittest.TestCase, Generic[RT]): - # Superclass with tests common to all generators. - # Subclasses must arrange for self.gen to retrieve the Random instance - # to be tested. - - gen = None # type: RT # Either Random or SystemRandom - - def randomlist(self, n: int) -> List[float]: - """Helper function to make a list of random numbers""" - return [self.gen.random() for i in range(n)] - - def test_autoseed(self) -> None: - self.gen.seed() - state1 = self.gen.getstate() - time.sleep(0.1) - self.gen.seed() # diffent seeds at different times - state2 = self.gen.getstate() - self.assertNotEqual(state1, state2) - - def test_saverestore(self) -> None: - N = 1000 - self.gen.seed() - state = self.gen.getstate() - randseq = self.randomlist(N) - self.gen.setstate(state) # should regenerate the same sequence - self.assertEqual(randseq, self.randomlist(N)) - - def test_seedargs(self) -> None: - for arg in [None, 0, 0, 1, 1, -1, -1, 10**20, -(10**20), - 3.14, complex(1., 2.), 'a', tuple('abc')]: - self.gen.seed(arg) - for arg in [list(range(3)), {'one': 1}]: - self.assertRaises(TypeError, self.gen.seed, arg) - self.assertRaises(TypeError, self.gen.seed, 1, 2, 3, 4) - self.assertRaises(TypeError, type(self.gen), []) # type: ignore # mypy issue 1846 - - def test_choice(self) -> None: - choice = self.gen.choice - with self.assertRaises(IndexError): - choice([]) - self.assertEqual(choice([50]), 50) - self.assertIn(choice([25, 75]), [25, 75]) - - def test_sample(self) -> None: - # For the entire allowable range of 0 <= k <= N, validate that - # the sample is of the correct length and contains only unique items - N = 100 - population = range(N) - for k in range(N+1): - s = self.gen.sample(population, k) - self.assertEqual(len(s), k) - uniq = set(s) - self.assertEqual(len(uniq), k) - self.assertTrue(uniq <= set(population)) - self.assertEqual(self.gen.sample([], 0), []) # test edge case N==k==0 - - def test_sample_distribution(self) -> None: - # For the entire allowable range of 0 <= k <= N, validate that - # sample generates all possible permutations - n = 5 - pop = range(n) - trials = 10000 # large num prevents false negatives without slowing normal case - def factorial(n: int) -> int: - if n == 0: - return 1 - return n * factorial(n - 1) - for k in range(n): - expected = factorial(n) // factorial(n-k) - perms = {} # type: Dict[tuple, object] - for i in range(trials): - perms[tuple(self.gen.sample(pop, k))] = None - if len(perms) == expected: - break - else: - self.fail() - - def test_sample_inputs(self) -> None: - # SF bug #801342 -- population can be any iterable defining __len__() - self.gen.sample(set(range(20)), 2) - self.gen.sample(range(20), 2) - self.gen.sample(range(20), 2) - self.gen.sample(str('abcdefghijklmnopqrst'), 2) - self.gen.sample(tuple('abcdefghijklmnopqrst'), 2) - - def test_sample_on_dicts(self) -> None: - self.assertRaises(TypeError, self.gen.sample, dict.fromkeys('abcdef'), 2) - - def test_gauss(self) -> None: - # Ensure that the seed() method initializes all the hidden state. In - # particular, through 2.2.1 it failed to reset a piece of state used - # by (and only by) the .gauss() method. - - for seed in 1, 12, 123, 1234, 12345, 123456, 654321: - self.gen.seed(seed) - x1 = self.gen.random() - y1 = self.gen.gauss(0, 1) - - self.gen.seed(seed) - x2 = self.gen.random() - y2 = self.gen.gauss(0, 1) - - self.assertEqual(x1, x2) - self.assertEqual(y1, y2) - - def test_pickling(self) -> None: - state = pickle.dumps(self.gen) - origseq = [self.gen.random() for i in range(10)] - newgen = pickle.loads(state) - restoredseq = [newgen.random() for i in range(10)] - self.assertEqual(origseq, restoredseq) - - def test_bug_1727780(self) -> None: - # verify that version-2-pickles can be loaded - # fine, whether they are created on 32-bit or 64-bit - # platforms, and that version-3-pickles load fine. - files = [("randv2_32.pck", 780), - ("randv2_64.pck", 866), - ("randv3.pck", 343)] - for file, value in files: - f = open(support.findfile(file),"rb") - r = pickle.load(f) - f.close() - self.assertEqual(int(r.random()*1000), value) - - def test_bug_9025(self) -> None: - # Had problem with an uneven distribution in int(n*random()) - # Verify the fix by checking that distributions fall within expectations. - n = 100000 - randrange = self.gen.randrange - k = sum(randrange(6755399441055744) % 3 == 2 for i in range(n)) - self.assertTrue(0.30 < k/n and k/n < .37, (k/n)) - -class SystemRandom_TestBasicOps(TestBasicOps[random.SystemRandom]): - gen = random.SystemRandom() - - def test_autoseed(self) -> None: - # Doesn't need to do anything except not fail - self.gen.seed() - - def test_saverestore(self) -> None: - self.assertRaises(NotImplementedError, self.gen.getstate) - self.assertRaises(NotImplementedError, self.gen.setstate, None) - - def test_seedargs(self) -> None: - # Doesn't need to do anything except not fail - self.gen.seed(100) - - def test_gauss(self) -> None: - self.gen.gauss_next = None - self.gen.seed(100) - self.assertEqual(self.gen.gauss_next, None) - - def test_pickling(self) -> None: - self.assertRaises(NotImplementedError, pickle.dumps, self.gen) - - def test_53_bits_per_float(self) -> None: - # This should pass whenever a C double has 53 bit precision. - span = 2 ** 53 # type: int - cum = 0 - for i in range(100): - cum |= int(self.gen.random() * span) - self.assertEqual(cum, span-1) - - def test_bigrand(self) -> None: - # The randrange routine should build-up the required number of bits - # in stages so that all bit positions are active. - span = 2 ** 500 # type: int - cum = 0 - for i in range(100): - r = self.gen.randrange(span) - self.assertTrue(0 <= r < span) - cum |= r - self.assertEqual(cum, span-1) - - def test_bigrand_ranges(self) -> None: - for i in [40,80, 160, 200, 211, 250, 375, 512, 550]: - start = self.gen.randrange(2 ** i) - stop = self.gen.randrange(2 ** (i-2)) - if stop <= start: - return - self.assertTrue(start <= self.gen.randrange(start, stop) < stop) - - def test_rangelimits(self) -> None: - for start, stop in [(-2,0), (-(2**60)-2,-(2**60)), (2**60,2**60+2)]: - self.assertEqual(set(range(start,stop)), - set([self.gen.randrange(start,stop) for i in range(100)])) - - def test_genrandbits(self) -> None: - # Verify ranges - for k in range(1, 1000): - self.assertTrue(0 <= self.gen.getrandbits(k) < 2**k) - - # Verify all bits active - getbits = self.gen.getrandbits - for span in [1, 2, 3, 4, 31, 32, 32, 52, 53, 54, 119, 127, 128, 129]: - cum = 0 - for i in range(100): - cum |= getbits(span) - self.assertEqual(cum, 2**span-1) - - # Verify argument checking - self.assertRaises(TypeError, self.gen.getrandbits) - self.assertRaises(TypeError, self.gen.getrandbits, 1, 2) - self.assertRaises(ValueError, self.gen.getrandbits, 0) - self.assertRaises(ValueError, self.gen.getrandbits, -1) - self.assertRaises(TypeError, self.gen.getrandbits, 10.1) - - def test_randbelow_logic(self, _log: Callable[[float, float], float] = log, - int: Callable[[float], int] = int) -> None: - # check bitcount transition points: 2**i and 2**(i+1)-1 - # show that: k = int(1.001 + _log(n, 2)) - # is equal to or one greater than the number of bits in n - for i in range(1, 1000): - n = 1 << i # check an exact power of two - numbits = i+1 - k = int(1.00001 + _log(n, 2)) - self.assertEqual(k, numbits) - self.assertEqual(n, 2**(k-1)) - - n += n - 1 # check 1 below the next power of two - k = int(1.00001 + _log(n, 2)) - self.assertIn(k, [numbits, numbits+1]) - self.assertTrue(2**k > n > 2**(k-2)) - - n -= n >> 15 # check a little farther below the next power of two - k = int(1.00001 + _log(n, 2)) - self.assertEqual(k, numbits) # note the stronger assertion - self.assertTrue(2**k > n > 2**(k-1)) # note the stronger assertion - - -class MersenneTwister_TestBasicOps(TestBasicOps[random.Random]): - gen = random.Random() - - def test_guaranteed_stable(self) -> None: - # These sequences are guaranteed to stay the same across versions of python - self.gen.seed(3456147, version=1) - self.assertEqual([self.gen.random().hex() for i in range(4)], - ['0x1.ac362300d90d2p-1', '0x1.9d16f74365005p-1', - '0x1.1ebb4352e4c4dp-1', '0x1.1a7422abf9c11p-1']) - self.gen.seed("the quick brown fox", version=2) - self.assertEqual([self.gen.random().hex() for i in range(4)], - ['0x1.1239ddfb11b7cp-3', '0x1.b3cbb5c51b120p-4', - '0x1.8c4f55116b60fp-1', '0x1.63eb525174a27p-1']) - - def test_setstate_first_arg(self) -> None: - self.assertRaises(ValueError, self.gen.setstate, (1, None, None)) - - def test_setstate_middle_arg(self) -> None: - # Wrong type, s/b tuple - self.assertRaises(TypeError, self.gen.setstate, (2, None, None)) - # Wrong length, s/b 625 - self.assertRaises(ValueError, self.gen.setstate, (2, (1,2,3), None)) - # Wrong type, s/b tuple of 625 ints - self.assertRaises(TypeError, self.gen.setstate, (2, tuple(['a',]*625), None)) - # Last element s/b an int also - self.assertRaises(TypeError, self.gen.setstate, (2, cast(Any, (0,))*624+('a',), None)) - - def test_referenceImplementation(self) -> None: - # Compare the python implementation with results from the original - # code. Create 2000 53-bit precision random floats. Compare only - # the last ten entries to show that the independent implementations - # are tracking. Here is the main() function needed to create the - # list of expected random numbers: - # void main(void){ - # int i; - # unsigned long init[4]={61731, 24903, 614, 42143}, length=4; - # init_by_array(init, length); - # for (i=0; i<2000; i++) { - # printf("%.15f ", genrand_res53()); - # if (i%5==4) printf("\n"); - # } - # } - expected = [0.45839803073713259, - 0.86057815201978782, - 0.92848331726782152, - 0.35932681119782461, - 0.081823493762449573, - 0.14332226470169329, - 0.084297823823520024, - 0.53814864671831453, - 0.089215024911993401, - 0.78486196105372907] - - self.gen.seed(61731 + (24903<<32) + (614<<64) + (42143<<96)) - actual = self.randomlist(2000)[-10:] - for a, e in zip(actual, expected): - self.assertAlmostEqual(a,e,places=14) - - def test_strong_reference_implementation(self) -> None: - # Like test_referenceImplementation, but checks for exact bit-level - # equality. This should pass on any box where C double contains - # at least 53 bits of precision (the underlying algorithm suffers - # no rounding errors -- all results are exact). - from math import ldexp - - expected = [0x0eab3258d2231f, - 0x1b89db315277a5, - 0x1db622a5518016, - 0x0b7f9af0d575bf, - 0x029e4c4db82240, - 0x04961892f5d673, - 0x02b291598e4589, - 0x11388382c15694, - 0x02dad977c9e1fe, - 0x191d96d4d334c6] - self.gen.seed(61731 + (24903<<32) + (614<<64) + (42143<<96)) - actual = self.randomlist(2000)[-10:] - for a, e in zip(actual, expected): - self.assertEqual(int(ldexp(a, 53)), e) - - def test_long_seed(self) -> None: - # This is most interesting to run in debug mode, just to make sure - # nothing blows up. Under the covers, a dynamically resized array - # is allocated, consuming space proportional to the number of bits - # in the seed. Unfortunately, that's a quadratic-time algorithm, - # so don't make this horribly big. - seed = (1 << (10000 * 8)) - 1 # about 10K bytes - self.gen.seed(seed) - - def test_53_bits_per_float(self) -> None: - # This should pass whenever a C double has 53 bit precision. - span = 2 ** 53 # type: int - cum = 0 - for i in range(100): - cum |= int(self.gen.random() * span) - self.assertEqual(cum, span-1) - - def test_bigrand(self) -> None: - # The randrange routine should build-up the required number of bits - # in stages so that all bit positions are active. - span = 2 ** 500 # type: int - cum = 0 - for i in range(100): - r = self.gen.randrange(span) - self.assertTrue(0 <= r < span) - cum |= r - self.assertEqual(cum, span-1) - - def test_bigrand_ranges(self) -> None: - for i in [40,80, 160, 200, 211, 250, 375, 512, 550]: - start = self.gen.randrange(2 ** i) - stop = self.gen.randrange(2 ** (i-2)) - if stop <= start: - return - self.assertTrue(start <= self.gen.randrange(start, stop) < stop) - - def test_rangelimits(self) -> None: - for start, stop in [(-2,0), (-(2**60)-2,-(2**60)), (2**60,2**60+2)]: - self.assertEqual(set(range(start,stop)), - set([self.gen.randrange(start,stop) for i in range(100)])) - - def test_genrandbits(self) -> None: - # Verify cross-platform repeatability - self.gen.seed(1234567) - self.assertEqual(self.gen.getrandbits(100), - 97904845777343510404718956115) - # Verify ranges - for k in range(1, 1000): - self.assertTrue(0 <= self.gen.getrandbits(k) < 2**k) - - # Verify all bits active - getbits = self.gen.getrandbits - for span in [1, 2, 3, 4, 31, 32, 32, 52, 53, 54, 119, 127, 128, 129]: - cum = 0 - for i in range(100): - cum |= getbits(span) - self.assertEqual(cum, 2**span-1) - - # Verify argument checking - self.assertRaises(TypeError, self.gen.getrandbits) - self.assertRaises(TypeError, self.gen.getrandbits, 'a') - self.assertRaises(TypeError, self.gen.getrandbits, 1, 2) - self.assertRaises(ValueError, self.gen.getrandbits, 0) - self.assertRaises(ValueError, self.gen.getrandbits, -1) - - def test_randbelow_logic(self, - _log: Callable[[int, float], float] = log, - int: Callable[[float], int] = int) -> None: - # check bitcount transition points: 2**i and 2**(i+1)-1 - # show that: k = int(1.001 + _log(n, 2)) - # is equal to or one greater than the number of bits in n - for i in range(1, 1000): - n = 1 << i # check an exact power of two - numbits = i+1 - k = int(1.00001 + _log(n, 2)) - self.assertEqual(k, numbits) - self.assertEqual(n, 2**(k-1)) - - n += n - 1 # check 1 below the next power of two - k = int(1.00001 + _log(n, 2)) - self.assertIn(k, [numbits, numbits+1]) - self.assertTrue(2**k > n > 2**(k-2)) - - n -= n >> 15 # check a little farther below the next power of two - k = int(1.00001 + _log(n, 2)) - self.assertEqual(k, numbits) # note the stronger assertion - self.assertTrue(2**k > n > 2**(k-1)) # note the stronger assertion - - def test_randrange_bug_1590891(self) -> None: - start = 1000000000000 - stop = -100000000000000000000 - step = -200 - x = self.gen.randrange(start, stop, step) - self.assertTrue(stop < x <= start) - self.assertEqual((x+stop)%step, 0) - -def gamma(z: float, sqrt2pi: float = (2.0*pi)**0.5) -> float: - # Reflection to right half of complex plane - if z < 0.5: - return pi / sin(pi*z) / gamma(1.0-z) - # Lanczos approximation with g=7 - az = z + (7.0 - 0.5) - return az ** (z-0.5) / exp(az) * sqrt2pi * fsum([ - 0.9999999999995183, - 676.5203681218835 / z, - -1259.139216722289 / (z+1.0), - 771.3234287757674 / (z+2.0), - -176.6150291498386 / (z+3.0), - 12.50734324009056 / (z+4.0), - -0.1385710331296526 / (z+5.0), - 0.9934937113930748e-05 / (z+6.0), - 0.1659470187408462e-06 / (z+7.0), - ]) - -class TestDistributions(unittest.TestCase): - def test_zeroinputs(self) -> None: - # Verify that distributions can handle a series of zero inputs' - g = random.Random() - x = [g.random() for i in range(50)] + [0.0]*5 - def patch() -> None: - setattr(g, 'random', x[:].pop) - patch(); g.uniform(1.0,10.0) - patch(); g.paretovariate(1.0) - patch(); g.expovariate(1.0) - patch(); g.weibullvariate(1.0, 1.0) - patch(); g.normalvariate(0.0, 1.0) - patch(); g.gauss(0.0, 1.0) - patch(); g.lognormvariate(0.0, 1.0) - patch(); g.vonmisesvariate(0.0, 1.0) - patch(); g.gammavariate(0.01, 1.0) - patch(); g.gammavariate(1.0, 1.0) - patch(); g.gammavariate(200.0, 1.0) - patch(); g.betavariate(3.0, 3.0) - patch(); g.triangular(0.0, 1.0, 1.0/3.0) - - def test_avg_std(self) -> None: - # Use integration to test distribution average and standard deviation. - # Only works for distributions which do not consume variates in pairs - g = random.Random() - N = 5000 - x = [i/float(N) for i in range(1,N)] - variate = None # type: Any - for variate, args, mu, sigmasqrd in [ - (g.uniform, (1.0,10.0), (10.0+1.0)/2, (10.0-1.0)**2/12), - (g.triangular, (0.0, 1.0, 1.0/3.0), 4.0/9.0, 7.0/9.0/18.0), - (g.expovariate, (1.5,), 1/1.5, 1/1.5**2), - (g.paretovariate, (5.0,), 5.0/(5.0-1), - 5.0/((5.0-1)**2*(5.0-2))), - (g.weibullvariate, (1.0, 3.0), gamma(1+1/3.0), - gamma(1+2/3.0)-gamma(1+1/3.0)**2) ]: - setattr(g, 'random', x[:].pop) - y = [] # type: List[float] - for i in range(len(x)): - try: - y.append(variate(*args)) - except IndexError: - pass - s1 = s2 = 0.0 - for e in y: - s1 += e - s2 += (e - mu) ** 2 - N = len(y) - self.assertAlmostEqual(s1/N, mu, places=2) - self.assertAlmostEqual(s2/(N-1), sigmasqrd, places=2) - -class TestModule(unittest.TestCase): - def testMagicConstants(self) -> None: - self.assertAlmostEqual(random.NV_MAGICCONST, 1.71552776992141) - self.assertAlmostEqual(random.TWOPI, 6.28318530718) - self.assertAlmostEqual(random.LOG4, 1.38629436111989) - self.assertAlmostEqual(random.SG_MAGICCONST, 2.50407739677627) - - def test__all__(self) -> None: - # tests validity but not completeness of the __all__ list - self.assertTrue(set(random.__all__) <= set(dir(random))) - - def test_random_subclass_with_kwargs(self) -> None: - # SF bug #1486663 -- this used to erroneously raise a TypeError - class Subclass(random.Random): - def __init__(self, newarg: object = None) -> None: - random.Random.__init__(self) - Subclass(newarg=1) - - -def test_main(verbose: bool = None) -> None: - testclasses = [MersenneTwister_TestBasicOps, - TestDistributions, - TestModule] - - try: - random.SystemRandom().random() - except NotImplementedError: - pass - else: - testclasses.append(SystemRandom_TestBasicOps) - - support.run_unittest(*testclasses) - - # verify reference counting - import sys - if verbose and hasattr(sys, "gettotalrefcount"): - counts = [None] * 5 # type: List[int] - for i in range(len(counts)): - support.run_unittest(*testclasses) - counts[i] = sys.gettotalrefcount() - print(counts) - -if __name__ == "__main__": - test_main(verbose=True) diff --git a/test-data/stdlib-samples/3.2/test/test_set.py b/test-data/stdlib-samples/3.2/test/test_set.py deleted file mode 100644 index 16f86198cc0fb..0000000000000 --- a/test-data/stdlib-samples/3.2/test/test_set.py +++ /dev/null @@ -1,1884 +0,0 @@ -import unittest -from test import support -import gc -import weakref -import operator -import copy -import pickle -from random import randrange, shuffle -import sys -import warnings -import collections -from typing import Set, Any - -class PassThru(Exception): - pass - -def check_pass_thru(): - raise PassThru - yield 1 - -class BadCmp: - def __hash__(self): - return 1 - def __eq__(self, other): - raise RuntimeError - -class ReprWrapper: - 'Used to test self-referential repr() calls' - def __repr__(self): - return repr(self.value) - -#class HashCountingInt(int): -# 'int-like object that counts the number of times __hash__ is called' -# def __init__(self, *args): -# self.hash_count = 0 -# def __hash__(self): -# self.hash_count += 1 -# return int.__hash__(self) - -class TestJointOps(unittest.TestCase): - # Tests common to both set and frozenset - - def setUp(self): - self.word = word = 'simsalabim' - self.otherword = 'madagascar' - self.letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' - self.s = self.thetype(word) - self.d = dict.fromkeys(word) - - def test_new_or_init(self): - self.assertRaises(TypeError, self.thetype, [], 2) - self.assertRaises(TypeError, set().__init__, a=1) - - def test_uniquification(self): - actual = sorted(self.s) - expected = sorted(self.d) - self.assertEqual(actual, expected) - self.assertRaises(PassThru, self.thetype, check_pass_thru()) - self.assertRaises(TypeError, self.thetype, [[]]) - - def test_len(self): - self.assertEqual(len(self.s), len(self.d)) - - def test_contains(self): - for c in self.letters: - self.assertEqual(c in self.s, c in self.d) - self.assertRaises(TypeError, self.s.__contains__, [[]]) - s = self.thetype([frozenset(self.letters)]) - self.assertIn(self.thetype(self.letters), s) - - def test_union(self): - u = self.s.union(self.otherword) - for c in self.letters: - self.assertEqual(c in u, c in self.d or c in self.otherword) - self.assertEqual(self.s, self.thetype(self.word)) - self.assertEqual(type(u), self.basetype) - self.assertRaises(PassThru, self.s.union, check_pass_thru()) - self.assertRaises(TypeError, self.s.union, [[]]) - for C in set, frozenset, dict.fromkeys, str, list, tuple: - self.assertEqual(self.thetype('abcba').union(C('cdc')), set('abcd')) - self.assertEqual(self.thetype('abcba').union(C('efgfe')), set('abcefg')) - self.assertEqual(self.thetype('abcba').union(C('ccb')), set('abc')) - self.assertEqual(self.thetype('abcba').union(C('ef')), set('abcef')) - self.assertEqual(self.thetype('abcba').union(C('ef'), C('fg')), set('abcefg')) - - # Issue #6573 - x = self.thetype() - self.assertEqual(x.union(set([1]), x, set([2])), self.thetype([1, 2])) - - def test_or(self): - i = self.s.union(self.otherword) - self.assertEqual(self.s | set(self.otherword), i) - self.assertEqual(self.s | frozenset(self.otherword), i) - try: - self.s | self.otherword - except TypeError: - pass - else: - self.fail("s|t did not screen-out general iterables") - - def test_intersection(self): - i = self.s.intersection(self.otherword) - for c in self.letters: - self.assertEqual(c in i, c in self.d and c in self.otherword) - self.assertEqual(self.s, self.thetype(self.word)) - self.assertEqual(type(i), self.basetype) - self.assertRaises(PassThru, self.s.intersection, check_pass_thru()) - for C in set, frozenset, dict.fromkeys, str, list, tuple: - self.assertEqual(self.thetype('abcba').intersection(C('cdc')), set('cc')) - self.assertEqual(self.thetype('abcba').intersection(C('efgfe')), set('')) - self.assertEqual(self.thetype('abcba').intersection(C('ccb')), set('bc')) - self.assertEqual(self.thetype('abcba').intersection(C('ef')), set('')) - self.assertEqual(self.thetype('abcba').intersection(C('cbcf'), C('bag')), set('b')) - s = self.thetype('abcba') - z = s.intersection() - if self.thetype == frozenset(): - self.assertEqual(id(s), id(z)) - else: - self.assertNotEqual(id(s), id(z)) - - def test_isdisjoint(self): - def f(s1, s2): - 'Pure python equivalent of isdisjoint()' - return not set(s1).intersection(s2) - for larg in '', 'a', 'ab', 'abc', 'ababac', 'cdc', 'cc', 'efgfe', 'ccb', 'ef': - s1 = self.thetype(larg) - for rarg in '', 'a', 'ab', 'abc', 'ababac', 'cdc', 'cc', 'efgfe', 'ccb', 'ef': - for C in set, frozenset, dict.fromkeys, str, list, tuple: - s2 = C(rarg) - actual = s1.isdisjoint(s2) - expected = f(s1, s2) - self.assertEqual(actual, expected) - self.assertTrue(actual is True or actual is False) - - def test_and(self): - i = self.s.intersection(self.otherword) - self.assertEqual(self.s & set(self.otherword), i) - self.assertEqual(self.s & frozenset(self.otherword), i) - try: - self.s & self.otherword - except TypeError: - pass - else: - self.fail("s&t did not screen-out general iterables") - - def test_difference(self): - i = self.s.difference(self.otherword) - for c in self.letters: - self.assertEqual(c in i, c in self.d and c not in self.otherword) - self.assertEqual(self.s, self.thetype(self.word)) - self.assertEqual(type(i), self.basetype) - self.assertRaises(PassThru, self.s.difference, check_pass_thru()) - self.assertRaises(TypeError, self.s.difference, [[]]) - for C in set, frozenset, dict.fromkeys, str, list, tuple: - self.assertEqual(self.thetype('abcba').difference(C('cdc')), set('ab')) - self.assertEqual(self.thetype('abcba').difference(C('efgfe')), set('abc')) - self.assertEqual(self.thetype('abcba').difference(C('ccb')), set('a')) - self.assertEqual(self.thetype('abcba').difference(C('ef')), set('abc')) - self.assertEqual(self.thetype('abcba').difference(), set('abc')) - self.assertEqual(self.thetype('abcba').difference(C('a'), C('b')), set('c')) - - def test_sub(self): - i = self.s.difference(self.otherword) - self.assertEqual(self.s - set(self.otherword), i) - self.assertEqual(self.s - frozenset(self.otherword), i) - try: - self.s - self.otherword - except TypeError: - pass - else: - self.fail("s-t did not screen-out general iterables") - - def test_symmetric_difference(self): - i = self.s.symmetric_difference(self.otherword) - for c in self.letters: - self.assertEqual(c in i, (c in self.d) ^ (c in self.otherword)) - self.assertEqual(self.s, self.thetype(self.word)) - self.assertEqual(type(i), self.basetype) - self.assertRaises(PassThru, self.s.symmetric_difference, check_pass_thru()) - self.assertRaises(TypeError, self.s.symmetric_difference, [[]]) - for C in set, frozenset, dict.fromkeys, str, list, tuple: - self.assertEqual(self.thetype('abcba').symmetric_difference(C('cdc')), set('abd')) - self.assertEqual(self.thetype('abcba').symmetric_difference(C('efgfe')), set('abcefg')) - self.assertEqual(self.thetype('abcba').symmetric_difference(C('ccb')), set('a')) - self.assertEqual(self.thetype('abcba').symmetric_difference(C('ef')), set('abcef')) - - def test_xor(self): - i = self.s.symmetric_difference(self.otherword) - self.assertEqual(self.s ^ set(self.otherword), i) - self.assertEqual(self.s ^ frozenset(self.otherword), i) - try: - self.s ^ self.otherword - except TypeError: - pass - else: - self.fail("s^t did not screen-out general iterables") - - def test_equality(self): - self.assertEqual(self.s, set(self.word)) - self.assertEqual(self.s, frozenset(self.word)) - self.assertEqual(self.s == self.word, False) - self.assertNotEqual(self.s, set(self.otherword)) - self.assertNotEqual(self.s, frozenset(self.otherword)) - self.assertEqual(self.s != self.word, True) - - def test_setOfFrozensets(self): - t = map(frozenset, ['abcdef', 'bcd', 'bdcb', 'fed', 'fedccba']) - s = self.thetype(t) - self.assertEqual(len(s), 3) - - def test_sub_and_super(self): - p, q, r = map(self.thetype, ['ab', 'abcde', 'def']) - self.assertTrue(p < q) - self.assertTrue(p <= q) - self.assertTrue(q <= q) - self.assertTrue(q > p) - self.assertTrue(q >= p) - self.assertFalse(q < r) - self.assertFalse(q <= r) - self.assertFalse(q > r) - self.assertFalse(q >= r) - self.assertTrue(set('a').issubset('abc')) - self.assertTrue(set('abc').issuperset('a')) - self.assertFalse(set('a').issubset('cbs')) - self.assertFalse(set('cbs').issuperset('a')) - - def test_pickling(self): - for i in range(pickle.HIGHEST_PROTOCOL + 1): - p = pickle.dumps(self.s, i) - dup = pickle.loads(p) - self.assertEqual(self.s, dup, "%s != %s" % (self.s, dup)) - if type(self.s) not in (set, frozenset): - self.s.x = 10 - p = pickle.dumps(self.s) - dup = pickle.loads(p) - self.assertEqual(self.s.x, dup.x) - - def test_deepcopy(self): - class Tracer: - def __init__(self, value): - self.value = value - def __hash__(self): - return self.value - def __deepcopy__(self, memo=None): - return Tracer(self.value + 1) - t = Tracer(10) - s = self.thetype([t]) - dup = copy.deepcopy(s) - self.assertNotEqual(id(s), id(dup)) - for elem in dup: - newt = elem - self.assertNotEqual(id(t), id(newt)) - self.assertEqual(t.value + 1, newt.value) - - def test_gc(self): - # Create a nest of cycles to exercise overall ref count check - class A: - pass - s = set(A() for i in range(1000)) - for elem in s: - elem.cycle = s - elem.sub = elem - elem.set = set([elem]) - - def test_subclass_with_custom_hash(self): - raise NotImplementedError() # runtime computed base class below - # Bug #1257731 - class H: # (self.thetype): - def __hash__(self): - return int(id(self) & 0x7fffffff) - s=H() - f=set() - f.add(s) - self.assertIn(s, f) - f.remove(s) - f.add(s) - f.discard(s) - - def test_badcmp(self): - s = self.thetype([BadCmp()]) - # Detect comparison errors during insertion and lookup - self.assertRaises(RuntimeError, self.thetype, [BadCmp(), BadCmp()]) - self.assertRaises(RuntimeError, s.__contains__, BadCmp()) - # Detect errors during mutating operations - if hasattr(s, 'add'): - self.assertRaises(RuntimeError, s.add, BadCmp()) - self.assertRaises(RuntimeError, s.discard, BadCmp()) - self.assertRaises(RuntimeError, s.remove, BadCmp()) - - def test_cyclical_repr(self): - w = ReprWrapper() - s = self.thetype([w]) - w.value = s - if self.thetype == set: - self.assertEqual(repr(s), '{set(...)}') - else: - name = repr(s).partition('(')[0] # strip class name - self.assertEqual(repr(s), '%s({%s(...)})' % (name, name)) - - def test_cyclical_print(self): - w = ReprWrapper() - s = self.thetype([w]) - w.value = s - fo = open(support.TESTFN, "w") - try: - fo.write(str(s)) - fo.close() - fo = open(support.TESTFN, "r") - self.assertEqual(fo.read(), repr(s)) - finally: - fo.close() - support.unlink(support.TESTFN) - - def test_do_not_rehash_dict_keys(self): - raise NotImplementedError() # cannot subclass int - n = 10 - d = None # dict.fromkeys(map(HashCountingInt, range(n))) - self.assertEqual(sum(elem.hash_count for elem in d), n) - s = self.thetype(d) - self.assertEqual(sum(elem.hash_count for elem in d), n) - s.difference(d) - self.assertEqual(sum(elem.hash_count for elem in d), n) - if hasattr(s, 'symmetric_difference_update'): - s.symmetric_difference_update(d) - self.assertEqual(sum(elem.hash_count for elem in d), n) - d2 = dict.fromkeys(set(d)) - self.assertEqual(sum(elem.hash_count for elem in d), n) - d3 = dict.fromkeys(frozenset(d)) - self.assertEqual(sum(elem.hash_count for elem in d), n) - d3 = dict.fromkeys(frozenset(d), 123) - self.assertEqual(sum(elem.hash_count for elem in d), n) - self.assertEqual(d3, dict.fromkeys(d, 123)) - - def test_container_iterator(self): - # Bug #3680: tp_traverse was not implemented for set iterator object - class C(object): - pass - obj = C() - ref = weakref.ref(obj) - container = set([obj, 1]) - obj.x = iter(container) - obj = None - container = None - gc.collect() - self.assertTrue(ref() is None, "Cycle was not collected") - -class TestSet(TestJointOps): - thetype = set - basetype = set - - def test_init(self): - s = self.thetype() - s.__init__(self.word) - self.assertEqual(s, set(self.word)) - s.__init__(self.otherword) - self.assertEqual(s, set(self.otherword)) - self.assertRaises(TypeError, s.__init__, s, 2); - self.assertRaises(TypeError, s.__init__, 1) - - def test_constructor_identity(self): - s = self.thetype(range(3)) - t = self.thetype(s) - self.assertNotEqual(id(s), id(t)) - - def test_set_literal(self): - raise NotImplementedError() - #s = set([1,2,3]) - #t = {1,2,3} - #self.assertEqual(s, t) - - def test_hash(self): - self.assertRaises(TypeError, hash, self.s) - - def test_clear(self): - self.s.clear() - self.assertEqual(self.s, set()) - self.assertEqual(len(self.s), 0) - - def test_copy(self): - dup = self.s.copy() - self.assertEqual(self.s, dup) - self.assertNotEqual(id(self.s), id(dup)) - self.assertEqual(type(dup), self.basetype) - - def test_add(self): - self.s.add('Q') - self.assertIn('Q', self.s) - dup = self.s.copy() - self.s.add('Q') - self.assertEqual(self.s, dup) - self.assertRaises(TypeError, self.s.add, []) - - def test_remove(self): - self.s.remove('a') - self.assertNotIn('a', self.s) - self.assertRaises(KeyError, self.s.remove, 'Q') - self.assertRaises(TypeError, self.s.remove, []) - s = self.thetype([frozenset(self.word)]) - self.assertIn(self.thetype(self.word), s) - s.remove(self.thetype(self.word)) - self.assertNotIn(self.thetype(self.word), s) - self.assertRaises(KeyError, self.s.remove, self.thetype(self.word)) - - def test_remove_keyerror_unpacking(self): - # bug: www.python.org/sf/1576657 - for v1 in ['Q', (1,)]: - try: - self.s.remove(v1) - except KeyError as e: - v2 = e.args[0] - self.assertEqual(v1, v2) - else: - self.fail() - - def test_remove_keyerror_set(self): - key = self.thetype([3, 4]) - try: - self.s.remove(key) - except KeyError as e: - self.assertTrue(e.args[0] is key, - "KeyError should be {0}, not {1}".format(key, - e.args[0])) - else: - self.fail() - - def test_discard(self): - self.s.discard('a') - self.assertNotIn('a', self.s) - self.s.discard('Q') - self.assertRaises(TypeError, self.s.discard, []) - s = self.thetype([frozenset(self.word)]) - self.assertIn(self.thetype(self.word), s) - s.discard(self.thetype(self.word)) - self.assertNotIn(self.thetype(self.word), s) - s.discard(self.thetype(self.word)) - - def test_pop(self): - for i in range(len(self.s)): - elem = self.s.pop() - self.assertNotIn(elem, self.s) - self.assertRaises(KeyError, self.s.pop) - - def test_update(self): - retval = self.s.update(self.otherword) - self.assertEqual(retval, None) - for c in (self.word + self.otherword): - self.assertIn(c, self.s) - self.assertRaises(PassThru, self.s.update, check_pass_thru()) - self.assertRaises(TypeError, self.s.update, [[]]) - for p, q in (('cdc', 'abcd'), ('efgfe', 'abcefg'), ('ccb', 'abc'), ('ef', 'abcef')): - for C in set, frozenset, dict.fromkeys, str, list, tuple: - s = self.thetype('abcba') - self.assertEqual(s.update(C(p)), None) - self.assertEqual(s, set(q)) - for p in ('cdc', 'efgfe', 'ccb', 'ef', 'abcda'): - q = 'ahi' - for C in set, frozenset, dict.fromkeys, str, list, tuple: - s = self.thetype('abcba') - self.assertEqual(s.update(C(p), C(q)), None) - self.assertEqual(s, set(s) | set(p) | set(q)) - - def test_ior(self): - self.s |= set(self.otherword) - for c in (self.word + self.otherword): - self.assertIn(c, self.s) - - def test_intersection_update(self): - retval = self.s.intersection_update(self.otherword) - self.assertEqual(retval, None) - for c in (self.word + self.otherword): - if c in self.otherword and c in self.word: - self.assertIn(c, self.s) - else: - self.assertNotIn(c, self.s) - self.assertRaises(PassThru, self.s.intersection_update, check_pass_thru()) - self.assertRaises(TypeError, self.s.intersection_update, [[]]) - for p, q in (('cdc', 'c'), ('efgfe', ''), ('ccb', 'bc'), ('ef', '')): - for C in set, frozenset, dict.fromkeys, str, list, tuple: - s = self.thetype('abcba') - self.assertEqual(s.intersection_update(C(p)), None) - self.assertEqual(s, set(q)) - ss = 'abcba' - s = self.thetype(ss) - t = 'cbc' - self.assertEqual(s.intersection_update(C(p), C(t)), None) - self.assertEqual(s, set('abcba')&set(p)&set(t)) - - def test_iand(self): - self.s &= set(self.otherword) - for c in (self.word + self.otherword): - if c in self.otherword and c in self.word: - self.assertIn(c, self.s) - else: - self.assertNotIn(c, self.s) - - def test_difference_update(self): - retval = self.s.difference_update(self.otherword) - self.assertEqual(retval, None) - for c in (self.word + self.otherword): - if c in self.word and c not in self.otherword: - self.assertIn(c, self.s) - else: - self.assertNotIn(c, self.s) - self.assertRaises(PassThru, self.s.difference_update, check_pass_thru()) - self.assertRaises(TypeError, self.s.difference_update, [[]]) - self.assertRaises(TypeError, self.s.symmetric_difference_update, [[]]) - for p, q in (('cdc', 'ab'), ('efgfe', 'abc'), ('ccb', 'a'), ('ef', 'abc')): - for C in set, frozenset, dict.fromkeys, str, list, tuple: - s = self.thetype('abcba') - self.assertEqual(s.difference_update(C(p)), None) - self.assertEqual(s, set(q)) - - s = self.thetype('abcdefghih') - s.difference_update() - self.assertEqual(s, self.thetype('abcdefghih')) - - s = self.thetype('abcdefghih') - s.difference_update(C('aba')) - self.assertEqual(s, self.thetype('cdefghih')) - - s = self.thetype('abcdefghih') - s.difference_update(C('cdc'), C('aba')) - self.assertEqual(s, self.thetype('efghih')) - - def test_isub(self): - self.s -= set(self.otherword) - for c in (self.word + self.otherword): - if c in self.word and c not in self.otherword: - self.assertIn(c, self.s) - else: - self.assertNotIn(c, self.s) - - def test_symmetric_difference_update(self): - retval = self.s.symmetric_difference_update(self.otherword) - self.assertEqual(retval, None) - for c in (self.word + self.otherword): - if (c in self.word) ^ (c in self.otherword): - self.assertIn(c, self.s) - else: - self.assertNotIn(c, self.s) - self.assertRaises(PassThru, self.s.symmetric_difference_update, check_pass_thru()) - self.assertRaises(TypeError, self.s.symmetric_difference_update, [[]]) - for p, q in (('cdc', 'abd'), ('efgfe', 'abcefg'), ('ccb', 'a'), ('ef', 'abcef')): - for C in set, frozenset, dict.fromkeys, str, list, tuple: - s = self.thetype('abcba') - self.assertEqual(s.symmetric_difference_update(C(p)), None) - self.assertEqual(s, set(q)) - - def test_ixor(self): - self.s ^= set(self.otherword) - for c in (self.word + self.otherword): - if (c in self.word) ^ (c in self.otherword): - self.assertIn(c, self.s) - else: - self.assertNotIn(c, self.s) - - def test_inplace_on_self(self): - t = self.s.copy() - t |= t - self.assertEqual(t, self.s) - t &= t - self.assertEqual(t, self.s) - t -= t - self.assertEqual(t, self.thetype()) - t = self.s.copy() - t ^= t - self.assertEqual(t, self.thetype()) - - def test_weakref(self): - s = self.thetype('gallahad') - p = weakref.proxy(s) - self.assertEqual(str(p), str(s)) - s = None - self.assertRaises(ReferenceError, str, p) - - def test_rich_compare(self): - class TestRichSetCompare: - def __gt__(self, some_set): - self.gt_called = True - return False - def __lt__(self, some_set): - self.lt_called = True - return False - def __ge__(self, some_set): - self.ge_called = True - return False - def __le__(self, some_set): - self.le_called = True - return False - - # This first tries the builtin rich set comparison, which doesn't know - # how to handle the custom object. Upon returning NotImplemented, the - # corresponding comparison on the right object is invoked. - myset = {1, 2, 3} - - myobj = TestRichSetCompare() - myset < myobj - self.assertTrue(myobj.gt_called) - - myobj = TestRichSetCompare() - myset > myobj - self.assertTrue(myobj.lt_called) - - myobj = TestRichSetCompare() - myset <= myobj - self.assertTrue(myobj.ge_called) - - myobj = TestRichSetCompare() - myset >= myobj - self.assertTrue(myobj.le_called) - - # C API test only available in a debug build - if hasattr(set, "test_c_api"): - def test_c_api(self): - self.assertEqual(set().test_c_api(), True) - -class SetSubclass(set): - pass - -class TestSetSubclass(TestSet): - thetype = SetSubclass - basetype = set - -class SetSubclassWithKeywordArgs(set): - def __init__(self, iterable=[], newarg=None): - set.__init__(self, iterable) - -class TestSetSubclassWithKeywordArgs(TestSet): - - def test_keywords_in_subclass(self): - 'SF bug #1486663 -- this used to erroneously raise a TypeError' - SetSubclassWithKeywordArgs(newarg=1) - -class TestFrozenSet(TestJointOps): - thetype = frozenset - basetype = frozenset - - def test_init(self): - s = self.thetype(self.word) - s.__init__(self.otherword) - self.assertEqual(s, set(self.word)) - - def test_singleton_empty_frozenset(self): - f = frozenset() - efs = [frozenset(), frozenset([]), frozenset(()), frozenset(''), - frozenset(), frozenset([]), frozenset(()), frozenset(''), - frozenset(range(0)), frozenset(frozenset()), - frozenset(f), f] - # All of the empty frozensets should have just one id() - self.assertEqual(len(set(map(id, efs))), 1) - - def test_constructor_identity(self): - s = self.thetype(range(3)) - t = self.thetype(s) - self.assertEqual(id(s), id(t)) - - def test_hash(self): - self.assertEqual(hash(self.thetype('abcdeb')), - hash(self.thetype('ebecda'))) - - # make sure that all permutations give the same hash value - n = 100 - seq = [randrange(n) for i in range(n)] - results = set() - for i in range(200): - shuffle(seq) - results.add(hash(self.thetype(seq))) - self.assertEqual(len(results), 1) - - def test_copy(self): - dup = self.s.copy() - self.assertEqual(id(self.s), id(dup)) - - def test_frozen_as_dictkey(self): - seq = list(range(10)) + list('abcdefg') + ['apple'] - key1 = self.thetype(seq) - key2 = self.thetype(reversed(seq)) - self.assertEqual(key1, key2) - self.assertNotEqual(id(key1), id(key2)) - d = {} - d[key1] = 42 - self.assertEqual(d[key2], 42) - - def test_hash_caching(self): - f = self.thetype('abcdcda') - self.assertEqual(hash(f), hash(f)) - - def test_hash_effectiveness(self): - n = 13 - hashvalues = set() - addhashvalue = hashvalues.add - elemmasks = [(i+1, 1<=": "issuperset", - } - - reverse = {"==": "==", - "!=": "!=", - "<": ">", - ">": "<", - "<=": ">=", - ">=": "<=", - } - - def test_issubset(self): - raise NotImplementedError() # eval not supported below - x = self.left - y = self.right - for case in "!=", "==", "<", "<=", ">", ">=": - expected = case in self.cases - # Test the binary infix spelling. - result = None ## eval("x" + case + "y", locals()) - self.assertEqual(result, expected) - # Test the "friendly" method-name spelling, if one exists. - if case in TestSubsets.case2method: - method = getattr(x, TestSubsets.case2method[case]) - result = method(y) - self.assertEqual(result, expected) - - # Now do the same for the operands reversed. - rcase = TestSubsets.reverse[case] - result = None ## eval("y" + rcase + "x", locals()) - self.assertEqual(result, expected) - if rcase in TestSubsets.case2method: - method = getattr(y, TestSubsets.case2method[rcase]) - result = method(x) - self.assertEqual(result, expected) -#------------------------------------------------------------------------------ - -class TestSubsetEqualEmpty(TestSubsets): - left = set() # type: Any - right = set() # type: Any - name = "both empty" - cases = "==", "<=", ">=" - -#------------------------------------------------------------------------------ - -class TestSubsetEqualNonEmpty(TestSubsets): - left = set([1, 2]) - right = set([1, 2]) - name = "equal pair" - cases = "==", "<=", ">=" - -#------------------------------------------------------------------------------ - -class TestSubsetEmptyNonEmpty(TestSubsets): - left = set() # type: Any - right = set([1, 2]) - name = "one empty, one non-empty" - cases = "!=", "<", "<=" - -#------------------------------------------------------------------------------ - -class TestSubsetPartial(TestSubsets): - left = set([1]) - right = set([1, 2]) - name = "one a non-empty proper subset of other" - cases = "!=", "<", "<=" - -#------------------------------------------------------------------------------ - -class TestSubsetNonOverlap(TestSubsets): - left = set([1]) - right = set([2]) - name = "neither empty, neither contains" - cases = "!=" - -#============================================================================== - -class TestOnlySetsInBinaryOps(unittest.TestCase): - - def test_eq_ne(self): - # Unlike the others, this is testing that == and != *are* allowed. - self.assertEqual(self.other == self.set, False) - self.assertEqual(self.set == self.other, False) - self.assertEqual(self.other != self.set, True) - self.assertEqual(self.set != self.other, True) - - def test_ge_gt_le_lt(self): - self.assertRaises(TypeError, lambda: self.set < self.other) - self.assertRaises(TypeError, lambda: self.set <= self.other) - self.assertRaises(TypeError, lambda: self.set > self.other) - self.assertRaises(TypeError, lambda: self.set >= self.other) - - self.assertRaises(TypeError, lambda: self.other < self.set) - self.assertRaises(TypeError, lambda: self.other <= self.set) - self.assertRaises(TypeError, lambda: self.other > self.set) - self.assertRaises(TypeError, lambda: self.other >= self.set) - - def test_update_operator(self): - try: - self.set |= self.other - except TypeError: - pass - else: - self.fail("expected TypeError") - - def test_update(self): - if self.otherIsIterable: - self.set.update(self.other) - else: - self.assertRaises(TypeError, self.set.update, self.other) - - def test_union(self): - self.assertRaises(TypeError, lambda: self.set | self.other) - self.assertRaises(TypeError, lambda: self.other | self.set) - if self.otherIsIterable: - self.set.union(self.other) - else: - self.assertRaises(TypeError, self.set.union, self.other) - - def test_intersection_update_operator(self): - try: - self.set &= self.other - except TypeError: - pass - else: - self.fail("expected TypeError") - - def test_intersection_update(self): - if self.otherIsIterable: - self.set.intersection_update(self.other) - else: - self.assertRaises(TypeError, - self.set.intersection_update, - self.other) - - def test_intersection(self): - self.assertRaises(TypeError, lambda: self.set & self.other) - self.assertRaises(TypeError, lambda: self.other & self.set) - if self.otherIsIterable: - self.set.intersection(self.other) - else: - self.assertRaises(TypeError, self.set.intersection, self.other) - - def test_sym_difference_update_operator(self): - try: - self.set ^= self.other - except TypeError: - pass - else: - self.fail("expected TypeError") - - def test_sym_difference_update(self): - if self.otherIsIterable: - self.set.symmetric_difference_update(self.other) - else: - self.assertRaises(TypeError, - self.set.symmetric_difference_update, - self.other) - - def test_sym_difference(self): - self.assertRaises(TypeError, lambda: self.set ^ self.other) - self.assertRaises(TypeError, lambda: self.other ^ self.set) - if self.otherIsIterable: - self.set.symmetric_difference(self.other) - else: - self.assertRaises(TypeError, self.set.symmetric_difference, self.other) - - def test_difference_update_operator(self): - try: - self.set -= self.other - except TypeError: - pass - else: - self.fail("expected TypeError") - - def test_difference_update(self): - if self.otherIsIterable: - self.set.difference_update(self.other) - else: - self.assertRaises(TypeError, - self.set.difference_update, - self.other) - - def test_difference(self): - self.assertRaises(TypeError, lambda: self.set - self.other) - self.assertRaises(TypeError, lambda: self.other - self.set) - if self.otherIsIterable: - self.set.difference(self.other) - else: - self.assertRaises(TypeError, self.set.difference, self.other) - -#------------------------------------------------------------------------------ - -class TestOnlySetsNumeric(TestOnlySetsInBinaryOps): - def setUp(self): - self.set = set((1, 2, 3)) - self.other = 19 - self.otherIsIterable = False - -#------------------------------------------------------------------------------ - -class TestOnlySetsDict(TestOnlySetsInBinaryOps): - def setUp(self): - self.set = set((1, 2, 3)) - self.other = {1:2, 3:4} - self.otherIsIterable = True - -#------------------------------------------------------------------------------ - -class TestOnlySetsOperator(TestOnlySetsInBinaryOps): - def setUp(self): - self.set = set((1, 2, 3)) - self.other = operator.add - self.otherIsIterable = False - -#------------------------------------------------------------------------------ - -class TestOnlySetsTuple(TestOnlySetsInBinaryOps): - def setUp(self): - self.set = set((1, 2, 3)) - self.other = (2, 4, 6) - self.otherIsIterable = True - -#------------------------------------------------------------------------------ - -class TestOnlySetsString(TestOnlySetsInBinaryOps): - def setUp(self): - self.set = set((1, 2, 3)) - self.other = 'abc' - self.otherIsIterable = True - -#------------------------------------------------------------------------------ - -class TestOnlySetsGenerator(TestOnlySetsInBinaryOps): - def setUp(self): - def gen(): - for i in range(0, 10, 2): - yield i - self.set = set((1, 2, 3)) - self.other = gen() - self.otherIsIterable = True - -#============================================================================== - -class TestCopying(unittest.TestCase): - - def test_copy(self): - dup = self.set.copy() - dup_list = sorted(dup, key=repr) - set_list = sorted(self.set, key=repr) - self.assertEqual(len(dup_list), len(set_list)) - for i in range(len(dup_list)): - self.assertTrue(dup_list[i] is set_list[i]) - - def test_deep_copy(self): - dup = copy.deepcopy(self.set) - ##print type(dup), repr(dup) - dup_list = sorted(dup, key=repr) - set_list = sorted(self.set, key=repr) - self.assertEqual(len(dup_list), len(set_list)) - for i in range(len(dup_list)): - self.assertEqual(dup_list[i], set_list[i]) - -#------------------------------------------------------------------------------ - -class TestCopyingEmpty(TestCopying): - def setUp(self): - self.set = set() - -#------------------------------------------------------------------------------ - -class TestCopyingSingleton(TestCopying): - def setUp(self): - self.set = set(["hello"]) - -#------------------------------------------------------------------------------ - -class TestCopyingTriple(TestCopying): - def setUp(self): - self.set = set(["zero", 0, None]) - -#------------------------------------------------------------------------------ - -class TestCopyingTuple(TestCopying): - def setUp(self): - self.set = set([(1, 2)]) - -#------------------------------------------------------------------------------ - -class TestCopyingNested(TestCopying): - def setUp(self): - self.set = set([((1, 2), (3, 4))]) - -#============================================================================== - -class TestIdentities(unittest.TestCase): - def setUp(self): - self.a = set('abracadabra') - self.b = set('alacazam') - - def test_binopsVsSubsets(self): - a, b = self.a, self.b - self.assertTrue(a - b < a) - self.assertTrue(b - a < b) - self.assertTrue(a & b < a) - self.assertTrue(a & b < b) - self.assertTrue(a | b > a) - self.assertTrue(a | b > b) - self.assertTrue(a ^ b < a | b) - - def test_commutativity(self): - a, b = self.a, self.b - self.assertEqual(a&b, b&a) - self.assertEqual(a|b, b|a) - self.assertEqual(a^b, b^a) - if a != b: - self.assertNotEqual(a-b, b-a) - - def test_summations(self): - # check that sums of parts equal the whole - a, b = self.a, self.b - self.assertEqual((a-b)|(a&b)|(b-a), a|b) - self.assertEqual((a&b)|(a^b), a|b) - self.assertEqual(a|(b-a), a|b) - self.assertEqual((a-b)|b, a|b) - self.assertEqual((a-b)|(a&b), a) - self.assertEqual((b-a)|(a&b), b) - self.assertEqual((a-b)|(b-a), a^b) - - def test_exclusion(self): - # check that inverse operations show non-overlap - a, b, zero = self.a, self.b, set() - self.assertEqual((a-b)&b, zero) - self.assertEqual((b-a)&a, zero) - self.assertEqual((a&b)&(a^b), zero) - -# Tests derived from test_itertools.py ======================================= - -def R(seqn): - 'Regular generator' - for i in seqn: - yield i - -class G: - 'Sequence using __getitem__' - def __init__(self, seqn): - self.seqn = seqn - def __getitem__(self, i): - return self.seqn[i] - -class I: - 'Sequence using iterator protocol' - def __init__(self, seqn): - self.seqn = seqn - self.i = 0 - def __iter__(self): - return self - def __next__(self): - if self.i >= len(self.seqn): raise StopIteration - v = self.seqn[self.i] - self.i += 1 - return v - -class Ig: - 'Sequence using iterator protocol defined with a generator' - def __init__(self, seqn): - self.seqn = seqn - self.i = 0 - def __iter__(self): - for val in self.seqn: - yield val - -class X: - 'Missing __getitem__ and __iter__' - def __init__(self, seqn): - self.seqn = seqn - self.i = 0 - def __next__(self): - if self.i >= len(self.seqn): raise StopIteration - v = self.seqn[self.i] - self.i += 1 - return v - -class N: - 'Iterator missing __next__()' - def __init__(self, seqn): - self.seqn = seqn - self.i = 0 - def __iter__(self): - return self - -class E: - 'Test propagation of exceptions' - def __init__(self, seqn): - self.seqn = seqn - self.i = 0 - def __iter__(self): - return self - def __next__(self): - 3 // 0 - -class S: - 'Test immediate stop' - def __init__(self, seqn): - pass - def __iter__(self): - return self - def __next__(self): - raise StopIteration - -from itertools import chain -def L(seqn): - 'Test multiple tiers of iterators' - return chain(map(lambda x:x, R(Ig(G(seqn))))) - -class TestVariousIteratorArgs(unittest.TestCase): - - def test_constructor(self): - for cons in (set, frozenset): - for s in ("123", "", range(1000), ('do', 1.2), range(2000,2200,5)): - for g in (G, I, Ig, S, L, R): - self.assertEqual(sorted(cons(g(s)), key=repr), sorted(g(s), key=repr)) - self.assertRaises(TypeError, cons , X(s)) - self.assertRaises(TypeError, cons , N(s)) - self.assertRaises(ZeroDivisionError, cons , E(s)) - - def test_inline_methods(self): - s = set('november') - for data in ("123", "", range(1000), ('do', 1.2), range(2000,2200,5), 'december'): - for meth in (s.union, s.intersection, s.difference, s.symmetric_difference, s.isdisjoint): - for g in (G, I, Ig, L, R): - expected = meth(data) - actual = meth(G(data)) - if isinstance(expected, bool): - self.assertEqual(actual, expected) - else: - self.assertEqual(sorted(actual, key=repr), sorted(expected, key=repr)) - self.assertRaises(TypeError, meth, X(s)) - self.assertRaises(TypeError, meth, N(s)) - self.assertRaises(ZeroDivisionError, meth, E(s)) - - def test_inplace_methods(self): - for data in ("123", "", range(1000), ('do', 1.2), range(2000,2200,5), 'december'): - for methname in ('update', 'intersection_update', - 'difference_update', 'symmetric_difference_update'): - for g in (G, I, Ig, S, L, R): - s = set('january') - t = s.copy() - getattr(s, methname)(list(g(data))) - getattr(t, methname)(g(data)) - self.assertEqual(sorted(s, key=repr), sorted(t, key=repr)) - - self.assertRaises(TypeError, getattr(set('january'), methname), X(data)) - self.assertRaises(TypeError, getattr(set('january'), methname), N(data)) - self.assertRaises(ZeroDivisionError, getattr(set('january'), methname), E(data)) - -be_bad = set2 = dict2 = None # type: Any - -class bad_eq: - def __eq__(self, other): - if be_bad: - set2.clear() - raise ZeroDivisionError - return self is other - def __hash__(self): - return 0 - -class bad_dict_clear: - def __eq__(self, other): - if be_bad: - dict2.clear() - return self is other - def __hash__(self): - return 0 - -class TestWeirdBugs(unittest.TestCase): - def test_8420_set_merge(self): - # This used to segfault - global be_bad, set2, dict2 - be_bad = False - set1 = {bad_eq()} - set2 = {bad_eq() for i in range(75)} - be_bad = True - self.assertRaises(ZeroDivisionError, set1.update, set2) - - be_bad = False - set1 = {bad_dict_clear()} - dict2 = {bad_dict_clear(): None} - be_bad = True - set1.symmetric_difference_update(dict2) - -# Application tests (based on David Eppstein's graph recipes ==================================== - -def powerset(U): - """Generates all subsets of a set or sequence U.""" - U = iter(U) - try: - x = frozenset([next(U)]) - for S in powerset(U): - yield S - yield S | x - except StopIteration: - yield frozenset() - -def cube(n): - """Graph of n-dimensional hypercube.""" - singletons = [frozenset([x]) for x in range(n)] - return dict([(x, frozenset([x^s for s in singletons])) - for x in powerset(range(n))]) - -def linegraph(G): - """Graph, the vertices of which are edges of G, - with two vertices being adjacent iff the corresponding - edges share a vertex.""" - L = {} - for x in G: - for y in G[x]: - nx = [frozenset([x,z]) for z in G[x] if z != y] - ny = [frozenset([y,z]) for z in G[y] if z != x] - L[frozenset([x,y])] = frozenset(nx+ny) - return L - -def faces(G): - 'Return a set of faces in G. Where a face is a set of vertices on that face' - # currently limited to triangles,squares, and pentagons - f = set() - for v1, edges in G.items(): - for v2 in edges: - for v3 in G[v2]: - if v1 == v3: - continue - if v1 in G[v3]: - f.add(frozenset([v1, v2, v3])) - else: - for v4 in G[v3]: - if v4 == v2: - continue - if v1 in G[v4]: - f.add(frozenset([v1, v2, v3, v4])) - else: - for v5 in G[v4]: - if v5 == v3 or v5 == v2: - continue - if v1 in G[v5]: - f.add(frozenset([v1, v2, v3, v4, v5])) - return f - - -class TestGraphs(unittest.TestCase): - - def test_cube(self): - - g = cube(3) # vert --> {v1, v2, v3} - vertices1 = set(g) - self.assertEqual(len(vertices1), 8) # eight vertices - for edge in g.values(): - self.assertEqual(len(edge), 3) # each vertex connects to three edges - vertices2 = set() - for edges in g.values(): - for v in edges: - vertices2.add(v) - self.assertEqual(vertices1, vertices2) # edge vertices in original set - - cubefaces = faces(g) - self.assertEqual(len(cubefaces), 6) # six faces - for face in cubefaces: - self.assertEqual(len(face), 4) # each face is a square - - def test_cuboctahedron(self): - - # http://en.wikipedia.org/wiki/Cuboctahedron - # 8 triangular faces and 6 square faces - # 12 identical vertices each connecting a triangle and square - - g = cube(3) - cuboctahedron = linegraph(g) # V( --> {V1, V2, V3, V4} - self.assertEqual(len(cuboctahedron), 12)# twelve vertices - - vertices = set(cuboctahedron) - for edges in cuboctahedron.values(): - self.assertEqual(len(edges), 4) # each vertex connects to four other vertices - othervertices = set(edge for edges in cuboctahedron.values() for edge in edges) - self.assertEqual(vertices, othervertices) # edge vertices in original set - - cubofaces = faces(cuboctahedron) - facesizes = collections.defaultdict(int) - for face in cubofaces: - facesizes[len(face)] += 1 - self.assertEqual(facesizes[3], 8) # eight triangular faces - self.assertEqual(facesizes[4], 6) # six square faces - - for vertex in cuboctahedron: - edge = vertex # Cuboctahedron vertices are edges in Cube - self.assertEqual(len(edge), 2) # Two cube vertices define an edge - for cubevert in edge: - self.assertIn(cubevert, g) - - -#============================================================================== - -def test_main(verbose=None): - test_classes = ( - TestSet, - TestSetSubclass, - TestSetSubclassWithKeywordArgs, - TestFrozenSet, - TestFrozenSetSubclass, - TestSetOfSets, - TestExceptionPropagation, - TestBasicOpsEmpty, - TestBasicOpsSingleton, - TestBasicOpsTuple, - TestBasicOpsTriple, - TestBasicOpsString, - TestBasicOpsBytes, - TestBasicOpsMixedStringBytes, - TestBinaryOps, - TestUpdateOps, - TestMutate, - TestSubsetEqualEmpty, - TestSubsetEqualNonEmpty, - TestSubsetEmptyNonEmpty, - TestSubsetPartial, - TestSubsetNonOverlap, - TestOnlySetsNumeric, - TestOnlySetsDict, - TestOnlySetsOperator, - TestOnlySetsTuple, - TestOnlySetsString, - TestOnlySetsGenerator, - TestCopyingEmpty, - TestCopyingSingleton, - TestCopyingTriple, - TestCopyingTuple, - TestCopyingNested, - TestIdentities, - TestVariousIteratorArgs, - TestGraphs, - TestWeirdBugs, - ) - - support.run_unittest(*test_classes) - - # verify reference counting - if verbose and hasattr(sys, "gettotalrefcount"): - import gc - counts = [None] * 5 - for i in range(len(counts)): - support.run_unittest(*test_classes) - gc.collect() - counts[i] = sys.gettotalrefcount() - print(counts) - -if __name__ == "__main__": - test_main(verbose=True) diff --git a/test-data/stdlib-samples/3.2/test/test_shutil.py b/test-data/stdlib-samples/3.2/test/test_shutil.py deleted file mode 100644 index 32e0fd153bcf8..0000000000000 --- a/test-data/stdlib-samples/3.2/test/test_shutil.py +++ /dev/null @@ -1,978 +0,0 @@ -# Copyright (C) 2003 Python Software Foundation - -import unittest -import shutil -import tempfile -import sys -import stat -import os -import os.path -import functools -from test import support -from test.support import TESTFN -from os.path import splitdrive -from distutils.spawn import find_executable, spawn -from shutil import (_make_tarball, _make_zipfile, make_archive, - register_archive_format, unregister_archive_format, - get_archive_formats, Error, unpack_archive, - register_unpack_format, RegistryError, - unregister_unpack_format, get_unpack_formats) -import tarfile -import warnings - -from test import support -from test.support import check_warnings, captured_stdout - -from typing import ( - Any, Callable, Tuple, List, Sequence, BinaryIO, IO, Union, cast -) -from types import TracebackType - -import bz2 -BZ2_SUPPORTED = True - -TESTFN2 = TESTFN + "2" - -import grp -import pwd -UID_GID_SUPPORT = True - -import zlib - -import zipfile -ZIP_SUPPORT = True - -def _fake_rename(*args: Any, **kwargs: Any) -> None: - # Pretend the destination path is on a different filesystem. - raise OSError() - -def mock_rename(func: Any) -> Any: - @functools.wraps(func) - def wrap(*args: Any, **kwargs: Any) -> Any: - try: - builtin_rename = shutil.rename - shutil.rename = cast(Any, _fake_rename) - return func(*args, **kwargs) - finally: - shutil.rename = cast(Any, builtin_rename) - return wrap - -class TestShutil(unittest.TestCase): - - def setUp(self) -> None: - super().setUp() - self.tempdirs = [] # type: List[str] - - def tearDown(self) -> None: - super().tearDown() - while self.tempdirs: - d = self.tempdirs.pop() - shutil.rmtree(d, os.name in ('nt', 'cygwin')) - - def write_file(self, path: Union[str, List[str], tuple], content: str = 'xxx') -> None: - """Writes a file in the given path. - - - path can be a string or a sequence. - """ - if isinstance(path, list): - path = os.path.join(*path) - elif isinstance(path, tuple): - path = cast(str, os.path.join(*path)) - f = open(path, 'w') - try: - f.write(content) - finally: - f.close() - - def mkdtemp(self) -> str: - """Create a temporary directory that will be cleaned up. - - Returns the path of the directory. - """ - d = tempfile.mkdtemp() - self.tempdirs.append(d) - return d - - def test_rmtree_errors(self) -> None: - # filename is guaranteed not to exist - filename = tempfile.mktemp() - self.assertRaises(OSError, shutil.rmtree, filename) - - # See bug #1071513 for why we don't run this on cygwin - # and bug #1076467 for why we don't run this as root. - if (hasattr(os, 'chmod') and sys.platform[:6] != 'cygwin' - and not (hasattr(os, 'geteuid') and os.geteuid() == 0)): - def test_on_error(self) -> None: - self.errorState = 0 - os.mkdir(TESTFN) - self.childpath = os.path.join(TESTFN, 'a') - f = open(self.childpath, 'w') - f.close() - old_dir_mode = os.stat(TESTFN).st_mode - old_child_mode = os.stat(self.childpath).st_mode - # Make unwritable. - os.chmod(self.childpath, stat.S_IREAD) - os.chmod(TESTFN, stat.S_IREAD) - - shutil.rmtree(TESTFN, onerror=self.check_args_to_onerror) - # Test whether onerror has actually been called. - self.assertEqual(self.errorState, 2, - "Expected call to onerror function did not happen.") - - # Make writable again. - os.chmod(TESTFN, old_dir_mode) - os.chmod(self.childpath, old_child_mode) - - # Clean up. - shutil.rmtree(TESTFN) - - def check_args_to_onerror(self, func: Callable[[str], Any], arg: str, - exc: Tuple[type, BaseException, - TracebackType]) -> None: - # test_rmtree_errors deliberately runs rmtree - # on a directory that is chmod 400, which will fail. - # This function is run when shutil.rmtree fails. - # 99.9% of the time it initially fails to remove - # a file in the directory, so the first time through - # func is os.remove. - # However, some Linux machines running ZFS on - # FUSE experienced a failure earlier in the process - # at os.listdir. The first failure may legally - # be either. - if self.errorState == 0: - if func is os.remove: - self.assertEqual(arg, self.childpath) - else: - self.assertIs(func, os.listdir, - "func must be either os.remove or os.listdir") - self.assertEqual(arg, TESTFN) - self.assertTrue(issubclass(exc[0], OSError)) - self.errorState = 1 - else: - self.assertEqual(func, os.rmdir) - self.assertEqual(arg, TESTFN) - self.assertTrue(issubclass(exc[0], OSError)) - self.errorState = 2 - - def test_rmtree_dont_delete_file(self) -> None: - # When called on a file instead of a directory, don't delete it. - handle, path = tempfile.mkstemp() - os.fdopen(handle).close() - self.assertRaises(OSError, shutil.rmtree, path) - os.remove(path) - - def _write_data(self, path: str, data: str) -> None: - f = open(path, "w") - f.write(data) - f.close() - - def test_copytree_simple(self) -> None: - - def read_data(path: str) -> str: - f = open(path) - data = f.read() - f.close() - return data - - src_dir = tempfile.mkdtemp() - dst_dir = os.path.join(tempfile.mkdtemp(), 'destination') - self._write_data(os.path.join(src_dir, 'test.txt'), '123') - os.mkdir(os.path.join(src_dir, 'test_dir')) - self._write_data(os.path.join(src_dir, 'test_dir', 'test.txt'), '456') - - try: - shutil.copytree(src_dir, dst_dir) - self.assertTrue(os.path.isfile(os.path.join(dst_dir, 'test.txt'))) - self.assertTrue(os.path.isdir(os.path.join(dst_dir, 'test_dir'))) - self.assertTrue(os.path.isfile(os.path.join(dst_dir, 'test_dir', - 'test.txt'))) - actual = read_data(os.path.join(dst_dir, 'test.txt')) - self.assertEqual(actual, '123') - actual = read_data(os.path.join(dst_dir, 'test_dir', 'test.txt')) - self.assertEqual(actual, '456') - finally: - for path in ( - os.path.join(src_dir, 'test.txt'), - os.path.join(dst_dir, 'test.txt'), - os.path.join(src_dir, 'test_dir', 'test.txt'), - os.path.join(dst_dir, 'test_dir', 'test.txt'), - ): - if os.path.exists(path): - os.remove(path) - for path in (src_dir, - os.path.dirname(dst_dir) - ): - if os.path.exists(path): - shutil.rmtree(path) - - def test_copytree_with_exclude(self) -> None: - - def read_data(path: str) -> str: - f = open(path) - data = f.read() - f.close() - return data - - # creating data - join = os.path.join - exists = os.path.exists - src_dir = tempfile.mkdtemp() - try: - dst_dir = join(tempfile.mkdtemp(), 'destination') - self._write_data(join(src_dir, 'test.txt'), '123') - self._write_data(join(src_dir, 'test.tmp'), '123') - os.mkdir(join(src_dir, 'test_dir')) - self._write_data(join(src_dir, 'test_dir', 'test.txt'), '456') - os.mkdir(join(src_dir, 'test_dir2')) - self._write_data(join(src_dir, 'test_dir2', 'test.txt'), '456') - os.mkdir(join(src_dir, 'test_dir2', 'subdir')) - os.mkdir(join(src_dir, 'test_dir2', 'subdir2')) - self._write_data(join(src_dir, 'test_dir2', 'subdir', 'test.txt'), - '456') - self._write_data(join(src_dir, 'test_dir2', 'subdir2', 'test.py'), - '456') - - - # testing glob-like patterns - try: - patterns = shutil.ignore_patterns('*.tmp', 'test_dir2') - shutil.copytree(src_dir, dst_dir, ignore=patterns) - # checking the result: some elements should not be copied - self.assertTrue(exists(join(dst_dir, 'test.txt'))) - self.assertTrue(not exists(join(dst_dir, 'test.tmp'))) - self.assertTrue(not exists(join(dst_dir, 'test_dir2'))) - finally: - if os.path.exists(dst_dir): - shutil.rmtree(dst_dir) - try: - patterns = shutil.ignore_patterns('*.tmp', 'subdir*') - shutil.copytree(src_dir, dst_dir, ignore=patterns) - # checking the result: some elements should not be copied - self.assertTrue(not exists(join(dst_dir, 'test.tmp'))) - self.assertTrue(not exists(join(dst_dir, 'test_dir2', 'subdir2'))) - self.assertTrue(not exists(join(dst_dir, 'test_dir2', 'subdir'))) - finally: - if os.path.exists(dst_dir): - shutil.rmtree(dst_dir) - - # testing callable-style - try: - def _filter(src: str, names: Sequence[str]) -> List[str]: - res = [] # type: List[str] - for name in names: - path = os.path.join(src, name) - - if (os.path.isdir(path) and - path.split()[-1] == 'subdir'): - res.append(name) - elif os.path.splitext(path)[-1] in ('.py'): - res.append(name) - return res - - shutil.copytree(src_dir, dst_dir, ignore=_filter) - - # checking the result: some elements should not be copied - self.assertTrue(not exists(join(dst_dir, 'test_dir2', 'subdir2', - 'test.py'))) - self.assertTrue(not exists(join(dst_dir, 'test_dir2', 'subdir'))) - - finally: - if os.path.exists(dst_dir): - shutil.rmtree(dst_dir) - finally: - shutil.rmtree(src_dir) - shutil.rmtree(os.path.dirname(dst_dir)) - - @unittest.skipUnless(hasattr(os, 'link'), 'requires os.link') - def test_dont_copy_file_onto_link_to_itself(self) -> None: - # Temporarily disable test on Windows. - if os.name == 'nt': - return - # bug 851123. - os.mkdir(TESTFN) - src = os.path.join(TESTFN, 'cheese') - dst = os.path.join(TESTFN, 'shop') - try: - with open(src, 'w') as f: - f.write('cheddar') - os.link(src, dst) - self.assertRaises(shutil.Error, shutil.copyfile, src, dst) - with open(src, 'r') as f: - self.assertEqual(f.read(), 'cheddar') - os.remove(dst) - finally: - shutil.rmtree(TESTFN, ignore_errors=True) - - @support.skip_unless_symlink - def test_dont_copy_file_onto_symlink_to_itself(self) -> None: - # bug 851123. - os.mkdir(TESTFN) - src = os.path.join(TESTFN, 'cheese') - dst = os.path.join(TESTFN, 'shop') - try: - with open(src, 'w') as f: - f.write('cheddar') - # Using `src` here would mean we end up with a symlink pointing - # to TESTFN/TESTFN/cheese, while it should point at - # TESTFN/cheese. - os.symlink('cheese', dst) - self.assertRaises(shutil.Error, shutil.copyfile, src, dst) - with open(src, 'r') as f: - self.assertEqual(f.read(), 'cheddar') - os.remove(dst) - finally: - shutil.rmtree(TESTFN, ignore_errors=True) - - @support.skip_unless_symlink - def test_rmtree_on_symlink(self) -> None: - # bug 1669. - os.mkdir(TESTFN) - try: - src = os.path.join(TESTFN, 'cheese') - dst = os.path.join(TESTFN, 'shop') - os.mkdir(src) - os.symlink(src, dst) - self.assertRaises(OSError, shutil.rmtree, dst) - finally: - shutil.rmtree(TESTFN, ignore_errors=True) - - if hasattr(os, "mkfifo"): - # Issue #3002: copyfile and copytree block indefinitely on named pipes - def test_copyfile_named_pipe(self) -> None: - os.mkfifo(TESTFN) - try: - self.assertRaises(shutil.SpecialFileError, - shutil.copyfile, TESTFN, TESTFN2) - self.assertRaises(shutil.SpecialFileError, - shutil.copyfile, __file__, TESTFN) - finally: - os.remove(TESTFN) - - @support.skip_unless_symlink - def test_copytree_named_pipe(self) -> None: - os.mkdir(TESTFN) - try: - subdir = os.path.join(TESTFN, "subdir") - os.mkdir(subdir) - pipe = os.path.join(subdir, "mypipe") - os.mkfifo(pipe) - try: - shutil.copytree(TESTFN, TESTFN2) - except shutil.Error as e: - errors = e.args[0] - self.assertEqual(len(errors), 1) - src, dst, error_msg = errors[0] - self.assertEqual("`%s` is a named pipe" % pipe, error_msg) - else: - self.fail("shutil.Error should have been raised") - finally: - shutil.rmtree(TESTFN, ignore_errors=True) - shutil.rmtree(TESTFN2, ignore_errors=True) - - def test_copytree_special_func(self) -> None: - - src_dir = self.mkdtemp() - dst_dir = os.path.join(self.mkdtemp(), 'destination') - self._write_data(os.path.join(src_dir, 'test.txt'), '123') - os.mkdir(os.path.join(src_dir, 'test_dir')) - self._write_data(os.path.join(src_dir, 'test_dir', 'test.txt'), '456') - - copied = [] # type: List[Tuple[str, str]] - def _copy(src: str, dst: str) -> None: - copied.append((src, dst)) - - shutil.copytree(src_dir, dst_dir, copy_function=_copy) - self.assertEqual(len(copied), 2) - - @support.skip_unless_symlink - def test_copytree_dangling_symlinks(self) -> None: - - # a dangling symlink raises an error at the end - src_dir = self.mkdtemp() - dst_dir = os.path.join(self.mkdtemp(), 'destination') - os.symlink('IDONTEXIST', os.path.join(src_dir, 'test.txt')) - os.mkdir(os.path.join(src_dir, 'test_dir')) - self._write_data(os.path.join(src_dir, 'test_dir', 'test.txt'), '456') - self.assertRaises(Error, shutil.copytree, src_dir, dst_dir) - - # a dangling symlink is ignored with the proper flag - dst_dir = os.path.join(self.mkdtemp(), 'destination2') - shutil.copytree(src_dir, dst_dir, ignore_dangling_symlinks=True) - self.assertNotIn('test.txt', os.listdir(dst_dir)) - - # a dangling symlink is copied if symlinks=True - dst_dir = os.path.join(self.mkdtemp(), 'destination3') - shutil.copytree(src_dir, dst_dir, symlinks=True) - self.assertIn('test.txt', os.listdir(dst_dir)) - - def _copy_file(self, - method: Callable[[str, str], None]) -> Tuple[str, str]: - fname = 'test.txt' - tmpdir = self.mkdtemp() - self.write_file([tmpdir, fname]) - file1 = os.path.join(tmpdir, fname) - tmpdir2 = self.mkdtemp() - method(file1, tmpdir2) - file2 = os.path.join(tmpdir2, fname) - return (file1, file2) - - @unittest.skipUnless(hasattr(os, 'chmod'), 'requires os.chmod') - def test_copy(self) -> None: - # Ensure that the copied file exists and has the same mode bits. - file1, file2 = self._copy_file(shutil.copy) - self.assertTrue(os.path.exists(file2)) - self.assertEqual(os.stat(file1).st_mode, os.stat(file2).st_mode) - - @unittest.skipUnless(hasattr(os, 'chmod'), 'requires os.chmod') - @unittest.skipUnless(hasattr(os, 'utime'), 'requires os.utime') - def test_copy2(self) -> None: - # Ensure that the copied file exists and has the same mode and - # modification time bits. - file1, file2 = self._copy_file(shutil.copy2) - self.assertTrue(os.path.exists(file2)) - file1_stat = os.stat(file1) - file2_stat = os.stat(file2) - self.assertEqual(file1_stat.st_mode, file2_stat.st_mode) - for attr in 'st_atime', 'st_mtime': - # The modification times may be truncated in the new file. - self.assertLessEqual(getattr(file1_stat, attr), - getattr(file2_stat, attr) + 1) - if hasattr(os, 'chflags') and hasattr(file1_stat, 'st_flags'): - self.assertEqual(getattr(file1_stat, 'st_flags'), - getattr(file2_stat, 'st_flags')) - - @unittest.skipUnless(zlib, "requires zlib") - def test_make_tarball(self) -> None: - # creating something to tar - tmpdir = self.mkdtemp() - self.write_file([tmpdir, 'file1'], 'xxx') - self.write_file([tmpdir, 'file2'], 'xxx') - os.mkdir(os.path.join(tmpdir, 'sub')) - self.write_file([tmpdir, 'sub', 'file3'], 'xxx') - - tmpdir2 = self.mkdtemp() - # force shutil to create the directory - os.rmdir(tmpdir2) - unittest.skipUnless(splitdrive(tmpdir)[0] == splitdrive(tmpdir2)[0], - "source and target should be on same drive") - - base_name = os.path.join(tmpdir2, 'archive') - - # working with relative paths to avoid tar warnings - old_dir = os.getcwd() - os.chdir(tmpdir) - try: - _make_tarball(splitdrive(base_name)[1], '.') - finally: - os.chdir(old_dir) - - # check if the compressed tarball was created - tarball = base_name + '.tar.gz' - self.assertTrue(os.path.exists(tarball)) - - # trying an uncompressed one - base_name = os.path.join(tmpdir2, 'archive') - old_dir = os.getcwd() - os.chdir(tmpdir) - try: - _make_tarball(splitdrive(base_name)[1], '.', compress=None) - finally: - os.chdir(old_dir) - tarball = base_name + '.tar' - self.assertTrue(os.path.exists(tarball)) - - def _tarinfo(self, path: str) -> tuple: - tar = tarfile.open(path) - try: - names = tar.getnames() - names.sort() - return tuple(names) - finally: - tar.close() - - def _create_files(self) -> Tuple[str, str, str]: - # creating something to tar - tmpdir = self.mkdtemp() - dist = os.path.join(tmpdir, 'dist') - os.mkdir(dist) - self.write_file([dist, 'file1'], 'xxx') - self.write_file([dist, 'file2'], 'xxx') - os.mkdir(os.path.join(dist, 'sub')) - self.write_file([dist, 'sub', 'file3'], 'xxx') - os.mkdir(os.path.join(dist, 'sub2')) - tmpdir2 = self.mkdtemp() - base_name = os.path.join(tmpdir2, 'archive') - return tmpdir, tmpdir2, base_name - - @unittest.skipUnless(zlib, "Requires zlib") - @unittest.skipUnless(find_executable('tar') and find_executable('gzip'), - 'Need the tar command to run') - def test_tarfile_vs_tar(self) -> None: - tmpdir, tmpdir2, base_name = self._create_files() - old_dir = os.getcwd() - os.chdir(tmpdir) - try: - _make_tarball(base_name, 'dist') - finally: - os.chdir(old_dir) - - # check if the compressed tarball was created - tarball = base_name + '.tar.gz' - self.assertTrue(os.path.exists(tarball)) - - # now create another tarball using `tar` - tarball2 = os.path.join(tmpdir, 'archive2.tar.gz') - tar_cmd = ['tar', '-cf', 'archive2.tar', 'dist'] - gzip_cmd = ['gzip', '-f9', 'archive2.tar'] - old_dir = os.getcwd() - os.chdir(tmpdir) - try: - with captured_stdout() as s: - spawn(tar_cmd) - spawn(gzip_cmd) - finally: - os.chdir(old_dir) - - self.assertTrue(os.path.exists(tarball2)) - # let's compare both tarballs - self.assertEqual(self._tarinfo(tarball), self._tarinfo(tarball2)) - - # trying an uncompressed one - base_name = os.path.join(tmpdir2, 'archive') - old_dir = os.getcwd() - os.chdir(tmpdir) - try: - _make_tarball(base_name, 'dist', compress=None) - finally: - os.chdir(old_dir) - tarball = base_name + '.tar' - self.assertTrue(os.path.exists(tarball)) - - # now for a dry_run - base_name = os.path.join(tmpdir2, 'archive') - old_dir = os.getcwd() - os.chdir(tmpdir) - try: - _make_tarball(base_name, 'dist', compress=None, dry_run=True) - finally: - os.chdir(old_dir) - tarball = base_name + '.tar' - self.assertTrue(os.path.exists(tarball)) - - @unittest.skipUnless(zlib, "Requires zlib") - @unittest.skipUnless(ZIP_SUPPORT, 'Need zip support to run') - def test_make_zipfile(self) -> None: - # creating something to tar - tmpdir = self.mkdtemp() - self.write_file([tmpdir, 'file1'], 'xxx') - self.write_file([tmpdir, 'file2'], 'xxx') - - tmpdir2 = self.mkdtemp() - # force shutil to create the directory - os.rmdir(tmpdir2) - base_name = os.path.join(tmpdir2, 'archive') - _make_zipfile(base_name, tmpdir) - - # check if the compressed tarball was created - tarball = base_name + '.zip' - self.assertTrue(os.path.exists(tarball)) - - - def test_make_archive(self) -> None: - tmpdir = self.mkdtemp() - base_name = os.path.join(tmpdir, 'archive') - self.assertRaises(ValueError, make_archive, base_name, 'xxx') - - @unittest.skipUnless(zlib, "Requires zlib") - def test_make_archive_owner_group(self) -> None: - # testing make_archive with owner and group, with various combinations - # this works even if there's not gid/uid support - if UID_GID_SUPPORT: - group = grp.getgrgid(0).gr_name - owner = pwd.getpwuid(0).pw_name - else: - group = owner = 'root' - - base_dir, root_dir, base_name = self._create_files() - base_name = os.path.join(self.mkdtemp() , 'archive') - res = make_archive(base_name, 'zip', root_dir, base_dir, owner=owner, - group=group) - self.assertTrue(os.path.exists(res)) - - res = make_archive(base_name, 'zip', root_dir, base_dir) - self.assertTrue(os.path.exists(res)) - - res = make_archive(base_name, 'tar', root_dir, base_dir, - owner=owner, group=group) - self.assertTrue(os.path.exists(res)) - - res = make_archive(base_name, 'tar', root_dir, base_dir, - owner='kjhkjhkjg', group='oihohoh') - self.assertTrue(os.path.exists(res)) - - - @unittest.skipUnless(zlib, "Requires zlib") - @unittest.skipUnless(UID_GID_SUPPORT, "Requires grp and pwd support") - def test_tarfile_root_owner(self) -> None: - tmpdir, tmpdir2, base_name = self._create_files() - old_dir = os.getcwd() - os.chdir(tmpdir) - group = grp.getgrgid(0).gr_name - owner = pwd.getpwuid(0).pw_name - try: - archive_name = _make_tarball(base_name, 'dist', compress=None, - owner=owner, group=group) - finally: - os.chdir(old_dir) - - # check if the compressed tarball was created - self.assertTrue(os.path.exists(archive_name)) - - # now checks the rights - archive = tarfile.open(archive_name) - try: - for member in archive.getmembers(): - self.assertEqual(member.uid, 0) - self.assertEqual(member.gid, 0) - finally: - archive.close() - - def test_make_archive_cwd(self) -> None: - current_dir = os.getcwd() - def _breaks(*args: Any, **kw: Any) -> None: - raise RuntimeError() - - register_archive_format('xxx', _breaks, [], 'xxx file') - try: - try: - make_archive('xxx', 'xxx', root_dir=self.mkdtemp()) - except Exception: - pass - self.assertEqual(os.getcwd(), current_dir) - finally: - unregister_archive_format('xxx') - - def test_register_archive_format(self) -> None: - - self.assertRaises(TypeError, register_archive_format, 'xxx', 1) - self.assertRaises(TypeError, register_archive_format, 'xxx', - lambda: 1/0, - 1) - self.assertRaises(TypeError, register_archive_format, 'xxx', - lambda: 1/0, - [(1, 2), (1, 2, 3)]) - - register_archive_format('xxx', lambda: 1/0, [('x', 2)], 'xxx file') - formats = [name for name, params in get_archive_formats()] - self.assertIn('xxx', formats) - - unregister_archive_format('xxx') - formats = [name for name, params in get_archive_formats()] - self.assertNotIn('xxx', formats) - - def _compare_dirs(self, dir1: str, dir2: str) -> List[str]: - # check that dir1 and dir2 are equivalent, - # return the diff - diff = [] # type: List[str] - for root, dirs, files in os.walk(dir1): - for file_ in files: - path = os.path.join(root, file_) - target_path = os.path.join(dir2, os.path.split(path)[-1]) - if not os.path.exists(target_path): - diff.append(file_) - return diff - - @unittest.skipUnless(zlib, "Requires zlib") - def test_unpack_archive(self) -> None: - formats = ['tar', 'gztar', 'zip'] - if BZ2_SUPPORTED: - formats.append('bztar') - - for format in formats: - tmpdir = self.mkdtemp() - base_dir, root_dir, base_name = self._create_files() - tmpdir2 = self.mkdtemp() - filename = make_archive(base_name, format, root_dir, base_dir) - - # let's try to unpack it now - unpack_archive(filename, tmpdir2) - diff = self._compare_dirs(tmpdir, tmpdir2) - self.assertEqual(diff, []) - - # and again, this time with the format specified - tmpdir3 = self.mkdtemp() - unpack_archive(filename, tmpdir3, format=format) - diff = self._compare_dirs(tmpdir, tmpdir3) - self.assertEqual(diff, []) - self.assertRaises(shutil.ReadError, unpack_archive, TESTFN) - self.assertRaises(ValueError, unpack_archive, TESTFN, format='xxx') - - def test_unpack_registery(self) -> None: - - formats = get_unpack_formats() - - def _boo(filename: str, extract_dir: str, extra: int) -> None: - self.assertEqual(extra, 1) - self.assertEqual(filename, 'stuff.boo') - self.assertEqual(extract_dir, 'xx') - - register_unpack_format('Boo', ['.boo', '.b2'], _boo, [('extra', 1)]) - unpack_archive('stuff.boo', 'xx') - - # trying to register a .boo unpacker again - self.assertRaises(RegistryError, register_unpack_format, 'Boo2', - ['.boo'], _boo) - - # should work now - unregister_unpack_format('Boo') - register_unpack_format('Boo2', ['.boo'], _boo) - self.assertIn(('Boo2', ['.boo'], ''), get_unpack_formats()) - self.assertNotIn(('Boo', ['.boo'], ''), get_unpack_formats()) - - # let's leave a clean state - unregister_unpack_format('Boo2') - self.assertEqual(get_unpack_formats(), formats) - - -class TestMove(unittest.TestCase): - - def setUp(self) -> None: - filename = "foo" - self.src_dir = tempfile.mkdtemp() - self.dst_dir = tempfile.mkdtemp() - self.src_file = os.path.join(self.src_dir, filename) - self.dst_file = os.path.join(self.dst_dir, filename) - with open(self.src_file, "wb") as f: - f.write(b"spam") - - def tearDown(self) -> None: - for d in (self.src_dir, self.dst_dir): - try: - if d: - shutil.rmtree(d) - except: - pass - - def _check_move_file(self, src: str, dst: str, real_dst: str) -> None: - with open(src, "rb") as f: - contents = f.read() - shutil.move(src, dst) - with open(real_dst, "rb") as f: - self.assertEqual(contents, f.read()) - self.assertFalse(os.path.exists(src)) - - def _check_move_dir(self, src: str, dst: str, real_dst: str) -> None: - contents = sorted(os.listdir(src)) - shutil.move(src, dst) - self.assertEqual(contents, sorted(os.listdir(real_dst))) - self.assertFalse(os.path.exists(src)) - - def test_move_file(self) -> None: - # Move a file to another location on the same filesystem. - self._check_move_file(self.src_file, self.dst_file, self.dst_file) - - def test_move_file_to_dir(self) -> None: - # Move a file inside an existing dir on the same filesystem. - self._check_move_file(self.src_file, self.dst_dir, self.dst_file) - - @mock_rename - def test_move_file_other_fs(self) -> None: - # Move a file to an existing dir on another filesystem. - self.test_move_file() - - @mock_rename - def test_move_file_to_dir_other_fs(self) -> None: - # Move a file to another location on another filesystem. - self.test_move_file_to_dir() - - def test_move_dir(self) -> None: - # Move a dir to another location on the same filesystem. - dst_dir = tempfile.mktemp() - try: - self._check_move_dir(self.src_dir, dst_dir, dst_dir) - finally: - try: - shutil.rmtree(dst_dir) - except: - pass - - @mock_rename - def test_move_dir_other_fs(self) -> None: - # Move a dir to another location on another filesystem. - self.test_move_dir() - - def test_move_dir_to_dir(self) -> None: - # Move a dir inside an existing dir on the same filesystem. - self._check_move_dir(self.src_dir, self.dst_dir, - os.path.join(self.dst_dir, os.path.basename(self.src_dir))) - - @mock_rename - def test_move_dir_to_dir_other_fs(self) -> None: - # Move a dir inside an existing dir on another filesystem. - self.test_move_dir_to_dir() - - def test_existing_file_inside_dest_dir(self) -> None: - # A file with the same name inside the destination dir already exists. - with open(self.dst_file, "wb"): - pass - self.assertRaises(shutil.Error, shutil.move, self.src_file, self.dst_dir) - - def test_dont_move_dir_in_itself(self) -> None: - # Moving a dir inside itself raises an Error. - dst = os.path.join(self.src_dir, "bar") - self.assertRaises(shutil.Error, shutil.move, self.src_dir, dst) - - def test_destinsrc_false_negative(self) -> None: - os.mkdir(TESTFN) - try: - for src, dst in [('srcdir', 'srcdir/dest')]: - src = os.path.join(TESTFN, src) - dst = os.path.join(TESTFN, dst) - self.assertTrue(shutil._destinsrc(src, dst), - msg='_destinsrc() wrongly concluded that ' - 'dst (%s) is not in src (%s)' % (dst, src)) - finally: - shutil.rmtree(TESTFN, ignore_errors=True) - - def test_destinsrc_false_positive(self) -> None: - os.mkdir(TESTFN) - try: - for src, dst in [('srcdir', 'src/dest'), ('srcdir', 'srcdir.new')]: - src = os.path.join(TESTFN, src) - dst = os.path.join(TESTFN, dst) - self.assertFalse(shutil._destinsrc(src, dst), - msg='_destinsrc() wrongly concluded that ' - 'dst (%s) is in src (%s)' % (dst, src)) - finally: - shutil.rmtree(TESTFN, ignore_errors=True) - - -class TestCopyFile(unittest.TestCase): - - _delete = False - - class Faux(object): - _entered = False - _exited_with = None # type: tuple - _raised = False - def __init__(self, raise_in_exit: bool = False, - suppress_at_exit: bool = True) -> None: - self._raise_in_exit = raise_in_exit - self._suppress_at_exit = suppress_at_exit - def read(self, *args: Any) -> str: - return '' - def __enter__(self) -> None: - self._entered = True - def __exit__(self, exc_type: type, exc_val: BaseException, - exc_tb: TracebackType) -> bool: - self._exited_with = exc_type, exc_val, exc_tb - if self._raise_in_exit: - self._raised = True - raise IOError("Cannot close") - return self._suppress_at_exit - - def tearDown(self) -> None: - shutil.open = open - - def _set_shutil_open(self, func: Any) -> None: - shutil.open = func - self._delete = True - - def test_w_source_open_fails(self) -> None: - def _open(filename: str, mode: str= 'r') -> BinaryIO: - if filename == 'srcfile': - raise IOError('Cannot open "srcfile"') - assert 0 # shouldn't reach here. - - self._set_shutil_open(_open) - - self.assertRaises(IOError, shutil.copyfile, 'srcfile', 'destfile') - - def test_w_dest_open_fails(self) -> None: - - srcfile = TestCopyFile.Faux() - - def _open(filename: str, mode: str = 'r') -> TestCopyFile.Faux: - if filename == 'srcfile': - return srcfile - if filename == 'destfile': - raise IOError('Cannot open "destfile"') - assert 0 # shouldn't reach here. - - self._set_shutil_open(_open) - - shutil.copyfile('srcfile', 'destfile') - self.assertTrue(srcfile._entered) - self.assertTrue(srcfile._exited_with[0] is IOError) - self.assertEqual(srcfile._exited_with[1].args, - ('Cannot open "destfile"',)) - - def test_w_dest_close_fails(self) -> None: - - srcfile = TestCopyFile.Faux() - destfile = TestCopyFile.Faux(True) - - def _open(filename: str, mode: str = 'r') -> TestCopyFile.Faux: - if filename == 'srcfile': - return srcfile - if filename == 'destfile': - return destfile - assert 0 # shouldn't reach here. - - self._set_shutil_open(_open) - - shutil.copyfile('srcfile', 'destfile') - self.assertTrue(srcfile._entered) - self.assertTrue(destfile._entered) - self.assertTrue(destfile._raised) - self.assertTrue(srcfile._exited_with[0] is IOError) - self.assertEqual(srcfile._exited_with[1].args, - ('Cannot close',)) - - def test_w_source_close_fails(self) -> None: - - srcfile = TestCopyFile.Faux(True) - destfile = TestCopyFile.Faux() - - def _open(filename: str, mode: str= 'r') -> TestCopyFile.Faux: - if filename == 'srcfile': - return srcfile - if filename == 'destfile': - return destfile - assert 0 # shouldn't reach here. - - self._set_shutil_open(_open) - - self.assertRaises(IOError, - shutil.copyfile, 'srcfile', 'destfile') - self.assertTrue(srcfile._entered) - self.assertTrue(destfile._entered) - self.assertFalse(destfile._raised) - self.assertTrue(srcfile._exited_with[0] is None) - self.assertTrue(srcfile._raised) - - def test_move_dir_caseinsensitive(self) -> None: - # Renames a folder to the same name - # but a different case. - - self.src_dir = tempfile.mkdtemp() - dst_dir = os.path.join( - os.path.dirname(self.src_dir), - os.path.basename(self.src_dir).upper()) - self.assertNotEqual(self.src_dir, dst_dir) - - try: - shutil.move(self.src_dir, dst_dir) - self.assertTrue(os.path.isdir(dst_dir)) - finally: - if os.path.exists(dst_dir): - os.rmdir(dst_dir) - - - -def test_main() -> None: - support.run_unittest(TestShutil, TestMove, TestCopyFile) - -if __name__ == '__main__': - test_main() diff --git a/test-data/stdlib-samples/3.2/test/test_tempfile.py b/test-data/stdlib-samples/3.2/test/test_tempfile.py deleted file mode 100644 index 31b0fecbf6775..0000000000000 --- a/test-data/stdlib-samples/3.2/test/test_tempfile.py +++ /dev/null @@ -1,1122 +0,0 @@ -# tempfile.py unit tests. -import tempfile -import os -import signal -import sys -import re -import warnings - -import unittest -from test import support - -from typing import Any, AnyStr, List, Dict, IO - - -if hasattr(os, 'stat'): - import stat - has_stat = 1 -else: - has_stat = 0 - -has_textmode = (tempfile._text_openflags != tempfile._bin_openflags) -has_spawnl = hasattr(os, 'spawnl') - -# TEST_FILES may need to be tweaked for systems depending on the maximum -# number of files that can be opened at one time (see ulimit -n) -if sys.platform in ('openbsd3', 'openbsd4'): - TEST_FILES = 48 -else: - TEST_FILES = 100 - -# This is organized as one test for each chunk of code in tempfile.py, -# in order of their appearance in the file. Testing which requires -# threads is not done here. - -# Common functionality. -class TC(unittest.TestCase): - - str_check = re.compile(r"[a-zA-Z0-9_-]{6}$") - - def setUp(self) -> None: - self._warnings_manager = support.check_warnings() - self._warnings_manager.__enter__() - warnings.filterwarnings("ignore", category=RuntimeWarning, - message="mktemp", module=__name__) - - def tearDown(self) -> None: - self._warnings_manager.__exit__(None, None, None) - - - def failOnException(self, what: str, ei: tuple = None) -> None: - if ei is None: - ei = sys.exc_info() - self.fail("%s raised %s: %s" % (what, ei[0], ei[1])) - - def nameCheck(self, name: str, dir: str, pre: str, suf: str) -> None: - (ndir, nbase) = os.path.split(name) - npre = nbase[:len(pre)] - nsuf = nbase[len(nbase)-len(suf):] - - # check for equality of the absolute paths! - self.assertEqual(os.path.abspath(ndir), os.path.abspath(dir), - "file '%s' not in directory '%s'" % (name, dir)) - self.assertEqual(npre, pre, - "file '%s' does not begin with '%s'" % (nbase, pre)) - self.assertEqual(nsuf, suf, - "file '%s' does not end with '%s'" % (nbase, suf)) - - nbase = nbase[len(pre):len(nbase)-len(suf)] - self.assertTrue(self.str_check.match(nbase), - "random string '%s' does not match /^[a-zA-Z0-9_-]{6}$/" - % nbase) - -test_classes = [] # type: List[type] - -class test_exports(TC): - def test_exports(self) -> None: - # There are no surprising symbols in the tempfile module - dict = tempfile.__dict__ - - expected = { - "NamedTemporaryFile" : 1, - "TemporaryFile" : 1, - "mkstemp" : 1, - "mkdtemp" : 1, - "mktemp" : 1, - "TMP_MAX" : 1, - "gettempprefix" : 1, - "gettempdir" : 1, - "tempdir" : 1, - "template" : 1, - "SpooledTemporaryFile" : 1, - "TemporaryDirectory" : 1, - } - - unexp = [] # type: List[str] - for key in dict: - if key[0] != '_' and key not in expected: - unexp.append(key) - self.assertTrue(len(unexp) == 0, - "unexpected keys: %s" % unexp) - -test_classes.append(test_exports) - - -class test__RandomNameSequence(TC): - """Test the internal iterator object _RandomNameSequence.""" - - def setUp(self) -> None: - self.r = tempfile._RandomNameSequence() - super().setUp() - - def test_get_six_char_str(self) -> None: - # _RandomNameSequence returns a six-character string - s = next(self.r) - self.nameCheck(s, '', '', '') - - def test_many(self) -> None: - # _RandomNameSequence returns no duplicate strings (stochastic) - - dict = {} # type: Dict[str, int] - r = self.r - for i in range(TEST_FILES): - s = next(r) - self.nameCheck(s, '', '', '') - self.assertNotIn(s, dict) - dict[s] = 1 - - def supports_iter(self) -> None: - # _RandomNameSequence supports the iterator protocol - - i = 0 - r = self.r - try: - for s in r: - i += 1 - if i == 20: - break - except: - self.failOnException("iteration") - - @unittest.skipUnless(hasattr(os, 'fork'), - "os.fork is required for this test") - def test_process_awareness(self) -> None: - # ensure that the random source differs between - # child and parent. - read_fd, write_fd = os.pipe() - pid = None # type: int - try: - pid = os.fork() - if not pid: - os.close(read_fd) - os.write(write_fd, next(self.r).encode("ascii")) - os.close(write_fd) - # bypass the normal exit handlers- leave those to - # the parent. - os._exit(0) - parent_value = next(self.r) - child_value = os.read(read_fd, len(parent_value)).decode("ascii") - finally: - if pid: - # best effort to ensure the process can't bleed out - # via any bugs above - try: - os.kill(pid, signal.SIGKILL) - except EnvironmentError: - pass - os.close(read_fd) - os.close(write_fd) - self.assertNotEqual(child_value, parent_value) - - -test_classes.append(test__RandomNameSequence) - - -class test__candidate_tempdir_list(TC): - """Test the internal function _candidate_tempdir_list.""" - - def test_nonempty_list(self) -> None: - # _candidate_tempdir_list returns a nonempty list of strings - - cand = tempfile._candidate_tempdir_list() - - self.assertFalse(len(cand) == 0) - for c in cand: - self.assertIsInstance(c, str) - - def test_wanted_dirs(self) -> None: - # _candidate_tempdir_list contains the expected directories - - # Make sure the interesting environment variables are all set. - with support.EnvironmentVarGuard() as env: - for envname in 'TMPDIR', 'TEMP', 'TMP': - dirname = os.getenv(envname) - if not dirname: - env[envname] = os.path.abspath(envname) - - cand = tempfile._candidate_tempdir_list() - - for envname in 'TMPDIR', 'TEMP', 'TMP': - dirname = os.getenv(envname) - if not dirname: raise ValueError - self.assertIn(dirname, cand) - - try: - dirname = os.getcwd() - except (AttributeError, os.error): - dirname = os.curdir - - self.assertIn(dirname, cand) - - # Not practical to try to verify the presence of OS-specific - # paths in this list. - -test_classes.append(test__candidate_tempdir_list) - - -# We test _get_default_tempdir by testing gettempdir. - - -class test__get_candidate_names(TC): - """Test the internal function _get_candidate_names.""" - - def test_retval(self) -> None: - # _get_candidate_names returns a _RandomNameSequence object - obj = tempfile._get_candidate_names() - self.assertIsInstance(obj, tempfile._RandomNameSequence) - - def test_same_thing(self) -> None: - # _get_candidate_names always returns the same object - a = tempfile._get_candidate_names() - b = tempfile._get_candidate_names() - - self.assertTrue(a is b) - -test_classes.append(test__get_candidate_names) - - -class test__mkstemp_inner(TC): - """Test the internal function _mkstemp_inner.""" - - class mkstemped: - _bflags = tempfile._bin_openflags - _tflags = tempfile._text_openflags - - def __init__(self, dir: str, pre: str, suf: str, bin: int) -> None: - if bin: flags = self._bflags - else: flags = self._tflags - - (self.fd, self.name) = tempfile._mkstemp_inner(dir, pre, suf, flags) - - self._close = os.close - self._unlink = os.unlink - - def write(self, str: bytes) -> None: - os.write(self.fd, str) - - def __del__(self) -> None: - self._close(self.fd) - self._unlink(self.name) - - def do_create(self, dir: str = None, pre: str = "", suf: str= "", - bin: int = 1) -> mkstemped: - if dir is None: - dir = tempfile.gettempdir() - try: - file = test__mkstemp_inner.mkstemped(dir, pre, suf, bin) # see #259 - except: - self.failOnException("_mkstemp_inner") - - self.nameCheck(file.name, dir, pre, suf) - return file - - def test_basic(self) -> None: - # _mkstemp_inner can create files - self.do_create().write(b"blat") - self.do_create(pre="a").write(b"blat") - self.do_create(suf="b").write(b"blat") - self.do_create(pre="a", suf="b").write(b"blat") - self.do_create(pre="aa", suf=".txt").write(b"blat") - - def test_basic_many(self) -> None: - # _mkstemp_inner can create many files (stochastic) - extant = list(range(TEST_FILES)) # type: List[Any] - for i in extant: - extant[i] = self.do_create(pre="aa") - - def test_choose_directory(self) -> None: - # _mkstemp_inner can create files in a user-selected directory - dir = tempfile.mkdtemp() - try: - self.do_create(dir=dir).write(b"blat") - finally: - os.rmdir(dir) - - def test_file_mode(self) -> None: - # _mkstemp_inner creates files with the proper mode - if not has_stat: - return # ugh, can't use SkipTest. - - file = self.do_create() - mode = stat.S_IMODE(os.stat(file.name).st_mode) - expected = 0o600 - if sys.platform in ('win32', 'os2emx'): - # There's no distinction among 'user', 'group' and 'world'; - # replicate the 'user' bits. - user = expected >> 6 - expected = user * (1 + 8 + 64) - self.assertEqual(mode, expected) - - def test_noinherit(self) -> None: - # _mkstemp_inner file handles are not inherited by child processes - if not has_spawnl: - return # ugh, can't use SkipTest. - - if support.verbose: - v="v" - else: - v="q" - - file = self.do_create() - fd = "%d" % file.fd - - try: - me = __file__ # type: str - except NameError: - me = sys.argv[0] - - # We have to exec something, so that FD_CLOEXEC will take - # effect. The core of this test is therefore in - # tf_inherit_check.py, which see. - tester = os.path.join(os.path.dirname(os.path.abspath(me)), - "tf_inherit_check.py") - - # On Windows a spawn* /path/ with embedded spaces shouldn't be quoted, - # but an arg with embedded spaces should be decorated with double - # quotes on each end - if sys.platform in ('win32',): - decorated = '"%s"' % sys.executable - tester = '"%s"' % tester - else: - decorated = sys.executable - - retval = os.spawnl(os.P_WAIT, sys.executable, decorated, tester, v, fd) - self.assertFalse(retval < 0, - "child process caught fatal signal %d" % -retval) - self.assertFalse(retval > 0, "child process reports failure %d"%retval) - - def test_textmode(self) -> None: - # _mkstemp_inner can create files in text mode - if not has_textmode: - return # ugh, can't use SkipTest. - - # A text file is truncated at the first Ctrl+Z byte - f = self.do_create(bin=0) - f.write(b"blat\x1a") - f.write(b"extra\n") - os.lseek(f.fd, 0, os.SEEK_SET) - self.assertEqual(os.read(f.fd, 20), b"blat") - -test_classes.append(test__mkstemp_inner) - - -class test_gettempprefix(TC): - """Test gettempprefix().""" - - def test_sane_template(self) -> None: - # gettempprefix returns a nonempty prefix string - p = tempfile.gettempprefix() - - self.assertIsInstance(p, str) - self.assertTrue(len(p) > 0) - - def test_usable_template(self) -> None: - # gettempprefix returns a usable prefix string - - # Create a temp directory, avoiding use of the prefix. - # Then attempt to create a file whose name is - # prefix + 'xxxxxx.xxx' in that directory. - p = tempfile.gettempprefix() + "xxxxxx.xxx" - d = tempfile.mkdtemp(prefix="") - try: - p = os.path.join(d, p) - try: - fd = os.open(p, os.O_RDWR | os.O_CREAT) - except: - self.failOnException("os.open") - os.close(fd) - os.unlink(p) - finally: - os.rmdir(d) - -test_classes.append(test_gettempprefix) - - -class test_gettempdir(TC): - """Test gettempdir().""" - - def test_directory_exists(self) -> None: - # gettempdir returns a directory which exists - - dir = tempfile.gettempdir() - self.assertTrue(os.path.isabs(dir) or dir == os.curdir, - "%s is not an absolute path" % dir) - self.assertTrue(os.path.isdir(dir), - "%s is not a directory" % dir) - - def test_directory_writable(self) -> None: - # gettempdir returns a directory writable by the user - - # sneaky: just instantiate a NamedTemporaryFile, which - # defaults to writing into the directory returned by - # gettempdir. - try: - file = tempfile.NamedTemporaryFile() - file.write(b"blat") - file.close() - except: - self.failOnException("create file in %s" % tempfile.gettempdir()) - - def test_same_thing(self) -> None: - # gettempdir always returns the same object - a = tempfile.gettempdir() - b = tempfile.gettempdir() - - self.assertTrue(a is b) - -test_classes.append(test_gettempdir) - - -class test_mkstemp(TC): - """Test mkstemp().""" - - def do_create(self, dir: str = None, pre: str = "", suf: str = "") -> None: - if dir is None: - dir = tempfile.gettempdir() - try: - (fd, name) = tempfile.mkstemp(dir=dir, prefix=pre, suffix=suf) - (ndir, nbase) = os.path.split(name) - adir = os.path.abspath(dir) - self.assertEqual(adir, ndir, - "Directory '%s' incorrectly returned as '%s'" % (adir, ndir)) - except: - self.failOnException("mkstemp") - - try: - self.nameCheck(name, dir, pre, suf) - finally: - os.close(fd) - os.unlink(name) - - def test_basic(self) -> None: - # mkstemp can create files - self.do_create() - self.do_create(pre="a") - self.do_create(suf="b") - self.do_create(pre="a", suf="b") - self.do_create(pre="aa", suf=".txt") - self.do_create(dir=".") - - def test_choose_directory(self) -> None: - # mkstemp can create directories in a user-selected directory - dir = tempfile.mkdtemp() - try: - self.do_create(dir=dir) - finally: - os.rmdir(dir) - -test_classes.append(test_mkstemp) - - -class test_mkdtemp(TC): - """Test mkdtemp().""" - - def do_create(self, dir: str = None, pre: str = "", suf: str = "") -> str: - if dir is None: - dir = tempfile.gettempdir() - try: - name = tempfile.mkdtemp(dir=dir, prefix=pre, suffix=suf) - except: - self.failOnException("mkdtemp") - - try: - self.nameCheck(name, dir, pre, suf) - return name - except: - os.rmdir(name) - raise - - def test_basic(self) -> None: - # mkdtemp can create directories - os.rmdir(self.do_create()) - os.rmdir(self.do_create(pre="a")) - os.rmdir(self.do_create(suf="b")) - os.rmdir(self.do_create(pre="a", suf="b")) - os.rmdir(self.do_create(pre="aa", suf=".txt")) - - def test_basic_many(self) -> None: - # mkdtemp can create many directories (stochastic) - extant = list(range(TEST_FILES)) # type: List[Any] - try: - for i in extant: - extant[i] = self.do_create(pre="aa") - finally: - for i in extant: - if(isinstance(i, str)): - os.rmdir(i) - - def test_choose_directory(self) -> None: - # mkdtemp can create directories in a user-selected directory - dir = tempfile.mkdtemp() - try: - os.rmdir(self.do_create(dir=dir)) - finally: - os.rmdir(dir) - - def test_mode(self) -> None: - # mkdtemp creates directories with the proper mode - if not has_stat: - return # ugh, can't use SkipTest. - - dir = self.do_create() - try: - mode = stat.S_IMODE(os.stat(dir).st_mode) - mode &= 0o777 # Mask off sticky bits inherited from /tmp - expected = 0o700 - if sys.platform in ('win32', 'os2emx'): - # There's no distinction among 'user', 'group' and 'world'; - # replicate the 'user' bits. - user = expected >> 6 - expected = user * (1 + 8 + 64) - self.assertEqual(mode, expected) - finally: - os.rmdir(dir) - -test_classes.append(test_mkdtemp) - - -class test_mktemp(TC): - """Test mktemp().""" - - # For safety, all use of mktemp must occur in a private directory. - # We must also suppress the RuntimeWarning it generates. - def setUp(self) -> None: - self.dir = tempfile.mkdtemp() - super().setUp() - - def tearDown(self) -> None: - if self.dir: - os.rmdir(self.dir) - self.dir = None - super().tearDown() - - class mktemped: - def _unlink(self, path: str) -> None: - os.unlink(path) - - _bflags = tempfile._bin_openflags - - def __init__(self, dir: str, pre: str, suf: str) -> None: - self.name = tempfile.mktemp(dir=dir, prefix=pre, suffix=suf) - # Create the file. This will raise an exception if it's - # mysteriously appeared in the meanwhile. - os.close(os.open(self.name, self._bflags, 0o600)) - - def __del__(self) -> None: - self._unlink(self.name) - - def do_create(self, pre: str = "", suf: str = "") -> mktemped: - try: - file = test_mktemp.mktemped(self.dir, pre, suf) # see #259 - except: - self.failOnException("mktemp") - - self.nameCheck(file.name, self.dir, pre, suf) - return file - - def test_basic(self) -> None: - # mktemp can choose usable file names - self.do_create() - self.do_create(pre="a") - self.do_create(suf="b") - self.do_create(pre="a", suf="b") - self.do_create(pre="aa", suf=".txt") - - def test_many(self) -> None: - # mktemp can choose many usable file names (stochastic) - extant = list(range(TEST_FILES)) # type: List[Any] - for i in extant: - extant[i] = self.do_create(pre="aa") - -## def test_warning(self): -## # mktemp issues a warning when used -## warnings.filterwarnings("error", -## category=RuntimeWarning, -## message="mktemp") -## self.assertRaises(RuntimeWarning, -## tempfile.mktemp, dir=self.dir) - -test_classes.append(test_mktemp) - - -# We test _TemporaryFileWrapper by testing NamedTemporaryFile. - - -class test_NamedTemporaryFile(TC): - """Test NamedTemporaryFile().""" - - def do_create(self, dir: str = None, pre: str = "", suf: str = "", - delete: bool = True) -> IO[Any]: - if dir is None: - dir = tempfile.gettempdir() - try: - file = tempfile.NamedTemporaryFile(dir=dir, prefix=pre, suffix=suf, - delete=delete) - except: - self.failOnException("NamedTemporaryFile") - - self.nameCheck(file.name, dir, pre, suf) - return file - - - def test_basic(self) -> None: - # NamedTemporaryFile can create files - self.do_create() - self.do_create(pre="a") - self.do_create(suf="b") - self.do_create(pre="a", suf="b") - self.do_create(pre="aa", suf=".txt") - - def test_creates_named(self) -> None: - # NamedTemporaryFile creates files with names - f = tempfile.NamedTemporaryFile() - self.assertTrue(os.path.exists(f.name), - "NamedTemporaryFile %s does not exist" % f.name) - - def test_del_on_close(self) -> None: - # A NamedTemporaryFile is deleted when closed - dir = tempfile.mkdtemp() - try: - f = tempfile.NamedTemporaryFile(dir=dir) - f.write(b'blat') - f.close() - self.assertFalse(os.path.exists(f.name), - "NamedTemporaryFile %s exists after close" % f.name) - finally: - os.rmdir(dir) - - def test_dis_del_on_close(self) -> None: - # Tests that delete-on-close can be disabled - dir = tempfile.mkdtemp() - tmp = None # type: str - try: - f = tempfile.NamedTemporaryFile(dir=dir, delete=False) - tmp = f.name - f.write(b'blat') - f.close() - self.assertTrue(os.path.exists(f.name), - "NamedTemporaryFile %s missing after close" % f.name) - finally: - if tmp is not None: - os.unlink(tmp) - os.rmdir(dir) - - def test_multiple_close(self) -> None: - # A NamedTemporaryFile can be closed many times without error - f = tempfile.NamedTemporaryFile() - f.write(b'abc\n') - f.close() - try: - f.close() - f.close() - except: - self.failOnException("close") - - def test_context_manager(self) -> None: - # A NamedTemporaryFile can be used as a context manager - with tempfile.NamedTemporaryFile() as f: - self.assertTrue(os.path.exists(f.name)) - self.assertFalse(os.path.exists(f.name)) - def use_closed(): - with f: - pass - self.assertRaises(ValueError, use_closed) - - # How to test the mode and bufsize parameters? - -test_classes.append(test_NamedTemporaryFile) - -class test_SpooledTemporaryFile(TC): - """Test SpooledTemporaryFile().""" - - def do_create(self, max_size: int = 0, dir: str = None, pre: str = "", - suf: str = "") -> tempfile.SpooledTemporaryFile: - if dir is None: - dir = tempfile.gettempdir() - try: - file = tempfile.SpooledTemporaryFile(max_size=max_size, dir=dir, prefix=pre, suffix=suf) - except: - self.failOnException("SpooledTemporaryFile") - - return file - - - def test_basic(self) -> None: - # SpooledTemporaryFile can create files - f = self.do_create() - self.assertFalse(f._rolled) - f = self.do_create(max_size=100, pre="a", suf=".txt") - self.assertFalse(f._rolled) - - def test_del_on_close(self) -> None: - # A SpooledTemporaryFile is deleted when closed - dir = tempfile.mkdtemp() - try: - f = tempfile.SpooledTemporaryFile(max_size=10, dir=dir) - self.assertFalse(f._rolled) - f.write(b'blat ' * 5) - self.assertTrue(f._rolled) - filename = f.name - f.close() - self.assertFalse(isinstance(filename, str) and os.path.exists(filename), - "SpooledTemporaryFile %s exists after close" % filename) - finally: - os.rmdir(dir) - - def test_rewrite_small(self) -> None: - # A SpooledTemporaryFile can be written to multiple within the max_size - f = self.do_create(max_size=30) - self.assertFalse(f._rolled) - for i in range(5): - f.seek(0, 0) - f.write(b'x' * 20) - self.assertFalse(f._rolled) - - def test_write_sequential(self) -> None: - # A SpooledTemporaryFile should hold exactly max_size bytes, and roll - # over afterward - f = self.do_create(max_size=30) - self.assertFalse(f._rolled) - f.write(b'x' * 20) - self.assertFalse(f._rolled) - f.write(b'x' * 10) - self.assertFalse(f._rolled) - f.write(b'x') - self.assertTrue(f._rolled) - - def test_writelines(self) -> None: - # Verify writelines with a SpooledTemporaryFile - f = self.do_create() - f.writelines([b'x', b'y', b'z']) - f.seek(0) - buf = f.read() - self.assertEqual(buf, b'xyz') - - def test_writelines_sequential(self) -> None: - # A SpooledTemporaryFile should hold exactly max_size bytes, and roll - # over afterward - f = self.do_create(max_size=35) - f.writelines([b'x' * 20, b'x' * 10, b'x' * 5]) - self.assertFalse(f._rolled) - f.write(b'x') - self.assertTrue(f._rolled) - - def test_sparse(self) -> None: - # A SpooledTemporaryFile that is written late in the file will extend - # when that occurs - f = self.do_create(max_size=30) - self.assertFalse(f._rolled) - f.seek(100, 0) - self.assertFalse(f._rolled) - f.write(b'x') - self.assertTrue(f._rolled) - - def test_fileno(self) -> None: - # A SpooledTemporaryFile should roll over to a real file on fileno() - f = self.do_create(max_size=30) - self.assertFalse(f._rolled) - self.assertTrue(f.fileno() > 0) - self.assertTrue(f._rolled) - - def test_multiple_close_before_rollover(self) -> None: - # A SpooledTemporaryFile can be closed many times without error - f = tempfile.SpooledTemporaryFile() - f.write(b'abc\n') - self.assertFalse(f._rolled) - f.close() - try: - f.close() - f.close() - except: - self.failOnException("close") - - def test_multiple_close_after_rollover(self) -> None: - # A SpooledTemporaryFile can be closed many times without error - f = tempfile.SpooledTemporaryFile(max_size=1) - f.write(b'abc\n') - self.assertTrue(f._rolled) - f.close() - try: - f.close() - f.close() - except: - self.failOnException("close") - - def test_bound_methods(self) -> None: - # It should be OK to steal a bound method from a SpooledTemporaryFile - # and use it independently; when the file rolls over, those bound - # methods should continue to function - f = self.do_create(max_size=30) - read = f.read - write = f.write - seek = f.seek - - write(b"a" * 35) - write(b"b" * 35) - seek(0, 0) - self.assertEqual(read(70), b'a'*35 + b'b'*35) - - def test_text_mode(self) -> None: - # Creating a SpooledTemporaryFile with a text mode should produce - # a file object reading and writing (Unicode) text strings. - f = tempfile.SpooledTemporaryFile(mode='w+', max_size=10) - f.write("abc\n") - f.seek(0) - self.assertEqual(f.read(), "abc\n") - f.write("def\n") - f.seek(0) - self.assertEqual(f.read(), "abc\ndef\n") - f.write("xyzzy\n") - f.seek(0) - self.assertEqual(f.read(), "abc\ndef\nxyzzy\n") - # Check that Ctrl+Z doesn't truncate the file - f.write("foo\x1abar\n") - f.seek(0) - self.assertEqual(f.read(), "abc\ndef\nxyzzy\nfoo\x1abar\n") - - def test_text_newline_and_encoding(self) -> None: - f = tempfile.SpooledTemporaryFile(mode='w+', max_size=10, - newline='', encoding='utf-8') - f.write("\u039B\r\n") - f.seek(0) - self.assertEqual(f.read(), "\u039B\r\n") - self.assertFalse(f._rolled) - - f.write("\u039B" * 20 + "\r\n") - f.seek(0) - self.assertEqual(f.read(), "\u039B\r\n" + ("\u039B" * 20) + "\r\n") - self.assertTrue(f._rolled) - - def test_context_manager_before_rollover(self) -> None: - # A SpooledTemporaryFile can be used as a context manager - with tempfile.SpooledTemporaryFile(max_size=1) as f: - self.assertFalse(f._rolled) - self.assertFalse(f.closed) - self.assertTrue(f.closed) - def use_closed(): - with f: - pass - self.assertRaises(ValueError, use_closed) - - def test_context_manager_during_rollover(self) -> None: - # A SpooledTemporaryFile can be used as a context manager - with tempfile.SpooledTemporaryFile(max_size=1) as f: - self.assertFalse(f._rolled) - f.write(b'abc\n') - f.flush() - self.assertTrue(f._rolled) - self.assertFalse(f.closed) - self.assertTrue(f.closed) - def use_closed(): - with f: - pass - self.assertRaises(ValueError, use_closed) - - def test_context_manager_after_rollover(self) -> None: - # A SpooledTemporaryFile can be used as a context manager - f = tempfile.SpooledTemporaryFile(max_size=1) - f.write(b'abc\n') - f.flush() - self.assertTrue(f._rolled) - with f: - self.assertFalse(f.closed) - self.assertTrue(f.closed) - def use_closed(): - with f: - pass - self.assertRaises(ValueError, use_closed) - - -test_classes.append(test_SpooledTemporaryFile) - - -class test_TemporaryFile(TC): - """Test TemporaryFile().""" - - def test_basic(self) -> None: - # TemporaryFile can create files - # No point in testing the name params - the file has no name. - try: - tempfile.TemporaryFile() - except: - self.failOnException("TemporaryFile") - - def test_has_no_name(self) -> None: - # TemporaryFile creates files with no names (on this system) - dir = tempfile.mkdtemp() - f = tempfile.TemporaryFile(dir=dir) - f.write(b'blat') - - # Sneaky: because this file has no name, it should not prevent - # us from removing the directory it was created in. - try: - os.rmdir(dir) - except: - ei = sys.exc_info() - # cleanup - f.close() - os.rmdir(dir) - self.failOnException("rmdir", ei) - - def test_multiple_close(self) -> None: - # A TemporaryFile can be closed many times without error - f = tempfile.TemporaryFile() - f.write(b'abc\n') - f.close() - try: - f.close() - f.close() - except: - self.failOnException("close") - - # How to test the mode and bufsize parameters? - def test_mode_and_encoding(self) -> None: - - def roundtrip(input: AnyStr, *args: Any, **kwargs: Any) -> None: - with tempfile.TemporaryFile(*args, **kwargs) as fileobj: - fileobj.write(input) - fileobj.seek(0) - self.assertEqual(input, fileobj.read()) - - roundtrip(b"1234", "w+b") - roundtrip("abdc\n", "w+") - roundtrip("\u039B", "w+", encoding="utf-16") - roundtrip("foo\r\n", "w+", newline="") - - -if tempfile.NamedTemporaryFile is not tempfile.TemporaryFile: - test_classes.append(test_TemporaryFile) - - -# Helper for test_del_on_shutdown -class NulledModules: - def __init__(self, *modules: Any) -> None: - self.refs = [mod.__dict__ for mod in modules] - self.contents = [ref.copy() for ref in self.refs] - - def __enter__(self) -> None: - for d in self.refs: - for key in d: - d[key] = None - - def __exit__(self, *exc_info: Any) -> None: - for d, c in zip(self.refs, self.contents): - d.clear() - d.update(c) - -class test_TemporaryDirectory(TC): - """Test TemporaryDirectory().""" - - def do_create(self, dir: str = None, pre: str = "", suf: str = "", - recurse: int = 1) -> tempfile.TemporaryDirectory: - if dir is None: - dir = tempfile.gettempdir() - try: - tmp = tempfile.TemporaryDirectory(dir=dir, prefix=pre, suffix=suf) - except: - self.failOnException("TemporaryDirectory") - self.nameCheck(tmp.name, dir, pre, suf) - # Create a subdirectory and some files - if recurse: - self.do_create(tmp.name, pre, suf, recurse-1) - with open(os.path.join(tmp.name, "test.txt"), "wb") as f: - f.write(b"Hello world!") - return tmp - - def test_mkdtemp_failure(self) -> None: - # Check no additional exception if mkdtemp fails - # Previously would raise AttributeError instead - # (noted as part of Issue #10188) - with tempfile.TemporaryDirectory() as nonexistent: - pass - with self.assertRaises(os.error): - tempfile.TemporaryDirectory(dir=nonexistent) - - def test_explicit_cleanup(self) -> None: - # A TemporaryDirectory is deleted when cleaned up - dir = tempfile.mkdtemp() - try: - d = self.do_create(dir=dir) - self.assertTrue(os.path.exists(d.name), - "TemporaryDirectory %s does not exist" % d.name) - d.cleanup() - self.assertFalse(os.path.exists(d.name), - "TemporaryDirectory %s exists after cleanup" % d.name) - finally: - os.rmdir(dir) - - @support.skip_unless_symlink - def test_cleanup_with_symlink_to_a_directory(self) -> None: - # cleanup() should not follow symlinks to directories (issue #12464) - d1 = self.do_create() - d2 = self.do_create() - - # Symlink d1/foo -> d2 - os.symlink(d2.name, os.path.join(d1.name, "foo")) - - # This call to cleanup() should not follow the "foo" symlink - d1.cleanup() - - self.assertFalse(os.path.exists(d1.name), - "TemporaryDirectory %s exists after cleanup" % d1.name) - self.assertTrue(os.path.exists(d2.name), - "Directory pointed to by a symlink was deleted") - self.assertEqual(os.listdir(d2.name), ['test.txt'], - "Contents of the directory pointed to by a symlink " - "were deleted") - d2.cleanup() - - @support.cpython_only - def test_del_on_collection(self) -> None: - # A TemporaryDirectory is deleted when garbage collected - dir = tempfile.mkdtemp() - try: - d = self.do_create(dir=dir) - name = d.name - del d # Rely on refcounting to invoke __del__ - self.assertFalse(os.path.exists(name), - "TemporaryDirectory %s exists after __del__" % name) - finally: - os.rmdir(dir) - - @unittest.expectedFailure # See issue #10188 - def test_del_on_shutdown(self) -> None: - # A TemporaryDirectory may be cleaned up during shutdown - # Make sure it works with the relevant modules nulled out - with self.do_create() as dir: - d = self.do_create(dir=dir) - # Mimic the nulling out of modules that - # occurs during system shutdown - modules = [os, os.path] - if has_stat: - modules.append(stat) - # Currently broken, so suppress the warning - # that is otherwise emitted on stdout - with support.captured_stderr() as err: - with NulledModules(*modules): - d.cleanup() - # Currently broken, so stop spurious exception by - # indicating the object has already been closed - d._closed = True - # And this assert will fail, as expected by the - # unittest decorator... - self.assertFalse(os.path.exists(d.name), - "TemporaryDirectory %s exists after cleanup" % d.name) - - def test_warnings_on_cleanup(self) -> None: - # Two kinds of warning on shutdown - # Issue 10888: may write to stderr if modules are nulled out - # ResourceWarning will be triggered by __del__ - with self.do_create() as dir: - if os.sep != '\\': - # Embed a backslash in order to make sure string escaping - # in the displayed error message is dealt with correctly - suffix = '\\check_backslash_handling' - else: - suffix = '' - d = self.do_create(dir=dir, suf=suffix) - - #Check for the Issue 10888 message - modules = [os, os.path] - if has_stat: - modules.append(stat) - with support.captured_stderr() as err: - with NulledModules(*modules): - d.cleanup() - message = err.getvalue().replace('\\\\', '\\') - self.assertIn("while cleaning up", message) - self.assertIn(d.name, message) - - # Check for the resource warning - with support.check_warnings(('Implicitly', ResourceWarning), quiet=False): - warnings.filterwarnings("always", category=ResourceWarning) - d.__del__() - self.assertFalse(os.path.exists(d.name), - "TemporaryDirectory %s exists after __del__" % d.name) - - def test_multiple_close(self) -> None: - # Can be cleaned-up many times without error - d = self.do_create() - d.cleanup() - try: - d.cleanup() - d.cleanup() - except: - self.failOnException("cleanup") - - def test_context_manager(self) -> None: - # Can be used as a context manager - d = self.do_create() - with d as name: - self.assertTrue(os.path.exists(name)) - self.assertEqual(name, d.name) - self.assertFalse(os.path.exists(name)) - - -test_classes.append(test_TemporaryDirectory) - -def test_main() -> None: - support.run_unittest(*test_classes) - -if __name__ == "__main__": - test_main() diff --git a/test-data/stdlib-samples/3.2/test/test_textwrap.py b/test-data/stdlib-samples/3.2/test/test_textwrap.py deleted file mode 100644 index 79d921a583e67..0000000000000 --- a/test-data/stdlib-samples/3.2/test/test_textwrap.py +++ /dev/null @@ -1,601 +0,0 @@ -# -# Test suite for the textwrap module. -# -# Original tests written by Greg Ward . -# Converted to PyUnit by Peter Hansen . -# Currently maintained by Greg Ward. -# -# $Id$ -# - -import unittest -from test import support - -from typing import Any, List, Sequence - -from textwrap import TextWrapper, wrap, fill, dedent - - -class BaseTestCase(unittest.TestCase): - '''Parent class with utility methods for textwrap tests.''' - - wrapper = None # type: TextWrapper - - def show(self, textin: Sequence[str]) -> str: - if isinstance(textin, list): - results = [] # type: List[str] - for i in range(len(textin)): - results.append(" %d: %r" % (i, textin[i])) - result = '\n'.join(results) - elif isinstance(textin, str): - result = " %s\n" % repr(textin) - return result - - - def check(self, result: Sequence[str], expect: Sequence[str]) -> None: - self.assertEqual(result, expect, - 'expected:\n%s\nbut got:\n%s' % ( - self.show(expect), self.show(result))) - - def check_wrap(self, text: str, width: int, expect: Sequence[str], - **kwargs: Any) -> None: - result = wrap(text, width, **kwargs) - self.check(result, expect) - - def check_split(self, text: str, expect: Sequence[str]) -> None: - result = self.wrapper._split(text) - self.assertEqual(result, expect, - "\nexpected %r\n" - "but got %r" % (expect, result)) - - -class WrapTestCase(BaseTestCase): - - def setUp(self) -> None: - self.wrapper = TextWrapper(width=45) - - def test_simple(self) -> None: - # Simple case: just words, spaces, and a bit of punctuation - - text = "Hello there, how are you this fine day? I'm glad to hear it!" - - self.check_wrap(text, 12, - ["Hello there,", - "how are you", - "this fine", - "day? I'm", - "glad to hear", - "it!"]) - self.check_wrap(text, 42, - ["Hello there, how are you this fine day?", - "I'm glad to hear it!"]) - self.check_wrap(text, 80, [text]) - - - def test_whitespace(self) -> None: - # Whitespace munging and end-of-sentence detection - - text = """\ -This is a paragraph that already has -line breaks. But some of its lines are much longer than the others, -so it needs to be wrapped. -Some lines are \ttabbed too. -What a mess! -""" - - expect = ["This is a paragraph that already has line", - "breaks. But some of its lines are much", - "longer than the others, so it needs to be", - "wrapped. Some lines are tabbed too. What a", - "mess!"] - - wrapper = TextWrapper(45, fix_sentence_endings=True) - result = wrapper.wrap(text) - self.check(result, expect) - - results = wrapper.fill(text) - self.check(results, '\n'.join(expect)) - - def test_fix_sentence_endings(self) -> None: - wrapper = TextWrapper(60, fix_sentence_endings=True) - - # SF #847346: ensure that fix_sentence_endings=True does the - # right thing even on input short enough that it doesn't need to - # be wrapped. - text = "A short line. Note the single space." - expect = ["A short line. Note the single space."] - self.check(wrapper.wrap(text), expect) - - # Test some of the hairy end cases that _fix_sentence_endings() - # is supposed to handle (the easy stuff is tested in - # test_whitespace() above). - text = "Well, Doctor? What do you think?" - expect = ["Well, Doctor? What do you think?"] - self.check(wrapper.wrap(text), expect) - - text = "Well, Doctor?\nWhat do you think?" - self.check(wrapper.wrap(text), expect) - - text = 'I say, chaps! Anyone for "tennis?"\nHmmph!' - expect = ['I say, chaps! Anyone for "tennis?" Hmmph!'] - self.check(wrapper.wrap(text), expect) - - wrapper.width = 20 - expect = ['I say, chaps!', 'Anyone for "tennis?"', 'Hmmph!'] - self.check(wrapper.wrap(text), expect) - - text = 'And she said, "Go to hell!"\nCan you believe that?' - expect = ['And she said, "Go to', - 'hell!" Can you', - 'believe that?'] - self.check(wrapper.wrap(text), expect) - - wrapper.width = 60 - expect = ['And she said, "Go to hell!" Can you believe that?'] - self.check(wrapper.wrap(text), expect) - - text = 'File stdio.h is nice.' - expect = ['File stdio.h is nice.'] - self.check(wrapper.wrap(text), expect) - - def test_wrap_short(self) -> None: - # Wrapping to make short lines longer - - text = "This is a\nshort paragraph." - - self.check_wrap(text, 20, ["This is a short", - "paragraph."]) - self.check_wrap(text, 40, ["This is a short paragraph."]) - - - def test_wrap_short_1line(self) -> None: - # Test endcases - - text = "This is a short line." - - self.check_wrap(text, 30, ["This is a short line."]) - self.check_wrap(text, 30, ["(1) This is a short line."], - initial_indent="(1) ") - - - def test_hyphenated(self) -> None: - # Test breaking hyphenated words - - text = ("this-is-a-useful-feature-for-" - "reformatting-posts-from-tim-peters'ly") - - self.check_wrap(text, 40, - ["this-is-a-useful-feature-for-", - "reformatting-posts-from-tim-peters'ly"]) - self.check_wrap(text, 41, - ["this-is-a-useful-feature-for-", - "reformatting-posts-from-tim-peters'ly"]) - self.check_wrap(text, 42, - ["this-is-a-useful-feature-for-reformatting-", - "posts-from-tim-peters'ly"]) - - def test_hyphenated_numbers(self) -> None: - # Test that hyphenated numbers (eg. dates) are not broken like words. - text = ("Python 1.0.0 was released on 1994-01-26. Python 1.0.1 was\n" - "released on 1994-02-15.") - - self.check_wrap(text, 30, ['Python 1.0.0 was released on', - '1994-01-26. Python 1.0.1 was', - 'released on 1994-02-15.']) - self.check_wrap(text, 40, ['Python 1.0.0 was released on 1994-01-26.', - 'Python 1.0.1 was released on 1994-02-15.']) - - text = "I do all my shopping at 7-11." - self.check_wrap(text, 25, ["I do all my shopping at", - "7-11."]) - self.check_wrap(text, 27, ["I do all my shopping at", - "7-11."]) - self.check_wrap(text, 29, ["I do all my shopping at 7-11."]) - - def test_em_dash(self) -> None: - # Test text with em-dashes - text = "Em-dashes should be written -- thus." - self.check_wrap(text, 25, - ["Em-dashes should be", - "written -- thus."]) - - # Probe the boundaries of the properly written em-dash, - # ie. " -- ". - self.check_wrap(text, 29, - ["Em-dashes should be written", - "-- thus."]) - expect = ["Em-dashes should be written --", - "thus."] - self.check_wrap(text, 30, expect) - self.check_wrap(text, 35, expect) - self.check_wrap(text, 36, - ["Em-dashes should be written -- thus."]) - - # The improperly written em-dash is handled too, because - # it's adjacent to non-whitespace on both sides. - text = "You can also do--this or even---this." - expect = ["You can also do", - "--this or even", - "---this."] - self.check_wrap(text, 15, expect) - self.check_wrap(text, 16, expect) - expect = ["You can also do--", - "this or even---", - "this."] - self.check_wrap(text, 17, expect) - self.check_wrap(text, 19, expect) - expect = ["You can also do--this or even", - "---this."] - self.check_wrap(text, 29, expect) - self.check_wrap(text, 31, expect) - expect = ["You can also do--this or even---", - "this."] - self.check_wrap(text, 32, expect) - self.check_wrap(text, 35, expect) - - # All of the above behaviour could be deduced by probing the - # _split() method. - text = "Here's an -- em-dash and--here's another---and another!" - expect = ["Here's", " ", "an", " ", "--", " ", "em-", "dash", " ", - "and", "--", "here's", " ", "another", "---", - "and", " ", "another!"] - self.check_split(text, expect) - - text = "and then--bam!--he was gone" - expect = ["and", " ", "then", "--", "bam!", "--", - "he", " ", "was", " ", "gone"] - self.check_split(text, expect) - - - def test_unix_options (self) -> None: - # Test that Unix-style command-line options are wrapped correctly. - # Both Optik (OptionParser) and Docutils rely on this behaviour! - - text = "You should use the -n option, or --dry-run in its long form." - self.check_wrap(text, 20, - ["You should use the", - "-n option, or --dry-", - "run in its long", - "form."]) - self.check_wrap(text, 21, - ["You should use the -n", - "option, or --dry-run", - "in its long form."]) - expect = ["You should use the -n option, or", - "--dry-run in its long form."] - self.check_wrap(text, 32, expect) - self.check_wrap(text, 34, expect) - self.check_wrap(text, 35, expect) - self.check_wrap(text, 38, expect) - expect = ["You should use the -n option, or --dry-", - "run in its long form."] - self.check_wrap(text, 39, expect) - self.check_wrap(text, 41, expect) - expect = ["You should use the -n option, or --dry-run", - "in its long form."] - self.check_wrap(text, 42, expect) - - # Again, all of the above can be deduced from _split(). - text = "the -n option, or --dry-run or --dryrun" - expect = ["the", " ", "-n", " ", "option,", " ", "or", " ", - "--dry-", "run", " ", "or", " ", "--dryrun"] - self.check_split(text, expect) - - def test_funky_hyphens (self) -> None: - # Screwy edge cases cooked up by David Goodger. All reported - # in SF bug #596434. - self.check_split("what the--hey!", ["what", " ", "the", "--", "hey!"]) - self.check_split("what the--", ["what", " ", "the--"]) - self.check_split("what the--.", ["what", " ", "the--."]) - self.check_split("--text--.", ["--text--."]) - - # When I first read bug #596434, this is what I thought David - # was talking about. I was wrong; these have always worked - # fine. The real problem is tested in test_funky_parens() - # below... - self.check_split("--option", ["--option"]) - self.check_split("--option-opt", ["--option-", "opt"]) - self.check_split("foo --option-opt bar", - ["foo", " ", "--option-", "opt", " ", "bar"]) - - def test_punct_hyphens(self) -> None: - # Oh bother, SF #965425 found another problem with hyphens -- - # hyphenated words in single quotes weren't handled correctly. - # In fact, the bug is that *any* punctuation around a hyphenated - # word was handled incorrectly, except for a leading "--", which - # was special-cased for Optik and Docutils. So test a variety - # of styles of punctuation around a hyphenated word. - # (Actually this is based on an Optik bug report, #813077). - self.check_split("the 'wibble-wobble' widget", - ['the', ' ', "'wibble-", "wobble'", ' ', 'widget']) - self.check_split('the "wibble-wobble" widget', - ['the', ' ', '"wibble-', 'wobble"', ' ', 'widget']) - self.check_split("the (wibble-wobble) widget", - ['the', ' ', "(wibble-", "wobble)", ' ', 'widget']) - self.check_split("the ['wibble-wobble'] widget", - ['the', ' ', "['wibble-", "wobble']", ' ', 'widget']) - - def test_funky_parens (self) -> None: - # Second part of SF bug #596434: long option strings inside - # parentheses. - self.check_split("foo (--option) bar", - ["foo", " ", "(--option)", " ", "bar"]) - - # Related stuff -- make sure parens work in simpler contexts. - self.check_split("foo (bar) baz", - ["foo", " ", "(bar)", " ", "baz"]) - self.check_split("blah (ding dong), wubba", - ["blah", " ", "(ding", " ", "dong),", - " ", "wubba"]) - - def test_initial_whitespace(self) -> None: - # SF bug #622849 reported inconsistent handling of leading - # whitespace; let's test that a bit, shall we? - text = " This is a sentence with leading whitespace." - self.check_wrap(text, 50, - [" This is a sentence with leading whitespace."]) - self.check_wrap(text, 30, - [" This is a sentence with", "leading whitespace."]) - - def test_no_drop_whitespace(self) -> None: - # SF patch #1581073 - text = " This is a sentence with much whitespace." - self.check_wrap(text, 10, - [" This is a", " ", "sentence ", - "with ", "much white", "space."], - drop_whitespace=False) - - def test_split(self) -> None: - # Ensure that the standard _split() method works as advertised - # in the comments - - text = "Hello there -- you goof-ball, use the -b option!" - - result = self.wrapper._split(text) - self.check(result, - ["Hello", " ", "there", " ", "--", " ", "you", " ", "goof-", - "ball,", " ", "use", " ", "the", " ", "-b", " ", "option!"]) - - def test_break_on_hyphens(self) -> None: - # Ensure that the break_on_hyphens attributes work - text = "yaba daba-doo" - self.check_wrap(text, 10, ["yaba daba-", "doo"], - break_on_hyphens=True) - self.check_wrap(text, 10, ["yaba", "daba-doo"], - break_on_hyphens=False) - - def test_bad_width(self) -> None: - # Ensure that width <= 0 is caught. - text = "Whatever, it doesn't matter." - self.assertRaises(ValueError, wrap, text, 0) - self.assertRaises(ValueError, wrap, text, -1) - - def test_no_split_at_umlaut(self) -> None: - text = "Die Empf\xe4nger-Auswahl" - self.check_wrap(text, 13, ["Die", "Empf\xe4nger-", "Auswahl"]) - - def test_umlaut_followed_by_dash(self) -> None: - text = "aa \xe4\xe4-\xe4\xe4" - self.check_wrap(text, 7, ["aa \xe4\xe4-", "\xe4\xe4"]) - - -class LongWordTestCase (BaseTestCase): - def setUp(self) -> None: - self.wrapper = TextWrapper() - self.text = '''\ -Did you say "supercalifragilisticexpialidocious?" -How *do* you spell that odd word, anyways? -''' - - def test_break_long(self) -> None: - # Wrap text with long words and lots of punctuation - - self.check_wrap(self.text, 30, - ['Did you say "supercalifragilis', - 'ticexpialidocious?" How *do*', - 'you spell that odd word,', - 'anyways?']) - self.check_wrap(self.text, 50, - ['Did you say "supercalifragilisticexpialidocious?"', - 'How *do* you spell that odd word, anyways?']) - - # SF bug 797650. Prevent an infinite loop by making sure that at - # least one character gets split off on every pass. - self.check_wrap('-'*10+'hello', 10, - ['----------', - ' h', - ' e', - ' l', - ' l', - ' o'], - subsequent_indent = ' '*15) - - # bug 1146. Prevent a long word to be wrongly wrapped when the - # preceding word is exactly one character shorter than the width - self.check_wrap(self.text, 12, - ['Did you say ', - '"supercalifr', - 'agilisticexp', - 'ialidocious?', - '" How *do*', - 'you spell', - 'that odd', - 'word,', - 'anyways?']) - - def test_nobreak_long(self) -> None: - # Test with break_long_words disabled - self.wrapper.break_long_words = False - self.wrapper.width = 30 - expect = ['Did you say', - '"supercalifragilisticexpialidocious?"', - 'How *do* you spell that odd', - 'word, anyways?' - ] - result = self.wrapper.wrap(self.text) - self.check(result, expect) - - # Same thing with kwargs passed to standalone wrap() function. - result = wrap(self.text, width=30, break_long_words=0) - self.check(result, expect) - - -class IndentTestCases(BaseTestCase): - - # called before each test method - def setUp(self) -> None: - self.text = '''\ -This paragraph will be filled, first without any indentation, -and then with some (including a hanging indent).''' - - - def test_fill(self) -> None: - # Test the fill() method - - expect = '''\ -This paragraph will be filled, first -without any indentation, and then with -some (including a hanging indent).''' - - result = fill(self.text, 40) - self.check(result, expect) - - - def test_initial_indent(self) -> None: - # Test initial_indent parameter - - expect = [" This paragraph will be filled,", - "first without any indentation, and then", - "with some (including a hanging indent)."] - result = wrap(self.text, 40, initial_indent=" ") - self.check(result, expect) - - expects = "\n".join(expect) - results = fill(self.text, 40, initial_indent=" ") - self.check(results, expects) - - - def test_subsequent_indent(self) -> None: - # Test subsequent_indent parameter - - expect = '''\ - * This paragraph will be filled, first - without any indentation, and then - with some (including a hanging - indent).''' - - result = fill(self.text, 40, - initial_indent=" * ", subsequent_indent=" ") - self.check(result, expect) - - -# Despite the similar names, DedentTestCase is *not* the inverse -# of IndentTestCase! -class DedentTestCase(unittest.TestCase): - - def assertUnchanged(self, text: str) -> None: - """assert that dedent() has no effect on 'text'""" - self.assertEqual(text, dedent(text)) - - def test_dedent_nomargin(self) -> None: - # No lines indented. - text = "Hello there.\nHow are you?\nOh good, I'm glad." - self.assertUnchanged(text) - - # Similar, with a blank line. - text = "Hello there.\n\nBoo!" - self.assertUnchanged(text) - - # Some lines indented, but overall margin is still zero. - text = "Hello there.\n This is indented." - self.assertUnchanged(text) - - # Again, add a blank line. - text = "Hello there.\n\n Boo!\n" - self.assertUnchanged(text) - - def test_dedent_even(self) -> None: - # All lines indented by two spaces. - text = " Hello there.\n How are ya?\n Oh good." - expect = "Hello there.\nHow are ya?\nOh good." - self.assertEqual(expect, dedent(text)) - - # Same, with blank lines. - text = " Hello there.\n\n How are ya?\n Oh good.\n" - expect = "Hello there.\n\nHow are ya?\nOh good.\n" - self.assertEqual(expect, dedent(text)) - - # Now indent one of the blank lines. - text = " Hello there.\n \n How are ya?\n Oh good.\n" - expect = "Hello there.\n\nHow are ya?\nOh good.\n" - self.assertEqual(expect, dedent(text)) - - def test_dedent_uneven(self) -> None: - # Lines indented unevenly. - text = '''\ - def foo(): - while 1: - return foo - ''' - expect = '''\ -def foo(): - while 1: - return foo -''' - self.assertEqual(expect, dedent(text)) - - # Uneven indentation with a blank line. - text = " Foo\n Bar\n\n Baz\n" - expect = "Foo\n Bar\n\n Baz\n" - self.assertEqual(expect, dedent(text)) - - # Uneven indentation with a whitespace-only line. - text = " Foo\n Bar\n \n Baz\n" - expect = "Foo\n Bar\n\n Baz\n" - self.assertEqual(expect, dedent(text)) - - # dedent() should not mangle internal tabs - def test_dedent_preserve_internal_tabs(self) -> None: - text = " hello\tthere\n how are\tyou?" - expect = "hello\tthere\nhow are\tyou?" - self.assertEqual(expect, dedent(text)) - - # make sure that it preserves tabs when it's not making any - # changes at all - self.assertEqual(expect, dedent(expect)) - - # dedent() should not mangle tabs in the margin (i.e. - # tabs and spaces both count as margin, but are *not* - # considered equivalent) - def test_dedent_preserve_margin_tabs(self) -> None: - text = " hello there\n\thow are you?" - self.assertUnchanged(text) - - # same effect even if we have 8 spaces - text = " hello there\n\thow are you?" - self.assertUnchanged(text) - - # dedent() only removes whitespace that can be uniformly removed! - text = "\thello there\n\thow are you?" - expect = "hello there\nhow are you?" - self.assertEqual(expect, dedent(text)) - - text = " \thello there\n \thow are you?" - self.assertEqual(expect, dedent(text)) - - text = " \t hello there\n \t how are you?" - self.assertEqual(expect, dedent(text)) - - text = " \thello there\n \t how are you?" - expect = "hello there\n how are you?" - self.assertEqual(expect, dedent(text)) - - -def test_main() -> None: - support.run_unittest(WrapTestCase, - LongWordTestCase, - IndentTestCases, - DedentTestCase) - -if __name__ == '__main__': - test_main() diff --git a/test-data/stdlib-samples/3.2/test/tf_inherit_check.py b/test-data/stdlib-samples/3.2/test/tf_inherit_check.py deleted file mode 100644 index 92ebd95e52368..0000000000000 --- a/test-data/stdlib-samples/3.2/test/tf_inherit_check.py +++ /dev/null @@ -1,25 +0,0 @@ -# Helper script for test_tempfile.py. argv[2] is the number of a file -# descriptor which should _not_ be open. Check this by attempting to -# write to it -- if we succeed, something is wrong. - -import sys -import os - -verbose = (sys.argv[1] == 'v') -try: - fd = int(sys.argv[2]) - - try: - os.write(fd, b"blat") - except os.error: - # Success -- could not write to fd. - sys.exit(0) - else: - if verbose: - sys.stderr.write("fd %d is open in child" % fd) - sys.exit(1) - -except Exception: - if verbose: - raise - sys.exit(1) diff --git a/test-data/stdlib-samples/3.2/textwrap.py b/test-data/stdlib-samples/3.2/textwrap.py deleted file mode 100644 index a6d026699704b..0000000000000 --- a/test-data/stdlib-samples/3.2/textwrap.py +++ /dev/null @@ -1,391 +0,0 @@ -"""Text wrapping and filling. -""" - -# Copyright (C) 1999-2001 Gregory P. Ward. -# Copyright (C) 2002, 2003 Python Software Foundation. -# Written by Greg Ward - -import string, re - -from typing import Dict, List, Any - -__all__ = ['TextWrapper', 'wrap', 'fill', 'dedent'] - -# Hardcode the recognized whitespace characters to the US-ASCII -# whitespace characters. The main reason for doing this is that in -# ISO-8859-1, 0xa0 is non-breaking whitespace, so in certain locales -# that character winds up in string.whitespace. Respecting -# string.whitespace in those cases would 1) make textwrap treat 0xa0 the -# same as any other whitespace char, which is clearly wrong (it's a -# *non-breaking* space), 2) possibly cause problems with Unicode, -# since 0xa0 is not in range(128). -_whitespace = '\t\n\x0b\x0c\r ' - -class TextWrapper: - """ - Object for wrapping/filling text. The public interface consists of - the wrap() and fill() methods; the other methods are just there for - subclasses to override in order to tweak the default behaviour. - If you want to completely replace the main wrapping algorithm, - you'll probably have to override _wrap_chunks(). - - Several instance attributes control various aspects of wrapping: - width (default: 70) - the maximum width of wrapped lines (unless break_long_words - is false) - initial_indent (default: "") - string that will be prepended to the first line of wrapped - output. Counts towards the line's width. - subsequent_indent (default: "") - string that will be prepended to all lines save the first - of wrapped output; also counts towards each line's width. - expand_tabs (default: true) - Expand tabs in input text to spaces before further processing. - Each tab will become 1 .. 8 spaces, depending on its position in - its line. If false, each tab is treated as a single character. - replace_whitespace (default: true) - Replace all whitespace characters in the input text by spaces - after tab expansion. Note that if expand_tabs is false and - replace_whitespace is true, every tab will be converted to a - single space! - fix_sentence_endings (default: false) - Ensure that sentence-ending punctuation is always followed - by two spaces. Off by default because the algorithm is - (unavoidably) imperfect. - break_long_words (default: true) - Break words longer than 'width'. If false, those words will not - be broken, and some lines might be longer than 'width'. - break_on_hyphens (default: true) - Allow breaking hyphenated words. If true, wrapping will occur - preferably on whitespaces and right after hyphens part of - compound words. - drop_whitespace (default: true) - Drop leading and trailing whitespace from lines. - """ - - unicode_whitespace_trans = {} # type: Dict[int, int] - uspace = ord(' ') - for x in _whitespace: - unicode_whitespace_trans[ord(x)] = uspace - - # This funky little regex is just the trick for splitting - # text up into word-wrappable chunks. E.g. - # "Hello there -- you goof-ball, use the -b option!" - # splits into - # Hello/ /there/ /--/ /you/ /goof-/ball,/ /use/ /the/ /-b/ /option! - # (after stripping out empty strings). - wordsep_re = re.compile( - r'(\s+|' # any whitespace - r'[^\s\w]*\w+[^0-9\W]-(?=\w+[^0-9\W])|' # hyphenated words - r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))') # em-dash - - # This less funky little regex just split on recognized spaces. E.g. - # "Hello there -- you goof-ball, use the -b option!" - # splits into - # Hello/ /there/ /--/ /you/ /goof-ball,/ /use/ /the/ /-b/ /option!/ - wordsep_simple_re = re.compile(r'(\s+)') - - # XXX this is not locale- or charset-aware -- string.lowercase - # is US-ASCII only (and therefore English-only) - sentence_end_re = re.compile(r'[a-z]' # lowercase letter - r'[\.\!\?]' # sentence-ending punct. - r'[\"\']?' # optional end-of-quote - r'\Z') # end of chunk - - - def __init__(self, - width: int = 70, - initial_indent: str = "", - subsequent_indent: str = "", - expand_tabs: bool = True, - replace_whitespace: bool = True, - fix_sentence_endings: bool = False, - break_long_words: bool = True, - drop_whitespace: bool = True, - break_on_hyphens: bool = True) -> None: - self.width = width - self.initial_indent = initial_indent - self.subsequent_indent = subsequent_indent - self.expand_tabs = expand_tabs - self.replace_whitespace = replace_whitespace - self.fix_sentence_endings = fix_sentence_endings - self.break_long_words = break_long_words - self.drop_whitespace = drop_whitespace - self.break_on_hyphens = break_on_hyphens - - - # -- Private methods ----------------------------------------------- - # (possibly useful for subclasses to override) - - def _munge_whitespace(self, text: str) -> str: - """_munge_whitespace(text : string) -> string - - Munge whitespace in text: expand tabs and convert all other - whitespace characters to spaces. Eg. " foo\tbar\n\nbaz" - becomes " foo bar baz". - """ - if self.expand_tabs: - text = text.expandtabs() - if self.replace_whitespace: - text = text.translate(self.unicode_whitespace_trans) - return text - - - def _split(self, text: str) -> List[str]: - """_split(text : string) -> [string] - - Split the text to wrap into indivisible chunks. Chunks are - not quite the same as words; see _wrap_chunks() for full - details. As an example, the text - Look, goof-ball -- use the -b option! - breaks into the following chunks: - 'Look,', ' ', 'goof-', 'ball', ' ', '--', ' ', - 'use', ' ', 'the', ' ', '-b', ' ', 'option!' - if break_on_hyphens is True, or in: - 'Look,', ' ', 'goof-ball', ' ', '--', ' ', - 'use', ' ', 'the', ' ', '-b', ' ', option!' - otherwise. - """ - if self.break_on_hyphens is True: - chunks = self.wordsep_re.split(text) - else: - chunks = self.wordsep_simple_re.split(text) - chunks = [c for c in chunks if c] - return chunks - - def _fix_sentence_endings(self, chunks: List[str]) -> None: - """_fix_sentence_endings(chunks : [string]) - - Correct for sentence endings buried in 'chunks'. Eg. when the - original text contains "... foo.\nBar ...", munge_whitespace() - and split() will convert that to [..., "foo.", " ", "Bar", ...] - which has one too few spaces; this method simply changes the one - space to two. - """ - i = 0 - patsearch = self.sentence_end_re.search - while i < len(chunks)-1: - if chunks[i+1] == " " and patsearch(chunks[i]): - chunks[i+1] = " " - i += 2 - else: - i += 1 - - def _handle_long_word(self, reversed_chunks: List[str], - cur_line: List[str], cur_len: int, - width: int) -> None: - """_handle_long_word(chunks : [string], - cur_line : [string], - cur_len : int, width : int) - - Handle a chunk of text (most likely a word, not whitespace) that - is too long to fit in any line. - """ - # Figure out when indent is larger than the specified width, and make - # sure at least one character is stripped off on every pass - if width < 1: - space_left = 1 - else: - space_left = width - cur_len - - # If we're allowed to break long words, then do so: put as much - # of the next chunk onto the current line as will fit. - if self.break_long_words: - cur_line.append(reversed_chunks[-1][:space_left]) - reversed_chunks[-1] = reversed_chunks[-1][space_left:] - - # Otherwise, we have to preserve the long word intact. Only add - # it to the current line if there's nothing already there -- - # that minimizes how much we violate the width constraint. - elif not cur_line: - cur_line.append(reversed_chunks.pop()) - - # If we're not allowed to break long words, and there's already - # text on the current line, do nothing. Next time through the - # main loop of _wrap_chunks(), we'll wind up here again, but - # cur_len will be zero, so the next line will be entirely - # devoted to the long word that we can't handle right now. - - def _wrap_chunks(self, chunks: List[str]) -> List[str]: - """_wrap_chunks(chunks : [string]) -> [string] - - Wrap a sequence of text chunks and return a list of lines of - length 'self.width' or less. (If 'break_long_words' is false, - some lines may be longer than this.) Chunks correspond roughly - to words and the whitespace between them: each chunk is - indivisible (modulo 'break_long_words'), but a line break can - come between any two chunks. Chunks should not have internal - whitespace; ie. a chunk is either all whitespace or a "word". - Whitespace chunks will be removed from the beginning and end of - lines, but apart from that whitespace is preserved. - """ - lines = [] # type: List[str] - if self.width <= 0: - raise ValueError("invalid width %r (must be > 0)" % self.width) - - # Arrange in reverse order so items can be efficiently popped - # from a stack of chucks. - chunks.reverse() - - while chunks: - - # Start the list of chunks that will make up the current line. - # cur_len is just the length of all the chunks in cur_line. - cur_line = [] # type: List[str] - cur_len = 0 - - # Figure out which static string will prefix this line. - if lines: - indent = self.subsequent_indent - else: - indent = self.initial_indent - - # Maximum width for this line. - width = self.width - len(indent) - - # First chunk on line is whitespace -- drop it, unless this - # is the very beginning of the text (ie. no lines started yet). - if self.drop_whitespace and chunks[-1].strip() == '' and lines: - del chunks[-1] - - while chunks: - l = len(chunks[-1]) - - # Can at least squeeze this chunk onto the current line. - if cur_len + l <= width: - cur_line.append(chunks.pop()) - cur_len += l - - # Nope, this line is full. - else: - break - - # The current line is full, and the next chunk is too big to - # fit on *any* line (not just this one). - if chunks and len(chunks[-1]) > width: - self._handle_long_word(chunks, cur_line, cur_len, width) - - # If the last chunk on this line is all whitespace, drop it. - if self.drop_whitespace and cur_line and cur_line[-1].strip() == '': - del cur_line[-1] - - # Convert current line back to a string and store it in list - # of all lines (return value). - if cur_line: - lines.append(indent + ''.join(cur_line)) - - return lines - - - # -- Public interface ---------------------------------------------- - - def wrap(self, text: str) -> List[str]: - """wrap(text : string) -> [string] - - Reformat the single paragraph in 'text' so it fits in lines of - no more than 'self.width' columns, and return a list of wrapped - lines. Tabs in 'text' are expanded with string.expandtabs(), - and all other whitespace characters (including newline) are - converted to space. - """ - text = self._munge_whitespace(text) - chunks = self._split(text) - if self.fix_sentence_endings: - self._fix_sentence_endings(chunks) - return self._wrap_chunks(chunks) - - def fill(self, text: str) -> str: - """fill(text : string) -> string - - Reformat the single paragraph in 'text' to fit in lines of no - more than 'self.width' columns, and return a new string - containing the entire wrapped paragraph. - """ - return "\n".join(self.wrap(text)) - - -# -- Convenience interface --------------------------------------------- - -def wrap(text: str, width: int = 70, **kwargs: Any) -> List[str]: - """Wrap a single paragraph of text, returning a list of wrapped lines. - - Reformat the single paragraph in 'text' so it fits in lines of no - more than 'width' columns, and return a list of wrapped lines. By - default, tabs in 'text' are expanded with string.expandtabs(), and - all other whitespace characters (including newline) are converted to - space. See TextWrapper class for available keyword args to customize - wrapping behaviour. - """ - w = TextWrapper(width=width, **kwargs) - return w.wrap(text) - -def fill(text: str, width: int = 70, **kwargs: Any) -> str: - """Fill a single paragraph of text, returning a new string. - - Reformat the single paragraph in 'text' to fit in lines of no more - than 'width' columns, and return a new string containing the entire - wrapped paragraph. As with wrap(), tabs are expanded and other - whitespace characters converted to space. See TextWrapper class for - available keyword args to customize wrapping behaviour. - """ - w = TextWrapper(width=width, **kwargs) - return w.fill(text) - - -# -- Loosely related functionality ------------------------------------- - -_whitespace_only_re = re.compile('^[ \t]+$', re.MULTILINE) -_leading_whitespace_re = re.compile('(^[ \t]*)(?:[^ \t\n])', re.MULTILINE) - -def dedent(text: str) -> str: - """Remove any common leading whitespace from every line in `text`. - - This can be used to make triple-quoted strings line up with the left - edge of the display, while still presenting them in the source code - in indented form. - - Note that tabs and spaces are both treated as whitespace, but they - are not equal: the lines " hello" and "\thello" are - considered to have no common leading whitespace. (This behaviour is - new in Python 2.5; older versions of this module incorrectly - expanded tabs before searching for common leading whitespace.) - """ - # Look for the longest leading string of spaces and tabs common to - # all lines. - margin = None # type: str - text = _whitespace_only_re.sub('', text) - indents = _leading_whitespace_re.findall(text) - for indent in indents: - if margin is None: - margin = indent - - # Current line more deeply indented than previous winner: - # no change (previous winner is still on top). - elif indent.startswith(margin): - pass - - # Current line consistent with and no deeper than previous winner: - # it's the new winner. - elif margin.startswith(indent): - margin = indent - - # Current line and previous winner have no common whitespace: - # there is no margin. - else: - margin = "" - break - - # sanity check (testing/debugging only) - if 0 and margin: - for line in text.split("\n"): - assert not line or line.startswith(margin), \ - "line = %r, margin = %r" % (line, margin) - - if margin: - text = re.sub(r'(?m)^' + margin, '', text) - return text - -if __name__ == "__main__": - #print dedent("\tfoo\n\tbar") - #print dedent(" \thello there\n \t how are you?") - print(dedent("Hello there.\n This is indented.")) From 378119fb0ce7cb6133eeccd4de236a330cc8e10e Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Sat, 8 Jan 2022 20:22:55 +0000 Subject: [PATCH 048/377] [mypyc] Ignore super calls to object.__init__() (#11938) This speeds up the deltablue benchmark by 15%. --- mypyc/irbuild/expression.py | 11 ++++++- mypyc/test-data/irbuild-classes.test | 47 ++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/mypyc/irbuild/expression.py b/mypyc/irbuild/expression.py index 6a42820b9b21e..71e497f9e368f 100644 --- a/mypyc/irbuild/expression.py +++ b/mypyc/irbuild/expression.py @@ -326,11 +326,20 @@ def translate_super_method_call(builder: IRBuilder, expr: CallExpr, callee: Supe return translate_call(builder, expr, callee) ir = builder.mapper.type_to_ir[callee.info] - # Search for the method in the mro, skipping ourselves. + # Search for the method in the mro, skipping ourselves. We + # determine targets of super calls to native methods statically. for base in ir.mro[1:]: if callee.name in base.method_decls: break else: + if (ir.is_ext_class + and ir.builtin_base is None + and not ir.inherits_python + and callee.name == '__init__' + and len(expr.args) == 0): + # Call translates to object.__init__(self), which is a + # no-op, so omit the call. + return builder.none() return translate_call(builder, expr, callee) decl = base.method_decl(callee.name) diff --git a/mypyc/test-data/irbuild-classes.test b/mypyc/test-data/irbuild-classes.test index 8f9b768df47c1..77943045ffe3a 100644 --- a/mypyc/test-data/irbuild-classes.test +++ b/mypyc/test-data/irbuild-classes.test @@ -795,6 +795,53 @@ L0: r0 = T.foo(self) return 1 +[case testSuperCallToObjectInitIsOmitted] +class C: + def __init__(self) -> None: + super().__init__() +class D: pass +class E(D): + def __init__(self) -> None: + super().__init__() +class F(C): + def __init__(self) -> None: + super().__init__() +class DictSubclass(dict): + def __init__(self) -> None: + super().__init__() +[out] +def C.__init__(self): + self :: __main__.C +L0: + return 1 +def E.__init__(self): + self :: __main__.E +L0: + return 1 +def F.__init__(self): + self :: __main__.F + r0 :: None +L0: + r0 = C.__init__(self) + return 1 +def DictSubclass.__init__(self): + self :: dict + r0 :: object + r1 :: str + r2, r3, r4 :: object + r5 :: str + r6, r7 :: object +L0: + r0 = builtins :: module + r1 = 'super' + r2 = CPyObject_GetAttr(r0, r1) + r3 = __main__.DictSubclass :: type + r4 = PyObject_CallFunctionObjArgs(r2, r3, self, 0) + r5 = '__init__' + r6 = CPyObject_GetAttr(r4, r5) + r7 = PyObject_CallFunctionObjArgs(r6, 0) + return 1 + [case testClassVariable] from typing import ClassVar class A: From c0c86d072d39fc2d217db57a0ca9ded84843d29b Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Sun, 9 Jan 2022 20:08:07 +0300 Subject: [PATCH 049/377] NamedTuple now narrows to bool correctly, when `__bool__` is defined (#11822) --- mypy/types.py | 27 ++++++++++++++++--- test-data/unit/check-namedtuple.test | 39 ++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 4 deletions(-) diff --git a/mypy/types.py b/mypy/types.py index 15ae47e341d40..39c0d8f640114 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -1526,12 +1526,31 @@ class TupleType(ProperType): def __init__(self, items: List[Type], fallback: Instance, line: int = -1, column: int = -1, implicit: bool = False) -> None: - super().__init__(line, column) - self.items = items self.partial_fallback = fallback + self.items = items self.implicit = implicit - self.can_be_true = len(self.items) > 0 - self.can_be_false = len(self.items) == 0 + super().__init__(line, column) + + def can_be_true_default(self) -> bool: + if self.can_be_any_bool(): + # Corner case: it is a `NamedTuple` with `__bool__` method defined. + # It can be anything: both `True` and `False`. + return True + return self.length() > 0 + + def can_be_false_default(self) -> bool: + if self.can_be_any_bool(): + # Corner case: it is a `NamedTuple` with `__bool__` method defined. + # It can be anything: both `True` and `False`. + return True + return self.length() == 0 + + def can_be_any_bool(self) -> bool: + return bool( + self.partial_fallback.type + and self.partial_fallback.type.fullname != 'builtins.tuple' + and self.partial_fallback.type.names.get('__bool__') + ) def length(self) -> int: return len(self.items) diff --git a/test-data/unit/check-namedtuple.test b/test-data/unit/check-namedtuple.test index 5d28d78013f4c..b95cc96f81155 100644 --- a/test-data/unit/check-namedtuple.test +++ b/test-data/unit/check-namedtuple.test @@ -1081,3 +1081,42 @@ t: T y: List[T] = [t] [builtins fixtures/tuple.pyi] [typing fixtures/typing-namedtuple.pyi] + +[case testNamedTupleWithBoolNarrowsToBool] +# flags: --warn-unreachable +from typing import NamedTuple + +class C(NamedTuple): + x: int + + def __bool__(self) -> bool: + pass + +def foo(c: C) -> None: + if c: + reveal_type(c) # N: Revealed type is "Tuple[builtins.int, fallback=__main__.C]" + else: + reveal_type(c) # N: Revealed type is "Tuple[builtins.int, fallback=__main__.C]" + +def bar(c: C) -> None: + if not c: + reveal_type(c) # N: Revealed type is "Tuple[builtins.int, fallback=__main__.C]" + else: + reveal_type(c) # N: Revealed type is "Tuple[builtins.int, fallback=__main__.C]" + +class C1(NamedTuple): + x: int + +def foo1(c: C1) -> None: + if c: + reveal_type(c) # N: Revealed type is "Tuple[builtins.int, fallback=__main__.C1]" + else: + c # E: Statement is unreachable + +def bar1(c: C1) -> None: + if not c: + c # E: Statement is unreachable + else: + reveal_type(c) # N: Revealed type is "Tuple[builtins.int, fallback=__main__.C1]" +[builtins fixtures/tuple.pyi] +[typing fixtures/typing-namedtuple.pyi] From 25b212990faed11993d49e822d50a0a88e10c959 Mon Sep 17 00:00:00 2001 From: Mark Bell Date: Sun, 9 Jan 2022 17:18:29 +0000 Subject: [PATCH 050/377] Fix `CallableType.formal_arguments` docstring (#11861) PR #11543 changed the `formal_arguments` method to return a list of formal arguments instead of yielding them. However the docstring was not updated at the time to reflect this. --- mypy/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/types.py b/mypy/types.py index 39c0d8f640114..128b9bf016d76 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -1273,7 +1273,7 @@ def max_possible_positional_args(self) -> int: return sum([kind.is_positional() for kind in self.arg_kinds]) def formal_arguments(self, include_star_args: bool = False) -> List[FormalArgument]: - """Yields the formal arguments corresponding to this callable, ignoring *arg and **kwargs. + """Return a list of the formal arguments of this callable, ignoring *arg and **kwargs. To handle *args and **kwargs, use the 'callable.var_args' and 'callable.kw_args' fields, if they are not None. From 6ea7cfa9de21eb0ae363257b1b2e5435b1ec4bce Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Sun, 9 Jan 2022 21:15:56 +0300 Subject: [PATCH 051/377] Microrefactoring: use more constants for type names (#11803) Co-authored-by: Jelle Zijlstra --- mypy/checkexpr.py | 5 ++--- mypy/exprtotype.py | 6 ++---- mypy/semanal.py | 19 ++++++++----------- mypy/typeanal.py | 23 ++++++++++------------- mypy/types.py | 36 ++++++++++++++++++++++++++++++++++++ 5 files changed, 58 insertions(+), 31 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index b1ffbf7a87be1..391c7a59d60be 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -20,7 +20,7 @@ PartialType, DeletedType, UninhabitedType, TypeType, TypeOfAny, LiteralType, LiteralValue, is_named_instance, FunctionLike, ParamSpecType, ParamSpecFlavor, StarType, is_optional, remove_optional, is_generic_instance, get_proper_type, ProperType, - get_proper_types, flatten_nested_unions + get_proper_types, flatten_nested_unions, LITERAL_TYPE_NAMES, ) from mypy.nodes import ( NameExpr, RefExpr, Var, FuncDef, OverloadedFuncDef, TypeInfo, CallExpr, @@ -4551,10 +4551,9 @@ def try_getting_literal(typ: Type) -> ProperType: def is_expr_literal_type(node: Expression) -> bool: """Returns 'true' if the given node is a Literal""" - valid = ('typing.Literal', 'typing_extensions.Literal') if isinstance(node, IndexExpr): base = node.base - return isinstance(base, RefExpr) and base.fullname in valid + return isinstance(base, RefExpr) and base.fullname in LITERAL_TYPE_NAMES if isinstance(node, NameExpr): underlying = node.node return isinstance(underlying, TypeAlias) and isinstance(get_proper_type(underlying.target), diff --git a/mypy/exprtotype.py b/mypy/exprtotype.py index 8f6f6c11f3464..243bbf024faf0 100644 --- a/mypy/exprtotype.py +++ b/mypy/exprtotype.py @@ -10,7 +10,7 @@ from mypy.fastparse import parse_type_string from mypy.types import ( Type, UnboundType, TypeList, EllipsisType, AnyType, CallableArgument, TypeOfAny, - RawExpressionType, ProperType, UnionType + RawExpressionType, ProperType, UnionType, ANNOTATED_TYPE_NAMES, ) from mypy.options import Options @@ -69,9 +69,7 @@ def expr_to_unanalyzed_type(expr: Expression, else: args = [expr.index] - if isinstance(expr.base, RefExpr) and expr.base.fullname in [ - 'typing.Annotated', 'typing_extensions.Annotated' - ]: + if isinstance(expr.base, RefExpr) and expr.base.fullname in ANNOTATED_TYPE_NAMES: # TODO: this is not the optimal solution as we are basically getting rid # of the Annotation definition and only returning the type information, # losing all the annotations. diff --git a/mypy/semanal.py b/mypy/semanal.py index 764fb4c363944..4938b96c8bcad 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -92,7 +92,8 @@ FunctionLike, UnboundType, TypeVarType, TupleType, UnionType, StarType, CallableType, Overloaded, Instance, Type, AnyType, LiteralType, LiteralValue, TypeTranslator, TypeOfAny, TypeType, NoneType, PlaceholderType, TPDICT_NAMES, ProperType, - get_proper_type, get_proper_types, TypeAliasType, TypeVarLikeType + get_proper_type, get_proper_types, TypeAliasType, TypeVarLikeType, + PROTOCOL_NAMES, TYPE_ALIAS_NAMES, FINAL_TYPE_NAMES, FINAL_DECORATOR_NAMES, ) from mypy.typeops import function_type, get_type_vars from mypy.type_visitor import TypeQuery @@ -1154,8 +1155,7 @@ def analyze_class(self, defn: ClassDef) -> None: for decorator in defn.decorators: decorator.accept(self) if isinstance(decorator, RefExpr): - if decorator.fullname in ('typing.final', - 'typing_extensions.final'): + if decorator.fullname in FINAL_DECORATOR_NAMES: self.fail("@final cannot be used with TypedDict", decorator) if info is None: self.mark_incomplete(defn.name, defn) @@ -1282,8 +1282,7 @@ def analyze_class_decorator(self, defn: ClassDef, decorator: Expression) -> None else: self.fail('@runtime_checkable can only be used with protocol classes', defn) - elif decorator.fullname in ('typing.final', - 'typing_extensions.final'): + elif decorator.fullname in FINAL_DECORATOR_NAMES: defn.info.is_final = True def clean_up_bases_and_infer_type_variables( @@ -1328,8 +1327,7 @@ class Foo(Bar, Generic[T]): ... if isinstance(base, UnboundType): sym = self.lookup_qualified(base.name, base) if sym is not None and sym.node is not None: - if (sym.node.fullname in ('typing.Protocol', 'typing_extensions.Protocol') and - i not in removed): + if sym.node.fullname in PROTOCOL_NAMES and i not in removed: # also remove bare 'Protocol' bases removed.append(i) is_protocol = True @@ -1377,8 +1375,7 @@ def analyze_class_typevar_declaration( if sym is None or sym.node is None: return None if (sym.node.fullname == 'typing.Generic' or - sym.node.fullname == 'typing.Protocol' and base.args or - sym.node.fullname == 'typing_extensions.Protocol' and base.args): + sym.node.fullname in PROTOCOL_NAMES and base.args): is_proto = sym.node.fullname != 'typing.Generic' tvars: TypeVarLikeList = [] for arg in unbound.args: @@ -2669,7 +2666,7 @@ def check_and_set_up_type_alias(self, s: AssignmentStmt) -> bool: pep_613 = False if s.unanalyzed_type is not None and isinstance(s.unanalyzed_type, UnboundType): lookup = self.lookup(s.unanalyzed_type.name, s, suppress_errors=True) - if lookup and lookup.fullname in ("typing.TypeAlias", "typing_extensions.TypeAlias"): + if lookup and lookup.fullname in TYPE_ALIAS_NAMES: pep_613 = True if not pep_613 and s.unanalyzed_type is not None: # Second rule: Explicit type (cls: Type[A] = A) always creates variable, not alias. @@ -3410,7 +3407,7 @@ def is_final_type(self, typ: Optional[Type]) -> bool: sym = self.lookup_qualified(typ.name, typ) if not sym or not sym.node: return False - return sym.node.fullname in ('typing.Final', 'typing_extensions.Final') + return sym.node.fullname in FINAL_TYPE_NAMES def fail_invalid_classvar(self, context: Context) -> None: self.fail(message_registry.CLASS_VAR_OUTSIDE_OF_CLASS, context) diff --git a/mypy/typeanal.py b/mypy/typeanal.py index 0646240a23f96..2a14162cf5585 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -17,7 +17,8 @@ StarType, PartialType, EllipsisType, UninhabitedType, TypeType, CallableArgument, TypeQuery, union_items, TypeOfAny, LiteralType, RawExpressionType, PlaceholderType, Overloaded, get_proper_type, TypeAliasType, RequiredType, - TypeVarLikeType, ParamSpecType, ParamSpecFlavor, callable_with_ellipsis + TypeVarLikeType, ParamSpecType, ParamSpecFlavor, callable_with_ellipsis, + TYPE_ALIAS_NAMES, FINAL_TYPE_NAMES, LITERAL_TYPE_NAMES, ANNOTATED_TYPE_NAMES, ) from mypy.nodes import ( @@ -42,10 +43,8 @@ 'typing.Tuple', 'typing.Type', 'typing.Union', - 'typing.Literal', - 'typing_extensions.Literal', - 'typing.Annotated', - 'typing_extensions.Annotated', + *LITERAL_TYPE_NAMES, + *ANNOTATED_TYPE_NAMES, } ARG_KINDS_BY_CONSTRUCTOR: Final = { @@ -262,7 +261,7 @@ def visit_unbound_type_nonoptional(self, t: UnboundType, defining_literal: bool) return res elif isinstance(node, TypeInfo): return self.analyze_type_with_type_info(node, t.args, t) - elif node.fullname in ("typing_extensions.TypeAlias", "typing.TypeAlias"): + elif node.fullname in TYPE_ALIAS_NAMES: return AnyType(TypeOfAny.special_form) else: return self.analyze_unbound_type_without_type_info(t, sym, defining_literal) @@ -286,7 +285,7 @@ def try_analyze_special_unbound_type(self, t: UnboundType, fullname: str) -> Opt return NoneType() elif fullname == 'typing.Any' or fullname == 'builtins.Any': return AnyType(TypeOfAny.explicit) - elif fullname in ('typing.Final', 'typing_extensions.Final'): + elif fullname in FINAL_TYPE_NAMES: self.fail("Final can be only used as an outermost qualifier" " in a variable annotation", t) return AnyType(TypeOfAny.from_error) @@ -351,9 +350,9 @@ def try_analyze_special_unbound_type(self, t: UnboundType, fullname: str) -> Opt return self.anal_type(t.args[0]) elif fullname in ('mypy_extensions.NoReturn', 'typing.NoReturn'): return UninhabitedType(is_noreturn=True) - elif fullname in ('typing_extensions.Literal', 'typing.Literal'): + elif fullname in LITERAL_TYPE_NAMES: return self.analyze_literal_type(t) - elif fullname in ('typing_extensions.Annotated', 'typing.Annotated'): + elif fullname in ANNOTATED_TYPE_NAMES: if len(t.args) < 2: self.fail("Annotated[...] must have exactly one type argument" " and at least one annotation", t) @@ -1287,11 +1286,9 @@ def visit_unbound_type(self, t: UnboundType) -> TypeVarLikeList: return [(name, node.node)] elif not self.include_callables and self._seems_like_callable(t): return [] - elif node and node.fullname in ('typing_extensions.Literal', 'typing.Literal'): + elif node and node.fullname in LITERAL_TYPE_NAMES: return [] - elif (node - and node.fullname in ('typing_extensions.Annotated', 'typing.Annotated') - and t.args): + elif node and node.fullname in ANNOTATED_TYPE_NAMES and t.args: # Don't query the second argument to Annotated for TypeVars return self.query_types([t.args[0]]) else: diff --git a/mypy/types.py b/mypy/types.py index 128b9bf016d76..f055d134d5822 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -81,6 +81,42 @@ "mypy_extensions._TypedDict", ) +# Supported names of Protocol base class. +PROTOCOL_NAMES: Final = ( + 'typing.Protocol', + 'typing_extensions.Protocol', +) + +# Supported TypeAlias names. +TYPE_ALIAS_NAMES: Final = ( + "typing.TypeAlias", + "typing_extensions.TypeAlias", +) + +# Supported Final type names. +FINAL_TYPE_NAMES: Final = ( + 'typing.Final', + 'typing_extensions.Final', +) + +# Supported @final decorator names. +FINAL_DECORATOR_NAMES: Final = ( + 'typing.final', + 'typing_extensions.final', +) + +# Supported Literal type names. +LITERAL_TYPE_NAMES: Final = ( + 'typing.Literal', + 'typing_extensions.Literal', +) + +# Supported Annotated type names. +ANNOTATED_TYPE_NAMES: Final = ( + 'typing.Annotated', + 'typing_extensions.Annotated', +) + # A placeholder used for Bogus[...] parameters _dummy: Final[Any] = object() From f6ebf108f76d3c2af0a2245c4abbad302b476141 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Mon, 10 Jan 2022 15:05:07 +0300 Subject: [PATCH 052/377] Fix `Enum` final props and writable special members, refs #11820 (#11945) --- mypy/checker.py | 2 +- test-data/unit/check-enum.test | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 51aa7a3942fff..ce1859c02a201 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -2517,7 +2517,7 @@ def check_compatibility_final_super(self, node: Var, self.msg.cant_override_final(node.name, base.name, node) return False if node.is_final: - if base.fullname in ENUM_BASES and node.name in ENUM_SPECIAL_PROPS: + if base.fullname in ENUM_BASES or node.name in ENUM_SPECIAL_PROPS: return True self.check_if_final_var_override_writable(node.name, base_node, node) return True diff --git a/test-data/unit/check-enum.test b/test-data/unit/check-enum.test index d80cd4822b8ce..8024fbcf7e3fb 100644 --- a/test-data/unit/check-enum.test +++ b/test-data/unit/check-enum.test @@ -1712,9 +1712,17 @@ class B(A): pass # E: Cannot inherit from final class "A" [case testEnumFinalSpecialProps] # https://github.com/python/mypy/issues/11699 +# https://github.com/python/mypy/issues/11820 from enum import Enum, IntEnum -class E(Enum): +class BaseWithSpecials: + __slots__ = () + __doc__ = 'doc' + __module__ = 'module' + __annotations__ = {'a': int} + __dict__ = {'a': 1} + +class E(BaseWithSpecials, Enum): name = 'a' value = 'b' _name_ = 'a1' From 41a79348d7b6d9c4b38f59aedadc9812c0732731 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Mon, 10 Jan 2022 12:39:39 +0000 Subject: [PATCH 053/377] [mypyc] Fix invalid unlikely() in certain rare branches (#11939) If we switch true/false branches, we also need to switch between likely/unlikely. This has an impact at least on accessing module-level final attributes with non-constant initializers. I couldn't see a significant difference in benchmark results compared to master, but this seems to help together with some other work-in-progress improvements I have been working on. --- mypyc/codegen/emitfunc.py | 7 ++++++- mypyc/test/test_emitfunc.py | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/mypyc/codegen/emitfunc.py b/mypyc/codegen/emitfunc.py index 3b94c56487694..b2dbab3d911bc 100644 --- a/mypyc/codegen/emitfunc.py +++ b/mypyc/codegen/emitfunc.py @@ -122,10 +122,12 @@ def visit_goto(self, op: Goto) -> None: def visit_branch(self, op: Branch) -> None: true, false = op.true, op.false negated = op.negated + negated_rare = False if true is self.next_block and op.traceback_entry is None: # Switch true/false since it avoids an else block. true, false = false, true negated = not negated + negated_rare = True neg = '!' if negated else '' cond = '' @@ -150,7 +152,10 @@ def visit_branch(self, op: Branch) -> None: # For error checks, tell the compiler the branch is unlikely if op.traceback_entry is not None or op.rare: - cond = 'unlikely({})'.format(cond) + if not negated_rare: + cond = 'unlikely({})'.format(cond) + else: + cond = 'likely({})'.format(cond) if false is self.next_block: if op.traceback_entry is None: diff --git a/mypyc/test/test_emitfunc.py b/mypyc/test/test_emitfunc.py index a3f55a7facf2f..60c62d2b4b4c5 100644 --- a/mypyc/test/test_emitfunc.py +++ b/mypyc/test/test_emitfunc.py @@ -187,6 +187,29 @@ def test_branch_is_error_next_block(self) -> None: """if (cpy_r_b == 2) goto CPyL9;""", next_block=next_block) + def test_branch_rare(self) -> None: + self.assert_emit(Branch(self.b, BasicBlock(8), BasicBlock(9), Branch.BOOL, rare=True), + """if (unlikely(cpy_r_b)) { + goto CPyL8; + } else + goto CPyL9; + """) + next_block = BasicBlock(9) + self.assert_emit(Branch(self.b, BasicBlock(8), next_block, Branch.BOOL, rare=True), + """if (unlikely(cpy_r_b)) goto CPyL8;""", + next_block=next_block) + next_block = BasicBlock(8) + b = Branch(self.b, next_block, BasicBlock(9), Branch.BOOL, rare=True) + self.assert_emit(b, + """if (likely(!cpy_r_b)) goto CPyL9;""", + next_block=next_block) + next_block = BasicBlock(8) + b = Branch(self.b, next_block, BasicBlock(9), Branch.BOOL, rare=True) + b.negated = True + self.assert_emit(b, + """if (likely(cpy_r_b)) goto CPyL9;""", + next_block=next_block) + def test_call(self) -> None: decl = FuncDecl('myfn', None, 'mod', FuncSignature([RuntimeArg('m', int_rprimitive)], int_rprimitive)) From 9ea6d928646f823af0bb646cca0aba26be7e1107 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Mon, 10 Jan 2022 16:09:02 +0300 Subject: [PATCH 054/377] Refactor `is_named_instance` and `refers_to_fullname` (#11961) --- mypy/constraints.py | 10 ++++------ mypy/semanal.py | 25 +++++++++++++------------ mypy/subtypes.py | 15 ++++----------- mypy/types.py | 16 ++++++++++++++-- 4 files changed, 35 insertions(+), 31 deletions(-) diff --git a/mypy/constraints.py b/mypy/constraints.py index 5a78cdb94e93a..9bc233054e917 100644 --- a/mypy/constraints.py +++ b/mypy/constraints.py @@ -8,7 +8,8 @@ TupleType, TypedDictType, UnionType, Overloaded, ErasedType, PartialType, DeletedType, UninhabitedType, TypeType, TypeVarId, TypeQuery, is_named_instance, TypeOfAny, LiteralType, ProperType, ParamSpecType, get_proper_type, TypeAliasType, is_union_with_any, - callable_with_ellipsis + callable_with_ellipsis, + TUPLE_LIKE_INSTANCE_NAMES, ) from mypy.maptype import map_instance_to_supertype import mypy.subtypes @@ -501,11 +502,8 @@ def visit_instance(self, template: Instance) -> List[Constraint]: return res if isinstance(actual, AnyType): return self.infer_against_any(template.args, actual) - if (isinstance(actual, TupleType) and - (is_named_instance(template, 'typing.Iterable') or - is_named_instance(template, 'typing.Container') or - is_named_instance(template, 'typing.Sequence') or - is_named_instance(template, 'typing.Reversible')) + if (isinstance(actual, TupleType) + and is_named_instance(template, TUPLE_LIKE_INSTANCE_NAMES) and self.direction == SUPERTYPE_OF): for item in actual.items: cb = infer_constraints(template.args[0], item, SUPERTYPE_OF) diff --git a/mypy/semanal.py b/mypy/semanal.py index 4938b96c8bcad..b25ad1542a040 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -94,6 +94,7 @@ TypeTranslator, TypeOfAny, TypeType, NoneType, PlaceholderType, TPDICT_NAMES, ProperType, get_proper_type, get_proper_types, TypeAliasType, TypeVarLikeType, PROTOCOL_NAMES, TYPE_ALIAS_NAMES, FINAL_TYPE_NAMES, FINAL_DECORATOR_NAMES, + is_named_instance, ) from mypy.typeops import function_type, get_type_vars from mypy.type_visitor import TypeQuery @@ -1038,8 +1039,7 @@ def visit_decorator(self, dec: Decorator) -> None: removed.append(i) dec.func.is_abstract = True self.check_decorated_function_is_method('abstractmethod', dec) - elif (refers_to_fullname(d, 'asyncio.coroutines.coroutine') or - refers_to_fullname(d, 'types.coroutine')): + elif refers_to_fullname(d, ('asyncio.coroutines.coroutine', 'types.coroutine')): removed.append(i) dec.func.is_awaitable_coroutine = True elif refers_to_fullname(d, 'builtins.staticmethod'): @@ -1052,9 +1052,10 @@ def visit_decorator(self, dec: Decorator) -> None: dec.func.is_class = True dec.var.is_classmethod = True self.check_decorated_function_is_method('classmethod', dec) - elif (refers_to_fullname(d, 'builtins.property') or - refers_to_fullname(d, 'abc.abstractproperty') or - refers_to_fullname(d, 'functools.cached_property')): + elif refers_to_fullname(d, ( + 'builtins.property', + 'abc.abstractproperty', + 'functools.cached_property')): removed.append(i) dec.func.is_property = True dec.var.is_property = True @@ -1068,8 +1069,7 @@ def visit_decorator(self, dec: Decorator) -> None: elif refers_to_fullname(d, 'typing.no_type_check'): dec.var.type = AnyType(TypeOfAny.special_form) no_type_check = True - elif (refers_to_fullname(d, 'typing.final') or - refers_to_fullname(d, 'typing_extensions.final')): + elif refers_to_fullname(d, FINAL_DECORATOR_NAMES): if self.is_class_scope(): assert self.type is not None, "No type set at class scope" if self.type.is_protocol: @@ -5315,16 +5315,17 @@ def replace_implicit_first_type(sig: FunctionLike, new: Type) -> FunctionLike: assert False -def refers_to_fullname(node: Expression, fullname: str) -> bool: +def refers_to_fullname(node: Expression, fullnames: Union[str, Tuple[str, ...]]) -> bool: """Is node a name or member expression with the given full name?""" + if not isinstance(fullnames, tuple): + fullnames = (fullnames,) + if not isinstance(node, RefExpr): return False - if node.fullname == fullname: + if node.fullname in fullnames: return True if isinstance(node.node, TypeAlias): - target = get_proper_type(node.node.target) - if isinstance(target, Instance) and target.type.fullname == fullname: - return True + return is_named_instance(node.node.target, fullnames) return False diff --git a/mypy/subtypes.py b/mypy/subtypes.py index 2001060001325..271e950de659c 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -7,7 +7,8 @@ Type, AnyType, UnboundType, TypeVisitor, FormalArgument, NoneType, Instance, TypeVarType, CallableType, TupleType, TypedDictType, UnionType, Overloaded, ErasedType, PartialType, DeletedType, UninhabitedType, TypeType, is_named_instance, - FunctionLike, TypeOfAny, LiteralType, get_proper_type, TypeAliasType, ParamSpecType + FunctionLike, TypeOfAny, LiteralType, get_proper_type, TypeAliasType, ParamSpecType, + TUPLE_LIKE_INSTANCE_NAMES, ) import mypy.applytype import mypy.constraints @@ -362,11 +363,7 @@ def visit_tuple_type(self, left: TupleType) -> bool: if isinstance(right, Instance): if is_named_instance(right, 'typing.Sized'): return True - elif (is_named_instance(right, 'builtins.tuple') or - is_named_instance(right, 'typing.Iterable') or - is_named_instance(right, 'typing.Container') or - is_named_instance(right, 'typing.Sequence') or - is_named_instance(right, 'typing.Reversible')): + elif is_named_instance(right, TUPLE_LIKE_INSTANCE_NAMES): if right.args: iter_type = right.args[0] else: @@ -1377,11 +1374,7 @@ def visit_callable_type(self, left: CallableType) -> bool: def visit_tuple_type(self, left: TupleType) -> bool: right = self.right if isinstance(right, Instance): - if (is_named_instance(right, 'builtins.tuple') or - is_named_instance(right, 'typing.Iterable') or - is_named_instance(right, 'typing.Container') or - is_named_instance(right, 'typing.Sequence') or - is_named_instance(right, 'typing.Reversible')): + if is_named_instance(right, TUPLE_LIKE_INSTANCE_NAMES): if not right.args: return False iter_type = get_proper_type(right.args[0]) diff --git a/mypy/types.py b/mypy/types.py index f055d134d5822..d3987897995ed 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -117,6 +117,15 @@ 'typing_extensions.Annotated', ) +# We use this constant in various places when checking `tuple` subtyping: +TUPLE_LIKE_INSTANCE_NAMES: Final = ( + 'builtins.tuple', + 'typing.Iterable', + 'typing.Container', + 'typing.Sequence', + 'typing.Reversible', +) + # A placeholder used for Bogus[...] parameters _dummy: Final[Any] = object() @@ -2482,9 +2491,12 @@ def strip_type(typ: Type) -> ProperType: return typ -def is_named_instance(t: Type, fullname: str) -> bool: +def is_named_instance(t: Type, fullnames: Union[str, Tuple[str, ...]]) -> bool: + if not isinstance(fullnames, tuple): + fullnames = (fullnames,) + t = get_proper_type(t) - return isinstance(t, Instance) and t.type.fullname == fullname + return isinstance(t, Instance) and t.type.fullname in fullnames TP = TypeVar('TP', bound=Type) From 48d810d5ed25f898d4f220a7476b6b267c289b9a Mon Sep 17 00:00:00 2001 From: joey-laminar <92668266+joey-laminar@users.noreply.github.com> Date: Mon, 10 Jan 2022 17:02:28 +0200 Subject: [PATCH 055/377] Make enum values final - fixes #11919 (#11962) This fix allows using enum values in place of literals. For example: ``` def is_a(a: Literal["a"]): return None class MyStr(Enum): a = "a" b = "b" is_a(MyStr.a.value) ``` Currently this fails with ``` error: Argument 1 to "is_a" has incompatible type "str"; expected "Literal['a']" ``` The fix itself is simple - the special casing of final status for enums was being called too late to have an effect. Moving the function call up solves the problem. Fixes #11919 --- mypy/semanal.py | 2 +- test-data/unit/check-enum.test | 45 ++++++++++++++++++++++------------ test-data/unit/merge.test | 6 ++--- 3 files changed, 34 insertions(+), 19 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index b25ad1542a040..fbef499dd91da 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -2104,10 +2104,10 @@ def visit_assignment_stmt(self, s: AssignmentStmt) -> None: s.is_final_def = self.unwrap_final(s) self.analyze_lvalues(s) self.check_final_implicit_def(s) + self.store_final_status(s) self.check_classvar(s) self.process_type_annotation(s) self.apply_dynamic_class_hook(s) - self.store_final_status(s) if not s.type: self.process_module_assignment(s.lvalues, s.rvalue, s) self.process__all__(s) diff --git a/test-data/unit/check-enum.test b/test-data/unit/check-enum.test index 8024fbcf7e3fb..8d3620b1b71e4 100644 --- a/test-data/unit/check-enum.test +++ b/test-data/unit/check-enum.test @@ -618,8 +618,8 @@ reveal_type(A2.x.value) # N: Revealed type is "builtins.int" reveal_type(A2.x._value_) # N: Revealed type is "builtins.int" is_x(reveal_type(A3.x.name)) # N: Revealed type is "Literal['x']" is_x(reveal_type(A3.x._name_)) # N: Revealed type is "Literal['x']" -reveal_type(A3.x.value) # N: Revealed type is "builtins.int" -reveal_type(A3.x._value_) # N: Revealed type is "builtins.int" +reveal_type(A3.x.value) # N: Revealed type is "Literal[1]?" +reveal_type(A3.x._value_) # N: Revealed type is "Literal[1]?" B1 = IntEnum('B1', 'x') class B2(IntEnum): @@ -639,8 +639,8 @@ reveal_type(B2.x.value) # N: Revealed type is "builtins.int" reveal_type(B2.x._value_) # N: Revealed type is "builtins.int" is_x(reveal_type(B3.x.name)) # N: Revealed type is "Literal['x']" is_x(reveal_type(B3.x._name_)) # N: Revealed type is "Literal['x']" -reveal_type(B3.x.value) # N: Revealed type is "builtins.int" -reveal_type(B3.x._value_) # N: Revealed type is "builtins.int" +reveal_type(B3.x.value) # N: Revealed type is "Literal[1]?" +reveal_type(B3.x._value_) # N: Revealed type is "Literal[1]?" # TODO: C1.x.value and C2.x.value should also be of type 'int' # This requires either a typeshed change or a plugin refinement @@ -661,8 +661,8 @@ reveal_type(C2.x.value) # N: Revealed type is "builtins.int" reveal_type(C2.x._value_) # N: Revealed type is "builtins.int" is_x(reveal_type(C3.x.name)) # N: Revealed type is "Literal['x']" is_x(reveal_type(C3.x._name_)) # N: Revealed type is "Literal['x']" -reveal_type(C3.x.value) # N: Revealed type is "builtins.int" -reveal_type(C3.x._value_) # N: Revealed type is "builtins.int" +reveal_type(C3.x.value) # N: Revealed type is "Literal[1]?" +reveal_type(C3.x._value_) # N: Revealed type is "Literal[1]?" D1 = Flag('D1', 'x') class D2(Flag): @@ -680,8 +680,8 @@ reveal_type(D2.x.value) # N: Revealed type is "builtins.int" reveal_type(D2.x._value_) # N: Revealed type is "builtins.int" is_x(reveal_type(D3.x.name)) # N: Revealed type is "Literal['x']" is_x(reveal_type(D3.x._name_)) # N: Revealed type is "Literal['x']" -reveal_type(D3.x.value) # N: Revealed type is "builtins.int" -reveal_type(D3.x._value_) # N: Revealed type is "builtins.int" +reveal_type(D3.x.value) # N: Revealed type is "Literal[1]?" +reveal_type(D3.x._value_) # N: Revealed type is "Literal[1]?" # TODO: Generalize our enum functional API logic to work with subclasses of Enum # See https://github.com/python/mypy/issues/6037 @@ -699,8 +699,8 @@ reveal_type(E2.x.value) # N: Revealed type is "builtins.int" reveal_type(E2.x._value_) # N: Revealed type is "builtins.int" is_x(reveal_type(E3.x.name)) # N: Revealed type is "Literal['x']" is_x(reveal_type(E3.x._name_)) # N: Revealed type is "Literal['x']" -reveal_type(E3.x.value) # N: Revealed type is "builtins.int" -reveal_type(E3.x._value_) # N: Revealed type is "builtins.int" +reveal_type(E3.x.value) # N: Revealed type is "Literal[1]?" +reveal_type(E3.x._value_) # N: Revealed type is "Literal[1]?" # TODO: Figure out if we can construct enums using EnumMetas using the functional API. @@ -737,9 +737,9 @@ from enum import Enum class SomeEnum(Enum): a = "foo" [out] -main:2: note: Revealed type is "builtins.int" +main:2: note: Revealed type is "Literal[1]?" [out2] -main:2: note: Revealed type is "builtins.str" +main:2: note: Revealed type is "Literal['foo']?" [case testEnumReachabilityChecksBasic] from enum import Enum @@ -1311,8 +1311,8 @@ class Foo(Enum): B = 2 a = Foo.A -reveal_type(a.value) # N: Revealed type is "builtins.int" -reveal_type(a._value_) # N: Revealed type is "builtins.int" +reveal_type(a.value) # N: Revealed type is "Union[Literal[1]?, Literal[2]?]" +reveal_type(a._value_) # N: Revealed type is "Union[Literal[1]?, Literal[2]?]" [case testNewSetsUnexpectedValueType] from enum import Enum @@ -1437,7 +1437,7 @@ class Foo(Enum): A = 1 A = 'a' # E: Attempted to reuse member name "A" in Enum definition "Foo" \ # E: Incompatible types in assignment (expression has type "str", variable has type "int") -reveal_type(Foo.A.value) # N: Revealed type is "builtins.int" +reveal_type(Foo.A.value) # N: Revealed type is "Literal[1]?" class Bar(Enum): A = 1 @@ -1796,3 +1796,18 @@ class C(Enum): class D(C): # E: Cannot inherit from final class "C" x: int # E: Cannot assign to final name "x" [builtins fixtures/bool.pyi] + +[case testEnumLiteralValues] +from enum import Enum + +class A(Enum): + str = "foo" + int = 1 + bool = False + tuple = (1,) + +reveal_type(A.str.value) # N: Revealed type is "Literal['foo']?" +reveal_type(A.int.value) # N: Revealed type is "Literal[1]?" +reveal_type(A.bool.value) # N: Revealed type is "Literal[False]?" +reveal_type(A.tuple.value) # N: Revealed type is "Tuple[Literal[1]?]" +[builtins fixtures/tuple.pyi] \ No newline at end of file diff --git a/test-data/unit/merge.test b/test-data/unit/merge.test index 3eb41c2303ddb..b59a713fef4d8 100644 --- a/test-data/unit/merge.test +++ b/test-data/unit/merge.test @@ -1435,7 +1435,7 @@ TypeInfo<0>( Bases(enum.Enum<1>) Mro(target.A<0>, enum.Enum<1>, builtins.object<2>) Names( - X<3> (builtins.int<4>)) + X<3> (Literal[0]?<4>)) MetaclassType(enum.EnumMeta<5>)) ==> TypeInfo<0>( @@ -1443,8 +1443,8 @@ TypeInfo<0>( Bases(enum.Enum<1>) Mro(target.A<0>, enum.Enum<1>, builtins.object<2>) Names( - X<3> (builtins.int<4>) - Y<6> (builtins.int<4>)) + X<3> (Literal[0]?<4>) + Y<6> (Literal[1]?<4>)) MetaclassType(enum.EnumMeta<5>)) [case testLiteralMerge] From 6c1eb5b36b83ecf959a50100d282ca86186f470f Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Tue, 11 Jan 2022 16:27:01 +0000 Subject: [PATCH 056/377] [mypyc] Raise AttributeError also for non-refcounted types (#11940) Previously we only raised it for refcounted types, potentially resulting in errors like this: ``` SystemError: initialization of m failed without raising an exception ``` Unfortunately, this slows down the richards benchmark by about 15%. We can get the lost performance back once we have support for always defined attributes, at the latest. --- mypyc/codegen/emitfunc.py | 18 +++++++++--------- mypyc/test-data/run-classes.test | 15 +++++++++++++++ mypyc/test/test_emitfunc.py | 9 +++++++++ 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/mypyc/codegen/emitfunc.py b/mypyc/codegen/emitfunc.py index b2dbab3d911bc..6215e29b51a17 100644 --- a/mypyc/codegen/emitfunc.py +++ b/mypyc/codegen/emitfunc.py @@ -292,17 +292,17 @@ def visit_get_attr(self, op: GetAttr) -> None: # Otherwise, use direct or offset struct access. attr_expr = self.get_attr_expr(obj, op, decl_cl) self.emitter.emit_line('{} = {};'.format(dest, attr_expr)) + self.emitter.emit_undefined_attr_check( + attr_rtype, attr_expr, '==', unlikely=True + ) + exc_class = 'PyExc_AttributeError' + self.emitter.emit_line( + 'PyErr_SetString({}, "attribute {} of {} undefined");'.format( + exc_class, repr(op.attr), repr(cl.name))) if attr_rtype.is_refcounted: - self.emitter.emit_undefined_attr_check( - attr_rtype, attr_expr, '==', unlikely=True - ) - exc_class = 'PyExc_AttributeError' - self.emitter.emit_lines( - 'PyErr_SetString({}, "attribute {} of {} undefined");'.format( - exc_class, repr(op.attr), repr(cl.name)), - '} else {') + self.emitter.emit_line('} else {') self.emitter.emit_inc_ref(attr_expr, attr_rtype) - self.emitter.emit_line('}') + self.emitter.emit_line('}') def visit_set_attr(self, op: SetAttr) -> None: dest = self.reg(op) diff --git a/mypyc/test-data/run-classes.test b/mypyc/test-data/run-classes.test index e2beca1bafc63..83838e1887625 100644 --- a/mypyc/test-data/run-classes.test +++ b/mypyc/test-data/run-classes.test @@ -336,6 +336,7 @@ class C: b: bool c: C d: object + e: int def setattrs(o: C, a: List[int], b: bool, c: C) -> None: o.a = a @@ -346,6 +347,8 @@ def getattrs(o: C) -> Tuple[List[int], bool, C]: return o.a, o.b, o.c [file driver.py] from native import C, setattrs, getattrs +from testutil import assertRaises + c1 = C() c2 = C() aa = [2] @@ -359,6 +362,18 @@ o = object() c1.d = o assert c1.d is o +c3 = C() +with assertRaises(AttributeError, "attribute 'a' of 'C' undefined"): + c3.a +with assertRaises(AttributeError, "attribute 'b' of 'C' undefined"): + c3.b +with assertRaises(AttributeError, "attribute 'c' of 'C' undefined"): + c3.c +with assertRaises(AttributeError, "attribute 'd' of 'C' undefined"): + c3.d +with assertRaises(AttributeError, "attribute 'e' of 'C' undefined"): + c3.e + [case testInitMethodWithMissingNoneReturnAnnotation] class C: def __init__(self): diff --git a/mypyc/test/test_emitfunc.py b/mypyc/test/test_emitfunc.py index 60c62d2b4b4c5..c18cd37b17072 100644 --- a/mypyc/test/test_emitfunc.py +++ b/mypyc/test/test_emitfunc.py @@ -288,6 +288,15 @@ def test_get_attr(self) -> None: } """) + def test_get_attr_non_refcounted(self) -> None: + self.assert_emit( + GetAttr(self.r, 'x', 1), + """cpy_r_r0 = ((mod___AObject *)cpy_r_r)->_x; + if (unlikely(((mod___AObject *)cpy_r_r)->_x == 2)) { + PyErr_SetString(PyExc_AttributeError, "attribute 'x' of 'A' undefined"); + } + """) + def test_set_attr(self) -> None: self.assert_emit( SetAttr(self.r, 'y', self.m, 1), From 0bc040eddfd90d5c0e7a22f00cbaa51d209ebbef Mon Sep 17 00:00:00 2001 From: Chris Keefe <39198770+ChrisKeefe@users.noreply.github.com> Date: Tue, 11 Jan 2022 17:07:03 -0700 Subject: [PATCH 057/377] DOC: Fixes Intelligent indexing example (#11973) --- docs/source/literal_types.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/literal_types.rst b/docs/source/literal_types.rst index b1669d01062a8..da62b31526c96 100644 --- a/docs/source/literal_types.rst +++ b/docs/source/literal_types.rst @@ -186,13 +186,13 @@ corresponding to some particular index, we can use Literal types like so: # But what if we want the index to be a variable? Normally mypy won't # know exactly what the index is and so will return a less precise type: - int_index = 1 + int_index = 0 reveal_type(tup[int_index]) # Revealed type is "Union[str, float]" # But if we use either Literal types or a Final int, we can gain back # the precision we originally had: - lit_index: Literal[1] = 1 - fin_index: Final = 1 + lit_index: Literal[0] = 0 + fin_index: Final = 0 reveal_type(tup[lit_index]) # Revealed type is "str" reveal_type(tup[fin_index]) # Revealed type is "str" From fa16759dc37fa313a2a607974d51d161c8ba5ea6 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Tue, 11 Jan 2022 20:29:05 -0800 Subject: [PATCH 058/377] Ignore more exceptions in stubtest (#11946) See python/typeshed#6801. --- mypy/stubtest.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/mypy/stubtest.py b/mypy/stubtest.py index 0a05cf2104099..cb005c4bd52c2 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -269,11 +269,14 @@ def verify_typeinfo( mangled_entry = "_{}{}".format(stub.name, entry) stub_to_verify = next((t.names[entry].node for t in stub.mro if entry in t.names), MISSING) assert stub_to_verify is not None - yield from verify( - stub_to_verify, - getattr(runtime, mangled_entry, MISSING), - object_path + [entry], - ) + try: + runtime_attr = getattr(runtime, mangled_entry, MISSING) + except Exception: + # Catch all exceptions in case the runtime raises an unexpected exception + # from __getattr__ or similar. + pass + else: + yield from verify(stub_to_verify, runtime_attr, object_path + [entry]) def _verify_static_class_methods( From a0234fabd0064d235f0700d62c3a7999874b8356 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Thu, 13 Jan 2022 10:02:29 +0300 Subject: [PATCH 059/377] Add 3.11-dev to CI (#11677) --- .github/workflows/test.yml | 40 ++++++++++++++++++-------------------- test-requirements.txt | 2 +- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3081c15594cbe..7f5c89c430da5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -113,24 +113,22 @@ jobs: - name: Test run: tox -e ${{ matrix.toxenv }} --skip-pkg-install -- ${{ matrix.tox_extra_args }} -# TODO: uncomment this when 3.11-dev is available -# python-nightly: -# runs-on: ubuntu-latest -# name: Test suite with Python nightly -# steps: -# - uses: actions/checkout@v2 -# - uses: actions/setup-python@v2 -# with: -# python-version: '3.11-dev' -# - name: Install tox -# run: | -# pip install -U pip==21.2.3 setuptools -# pip install --upgrade 'setuptools!=50' virtualenv==20.4.7 tox==3.20.1 -# - name: Setup tox environment -# run: tox -e py --notest -# - name: Test -# run: tox -e py --skip-pkg-install -- "-n 2" -# continue-on-error: true -# - name: Mark as a success -# run: exit 0 - + python-nightly: + runs-on: ubuntu-latest + name: Test suite with Python nightly + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: '3.11-dev' + - name: Install tox + run: | + pip install -U pip==21.2.3 setuptools + pip install --upgrade 'setuptools!=50' virtualenv==20.4.7 tox==3.20.1 + - name: Setup tox environment + run: tox -e py --notest + - name: Test + run: tox -e py --skip-pkg-install -- "-n 2" + continue-on-error: true + - name: Mark as a success + run: exit 0 diff --git a/test-requirements.txt b/test-requirements.txt index c5db79ada8161..a9fcd412f175b 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -4,7 +4,7 @@ attrs>=18.0 flake8==3.9.2 flake8-bugbear flake8-pyi>=20.5 -lxml>=4.4.0 +lxml>=4.4.0; python_version<'3.11' psutil>=4.0 pytest>=6.2.0,<7.0.0 pytest-xdist>=1.34.0,<2.0.0 From 17850b3bd77ae9efb5d21f656c4e4e05ac48d894 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Fri, 14 Jan 2022 17:15:48 +0300 Subject: [PATCH 060/377] Microrefactoring: `py_version <= 2` should be `py_version == 2` (#11986) --- mypy/checkexpr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 391c7a59d60be..b05f9168ee129 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -2205,7 +2205,7 @@ def visit_op_expr(self, e: OpExpr) -> Type: return self.strfrm_checker.check_str_interpolation(e.left, e.right) if isinstance(e.left, StrExpr): return self.strfrm_checker.check_str_interpolation(e.left, e.right) - elif pyversion[0] <= 2: + elif pyversion[0] == 2: if isinstance(e.left, (StrExpr, BytesExpr, UnicodeExpr)): return self.strfrm_checker.check_str_interpolation(e.left, e.right) left_type = self.accept(e.left) From 2bfa3b48e671f461b9d9ad9e49dcb83c31bade37 Mon Sep 17 00:00:00 2001 From: Max Rossmannek Date: Sat, 15 Jan 2022 21:18:54 +0100 Subject: [PATCH 061/377] Fix #11971 (#11972) Allows PlaceholderNode objects before raising an error for the attempted reuse of a member name inside an Enum. --- mypy/semanal.py | 2 +- test-data/unit/check-enum.test | 2 +- test-data/unit/pythoneval.test | 12 ++++++++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index fbef499dd91da..6beb967b68058 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -2871,7 +2871,7 @@ def analyze_name_lvalue(self, outer = self.is_global_or_nonlocal(name) if kind == MDEF and isinstance(self.type, TypeInfo) and self.type.is_enum: # Special case: we need to be sure that `Enum` keys are unique. - if existing: + if existing is not None and not isinstance(existing.node, PlaceholderNode): self.fail('Attempted to reuse member name "{}" in Enum definition "{}"'.format( name, self.type.name, ), lvalue) diff --git a/test-data/unit/check-enum.test b/test-data/unit/check-enum.test index 8d3620b1b71e4..aac97c6c69af2 100644 --- a/test-data/unit/check-enum.test +++ b/test-data/unit/check-enum.test @@ -1810,4 +1810,4 @@ reveal_type(A.str.value) # N: Revealed type is "Literal['foo']?" reveal_type(A.int.value) # N: Revealed type is "Literal[1]?" reveal_type(A.bool.value) # N: Revealed type is "Literal[False]?" reveal_type(A.tuple.value) # N: Revealed type is "Tuple[Literal[1]?]" -[builtins fixtures/tuple.pyi] \ No newline at end of file +[builtins fixtures/tuple.pyi] diff --git a/test-data/unit/pythoneval.test b/test-data/unit/pythoneval.test index 9bf511e1aba3c..ab1593dac7541 100644 --- a/test-data/unit/pythoneval.test +++ b/test-data/unit/pythoneval.test @@ -1573,3 +1573,15 @@ x: OrderedDict[str, str] = OrderedDict({}) reveal_type(x) # Revealed type is "collections.OrderedDict[builtins.str, builtins.int]" [out] _testTypingExtensionsOrderedDictAlias.py:3: note: Revealed type is "collections.OrderedDict[builtins.str, builtins.str]" + +[case testEnumValueWithPlaceholderNodeType] +# https://github.com/python/mypy/issues/11971 +from enum import Enum +from typing import Callable, Dict +class Foo(Enum): + Bar: Foo = Callable[[str], None] + Baz: Foo = Callable[[Dict[str, "Missing"]], None] +[out] +_testEnumValueWithPlaceholderNodeType.py:5: error: Incompatible types in assignment (expression has type "object", variable has type "Foo") +_testEnumValueWithPlaceholderNodeType.py:6: error: Incompatible types in assignment (expression has type "object", variable has type "Foo") +_testEnumValueWithPlaceholderNodeType.py:6: error: Name "Missing" is not defined From 9943444c777d829cd1595d043baa883d9407971d Mon Sep 17 00:00:00 2001 From: Brian Phillips <56549508+bphillips-exos@users.noreply.github.com> Date: Sat, 15 Jan 2022 18:13:34 -0500 Subject: [PATCH 062/377] Add no-overload-impl error code (#11944) --- docs/source/error_code_list.rst | 22 ++++++++++++++++++++++ mypy/errorcodes.py | 5 +++++ mypy/semanal.py | 2 +- test-data/unit/check-errorcodes.test | 11 +++++++++++ 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/docs/source/error_code_list.rst b/docs/source/error_code_list.rst index 852913ce79bb9..e655cae3c45df 100644 --- a/docs/source/error_code_list.rst +++ b/docs/source/error_code_list.rst @@ -657,6 +657,28 @@ consistently when using the call-based syntax. Example: # Error: First argument to namedtuple() should be "Point2D", not "Point" Point2D = NamedTuple("Point", [("x", int), ("y", int)]) +Check that overloaded functions have an implementation [no-overload-impl] +------------------------------------------------------------------------- + +Overloaded functions outside of stub files must be followed by a non overloaded +implementation. + +.. code-block:: python + + from typing import overload + + @overload + def func(value: int) -> int: + ... + + @overload + def func(value: str) -> str: + ... + + # presence of required function below is checked + def func(value): + pass # actual implementation + Report syntax errors [syntax] ----------------------------- diff --git a/mypy/errorcodes.py b/mypy/errorcodes.py index 2a07bbb8597b3..ec9d8895aea6f 100644 --- a/mypy/errorcodes.py +++ b/mypy/errorcodes.py @@ -133,6 +133,11 @@ def __str__(self) -> str: NAME_MATCH: Final = ErrorCode( "name-match", "Check that type definition has consistent naming", "General" ) +NO_OVERLOAD_IMPL: Final = ErrorCode( + "no-overload-impl", + "Check that overloaded functions outside stub files have an implementation", + "General", +) # Syntax errors are often blocking. diff --git a/mypy/semanal.py b/mypy/semanal.py index 6beb967b68058..22d6b2e571bad 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -880,7 +880,7 @@ def handle_missing_overload_implementation(self, defn: OverloadedFuncDef) -> Non else: self.fail( "An overloaded function outside a stub file must have an implementation", - defn) + defn, code=codes.NO_OVERLOAD_IMPL) def process_final_in_overload(self, defn: OverloadedFuncDef) -> None: """Detect the @final status of an overloaded function (and perform checks).""" diff --git a/test-data/unit/check-errorcodes.test b/test-data/unit/check-errorcodes.test index 2f84ee1f4c6e5..568d3a9522f92 100644 --- a/test-data/unit/check-errorcodes.test +++ b/test-data/unit/check-errorcodes.test @@ -898,6 +898,17 @@ if lst: pass [builtins fixtures/list.pyi] +[case testNoOverloadImplementation] +from typing import overload + +@overload # E: An overloaded function outside a stub file must have an implementation [no-overload-impl] +def f(arg: int) -> int: + ... + +@overload +def f(arg: str) -> str: + ... + [case testSliceInDict39] # flags: --python-version 3.9 --show-column-numbers from typing import Dict From 5f39f5db4c936e74a5b32fe690402eb9235493d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustav=20Gr=C3=A4nsbo?= Date: Sun, 16 Jan 2022 20:41:28 +0100 Subject: [PATCH 063/377] Clarify stub-only packages need to be installed (#9958) * Clarify stub-only packages need to be installed * Add link to PEP 561 --- docs/source/running_mypy.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/running_mypy.rst b/docs/source/running_mypy.rst index d1c701e27e5ad..070e4556c04e6 100644 --- a/docs/source/running_mypy.rst +++ b/docs/source/running_mypy.rst @@ -491,7 +491,7 @@ This is computed from the following items: .. note:: - You cannot point to a :pep:`561` package via the ``MYPYPATH``, it must be + You cannot point to a stub-only package (:pep:`561`) via the ``MYPYPATH``, it must be installed (see :ref:`PEP 561 support `) Second, mypy searches for stub files in addition to regular Python files From 1aa9cf91c15706bff00f5d9a953481b36fcf9b9a Mon Sep 17 00:00:00 2001 From: joey-laminar <92668266+joey-laminar@users.noreply.github.com> Date: Mon, 17 Jan 2022 17:46:45 +0200 Subject: [PATCH 064/377] Fix __init__ in Dataclasses inheriting from Any (#11966) Dataclasses that inherit from Any (actually another type that we don't know) should assume an (almost) arbitrary constructor. Fixes #11921 --- mypy/plugins/dataclasses.py | 28 ++++++++++++++++++++++----- test-data/unit/check-dataclasses.test | 14 ++++++++++++++ 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/mypy/plugins/dataclasses.py b/mypy/plugins/dataclasses.py index e3daec58922f5..6894959bd47b2 100644 --- a/mypy/plugins/dataclasses.py +++ b/mypy/plugins/dataclasses.py @@ -4,9 +4,10 @@ from typing_extensions import Final from mypy.nodes import ( - ARG_OPT, ARG_NAMED, ARG_NAMED_OPT, ARG_POS, MDEF, Argument, AssignmentStmt, CallExpr, - Context, Expression, JsonDict, NameExpr, RefExpr, - SymbolTableNode, TempNode, TypeInfo, Var, TypeVarExpr, PlaceholderNode + ARG_OPT, ARG_NAMED, ARG_NAMED_OPT, ARG_POS, ARG_STAR, ARG_STAR2, MDEF, + Argument, AssignmentStmt, CallExpr, Context, Expression, JsonDict, + NameExpr, RefExpr, SymbolTableNode, TempNode, TypeInfo, Var, TypeVarExpr, + PlaceholderNode ) from mypy.plugin import ClassDefContext, SemanticAnalyzerPluginInterface from mypy.plugins.common import ( @@ -141,11 +142,28 @@ def transform(self) -> None: if (decorator_arguments['init'] and ('__init__' not in info.names or info.names['__init__'].plugin_generated) and attributes): + + args = [attr.to_argument() for attr in attributes if attr.is_in_init + and not self._is_kw_only_type(attr.type)] + + if info.fallback_to_any: + # Make positional args optional since we don't know their order. + # This will at least allow us to typecheck them if they are called + # as kwargs + for arg in args: + if arg.kind == ARG_POS: + arg.kind = ARG_OPT + + nameless_var = Var('') + args = [Argument(nameless_var, AnyType(TypeOfAny.explicit), None, ARG_STAR), + *args, + Argument(nameless_var, AnyType(TypeOfAny.explicit), None, ARG_STAR2), + ] + add_method( ctx, '__init__', - args=[attr.to_argument() for attr in attributes if attr.is_in_init - and not self._is_kw_only_type(attr.type)], + args=args, return_type=NoneType(), ) diff --git a/test-data/unit/check-dataclasses.test b/test-data/unit/check-dataclasses.test index 80e5f81e110fa..eed329bb59c7a 100644 --- a/test-data/unit/check-dataclasses.test +++ b/test-data/unit/check-dataclasses.test @@ -1522,3 +1522,17 @@ PublishedMessagesVar = dict[int, 'PublishedMessages'] class PublishedMessages: left: int [builtins fixtures/dataclasses.pyi] + +[case testDataclassesAnyInherit] +# flags: --python-version 3.7 +from dataclasses import dataclass +from typing import Any +B: Any +@dataclass +class A(B): + a: int + +A(a=1, b=2) +A(1) +A(a="foo") # E: Argument "a" to "A" has incompatible type "str"; expected "int" +[builtins fixtures/dataclasses.pyi] From 9b63751819d040fd78b8f37fac14e2fff6b927bc Mon Sep 17 00:00:00 2001 From: Adrian Freund Date: Tue, 18 Jan 2022 11:34:12 +0100 Subject: [PATCH 065/377] Support for python 3.10 match statement (#10191) --- mypy/checker.py | 285 ++++- mypy/checkexpr.py | 10 +- mypy/checkpattern.py | 683 ++++++++++ mypy/errorcodes.py | 3 + mypy/fastparse.py | 103 +- mypy/message_registry.py | 16 + mypy/messages.py | 2 +- mypy/nodes.py | 22 + mypy/patterns.py | 132 ++ mypy/plugins/common.py | 27 + mypy/plugins/dataclasses.py | 17 +- mypy/reachability.py | 41 +- mypy/renaming.py | 20 +- mypy/semanal.py | 60 +- mypy/semanal_namedtuple.py | 6 +- mypy/semanal_pass1.py | 15 +- mypy/strconv.py | 49 + mypy/subtypes.py | 2 +- mypy/test/helpers.py | 2 + mypy/test/testparse.py | 5 + mypy/test/testsemanal.py | 7 + mypy/traverser.py | 53 +- mypy/typeops.py | 2 +- mypy/visitor.py | 72 +- mypyc/irbuild/visitor.py | 6 +- test-data/unit/check-narrowing.test | 2 +- test-data/unit/check-python310.test | 1182 +++++++++++++++++- test-data/unit/deps.test | 1 + test-data/unit/fixtures/dict.pyi | 6 +- test-data/unit/fixtures/primitives.pyi | 18 +- test-data/unit/fixtures/typing-full.pyi | 4 + test-data/unit/lib-stub/collections.pyi | 4 +- test-data/unit/lib-stub/dataclasses.pyi | 1 - test-data/unit/lib-stub/types.pyi | 2 - test-data/unit/merge.test | 40 +- test-data/unit/parse-python310.test | 603 +++++++++ test-data/unit/semanal-errors-python310.test | 43 + test-data/unit/semanal-python310.test | 204 +++ test-requirements.txt | 3 +- 39 files changed, 3620 insertions(+), 133 deletions(-) create mode 100644 mypy/checkpattern.py create mode 100644 mypy/patterns.py create mode 100644 test-data/unit/parse-python310.test create mode 100644 test-data/unit/semanal-errors-python310.test create mode 100644 test-data/unit/semanal-python310.test diff --git a/mypy/checker.py b/mypy/checker.py index ce1859c02a201..6f8ab758cc943 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -2,11 +2,12 @@ import itertools import fnmatch +from collections import defaultdict from contextlib import contextmanager from typing import ( Any, Dict, Set, List, cast, Tuple, TypeVar, Union, Optional, NamedTuple, Iterator, - Iterable, Sequence, Mapping, Generic, AbstractSet, Callable + Iterable, Sequence, Mapping, Generic, AbstractSet, Callable, overload ) from typing_extensions import Final, TypeAlias as _TypeAlias @@ -25,8 +26,7 @@ Import, ImportFrom, ImportAll, ImportBase, TypeAlias, ARG_POS, ARG_STAR, LITERAL_TYPE, LDEF, MDEF, GDEF, CONTRAVARIANT, COVARIANT, INVARIANT, TypeVarExpr, AssignmentExpr, - is_final_node, - ARG_NAMED) + is_final_node, ARG_NAMED, MatchStmt) from mypy import nodes from mypy import operators from mypy.literals import literal, literal_hash, Key @@ -50,6 +50,7 @@ type_object_type, analyze_decorator_or_funcbase_access, ) +from mypy.checkpattern import PatternChecker from mypy.semanal_enum import ENUM_BASES, ENUM_SPECIAL_PROPS from mypy.typeops import ( map_type_from_supertype, bind_self, erase_to_bound, make_simplified_union, @@ -171,6 +172,8 @@ class TypeChecker(NodeVisitor[None], CheckerPluginInterface): # Helper for type checking expressions expr_checker: mypy.checkexpr.ExpressionChecker + pattern_checker: PatternChecker + tscope: Scope scope: "CheckerScope" # Stack of function return types @@ -235,6 +238,7 @@ def __init__(self, errors: Errors, modules: Dict[str, MypyFile], options: Option self.msg = MessageBuilder(errors, modules) self.plugin = plugin self.expr_checker = mypy.checkexpr.ExpressionChecker(self, self.msg, self.plugin) + self.pattern_checker = PatternChecker(self, self.msg, self.plugin) self.tscope = Scope() self.scope = CheckerScope(tree) self.binder = ConditionalTypeBinder() @@ -1434,6 +1438,19 @@ def check_setattr_method(self, typ: Type, context: Context) -> None: if not is_subtype(typ, method_type): self.msg.invalid_signature_for_special_method(typ, context, '__setattr__') + def check_match_args(self, var: Var, typ: Type, context: Context) -> None: + """Check that __match_args__ is final and contains literal strings""" + + if not var.is_final: + self.note("__match_args__ must be final for checking of match statements to work", + context, code=codes.LITERAL_REQ) + + typ = get_proper_type(typ) + if not isinstance(typ, TupleType) or \ + not all([is_string_literal(item) for item in typ.items]): + self.msg.note("__match_args__ must be a tuple containing string literals for checking " + "of match statements to work", context, code=codes.LITERAL_REQ) + def expand_typevars(self, defn: FuncItem, typ: CallableType) -> List[Tuple[FuncItem, CallableType]]: # TODO use generator @@ -2166,6 +2183,10 @@ def check_assignment(self, lvalue: Lvalue, rvalue: Expression, infer_lvalue_type else: self.check_getattr_method(signature, lvalue, name) + if name == '__match_args__' and inferred is not None: + typ = self.expr_checker.accept(rvalue) + self.check_match_args(inferred, typ, lvalue) + # Defer PartialType's super type checking. if (isinstance(lvalue, RefExpr) and not (isinstance(lvalue_type, PartialType) and lvalue_type.type is None)): @@ -3904,6 +3925,75 @@ def visit_continue_stmt(self, s: ContinueStmt) -> None: self.binder.handle_continue() return None + def visit_match_stmt(self, s: MatchStmt) -> None: + with self.binder.frame_context(can_skip=False, fall_through=0): + subject_type = get_proper_type(self.expr_checker.accept(s.subject)) + + if isinstance(subject_type, DeletedType): + self.msg.deleted_as_rvalue(subject_type, s) + + pattern_types = [self.pattern_checker.accept(p, subject_type) for p in s.patterns] + + type_maps: List[TypeMap] = [t.captures for t in pattern_types] + self.infer_variable_types_from_type_maps(type_maps) + + for pattern_type, g, b in zip(pattern_types, s.guards, s.bodies): + with self.binder.frame_context(can_skip=True, fall_through=2): + if b.is_unreachable or isinstance(get_proper_type(pattern_type.type), + UninhabitedType): + self.push_type_map(None) + else: + self.binder.put(s.subject, pattern_type.type) + self.push_type_map(pattern_type.captures) + if g is not None: + gt = get_proper_type(self.expr_checker.accept(g)) + + if isinstance(gt, DeletedType): + self.msg.deleted_as_rvalue(gt, s) + + if_map, _ = self.find_isinstance_check(g) + + self.push_type_map(if_map) + self.accept(b) + + # This is needed due to a quirk in frame_context. Without it types will stay narrowed + # after the match. + with self.binder.frame_context(can_skip=False, fall_through=2): + pass + + def infer_variable_types_from_type_maps(self, type_maps: List[TypeMap]) -> None: + all_captures: Dict[Var, List[Tuple[NameExpr, Type]]] = defaultdict(list) + for tm in type_maps: + if tm is not None: + for expr, typ in tm.items(): + if isinstance(expr, NameExpr): + node = expr.node + assert isinstance(node, Var) + all_captures[node].append((expr, typ)) + + for var, captures in all_captures.items(): + conflict = False + types: List[Type] = [] + for expr, typ in captures: + types.append(typ) + + previous_type, _, inferred = self.check_lvalue(expr) + if previous_type is not None: + conflict = True + self.check_subtype(typ, previous_type, expr, + msg=message_registry.INCOMPATIBLE_TYPES_IN_CAPTURE, + subtype_label="pattern captures type", + supertype_label="variable has type") + for type_map in type_maps: + if type_map is not None and expr in type_map: + del type_map[expr] + + if not conflict: + new_type = UnionType.make_union(types) + # Infer the union type at the first occurrence + first_occurrence, _ = captures[0] + self.infer_variable_type(var, first_occurrence, new_type, first_occurrence) + def make_fake_typeinfo(self, curr_module_fullname: str, class_gen_name: str, @@ -4268,11 +4358,14 @@ def is_type_call(expr: CallExpr) -> bool: if_maps: List[TypeMap] = [] else_maps: List[TypeMap] = [] for expr in exprs_in_type_calls: - current_if_map, current_else_map = self.conditional_type_map_with_intersection( - expr, + current_if_type, current_else_type = self.conditional_types_with_intersection( type_map[expr], - type_being_compared + type_being_compared, + expr ) + current_if_map, current_else_map = conditional_types_to_typemaps(expr, + current_if_type, + current_else_type) if_maps.append(current_if_map) else_maps.append(current_else_map) @@ -4328,10 +4421,13 @@ def find_isinstance_check_helper(self, node: Expression) -> Tuple[TypeMap, TypeM if len(node.args) != 2: # the error will be reported elsewhere return {}, {} if literal(expr) == LITERAL_TYPE: - return self.conditional_type_map_with_intersection( + return conditional_types_to_typemaps( expr, - type_map[expr], - get_isinstance_type(node.args[1], type_map), + *self.conditional_types_with_intersection( + type_map[expr], + get_isinstance_type(node.args[1], type_map), + expr + ) ) elif refers_to_fullname(node.callee, 'builtins.issubclass'): if len(node.args) != 2: # the error will be reported elsewhere @@ -4849,10 +4945,11 @@ def refine_identity_comparison_expression(self, if sum_type_name is not None: expr_type = try_expanding_sum_type_to_union(expr_type, sum_type_name) - # We intentionally use 'conditional_type_map' directly here instead of - # 'self.conditional_type_map_with_intersection': we only compute ad-hoc + # We intentionally use 'conditional_types' directly here instead of + # 'self.conditional_types_with_intersection': we only compute ad-hoc # intersections when working with pure instances. - partial_type_maps.append(conditional_type_map(expr, expr_type, target_type)) + types = conditional_types(expr_type, target_type) + partial_type_maps.append(conditional_types_to_typemaps(expr, *types)) return reduce_conditional_maps(partial_type_maps) @@ -5279,54 +5376,72 @@ def infer_issubclass_maps(self, node: CallExpr, # Any other object whose type we don't know precisely # for example, Any or a custom metaclass. return {}, {} # unknown type - yes_map, no_map = self.conditional_type_map_with_intersection(expr, vartype, type) + yes_type, no_type = self.conditional_types_with_intersection(vartype, type, expr) + yes_map, no_map = conditional_types_to_typemaps(expr, yes_type, no_type) yes_map, no_map = map(convert_to_typetype, (yes_map, no_map)) return yes_map, no_map - def conditional_type_map_with_intersection(self, - expr: Expression, - expr_type: Type, - type_ranges: Optional[List[TypeRange]], - ) -> Tuple[TypeMap, TypeMap]: - # For some reason, doing "yes_map, no_map = conditional_type_maps(...)" + @overload + def conditional_types_with_intersection(self, + expr_type: Type, + type_ranges: Optional[List[TypeRange]], + ctx: Context, + default: None = None + ) -> Tuple[Optional[Type], Optional[Type]]: ... + + @overload + def conditional_types_with_intersection(self, + expr_type: Type, + type_ranges: Optional[List[TypeRange]], + ctx: Context, + default: Type + ) -> Tuple[Type, Type]: ... + + def conditional_types_with_intersection(self, + expr_type: Type, + type_ranges: Optional[List[TypeRange]], + ctx: Context, + default: Optional[Type] = None + ) -> Tuple[Optional[Type], Optional[Type]]: + initial_types = conditional_types(expr_type, type_ranges, default) + # For some reason, doing "yes_map, no_map = conditional_types_to_typemaps(...)" # doesn't work: mypyc will decide that 'yes_map' is of type None if we try. - initial_maps = conditional_type_map(expr, expr_type, type_ranges) - yes_map: TypeMap = initial_maps[0] - no_map: TypeMap = initial_maps[1] + yes_type: Optional[Type] = initial_types[0] + no_type: Optional[Type] = initial_types[1] - if yes_map is not None or type_ranges is None: - return yes_map, no_map + if not isinstance(get_proper_type(yes_type), UninhabitedType) or type_ranges is None: + return yes_type, no_type - # If conditions_type_map was unable to successfully narrow the expr_type + # If conditional_types was unable to successfully narrow the expr_type # using the type_ranges and concluded if-branch is unreachable, we try # computing it again using a different algorithm that tries to generate # an ad-hoc intersection between the expr_type and the type_ranges. - expr_type = get_proper_type(expr_type) - if isinstance(expr_type, UnionType): - possible_expr_types = get_proper_types(expr_type.relevant_items()) + proper_type = get_proper_type(expr_type) + if isinstance(proper_type, UnionType): + possible_expr_types = get_proper_types(proper_type.relevant_items()) else: - possible_expr_types = [expr_type] + possible_expr_types = [proper_type] possible_target_types = [] for tr in type_ranges: item = get_proper_type(tr.item) if not isinstance(item, Instance) or tr.is_upper_bound: - return yes_map, no_map + return yes_type, no_type possible_target_types.append(item) out = [] for v in possible_expr_types: if not isinstance(v, Instance): - return yes_map, no_map + return yes_type, no_type for t in possible_target_types: - intersection = self.intersect_instances((v, t), expr) + intersection = self.intersect_instances((v, t), ctx) if intersection is None: continue out.append(intersection) if len(out) == 0: - return None, {} + return UninhabitedType(), expr_type new_yes_type = make_simplified_union(out) - return {expr: new_yes_type}, {} + return new_yes_type, expr_type def is_writable_attribute(self, node: Node) -> bool: """Check if an attribute is writable""" @@ -5339,48 +5454,75 @@ def is_writable_attribute(self, node: Node) -> bool: return False -def conditional_type_map(expr: Expression, - current_type: Optional[Type], - proposed_type_ranges: Optional[List[TypeRange]], - ) -> Tuple[TypeMap, TypeMap]: - """Takes in an expression, the current type of the expression, and a - proposed type of that expression. +@overload +def conditional_types(current_type: Type, + proposed_type_ranges: Optional[List[TypeRange]], + default: None = None + ) -> Tuple[Optional[Type], Optional[Type]]: ... + + +@overload +def conditional_types(current_type: Type, + proposed_type_ranges: Optional[List[TypeRange]], + default: Type + ) -> Tuple[Type, Type]: ... - Returns a 2-tuple: The first element is a map from the expression to - the proposed type, if the expression can be the proposed type. The - second element is a map from the expression to the type it would hold - if it was not the proposed type, if any. None means bot, {} means top""" + +def conditional_types(current_type: Type, + proposed_type_ranges: Optional[List[TypeRange]], + default: Optional[Type] = None + ) -> Tuple[Optional[Type], Optional[Type]]: + """Takes in the current type and a proposed type of an expression. + + Returns a 2-tuple: The first element is the proposed type, if the expression + can be the proposed type. The second element is the type it would hold + if it was not the proposed type, if any. UninhabitedType means unreachable. + None means no new information can be inferred. If default is set it is returned + instead.""" if proposed_type_ranges: proposed_items = [type_range.item for type_range in proposed_type_ranges] proposed_type = make_simplified_union(proposed_items) - if current_type: - if isinstance(proposed_type, AnyType): - # We don't really know much about the proposed type, so we shouldn't - # attempt to narrow anything. Instead, we broaden the expr to Any to - # avoid false positives - return {expr: proposed_type}, {} - elif (not any(type_range.is_upper_bound for type_range in proposed_type_ranges) - and is_proper_subtype(current_type, proposed_type)): - # Expression is always of one of the types in proposed_type_ranges - return {}, None - elif not is_overlapping_types(current_type, proposed_type, - prohibit_none_typevar_overlap=True): - # Expression is never of any type in proposed_type_ranges - return None, {} - else: - # we can only restrict when the type is precise, not bounded - proposed_precise_type = UnionType.make_union([ - type_range.item - for type_range in proposed_type_ranges - if not type_range.is_upper_bound - ]) - remaining_type = restrict_subtype_away(current_type, proposed_precise_type) - return {expr: proposed_type}, {expr: remaining_type} + if isinstance(proposed_type, AnyType): + # We don't really know much about the proposed type, so we shouldn't + # attempt to narrow anything. Instead, we broaden the expr to Any to + # avoid false positives + return proposed_type, default + elif (not any(type_range.is_upper_bound for type_range in proposed_type_ranges) + and is_proper_subtype(current_type, proposed_type)): + # Expression is always of one of the types in proposed_type_ranges + return default, UninhabitedType() + elif not is_overlapping_types(current_type, proposed_type, + prohibit_none_typevar_overlap=True): + # Expression is never of any type in proposed_type_ranges + return UninhabitedType(), default else: - return {expr: proposed_type}, {} + # we can only restrict when the type is precise, not bounded + proposed_precise_type = UnionType.make_union([type_range.item + for type_range in proposed_type_ranges + if not type_range.is_upper_bound]) + remaining_type = restrict_subtype_away(current_type, proposed_precise_type) + return proposed_type, remaining_type else: # An isinstance check, but we don't understand the type - return {}, {} + return current_type, default + + +def conditional_types_to_typemaps(expr: Expression, + yes_type: Optional[Type], + no_type: Optional[Type] + ) -> Tuple[TypeMap, TypeMap]: + maps: List[TypeMap] = [] + for typ in (yes_type, no_type): + proper_type = get_proper_type(typ) + if isinstance(proper_type, UninhabitedType): + maps.append(None) + elif proper_type is None: + maps.append({}) + else: + assert typ is not None + maps.append({expr: typ}) + + return cast(Tuple[TypeMap, TypeMap], tuple(maps)) def gen_unique_name(base: str, table: SymbolTable) -> str: @@ -6190,6 +6332,11 @@ def is_private(node_name: str) -> bool: return node_name.startswith('__') and not node_name.endswith('__') +def is_string_literal(typ: Type) -> bool: + strs = try_getting_str_literals_from_type(typ) + return strs is not None and len(strs) == 1 + + def has_bool_item(typ: ProperType) -> bool: """Return True if type is 'bool' or a union with a 'bool' item.""" if is_named_instance(typ, 'builtins.bool'): diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index b05f9168ee129..66d8fa4b76960 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -3077,7 +3077,11 @@ def nonliteral_tuple_index_helper(self, left_type: TupleType, index: Expression) else: return union - def visit_typeddict_index_expr(self, td_type: TypedDictType, index: Expression) -> Type: + def visit_typeddict_index_expr(self, td_type: TypedDictType, + index: Expression, + local_errors: Optional[MessageBuilder] = None + ) -> Type: + local_errors = local_errors or self.msg if isinstance(index, (StrExpr, UnicodeExpr)): key_names = [index.value] else: @@ -3097,14 +3101,14 @@ def visit_typeddict_index_expr(self, td_type: TypedDictType, index: Expression) and key_type.fallback.type.fullname != 'builtins.bytes'): key_names.append(key_type.value) else: - self.msg.typeddict_key_must_be_string_literal(td_type, index) + local_errors.typeddict_key_must_be_string_literal(td_type, index) return AnyType(TypeOfAny.from_error) value_types = [] for key_name in key_names: value_type = td_type.items.get(key_name) if value_type is None: - self.msg.typeddict_key_not_found(td_type, key_name, index) + local_errors.typeddict_key_not_found(td_type, key_name, index) return AnyType(TypeOfAny.from_error) else: value_types.append(value_type) diff --git a/mypy/checkpattern.py b/mypy/checkpattern.py new file mode 100644 index 0000000000000..2c40e856be885 --- /dev/null +++ b/mypy/checkpattern.py @@ -0,0 +1,683 @@ +"""Pattern checker. This file is conceptually part of TypeChecker.""" +from collections import defaultdict +from typing import List, Optional, Tuple, Dict, NamedTuple, Set, Union +from typing_extensions import Final + +import mypy.checker +from mypy.checkmember import analyze_member_access +from mypy.expandtype import expand_type_by_instance +from mypy.join import join_types +from mypy.literals import literal_hash +from mypy.maptype import map_instance_to_supertype +from mypy.meet import narrow_declared_type +from mypy import message_registry +from mypy.messages import MessageBuilder +from mypy.nodes import Expression, ARG_POS, TypeAlias, TypeInfo, Var, NameExpr +from mypy.patterns import ( + Pattern, AsPattern, OrPattern, ValuePattern, SequencePattern, StarredPattern, MappingPattern, + ClassPattern, SingletonPattern +) +from mypy.plugin import Plugin +from mypy.subtypes import is_subtype +from mypy.typeops import try_getting_str_literals_from_type, make_simplified_union +from mypy.types import ( + ProperType, AnyType, TypeOfAny, Instance, Type, UninhabitedType, get_proper_type, + TypedDictType, TupleType, NoneType, UnionType +) +from mypy.typevars import fill_typevars +from mypy.visitor import PatternVisitor + +self_match_type_names: Final = [ + "builtins.bool", + "builtins.bytearray", + "builtins.bytes", + "builtins.dict", + "builtins.float", + "builtins.frozenset", + "builtins.int", + "builtins.list", + "builtins.set", + "builtins.str", + "builtins.tuple", +] + +non_sequence_match_type_names: Final = [ + "builtins.str", + "builtins.bytes", + "builtins.bytearray" +] + + +# For every Pattern a PatternType can be calculated. This requires recursively calculating +# the PatternTypes of the sub-patterns first. +# Using the data in the PatternType the match subject and captured names can be narrowed/inferred. +PatternType = NamedTuple( + 'PatternType', + [ + ('type', Type), # The type the match subject can be narrowed to + ('rest_type', Type), # For exhaustiveness checking. Not used yet + ('captures', Dict[Expression, Type]), # The variables captured by the pattern + ]) + + +class PatternChecker(PatternVisitor[PatternType]): + """Pattern checker. + + This class checks if a pattern can match a type, what the type can be narrowed to, and what + type capture patterns should be inferred as. + """ + + # Some services are provided by a TypeChecker instance. + chk: 'mypy.checker.TypeChecker' + # This is shared with TypeChecker, but stored also here for convenience. + msg: MessageBuilder + # Currently unused + plugin: Plugin + # The expression being matched against the pattern + subject: Expression + + subject_type: Type + # Type of the subject to check the (sub)pattern against + type_context: List[Type] + # Types that match against self instead of their __match_args__ if used as a class pattern + # Filled in from self_match_type_names + self_match_types: List[Type] + # Types that are sequences, but don't match sequence patterns. Filled in from + # non_sequence_match_type_names + non_sequence_match_types: List[Type] + + def __init__(self, + chk: 'mypy.checker.TypeChecker', + msg: MessageBuilder, plugin: Plugin + ) -> None: + self.chk = chk + self.msg = msg + self.plugin = plugin + + self.type_context = [] + self.self_match_types = self.generate_types_from_names(self_match_type_names) + self.non_sequence_match_types = self.generate_types_from_names( + non_sequence_match_type_names + ) + + def accept(self, o: Pattern, type_context: Type) -> PatternType: + self.type_context.append(type_context) + result = o.accept(self) + self.type_context.pop() + + return result + + def visit_as_pattern(self, o: AsPattern) -> PatternType: + current_type = self.type_context[-1] + if o.pattern is not None: + pattern_type = self.accept(o.pattern, current_type) + typ, rest_type, type_map = pattern_type + else: + typ, rest_type, type_map = current_type, UninhabitedType(), {} + + if not is_uninhabited(typ) and o.name is not None: + typ, _ = self.chk.conditional_types_with_intersection(current_type, + [get_type_range(typ)], + o, + default=current_type) + if not is_uninhabited(typ): + type_map[o.name] = typ + + return PatternType(typ, rest_type, type_map) + + def visit_or_pattern(self, o: OrPattern) -> PatternType: + current_type = self.type_context[-1] + + # + # Check all the subpatterns + # + pattern_types = [] + for pattern in o.patterns: + pattern_type = self.accept(pattern, current_type) + pattern_types.append(pattern_type) + current_type = pattern_type.rest_type + + # + # Collect the final type + # + types = [] + for pattern_type in pattern_types: + if not is_uninhabited(pattern_type.type): + types.append(pattern_type.type) + + # + # Check the capture types + # + capture_types: Dict[Var, List[Tuple[Expression, Type]]] = defaultdict(list) + # Collect captures from the first subpattern + for expr, typ in pattern_types[0].captures.items(): + node = get_var(expr) + capture_types[node].append((expr, typ)) + + # Check if other subpatterns capture the same names + for i, pattern_type in enumerate(pattern_types[1:]): + vars = {get_var(expr) for expr, _ in pattern_type.captures.items()} + if capture_types.keys() != vars: + self.msg.fail(message_registry.OR_PATTERN_ALTERNATIVE_NAMES, o.patterns[i]) + for expr, typ in pattern_type.captures.items(): + node = get_var(expr) + capture_types[node].append((expr, typ)) + + captures: Dict[Expression, Type] = {} + for var, capture_list in capture_types.items(): + typ = UninhabitedType() + for _, other in capture_list: + typ = join_types(typ, other) + + captures[capture_list[0][0]] = typ + + union_type = make_simplified_union(types) + return PatternType(union_type, current_type, captures) + + def visit_value_pattern(self, o: ValuePattern) -> PatternType: + current_type = self.type_context[-1] + typ = self.chk.expr_checker.accept(o.expr) + narrowed_type, rest_type = self.chk.conditional_types_with_intersection( + current_type, + [get_type_range(typ)], + o, + default=current_type + ) + return PatternType(narrowed_type, rest_type, {}) + + def visit_singleton_pattern(self, o: SingletonPattern) -> PatternType: + current_type = self.type_context[-1] + value: Union[bool, None] = o.value + if isinstance(value, bool): + typ = self.chk.expr_checker.infer_literal_expr_type(value, "builtins.bool") + elif value is None: + typ = NoneType() + else: + assert False + + narrowed_type, rest_type = self.chk.conditional_types_with_intersection( + current_type, + [get_type_range(typ)], + o, + default=current_type + ) + return PatternType(narrowed_type, rest_type, {}) + + def visit_sequence_pattern(self, o: SequencePattern) -> PatternType: + # + # check for existence of a starred pattern + # + current_type = get_proper_type(self.type_context[-1]) + if not self.can_match_sequence(current_type): + return self.early_non_match() + star_positions = [i for i, p in enumerate(o.patterns) if isinstance(p, StarredPattern)] + star_position: Optional[int] = None + if len(star_positions) == 1: + star_position = star_positions[0] + elif len(star_positions) >= 2: + assert False, "Parser should prevent multiple starred patterns" + required_patterns = len(o.patterns) + if star_position is not None: + required_patterns -= 1 + + # + # get inner types of original type + # + if isinstance(current_type, TupleType): + inner_types = current_type.items + size_diff = len(inner_types) - required_patterns + if size_diff < 0: + return self.early_non_match() + elif size_diff > 0 and star_position is None: + return self.early_non_match() + else: + inner_type = self.get_sequence_type(current_type) + if inner_type is None: + inner_type = self.chk.named_type("builtins.object") + inner_types = [inner_type] * len(o.patterns) + + # + # match inner patterns + # + contracted_new_inner_types: List[Type] = [] + contracted_rest_inner_types: List[Type] = [] + captures: Dict[Expression, Type] = {} + + contracted_inner_types = self.contract_starred_pattern_types(inner_types, + star_position, + required_patterns) + can_match = True + for p, t in zip(o.patterns, contracted_inner_types): + pattern_type = self.accept(p, t) + typ, rest, type_map = pattern_type + if is_uninhabited(typ): + can_match = False + else: + contracted_new_inner_types.append(typ) + contracted_rest_inner_types.append(rest) + self.update_type_map(captures, type_map) + new_inner_types = self.expand_starred_pattern_types(contracted_new_inner_types, + star_position, + len(inner_types)) + + # + # Calculate new type + # + new_type: Type + rest_type: Type = current_type + if not can_match: + new_type = UninhabitedType() + elif isinstance(current_type, TupleType): + narrowed_inner_types = [] + inner_rest_types = [] + for inner_type, new_inner_type in zip(inner_types, new_inner_types): + narrowed_inner_type, inner_rest_type = \ + self.chk.conditional_types_with_intersection( + new_inner_type, + [get_type_range(inner_type)], + o, + default=new_inner_type + ) + narrowed_inner_types.append(narrowed_inner_type) + inner_rest_types.append(inner_rest_type) + if all(not is_uninhabited(typ) for typ in narrowed_inner_types): + new_type = TupleType(narrowed_inner_types, current_type.partial_fallback) + else: + new_type = UninhabitedType() + + if all(is_uninhabited(typ) for typ in inner_rest_types): + # All subpatterns always match, so we can apply negative narrowing + new_type, rest_type = self.chk.conditional_types_with_intersection( + current_type, [get_type_range(new_type)], o, default=current_type + ) + else: + new_inner_type = UninhabitedType() + for typ in new_inner_types: + new_inner_type = join_types(new_inner_type, typ) + new_type = self.construct_sequence_child(current_type, new_inner_type) + if not is_subtype(new_type, current_type): + new_type = current_type + return PatternType(new_type, rest_type, captures) + + def get_sequence_type(self, t: Type) -> Optional[Type]: + t = get_proper_type(t) + if isinstance(t, AnyType): + return AnyType(TypeOfAny.from_another_any, t) + if isinstance(t, UnionType): + items = [self.get_sequence_type(item) for item in t.items] + not_none_items = [item for item in items if item is not None] + if len(not_none_items) > 0: + return make_simplified_union(not_none_items) + else: + return None + + if self.chk.type_is_iterable(t) and isinstance(t, Instance): + return self.chk.iterable_item_type(t) + else: + return None + + def contract_starred_pattern_types(self, + types: List[Type], + star_pos: Optional[int], + num_patterns: int + ) -> List[Type]: + """ + Contracts a list of types in a sequence pattern depending on the position of a starred + capture pattern. + + For example if the sequence pattern [a, *b, c] is matched against types [bool, int, str, + bytes] the contracted types are [bool, Union[int, str], bytes]. + + If star_pos in None the types are returned unchanged. + """ + if star_pos is None: + return types + new_types = types[:star_pos] + star_length = len(types) - num_patterns + new_types.append(make_simplified_union(types[star_pos:star_pos+star_length])) + new_types += types[star_pos+star_length:] + + return new_types + + def expand_starred_pattern_types(self, + types: List[Type], + star_pos: Optional[int], + num_types: int + ) -> List[Type]: + """ + Undoes the contraction done by contract_starred_pattern_types. + + For example if the sequence pattern is [a, *b, c] and types [bool, int, str] are extended + to lenght 4 the result is [bool, int, int, str]. + """ + if star_pos is None: + return types + new_types = types[:star_pos] + star_length = num_types - len(types) + 1 + new_types += [types[star_pos]] * star_length + new_types += types[star_pos+1:] + + return new_types + + def visit_starred_pattern(self, o: StarredPattern) -> PatternType: + captures: Dict[Expression, Type] = {} + if o.capture is not None: + list_type = self.chk.named_generic_type('builtins.list', [self.type_context[-1]]) + captures[o.capture] = list_type + return PatternType(self.type_context[-1], UninhabitedType(), captures) + + def visit_mapping_pattern(self, o: MappingPattern) -> PatternType: + current_type = get_proper_type(self.type_context[-1]) + can_match = True + captures: Dict[Expression, Type] = {} + for key, value in zip(o.keys, o.values): + inner_type = self.get_mapping_item_type(o, current_type, key) + if inner_type is None: + can_match = False + inner_type = self.chk.named_type("builtins.object") + pattern_type = self.accept(value, inner_type) + if is_uninhabited(pattern_type.type): + can_match = False + else: + self.update_type_map(captures, pattern_type.captures) + + if o.rest is not None: + mapping = self.chk.named_type("typing.Mapping") + if is_subtype(current_type, mapping) and isinstance(current_type, Instance): + mapping_inst = map_instance_to_supertype(current_type, mapping.type) + dict_typeinfo = self.chk.lookup_typeinfo("builtins.dict") + dict_type = fill_typevars(dict_typeinfo) + rest_type = expand_type_by_instance(dict_type, mapping_inst) + else: + object_type = self.chk.named_type("builtins.object") + rest_type = self.chk.named_generic_type("builtins.dict", + [object_type, object_type]) + + captures[o.rest] = rest_type + + if can_match: + # We can't narrow the type here, as Mapping key is invariant. + new_type = self.type_context[-1] + else: + new_type = UninhabitedType() + return PatternType(new_type, current_type, captures) + + def get_mapping_item_type(self, + pattern: MappingPattern, + mapping_type: Type, + key: Expression + ) -> Optional[Type]: + local_errors = self.msg.clean_copy() + local_errors.disable_count = 0 + mapping_type = get_proper_type(mapping_type) + if isinstance(mapping_type, TypedDictType): + result: Optional[Type] = self.chk.expr_checker.visit_typeddict_index_expr( + mapping_type, key, local_errors=local_errors) + # If we can't determine the type statically fall back to treating it as a normal + # mapping + if local_errors.is_errors(): + local_errors = self.msg.clean_copy() + local_errors.disable_count = 0 + result = self.get_simple_mapping_item_type(pattern, + mapping_type, + key, + local_errors) + + if local_errors.is_errors(): + result = None + else: + result = self.get_simple_mapping_item_type(pattern, + mapping_type, + key, + local_errors) + return result + + def get_simple_mapping_item_type(self, + pattern: MappingPattern, + mapping_type: Type, + key: Expression, + local_errors: MessageBuilder + ) -> Type: + result, _ = self.chk.expr_checker.check_method_call_by_name('__getitem__', + mapping_type, + [key], + [ARG_POS], + pattern, + local_errors=local_errors) + return result + + def visit_class_pattern(self, o: ClassPattern) -> PatternType: + current_type = get_proper_type(self.type_context[-1]) + + # + # Check class type + # + type_info = o.class_ref.node + assert type_info is not None + if isinstance(type_info, TypeAlias) and not type_info.no_args: + self.msg.fail(message_registry.CLASS_PATTERN_GENERIC_TYPE_ALIAS, o) + return self.early_non_match() + if isinstance(type_info, TypeInfo): + any_type = AnyType(TypeOfAny.implementation_artifact) + typ: Type = Instance(type_info, [any_type] * len(type_info.defn.type_vars)) + elif isinstance(type_info, TypeAlias): + typ = type_info.target + else: + if isinstance(type_info, Var): + name = str(type_info.type) + else: + name = type_info.name + self.msg.fail(message_registry.CLASS_PATTERN_TYPE_REQUIRED.format(name), o.class_ref) + return self.early_non_match() + + new_type, rest_type = self.chk.conditional_types_with_intersection( + current_type, [get_type_range(typ)], o, default=current_type + ) + if is_uninhabited(new_type): + return self.early_non_match() + # TODO: Do I need this? + narrowed_type = narrow_declared_type(current_type, new_type) + + # + # Convert positional to keyword patterns + # + keyword_pairs: List[Tuple[Optional[str], Pattern]] = [] + match_arg_set: Set[str] = set() + + captures: Dict[Expression, Type] = {} + + if len(o.positionals) != 0: + if self.should_self_match(typ): + if len(o.positionals) > 1: + self.msg.fail(message_registry.CLASS_PATTERN_TOO_MANY_POSITIONAL_ARGS, o) + pattern_type = self.accept(o.positionals[0], narrowed_type) + if not is_uninhabited(pattern_type.type): + return PatternType(pattern_type.type, + join_types(rest_type, pattern_type.rest_type), + pattern_type.captures) + captures = pattern_type.captures + else: + local_errors = self.msg.clean_copy() + match_args_type = analyze_member_access("__match_args__", typ, o, + False, False, False, + local_errors, + original_type=typ, + chk=self.chk) + + if local_errors.is_errors(): + self.msg.fail(message_registry.MISSING_MATCH_ARGS.format(typ), o) + return self.early_non_match() + + proper_match_args_type = get_proper_type(match_args_type) + if isinstance(proper_match_args_type, TupleType): + match_arg_names = get_match_arg_names(proper_match_args_type) + + if len(o.positionals) > len(match_arg_names): + self.msg.fail(message_registry.CLASS_PATTERN_TOO_MANY_POSITIONAL_ARGS, o) + return self.early_non_match() + else: + match_arg_names = [None] * len(o.positionals) + + for arg_name, pos in zip(match_arg_names, o.positionals): + keyword_pairs.append((arg_name, pos)) + if arg_name is not None: + match_arg_set.add(arg_name) + + # + # Check for duplicate patterns + # + keyword_arg_set = set() + has_duplicates = False + for key, value in zip(o.keyword_keys, o.keyword_values): + keyword_pairs.append((key, value)) + if key in match_arg_set: + self.msg.fail( + message_registry.CLASS_PATTERN_KEYWORD_MATCHES_POSITIONAL.format(key), + value + ) + has_duplicates = True + elif key in keyword_arg_set: + self.msg.fail(message_registry.CLASS_PATTERN_DUPLICATE_KEYWORD_PATTERN.format(key), + value) + has_duplicates = True + keyword_arg_set.add(key) + + if has_duplicates: + return self.early_non_match() + + # + # Check keyword patterns + # + can_match = True + for keyword, pattern in keyword_pairs: + key_type: Optional[Type] = None + local_errors = self.msg.clean_copy() + if keyword is not None: + key_type = analyze_member_access(keyword, + narrowed_type, + pattern, + False, + False, + False, + local_errors, + original_type=new_type, + chk=self.chk) + else: + key_type = AnyType(TypeOfAny.from_error) + if local_errors.is_errors() or key_type is None: + key_type = AnyType(TypeOfAny.from_error) + self.msg.fail(message_registry.CLASS_PATTERN_UNKNOWN_KEYWORD.format(typ, keyword), + value) + + inner_type, inner_rest_type, inner_captures = self.accept(pattern, key_type) + if is_uninhabited(inner_type): + can_match = False + else: + self.update_type_map(captures, inner_captures) + if not is_uninhabited(inner_rest_type): + rest_type = current_type + + if not can_match: + new_type = UninhabitedType() + return PatternType(new_type, rest_type, captures) + + def should_self_match(self, typ: Type) -> bool: + typ = get_proper_type(typ) + if isinstance(typ, Instance) and typ.type.is_named_tuple: + return False + for other in self.self_match_types: + if is_subtype(typ, other): + return True + return False + + def can_match_sequence(self, typ: ProperType) -> bool: + if isinstance(typ, UnionType): + return any(self.can_match_sequence(get_proper_type(item)) for item in typ.items) + for other in self.non_sequence_match_types: + # We have to ignore promotions, as memoryview should match, but bytes, + # which it can be promoted to, shouldn't + if is_subtype(typ, other, ignore_promotions=True): + return False + sequence = self.chk.named_type("typing.Sequence") + # If the static type is more general than sequence the actual type could still match + return is_subtype(typ, sequence) or is_subtype(sequence, typ) + + def generate_types_from_names(self, type_names: List[str]) -> List[Type]: + types: List[Type] = [] + for name in type_names: + try: + types.append(self.chk.named_type(name)) + except KeyError as e: + # 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(self, + original_type_map: Dict[Expression, Type], + extra_type_map: Dict[Expression, Type] + ) -> None: + # Calculating this would not be needed if TypeMap directly used literal hashes instead of + # expressions, as suggested in the TODO above it's definition + already_captured = set(literal_hash(expr) for expr in original_type_map) + for expr, typ in extra_type_map.items(): + if literal_hash(expr) in already_captured: + node = get_var(expr) + self.msg.fail(message_registry.MULTIPLE_ASSIGNMENTS_IN_PATTERN.format(node.name), + expr) + else: + original_type_map[expr] = typ + + def construct_sequence_child(self, outer_type: Type, inner_type: Type) -> Type: + """ + If outer_type is a child class of typing.Sequence returns a new instance of + outer_type, that is a Sequence of inner_type. If outer_type is not a child class of + typing.Sequence just returns a Sequence of inner_type + + For example: + construct_sequence_child(List[int], str) = List[str] + """ + sequence = self.chk.named_generic_type("typing.Sequence", [inner_type]) + if is_subtype(outer_type, self.chk.named_type("typing.Sequence")): + proper_type = get_proper_type(outer_type) + assert isinstance(proper_type, Instance) + empty_type = fill_typevars(proper_type.type) + partial_type = expand_type_by_instance(empty_type, sequence) + return expand_type_by_instance(partial_type, proper_type) + else: + return sequence + + def early_non_match(self) -> PatternType: + return PatternType(UninhabitedType(), self.type_context[-1], {}) + + +def get_match_arg_names(typ: TupleType) -> List[Optional[str]]: + args: List[Optional[str]] = [] + for item in typ.items: + values = try_getting_str_literals_from_type(item) + if values is None or len(values) != 1: + args.append(None) + else: + args.append(values[0]) + return args + + +def get_var(expr: Expression) -> Var: + """ + Warning: this in only true for expressions captured by a match statement. + Don't call it from anywhere else + """ + assert isinstance(expr, NameExpr) + node = expr.node + assert isinstance(node, Var) + return node + + +def get_type_range(typ: Type) -> 'mypy.checker.TypeRange': + return mypy.checker.TypeRange(typ, is_upper_bound=False) + + +def is_uninhabited(typ: Type) -> bool: + return isinstance(get_proper_type(typ), UninhabitedType) diff --git a/mypy/errorcodes.py b/mypy/errorcodes.py index ec9d8895aea6f..ba716608ae569 100644 --- a/mypy/errorcodes.py +++ b/mypy/errorcodes.py @@ -94,6 +94,9 @@ def __str__(self) -> str: EXIT_RETURN: Final = ErrorCode( "exit-return", "Warn about too general return type for '__exit__'", "General" ) +LITERAL_REQ: Final = ErrorCode( + "literal-required", "Check that value is a literal", 'General' +) # These error codes aren't enabled by default. NO_UNTYPED_DEF: Final[ErrorCode] = ErrorCode( diff --git a/mypy/fastparse.py b/mypy/fastparse.py index f3dd1f0a8fefb..a5129fae1b743 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -8,6 +8,7 @@ from typing import ( Tuple, Union, TypeVar, Callable, Sequence, Optional, Any, Dict, cast, List ) + from typing_extensions import Final, Literal, overload from mypy.sharedparse import ( @@ -19,18 +20,22 @@ ClassDef, Decorator, Block, Var, OperatorAssignmentStmt, ExpressionStmt, AssignmentStmt, ReturnStmt, RaiseStmt, AssertStmt, DelStmt, BreakStmt, ContinueStmt, PassStmt, GlobalDecl, - WhileStmt, ForStmt, IfStmt, TryStmt, WithStmt, + WhileStmt, ForStmt, IfStmt, TryStmt, WithStmt, MatchStmt, TupleExpr, GeneratorExpr, ListComprehension, ListExpr, ConditionalExpr, DictExpr, SetExpr, NameExpr, IntExpr, StrExpr, BytesExpr, UnicodeExpr, FloatExpr, CallExpr, SuperExpr, MemberExpr, IndexExpr, SliceExpr, OpExpr, UnaryExpr, LambdaExpr, ComparisonExpr, AssignmentExpr, StarExpr, YieldFromExpr, NonlocalDecl, DictionaryComprehension, SetComprehension, ComplexExpr, EllipsisExpr, YieldExpr, Argument, - AwaitExpr, TempNode, Expression, Statement, + AwaitExpr, TempNode, RefExpr, Expression, Statement, ArgKind, ARG_POS, ARG_OPT, ARG_STAR, ARG_NAMED, ARG_NAMED_OPT, ARG_STAR2, check_arg_names, FakeInfo, ) +from mypy.patterns import ( + AsPattern, OrPattern, ValuePattern, SequencePattern, StarredPattern, MappingPattern, + ClassPattern, SingletonPattern +) from mypy.types import ( Type, CallableType, AnyType, UnboundType, TupleType, TypeList, EllipsisType, CallableArgument, TypeOfAny, Instance, RawExpressionType, ProperType, UnionType, @@ -107,6 +112,27 @@ def ast3_parse(source: Union[str, bytes], filename: str, mode: str, # These don't exist before 3.8 NamedExpr = Any Constant = Any + + if sys.version_info >= (3, 10): + Match = ast3.Match + MatchValue = ast3.MatchValue + MatchSingleton = ast3.MatchSingleton + MatchSequence = ast3.MatchSequence + MatchStar = ast3.MatchStar + MatchMapping = ast3.MatchMapping + MatchClass = ast3.MatchClass + MatchAs = ast3.MatchAs + MatchOr = ast3.MatchOr + else: + Match = Any + MatchValue = Any + MatchSingleton = Any + MatchSequence = Any + MatchStar = Any + MatchMapping = Any + MatchClass = Any + MatchAs = Any + MatchOr = Any except ImportError: try: from typed_ast import ast35 # type: ignore[attr-defined] # noqa: F401 @@ -1287,11 +1313,74 @@ def visit_Index(self, n: Index) -> Node: # cast for mypyc's benefit on Python 3.9 return self.visit(cast(Any, n).value) - def visit_Match(self, n: Any) -> Node: - self.fail("Match statement is not supported", - line=n.lineno, column=n.col_offset, blocker=True) - # Just return some valid node - return PassStmt() + # Match(expr subject, match_case* cases) # python 3.10 and later + def visit_Match(self, n: Match) -> MatchStmt: + node = MatchStmt(self.visit(n.subject), + [self.visit(c.pattern) for c in n.cases], + [self.visit(c.guard) for c in n.cases], + [self.as_required_block(c.body, n.lineno) for c in n.cases]) + return self.set_line(node, n) + + def visit_MatchValue(self, n: MatchValue) -> ValuePattern: + node = ValuePattern(self.visit(n.value)) + return self.set_line(node, n) + + def visit_MatchSingleton(self, n: MatchSingleton) -> SingletonPattern: + node = SingletonPattern(n.value) + return self.set_line(node, n) + + def visit_MatchSequence(self, n: MatchSequence) -> SequencePattern: + patterns = [self.visit(p) for p in n.patterns] + stars = [p for p in patterns if isinstance(p, StarredPattern)] + assert len(stars) < 2 + + node = SequencePattern(patterns) + return self.set_line(node, n) + + def visit_MatchStar(self, n: MatchStar) -> StarredPattern: + if n.name is None: + node = StarredPattern(None) + else: + node = StarredPattern(NameExpr(n.name)) + + return self.set_line(node, n) + + def visit_MatchMapping(self, n: MatchMapping) -> MappingPattern: + keys = [self.visit(k) for k in n.keys] + values = [self.visit(v) for v in n.patterns] + + if n.rest is None: + rest = None + else: + rest = NameExpr(n.rest) + + node = MappingPattern(keys, values, rest) + return self.set_line(node, n) + + def visit_MatchClass(self, n: MatchClass) -> ClassPattern: + class_ref = self.visit(n.cls) + assert isinstance(class_ref, RefExpr) + positionals = [self.visit(p) for p in n.patterns] + keyword_keys = n.kwd_attrs + keyword_values = [self.visit(p) for p in n.kwd_patterns] + + node = ClassPattern(class_ref, positionals, keyword_keys, keyword_values) + return self.set_line(node, n) + + # MatchAs(expr pattern, identifier name) + def visit_MatchAs(self, n: MatchAs) -> AsPattern: + if n.name is None: + name = None + else: + name = NameExpr(n.name) + name = self.set_line(name, n) + node = AsPattern(self.visit(n.pattern), name) + return self.set_line(node, n) + + # MatchOr(expr* pattern) + def visit_MatchOr(self, n: MatchOr) -> OrPattern: + node = OrPattern([self.visit(pattern) for pattern in n.patterns]) + return self.set_line(node, n) class TypeConverter: diff --git a/mypy/message_registry.py b/mypy/message_registry.py index 77dff11548331..1477cc4da575b 100644 --- a/mypy/message_registry.py +++ b/mypy/message_registry.py @@ -64,6 +64,7 @@ def format(self, *args: object, **kwargs: object) -> "ErrorMessage": INCOMPATIBLE_TYPES_IN_YIELD: Final = ErrorMessage('Incompatible types in "yield"') INCOMPATIBLE_TYPES_IN_YIELD_FROM: Final = ErrorMessage('Incompatible types in "yield from"') INCOMPATIBLE_TYPES_IN_STR_INTERPOLATION: Final = "Incompatible types in string interpolation" +INCOMPATIBLE_TYPES_IN_CAPTURE: Final = ErrorMessage('Incompatible types in capture pattern') MUST_HAVE_NONE_RETURN_TYPE: Final = ErrorMessage('The return type of "{}" must be None') INVALID_TUPLE_INDEX_TYPE: Final = ErrorMessage("Invalid tuple index type") TUPLE_INDEX_OUT_OF_RANGE: Final = ErrorMessage("Tuple index out of range") @@ -229,3 +230,18 @@ def format(self, *args: object, **kwargs: object) -> "ErrorMessage": CONTIGUOUS_ITERABLE_EXPECTED: Final = ErrorMessage("Contiguous iterable with same type expected") ITERABLE_TYPE_EXPECTED: Final = ErrorMessage("Invalid type '{}' for *expr (iterable expected)") TYPE_GUARD_POS_ARG_REQUIRED: Final = ErrorMessage("Type guard requires positional argument") + +# Match Statement +MISSING_MATCH_ARGS: Final = 'Class "{}" doesn\'t define "__match_args__"' +OR_PATTERN_ALTERNATIVE_NAMES: Final = "Alternative patterns bind different names" +CLASS_PATTERN_GENERIC_TYPE_ALIAS: Final = ( + "Class pattern class must not be a type alias with type parameters" +) +CLASS_PATTERN_TYPE_REQUIRED: Final = 'Expected type in class pattern; found "{}"' +CLASS_PATTERN_TOO_MANY_POSITIONAL_ARGS: Final = "Too many positional patterns for class pattern" +CLASS_PATTERN_KEYWORD_MATCHES_POSITIONAL: Final = ( + 'Keyword "{}" already matches a positional pattern' +) +CLASS_PATTERN_DUPLICATE_KEYWORD_PATTERN: Final = 'Duplicate keyword pattern "{}"' +CLASS_PATTERN_UNKNOWN_KEYWORD: Final = 'Class "{}" has no attribute "{}"' +MULTIPLE_ASSIGNMENTS_IN_PATTERN: Final = 'Multiple assignments to name "{}" in pattern' diff --git a/mypy/messages.py b/mypy/messages.py index cbe389a597e51..406237783cf14 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -1258,7 +1258,7 @@ def typeddict_key_must_be_string_literal( context: Context) -> None: self.fail( 'TypedDict key must be a string literal; expected one of {}'.format( - format_item_name_list(typ.items.keys())), context) + format_item_name_list(typ.items.keys())), context, code=codes.LITERAL_REQ) def typeddict_key_not_found( self, diff --git a/mypy/nodes.py b/mypy/nodes.py index 78a018f94a78f..5f0d58aecb569 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -17,6 +17,9 @@ from mypy.bogus_type import Bogus +if TYPE_CHECKING: + from mypy.patterns import Pattern + class Context: """Base type for objects that are valid as error message locations.""" @@ -1368,6 +1371,25 @@ def accept(self, visitor: StatementVisitor[T]) -> T: return visitor.visit_with_stmt(self) +class MatchStmt(Statement): + subject: Expression + patterns: List['Pattern'] + guards: List[Optional[Expression]] + bodies: List[Block] + + def __init__(self, subject: Expression, patterns: List['Pattern'], + guards: List[Optional[Expression]], bodies: List[Block]) -> None: + super().__init__() + assert len(patterns) == len(guards) == len(bodies) + self.subject = subject + self.patterns = patterns + self.guards = guards + self.bodies = bodies + + def accept(self, visitor: StatementVisitor[T]) -> T: + return visitor.visit_match_stmt(self) + + class PrintStmt(Statement): """Python 2 print statement""" diff --git a/mypy/patterns.py b/mypy/patterns.py new file mode 100644 index 0000000000000..8557fac6daf61 --- /dev/null +++ b/mypy/patterns.py @@ -0,0 +1,132 @@ +"""Classes for representing match statement patterns.""" +from typing import TypeVar, List, Optional, Union + +from mypy_extensions import trait + +from mypy.nodes import Node, RefExpr, NameExpr, Expression +from mypy.visitor import PatternVisitor + + +T = TypeVar('T') + + +@trait +class Pattern(Node): + """A pattern node.""" + + __slots__ = () + + def accept(self, visitor: PatternVisitor[T]) -> T: + raise RuntimeError('Not implemented') + + +class AsPattern(Pattern): + # The python ast, and therefore also our ast merges capture, wildcard and as patterns into one + # for easier handling. + # If pattern is None this is a capture pattern. If name and pattern are both none this is a + # wildcard pattern. + # Only name being None should not happen but also won't break anything. + pattern: Optional[Pattern] + name: Optional[NameExpr] + + def __init__(self, pattern: Optional[Pattern], name: Optional[NameExpr]) -> None: + super().__init__() + self.pattern = pattern + self.name = name + + def accept(self, visitor: PatternVisitor[T]) -> T: + return visitor.visit_as_pattern(self) + + +class OrPattern(Pattern): + patterns: List[Pattern] + + def __init__(self, patterns: List[Pattern]) -> None: + super().__init__() + self.patterns = patterns + + def accept(self, visitor: PatternVisitor[T]) -> T: + return visitor.visit_or_pattern(self) + + +class ValuePattern(Pattern): + expr: Expression + + def __init__(self, expr: Expression): + super().__init__() + self.expr = expr + + def accept(self, visitor: PatternVisitor[T]) -> T: + return visitor.visit_value_pattern(self) + + +class SingletonPattern(Pattern): + # This can be exactly True, False or None + value: Union[bool, None] + + def __init__(self, value: Union[bool, None]): + super().__init__() + self.value = value + + def accept(self, visitor: PatternVisitor[T]) -> T: + return visitor.visit_singleton_pattern(self) + + +class SequencePattern(Pattern): + patterns: List[Pattern] + + def __init__(self, patterns: List[Pattern]): + super().__init__() + self.patterns = patterns + + def accept(self, visitor: PatternVisitor[T]) -> T: + return visitor.visit_sequence_pattern(self) + + +class StarredPattern(Pattern): + # None corresponds to *_ in a list pattern. It will match multiple items but won't bind them to + # a name. + capture: Optional[NameExpr] + + def __init__(self, capture: Optional[NameExpr]): + super().__init__() + self.capture = capture + + def accept(self, visitor: PatternVisitor[T]) -> T: + return visitor.visit_starred_pattern(self) + + +class MappingPattern(Pattern): + keys: List[Expression] + values: List[Pattern] + rest: Optional[NameExpr] + + def __init__(self, keys: List[Expression], values: List[Pattern], + rest: Optional[NameExpr]): + super().__init__() + assert len(keys) == len(values) + self.keys = keys + self.values = values + self.rest = rest + + def accept(self, visitor: PatternVisitor[T]) -> T: + return visitor.visit_mapping_pattern(self) + + +class ClassPattern(Pattern): + class_ref: RefExpr + positionals: List[Pattern] + keyword_keys: List[str] + keyword_values: List[Pattern] + + def __init__(self, class_ref: RefExpr, positionals: List[Pattern], keyword_keys: List[str], + keyword_values: List[Pattern]): + super().__init__() + assert len(keyword_keys) == len(keyword_values) + self.class_ref = class_ref + self.positionals = positionals + self.keyword_keys = keyword_keys + self.keyword_values = keyword_values + + def accept(self, visitor: PatternVisitor[T]) -> T: + return visitor.visit_class_pattern(self) diff --git a/mypy/plugins/common.py b/mypy/plugins/common.py index 1beb538493272..95f4618da4a14 100644 --- a/mypy/plugins/common.py +++ b/mypy/plugins/common.py @@ -156,6 +156,33 @@ def add_method_to_class( info.defn.defs.body.append(func) +def add_attribute_to_class( + api: SemanticAnalyzerPluginInterface, + cls: ClassDef, + name: str, + typ: Type, + final: bool = False, +) -> None: + """ + Adds a new attribute to a class definition. + This currently only generates the symbol table entry and no corresponding AssignmentStatement + """ + info = cls.info + + # NOTE: we would like the plugin generated node to dominate, but we still + # need to keep any existing definitions so they get semantically analyzed. + if name in info.names: + # Get a nice unique name instead. + r_name = get_unique_redefinition_name(name, info.names) + info.names[r_name] = info.names[name] + + node = Var(name, typ) + node.info = info + node.is_final = final + node._fullname = info.fullname + '.' + name + info.names[name] = SymbolTableNode(MDEF, node, plugin_generated=True) + + def deserialize_and_fixup_type( data: Union[str, JsonDict], api: SemanticAnalyzerPluginInterface ) -> Type: diff --git a/mypy/plugins/dataclasses.py b/mypy/plugins/dataclasses.py index 6894959bd47b2..091c627f5c1b1 100644 --- a/mypy/plugins/dataclasses.py +++ b/mypy/plugins/dataclasses.py @@ -11,12 +11,12 @@ ) from mypy.plugin import ClassDefContext, SemanticAnalyzerPluginInterface from mypy.plugins.common import ( - add_method, _get_decorator_bool_argument, deserialize_and_fixup_type, + add_method, _get_decorator_bool_argument, deserialize_and_fixup_type, add_attribute_to_class, ) from mypy.typeops import map_type_from_supertype from mypy.types import ( - Type, Instance, NoneType, TypeVarType, CallableType, get_proper_type, - AnyType, TypeOfAny, + Type, Instance, NoneType, TypeVarType, CallableType, TupleType, LiteralType, + get_proper_type, AnyType, TypeOfAny, ) from mypy.server.trigger import make_wildcard_trigger @@ -132,6 +132,7 @@ def transform(self) -> None: 'order': _get_decorator_bool_argument(self._ctx, 'order', False), 'frozen': _get_decorator_bool_argument(self._ctx, 'frozen', False), 'slots': _get_decorator_bool_argument(self._ctx, 'slots', False), + 'match_args': _get_decorator_bool_argument(self._ctx, 'match_args', True), } py_version = self._ctx.api.options.python_version @@ -218,6 +219,16 @@ def transform(self) -> None: self.reset_init_only_vars(info, attributes) + if (decorator_arguments['match_args'] and + ('__match_args__' not in info.names or + info.names['__match_args__'].plugin_generated) and + attributes): + str_type = ctx.api.named_type("builtins.str") + literals: List[Type] = [LiteralType(attr.name, str_type) + for attr in attributes if attr.is_in_init] + match_args_type = TupleType(literals, ctx.api.named_type("builtins.tuple")) + add_attribute_to_class(ctx.api, ctx.cls, "__match_args__", match_args_type, final=True) + self._add_dataclass_fields_magic_attribute() info.metadata['dataclass'] = { diff --git a/mypy/reachability.py b/mypy/reachability.py index 44a21b993cfc3..eec472376317a 100644 --- a/mypy/reachability.py +++ b/mypy/reachability.py @@ -4,11 +4,12 @@ from typing_extensions import Final from mypy.nodes import ( - Expression, IfStmt, Block, AssertStmt, NameExpr, UnaryExpr, MemberExpr, OpExpr, ComparisonExpr, - StrExpr, UnicodeExpr, CallExpr, IntExpr, TupleExpr, IndexExpr, SliceExpr, Import, ImportFrom, - ImportAll, LITERAL_YES + Expression, IfStmt, Block, AssertStmt, MatchStmt, NameExpr, UnaryExpr, MemberExpr, OpExpr, + ComparisonExpr, StrExpr, UnicodeExpr, CallExpr, IntExpr, TupleExpr, IndexExpr, SliceExpr, + Import, ImportFrom, ImportAll, LITERAL_YES ) from mypy.options import Options +from mypy.patterns import Pattern, AsPattern, OrPattern from mypy.traverser import TraverserVisitor from mypy.literals import literal @@ -63,6 +64,30 @@ def infer_reachability_of_if_statement(s: IfStmt, options: Options) -> None: break +def infer_reachability_of_match_statement(s: MatchStmt, options: Options) -> None: + for i, guard in enumerate(s.guards): + pattern_value = infer_pattern_value(s.patterns[i]) + + if guard is not None: + guard_value = infer_condition_value(guard, options) + else: + guard_value = ALWAYS_TRUE + + if pattern_value in (ALWAYS_FALSE, MYPY_FALSE) \ + or guard_value in (ALWAYS_FALSE, MYPY_FALSE): + # The case is considered always false, so we skip the case body. + mark_block_unreachable(s.bodies[i]) + elif pattern_value in (ALWAYS_FALSE, MYPY_TRUE) \ + and guard_value in (ALWAYS_TRUE, MYPY_TRUE): + for body in s.bodies[i + 1:]: + mark_block_unreachable(body) + + if guard_value == MYPY_TRUE: + # This condition is false at runtime; this will affect + # import priorities. + mark_block_mypy_only(s.bodies[i]) + + def assert_will_always_fail(s: AssertStmt, options: Options) -> bool: return infer_condition_value(s.expr, options) in (ALWAYS_FALSE, MYPY_FALSE) @@ -118,6 +143,16 @@ def infer_condition_value(expr: Expression, options: Options) -> int: return result +def infer_pattern_value(pattern: Pattern) -> int: + if isinstance(pattern, AsPattern) and pattern.pattern is None: + return ALWAYS_TRUE + elif isinstance(pattern, OrPattern) and \ + any(infer_pattern_value(p) == ALWAYS_TRUE for p in pattern.patterns): + return ALWAYS_TRUE + else: + return TRUTH_VALUE_UNKNOWN + + def consider_sys_version_info(expr: Expression, pyversion: Tuple[int, ...]) -> int: """Consider whether expr is a comparison involving sys.version_info. diff --git a/mypy/renaming.py b/mypy/renaming.py index a43abb13c6880..c200e94d58e78 100644 --- a/mypy/renaming.py +++ b/mypy/renaming.py @@ -4,9 +4,10 @@ from mypy.nodes import ( Block, AssignmentStmt, NameExpr, MypyFile, FuncDef, Lvalue, ListExpr, TupleExpr, - WhileStmt, ForStmt, BreakStmt, ContinueStmt, TryStmt, WithStmt, StarExpr, ImportFrom, - MemberExpr, IndexExpr, Import, ClassDef + WhileStmt, ForStmt, BreakStmt, ContinueStmt, TryStmt, WithStmt, MatchStmt, StarExpr, + ImportFrom, MemberExpr, IndexExpr, Import, ClassDef ) +from mypy.patterns import AsPattern from mypy.traverser import TraverserVisitor # Scope kinds @@ -159,6 +160,21 @@ def visit_assignment_stmt(self, s: AssignmentStmt) -> None: for lvalue in s.lvalues: self.analyze_lvalue(lvalue) + def visit_match_stmt(self, s: MatchStmt) -> None: + for i in range(len(s.patterns)): + with self.enter_block(): + s.patterns[i].accept(self) + guard = s.guards[i] + if guard is not None: + guard.accept(self) + # We already entered a block, so visit this block's statements directly + for stmt in s.bodies[i].body: + stmt.accept(self) + + def visit_capture_pattern(self, p: AsPattern) -> None: + if p.name is not None: + self.analyze_lvalue(p.name) + def analyze_lvalue(self, lvalue: Lvalue, is_nested: bool = False) -> None: """Process assignment; in particular, keep track of (re)defined names. diff --git a/mypy/semanal.py b/mypy/semanal.py index 22d6b2e571bad..7b9348eb21e85 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -78,6 +78,11 @@ typing_extensions_aliases, EnumCallExpr, RUNTIME_PROTOCOL_DECOS, FakeExpression, Statement, AssignmentExpr, ParamSpecExpr, EllipsisExpr, TypeVarLikeExpr, FuncBase, implicit_module_attrs, + MatchStmt +) +from mypy.patterns import ( + AsPattern, OrPattern, ValuePattern, SequencePattern, + StarredPattern, MappingPattern, ClassPattern ) from mypy.tvar_scope import TypeVarLikeScope from mypy.typevars import fill_typevars @@ -121,8 +126,8 @@ from mypy.semanal_enum import EnumCallAnalyzer, ENUM_BASES from mypy.semanal_newtype import NewTypeAnalyzer from mypy.reachability import ( - infer_reachability_of_if_statement, infer_condition_value, ALWAYS_FALSE, ALWAYS_TRUE, - MYPY_TRUE, MYPY_FALSE + infer_reachability_of_if_statement, infer_reachability_of_match_statement, + infer_condition_value, ALWAYS_FALSE, ALWAYS_TRUE, MYPY_TRUE, MYPY_FALSE ) from mypy.mro import calculate_mro, MroError @@ -3779,6 +3784,17 @@ def visit_exec_stmt(self, s: ExecStmt) -> None: if s.locals: s.locals.accept(self) + def visit_match_stmt(self, s: MatchStmt) -> None: + self.statement = s + infer_reachability_of_match_statement(s, self.options) + s.subject.accept(self) + for i in range(len(s.patterns)): + s.patterns[i].accept(self) + guard = s.guards[i] + if guard is not None: + guard.accept(self) + self.visit_block(s.bodies[i]) + # # Expressions # @@ -4246,6 +4262,46 @@ def visit_await_expr(self, expr: AwaitExpr) -> None: self.fail('"await" outside coroutine ("async def")', expr) expr.expr.accept(self) + # + # Patterns + # + + def visit_as_pattern(self, p: AsPattern) -> None: + if p.pattern is not None: + p.pattern.accept(self) + if p.name is not None: + self.analyze_lvalue(p.name) + + def visit_or_pattern(self, p: OrPattern) -> None: + for pattern in p.patterns: + pattern.accept(self) + + def visit_value_pattern(self, p: ValuePattern) -> None: + p.expr.accept(self) + + def visit_sequence_pattern(self, p: SequencePattern) -> None: + for pattern in p.patterns: + pattern.accept(self) + + def visit_starred_pattern(self, p: StarredPattern) -> None: + if p.capture is not None: + self.analyze_lvalue(p.capture) + + def visit_mapping_pattern(self, p: MappingPattern) -> None: + for key in p.keys: + key.accept(self) + for value in p.values: + value.accept(self) + if p.rest is not None: + self.analyze_lvalue(p.rest) + + def visit_class_pattern(self, p: ClassPattern) -> None: + p.class_ref.accept(self) + for pos in p.positionals: + pos.accept(self) + for v in p.keyword_values: + v.accept(self) + # # Lookup functions # diff --git a/mypy/semanal_namedtuple.py b/mypy/semanal_namedtuple.py index 8930c63d2bef6..2357225caebbe 100644 --- a/mypy/semanal_namedtuple.py +++ b/mypy/semanal_namedtuple.py @@ -9,7 +9,7 @@ from mypy.types import ( Type, TupleType, AnyType, TypeOfAny, CallableType, TypeType, TypeVarType, - UnboundType, + UnboundType, LiteralType, ) from mypy.semanal_shared import ( SemanticAnalyzerInterface, set_callable_name, calculate_tuple_fallback, PRIORITY_FALLBACKS @@ -398,6 +398,9 @@ def build_namedtuple_typeinfo(self, iterable_type = self.api.named_type_or_none('typing.Iterable', [implicit_any]) function_type = self.api.named_type('builtins.function') + literals: List[Type] = [LiteralType(item, strtype) for item in items] + match_args_type = TupleType(literals, basetuple_type) + info = self.api.basic_new_typeinfo(name, fallback, line) info.is_named_tuple = True tuple_base = TupleType(types, fallback) @@ -436,6 +439,7 @@ def add_field(var: Var, is_initialized_in_class: bool = False, add_field(Var('_source', strtype), is_initialized_in_class=True) add_field(Var('__annotations__', ordereddictype), is_initialized_in_class=True) add_field(Var('__doc__', strtype), is_initialized_in_class=True) + add_field(Var('__match_args__', match_args_type), is_initialized_in_class=True) tvd = TypeVarType(SELF_TVAR_NAME, info.fullname + '.' + SELF_TVAR_NAME, -1, [], info.tuple_type) diff --git a/mypy/semanal_pass1.py b/mypy/semanal_pass1.py index 0296788e39903..2b096f08082a4 100644 --- a/mypy/semanal_pass1.py +++ b/mypy/semanal_pass1.py @@ -2,11 +2,14 @@ from mypy.nodes import ( MypyFile, AssertStmt, IfStmt, Block, AssignmentStmt, ExpressionStmt, ReturnStmt, ForStmt, - Import, ImportAll, ImportFrom, ClassDef, FuncDef + MatchStmt, Import, ImportAll, ImportFrom, ClassDef, FuncDef ) from mypy.traverser import TraverserVisitor from mypy.options import Options -from mypy.reachability import infer_reachability_of_if_statement, assert_will_always_fail +from mypy.reachability import ( + infer_reachability_of_if_statement, assert_will_always_fail, + infer_reachability_of_match_statement +) class SemanticAnalyzerPreAnalysis(TraverserVisitor): @@ -102,6 +105,14 @@ def visit_block(self, b: Block) -> None: return super().visit_block(b) + def visit_match_stmt(self, s: MatchStmt) -> None: + infer_reachability_of_match_statement(s, self.options) + for guard in s.guards: + if guard is not None: + guard.accept(self) + for body in s.bodies: + body.accept(self) + # The remaining methods are an optimization: don't visit nested expressions # of common statements, since they can have no effect. diff --git a/mypy/strconv.py b/mypy/strconv.py index c63063af0776b..22534a44971d4 100644 --- a/mypy/strconv.py +++ b/mypy/strconv.py @@ -4,11 +4,15 @@ import os from typing import Any, List, Tuple, Optional, Union, Sequence +from typing_extensions import TYPE_CHECKING from mypy.util import short_type, IdMapper import mypy.nodes from mypy.visitor import NodeVisitor +if TYPE_CHECKING: + import mypy.patterns + class StrConv(NodeVisitor[str]): """Visitor for converting a node to a human-readable string. @@ -311,6 +315,15 @@ def visit_print_stmt(self, o: 'mypy.nodes.PrintStmt') -> str: def visit_exec_stmt(self, o: 'mypy.nodes.ExecStmt') -> str: return self.dump([o.expr, o.globals, o.locals], o) + def visit_match_stmt(self, o: 'mypy.nodes.MatchStmt') -> str: + a: List[Any] = [o.subject] + for i in range(len(o.patterns)): + a.append(('Pattern', [o.patterns[i]])) + if o.guards[i] is not None: + a.append(('Guard', [o.guards[i]])) + a.append(('Body', o.bodies[i].body)) + return self.dump(a, o) + # Expressions # Simple expressions @@ -537,6 +550,42 @@ def visit_backquote_expr(self, o: 'mypy.nodes.BackquoteExpr') -> str: def visit_temp_node(self, o: 'mypy.nodes.TempNode') -> str: return self.dump([o.type], o) + def visit_as_pattern(self, o: 'mypy.patterns.AsPattern') -> str: + return self.dump([o.pattern, o.name], o) + + def visit_or_pattern(self, o: 'mypy.patterns.OrPattern') -> str: + return self.dump(o.patterns, o) + + def visit_value_pattern(self, o: 'mypy.patterns.ValuePattern') -> str: + return self.dump([o.expr], o) + + def visit_singleton_pattern(self, o: 'mypy.patterns.SingletonPattern') -> str: + return self.dump([o.value], o) + + def visit_sequence_pattern(self, o: 'mypy.patterns.SequencePattern') -> str: + return self.dump(o.patterns, o) + + def visit_starred_pattern(self, o: 'mypy.patterns.StarredPattern') -> str: + return self.dump([o.capture], o) + + def visit_mapping_pattern(self, o: 'mypy.patterns.MappingPattern') -> str: + a: List[Any] = [] + for i in range(len(o.keys)): + a.append(('Key', [o.keys[i]])) + a.append(('Value', [o.values[i]])) + if o.rest is not None: + a.append(('Rest', [o.rest])) + return self.dump(a, o) + + def visit_class_pattern(self, o: 'mypy.patterns.ClassPattern') -> str: + a: List[Any] = [o.class_ref] + if len(o.positionals) > 0: + a.append(('Positionals', o.positionals)) + for i in range(len(o.keyword_keys)): + a.append(('Keyword', [o.keyword_keys[i], o.keyword_values[i]])) + + return self.dump(a, o) + def dump_tagged(nodes: Sequence[object], tag: Optional[str], str_conv: 'StrConv') -> str: """Convert an array into a pretty-printed multiline string representation. diff --git a/mypy/subtypes.py b/mypy/subtypes.py index 271e950de659c..51a9dfbb8bc1e 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -1436,7 +1436,7 @@ def visit_type_type(self, left: TypeType) -> bool: if right.type.fullname == 'builtins.type': # TODO: Strictly speaking, the type builtins.type is considered equivalent to # Type[Any]. However, this would break the is_proper_subtype check in - # conditional_type_map for cases like isinstance(x, type) when the type + # conditional_types for cases like isinstance(x, type) when the type # of x is Type[int]. It's unclear what's the right way to address this. return True if right.type.fullname == 'builtins.object': diff --git a/mypy/test/helpers.py b/mypy/test/helpers.py index fbd44bca868b5..f9f117634c21b 100644 --- a/mypy/test/helpers.py +++ b/mypy/test/helpers.py @@ -287,6 +287,8 @@ def num_skipped_suffix_lines(a1: List[str], a2: List[str]) -> int: def testfile_pyversion(path: str) -> Tuple[int, int]: if path.endswith('python2.test'): return defaults.PYTHON2_VERSION + elif path.endswith('python310.test'): + return 3, 10 else: return defaults.PYTHON3_VERSION diff --git a/mypy/test/testparse.py b/mypy/test/testparse.py index e9ff6839bc2cf..1587147c0777d 100644 --- a/mypy/test/testparse.py +++ b/mypy/test/testparse.py @@ -18,6 +18,9 @@ class ParserSuite(DataSuite): files = ['parse.test', 'parse-python2.test'] + if sys.version_info >= (3, 10): + files.append('parse-python310.test') + def run_case(self, testcase: DataDrivenTestCase) -> None: test_parser(testcase) @@ -31,6 +34,8 @@ def test_parser(testcase: DataDrivenTestCase) -> None: if testcase.file.endswith('python2.test'): options.python_version = defaults.PYTHON2_VERSION + elif testcase.file.endswith('python310.test'): + options.python_version = (3, 10) else: options.python_version = defaults.PYTHON3_VERSION diff --git a/mypy/test/testsemanal.py b/mypy/test/testsemanal.py index a71bac53619d1..441f9ab32dbb3 100644 --- a/mypy/test/testsemanal.py +++ b/mypy/test/testsemanal.py @@ -1,6 +1,7 @@ """Semantic analyzer test cases""" import os.path +import sys from typing import Dict, List @@ -38,6 +39,10 @@ ] +if sys.version_info >= (3, 10): + semanal_files.append('semanal-python310.test') + + def get_semanal_options(program_text: str, testcase: DataDrivenTestCase) -> Options: options = parse_options(program_text, testcase, 1) options.use_builtins_fixtures = True @@ -104,6 +109,8 @@ def test_semanal(testcase: DataDrivenTestCase) -> None: class SemAnalErrorSuite(DataSuite): files = ['semanal-errors.test'] + if sys.version_info >= (3, 10): + semanal_files.append('semanal-errors-python310.test') def run_case(self, testcase: DataDrivenTestCase) -> None: test_semanal_error(testcase) diff --git a/mypy/traverser.py b/mypy/traverser.py index a5f993bd2fa52..6ab97116a12ea 100644 --- a/mypy/traverser.py +++ b/mypy/traverser.py @@ -3,13 +3,17 @@ from typing import List, Tuple from mypy_extensions import mypyc_attr +from mypy.patterns import ( + AsPattern, OrPattern, ValuePattern, SequencePattern, StarredPattern, MappingPattern, + ClassPattern +) from mypy.visitor import NodeVisitor from mypy.nodes import ( Block, MypyFile, FuncBase, FuncItem, CallExpr, ClassDef, Decorator, FuncDef, ExpressionStmt, AssignmentStmt, OperatorAssignmentStmt, WhileStmt, ForStmt, ReturnStmt, AssertStmt, DelStmt, IfStmt, RaiseStmt, - TryStmt, WithStmt, NameExpr, MemberExpr, OpExpr, SliceExpr, CastExpr, RevealExpr, - UnaryExpr, ListExpr, TupleExpr, DictExpr, SetExpr, IndexExpr, AssignmentExpr, + TryStmt, WithStmt, MatchStmt, NameExpr, MemberExpr, OpExpr, SliceExpr, CastExpr, + RevealExpr, UnaryExpr, ListExpr, TupleExpr, DictExpr, SetExpr, IndexExpr, AssignmentExpr, GeneratorExpr, ListComprehension, SetComprehension, DictionaryComprehension, ConditionalExpr, TypeApplication, ExecStmt, Import, ImportFrom, LambdaExpr, ComparisonExpr, OverloadedFuncDef, YieldFromExpr, @@ -156,6 +160,15 @@ def visit_with_stmt(self, o: WithStmt) -> None: targ.accept(self) o.body.accept(self) + def visit_match_stmt(self, o: MatchStmt) -> None: + o.subject.accept(self) + for i in range(len(o.patterns)): + o.patterns[i].accept(self) + guard = o.guards[i] + if guard is not None: + guard.accept(self) + o.bodies[i].accept(self) + def visit_member_expr(self, o: MemberExpr) -> None: o.expr.accept(self) @@ -279,6 +292,42 @@ def visit_await_expr(self, o: AwaitExpr) -> None: def visit_super_expr(self, o: SuperExpr) -> None: o.call.accept(self) + def visit_as_pattern(self, o: AsPattern) -> None: + if o.pattern is not None: + o.pattern.accept(self) + if o.name is not None: + o.name.accept(self) + + def visit_or_pattern(self, o: OrPattern) -> None: + for p in o.patterns: + p.accept(self) + + def visit_value_pattern(self, o: ValuePattern) -> None: + o.expr.accept(self) + + def visit_sequence_pattern(self, o: SequencePattern) -> None: + for p in o.patterns: + p.accept(self) + + def visit_starred_patten(self, o: StarredPattern) -> None: + if o.capture is not None: + o.capture.accept(self) + + def visit_mapping_pattern(self, o: MappingPattern) -> None: + for key in o.keys: + key.accept(self) + for value in o.values: + value.accept(self) + if o.rest is not None: + o.rest.accept(self) + + def visit_class_pattern(self, o: ClassPattern) -> None: + o.class_ref.accept(self) + for p in o.positionals: + p.accept(self) + for v in o.keyword_values: + v.accept(self) + def visit_import(self, o: Import) -> None: for a in o.assignments: a.accept(self) diff --git a/mypy/typeops.py b/mypy/typeops.py index 677b8c7f4decf..88d4bc744bdf8 100644 --- a/mypy/typeops.py +++ b/mypy/typeops.py @@ -779,7 +779,7 @@ def coerce_to_literal(typ: Type) -> Type: typ = get_proper_type(typ) if isinstance(typ, UnionType): new_items = [coerce_to_literal(item) for item in typ.items] - return make_simplified_union(new_items) + return UnionType.make_union(new_items) elif isinstance(typ, Instance): if typ.last_known_value: return typ.last_known_value diff --git a/mypy/visitor.py b/mypy/visitor.py index b98ec773bbe37..9d3ebb6818b4f 100644 --- a/mypy/visitor.py +++ b/mypy/visitor.py @@ -8,6 +8,7 @@ if TYPE_CHECKING: # break import cycle only needed for mypy import mypy.nodes + import mypy.patterns T = TypeVar('T') @@ -310,10 +311,50 @@ def visit_print_stmt(self, o: 'mypy.nodes.PrintStmt') -> T: def visit_exec_stmt(self, o: 'mypy.nodes.ExecStmt') -> T: pass + @abstractmethod + def visit_match_stmt(self, o: 'mypy.nodes.MatchStmt') -> T: + pass + @trait @mypyc_attr(allow_interpreted_subclasses=True) -class NodeVisitor(Generic[T], ExpressionVisitor[T], StatementVisitor[T]): +class PatternVisitor(Generic[T]): + @abstractmethod + def visit_as_pattern(self, o: 'mypy.patterns.AsPattern') -> T: + pass + + @abstractmethod + def visit_or_pattern(self, o: 'mypy.patterns.OrPattern') -> T: + pass + + @abstractmethod + def visit_value_pattern(self, o: 'mypy.patterns.ValuePattern') -> T: + pass + + @abstractmethod + def visit_singleton_pattern(self, o: 'mypy.patterns.SingletonPattern') -> T: + pass + + @abstractmethod + def visit_sequence_pattern(self, o: 'mypy.patterns.SequencePattern') -> T: + pass + + @abstractmethod + def visit_starred_pattern(self, o: 'mypy.patterns.StarredPattern') -> T: + pass + + @abstractmethod + def visit_mapping_pattern(self, o: 'mypy.patterns.MappingPattern') -> T: + pass + + @abstractmethod + def visit_class_pattern(self, o: 'mypy.patterns.ClassPattern') -> T: + pass + + +@trait +@mypyc_attr(allow_interpreted_subclasses=True) +class NodeVisitor(Generic[T], ExpressionVisitor[T], StatementVisitor[T], PatternVisitor[T]): """Empty base class for parse tree node visitors. The T type argument specifies the return type of the visit @@ -429,6 +470,9 @@ def visit_print_stmt(self, o: 'mypy.nodes.PrintStmt') -> T: def visit_exec_stmt(self, o: 'mypy.nodes.ExecStmt') -> T: pass + def visit_match_stmt(self, o: 'mypy.nodes.MatchStmt') -> T: + pass + # Expressions (default no-op implementation) def visit_int_expr(self, o: 'mypy.nodes.IntExpr') -> T: @@ -562,3 +606,29 @@ def visit_await_expr(self, o: 'mypy.nodes.AwaitExpr') -> T: def visit_temp_node(self, o: 'mypy.nodes.TempNode') -> T: pass + + # Patterns + + def visit_as_pattern(self, o: 'mypy.patterns.AsPattern') -> T: + pass + + def visit_or_pattern(self, o: 'mypy.patterns.OrPattern') -> T: + pass + + def visit_value_pattern(self, o: 'mypy.patterns.ValuePattern') -> T: + pass + + def visit_singleton_pattern(self, o: 'mypy.patterns.SingletonPattern') -> T: + pass + + def visit_sequence_pattern(self, o: 'mypy.patterns.SequencePattern') -> T: + pass + + def visit_starred_pattern(self, o: 'mypy.patterns.StarredPattern') -> T: + pass + + def visit_mapping_pattern(self, o: 'mypy.patterns.MappingPattern') -> T: + pass + + def visit_class_pattern(self, o: 'mypy.patterns.ClassPattern') -> T: + pass diff --git a/mypyc/irbuild/visitor.py b/mypyc/irbuild/visitor.py index 1a6a84809707e..43cfd457667dc 100644 --- a/mypyc/irbuild/visitor.py +++ b/mypyc/irbuild/visitor.py @@ -16,7 +16,8 @@ FloatExpr, GeneratorExpr, GlobalDecl, LambdaExpr, ListComprehension, SetComprehension, NamedTupleExpr, NewTypeExpr, NonlocalDecl, OverloadedFuncDef, PrintStmt, RaiseStmt, RevealExpr, SetExpr, SliceExpr, StarExpr, SuperExpr, TryStmt, TypeAliasExpr, TypeApplication, - TypeVarExpr, TypedDictExpr, UnicodeExpr, WithStmt, YieldFromExpr, YieldExpr, ParamSpecExpr + TypeVarExpr, TypedDictExpr, UnicodeExpr, WithStmt, YieldFromExpr, YieldExpr, ParamSpecExpr, + MatchStmt ) from mypyc.ir.ops import Value @@ -179,6 +180,9 @@ def visit_nonlocal_decl(self, stmt: NonlocalDecl) -> None: # Pure declaration -- no runtime effect pass + def visit_match_stmt(self, stmt: MatchStmt) -> None: + self.bail("Match statements are not yet supported", stmt.line) + # Expressions def visit_name_expr(self, expr: NameExpr) -> Value: diff --git a/test-data/unit/check-narrowing.test b/test-data/unit/check-narrowing.test index d6b25ef456d9c..16cdc69ec1b7a 100644 --- a/test-data/unit/check-narrowing.test +++ b/test-data/unit/check-narrowing.test @@ -1227,7 +1227,7 @@ def unreachable(x: Union[str, List[str]]) -> None: elif isinstance(x, list): reveal_type(x) # N: Revealed type is "builtins.list[builtins.str]" else: - reveal_type(x) # N: Revealed type is "" + reveal_type(x) # No output: this branch is unreachable def all_parts_covered(x: Union[str, List[str], List[int], int]) -> None: if isinstance(x, str): diff --git a/test-data/unit/check-python310.test b/test-data/unit/check-python310.test index 3bcac61855b46..602faba7fbcaf 100644 --- a/test-data/unit/check-python310.test +++ b/test-data/unit/check-python310.test @@ -1,7 +1,1177 @@ -[case testMatchStatementNotSupported] -# flags: --python-version 3.10 -match str(): # E: Match statement is not supported - case 'x': - 1 + '' +-- Capture Pattern -- +[case testCapturePatternType] +class A: ... +m: A + +match m: + case a: + reveal_type(a) # N: Revealed type is "__main__.A" + + +-- Literal Pattern -- +[case testLiteralPatternNarrows] +m: object + +match m: + case 1: + reveal_type(m) # N: Revealed type is "Literal[1]?" + +[case testLiteralPatternAlreadyNarrower] +m: bool + +match m: + case 1: + reveal_type(m) # N: Revealed type is "builtins.bool" + +[case testLiteralPatternUnreachable] +# primitives are needed because otherwise mypy doesn't see that int and str are incompatible +m: int + +match m: + case "str": + reveal_type(m) +[builtins fixtures/primitives.pyi] + + +-- Value Pattern -- +[case testValuePatternNarrows] +import b +m: object + +match m: + case b.b: + reveal_type(m) # N: Revealed type is "builtins.int" +[file b.py] +b: int + +[case testValuePatternAlreadyNarrower] +import b +m: bool + +match m: + case b.b: + reveal_type(m) # N: Revealed type is "builtins.bool" +[file b.py] +b: int + +[case testValuePatternIntersect] +import b + +class A: ... +m: A + +match m: + case b.b: + reveal_type(m) # N: Revealed type is "__main__." +[file b.py] +class B: ... +b: B + +[case testValuePatternUnreachable] +# primitives are needed because otherwise mypy doesn't see that int and str are incompatible +import b + +m: int + +match m: + case b.b: + reveal_type(m) +[file b.py] +b: str +[builtins fixtures/primitives.pyi] + + +-- Sequence Pattern -- +[case testSequencePatternCaptures] +from typing import List +m: List[int] + +match m: + case [a]: + reveal_type(a) # N: Revealed type is "builtins.int*" +[builtins fixtures/list.pyi] + +[case testSequencePatternCapturesStarred] +from typing import Sequence +m: Sequence[int] + +match m: + case [a, *b]: + reveal_type(a) # N: Revealed type is "builtins.int*" + reveal_type(b) # N: Revealed type is "builtins.list[builtins.int*]" +[builtins fixtures/list.pyi] + +[case testSequencePatternNarrowsInner] +from typing import Sequence +m: Sequence[object] + +match m: + case [1, True]: + reveal_type(m) # N: Revealed type is "typing.Sequence[builtins.int]" + +[case testSequencePatternNarrowsOuter] +from typing import Sequence +m: object + +match m: + case [1, True]: + reveal_type(m) # N: Revealed type is "typing.Sequence[builtins.int]" + +[case testSequencePatternAlreadyNarrowerInner] +from typing import Sequence +m: Sequence[bool] + +match m: + case [1, True]: + reveal_type(m) # N: Revealed type is "typing.Sequence[builtins.bool]" + +[case testSequencePatternAlreadyNarrowerOuter] +from typing import Sequence +m: Sequence[object] + +match m: + case [1, True]: + reveal_type(m) # N: Revealed type is "typing.Sequence[builtins.int]" + +[case testSequencePatternAlreadyNarrowerBoth] +from typing import Sequence +m: Sequence[bool] + +match m: + case [1, True]: + reveal_type(m) # N: Revealed type is "typing.Sequence[builtins.bool]" + +[case testNestedSequencePatternNarrowsInner] +from typing import Sequence +m: Sequence[Sequence[object]] + +match m: + case [[1], [True]]: + reveal_type(m) # N: Revealed type is "typing.Sequence[typing.Sequence[builtins.int]]" + +[case testNestedSequencePatternNarrowsOuter] +from typing import Sequence +m: object + +match m: + case [[1], [True]]: + reveal_type(m) # N: Revealed type is "typing.Sequence[typing.Sequence[builtins.int]]" + +[case testSequencePatternDoesntNarrowInvariant] +from typing import List +m: List[object] + +match m: + case [1]: + reveal_type(m) # N: Revealed type is "builtins.list[builtins.object]" +[builtins fixtures/list.pyi] + +[case testSequencePatternMatches] +import array, collections +from typing import Sequence, Iterable + +m1: object +m2: Sequence[int] +m3: array.array[int] +m4: collections.deque[int] +m5: list[int] +m6: memoryview +m7: range +m8: tuple[int] + +m9: str +m10: bytes +m11: bytearray + +match m1: + case [a]: + reveal_type(a) # N: Revealed type is "builtins.object" + +match m2: + case [b]: + reveal_type(b) # N: Revealed type is "builtins.int*" + +match m3: + case [c]: + reveal_type(c) # N: Revealed type is "builtins.int*" + +match m4: + case [d]: + reveal_type(d) # N: Revealed type is "builtins.int*" + +match m5: + case [e]: + reveal_type(e) # N: Revealed type is "builtins.int*" + +match m6: + case [f]: + reveal_type(f) # N: Revealed type is "builtins.int*" + +match m7: + case [g]: + reveal_type(g) # N: Revealed type is "builtins.int*" + +match m8: + case [h]: + reveal_type(h) # N: Revealed type is "builtins.int" + +match m9: + case [i]: + reveal_type(i) + +match m10: + case [j]: + reveal_type(j) + +match m11: + case [k]: + reveal_type(k) +[builtins fixtures/primitives.pyi] +[typing fixtures/typing-full.pyi] + + +[case testSequencePatternCapturesTuple] +from typing import Tuple +m: Tuple[int, str, bool] + +match m: + case [a, b, c]: + reveal_type(a) # N: Revealed type is "builtins.int" + reveal_type(b) # N: Revealed type is "builtins.str" + reveal_type(c) # N: Revealed type is "builtins.bool" + reveal_type(m) # N: Revealed type is "Tuple[builtins.int, builtins.str, builtins.bool]" +[builtins fixtures/list.pyi] + +[case testSequencePatternTupleTooLong] +from typing import Tuple +m: Tuple[int, str] + +match m: + case [a, b, c]: + reveal_type(a) + reveal_type(b) + reveal_type(c) +[builtins fixtures/list.pyi] + +[case testSequencePatternTupleTooShort] +from typing import Tuple +m: Tuple[int, str, bool] + +match m: + case [a, b]: + reveal_type(a) + reveal_type(b) +[builtins fixtures/list.pyi] + +[case testSequencePatternTupleNarrows] +from typing import Tuple +m: Tuple[object, object] + +match m: + case [1, "str"]: + reveal_type(m) # N: Revealed type is "Tuple[Literal[1]?, Literal['str']?]" +[builtins fixtures/list.pyi] + +[case testSequencePatternTupleStarred] +from typing import Tuple +m: Tuple[int, str, bool] + +match m: + case [a, *b, c]: + reveal_type(a) # N: Revealed type is "builtins.int" + reveal_type(b) # N: Revealed type is "builtins.list[builtins.str]" + reveal_type(c) # N: Revealed type is "builtins.bool" + reveal_type(m) # N: Revealed type is "Tuple[builtins.int, builtins.str, builtins.bool]" +[builtins fixtures/list.pyi] + +[case testSequencePatternTupleStarredUnion] +from typing import Tuple +m: Tuple[int, str, float, bool] + +match m: + case [a, *b, c]: + reveal_type(a) # N: Revealed type is "builtins.int" + reveal_type(b) # N: Revealed type is "builtins.list[Union[builtins.str, builtins.float]]" + reveal_type(c) # N: Revealed type is "builtins.bool" + reveal_type(m) # N: Revealed type is "Tuple[builtins.int, builtins.str, builtins.float, builtins.bool]" +[builtins fixtures/list.pyi] + + +[case testSequencePatternTupleStarredTooShort] +from typing import Tuple +m: Tuple[int] +reveal_type(m) # N: Revealed type is "Tuple[builtins.int]" + +match m: + case [a, *b, c]: + reveal_type(a) + reveal_type(b) + reveal_type(c) +[builtins fixtures/list.pyi] + +[case testNonMatchingSequencePattern] +from typing import List + +x: List[int] +match x: + case [str()]: + pass + +[case testSequenceUnion-skip] +from typing import List, Union +m: Union[List[List[str]], str] + +match m: + case [list(['str'])]: + reveal_type(m) # N: Revealed type is "builtins.list[builtins.list[builtins.str]]" +[builtins fixtures/list.pyi] + +-- Mapping Pattern -- +[case testMappingPatternCaptures] +from typing import Dict +import b +m: Dict[str, int] + +match m: + case {"key": v}: + reveal_type(v) # N: Revealed type is "builtins.int*" + case {b.b: v2}: + reveal_type(v2) # N: Revealed type is "builtins.int*" +[file b.py] +b: str +[builtins fixtures/dict.pyi] + +[case testMappingPatternCapturesWrongKeyType] +# This is not actually unreachable, as a subclass of dict could accept keys with different types +from typing import Dict +import b +m: Dict[str, int] + +match m: + case {1: v}: + reveal_type(v) # N: Revealed type is "builtins.int*" + case {b.b: v2}: + reveal_type(v2) # N: Revealed type is "builtins.int*" +[file b.py] +b: int +[builtins fixtures/dict.pyi] + +[case testMappingPatternCapturesTypedDict] +from typing import TypedDict + +class A(TypedDict): + a: str + b: int + +m: A + +match m: + case {"a": v}: + reveal_type(v) # N: Revealed type is "builtins.str" + case {"b": v2}: + reveal_type(v2) # N: Revealed type is "builtins.int" + case {"a": v3, "b": v4}: + reveal_type(v3) # N: Revealed type is "builtins.str" + reveal_type(v4) # N: Revealed type is "builtins.int" + case {"o": v5}: + reveal_type(v5) # N: Revealed type is "builtins.object*" +[typing fixtures/typing-typeddict.pyi] + +[case testMappingPatternCapturesTypedDictWithLiteral] +from typing import TypedDict +import b + +class A(TypedDict): + a: str + b: int + +m: A + +match m: + case {b.a: v}: + reveal_type(v) # N: Revealed type is "builtins.str" + case {b.b: v2}: + reveal_type(v2) # N: Revealed type is "builtins.int" + case {b.a: v3, b.b: v4}: + reveal_type(v3) # N: Revealed type is "builtins.str" + reveal_type(v4) # N: Revealed type is "builtins.int" + case {b.o: v5}: + reveal_type(v5) # N: Revealed type is "builtins.object*" +[file b.py] +from typing import Final, Literal +a: Final = "a" +b: Literal["b"] = "b" +o: Final[str] = "o" +[typing fixtures/typing-typeddict.pyi] + +[case testMappingPatternCapturesTypedDictWithNonLiteral] +from typing import TypedDict +import b + +class A(TypedDict): + a: str + b: int + +m: A + +match m: + case {b.a: v}: + reveal_type(v) # N: Revealed type is "builtins.object*" +[file b.py] +from typing import Final, Literal +a: str +[typing fixtures/typing-typeddict.pyi] + +[case testMappingPatternCapturesTypedDictUnreachable] +# TypedDict keys are always str, so this is actually unreachable +from typing import TypedDict +import b + +class A(TypedDict): + a: str + b: int + +m: A + +match m: + case {1: v}: + reveal_type(v) + case {b.b: v2}: + reveal_type(v2) +[file b.py] +b: int +[typing fixtures/typing-typeddict.pyi] + +[case testMappingPatternCaptureRest] +m: object + +match m: + case {'k': 1, **r}: + reveal_type(r) # N: Revealed type is "builtins.dict[builtins.object, builtins.object]" +[builtins fixtures/dict.pyi] + +[case testMappingPatternCaptureRestFromMapping] +from typing import Mapping + +m: Mapping[str, int] + +match m: + case {'k': 1, **r}: + reveal_type(r) # N: Revealed type is "builtins.dict[builtins.str*, builtins.int*]" +[builtins fixtures/dict.pyi] + +-- Mapping patterns currently don't narrow -- + +-- Class Pattern -- +[case testClassPatternCapturePositional] +from typing import Final + +class A: + __match_args__: Final = ("a", "b") + a: str + b: int + +m: A + +match m: + case A(i, j): + reveal_type(i) # N: Revealed type is "builtins.str" + reveal_type(j) # N: Revealed type is "builtins.int" +[builtins fixtures/tuple.pyi] + +[case testClassPatternMemberClassCapturePositional] +import b + +m: b.A + +match m: + case b.A(i, j): + reveal_type(i) # N: Revealed type is "builtins.str" + reveal_type(j) # N: Revealed type is "builtins.int" +[file b.py] +from typing import Final + +class A: + __match_args__: Final = ("a", "b") + a: str + b: int +[builtins fixtures/tuple.pyi] + +[case testClassPatternCaptureKeyword] +class A: + a: str + b: int + +m: A + +match m: + case A(a=i, b=j): + reveal_type(i) # N: Revealed type is "builtins.str" + reveal_type(j) # N: Revealed type is "builtins.int" + +[case testClassPatternCaptureSelf] +m: object + +match m: + case bool(a): + reveal_type(a) # N: Revealed type is "builtins.bool" + case bytearray(b): + reveal_type(b) # N: Revealed type is "builtins.bytearray" + case bytes(c): + reveal_type(c) # N: Revealed type is "builtins.bytes" + case dict(d): + reveal_type(d) # N: Revealed type is "builtins.dict[Any, Any]" + case float(e): + reveal_type(e) # N: Revealed type is "builtins.float" + case frozenset(f): + reveal_type(f) # N: Revealed type is "builtins.frozenset[Any]" + case int(g): + reveal_type(g) # N: Revealed type is "builtins.int" + case list(h): + reveal_type(h) # N: Revealed type is "builtins.list[Any]" + case set(i): + reveal_type(i) # N: Revealed type is "builtins.set[Any]" + case str(j): + reveal_type(j) # N: Revealed type is "builtins.str" + case tuple(k): + reveal_type(k) # N: Revealed type is "builtins.tuple[Any]" +[builtins fixtures/primitives.pyi] + +[case testClassPatternNarrowSelfCapture] +m: object + +match m: + case bool(): + reveal_type(m) # N: Revealed type is "builtins.bool" + case bytearray(): + reveal_type(m) # N: Revealed type is "builtins.bytearray" + case bytes(): + reveal_type(m) # N: Revealed type is "builtins.bytes" + case dict(): + reveal_type(m) # N: Revealed type is "builtins.dict[Any, Any]" + case float(): + reveal_type(m) # N: Revealed type is "builtins.float" + case frozenset(): + reveal_type(m) # N: Revealed type is "builtins.frozenset[Any]" + case int(): + reveal_type(m) # N: Revealed type is "builtins.int" + case list(): + reveal_type(m) # N: Revealed type is "builtins.list[Any]" + case set(): + reveal_type(m) # N: Revealed type is "builtins.set[Any]" + case str(): + reveal_type(m) # N: Revealed type is "builtins.str" + case tuple(): + reveal_type(m) # N: Revealed type is "builtins.tuple[Any]" +[builtins fixtures/primitives.pyi] + +[case testClassPatternCaptureDataclass] +from dataclasses import dataclass + +@dataclass +class A: + a: str + b: int + +m: A + +match m: + case A(i, j): + reveal_type(i) # N: Revealed type is "builtins.str" + reveal_type(j) # N: Revealed type is "builtins.int" +[builtins fixtures/dataclasses.pyi] + +[case testClassPatternCaptureDataclassNoMatchArgs] +from dataclasses import dataclass + +@dataclass(match_args=False) +class A: + a: str + b: int + +m: A + +match m: + case A(i, j): # E: Class "__main__.A" doesn't define "__match_args__" + pass +[builtins fixtures/dataclasses.pyi] + +[case testClassPatternCaptureDataclassPartialMatchArgs] +from dataclasses import dataclass, field + +@dataclass +class A: + a: str + b: int = field(init=False) + +m: A + +match m: + case A(i, j): # E: Too many positional patterns for class pattern + pass + case A(k): + reveal_type(k) # N: Revealed type is "builtins.str" +[builtins fixtures/dataclasses.pyi] + +[case testClassPatternCaptureNamedTupleInline] +from collections import namedtuple + +A = namedtuple("A", ["a", "b"]) + +m: A + +match m: + case A(i, j): + reveal_type(i) # N: Revealed type is "Any" + reveal_type(j) # N: Revealed type is "Any" +[builtins fixtures/list.pyi] + +[case testClassPatternCaptureNamedTupleInlineTyped] +from typing import NamedTuple + +A = NamedTuple("A", [("a", str), ("b", int)]) + +m: A + +match m: + case A(i, j): + reveal_type(i) # N: Revealed type is "builtins.str" + reveal_type(j) # N: Revealed type is "builtins.int" +[builtins fixtures/list.pyi] + +[case testClassPatternCaptureNamedTupleClass] +from typing import NamedTuple + +class A(NamedTuple): + a: str + b: int + +m: A + +match m: + case A(i, j): + reveal_type(i) # N: Revealed type is "builtins.str" + reveal_type(j) # N: Revealed type is "builtins.int" +[builtins fixtures/tuple.pyi] + +[case testClassPatternCaptureGeneric] +from typing import Generic, TypeVar + +T = TypeVar('T') + +class A(Generic[T]): + a: T + +m: object + +match m: + case A(a=i): + reveal_type(m) # N: Revealed type is "__main__.A[Any]" + reveal_type(i) # N: Revealed type is "Any" + +[case testClassPatternCaptureGenericAlreadyKnown] +from typing import Generic, TypeVar + +T = TypeVar('T') + +class A(Generic[T]): + a: T + +m: A[int] + +match m: + case A(a=i): + reveal_type(m) # N: Revealed type is "__main__.A[builtins.int]" + reveal_type(i) # N: Revealed type is "builtins.int*" + +[case testClassPatternCaptureFilledGenericTypeAlias] +from typing import Generic, TypeVar + +T = TypeVar('T') + +class A(Generic[T]): + a: T + +B = A[int] + +m: object + +match m: + case B(a=i): # E: Class pattern class must not be a type alias with type parameters + reveal_type(i) + +[case testClassPatternCaptureGenericTypeAlias] +from typing import Generic, TypeVar + +T = TypeVar('T') + +class A(Generic[T]): + a: T + +B = A + +m: object + +match m: + case B(a=i): + pass + +[case testClassPatternNarrows] +from typing import Final + +class A: + __match_args__: Final = ("a", "b") + a: str + b: int + +m: object + +match m: + case A(): + reveal_type(m) # N: Revealed type is "__main__.A" + case A(i, j): + reveal_type(m) # N: Revealed type is "__main__.A" +[builtins fixtures/tuple.pyi] + +[case testClassPatternNarrowsUnion] +from typing import Final, Union + +class A: + __match_args__: Final = ("a", "b") + a: str + b: int + +class B: + __match_args__: Final = ("a", "b") + a: int + b: str + +m: Union[A, B] + +match m: + case A(): + reveal_type(m) # N: Revealed type is "__main__.A" + +match m: + case A(i, j): + reveal_type(m) # N: Revealed type is "__main__.A" + reveal_type(i) # N: Revealed type is "builtins.str" + reveal_type(j) # N: Revealed type is "builtins.int" + +match m: + case B(): + reveal_type(m) # N: Revealed type is "__main__.B" + +match m: + case B(k, l): + reveal_type(m) # N: Revealed type is "__main__.B" + reveal_type(k) # N: Revealed type is "builtins.int" + reveal_type(l) # N: Revealed type is "builtins.str" +[builtins fixtures/tuple.pyi] + +[case testClassPatternAlreadyNarrower] +from typing import Final + +class A: + __match_args__: Final = ("a", "b") + a: str + b: int +class B(A): ... + +m: B + +match m: + case A(): + reveal_type(m) # N: Revealed type is "__main__.B" + +match m: + case A(i, j): + reveal_type(m) # N: Revealed type is "__main__.B" +[builtins fixtures/tuple.pyi] + +[case testClassPatternIntersection] +from typing import Final + +class A: + __match_args__: Final = ("a", "b") + a: str + b: int +class B: ... + +m: B + +match m: + case A(): + reveal_type(m) # N: Revealed type is "__main__." + case A(i, j): + reveal_type(m) # N: Revealed type is "__main__.1" +[builtins fixtures/tuple.pyi] + +[case testClassPatternNonexistentKeyword] +class A: ... + +m: object + +match m: + case A(a=j): # E: Class "__main__.A" has no attribute "a" + reveal_type(m) # N: Revealed type is "__main__.A" + reveal_type(j) # N: Revealed type is "Any" + +[case testClassPatternDuplicateKeyword] +class A: + a: str + +m: object + +match m: + case A(a=i, a=j): # E: Duplicate keyword pattern "a" + pass + +[case testClassPatternDuplicateImplicitKeyword] +from typing import Final + +class A: + __match_args__: Final = ("a",) + a: str + +m: object + +match m: + case A(i, a=j): # E: Keyword "a" already matches a positional pattern + pass +[builtins fixtures/tuple.pyi] + +[case testClassPatternTooManyPositionals] +from typing import Final + +class A: + __match_args__: Final = ("a", "b") + a: str + b: int + +m: object + +match m: + case A(i, j, k): # E: Too many positional patterns for class pattern + pass +[builtins fixtures/tuple.pyi] + +[case testClassPatternIsNotType] +a = 1 +m: object + +match m: + case a(i, j): # E: Expected type in class pattern; found "builtins.int" + reveal_type(i) + reveal_type(j) + +[case testClassPatternNestedGenerics] +# From cpython test_patma.py +x = [[{0: 0}]] +match x: + case list([({-0-0j: int(real=0+0j, imag=0-0j) | (1) as z},)]): + y = 0 + +reveal_type(x) # N: Revealed type is "builtins.list[builtins.list*[builtins.dict*[builtins.int*, builtins.int*]]]" +reveal_type(y) # N: Revealed type is "builtins.int" +reveal_type(z) # N: Revealed type is "builtins.int*" +[builtins fixtures/dict.pyi] + +[case testNonFinalMatchArgs] +class A: + __match_args__ = ("a", "b") # N: __match_args__ must be final for checking of match statements to work + a: str + b: int + +m: object + +match m: + case A(i, j): + reveal_type(i) # N: Revealed type is "Any" + reveal_type(j) # N: Revealed type is "Any" +[builtins fixtures/tuple.pyi] + +[case testAnyTupleMatchArgs] +from typing import Tuple, Any + +class A: + __match_args__: Tuple[Any, ...] + a: str + b: int + +m: object + +match m: + case A(i, j, k): + reveal_type(i) # N: Revealed type is "Any" + reveal_type(j) # N: Revealed type is "Any" + reveal_type(k) # N: Revealed type is "Any" +[builtins fixtures/tuple.pyi] + +[case testNonLiteralMatchArgs] +from typing import Final + +b: str = "b" +class A: + __match_args__: Final = ("a", b) # N: __match_args__ must be a tuple containing string literals for checking of match statements to work + a: str + b: int + +m: object + +match m: + case A(i, j, k): # E: Too many positional patterns for class pattern + pass + case A(i, j): + reveal_type(i) # N: Revealed type is "builtins.str" + reveal_type(j) # N: Revealed type is "Any" +[builtins fixtures/tuple.pyi] + +[case testExternalMatchArgs] +from typing import Final, Literal + +args: Final = ("a", "b") +class A: + __match_args__: Final = args + a: str + b: int + +arg: Final = "a" +arg2: Literal["b"] = "b" +class B: + __match_args__: Final = (arg, arg2) + a: str + b: int + +[builtins fixtures/tuple.pyi] +[typing fixtures/typing-medium.pyi] + + +-- As Pattern -- +[case testAsPattern] +m: int + +match m: + case x as l: + reveal_type(x) # N: Revealed type is "builtins.int" + reveal_type(l) # N: Revealed type is "builtins.int" + +[case testAsPatternNarrows] +m: object + +match m: + case int() as l: + reveal_type(l) # N: Revealed type is "builtins.int" + +[case testAsPatternCapturesOr] +m: object + +match m: + case 1 | 2 as n: + reveal_type(n) # N: Revealed type is "Union[Literal[1]?, Literal[2]?]" + +[case testAsPatternAlreadyNarrower] +m: bool + +match m: + case int() as l: + reveal_type(l) # N: Revealed type is "builtins.bool" + + +-- Or Pattern -- +[case testOrPatternNarrows] +m: object + +match m: + case 1 | 2: + reveal_type(m) # N: Revealed type is "Union[Literal[1]?, Literal[2]?]" + +[case testOrPatternNarrowsStr] +m: object + +match m: + case "foo" | "bar": + reveal_type(m) # N: Revealed type is "Union[Literal['foo']?, Literal['bar']?]" + +[case testOrPatternNarrowsUnion] +m: object + +match m: + case 1 | "foo": + reveal_type(m) # N: Revealed type is "Union[Literal[1]?, Literal['foo']?]" + +[case testOrPatterCapturesMissing] +from typing import List +m: List[int] + +match m: + case [x, y] | list(x): # E: Alternative patterns bind different names + reveal_type(x) # N: Revealed type is "builtins.object" + reveal_type(y) # N: Revealed type is "builtins.int*" +[builtins fixtures/list.pyi] + +[case testOrPatternCapturesJoin] +m: object + +match m: + case list(x) | dict(x): + reveal_type(x) # N: Revealed type is "typing.Iterable[Any]" +[builtins fixtures/dict.pyi] + + +-- Interactions -- +[case testCapturePatternMultipleCases] +m: object + +match m: + case int(x): + reveal_type(x) # N: Revealed type is "builtins.int" + case str(x): + reveal_type(x) # N: Revealed type is "builtins.str" + +reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]" + +[case testCapturePatternMultipleCaptures] +from typing import Iterable + +m: Iterable[int] + +match m: + case [x, x]: # E: Multiple assignments to name "x" in pattern + reveal_type(x) # N: Revealed type is "builtins.int" +[builtins fixtures/list.pyi] + +[case testCapturePatternPreexistingSame] +a: int +m: int + +match m: + case a: + reveal_type(a) # N: Revealed type is "builtins.int" + +[case testCapturePatternPreexistingIncompatible] +a: str +m: int + +match m: + case a: # E: Incompatible types in capture pattern (pattern captures type "int", variable has type "str") + reveal_type(a) # N: Revealed type is "builtins.str" + +[case testCapturePatternPreexistingIncompatibleLater] +a: str +m: object + +match m: + case str(a): + reveal_type(a) # N: Revealed type is "builtins.str" + case int(a): # E: Incompatible types in capture pattern (pattern captures type "int", variable has type "str") + reveal_type(a) # N: Revealed type is "builtins.str" + + +-- Guards -- +[case testSimplePatternGuard] +m: str + +def guard() -> bool: ... + +match m: + case a if guard(): + reveal_type(a) # N: Revealed type is "builtins.str" + +[case testAlwaysTruePatternGuard] +m: str + +match m: + case a if True: + reveal_type(a) # N: Revealed type is "builtins.str" + +[case testAlwaysFalsePatternGuard] +m: str + +match m: + case a if False: + reveal_type(a) + +[case testRedefiningPatternGuard] +# flags: --strict-optional +m: str + +match m: + case a if a := 1: # E: Incompatible types in assignment (expression has type "int", variable has type "str") + reveal_type(a) # N: Revealed type is "" + +[case testAssigningPatternGuard] +m: str + +match m: + case a if a := "test": + reveal_type(a) # N: Revealed type is "builtins.str" + +[case testNarrowingPatternGuard] +m: object + +match m: + case a if isinstance(a, str): + reveal_type(a) # N: Revealed type is "builtins.str" +[builtins fixtures/isinstancelist.pyi] + +[case testIncompatiblePatternGuard] +class A: ... +class B: ... + +m: A + +match m: + case a if isinstance(a, B): + reveal_type(a) # N: Revealed type is "__main__." +[builtins fixtures/isinstancelist.pyi] + +[case testUnreachablePatternGuard] +m: str + +match m: + case a if isinstance(a, int): + reveal_type(a) +[builtins fixtures/isinstancelist.pyi] + +-- Exhaustiveness -- +[case testUnionNegativeNarrowing-skip] +from typing import Union + +m: Union[str, int] + +match m: + case str(a): + reveal_type(a) # N: Revealed type is "builtins.str" + reveal_type(m) # N: Revealed type is "builtins.str" + case b: + reveal_type(b) # N: Revealed type is "builtins.int" + reveal_type(m) # N: Revealed type is "builtins.int" + +[case testOrPatternNegativeNarrowing-skip] +from typing import Union + +m: Union[str, bytes, int] + +match m: + case str(a) | bytes(a): + reveal_type(a) # N: Revealed type is "builtins.object" + reveal_type(m) # N: Revealed type is "Union[builtins.str, builtins.bytes]" + case b: + reveal_type(b) # N: Revealed type is "builtins.int" + +[case testExhaustiveReturn-skip] +def foo(value) -> int: + match value: + case "bar": + return 1 case _: - 1 + b'' + return 2 + +[case testNoneExhaustiveReturn-skip] +def foo(value) -> int: # E: Missing return statement + match value: + case "bar": + return 1 + case 2: + return 2 diff --git a/test-data/unit/deps.test b/test-data/unit/deps.test index d833a05e201a0..fd593a975ca07 100644 --- a/test-data/unit/deps.test +++ b/test-data/unit/deps.test @@ -1436,6 +1436,7 @@ class B(A): -> , m -> -> , m.B.__init__ + -> -> -> -> diff --git a/test-data/unit/fixtures/dict.pyi b/test-data/unit/fixtures/dict.pyi index fd509de8a6c2f..f8a5e3481d135 100644 --- a/test-data/unit/fixtures/dict.pyi +++ b/test-data/unit/fixtures/dict.pyi @@ -32,7 +32,11 @@ class dict(Mapping[KT, VT]): def __len__(self) -> int: ... class int: # for convenience - def __add__(self, x: int) -> int: pass + def __add__(self, x: Union[int, complex]) -> int: pass + def __sub__(self, x: Union[int, complex]) -> int: pass + def __neg__(self): pass + real: int + imag: int class str: pass # for keyword argument key type class unicode: pass # needed for py2 docstrings diff --git a/test-data/unit/fixtures/primitives.pyi b/test-data/unit/fixtures/primitives.pyi index 71f59a9c1d8cf..c728385354434 100644 --- a/test-data/unit/fixtures/primitives.pyi +++ b/test-data/unit/fixtures/primitives.pyi @@ -1,5 +1,6 @@ # builtins stub with non-generic primitive types -from typing import Generic, TypeVar, Sequence, Iterator, Mapping +from typing import Generic, TypeVar, Sequence, Iterator, Mapping, Iterable, overload + T = TypeVar('T') V = TypeVar('V') @@ -48,5 +49,20 @@ class list(Sequence[T]): def __getitem__(self, item: int) -> T: pass class dict(Mapping[T, V]): def __iter__(self) -> Iterator[T]: pass +class set(Iterable[T]): + def __iter__(self) -> Iterator[T]: pass +class frozenset(Iterable[T]): + def __iter__(self) -> Iterator[T]: pass class function: pass class ellipsis: pass + +class range(Sequence[int]): + @overload + def __init__(self, stop: int) -> None: pass + @overload + def __init__(self, start: int, stop: int, step: int = ...) -> None: pass + def count(self, value: int) -> int: pass + def index(self, value: int) -> int: pass + def __getitem__(self, i: int) -> int: pass + def __iter__(self) -> Iterator[int]: pass + def __contains__(self, other: object) -> bool: pass diff --git a/test-data/unit/fixtures/typing-full.pyi b/test-data/unit/fixtures/typing-full.pyi index 3de9f934b2554..739bf703f3e7a 100644 --- a/test-data/unit/fixtures/typing-full.pyi +++ b/test-data/unit/fixtures/typing-full.pyi @@ -129,6 +129,10 @@ class Sequence(Iterable[T_co], Container[T_co]): @abstractmethod def __getitem__(self, n: Any) -> T_co: pass +class MutableSequence(Sequence[T]): + @abstractmethod + def __setitem__(self, n: Any, o: T) -> None: pass + class Mapping(Iterable[T], Generic[T, T_co], metaclass=ABCMeta): def __getitem__(self, key: T) -> T_co: pass @overload diff --git a/test-data/unit/lib-stub/collections.pyi b/test-data/unit/lib-stub/collections.pyi index 71f797e565e87..7ea264f764eed 100644 --- a/test-data/unit/lib-stub/collections.pyi +++ b/test-data/unit/lib-stub/collections.pyi @@ -1,4 +1,4 @@ -from typing import Any, Iterable, Union, Optional, Dict, TypeVar, overload, Optional, Callable, Sized +from typing import Any, Iterable, Union, Dict, TypeVar, Optional, Callable, Generic, Sequence, MutableMapping def namedtuple( typename: str, @@ -20,6 +20,6 @@ class defaultdict(Dict[KT, VT]): class Counter(Dict[KT, int], Generic[KT]): ... -class deque(Sized, Iterable[KT], Reversible[KT], Generic[KT]): ... +class deque(Sequence[KT], Generic[KT]): ... class ChainMap(MutableMapping[KT, VT], Generic[KT, VT]): ... diff --git a/test-data/unit/lib-stub/dataclasses.pyi b/test-data/unit/lib-stub/dataclasses.pyi index e0491e14876b0..bd33b459266c1 100644 --- a/test-data/unit/lib-stub/dataclasses.pyi +++ b/test-data/unit/lib-stub/dataclasses.pyi @@ -15,7 +15,6 @@ def dataclass(*, init: bool = ..., repr: bool = ..., eq: bool = ..., order: bool unsafe_hash: bool = ..., frozen: bool = ..., match_args: bool = ..., kw_only: bool = ..., slots: bool = ...) -> Callable[[Type[_T]], Type[_T]]: ... - @overload def field(*, default: _T, init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., diff --git a/test-data/unit/lib-stub/types.pyi b/test-data/unit/lib-stub/types.pyi index 6fc596ecbf139..3ac4945ef5a72 100644 --- a/test-data/unit/lib-stub/types.pyi +++ b/test-data/unit/lib-stub/types.pyi @@ -5,8 +5,6 @@ _T = TypeVar('_T') def coroutine(func: _T) -> _T: pass -class bool: ... - class ModuleType: __file__ = ... # type: str diff --git a/test-data/unit/merge.test b/test-data/unit/merge.test index b59a713fef4d8..881e21bb1a929 100644 --- a/test-data/unit/merge.test +++ b/test-data/unit/merge.test @@ -671,15 +671,16 @@ TypeInfo<2>( _NT<6> __annotations__<7> (builtins.object<1>) __doc__<8> (builtins.str<9>) - __new__<10> - _asdict<11> - _field_defaults<12> (builtins.object<1>) - _field_types<13> (builtins.object<1>) - _fields<14> (Tuple[builtins.str<9>]) - _make<15> - _replace<16> - _source<17> (builtins.str<9>) - x<18> (target.A<0>))) + __match_args__<10> (Tuple[Literal['x']]) + __new__<11> + _asdict<12> + _field_defaults<13> (builtins.object<1>) + _field_types<14> (builtins.object<1>) + _fields<15> (Tuple[builtins.str<9>]) + _make<16> + _replace<17> + _source<18> (builtins.str<9>) + x<19> (target.A<0>))) ==> TypeInfo<0>( Name(target.A) @@ -694,16 +695,17 @@ TypeInfo<2>( _NT<6> __annotations__<7> (builtins.object<1>) __doc__<8> (builtins.str<9>) - __new__<10> - _asdict<11> - _field_defaults<12> (builtins.object<1>) - _field_types<13> (builtins.object<1>) - _fields<14> (Tuple[builtins.str<9>, builtins.str<9>]) - _make<15> - _replace<16> - _source<17> (builtins.str<9>) - x<18> (target.A<0>) - y<19> (target.A<0>))) + __match_args__<10> (Tuple[Literal['x'], Literal['y']]) + __new__<11> + _asdict<12> + _field_defaults<13> (builtins.object<1>) + _field_types<14> (builtins.object<1>) + _fields<15> (Tuple[builtins.str<9>, builtins.str<9>]) + _make<16> + _replace<17> + _source<18> (builtins.str<9>) + x<19> (target.A<0>) + y<20> (target.A<0>))) [case testUnionType_types] import target diff --git a/test-data/unit/parse-python310.test b/test-data/unit/parse-python310.test new file mode 100644 index 0000000000000..87e0e9d5d2832 --- /dev/null +++ b/test-data/unit/parse-python310.test @@ -0,0 +1,603 @@ +-- Test cases for parser -- Python 3.10 syntax (match statement) +-- +-- See parse.test for a description of this file format. + +[case testSimpleMatch] +match a: + case 1: + pass +[out] +MypyFile:1( + MatchStmt:1( + NameExpr(a) + Pattern( + ValuePattern:2( + IntExpr(1))) + Body( + PassStmt:3()))) + + +[case testTupleMatch] +match a, b: + case 1: + pass +[out] +MypyFile:1( + MatchStmt:1( + TupleExpr:1( + NameExpr(a) + NameExpr(b)) + Pattern( + ValuePattern:2( + IntExpr(1))) + Body( + PassStmt:3()))) + +[case testMatchWithGuard] +match a: + case 1 if f(): + pass + case d if d > 5: + pass +[out] +MypyFile:1( + MatchStmt:1( + NameExpr(a) + Pattern( + ValuePattern:2( + IntExpr(1))) + Guard( + CallExpr:2( + NameExpr(f) + Args())) + Body( + PassStmt:3()) + Pattern( + AsPattern:4( + NameExpr(d))) + Guard( + ComparisonExpr:4( + > + NameExpr(d) + IntExpr(5))) + Body( + PassStmt:5()))) + +[case testAsPattern] +match a: + case 1 as b: + pass +[out] +MypyFile:1( + MatchStmt:1( + NameExpr(a) + Pattern( + AsPattern:2( + ValuePattern:2( + IntExpr(1)) + NameExpr(b))) + Body( + PassStmt:3()))) + + +[case testLiteralPattern] +match a: + case 1: + pass + case -1: + pass + case 1+2j: + pass + case -1+2j: + pass + case 1-2j: + pass + case -1-2j: + pass + case "str": + pass + case b"bytes": + pass + case r"raw_string": + pass + case None: + pass + case True: + pass + case False: + pass +[out] +MypyFile:1( + MatchStmt:1( + NameExpr(a) + Pattern( + ValuePattern:2( + IntExpr(1))) + Body( + PassStmt:3()) + Pattern( + ValuePattern:4( + UnaryExpr:4( + - + IntExpr(1)))) + Body( + PassStmt:5()) + Pattern( + ValuePattern:6( + OpExpr:6( + + + IntExpr(1) + ComplexExpr(2j)))) + Body( + PassStmt:7()) + Pattern( + ValuePattern:8( + OpExpr:8( + + + UnaryExpr:8( + - + IntExpr(1)) + ComplexExpr(2j)))) + Body( + PassStmt:9()) + Pattern( + ValuePattern:10( + OpExpr:10( + - + IntExpr(1) + ComplexExpr(2j)))) + Body( + PassStmt:11()) + Pattern( + ValuePattern:12( + OpExpr:12( + - + UnaryExpr:12( + - + IntExpr(1)) + ComplexExpr(2j)))) + Body( + PassStmt:13()) + Pattern( + ValuePattern:14( + StrExpr(str))) + Body( + PassStmt:15()) + Pattern( + ValuePattern:16( + BytesExpr(bytes))) + Body( + PassStmt:17()) + Pattern( + ValuePattern:18( + StrExpr(raw_string))) + Body( + PassStmt:19()) + Pattern( + SingletonPattern:20()) + Body( + PassStmt:21()) + Pattern( + SingletonPattern:22( + True)) + Body( + PassStmt:23()) + Pattern( + SingletonPattern:24( + False)) + Body( + PassStmt:25()))) + +[case testCapturePattern] +match a: + case x: + pass + case longName: + pass +[out] +MypyFile:1( + MatchStmt:1( + NameExpr(a) + Pattern( + AsPattern:2( + NameExpr(x))) + Body( + PassStmt:3()) + Pattern( + AsPattern:4( + NameExpr(longName))) + Body( + PassStmt:5()))) + +[case testWildcardPattern] +match a: + case _: + pass +[out] +MypyFile:1( + MatchStmt:1( + NameExpr(a) + Pattern( + AsPattern:2()) + Body( + PassStmt:3()))) + +[case testValuePattern] +match a: + case b.c: + pass + case b.c.d.e.f: + pass +[out] +MypyFile:1( + MatchStmt:1( + NameExpr(a) + Pattern( + ValuePattern:2( + MemberExpr:2( + NameExpr(b) + c))) + Body( + PassStmt:3()) + Pattern( + ValuePattern:4( + MemberExpr:4( + MemberExpr:4( + MemberExpr:4( + MemberExpr:4( + NameExpr(b) + c) + d) + e) + f))) + Body( + PassStmt:5()))) + +[case testGroupPattern] +# This is optimized out by the compiler. It doesn't appear in the ast +match a: + case (1): + pass +[out] +MypyFile:1( + MatchStmt:2( + NameExpr(a) + Pattern( + ValuePattern:3( + IntExpr(1))) + Body( + PassStmt:4()))) + +[case testSequencePattern] +match a: + case []: + pass + case (): + pass + case [1]: + pass + case (1,): + pass + case 1,: + pass + case [1, 2, 3]: + pass + case (1, 2, 3): + pass + case 1, 2, 3: + pass + case [1, *a, 2]: + pass + case (1, *a, 2): + pass + case 1, *a, 2: + pass + case [1, *_, 2]: + pass + case (1, *_, 2): + pass + case 1, *_, 2: + pass +[out] +MypyFile:1( + MatchStmt:1( + NameExpr(a) + Pattern( + SequencePattern:2()) + Body( + PassStmt:3()) + Pattern( + SequencePattern:4()) + Body( + PassStmt:5()) + Pattern( + SequencePattern:6( + ValuePattern:6( + IntExpr(1)))) + Body( + PassStmt:7()) + Pattern( + SequencePattern:8( + ValuePattern:8( + IntExpr(1)))) + Body( + PassStmt:9()) + Pattern( + SequencePattern:10( + ValuePattern:10( + IntExpr(1)))) + Body( + PassStmt:11()) + Pattern( + SequencePattern:12( + ValuePattern:12( + IntExpr(1)) + ValuePattern:12( + IntExpr(2)) + ValuePattern:12( + IntExpr(3)))) + Body( + PassStmt:13()) + Pattern( + SequencePattern:14( + ValuePattern:14( + IntExpr(1)) + ValuePattern:14( + IntExpr(2)) + ValuePattern:14( + IntExpr(3)))) + Body( + PassStmt:15()) + Pattern( + SequencePattern:16( + ValuePattern:16( + IntExpr(1)) + ValuePattern:16( + IntExpr(2)) + ValuePattern:16( + IntExpr(3)))) + Body( + PassStmt:17()) + Pattern( + SequencePattern:18( + ValuePattern:18( + IntExpr(1)) + StarredPattern:18( + NameExpr(a)) + ValuePattern:18( + IntExpr(2)))) + Body( + PassStmt:19()) + Pattern( + SequencePattern:20( + ValuePattern:20( + IntExpr(1)) + StarredPattern:20( + NameExpr(a)) + ValuePattern:20( + IntExpr(2)))) + Body( + PassStmt:21()) + Pattern( + SequencePattern:22( + ValuePattern:22( + IntExpr(1)) + StarredPattern:22( + NameExpr(a)) + ValuePattern:22( + IntExpr(2)))) + Body( + PassStmt:23()) + Pattern( + SequencePattern:24( + ValuePattern:24( + IntExpr(1)) + StarredPattern:24() + ValuePattern:24( + IntExpr(2)))) + Body( + PassStmt:25()) + Pattern( + SequencePattern:26( + ValuePattern:26( + IntExpr(1)) + StarredPattern:26() + ValuePattern:26( + IntExpr(2)))) + Body( + PassStmt:27()) + Pattern( + SequencePattern:28( + ValuePattern:28( + IntExpr(1)) + StarredPattern:28() + ValuePattern:28( + IntExpr(2)))) + Body( + PassStmt:29()))) + +[case testMappingPattern] +match a: + case {'k': v}: + pass + case {a.b: v}: + pass + case {1: v}: + pass + case {a.c: v}: + pass + case {'k': v1, a.b: v2, 1: v3, a.c: v4}: + pass + case {'k1': 1, 'k2': "str", 'k3': b'bytes', 'k4': None}: + pass + case {'k': v, **r}: + pass + case {**r}: + pass +[out] +MypyFile:1( + MatchStmt:1( + NameExpr(a) + Pattern( + MappingPattern:2( + Key( + StrExpr(k)) + Value( + AsPattern:2( + NameExpr(v))))) + Body( + PassStmt:3()) + Pattern( + MappingPattern:4( + Key( + MemberExpr:4( + NameExpr(a) + b)) + Value( + AsPattern:4( + NameExpr(v))))) + Body( + PassStmt:5()) + Pattern( + MappingPattern:6( + Key( + IntExpr(1)) + Value( + AsPattern:6( + NameExpr(v))))) + Body( + PassStmt:7()) + Pattern( + MappingPattern:8( + Key( + MemberExpr:8( + NameExpr(a) + c)) + Value( + AsPattern:8( + NameExpr(v))))) + Body( + PassStmt:9()) + Pattern( + MappingPattern:10( + Key( + StrExpr(k)) + Value( + AsPattern:10( + NameExpr(v1))) + Key( + MemberExpr:10( + NameExpr(a) + b)) + Value( + AsPattern:10( + NameExpr(v2))) + Key( + IntExpr(1)) + Value( + AsPattern:10( + NameExpr(v3))) + Key( + MemberExpr:10( + NameExpr(a) + c)) + Value( + AsPattern:10( + NameExpr(v4))))) + Body( + PassStmt:11()) + Pattern( + MappingPattern:12( + Key( + StrExpr(k1)) + Value( + ValuePattern:12( + IntExpr(1))) + Key( + StrExpr(k2)) + Value( + ValuePattern:12( + StrExpr(str))) + Key( + StrExpr(k3)) + Value( + ValuePattern:12( + BytesExpr(bytes))) + Key( + StrExpr(k4)) + Value( + SingletonPattern:12()))) + Body( + PassStmt:13()) + Pattern( + MappingPattern:14( + Key( + StrExpr(k)) + Value( + AsPattern:14( + NameExpr(v))) + Rest( + NameExpr(r)))) + Body( + PassStmt:15()) + Pattern( + MappingPattern:16( + Rest( + NameExpr(r)))) + Body( + PassStmt:17()))) + +[case testClassPattern] +match a: + case A(): + pass + case B(1, 2): + pass + case B(1, b=2): + pass + case B(a=1, b=2): + pass +[out] +MypyFile:1( + MatchStmt:1( + NameExpr(a) + Pattern( + ClassPattern:2( + NameExpr(A))) + Body( + PassStmt:3()) + Pattern( + ClassPattern:4( + NameExpr(B) + Positionals( + ValuePattern:4( + IntExpr(1)) + ValuePattern:4( + IntExpr(2))))) + Body( + PassStmt:5()) + Pattern( + ClassPattern:6( + NameExpr(B) + Positionals( + ValuePattern:6( + IntExpr(1))) + Keyword( + b + ValuePattern:6( + IntExpr(2))))) + Body( + PassStmt:7()) + Pattern( + ClassPattern:8( + NameExpr(B) + Keyword( + a + ValuePattern:8( + IntExpr(1))) + Keyword( + b + ValuePattern:8( + IntExpr(2))))) + Body( + PassStmt:9()))) diff --git a/test-data/unit/semanal-errors-python310.test b/test-data/unit/semanal-errors-python310.test new file mode 100644 index 0000000000000..68c158cddae66 --- /dev/null +++ b/test-data/unit/semanal-errors-python310.test @@ -0,0 +1,43 @@ +[case testMatchUndefinedSubject] +import typing +match x: + case _: + pass +[out] +main:2: error: Name "x" is not defined + +[case testMatchUndefinedValuePattern] +import typing +x = 1 +match x: + case a.b: + pass +[out] +main:4: error: Name "a" is not defined + +[case testMatchUndefinedClassPattern] +import typing +x = 1 +match x: + case A(): + pass +[out] +main:4: error: Name "A" is not defined + +[case testNoneBindingWildcardPattern] +import typing +x = 1 +match x: + case _: + _ +[out] +main:5: error: Name "_" is not defined + +[case testNoneBindingStarredWildcardPattern] +import typing +x = 1 +match x: + case [*_]: + _ +[out] +main:5: error: Name "_" is not defined diff --git a/test-data/unit/semanal-python310.test b/test-data/unit/semanal-python310.test new file mode 100644 index 0000000000000..a009636575dcd --- /dev/null +++ b/test-data/unit/semanal-python310.test @@ -0,0 +1,204 @@ +-- Python 3.10 semantic analysis test cases. + +[case testCapturePattern] +x = 1 +match x: + case a: + a +[out] +MypyFile:1( + AssignmentStmt:1( + NameExpr(x* [__main__.x]) + IntExpr(1)) + MatchStmt:2( + NameExpr(x [__main__.x]) + Pattern( + AsPattern:3( + NameExpr(a* [__main__.a]))) + Body( + ExpressionStmt:4( + NameExpr(a [__main__.a]))))) + +[case testCapturePatternOutliving] +x = 1 +match x: + case a: + pass +a +[out] +MypyFile:1( + AssignmentStmt:1( + NameExpr(x* [__main__.x]) + IntExpr(1)) + MatchStmt:2( + NameExpr(x [__main__.x]) + Pattern( + AsPattern:3( + NameExpr(a* [__main__.a]))) + Body( + PassStmt:4())) + ExpressionStmt:5( + NameExpr(a [__main__.a]))) + +[case testNestedCapturePatterns] +x = 1 +match x: + case ([a], {'k': b}): + a + b +[out] +MypyFile:1( + AssignmentStmt:1( + NameExpr(x* [__main__.x]) + IntExpr(1)) + MatchStmt:2( + NameExpr(x [__main__.x]) + Pattern( + SequencePattern:3( + SequencePattern:3( + AsPattern:3( + NameExpr(a* [__main__.a]))) + MappingPattern:3( + Key( + StrExpr(k)) + Value( + AsPattern:3( + NameExpr(b* [__main__.b])))))) + Body( + ExpressionStmt:4( + NameExpr(a [__main__.a])) + ExpressionStmt:5( + NameExpr(b [__main__.b]))))) + +[case testMappingPatternRest] +x = 1 +match x: + case {**r}: + r +[out] +MypyFile:1( + AssignmentStmt:1( + NameExpr(x* [__main__.x]) + IntExpr(1)) + MatchStmt:2( + NameExpr(x [__main__.x]) + Pattern( + MappingPattern:3( + Rest( + NameExpr(r* [__main__.r])))) + Body( + ExpressionStmt:4( + NameExpr(r [__main__.r]))))) + + +[case testAsPattern] +x = 1 +match x: + case 1 as a: + a +[out] +MypyFile:1( + AssignmentStmt:1( + NameExpr(x* [__main__.x]) + IntExpr(1)) + MatchStmt:2( + NameExpr(x [__main__.x]) + Pattern( + AsPattern:3( + ValuePattern:3( + IntExpr(1)) + NameExpr(a* [__main__.a]))) + Body( + ExpressionStmt:4( + NameExpr(a [__main__.a]))))) + +[case testGuard] +x = 1 +a = 1 +match x: + case 1 if a: + pass +[out] +MypyFile:1( + AssignmentStmt:1( + NameExpr(x* [__main__.x]) + IntExpr(1)) + AssignmentStmt:2( + NameExpr(a* [__main__.a]) + IntExpr(1)) + MatchStmt:3( + NameExpr(x [__main__.x]) + Pattern( + ValuePattern:4( + IntExpr(1))) + Guard( + NameExpr(a [__main__.a])) + Body( + PassStmt:5()))) + +[case testCapturePatternInGuard] +x = 1 +match x: + case a if a: + pass +[out] +MypyFile:1( + AssignmentStmt:1( + NameExpr(x* [__main__.x]) + IntExpr(1)) + MatchStmt:2( + NameExpr(x [__main__.x]) + Pattern( + AsPattern:3( + NameExpr(a* [__main__.a]))) + Guard( + NameExpr(a [__main__.a])) + Body( + PassStmt:4()))) + +[case testAsPatternInGuard] +x = 1 +match x: + case 1 as a if a: + pass +[out] +MypyFile:1( + AssignmentStmt:1( + NameExpr(x* [__main__.x]) + IntExpr(1)) + MatchStmt:2( + NameExpr(x [__main__.x]) + Pattern( + AsPattern:3( + ValuePattern:3( + IntExpr(1)) + NameExpr(a* [__main__.a]))) + Guard( + NameExpr(a [__main__.a])) + Body( + PassStmt:4()))) + +[case testValuePattern] +import _a + +x = 1 +match x: + case _a.b: + pass +[file _a.py] +b = 1 +[out] +MypyFile:1( + Import:1(_a) + AssignmentStmt:3( + NameExpr(x* [__main__.x]) + IntExpr(1)) + MatchStmt:4( + NameExpr(x [__main__.x]) + Pattern( + ValuePattern:5( + MemberExpr:5( + NameExpr(_a) + b [_a.b]))) + Body( + PassStmt:6()))) diff --git a/test-requirements.txt b/test-requirements.txt index a9fcd412f175b..d4e21592721b2 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -6,7 +6,8 @@ flake8-bugbear flake8-pyi>=20.5 lxml>=4.4.0; python_version<'3.11' psutil>=4.0 -pytest>=6.2.0,<7.0.0 +# pytest 6.2.3 does not support Python 3.10 +pytest>=6.2.4,<7.0.0 pytest-xdist>=1.34.0,<2.0.0 pytest-forked>=1.3.0,<2.0.0 pytest-cov>=2.10.0,<3.0.0 From 5918919629cdf78eec2ffafa4257321eb2e2cfd3 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Tue, 18 Jan 2022 11:19:13 +0000 Subject: [PATCH 066/377] Fix failing match statement tests (#12007) --- test-data/unit/check-python310.test | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test-data/unit/check-python310.test b/test-data/unit/check-python310.test index 602faba7fbcaf..4c0324b9bec76 100644 --- a/test-data/unit/check-python310.test +++ b/test-data/unit/check-python310.test @@ -534,7 +534,7 @@ match m: case str(j): reveal_type(j) # N: Revealed type is "builtins.str" case tuple(k): - reveal_type(k) # N: Revealed type is "builtins.tuple[Any]" + reveal_type(k) # N: Revealed type is "builtins.tuple[Any, ...]" [builtins fixtures/primitives.pyi] [case testClassPatternNarrowSelfCapture] @@ -562,7 +562,7 @@ match m: case str(): reveal_type(m) # N: Revealed type is "builtins.str" case tuple(): - reveal_type(m) # N: Revealed type is "builtins.tuple[Any]" + reveal_type(m) # N: Revealed type is "builtins.tuple[Any, ...]" [builtins fixtures/primitives.pyi] [case testClassPatternCaptureDataclass] From 9b3147701f054bf8ef42bd96e33153b05976a5e1 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Tue, 18 Jan 2022 16:07:44 +0300 Subject: [PATCH 067/377] Fix CI by disabling it on 3.11 (#12003) --- .github/workflows/test.yml | 39 +++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7f5c89c430da5..7b3740bc4b15e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -113,22 +113,23 @@ jobs: - name: Test run: tox -e ${{ matrix.toxenv }} --skip-pkg-install -- ${{ matrix.tox_extra_args }} - python-nightly: - runs-on: ubuntu-latest - name: Test suite with Python nightly - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 - with: - python-version: '3.11-dev' - - name: Install tox - run: | - pip install -U pip==21.2.3 setuptools - pip install --upgrade 'setuptools!=50' virtualenv==20.4.7 tox==3.20.1 - - name: Setup tox environment - run: tox -e py --notest - - name: Test - run: tox -e py --skip-pkg-install -- "-n 2" - continue-on-error: true - - name: Mark as a success - run: exit 0 +# TODO: re-enable when `typed-ast` will be fixed for `python==3.11` +# python-nightly: +# runs-on: ubuntu-latest +# name: Test suite with Python nightly +# steps: +# - uses: actions/checkout@v2 +# - uses: actions/setup-python@v2 +# with: +# python-version: '3.11-dev' +# - name: Install tox +# run: | +# pip install -U pip==21.2.3 setuptools +# pip install --upgrade 'setuptools!=50' virtualenv==20.4.7 tox==3.20.1 +# - name: Setup tox environment +# run: tox -e py --notest +# - name: Test +# run: tox -e py --skip-pkg-install -- "-n 2" +# continue-on-error: true +# - name: Mark as a success +# run: exit 0 From 002e3091b54757161ef4339edc22a376db12649d Mon Sep 17 00:00:00 2001 From: Jannic Warken Date: Tue, 18 Jan 2022 18:10:41 +0100 Subject: [PATCH 068/377] Fix handling of NoReturn in Union return types (#11996) There are several discussions and comments describing the following problem (references can be found at the end of the PR summary): ```python def func() -> str | NoReturn: ... func().lower() ``` At the moment the code results in: `"NoReturn" of "Union[str, NoReturn]" has no attribute "lower"` Make `Union[int, NoReturn]` equivalent to `int` in a return type, because in case the function returns it must be `int`. --- mypy/checkexpr.py | 2 ++ test-data/unit/check-unions.test | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 66d8fa4b76960..9bf3ec3a4456c 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -378,6 +378,8 @@ def visit_call_expr_inner(self, e: CallExpr, allow_none_return: bool = False) -> if isinstance(e.callee, MemberExpr) and e.callee.name == 'format': self.check_str_format_call(e) ret_type = get_proper_type(ret_type) + if isinstance(ret_type, UnionType): + ret_type = make_simplified_union(ret_type.items) if isinstance(ret_type, UninhabitedType) and not ret_type.ambiguous: self.chk.binder.unreachable() # Warn on calls to functions that always return None. The check diff --git a/test-data/unit/check-unions.test b/test-data/unit/check-unions.test index cf1ff5650d49f..6966af289f28f 100644 --- a/test-data/unit/check-unions.test +++ b/test-data/unit/check-unions.test @@ -144,6 +144,11 @@ f(1) f(None) f('') # E: Argument 1 to "f" has incompatible type "str"; expected "Optional[int]" +[case testUnionWithNoReturn] +from typing import Union, NoReturn +def f() -> Union[int, NoReturn]: ... +reveal_type(f()) # N: Revealed type is "builtins.int" + [case testUnionSimplificationGenericFunction] from typing import TypeVar, Union, List T = TypeVar('T') From 0a03ba0d11136647ac74dc5fceac9b2cceb1f673 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Tue, 18 Jan 2022 21:07:26 +0300 Subject: [PATCH 069/377] Move `final` detection for `Enum` in `checker.py` (#11984) Fixes #11850 --- mypy/checker.py | 47 ++++++++++++- mypy/semanal.py | 34 ++------- mypy/stubtest.py | 16 +---- mypy/util.py | 20 ++++++ test-data/unit/check-enum.test | 99 +++++++++++++++++++++------ test-data/unit/check-incremental.test | 4 +- 6 files changed, 149 insertions(+), 71 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 6f8ab758cc943..2f99b9b4fece7 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -24,9 +24,9 @@ Context, Decorator, PrintStmt, BreakStmt, PassStmt, ContinueStmt, ComparisonExpr, StarExpr, EllipsisExpr, RefExpr, PromoteExpr, Import, ImportFrom, ImportAll, ImportBase, TypeAlias, - ARG_POS, ARG_STAR, LITERAL_TYPE, LDEF, MDEF, GDEF, + ARG_POS, ARG_STAR, ARG_NAMED, LITERAL_TYPE, LDEF, MDEF, GDEF, CONTRAVARIANT, COVARIANT, INVARIANT, TypeVarExpr, AssignmentExpr, - is_final_node, ARG_NAMED, MatchStmt) + is_final_node, MatchStmt) from mypy import nodes from mypy import operators from mypy.literals import literal, literal_hash, Key @@ -86,7 +86,7 @@ from mypy import state, errorcodes as codes from mypy.traverser import has_return_statement, all_return_statements from mypy.errorcodes import ErrorCode -from mypy.util import is_typeshed_file +from mypy.util import is_typeshed_file, is_dunder, is_sunder T = TypeVar('T') @@ -1833,6 +1833,10 @@ def visit_class_def(self, defn: ClassDef) -> None: # that completely swap out the type. (e.g. Callable[[Type[A]], Type[B]]) if typ.is_protocol and typ.defn.type_vars: self.check_protocol_variance(defn) + if not defn.has_incompatible_baseclass and defn.info.is_enum: + for base in defn.info.mro[1:-1]: # we don't need self and `object` + if base.is_enum and base.fullname not in ENUM_BASES: + self.check_final_enum(defn, base) def check_final_deletable(self, typ: TypeInfo) -> None: # These checks are only for mypyc. Only perform some checks that are easier @@ -1890,6 +1894,43 @@ def check_init_subclass(self, defn: ClassDef) -> None: # all other bases have already been checked. break + def check_final_enum(self, defn: ClassDef, base: TypeInfo) -> None: + for sym in base.names.values(): + if self.is_final_enum_value(sym): + self.fail( + 'Cannot extend enum with existing members: "{}"'.format( + base.name, + ), + defn, + ) + break + + def is_final_enum_value(self, sym: SymbolTableNode) -> bool: + if isinstance(sym.node, (FuncBase, Decorator)): + return False # A method is fine + if not isinstance(sym.node, Var): + return True # Can be a class or anything else + + # Now, only `Var` is left, we need to check: + # 1. Private name like in `__prop = 1` + # 2. Dunder name like `__hash__ = some_hasher` + # 3. Sunder name like `_order_ = 'a, b, c'` + # 4. If it is a method / descriptor like in `method = classmethod(func)` + if ( + is_private(sym.node.name) + or is_dunder(sym.node.name) + or is_sunder(sym.node.name) + # TODO: make sure that `x = @class/staticmethod(func)` + # and `x = property(prop)` both work correctly. + # Now they are incorrectly counted as enum members. + or isinstance(get_proper_type(sym.node.type), FunctionLike) + ): + return False + + if self.is_stub or sym.node.has_explicit_value: + return True + return False + def check_protocol_variance(self, defn: ClassDef) -> None: """Check that protocol definition is compatible with declared variances of type variables. diff --git a/mypy/semanal.py b/mypy/semanal.py index 7b9348eb21e85..a7c5eda732af0 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -77,12 +77,12 @@ REVEAL_LOCALS, is_final_node, TypedDictExpr, type_aliases_source_versions, typing_extensions_aliases, EnumCallExpr, RUNTIME_PROTOCOL_DECOS, FakeExpression, Statement, AssignmentExpr, - ParamSpecExpr, EllipsisExpr, TypeVarLikeExpr, FuncBase, implicit_module_attrs, - MatchStmt + ParamSpecExpr, EllipsisExpr, TypeVarLikeExpr, implicit_module_attrs, + MatchStmt, ) from mypy.patterns import ( AsPattern, OrPattern, ValuePattern, SequencePattern, - StarredPattern, MappingPattern, ClassPattern + StarredPattern, MappingPattern, ClassPattern, ) from mypy.tvar_scope import TypeVarLikeScope from mypy.typevars import fill_typevars @@ -123,7 +123,7 @@ ) from mypy.semanal_namedtuple import NamedTupleAnalyzer from mypy.semanal_typeddict import TypedDictAnalyzer -from mypy.semanal_enum import EnumCallAnalyzer, ENUM_BASES +from mypy.semanal_enum import EnumCallAnalyzer from mypy.semanal_newtype import NewTypeAnalyzer from mypy.reachability import ( infer_reachability_of_if_statement, infer_reachability_of_match_statement, @@ -1554,13 +1554,6 @@ def configure_base_classes(self, elif isinstance(base, Instance): if base.type.is_newtype: self.fail('Cannot subclass "NewType"', defn) - if self.enum_has_final_values(base): - # This means that are trying to subclass a non-default - # Enum class, with defined members. This is not possible. - # In runtime, it will raise. We need to mark this type as final. - # However, methods can be defined on a type: only values can't. - # We also don't count values with annotations only. - base.type.is_final = True base_types.append(base) elif isinstance(base, AnyType): if self.options.disallow_subclassing_any: @@ -1598,25 +1591,6 @@ def configure_base_classes(self, return self.calculate_class_mro(defn, self.object_type) - def enum_has_final_values(self, base: Instance) -> bool: - if ( - base.type.is_enum - and base.type.fullname not in ENUM_BASES - and base.type.names - and base.type.defn - ): - for sym in base.type.names.values(): - if isinstance(sym.node, (FuncBase, Decorator)): - continue # A method - if not isinstance(sym.node, Var): - return True # Can be a class - if self.is_stub_file or sym.node.has_explicit_value: - # Corner case: assignments like `x: int` are fine in `.py` files. - # But, not is `.pyi` files, because we don't know - # if there's aactually a value or not. - return True - return False - def configure_tuple_base_class(self, defn: ClassDef, base: TupleType, diff --git a/mypy/stubtest.py b/mypy/stubtest.py index cb005c4bd52c2..d0f62dfc3ed20 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -25,7 +25,7 @@ from mypy import nodes from mypy.config_parser import parse_config_file from mypy.options import Options -from mypy.util import FancyFormatter, bytes_to_human_readable_repr +from mypy.util import FancyFormatter, bytes_to_human_readable_repr, is_dunder, SPECIAL_DUNDERS class Missing: @@ -899,20 +899,6 @@ def verify_typealias( ) -SPECIAL_DUNDERS = ("__init__", "__new__", "__call__", "__init_subclass__", "__class_getitem__") - - -def is_dunder(name: str, exclude_special: bool = False) -> bool: - """Returns whether name is a dunder name. - - :param exclude_special: Whether to return False for a couple special dunder methods. - - """ - if exclude_special and name in SPECIAL_DUNDERS: - return False - return name.startswith("__") and name.endswith("__") - - def is_probably_a_function(runtime: Any) -> bool: return ( isinstance(runtime, (types.FunctionType, types.BuiltinFunctionType)) diff --git a/mypy/util.py b/mypy/util.py index 9f620e823e919..cd1e15afb4cf1 100644 --- a/mypy/util.py +++ b/mypy/util.py @@ -46,6 +46,26 @@ "C:\\Python27\\python.exe", ] +SPECIAL_DUNDERS: Final = frozenset(( + "__init__", "__new__", "__call__", "__init_subclass__", "__class_getitem__", +)) + + +def is_dunder(name: str, exclude_special: bool = False) -> bool: + """Returns whether name is a dunder name. + + Args: + exclude_special: Whether to return False for a couple special dunder methods. + + """ + if exclude_special and name in SPECIAL_DUNDERS: + return False + return name.startswith("__") and name.endswith("__") + + +def is_sunder(name: str) -> bool: + return not is_dunder(name) and name.startswith('_') and name.endswith('_') + def split_module_names(mod_name: str) -> List[str]: """Return the module and all parent module names. diff --git a/test-data/unit/check-enum.test b/test-data/unit/check-enum.test index aac97c6c69af2..2af57da9cbdc4 100644 --- a/test-data/unit/check-enum.test +++ b/test-data/unit/check-enum.test @@ -1469,22 +1469,22 @@ class NonEmptyFlag(Flag): class NonEmptyIntFlag(IntFlag): x = 1 -class ErrorEnumWithValue(NonEmptyEnum): # E: Cannot inherit from final class "NonEmptyEnum" +class ErrorEnumWithValue(NonEmptyEnum): # E: Cannot extend enum with existing members: "NonEmptyEnum" x = 1 # E: Cannot override final attribute "x" (previously declared in base class "NonEmptyEnum") -class ErrorIntEnumWithValue(NonEmptyIntEnum): # E: Cannot inherit from final class "NonEmptyIntEnum" +class ErrorIntEnumWithValue(NonEmptyIntEnum): # E: Cannot extend enum with existing members: "NonEmptyIntEnum" x = 1 # E: Cannot override final attribute "x" (previously declared in base class "NonEmptyIntEnum") -class ErrorFlagWithValue(NonEmptyFlag): # E: Cannot inherit from final class "NonEmptyFlag" +class ErrorFlagWithValue(NonEmptyFlag): # E: Cannot extend enum with existing members: "NonEmptyFlag" x = 1 # E: Cannot override final attribute "x" (previously declared in base class "NonEmptyFlag") -class ErrorIntFlagWithValue(NonEmptyIntFlag): # E: Cannot inherit from final class "NonEmptyIntFlag" +class ErrorIntFlagWithValue(NonEmptyIntFlag): # E: Cannot extend enum with existing members: "NonEmptyIntFlag" x = 1 # E: Cannot override final attribute "x" (previously declared in base class "NonEmptyIntFlag") -class ErrorEnumWithoutValue(NonEmptyEnum): # E: Cannot inherit from final class "NonEmptyEnum" +class ErrorEnumWithoutValue(NonEmptyEnum): # E: Cannot extend enum with existing members: "NonEmptyEnum" pass -class ErrorIntEnumWithoutValue(NonEmptyIntEnum): # E: Cannot inherit from final class "NonEmptyIntEnum" +class ErrorIntEnumWithoutValue(NonEmptyIntEnum): # E: Cannot extend enum with existing members: "NonEmptyIntEnum" pass -class ErrorFlagWithoutValue(NonEmptyFlag): # E: Cannot inherit from final class "NonEmptyFlag" +class ErrorFlagWithoutValue(NonEmptyFlag): # E: Cannot extend enum with existing members: "NonEmptyFlag" pass -class ErrorIntFlagWithoutValue(NonEmptyIntFlag): # E: Cannot inherit from final class "NonEmptyIntFlag" +class ErrorIntFlagWithoutValue(NonEmptyIntFlag): # E: Cannot extend enum with existing members: "NonEmptyIntFlag" pass [builtins fixtures/bool.pyi] @@ -1588,13 +1588,17 @@ class NonEmptyIntFlag(IntFlag): class NonEmptyEnumMeta(EnumMeta): x = 1 -class ErrorEnumWithoutValue(NonEmptyEnum): # E: Cannot inherit from final class "NonEmptyEnum" +class ErrorEnumWithoutValue(NonEmptyEnum): # E: Cannot inherit from final class "NonEmptyEnum" \ + # E: Cannot extend enum with existing members: "NonEmptyEnum" pass -class ErrorIntEnumWithoutValue(NonEmptyIntEnum): # E: Cannot inherit from final class "NonEmptyIntEnum" +class ErrorIntEnumWithoutValue(NonEmptyIntEnum): # E: Cannot inherit from final class "NonEmptyIntEnum" \ + # E: Cannot extend enum with existing members: "NonEmptyIntEnum" pass -class ErrorFlagWithoutValue(NonEmptyFlag): # E: Cannot inherit from final class "NonEmptyFlag" +class ErrorFlagWithoutValue(NonEmptyFlag): # E: Cannot inherit from final class "NonEmptyFlag" \ + # E: Cannot extend enum with existing members: "NonEmptyFlag" pass -class ErrorIntFlagWithoutValue(NonEmptyIntFlag): # E: Cannot inherit from final class "NonEmptyIntFlag" +class ErrorIntFlagWithoutValue(NonEmptyIntFlag): # E: Cannot inherit from final class "NonEmptyIntFlag" \ + # E: Cannot extend enum with existing members: "NonEmptyIntFlag" pass class ErrorEnumMetaWithoutValue(NonEmptyEnumMeta): # E: Cannot inherit from final class "NonEmptyEnumMeta" pass @@ -1692,13 +1696,13 @@ class NonEmptyIntFlag(IntFlag): x = 1 def method(self) -> None: pass -class ErrorEnumWithoutValue(NonEmptyEnum): # E: Cannot inherit from final class "NonEmptyEnum" +class ErrorEnumWithoutValue(NonEmptyEnum): # E: Cannot extend enum with existing members: "NonEmptyEnum" pass -class ErrorIntEnumWithoutValue(NonEmptyIntEnum): # E: Cannot inherit from final class "NonEmptyIntEnum" +class ErrorIntEnumWithoutValue(NonEmptyIntEnum): # E: Cannot extend enum with existing members: "NonEmptyIntEnum" pass -class ErrorFlagWithoutValue(NonEmptyFlag): # E: Cannot inherit from final class "NonEmptyFlag" +class ErrorFlagWithoutValue(NonEmptyFlag): # E: Cannot extend enum with existing members: "NonEmptyFlag" pass -class ErrorIntFlagWithoutValue(NonEmptyIntFlag): # E: Cannot inherit from final class "NonEmptyIntFlag" +class ErrorIntFlagWithoutValue(NonEmptyIntFlag): # E: Cannot extend enum with existing members: "NonEmptyIntFlag" pass [builtins fixtures/bool.pyi] @@ -1707,7 +1711,7 @@ from enum import Enum class A(Enum): class Inner: pass -class B(A): pass # E: Cannot inherit from final class "A" +class B(A): pass # E: Cannot extend enum with existing members: "A" [builtins fixtures/bool.pyi] [case testEnumFinalSpecialProps] @@ -1765,12 +1769,12 @@ class B(A): class A1(Enum): x: int = 1 -class B1(A1): # E: Cannot inherit from final class "A1" +class B1(A1): # E: Cannot extend enum with existing members: "A1" pass class A2(Enum): x = 2 -class B2(A2): # E: Cannot inherit from final class "A2" +class B2(A2): # E: Cannot extend enum with existing members: "A2" pass # We leave this `Final` without a value, @@ -1788,12 +1792,12 @@ import lib from enum import Enum class A(Enum): x: int -class B(A): # E: Cannot inherit from final class "A" +class B(A): # E: Cannot extend enum with existing members: "A" x = 1 # E: Cannot override writable attribute "x" with a final one class C(Enum): x = 1 -class D(C): # E: Cannot inherit from final class "C" +class D(C): # E: Cannot extend enum with existing members: "C" x: int # E: Cannot assign to final name "x" [builtins fixtures/bool.pyi] @@ -1811,3 +1815,56 @@ reveal_type(A.int.value) # N: Revealed type is "Literal[1]?" reveal_type(A.bool.value) # N: Revealed type is "Literal[False]?" reveal_type(A.tuple.value) # N: Revealed type is "Tuple[Literal[1]?]" [builtins fixtures/tuple.pyi] + +[case testFinalWithPrivateAssignment] +import enum +class Some(enum.Enum): + __priv = 1 + +class Other(Some): # Should pass + pass +[builtins fixtures/tuple.pyi] + +[case testFinalWithDunderAssignment] +import enum +class Some(enum.Enum): + __some__ = 1 + +class Other(Some): # Should pass + pass +[builtins fixtures/tuple.pyi] + +[case testFinalWithSunderAssignment] +import enum +class Some(enum.Enum): + _some_ = 1 + +class Other(Some): # Should pass + pass +[builtins fixtures/tuple.pyi] + +[case testFinalWithMethodAssignment] +import enum +from typing import overload +class Some(enum.Enum): + def lor(self, other) -> bool: + pass + + ror = lor + +class Other(Some): # Should pass + pass + + +class WithOverload(enum.IntEnum): + @overload + def meth(self, arg: int) -> int: pass + @overload + def meth(self, arg: str) -> str: pass + def meth(self, arg): pass + + alias = meth + +class SubWithOverload(WithOverload): # Should pass + pass +[builtins fixtures/tuple.pyi] diff --git a/test-data/unit/check-incremental.test b/test-data/unit/check-incremental.test index ec1dff4977d4e..1a73f9f33274b 100644 --- a/test-data/unit/check-incremental.test +++ b/test-data/unit/check-incremental.test @@ -5627,9 +5627,9 @@ class FinalEnum(Enum): [builtins fixtures/isinstance.pyi] [out] main:3: error: Cannot override writable attribute "x" with a final one -main:4: error: Cannot inherit from final class "FinalEnum" +main:4: error: Cannot extend enum with existing members: "FinalEnum" main:5: error: Cannot override final attribute "x" (previously declared in base class "FinalEnum") [out2] main:3: error: Cannot override writable attribute "x" with a final one -main:4: error: Cannot inherit from final class "FinalEnum" +main:4: error: Cannot extend enum with existing members: "FinalEnum" main:5: error: Cannot override final attribute "x" (previously declared in base class "FinalEnum") From bb4b5346dd5d1a6f8e1642024bb04d5250118b50 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Wed, 19 Jan 2022 12:58:25 +0000 Subject: [PATCH 070/377] Fix self-check when targeting Python 3.10 (#12020) This should fix wheel builds. Our CI always targets Python 3.6 when doing a self check, which means that we won't catch issues specific to more recent Python versions. --- mypy/fastparse.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mypy/fastparse.py b/mypy/fastparse.py index a5129fae1b743..5f9ec87e544fb 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -123,6 +123,7 @@ def ast3_parse(source: Union[str, bytes], filename: str, mode: str, MatchClass = ast3.MatchClass MatchAs = ast3.MatchAs MatchOr = ast3.MatchOr + AstNode = Union[ast3.expr, ast3.stmt, ast3.pattern, ast3.ExceptHandler] else: Match = Any MatchValue = Any @@ -133,6 +134,7 @@ def ast3_parse(source: Union[str, bytes], filename: str, mode: str, MatchClass = Any MatchAs = Any MatchOr = Any + AstNode = Union[ast3.expr, ast3.stmt, ast3.ExceptHandler] except ImportError: try: from typed_ast import ast35 # type: ignore[attr-defined] # noqa: F401 @@ -357,7 +359,7 @@ def visit(self, node: Optional[AST]) -> Any: self.visitor_cache[typeobj] = visitor return visitor(node) - def set_line(self, node: N, n: Union[ast3.expr, ast3.stmt, ast3.ExceptHandler]) -> N: + def set_line(self, node: N, n: AstNode) -> N: node.line = n.lineno node.column = n.col_offset node.end_line = getattr(n, "end_lineno", None) if isinstance(n, ast3.expr) else None From 0cec4f7a2e2c569b28f0ced916edd57903e57b7a Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Thu, 20 Jan 2022 17:31:01 +0300 Subject: [PATCH 071/377] Microrefactoring: removed useless var from `meet.py` (#12025) --- mypy/meet.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/mypy/meet.py b/mypy/meet.py index 2ea2bc62a660a..0b336aa6f8104 100644 --- a/mypy/meet.py +++ b/mypy/meet.py @@ -508,15 +508,14 @@ def visit_param_spec(self, t: ParamSpecType) -> ProperType: def visit_instance(self, t: Instance) -> ProperType: if isinstance(self.s, Instance): - si = self.s - if t.type == si.type: + if t.type == self.s.type: if is_subtype(t, self.s) or is_subtype(self.s, t): # Combine type arguments. We could have used join below # equivalently. args: List[Type] = [] # N.B: We use zip instead of indexing because the lengths might have # mismatches during daemon reprocessing. - for ta, sia in zip(t.args, si.args): + for ta, sia in zip(t.args, self.s.args): args.append(self.meet(ta, sia)) return Instance(t.type, args) else: From 6d243321d632c47b9fef5f2ad6a972f9f4b94eff Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sat, 22 Jan 2022 20:01:03 -0800 Subject: [PATCH 072/377] stubtest: treat dicts as a subtype of typeddict (#12040) --- mypy/stubtest.py | 8 ++++++++ mypy/test/teststubtest.py | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/mypy/stubtest.py b/mypy/stubtest.py index d0f62dfc3ed20..ac9a4ed97ceed 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -932,6 +932,14 @@ def is_subtype_helper(left: mypy.types.Type, right: mypy.types.Type) -> bool: # Pretend Literal[0, 1] is a subtype of bool to avoid unhelpful errors. return True + if ( + isinstance(right, mypy.types.TypedDictType) + and isinstance(left, mypy.types.Instance) + and left.type.fullname == "builtins.dict" + ): + # Special case checks against TypedDicts + return True + with mypy.state.strict_optional_set(True): return mypy.subtypes.is_subtype(left, right) diff --git a/mypy/test/teststubtest.py b/mypy/test/teststubtest.py index 6cc5560043376..988dcdab0a8eb 100644 --- a/mypy/test/teststubtest.py +++ b/mypy/test/teststubtest.py @@ -828,6 +828,41 @@ def test_bad_literal(self) -> Iterator[Case]: error='WRONG_BOOL_2', ) + @collect_cases + def test_special_subtype(self) -> Iterator[Case]: + yield Case( + stub=""" + b1: bool + b2: bool + b3: bool + """, + runtime=""" + b1 = 0 + b2 = 1 + b3 = 2 + """, + error="b3", + ) + yield Case( + stub=""" + from typing_extensions import TypedDict + + class _Options(TypedDict): + a: str + b: int + + opt1: _Options + opt2: _Options + opt3: _Options + """, + runtime=""" + opt1 = {"a": "3.", "b": 14} + opt2 = {"some": "stuff"} # false negative + opt3 = 0 + """, + error="opt3", + ) + def remove_color_code(s: str) -> str: return re.sub("\\x1b.*?m", "", s) # this works! From 619d9bdf7ae70ce953f1a10aebccfdc3526b7200 Mon Sep 17 00:00:00 2001 From: Alexandre Bouayad Date: Mon, 24 Jan 2022 01:40:30 +0100 Subject: [PATCH 073/377] Fix crash with yield in comprehension (#12048) Fixes #10189 Produce an error when encountering a yield expression (both `yield` and `yield from` clauses) in comprehensions and generator expressions. The latter is a syntax error in python 3.8+; see #10189 and also [python issue 10544](https://bugs.python.org/issue10544). --- mypy/semanal.py | 36 ++++++++++++---------- mypy/semanal_main.py | 2 +- test-data/unit/check-semanal-error.test | 41 +++++++++++++++++++++++-- 3 files changed, 60 insertions(+), 19 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index a7c5eda732af0..2a24c129b133a 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -3830,13 +3830,15 @@ def visit_star_expr(self, expr: StarExpr) -> None: expr.expr.accept(self) def visit_yield_from_expr(self, e: YieldFromExpr) -> None: - if not self.is_func_scope(): # not sure + if not self.is_func_scope(): self.fail('"yield from" outside function', e, serious=True, blocker=True) + elif self.is_comprehension_stack[-1]: + self.fail('"yield from" inside comprehension or generator expression', + e, serious=True, blocker=True) + elif self.function_stack[-1].is_coroutine: + self.fail('"yield from" in async function', e, serious=True, blocker=True) else: - if self.function_stack[-1].is_coroutine: - self.fail('"yield from" in async function', e, serious=True, blocker=True) - else: - self.function_stack[-1].is_generator = True + self.function_stack[-1].is_generator = True if e.expr: e.expr.accept(self) @@ -4214,20 +4216,22 @@ def visit__promote_expr(self, expr: PromoteExpr) -> None: if analyzed is not None: expr.type = analyzed - def visit_yield_expr(self, expr: YieldExpr) -> None: + def visit_yield_expr(self, e: YieldExpr) -> None: if not self.is_func_scope(): - self.fail('"yield" outside function', expr, serious=True, blocker=True) - else: - if self.function_stack[-1].is_coroutine: - if self.options.python_version < (3, 6): - self.fail('"yield" in async function', expr, serious=True, blocker=True) - else: - self.function_stack[-1].is_generator = True - self.function_stack[-1].is_async_generator = True + self.fail('"yield" outside function', e, serious=True, blocker=True) + elif self.is_comprehension_stack[-1]: + self.fail('"yield" inside comprehension or generator expression', + e, serious=True, blocker=True) + elif self.function_stack[-1].is_coroutine: + if self.options.python_version < (3, 6): + self.fail('"yield" in async function', e, serious=True, blocker=True) else: self.function_stack[-1].is_generator = True - if expr.expr: - expr.expr.accept(self) + self.function_stack[-1].is_async_generator = True + else: + self.function_stack[-1].is_generator = True + if e.expr: + e.expr.accept(self) def visit_await_expr(self, expr: AwaitExpr) -> None: if not self.is_func_scope(): diff --git a/mypy/semanal_main.py b/mypy/semanal_main.py index 7e187945da480..d935252ba9cf8 100644 --- a/mypy/semanal_main.py +++ b/mypy/semanal_main.py @@ -307,7 +307,7 @@ def semantic_analyze_target(target: str, Return tuple with these items: - list of deferred targets - was some definition incomplete (need to run another pass) - - were any new names were defined (or placeholders replaced) + - were any new names defined (or placeholders replaced) """ state.manager.processed_targets.append(target) tree = state.tree diff --git a/test-data/unit/check-semanal-error.test b/test-data/unit/check-semanal-error.test index f91e3b1360c72..c6cf45d96691d 100644 --- a/test-data/unit/check-semanal-error.test +++ b/test-data/unit/check-semanal-error.test @@ -77,10 +77,47 @@ continue # E: "continue" outside loop [case testYieldOutsideFunction] yield # E: "yield" outside function - -[case testYieldFromOutsideFunction] x = 1 yield from x # E: "yield from" outside function +[(yield 1) for _ in x] # E: "yield" inside comprehension or generator expression +{(yield 1) for _ in x} # E: "yield" inside comprehension or generator expression +{i: (yield 1) for i in x} # E: "yield" inside comprehension or generator expression +((yield 1) for _ in x) # E: "yield" inside comprehension or generator expression +y = 1 +[(yield from x) for _ in y] # E: "yield from" inside comprehension or generator expression +{(yield from x) for _ in y} # E: "yield from" inside comprehension or generator expression +{i: (yield from x) for i in y} # E: "yield from" inside comprehension or generator expression +((yield from x) for _ in y) # E: "yield from" inside comprehension or generator expression +def f(y): + [x for x in (yield y)] + {x for x in (yield y)} + {x: x for x in (yield y)} + (x for x in (yield y)) + [x for x in (yield from y)] + {x for x in (yield from y)} + {x: x for x in (yield from y)} + (x for x in (yield from y)) +def g(y): + [(yield 1) for _ in y] # E: "yield" inside comprehension or generator expression + {(yield 1) for _ in y} # E: "yield" inside comprehension or generator expression + {i: (yield 1) for i in y} # E: "yield" inside comprehension or generator expression + ((yield 1) for _ in y) # E: "yield" inside comprehension or generator expression + lst = 1 + [(yield from lst) for _ in y] # E: "yield from" inside comprehension or generator expression + {(yield from lst) for _ in y} # E: "yield from" inside comprehension or generator expression + {i: (yield from lst) for i in y} # E: "yield from" inside comprehension or generator expression + ((yield from lst) for _ in y) # E: "yield from" inside comprehension or generator expression +def h(y): + lst = 1 + [x for x in lst if (yield y)] # E: "yield" inside comprehension or generator expression + {x for x in lst if (yield y)} # E: "yield" inside comprehension or generator expression + {x: x for x in lst if (yield y)} # E: "yield" inside comprehension or generator expression + (x for x in lst if (yield y)) # E: "yield" inside comprehension or generator expression + lst = 1 + [x for x in lst if (yield from y)] # E: "yield from" inside comprehension or generator expression + {x for x in lst if (yield from y)} # E: "yield from" inside comprehension or generator expression + {x: x for x in lst if (yield from y)} # E: "yield from" inside comprehension or generator expression + (x for x in lst if (yield from y)) # E: "yield from" inside comprehension or generator expression [case testImportFuncDup] From af366c0d53b3cfe1bed1baba4e2869460276eb81 Mon Sep 17 00:00:00 2001 From: Matt Bogosian Date: Mon, 24 Jan 2022 07:11:55 -0600 Subject: [PATCH 074/377] Explain generic `Protocol[T1, T2, ...]` shorthand in Mypy docs (#12047) As far as I can tell, the nugget exposed by this commit lives only in PEP 544. This copies that nugget closer to where it is likely to be spotted by the intended audience. PEPs may not be accessible to customers who reasonably expect relevant information to be surfaced in featured documentation. Even if customers are aware of PEPs, they may not think to look there, and don't likely consider them primary sources. It is reasonable to assume that is the job of the docs, with PEPs capturing more esoteric nuances, rationales and other then-relevant details of decision-making, etc. It's also reasonable to expect that where further study may be helpful, links from relevant sections of primary sources to secondary materials like PEPs should exist. This commit fills in both gaps for the subject shorthand. --- docs/source/generics.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/source/generics.rst b/docs/source/generics.rst index 7e64aa1814038..7730bd0e5c108 100644 --- a/docs/source/generics.rst +++ b/docs/source/generics.rst @@ -673,6 +673,10 @@ protocols mostly follow the normal rules for generic classes. Example: y: Box[int] = ... x = y # Error -- Box is invariant +Per :pep:`PEP 544: Generic protocols <544#generic-protocols>`, ``class +ClassName(Protocol[T])`` is allowed as a shorthand for ``class +ClassName(Protocol, Generic[T])``. + The main difference between generic protocols and ordinary generic classes is that mypy checks that the declared variances of generic type variables in a protocol match how they are used in the protocol From 36804497279809675fd4651eefb023aad4918efa Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Tue, 25 Jan 2022 15:08:51 +0000 Subject: [PATCH 075/377] Simplify unions when erasing last known values (#12064) When we erase last known values in an union with multiple Instance types, make sure that the resulting union doesn't have duplicate erased types. The duplicate items weren't incorrect as such, but they could cause overly complex error messages and potentially slow type checking performance. This is one of the fixes extracted from #12054. Since some of the changes may cause regressions, it's better to split the PR. Work on #12051. Co-authored-by: Nikita Sobolev --- mypy/erasetype.py | 35 +++++++++++++++++++++++-- mypy/test/testtypes.py | 48 ++++++++++++++++++++++++++++++++-- mypy/test/typefixture.py | 2 ++ test-data/unit/check-enum.test | 14 ++++++++++ 4 files changed, 95 insertions(+), 4 deletions(-) diff --git a/mypy/erasetype.py b/mypy/erasetype.py index 3301325eb0a18..f33b4f3a95cce 100644 --- a/mypy/erasetype.py +++ b/mypy/erasetype.py @@ -1,10 +1,10 @@ -from typing import Optional, Container, Callable +from typing import Optional, Container, Callable, List, Dict, cast from mypy.types import ( Type, TypeVisitor, UnboundType, AnyType, NoneType, TypeVarId, Instance, TypeVarType, CallableType, TupleType, TypedDictType, UnionType, Overloaded, ErasedType, PartialType, DeletedType, TypeTranslator, UninhabitedType, TypeType, TypeOfAny, LiteralType, ProperType, - get_proper_type, TypeAliasType, ParamSpecType + get_proper_type, get_proper_types, TypeAliasType, ParamSpecType ) from mypy.nodes import ARG_STAR, ARG_STAR2 @@ -161,3 +161,34 @@ def visit_type_alias_type(self, t: TypeAliasType) -> Type: # Type aliases can't contain literal values, because they are # always constructed as explicit types. return t + + def visit_union_type(self, t: UnionType) -> Type: + new = cast(UnionType, super().visit_union_type(t)) + # Erasure can result in many duplicate items; merge them. + # Call make_simplified_union only on lists of instance types + # that all have the same fullname, to avoid simplifying too + # much. + instances = [item for item in new.items + if isinstance(get_proper_type(item), Instance)] + # Avoid merge in simple cases such as optional types. + if len(instances) > 1: + instances_by_name: Dict[str, List[Instance]] = {} + new_items = get_proper_types(new.items) + for item in new_items: + if isinstance(item, Instance) and not item.args: + instances_by_name.setdefault(item.type.fullname, []).append(item) + merged: List[Type] = [] + for item in new_items: + if isinstance(item, Instance) and not item.args: + types = instances_by_name.get(item.type.fullname) + if types is not None: + if len(types) == 1: + merged.append(item) + else: + from mypy.typeops import make_simplified_union + merged.append(make_simplified_union(types)) + del instances_by_name[item.type.fullname] + else: + merged.append(item) + return UnionType.make_union(merged) + return new diff --git a/mypy/test/testtypes.py b/mypy/test/testtypes.py index 0d37fe795bbcd..6af1c18145cfe 100644 --- a/mypy/test/testtypes.py +++ b/mypy/test/testtypes.py @@ -3,7 +3,7 @@ from typing import List, Tuple from mypy.test.helpers import Suite, assert_equal, assert_type, skip -from mypy.erasetype import erase_type +from mypy.erasetype import erase_type, remove_instance_last_known_values from mypy.expandtype import expand_type from mypy.join import join_types, join_simple from mypy.meet import meet_types, narrow_declared_type @@ -11,7 +11,8 @@ from mypy.indirection import TypeIndirectionVisitor from mypy.types import ( UnboundType, AnyType, CallableType, TupleType, TypeVarType, Type, Instance, NoneType, - Overloaded, TypeType, UnionType, UninhabitedType, TypeVarId, TypeOfAny, get_proper_type + Overloaded, TypeType, UnionType, UninhabitedType, TypeVarId, TypeOfAny, ProperType, + get_proper_type ) from mypy.nodes import ARG_POS, ARG_OPT, ARG_STAR, ARG_STAR2, CONTRAVARIANT, INVARIANT, COVARIANT from mypy.subtypes import is_subtype, is_more_precise, is_proper_subtype @@ -1092,3 +1093,46 @@ def assert_simple_is_same(self, s: Type, t: Type, expected: bool, strict: bool) '({} == {}) is {{}} ({{}} expected)'.format(s, t)) assert_equal(hash(s) == hash(t), expected, '(hash({}) == hash({}) is {{}} ({{}} expected)'.format(s, t)) + + +class RemoveLastKnownValueSuite(Suite): + def setUp(self) -> None: + self.fx = TypeFixture() + + def test_optional(self) -> None: + t = UnionType.make_union([self.fx.a, self.fx.nonet]) + self.assert_union_result(t, [self.fx.a, self.fx.nonet]) + + def test_two_instances(self) -> None: + t = UnionType.make_union([self.fx.a, self.fx.b]) + self.assert_union_result(t, [self.fx.a, self.fx.b]) + + def test_multiple_same_instances(self) -> None: + t = UnionType.make_union([self.fx.a, self.fx.a]) + assert remove_instance_last_known_values(t) == self.fx.a + t = UnionType.make_union([self.fx.a, self.fx.a, self.fx.b]) + self.assert_union_result(t, [self.fx.a, self.fx.b]) + t = UnionType.make_union([self.fx.a, self.fx.nonet, self.fx.a, self.fx.b]) + self.assert_union_result(t, [self.fx.a, self.fx.nonet, self.fx.b]) + + def test_single_last_known_value(self) -> None: + t = UnionType.make_union([self.fx.lit1_inst, self.fx.nonet]) + self.assert_union_result(t, [self.fx.a, self.fx.nonet]) + + def test_last_known_values_with_merge(self) -> None: + t = UnionType.make_union([self.fx.lit1_inst, self.fx.lit2_inst, self.fx.lit4_inst]) + assert remove_instance_last_known_values(t) == self.fx.a + t = UnionType.make_union([self.fx.lit1_inst, + self.fx.b, + self.fx.lit2_inst, + self.fx.lit4_inst]) + self.assert_union_result(t, [self.fx.a, self.fx.b]) + + def test_generics(self) -> None: + t = UnionType.make_union([self.fx.ga, self.fx.gb]) + self.assert_union_result(t, [self.fx.ga, self.fx.gb]) + + def assert_union_result(self, t: ProperType, expected: List[Type]) -> None: + t2 = remove_instance_last_known_values(t) + assert type(t2) is UnionType + assert t2.items == expected diff --git a/mypy/test/typefixture.py b/mypy/test/typefixture.py index 1a5dd81641362..7d4faeccf432b 100644 --- a/mypy/test/typefixture.py +++ b/mypy/test/typefixture.py @@ -157,9 +157,11 @@ def make_type_var(name: str, id: int, values: List[Type], upper_bound: Type, self.lit1 = LiteralType(1, self.a) self.lit2 = LiteralType(2, self.a) self.lit3 = LiteralType("foo", self.d) + self.lit4 = LiteralType(4, self.a) self.lit1_inst = Instance(self.ai, [], last_known_value=self.lit1) self.lit2_inst = Instance(self.ai, [], last_known_value=self.lit2) self.lit3_inst = Instance(self.di, [], last_known_value=self.lit3) + self.lit4_inst = Instance(self.ai, [], last_known_value=self.lit4) self.type_a = TypeType.make_normalized(self.a) self.type_b = TypeType.make_normalized(self.b) diff --git a/test-data/unit/check-enum.test b/test-data/unit/check-enum.test index 2af57da9cbdc4..92982ef30b4e4 100644 --- a/test-data/unit/check-enum.test +++ b/test-data/unit/check-enum.test @@ -1868,3 +1868,17 @@ class WithOverload(enum.IntEnum): class SubWithOverload(WithOverload): # Should pass pass [builtins fixtures/tuple.pyi] + +[case testEnumtValueUnionSimplification] +from enum import IntEnum +from typing import Any + +class C(IntEnum): + X = 0 + Y = 1 + Z = 2 + +def f1(c: C) -> None: + x = {'x': c.value} + reveal_type(x) # N: Revealed type is "builtins.dict[builtins.str*, builtins.int]" +[builtins fixtures/dict.pyi] From fb94f80dfc75e54b68a1819213cee553d3b41eee Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Tue, 25 Jan 2022 16:44:25 +0000 Subject: [PATCH 076/377] Fix join of Any against a union type (#12068) Make the join of a union type and Any commutative. Previously the result depended on the order of the operands, which was clearly incorrect. Fix #12051, but other use cases are affected as well. This change was split off from #12054. --- mypy/join.py | 6 +++--- test-data/unit/check-enum.test | 6 ++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/mypy/join.py b/mypy/join.py index d298b495fdc51..161c65ea800cd 100644 --- a/mypy/join.py +++ b/mypy/join.py @@ -175,15 +175,15 @@ def join_types(s: Type, t: Type, instance_joiner: Optional[InstanceJoiner] = Non s = mypy.typeops.true_or_false(s) t = mypy.typeops.true_or_false(t) + if isinstance(s, UnionType) and not isinstance(t, UnionType): + s, t = t, s + if isinstance(s, AnyType): return s if isinstance(s, ErasedType): return t - if isinstance(s, UnionType) and not isinstance(t, UnionType): - s, t = t, s - if isinstance(s, NoneType) and not isinstance(t, NoneType): s, t = t, s diff --git a/test-data/unit/check-enum.test b/test-data/unit/check-enum.test index 92982ef30b4e4..3d7c3fc3a392d 100644 --- a/test-data/unit/check-enum.test +++ b/test-data/unit/check-enum.test @@ -1881,4 +1881,10 @@ class C(IntEnum): def f1(c: C) -> None: x = {'x': c.value} reveal_type(x) # N: Revealed type is "builtins.dict[builtins.str*, builtins.int]" + +def f2(c: C, a: Any) -> None: + x = {'x': c.value, 'y': a} + reveal_type(x) # N: Revealed type is "builtins.dict[builtins.str*, Any]" + y = {'y': a, 'x': c.value} + reveal_type(y) # N: Revealed type is "builtins.dict[builtins.str*, Any]" [builtins fixtures/dict.pyi] From 99f4d5af147d364eda1d4b99e79770c171896f13 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Tue, 25 Jan 2022 16:54:40 +0000 Subject: [PATCH 077/377] Add note about wrong error code in type: ignore (#12067) If we change the error code of a message, it can result in existing "type: ignore" comments being ignored. If this seems to be the case, add a note that hints about changing the ignored error code. Give a more specific message for a set of special cased error codes where we know the original error code. In other cases give a more vague message. --- mypy/errors.py | 23 +++++++++ test-data/unit/check-errorcodes.test | 71 +++++++++++++++++++++------- 2 files changed, 76 insertions(+), 18 deletions(-) diff --git a/mypy/errors.py b/mypy/errors.py index c711456468ed4..ec49541a15a51 100644 --- a/mypy/errors.py +++ b/mypy/errors.py @@ -16,8 +16,13 @@ from mypy.util import DEFAULT_SOURCE_OFFSET, is_typeshed_file T = TypeVar("T") + allowed_duplicates: Final = ["@overload", "Got:", "Expected:"] +# Keep track of the original error code when the error code of a message is changed. +# This is used to give notes about out-of-date "type: ignore" comments. +original_error_codes: Final = {codes.LITERAL_REQ: codes.MISC} + class ErrorInfo: """Representation of a single error message.""" @@ -388,6 +393,24 @@ def add_error_info(self, info: ErrorInfo) -> None: info.hidden = True self.report_hidden_errors(info) self._add_error_info(file, info) + ignored_codes = self.ignored_lines.get(file, {}).get(info.line, []) + if ignored_codes and info.code: + # Something is ignored on the line, but not this error, so maybe the error + # code is incorrect. + msg = f'Error code "{info.code.code}" not covered by "type: ignore" comment' + if info.code in original_error_codes: + # If there seems to be a "type: ignore" with a stale error + # code, report a more specific note. + old_code = original_error_codes[info.code].code + if old_code in ignored_codes: + msg = (f'Error code changed to {info.code.code}; "type: ignore" comment ' + + 'may be out of date') + note = ErrorInfo( + info.import_ctx, info.file, info.module, info.type, info.function_or_member, + info.line, info.column, 'note', msg, + code=None, blocker=False, only_once=False, allow_dups=False + ) + self._add_error_info(file, note) def has_many_errors(self) -> bool: if self.many_errors_threshold < 0: diff --git a/test-data/unit/check-errorcodes.test b/test-data/unit/check-errorcodes.test index 568d3a9522f92..177612959354f 100644 --- a/test-data/unit/check-errorcodes.test +++ b/test-data/unit/check-errorcodes.test @@ -75,41 +75,51 @@ for v in f(): # type: int, int # E: Syntax error in type annotation [syntax] [case testErrorCodeIgnore1] 'x'.foobar # type: ignore[attr-defined] -'x'.foobar # type: ignore[xyz] # E: "str" has no attribute "foobar" [attr-defined] +'x'.foobar # type: ignore[xyz] # E: "str" has no attribute "foobar" [attr-defined] \ + # N: Error code "attr-defined" not covered by "type: ignore" comment 'x'.foobar # type: ignore [case testErrorCodeIgnore2] a = 'x'.foobar # type: int # type: ignore[attr-defined] -b = 'x'.foobar # type: int # type: ignore[xyz] # E: "str" has no attribute "foobar" [attr-defined] +b = 'x'.foobar # type: int # type: ignore[xyz] # E: "str" has no attribute "foobar" [attr-defined] \ + # N: Error code "attr-defined" not covered by "type: ignore" comment c = 'x'.foobar # type: int # type: ignore [case testErrorCodeIgnore1_python2] 'x'.foobar # type: ignore[attr-defined] -'x'.foobar # type: ignore[xyz] # E: "str" has no attribute "foobar" [attr-defined] +'x'.foobar # type: ignore[xyz] # E: "str" has no attribute "foobar" [attr-defined] \ + # N: Error code "attr-defined" not covered by "type: ignore" comment 'x'.foobar # type: ignore [case testErrorCodeIgnore2_python2] a = 'x'.foobar # type: int # type: ignore[attr-defined] -b = 'x'.foobar # type: int # type: ignore[xyz] # E: "str" has no attribute "foobar" [attr-defined] +b = 'x'.foobar # type: int # type: ignore[xyz] # E: "str" has no attribute "foobar" [attr-defined] \ + # N: Error code "attr-defined" not covered by "type: ignore" comment c = 'x'.foobar # type: int # type: ignore [case testErrorCodeIgnoreMultiple1] a = 'x'.foobar(b) # type: ignore[name-defined, attr-defined] -a = 'x'.foobar(b) # type: ignore[name-defined, xyz] # E: "str" has no attribute "foobar" [attr-defined] -a = 'x'.foobar(b) # type: ignore[xyz, w, attr-defined] # E: Name "b" is not defined [name-defined] +a = 'x'.foobar(b) # type: ignore[name-defined, xyz] # E: "str" has no attribute "foobar" [attr-defined] \ + # N: Error code "attr-defined" not covered by "type: ignore" comment +a = 'x'.foobar(b) # type: ignore[xyz, w, attr-defined] # E: Name "b" is not defined [name-defined] \ + # N: Error code "name-defined" not covered by "type: ignore" comment [case testErrorCodeIgnoreMultiple2] a = 'x'.foobar(b) # type: int # type: ignore[name-defined, attr-defined] -b = 'x'.foobar(b) # type: int # type: ignore[name-defined, xyz] # E: "str" has no attribute "foobar" [attr-defined] +b = 'x'.foobar(b) # type: int # type: ignore[name-defined, xyz] # E: "str" has no attribute "foobar" [attr-defined] \ + # N: Error code "attr-defined" not covered by "type: ignore" comment [case testErrorCodeIgnoreMultiple1_python2] a = 'x'.foobar(b) # type: ignore[name-defined, attr-defined] -a = 'x'.foobar(b) # type: ignore[name-defined, xyz] # E: "str" has no attribute "foobar" [attr-defined] -a = 'x'.foobar(b) # type: ignore[xyz, w, attr-defined] # E: Name "b" is not defined [name-defined] +a = 'x'.foobar(b) # type: ignore[name-defined, xyz] # E: "str" has no attribute "foobar" [attr-defined] \ + # N: Error code "attr-defined" not covered by "type: ignore" comment +a = 'x'.foobar(b) # type: ignore[xyz, w, attr-defined] # E: Name "b" is not defined [name-defined] \ + # N: Error code "name-defined" not covered by "type: ignore" comment [case testErrorCodeIgnoreMultiple2_python2] a = 'x'.foobar(b) # type: int # type: ignore[name-defined, attr-defined] -b = 'x'.foobar(b) # type: int # type: ignore[name-defined, xyz] # E: "str" has no attribute "foobar" [attr-defined] +b = 'x'.foobar(b) # type: int # type: ignore[name-defined, xyz] # E: "str" has no attribute "foobar" [attr-defined] \ + # N: Error code "attr-defined" not covered by "type: ignore" comment [case testErrorCodeWarnUnusedIgnores1] # flags: --warn-unused-ignores @@ -140,16 +150,22 @@ x # type: ignore [name-defined] x2 # type: ignore [ name-defined ] x3 # type: ignore [ xyz , name-defined ] x4 # type: ignore[xyz,name-defined] -y # type: ignore [xyz] # E: Name "y" is not defined [name-defined] -y # type: ignore[ xyz ] # E: Name "y" is not defined [name-defined] -y # type: ignore[ xyz , foo ] # E: Name "y" is not defined [name-defined] +y # type: ignore [xyz] # E: Name "y" is not defined [name-defined] \ + # N: Error code "name-defined" not covered by "type: ignore" comment +y # type: ignore[ xyz ] # E: Name "y" is not defined [name-defined] \ + # N: Error code "name-defined" not covered by "type: ignore" comment +y # type: ignore[ xyz , foo ] # E: Name "y" is not defined [name-defined] \ + # N: Error code "name-defined" not covered by "type: ignore" comment a = z # type: int # type: ignore [name-defined] b = z2 # type: int # type: ignore [ name-defined ] c = z2 # type: int # type: ignore [ name-defined , xyz ] -d = zz # type: int # type: ignore [xyz] # E: Name "zz" is not defined [name-defined] -e = zz # type: int # type: ignore [ xyz ] # E: Name "zz" is not defined [name-defined] -f = zz # type: int # type: ignore [ xyz,foo ] # E: Name "zz" is not defined [name-defined] +d = zz # type: int # type: ignore [xyz] # E: Name "zz" is not defined [name-defined] \ + # N: Error code "name-defined" not covered by "type: ignore" comment +e = zz # type: int # type: ignore [ xyz ] # E: Name "zz" is not defined [name-defined] \ + # N: Error code "name-defined" not covered by "type: ignore" comment +f = zz # type: int # type: ignore [ xyz,foo ] # E: Name "zz" is not defined [name-defined] \ + # N: Error code "name-defined" not covered by "type: ignore" comment [case testErrorCodeIgnoreAfterArgComment] def f(x # type: xyz # type: ignore[name-defined] # Comment @@ -162,7 +178,8 @@ def g(x # type: xyz # type: ignore # Comment # type () -> None pass -def h(x # type: xyz # type: ignore[foo] # E: Name "xyz" is not defined [name-defined] +def h(x # type: xyz # type: ignore[foo] # E: Name "xyz" is not defined [name-defined] \ + # N: Error code "name-defined" not covered by "type: ignore" comment ): # type () -> None pass @@ -178,7 +195,8 @@ def g(x # type: xyz # type: ignore # Comment # type () -> None pass -def h(x # type: xyz # type: ignore[foo] # E: Name "xyz" is not defined [name-defined] +def h(x # type: xyz # type: ignore[foo] # E: Name "xyz" is not defined [name-defined] \ + # N: Error code "name-defined" not covered by "type: ignore" comment ): # type () -> None pass @@ -944,3 +962,20 @@ class TensorType: ... t: TensorType["batch":..., float] # type: ignore reveal_type(t) # N: Revealed type is "__main__.TensorType" [builtins fixtures/tuple.pyi] + +[case testNoteAboutChangedTypedDictErrorCode] +from typing_extensions import TypedDict +class D(TypedDict): + x: int + +def f(d: D, s: str) -> None: + d[s] # type: ignore[xyz] \ + # E: TypedDict key must be a string literal; expected one of ("x") [literal-required] \ + # N: Error code "literal-required" not covered by "type: ignore" comment + d[s] # E: TypedDict key must be a string literal; expected one of ("x") [literal-required] + d[s] # type: ignore[misc] \ + # E: TypedDict key must be a string literal; expected one of ("x") [literal-required] \ + # N: Error code changed to literal-required; "type: ignore" comment may be out of date + d[s] # type: ignore[literal-required] +[builtins fixtures/dict.pyi] +[typing fixtures/typing-typeddict.pyi] From d5d077bbc684e5d9aabb6ac9d9c10e393efc37aa Mon Sep 17 00:00:00 2001 From: Mehdi Drissi Date: Wed, 26 Jan 2022 10:44:33 -0600 Subject: [PATCH 078/377] Fix crash involving explicit any flag and Required (#12039) Co-authored-by: Mehdi Drissi --- mypy/types.py | 3 +++ test-data/unit/check-typeddict.test | 13 +++++++++++++ test-data/unit/fixtures/typing-typeddict.pyi | 3 ++- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/mypy/types.py b/mypy/types.py index d3987897995ed..1d7ab669a2d4e 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -360,6 +360,9 @@ def __repr__(self) -> str: else: return "NotRequired[{}]".format(self.item) + def accept(self, visitor: 'TypeVisitor[T]') -> T: + return self.item.accept(visitor) + class ProperType(Type): """Not a type alias. diff --git a/test-data/unit/check-typeddict.test b/test-data/unit/check-typeddict.test index 921d2ab5c46ef..a9321826b3ba4 100644 --- a/test-data/unit/check-typeddict.test +++ b/test-data/unit/check-typeddict.test @@ -2208,6 +2208,12 @@ class Movie(TypedDict, total=False): year: int [typing fixtures/typing-typeddict.pyi] +[case testRequiredExplicitAny] +# flags: --disallow-any-explicit +from typing import TypedDict +from typing import Required +Foo = TypedDict("Foo", {"a.x": Required[int]}) +[typing fixtures/typing-typeddict.pyi] -- NotRequired[] @@ -2271,6 +2277,13 @@ class Movie(TypedDict): year: int [typing fixtures/typing-typeddict.pyi] +[case testNotRequiredExplicitAny] +# flags: --disallow-any-explicit +from typing import TypedDict +from typing import NotRequired +Foo = TypedDict("Foo", {"a.x": NotRequired[int]}) +[typing fixtures/typing-typeddict.pyi] + -- Union dunders [case testTypedDictUnionGetItem] diff --git a/test-data/unit/fixtures/typing-typeddict.pyi b/test-data/unit/fixtures/typing-typeddict.pyi index 72f5007070940..378570b4c19c8 100644 --- a/test-data/unit/fixtures/typing-typeddict.pyi +++ b/test-data/unit/fixtures/typing-typeddict.pyi @@ -43,7 +43,8 @@ class Iterator(Iterable[T_co], Protocol): def __next__(self) -> T_co: pass class Sequence(Iterable[T_co]): - def __getitem__(self, n: Any) -> T_co: pass + # misc is for explicit Any. + def __getitem__(self, n: Any) -> T_co: pass # type: ignore[misc] class Mapping(Iterable[T], Generic[T, T_co], metaclass=ABCMeta): def __getitem__(self, key: T) -> T_co: pass From a825c15bce10caf10e7a468e94571abeee77b69c Mon Sep 17 00:00:00 2001 From: Matt Bogosian Date: Wed, 26 Jan 2022 18:44:30 -0600 Subject: [PATCH 079/377] Fix error in `exclude` section (#12078) Brings INI and TOML examples in line as noted. --- docs/source/config_file.rst | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/source/config_file.rst b/docs/source/config_file.rst index 26589e71e86b6..c9c79ee86f473 100644 --- a/docs/source/config_file.rst +++ b/docs/source/config_file.rst @@ -237,8 +237,9 @@ section of the command line docs. [tool.mypy] exclude = [ - "^file1\\.py$", # TOML's double-quoted strings require escaping backslashes - '^file2\.py$', # but TOML's single-quoted strings do not + "^one\.py$", # TOML's double-quoted strings require escaping backslashes + 'two\.pyi$', # but TOML's single-quoted strings do not + '^three\.', ] A single, multi-line string: @@ -247,9 +248,10 @@ section of the command line docs. [tool.mypy] exclude = '''(?x)( - ^file1\.py$ - |^file2\.py$, - )''' + ^one\.py$ # files named "one.py" + | two\.pyi$ # or files ending with "two.pyi" + | ^three\. # or files starting with "three." + )''' # TOML's single-quoted strings do not require escaping backslashes See :ref:`using-a-pyproject-toml`. From e2852039bafaf0d7463623dd5410c02797eae21b Mon Sep 17 00:00:00 2001 From: KotlinIsland <65446343+KotlinIsland@users.noreply.github.com> Date: Thu, 27 Jan 2022 12:06:08 +1000 Subject: [PATCH 080/377] [docs] add more info to allow_redefinition (#11951) --- docs/source/command_line.rst | 11 ++++++++++- docs/source/config_file.rst | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/docs/source/command_line.rst b/docs/source/command_line.rst index fb30245794f7e..36c13910c21a3 100644 --- a/docs/source/command_line.rst +++ b/docs/source/command_line.rst @@ -524,7 +524,16 @@ of the above sections. # 'items' has type list[str] items = [item.split() for item in items] # 'items' now has type list[list[str]] - ... + + The variable must be used before it can be redefined: + + .. code-block:: python + + def process(items: list[str]) -> None: + items = "mypy" # invalid redefinition to str because the variable hasn't been used yet + print(items) + items = "100" # valid, items now has type str + items = int(items) # valid, items now has type int .. option:: --local-partial-types diff --git a/docs/source/config_file.rst b/docs/source/config_file.rst index c9c79ee86f473..0b53f1ca53703 100644 --- a/docs/source/config_file.rst +++ b/docs/source/config_file.rst @@ -615,6 +615,24 @@ section of the command line docs. Allows variables to be redefined with an arbitrary type, as long as the redefinition is in the same block and nesting level as the original definition. + Example where this can be useful: + + .. code-block:: python + + def process(items: list[str]) -> None: + # 'items' has type list[str] + items = [item.split() for item in items] + # 'items' now has type list[list[str]] + + The variable must be used before it can be redefined: + + .. code-block:: python + + def process(items: list[str]) -> None: + items = "mypy" # invalid redefinition to str because the variable hasn't been used yet + print(items) + items = "100" # valid, items now has type str + items = int(items) # valid, items now has type int .. confval:: local_partial_types From b36d8cf5d4d0bb77c5a8cf783ba4def16cd9846a Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Thu, 27 Jan 2022 07:01:23 -0800 Subject: [PATCH 081/377] stubtest: use VERSIONS for submodules (#12083) Closes #12062 Addresses feedback in #12066 --- mypy/stubtest.py | 26 +++++++++++++++++--------- mypy/test/teststubtest.py | 11 +++++++++-- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/mypy/stubtest.py b/mypy/stubtest.py index ac9a4ed97ceed..4ca088d8aa3ee 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -1107,19 +1107,27 @@ def get_stub(module: str) -> Optional[nodes.MypyFile]: return _all_stubs.get(module) -def get_typeshed_stdlib_modules(custom_typeshed_dir: Optional[str]) -> List[str]: +def get_typeshed_stdlib_modules( + custom_typeshed_dir: Optional[str], + version_info: Optional[Tuple[int, int]] = None +) -> List[str]: """Returns a list of stdlib modules in typeshed (for current Python version).""" stdlib_py_versions = mypy.modulefinder.load_stdlib_py_versions(custom_typeshed_dir) - packages = set() + if version_info is None: + version_info = sys.version_info[0:2] # Typeshed's minimum supported Python 3 is Python 3.6 if sys.version_info < (3, 6): version_info = (3, 6) - else: - version_info = sys.version_info[0:2] - for module, versions in stdlib_py_versions.items(): - minver, maxver = versions - if version_info >= minver and (maxver is None or version_info <= maxver): - packages.add(module) + + def exists_in_version(module: str) -> bool: + assert version_info is not None + parts = module.split(".") + for i in range(len(parts), 0, -1): + current_module = ".".join(parts[:i]) + if current_module in stdlib_py_versions: + minver, maxver = stdlib_py_versions[current_module] + return version_info >= minver and (maxver is None or version_info <= maxver) + return False if custom_typeshed_dir: typeshed_dir = Path(custom_typeshed_dir) @@ -1132,7 +1140,7 @@ def get_typeshed_stdlib_modules(custom_typeshed_dir: Optional[str]) -> List[str] if path.stem == "__init__": path = path.parent module = ".".join(path.relative_to(stdlib_dir).parts[:-1] + (path.stem,)) - if module.split(".")[0] in packages: + if exists_in_version(module): modules.append(module) return sorted(modules) diff --git a/mypy/test/teststubtest.py b/mypy/test/teststubtest.py index 988dcdab0a8eb..30ed953d73900 100644 --- a/mypy/test/teststubtest.py +++ b/mypy/test/teststubtest.py @@ -983,12 +983,19 @@ def test_missing_stubs(self) -> None: assert "error: not_a_module failed to find stubs" in remove_color_code(output.getvalue()) def test_get_typeshed_stdlib_modules(self) -> None: - stdlib = mypy.stubtest.get_typeshed_stdlib_modules(None) + stdlib = mypy.stubtest.get_typeshed_stdlib_modules(None, (3, 6)) assert "builtins" in stdlib assert "os" in stdlib assert "os.path" in stdlib assert "asyncio" in stdlib - assert ("dataclasses" in stdlib) == (sys.version_info >= (3, 7)) + assert "graphlib" not in stdlib + assert "formatter" in stdlib + assert "importlib.metadata" not in stdlib + + stdlib = mypy.stubtest.get_typeshed_stdlib_modules(None, (3, 10)) + assert "graphlib" in stdlib + assert "formatter" not in stdlib + assert "importlib.metadata" in stdlib def test_signature(self) -> None: def f(a: int, b: int, *, c: int, d: int = 0, **kwargs: Any) -> None: From e266cdf04f7ded2ee2da89b5912402df52a8e254 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Fri, 28 Jan 2022 00:37:28 -0800 Subject: [PATCH 082/377] Sync typeshed (#11905) Source commit: https://github.com/python/typeshed/commit/9116b2928d63632cb9c9526b18d1ffafaf5bafa4 * Fix self check * update testDictWithStarStarSpecialCase * update testTypedDictMappingMethods * xfail testAsyncioGatherPreciseType Co-authored-by: hauntsaninja <> --- mypy/fscache.py | 9 +- .../stdlib/@python2/_typeshed/xml.pyi | 3 +- mypy/typeshed/stdlib/@python2/_winreg.pyi | 174 +-- mypy/typeshed/stdlib/@python2/contextlib.pyi | 3 +- mypy/typeshed/stdlib/@python2/crypt.pyi | 5 +- .../stdlib/@python2/ctypes/__init__.pyi | 2 +- .../@python2/distutils/command/bdist_msi.pyi | 12 +- mypy/typeshed/stdlib/@python2/fcntl.pyi | 155 +-- mypy/typeshed/stdlib/@python2/grp.pyi | 19 +- mypy/typeshed/stdlib/@python2/pty.pyi | 23 +- mypy/typeshed/stdlib/@python2/pwd.pyi | 25 +- mypy/typeshed/stdlib/@python2/readline.pyi | 57 +- mypy/typeshed/stdlib/@python2/resource.pyi | 84 +- mypy/typeshed/stdlib/@python2/spwd.pyi | 27 +- mypy/typeshed/stdlib/@python2/syslog.pyi | 83 +- mypy/typeshed/stdlib/@python2/termios.pyi | 484 ++++---- mypy/typeshed/stdlib/@python2/tty.pyi | 23 +- mypy/typeshed/stdlib/@python2/types.pyi | 2 +- mypy/typeshed/stdlib/VERSIONS | 9 +- mypy/typeshed/stdlib/_bisect.pyi | 20 +- mypy/typeshed/stdlib/_codecs.pyi | 22 +- mypy/typeshed/stdlib/_compat_pickle.pyi | 10 +- mypy/typeshed/stdlib/_compression.pyi | 4 +- mypy/typeshed/stdlib/_csv.pyi | 6 +- mypy/typeshed/stdlib/_curses.pyi | 1089 ++++++++--------- mypy/typeshed/stdlib/_dummy_thread.pyi | 6 +- mypy/typeshed/stdlib/_dummy_threading.pyi | 2 +- mypy/typeshed/stdlib/_imp.pyi | 4 + mypy/typeshed/stdlib/_markupbase.pyi | 13 +- mypy/typeshed/stdlib/_msi.pyi | 16 +- mypy/typeshed/stdlib/_operator.pyi | 195 ++- mypy/typeshed/stdlib/_osx_support.pyi | 15 +- mypy/typeshed/stdlib/_posixsubprocess.pyi | 44 +- mypy/typeshed/stdlib/_py_abc.pyi | 4 +- mypy/typeshed/stdlib/_random.pyi | 6 +- mypy/typeshed/stdlib/_socket.pyi | 10 +- mypy/typeshed/stdlib/_stat.pyi | 134 +- mypy/typeshed/stdlib/_thread.pyi | 9 +- mypy/typeshed/stdlib/_threading_local.pyi | 4 +- mypy/typeshed/stdlib/_tkinter.pyi | 4 +- mypy/typeshed/stdlib/_typeshed/__init__.pyi | 29 +- mypy/typeshed/stdlib/_typeshed/dbapi.pyi | 36 + mypy/typeshed/stdlib/_typeshed/wsgi.pyi | 4 +- mypy/typeshed/stdlib/_typeshed/xml.pyi | 3 +- mypy/typeshed/stdlib/_weakref.pyi | 1 + mypy/typeshed/stdlib/_winapi.pyi | 315 +++-- mypy/typeshed/stdlib/abc.pyi | 8 +- mypy/typeshed/stdlib/aifc.pyi | 4 +- mypy/typeshed/stdlib/argparse.pyi | 41 +- mypy/typeshed/stdlib/array.pyi | 8 +- mypy/typeshed/stdlib/ast.pyi | 61 +- mypy/typeshed/stdlib/asyncio/__init__.pyi | 39 +- mypy/typeshed/stdlib/asyncio/base_events.pyi | 51 +- .../stdlib/asyncio/base_subprocess.pyi | 10 +- mypy/typeshed/stdlib/asyncio/constants.pyi | 9 +- mypy/typeshed/stdlib/asyncio/coroutines.pyi | 18 +- mypy/typeshed/stdlib/asyncio/events.pyi | 6 +- .../stdlib/asyncio/proactor_events.pyi | 4 +- mypy/typeshed/stdlib/asyncio/streams.pyi | 84 +- mypy/typeshed/stdlib/asyncio/tasks.pyi | 34 +- mypy/typeshed/stdlib/asyncio/threads.pyi | 8 +- mypy/typeshed/stdlib/asyncio/trsock.pyi | 6 +- mypy/typeshed/stdlib/asyncio/unix_events.pyi | 77 +- .../stdlib/asyncio/windows_events.pyi | 134 +- .../typeshed/stdlib/asyncio/windows_utils.pyi | 46 +- mypy/typeshed/stdlib/asyncore.pyi | 8 +- mypy/typeshed/stdlib/atexit.pyi | 2 +- mypy/typeshed/stdlib/audioop.pyi | 6 +- mypy/typeshed/stdlib/bdb.pyi | 4 +- mypy/typeshed/stdlib/binascii.pyi | 11 +- mypy/typeshed/stdlib/binhex.pyi | 4 +- mypy/typeshed/stdlib/builtins.pyi | 176 +-- mypy/typeshed/stdlib/bz2.pyi | 15 +- mypy/typeshed/stdlib/cProfile.pyi | 4 +- mypy/typeshed/stdlib/calendar.pyi | 6 +- mypy/typeshed/stdlib/cgi.pyi | 2 +- mypy/typeshed/stdlib/cgitb.pyi | 4 +- mypy/typeshed/stdlib/codecs.pyi | 13 +- mypy/typeshed/stdlib/collections/__init__.pyi | 142 ++- .../stdlib/concurrent/futures/_base.pyi | 23 +- .../stdlib/concurrent/futures/process.pyi | 12 +- .../stdlib/concurrent/futures/thread.pyi | 12 +- mypy/typeshed/stdlib/configparser.pyi | 21 +- mypy/typeshed/stdlib/contextlib.pyi | 49 +- mypy/typeshed/stdlib/copyreg.pyi | 4 +- mypy/typeshed/stdlib/crypt.pyi | 30 +- mypy/typeshed/stdlib/csv.pyi | 4 +- mypy/typeshed/stdlib/ctypes/__init__.pyi | 30 +- mypy/typeshed/stdlib/curses/__init__.pyi | 22 +- mypy/typeshed/stdlib/curses/ascii.pyi | 117 +- mypy/typeshed/stdlib/curses/panel.pyi | 39 +- mypy/typeshed/stdlib/curses/textpad.pyi | 19 +- mypy/typeshed/stdlib/dataclasses.pyi | 12 +- mypy/typeshed/stdlib/datetime.pyi | 12 +- mypy/typeshed/stdlib/dbm/__init__.pyi | 4 +- mypy/typeshed/stdlib/dbm/gnu.pyi | 6 +- mypy/typeshed/stdlib/dbm/ndbm.pyi | 4 +- mypy/typeshed/stdlib/decimal.pyi | 17 +- mypy/typeshed/stdlib/difflib.pyi | 6 +- mypy/typeshed/stdlib/dis.pyi | 24 +- mypy/typeshed/stdlib/distutils/ccompiler.pyi | 6 +- .../stdlib/distutils/command/__init__.pyi | 40 + .../stdlib/distutils/command/check.pyi | 2 +- .../stdlib/distutils/command/install.pyi | 4 +- .../stdlib/distutils/fancy_getopt.pyi | 6 +- mypy/typeshed/stdlib/distutils/util.pyi | 4 +- mypy/typeshed/stdlib/distutils/version.pyi | 4 +- mypy/typeshed/stdlib/doctest.pyi | 4 +- .../stdlib/email/_header_value_parser.pyi | 6 +- mypy/typeshed/stdlib/email/base64mime.pyi | 7 + mypy/typeshed/stdlib/email/headerregistry.pyi | 52 +- mypy/typeshed/stdlib/email/message.pyi | 11 +- .../stdlib/email/mime/application.pyi | 4 +- mypy/typeshed/stdlib/email/mime/audio.pyi | 4 +- mypy/typeshed/stdlib/email/mime/base.pyi | 4 +- mypy/typeshed/stdlib/email/mime/image.pyi | 4 +- mypy/typeshed/stdlib/email/mime/multipart.pyi | 4 +- mypy/typeshed/stdlib/email/policy.pyi | 34 +- mypy/typeshed/stdlib/email/quoprimime.pyi | 13 + mypy/typeshed/stdlib/email/utils.pyi | 6 +- mypy/typeshed/stdlib/encodings/utf_8_sig.pyi | 27 + mypy/typeshed/stdlib/enum.pyi | 121 +- mypy/typeshed/stdlib/fcntl.pyi | 182 +-- mypy/typeshed/stdlib/fileinput.pyi | 3 +- mypy/typeshed/stdlib/formatter.pyi | 10 +- mypy/typeshed/stdlib/fractions.pyi | 2 + mypy/typeshed/stdlib/ftplib.pyi | 8 +- mypy/typeshed/stdlib/functools.pyi | 16 +- mypy/typeshed/stdlib/genericpath.pyi | 8 +- mypy/typeshed/stdlib/gettext.pyi | 106 +- mypy/typeshed/stdlib/graphlib.pyi | 4 +- mypy/typeshed/stdlib/grp.pyi | 28 +- mypy/typeshed/stdlib/hashlib.pyi | 4 +- mypy/typeshed/stdlib/heapq.pyi | 6 +- mypy/typeshed/stdlib/hmac.pyi | 3 + mypy/typeshed/stdlib/html/parser.pyi | 9 +- mypy/typeshed/stdlib/http/client.pyi | 2 +- mypy/typeshed/stdlib/http/cookiejar.pyi | 6 +- mypy/typeshed/stdlib/http/cookies.pyi | 8 +- mypy/typeshed/stdlib/imaplib.pyi | 6 +- mypy/typeshed/stdlib/importlib/abc.pyi | 19 +- mypy/typeshed/stdlib/importlib/machinery.pyi | 42 +- .../{metadata.pyi => metadata/__init__.pyi} | 20 +- .../stdlib/importlib/metadata/_meta.pyi | 18 + mypy/typeshed/stdlib/importlib/resources.pyi | 3 + mypy/typeshed/stdlib/importlib/util.pyi | 10 +- mypy/typeshed/stdlib/inspect.pyi | 146 ++- mypy/typeshed/stdlib/io.pyi | 34 +- mypy/typeshed/stdlib/ipaddress.pyi | 15 +- mypy/typeshed/stdlib/itertools.pyi | 30 +- mypy/typeshed/stdlib/json/encoder.pyi | 8 +- .../typeshed/stdlib/lib2to3/pgen2/grammar.pyi | 8 +- mypy/typeshed/stdlib/lib2to3/pgen2/token.pyi | 4 + .../stdlib/lib2to3/pgen2/tokenize.pyi | 6 +- mypy/typeshed/stdlib/lib2to3/pytree.pyi | 8 +- mypy/typeshed/stdlib/linecache.pyi | 6 +- mypy/typeshed/stdlib/locale.pyi | 8 +- mypy/typeshed/stdlib/logging/__init__.pyi | 52 +- mypy/typeshed/stdlib/logging/handlers.pyi | 2 +- mypy/typeshed/stdlib/lzma.pyi | 4 +- mypy/typeshed/stdlib/mailcap.pyi | 4 +- mypy/typeshed/stdlib/math.pyi | 6 +- mypy/typeshed/stdlib/mimetypes.pyi | 9 +- mypy/typeshed/stdlib/mmap.pyi | 5 +- mypy/typeshed/stdlib/modulefinder.pyi | 4 +- mypy/typeshed/stdlib/msilib/__init__.pyi | 4 +- mypy/typeshed/stdlib/msilib/sequence.pyi | 4 +- .../stdlib/multiprocessing/connection.pyi | 4 +- .../stdlib/multiprocessing/context.pyi | 2 +- .../multiprocessing/dummy/connection.pyi | 8 +- .../stdlib/multiprocessing/managers.pyi | 15 +- mypy/typeshed/stdlib/multiprocessing/pool.pyi | 26 +- .../stdlib/multiprocessing/process.pyi | 6 +- .../stdlib/multiprocessing/shared_memory.pyi | 4 +- .../stdlib/multiprocessing/synchronize.pyi | 9 +- mypy/typeshed/stdlib/netrc.pyi | 4 +- mypy/typeshed/stdlib/nntplib.pyi | 4 +- mypy/typeshed/stdlib/ntpath.pyi | 8 +- mypy/typeshed/stdlib/operator.pyi | 226 +--- mypy/typeshed/stdlib/optparse.pyi | 18 +- mypy/typeshed/stdlib/os/__init__.pyi | 382 ++++-- mypy/typeshed/stdlib/parser.pyi | 6 +- mypy/typeshed/stdlib/pathlib.pyi | 4 +- mypy/typeshed/stdlib/pickle.pyi | 12 +- mypy/typeshed/stdlib/pickletools.pyi | 14 +- mypy/typeshed/stdlib/platform.pyi | 9 +- mypy/typeshed/stdlib/plistlib.pyi | 8 +- mypy/typeshed/stdlib/poplib.pyi | 4 +- mypy/typeshed/stdlib/posix.pyi | 504 +++++--- mypy/typeshed/stdlib/posixpath.pyi | 8 +- mypy/typeshed/stdlib/profile.pyi | 4 +- mypy/typeshed/stdlib/pstats.pyi | 4 +- mypy/typeshed/stdlib/pty.pyi | 25 +- mypy/typeshed/stdlib/pwd.pyi | 41 +- mypy/typeshed/stdlib/pydoc.pyi | 38 +- mypy/typeshed/stdlib/pyexpat/__init__.pyi | 6 +- mypy/typeshed/stdlib/random.pyi | 25 +- mypy/typeshed/stdlib/readline.pyi | 61 +- mypy/typeshed/stdlib/reprlib.pyi | 4 +- mypy/typeshed/stdlib/resource.pyi | 127 +- mypy/typeshed/stdlib/sched.pyi | 8 +- mypy/typeshed/stdlib/secrets.pyi | 5 +- mypy/typeshed/stdlib/select.pyi | 10 +- mypy/typeshed/stdlib/signal.pyi | 195 ++- mypy/typeshed/stdlib/smtpd.pyi | 14 +- mypy/typeshed/stdlib/smtplib.pyi | 25 +- mypy/typeshed/stdlib/socket.pyi | 6 +- mypy/typeshed/stdlib/socketserver.pyi | 7 +- mypy/typeshed/stdlib/spwd.pyi | 41 +- mypy/typeshed/stdlib/sqlite3/dbapi2.pyi | 47 +- mypy/typeshed/stdlib/sre_compile.pyi | 17 +- mypy/typeshed/stdlib/sre_constants.pyi | 13 + mypy/typeshed/stdlib/sre_parse.pyi | 21 +- mypy/typeshed/stdlib/ssl.pyi | 35 +- mypy/typeshed/stdlib/stat.pyi | 98 +- mypy/typeshed/stdlib/statistics.pyi | 6 +- mypy/typeshed/stdlib/stringprep.pyi | 8 + mypy/typeshed/stdlib/struct.pyi | 14 +- mypy/typeshed/stdlib/symbol.pyi | 10 + mypy/typeshed/stdlib/symtable.pyi | 21 +- mypy/typeshed/stdlib/sys.pyi | 49 +- mypy/typeshed/stdlib/sysconfig.pyi | 6 +- mypy/typeshed/stdlib/syslog.pyi | 86 +- mypy/typeshed/stdlib/tarfile.pyi | 10 +- mypy/typeshed/stdlib/tempfile.pyi | 4 +- mypy/typeshed/stdlib/termios.pyi | 486 ++++---- mypy/typeshed/stdlib/threading.pyi | 27 +- mypy/typeshed/stdlib/time.pyi | 57 +- mypy/typeshed/stdlib/tkinter/__init__.pyi | 300 ++--- mypy/typeshed/stdlib/tkinter/filedialog.pyi | 18 +- mypy/typeshed/stdlib/tkinter/font.pyi | 10 +- mypy/typeshed/stdlib/tkinter/tix.pyi | 12 +- mypy/typeshed/stdlib/tkinter/ttk.pyi | 88 +- mypy/typeshed/stdlib/token.pyi | 2 + mypy/typeshed/stdlib/tokenize.pyi | 4 +- mypy/typeshed/stdlib/trace.pyi | 8 +- mypy/typeshed/stdlib/traceback.pyi | 50 +- mypy/typeshed/stdlib/tracemalloc.pyi | 11 +- mypy/typeshed/stdlib/tty.pyi | 25 +- mypy/typeshed/stdlib/turtle.pyi | 40 +- mypy/typeshed/stdlib/types.pyi | 111 +- mypy/typeshed/stdlib/typing.pyi | 57 +- mypy/typeshed/stdlib/typing_extensions.pyi | 8 +- mypy/typeshed/stdlib/unicodedata.pyi | 2 +- mypy/typeshed/stdlib/unittest/__init__.pyi | 24 +- mypy/typeshed/stdlib/unittest/_log.pyi | 27 + mypy/typeshed/stdlib/unittest/case.pyi | 178 +-- mypy/typeshed/stdlib/unittest/loader.pyi | 6 +- mypy/typeshed/stdlib/unittest/main.pyi | 3 + mypy/typeshed/stdlib/unittest/mock.pyi | 165 ++- mypy/typeshed/stdlib/unittest/result.pyi | 7 +- mypy/typeshed/stdlib/unittest/runner.pyi | 2 +- mypy/typeshed/stdlib/unittest/signals.pyi | 2 +- mypy/typeshed/stdlib/unittest/util.pyi | 4 +- mypy/typeshed/stdlib/urllib/parse.pyi | 8 +- mypy/typeshed/stdlib/urllib/request.pyi | 6 +- mypy/typeshed/stdlib/urllib/response.pyi | 4 +- mypy/typeshed/stdlib/uuid.pyi | 4 +- mypy/typeshed/stdlib/venv/__init__.pyi | 3 + mypy/typeshed/stdlib/weakref.pyi | 20 +- mypy/typeshed/stdlib/webbrowser.pyi | 63 +- mypy/typeshed/stdlib/winreg.pyi | 182 +-- mypy/typeshed/stdlib/wsgiref/handlers.pyi | 4 +- mypy/typeshed/stdlib/wsgiref/headers.pyi | 4 +- mypy/typeshed/stdlib/wsgiref/util.pyi | 4 +- mypy/typeshed/stdlib/xml/dom/__init__.pyi | 1 + mypy/typeshed/stdlib/xml/dom/expatbuilder.pyi | 100 +- mypy/typeshed/stdlib/xml/dom/minicompat.pyi | 8 +- mypy/typeshed/stdlib/xml/dom/minidom.pyi | 23 +- mypy/typeshed/stdlib/xml/dom/pulldom.pyi | 8 +- mypy/typeshed/stdlib/xml/dom/xmlbuilder.pyi | 109 +- .../stdlib/xml/etree/ElementInclude.pyi | 4 + .../typeshed/stdlib/xml/etree/ElementPath.pyi | 6 +- .../typeshed/stdlib/xml/etree/ElementTree.pyi | 38 +- mypy/typeshed/stdlib/xmlrpc/client.pyi | 34 +- mypy/typeshed/stdlib/xmlrpc/server.pyi | 19 +- mypy/typeshed/stdlib/zipfile.pyi | 8 +- mypy/typeshed/stdlib/zipimport.pyi | 6 +- mypy/typeshed/stdlib/zlib.pyi | 5 + .../stubs/mypy-extensions/mypy_extensions.pyi | 7 +- test-data/unit/pythoneval.test | 7 +- 281 files changed, 6083 insertions(+), 4685 deletions(-) create mode 100644 mypy/typeshed/stdlib/_typeshed/dbapi.pyi create mode 100644 mypy/typeshed/stdlib/email/base64mime.pyi create mode 100644 mypy/typeshed/stdlib/email/quoprimime.pyi create mode 100644 mypy/typeshed/stdlib/encodings/utf_8_sig.pyi rename mypy/typeshed/stdlib/importlib/{metadata.pyi => metadata/__init__.pyi} (80%) create mode 100644 mypy/typeshed/stdlib/importlib/metadata/_meta.pyi create mode 100644 mypy/typeshed/stdlib/unittest/_log.pyi diff --git a/mypy/fscache.py b/mypy/fscache.py index ea71577b5f86d..d0be1abd8cb93 100644 --- a/mypy/fscache.py +++ b/mypy/fscache.py @@ -143,16 +143,13 @@ def _fake_init(self, path: str) -> os.stat_result: assert not os.path.exists(path), path # Not cached! dirname = os.path.normpath(dirname) st = self.stat(dirname) # May raise OSError - # Get stat result as a sequence so we can modify it. - # (Alas, typeshed's os.stat_result is not a sequence yet.) - tpl = tuple(st) # type: ignore[arg-type, var-annotated] - seq: List[float] = list(tpl) + # Get stat result as a list so we can modify it. + seq: List[float] = list(st) seq[stat.ST_MODE] = stat.S_IFREG | 0o444 seq[stat.ST_INO] = 1 seq[stat.ST_NLINK] = 1 seq[stat.ST_SIZE] = 0 - tpl = tuple(seq) - st = os.stat_result(tpl) + st = os.stat_result(seq) self.stat_cache[path] = st # Make listdir() and read() also pretend this file exists. self.fake_package_cache.add(dirname) diff --git a/mypy/typeshed/stdlib/@python2/_typeshed/xml.pyi b/mypy/typeshed/stdlib/@python2/_typeshed/xml.pyi index 6a5d2531ca72d..eaff9a641db43 100644 --- a/mypy/typeshed/stdlib/@python2/_typeshed/xml.pyi +++ b/mypy/typeshed/stdlib/@python2/_typeshed/xml.pyi @@ -1,7 +1,6 @@ # Stub-only types. This module does not exist at runtime. -from typing import Any -from typing_extensions import Protocol +from typing import Any, Protocol # As defined https://docs.python.org/3/library/xml.dom.html#domimplementation-objects class DOMImplementation(Protocol): diff --git a/mypy/typeshed/stdlib/@python2/_winreg.pyi b/mypy/typeshed/stdlib/@python2/_winreg.pyi index 7297626ac8b39..5b8ec1130ca1c 100644 --- a/mypy/typeshed/stdlib/@python2/_winreg.pyi +++ b/mypy/typeshed/stdlib/@python2/_winreg.pyi @@ -1,96 +1,96 @@ +import sys from types import TracebackType from typing import Any, Tuple, Type, Union -_KeyType = Union[HKEYType, int] +if sys.platform == "win32": + _KeyType = Union[HKEYType, int] + def CloseKey(__hkey: _KeyType) -> None: ... + def ConnectRegistry(__computer_name: str | None, __key: _KeyType) -> HKEYType: ... + def CreateKey(__key: _KeyType, __sub_key: str | None) -> HKEYType: ... + def CreateKeyEx(key: _KeyType, sub_key: str | None, reserved: int = ..., access: int = ...) -> HKEYType: ... + def DeleteKey(__key: _KeyType, __sub_key: str) -> None: ... + def DeleteKeyEx(key: _KeyType, sub_key: str, access: int = ..., reserved: int = ...) -> None: ... + def DeleteValue(__key: _KeyType, __value: str) -> None: ... + def EnumKey(__key: _KeyType, __index: int) -> str: ... + def EnumValue(__key: _KeyType, __index: int) -> Tuple[str, Any, int]: ... + def ExpandEnvironmentStrings(__str: str) -> str: ... + def FlushKey(__key: _KeyType) -> None: ... + def LoadKey(__key: _KeyType, __sub_key: str, __file_name: str) -> None: ... + def OpenKey(key: _KeyType, sub_key: str, reserved: int = ..., access: int = ...) -> HKEYType: ... + def OpenKeyEx(key: _KeyType, sub_key: str, reserved: int = ..., access: int = ...) -> HKEYType: ... + def QueryInfoKey(__key: _KeyType) -> Tuple[int, int, int]: ... + def QueryValue(__key: _KeyType, __sub_key: str | None) -> str: ... + def QueryValueEx(__key: _KeyType, __name: str) -> Tuple[Any, int]: ... + def SaveKey(__key: _KeyType, __file_name: str) -> None: ... + def SetValue(__key: _KeyType, __sub_key: str, __type: int, __value: str) -> None: ... + def SetValueEx( + __key: _KeyType, __value_name: str | None, __reserved: Any, __type: int, __value: str | int + ) -> None: ... # reserved is ignored + def DisableReflectionKey(__key: _KeyType) -> None: ... + def EnableReflectionKey(__key: _KeyType) -> None: ... + def QueryReflectionKey(__key: _KeyType) -> bool: ... + HKEY_CLASSES_ROOT: int + HKEY_CURRENT_USER: int + HKEY_LOCAL_MACHINE: int + HKEY_USERS: int + HKEY_PERFORMANCE_DATA: int + HKEY_CURRENT_CONFIG: int + HKEY_DYN_DATA: int -def CloseKey(__hkey: _KeyType) -> None: ... -def ConnectRegistry(__computer_name: str | None, __key: _KeyType) -> HKEYType: ... -def CreateKey(__key: _KeyType, __sub_key: str | None) -> HKEYType: ... -def CreateKeyEx(key: _KeyType, sub_key: str | None, reserved: int = ..., access: int = ...) -> HKEYType: ... -def DeleteKey(__key: _KeyType, __sub_key: str) -> None: ... -def DeleteKeyEx(key: _KeyType, sub_key: str, access: int = ..., reserved: int = ...) -> None: ... -def DeleteValue(__key: _KeyType, __value: str) -> None: ... -def EnumKey(__key: _KeyType, __index: int) -> str: ... -def EnumValue(__key: _KeyType, __index: int) -> Tuple[str, Any, int]: ... -def ExpandEnvironmentStrings(__str: str) -> str: ... -def FlushKey(__key: _KeyType) -> None: ... -def LoadKey(__key: _KeyType, __sub_key: str, __file_name: str) -> None: ... -def OpenKey(key: _KeyType, sub_key: str, reserved: int = ..., access: int = ...) -> HKEYType: ... -def OpenKeyEx(key: _KeyType, sub_key: str, reserved: int = ..., access: int = ...) -> HKEYType: ... -def QueryInfoKey(__key: _KeyType) -> Tuple[int, int, int]: ... -def QueryValue(__key: _KeyType, __sub_key: str | None) -> str: ... -def QueryValueEx(__key: _KeyType, __name: str) -> Tuple[Any, int]: ... -def SaveKey(__key: _KeyType, __file_name: str) -> None: ... -def SetValue(__key: _KeyType, __sub_key: str, __type: int, __value: str) -> None: ... -def SetValueEx( - __key: _KeyType, __value_name: str | None, __reserved: Any, __type: int, __value: str | int -) -> None: ... # reserved is ignored -def DisableReflectionKey(__key: _KeyType) -> None: ... -def EnableReflectionKey(__key: _KeyType) -> None: ... -def QueryReflectionKey(__key: _KeyType) -> bool: ... + KEY_ALL_ACCESS: int + KEY_WRITE: int + KEY_READ: int + KEY_EXECUTE: int + KEY_QUERY_VALUE: int + KEY_SET_VALUE: int + KEY_CREATE_SUB_KEY: int + KEY_ENUMERATE_SUB_KEYS: int + KEY_NOTIFY: int + KEY_CREATE_LINK: int -HKEY_CLASSES_ROOT: int -HKEY_CURRENT_USER: int -HKEY_LOCAL_MACHINE: int -HKEY_USERS: int -HKEY_PERFORMANCE_DATA: int -HKEY_CURRENT_CONFIG: int -HKEY_DYN_DATA: int + KEY_WOW64_64KEY: int + KEY_WOW64_32KEY: int -KEY_ALL_ACCESS: int -KEY_WRITE: int -KEY_READ: int -KEY_EXECUTE: int -KEY_QUERY_VALUE: int -KEY_SET_VALUE: int -KEY_CREATE_SUB_KEY: int -KEY_ENUMERATE_SUB_KEYS: int -KEY_NOTIFY: int -KEY_CREATE_LINK: int + REG_BINARY: int + REG_DWORD: int + REG_DWORD_LITTLE_ENDIAN: int + REG_DWORD_BIG_ENDIAN: int + REG_EXPAND_SZ: int + REG_LINK: int + REG_MULTI_SZ: int + REG_NONE: int + REG_RESOURCE_LIST: int + REG_FULL_RESOURCE_DESCRIPTOR: int + REG_RESOURCE_REQUIREMENTS_LIST: int + REG_SZ: int -KEY_WOW64_64KEY: int -KEY_WOW64_32KEY: int + REG_CREATED_NEW_KEY: int # undocumented + REG_LEGAL_CHANGE_FILTER: int # undocumented + REG_LEGAL_OPTION: int # undocumented + REG_NOTIFY_CHANGE_ATTRIBUTES: int # undocumented + REG_NOTIFY_CHANGE_LAST_SET: int # undocumented + REG_NOTIFY_CHANGE_NAME: int # undocumented + REG_NOTIFY_CHANGE_SECURITY: int # undocumented + REG_NO_LAZY_FLUSH: int # undocumented + REG_OPENED_EXISTING_KEY: int # undocumented + REG_OPTION_BACKUP_RESTORE: int # undocumented + REG_OPTION_CREATE_LINK: int # undocumented + REG_OPTION_NON_VOLATILE: int # undocumented + REG_OPTION_OPEN_LINK: int # undocumented + REG_OPTION_RESERVED: int # undocumented + REG_OPTION_VOLATILE: int # undocumented + REG_REFRESH_HIVE: int # undocumented + REG_WHOLE_HIVE_VOLATILE: int # undocumented -REG_BINARY: int -REG_DWORD: int -REG_DWORD_LITTLE_ENDIAN: int -REG_DWORD_BIG_ENDIAN: int -REG_EXPAND_SZ: int -REG_LINK: int -REG_MULTI_SZ: int -REG_NONE: int -REG_RESOURCE_LIST: int -REG_FULL_RESOURCE_DESCRIPTOR: int -REG_RESOURCE_REQUIREMENTS_LIST: int -REG_SZ: int + error = OSError -REG_CREATED_NEW_KEY: int # undocumented -REG_LEGAL_CHANGE_FILTER: int # undocumented -REG_LEGAL_OPTION: int # undocumented -REG_NOTIFY_CHANGE_ATTRIBUTES: int # undocumented -REG_NOTIFY_CHANGE_LAST_SET: int # undocumented -REG_NOTIFY_CHANGE_NAME: int # undocumented -REG_NOTIFY_CHANGE_SECURITY: int # undocumented -REG_NO_LAZY_FLUSH: int # undocumented -REG_OPENED_EXISTING_KEY: int # undocumented -REG_OPTION_BACKUP_RESTORE: int # undocumented -REG_OPTION_CREATE_LINK: int # undocumented -REG_OPTION_NON_VOLATILE: int # undocumented -REG_OPTION_OPEN_LINK: int # undocumented -REG_OPTION_RESERVED: int # undocumented -REG_OPTION_VOLATILE: int # undocumented -REG_REFRESH_HIVE: int # undocumented -REG_WHOLE_HIVE_VOLATILE: int # undocumented - -error = OSError - -# Though this class has a __name__ of PyHKEY, it's exposed as HKEYType for some reason -class HKEYType: - def __bool__(self) -> bool: ... - def __int__(self) -> int: ... - def __enter__(self) -> HKEYType: ... - def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None - ) -> bool | None: ... - def Close(self) -> None: ... - def Detach(self) -> int: ... + # Though this class has a __name__ of PyHKEY, it's exposed as HKEYType for some reason + class HKEYType: + def __bool__(self) -> bool: ... + def __int__(self) -> int: ... + def __enter__(self) -> HKEYType: ... + def __exit__( + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> bool | None: ... + def Close(self) -> None: ... + def Detach(self) -> int: ... diff --git a/mypy/typeshed/stdlib/@python2/contextlib.pyi b/mypy/typeshed/stdlib/@python2/contextlib.pyi index 6aabf5a16e475..6782fbf1874c2 100644 --- a/mypy/typeshed/stdlib/@python2/contextlib.pyi +++ b/mypy/typeshed/stdlib/@python2/contextlib.pyi @@ -1,6 +1,5 @@ from types import TracebackType -from typing import IO, Any, Callable, ContextManager, Iterable, Iterator, Optional, Type, TypeVar -from typing_extensions import Protocol +from typing import IO, Any, Callable, ContextManager, Iterable, Iterator, Optional, Protocol, Type, TypeVar _T = TypeVar("_T") _T_co = TypeVar("_T_co", covariant=True) diff --git a/mypy/typeshed/stdlib/@python2/crypt.pyi b/mypy/typeshed/stdlib/@python2/crypt.pyi index c4036dbe7a5a0..a7c0cb1e8fbca 100644 --- a/mypy/typeshed/stdlib/@python2/crypt.pyi +++ b/mypy/typeshed/stdlib/@python2/crypt.pyi @@ -1 +1,4 @@ -def crypt(word: str, salt: str) -> str: ... +import sys + +if sys.platform != "win32": + def crypt(word: str, salt: str) -> str: ... diff --git a/mypy/typeshed/stdlib/@python2/ctypes/__init__.pyi b/mypy/typeshed/stdlib/@python2/ctypes/__init__.pyi index 33184cc2ff880..8a10ff954e273 100644 --- a/mypy/typeshed/stdlib/@python2/ctypes/__init__.pyi +++ b/mypy/typeshed/stdlib/@python2/ctypes/__init__.pyi @@ -150,7 +150,7 @@ def create_unicode_buffer(init: _UnionT[int, Text], size: int | None = ...) -> A if sys.platform == "win32": def DllCanUnloadNow() -> int: ... def DllGetClassObject(rclsid: Any, riid: Any, ppv: Any) -> int: ... # TODO not documented - def FormatError(code: int) -> str: ... + def FormatError(code: int = ...) -> str: ... def GetLastError() -> int: ... def get_errno() -> int: ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/command/bdist_msi.pyi b/mypy/typeshed/stdlib/@python2/distutils/command/bdist_msi.pyi index a761792018a92..150229fb01c91 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/command/bdist_msi.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/command/bdist_msi.pyi @@ -1,6 +1,8 @@ -from distutils.cmd import Command +import sys -class bdist_msi(Command): - def initialize_options(self) -> None: ... - def finalize_options(self) -> None: ... - def run(self) -> None: ... +if sys.platform == "win32": + from distutils.cmd import Command + class bdist_msi(Command): + def initialize_options(self) -> None: ... + def finalize_options(self) -> None: ... + def run(self) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/fcntl.pyi b/mypy/typeshed/stdlib/@python2/fcntl.pyi index b3730270f1cc1..0d9d598ab7c59 100644 --- a/mypy/typeshed/stdlib/@python2/fcntl.pyi +++ b/mypy/typeshed/stdlib/@python2/fcntl.pyi @@ -1,82 +1,83 @@ +import sys from _typeshed import FileDescriptorLike from typing import Any -FASYNC: int -FD_CLOEXEC: int +if sys.platform != "win32": + FASYNC: int + FD_CLOEXEC: int -DN_ACCESS: int -DN_ATTRIB: int -DN_CREATE: int -DN_DELETE: int -DN_MODIFY: int -DN_MULTISHOT: int -DN_RENAME: int -F_DUPFD: int -F_EXLCK: int -F_GETFD: int -F_GETFL: int -F_GETLEASE: int -F_GETLK: int -F_GETLK64: int -F_GETOWN: int -F_GETSIG: int -F_NOTIFY: int -F_RDLCK: int -F_SETFD: int -F_SETFL: int -F_SETLEASE: int -F_SETLK: int -F_SETLK64: int -F_SETLKW: int -F_SETLKW64: int -F_SETOWN: int -F_SETSIG: int -F_SHLCK: int -F_UNLCK: int -F_WRLCK: int -I_ATMARK: int -I_CANPUT: int -I_CKBAND: int -I_FDINSERT: int -I_FIND: int -I_FLUSH: int -I_FLUSHBAND: int -I_GETBAND: int -I_GETCLTIME: int -I_GETSIG: int -I_GRDOPT: int -I_GWROPT: int -I_LINK: int -I_LIST: int -I_LOOK: int -I_NREAD: int -I_PEEK: int -I_PLINK: int -I_POP: int -I_PUNLINK: int -I_PUSH: int -I_RECVFD: int -I_SENDFD: int -I_SETCLTIME: int -I_SETSIG: int -I_SRDOPT: int -I_STR: int -I_SWROPT: int -I_UNLINK: int -LOCK_EX: int -LOCK_MAND: int -LOCK_NB: int -LOCK_READ: int -LOCK_RW: int -LOCK_SH: int -LOCK_UN: int -LOCK_WRITE: int + DN_ACCESS: int + DN_ATTRIB: int + DN_CREATE: int + DN_DELETE: int + DN_MODIFY: int + DN_MULTISHOT: int + DN_RENAME: int + F_DUPFD: int + F_EXLCK: int + F_GETFD: int + F_GETFL: int + F_GETLEASE: int + F_GETLK: int + F_GETLK64: int + F_GETOWN: int + F_GETSIG: int + F_NOTIFY: int + F_RDLCK: int + F_SETFD: int + F_SETFL: int + F_SETLEASE: int + F_SETLK: int + F_SETLK64: int + F_SETLKW: int + F_SETLKW64: int + F_SETOWN: int + F_SETSIG: int + F_SHLCK: int + F_UNLCK: int + F_WRLCK: int + I_ATMARK: int + I_CANPUT: int + I_CKBAND: int + I_FDINSERT: int + I_FIND: int + I_FLUSH: int + I_FLUSHBAND: int + I_GETBAND: int + I_GETCLTIME: int + I_GETSIG: int + I_GRDOPT: int + I_GWROPT: int + I_LINK: int + I_LIST: int + I_LOOK: int + I_NREAD: int + I_PEEK: int + I_PLINK: int + I_POP: int + I_PUNLINK: int + I_PUSH: int + I_RECVFD: int + I_SENDFD: int + I_SETCLTIME: int + I_SETSIG: int + I_SRDOPT: int + I_STR: int + I_SWROPT: int + I_UNLINK: int + LOCK_EX: int + LOCK_MAND: int + LOCK_NB: int + LOCK_READ: int + LOCK_RW: int + LOCK_SH: int + LOCK_UN: int + LOCK_WRITE: int -# TODO All these return either int or bytes depending on the value of -# cmd (not on the type of arg). -def fcntl(fd: FileDescriptorLike, op: int, arg: int | bytes = ...) -> Any: ... - -# TODO: arg: int or read-only buffer interface or read-write buffer interface -def ioctl(fd: FileDescriptorLike, op: int, arg: int | bytes = ..., mutate_flag: bool = ...) -> Any: ... -def flock(fd: FileDescriptorLike, op: int) -> None: ... -def lockf(fd: FileDescriptorLike, op: int, length: int = ..., start: int = ..., whence: int = ...) -> Any: ... + # TODO All these return either int or bytes depending on the value of + # cmd (not on the type of arg). + def fcntl(fd: FileDescriptorLike, op: int, arg: int | bytes = ...) -> Any: ... + # TODO: arg: int or read-only buffer interface or read-write buffer interface + def ioctl(fd: FileDescriptorLike, op: int, arg: int | bytes = ..., mutate_flag: bool = ...) -> Any: ... + def flock(fd: FileDescriptorLike, op: int) -> None: ... + def lockf(fd: FileDescriptorLike, op: int, length: int = ..., start: int = ..., whence: int = ...) -> Any: ... diff --git a/mypy/typeshed/stdlib/@python2/grp.pyi b/mypy/typeshed/stdlib/@python2/grp.pyi index 63898b26bf178..6e937ec0f2629 100644 --- a/mypy/typeshed/stdlib/@python2/grp.pyi +++ b/mypy/typeshed/stdlib/@python2/grp.pyi @@ -1,11 +1,12 @@ +import sys from typing import List, NamedTuple -class struct_group(NamedTuple): - gr_name: str - gr_passwd: str | None - gr_gid: int - gr_mem: List[str] - -def getgrall() -> List[struct_group]: ... -def getgrgid(id: int) -> struct_group: ... -def getgrnam(name: str) -> struct_group: ... +if sys.platform != "win32": + class struct_group(NamedTuple): + gr_name: str + gr_passwd: str | None + gr_gid: int + gr_mem: List[str] + def getgrall() -> List[struct_group]: ... + def getgrgid(id: int) -> struct_group: ... + def getgrnam(name: str) -> struct_group: ... diff --git a/mypy/typeshed/stdlib/@python2/pty.pyi b/mypy/typeshed/stdlib/@python2/pty.pyi index e8afa2df5166c..d9d9fd98e41be 100644 --- a/mypy/typeshed/stdlib/@python2/pty.pyi +++ b/mypy/typeshed/stdlib/@python2/pty.pyi @@ -1,15 +1,16 @@ +import sys from typing import Callable, Iterable, Tuple -_Reader = Callable[[int], bytes] +if sys.platform != "win32": + _Reader = Callable[[int], bytes] -STDIN_FILENO: int -STDOUT_FILENO: int -STDERR_FILENO: int + STDIN_FILENO: int + STDOUT_FILENO: int + STDERR_FILENO: int -CHILD: int - -def openpty() -> Tuple[int, int]: ... -def master_open() -> Tuple[int, str]: ... -def slave_open(tty_name: str) -> int: ... -def fork() -> Tuple[int, int]: ... -def spawn(argv: str | Iterable[str], master_read: _Reader = ..., stdin_read: _Reader = ...) -> None: ... + CHILD: int + def openpty() -> Tuple[int, int]: ... + def master_open() -> Tuple[int, str]: ... + def slave_open(tty_name: str) -> int: ... + def fork() -> Tuple[int, int]: ... + def spawn(argv: str | Iterable[str], master_read: _Reader = ..., stdin_read: _Reader = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/pwd.pyi b/mypy/typeshed/stdlib/@python2/pwd.pyi index 83020c1576dd5..583999fd84b7f 100644 --- a/mypy/typeshed/stdlib/@python2/pwd.pyi +++ b/mypy/typeshed/stdlib/@python2/pwd.pyi @@ -1,14 +1,15 @@ +import sys from typing import List, Tuple -class struct_passwd(Tuple[str, str, int, int, str, str, str]): - pw_name: str - pw_passwd: str - pw_uid: int - pw_gid: int - pw_gecos: str - pw_dir: str - pw_shell: str - -def getpwall() -> List[struct_passwd]: ... -def getpwuid(__uid: int) -> struct_passwd: ... -def getpwnam(__name: str) -> struct_passwd: ... +if sys.platform != "win32": + class struct_passwd(Tuple[str, str, int, int, str, str, str]): + pw_name: str + pw_passwd: str + pw_uid: int + pw_gid: int + pw_gecos: str + pw_dir: str + pw_shell: str + def getpwall() -> List[struct_passwd]: ... + def getpwuid(__uid: int) -> struct_passwd: ... + def getpwnam(__name: str) -> struct_passwd: ... diff --git a/mypy/typeshed/stdlib/@python2/readline.pyi b/mypy/typeshed/stdlib/@python2/readline.pyi index fb9b12d9a8e93..9b82d9bae6362 100644 --- a/mypy/typeshed/stdlib/@python2/readline.pyi +++ b/mypy/typeshed/stdlib/@python2/readline.pyi @@ -1,30 +1,31 @@ +import sys from typing import Callable, Optional, Sequence, Text -_CompleterT = Optional[Callable[[str, int], Optional[str]]] -_CompDispT = Optional[Callable[[str, Sequence[str], int], None]] - -def parse_and_bind(__string: str) -> None: ... -def read_init_file(__filename: Text | None = ...) -> None: ... -def get_line_buffer() -> str: ... -def insert_text(__string: str) -> None: ... -def redisplay() -> None: ... -def read_history_file(__filename: Text | None = ...) -> None: ... -def write_history_file(__filename: Text | None = ...) -> None: ... -def get_history_length() -> int: ... -def set_history_length(__length: int) -> None: ... -def clear_history() -> None: ... -def get_current_history_length() -> int: ... -def get_history_item(__index: int) -> str: ... -def remove_history_item(__pos: int) -> None: ... -def replace_history_item(__pos: int, __line: str) -> None: ... -def add_history(__string: str) -> None: ... -def set_startup_hook(__function: Callable[[], None] | None = ...) -> None: ... -def set_pre_input_hook(__function: Callable[[], None] | None = ...) -> None: ... -def set_completer(__function: _CompleterT = ...) -> None: ... -def get_completer() -> _CompleterT: ... -def get_completion_type() -> int: ... -def get_begidx() -> int: ... -def get_endidx() -> int: ... -def set_completer_delims(__string: str) -> None: ... -def get_completer_delims() -> str: ... -def set_completion_display_matches_hook(__function: _CompDispT = ...) -> None: ... +if sys.platform != "win32": + _CompleterT = Optional[Callable[[str, int], Optional[str]]] + _CompDispT = Optional[Callable[[str, Sequence[str], int], None]] + def parse_and_bind(__string: str) -> None: ... + def read_init_file(__filename: Text | None = ...) -> None: ... + def get_line_buffer() -> str: ... + def insert_text(__string: str) -> None: ... + def redisplay() -> None: ... + def read_history_file(__filename: Text | None = ...) -> None: ... + def write_history_file(__filename: Text | None = ...) -> None: ... + def get_history_length() -> int: ... + def set_history_length(__length: int) -> None: ... + def clear_history() -> None: ... + def get_current_history_length() -> int: ... + def get_history_item(__index: int) -> str: ... + def remove_history_item(__pos: int) -> None: ... + def replace_history_item(__pos: int, __line: str) -> None: ... + def add_history(__string: str) -> None: ... + def set_startup_hook(__function: Callable[[], None] | None = ...) -> None: ... + def set_pre_input_hook(__function: Callable[[], None] | None = ...) -> None: ... + def set_completer(__function: _CompleterT = ...) -> None: ... + def get_completer() -> _CompleterT: ... + def get_completion_type() -> int: ... + def get_begidx() -> int: ... + def get_endidx() -> int: ... + def set_completer_delims(__string: str) -> None: ... + def get_completer_delims() -> str: ... + def set_completion_display_matches_hook(__function: _CompDispT = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/resource.pyi b/mypy/typeshed/stdlib/@python2/resource.pyi index ad9502db1940d..476438d536744 100644 --- a/mypy/typeshed/stdlib/@python2/resource.pyi +++ b/mypy/typeshed/stdlib/@python2/resource.pyi @@ -1,46 +1,42 @@ +import sys from typing import NamedTuple, Tuple -class error(Exception): ... - -RLIM_INFINITY: int - -def getrlimit(resource: int) -> Tuple[int, int]: ... -def setrlimit(resource: int, limits: Tuple[int, int]) -> None: ... - -RLIMIT_CORE: int -RLIMIT_CPU: int -RLIMIT_FSIZE: int -RLIMIT_DATA: int -RLIMIT_STACK: int -RLIMIT_RSS: int -RLIMIT_NPROC: int -RLIMIT_NOFILE: int -RLIMIT_OFILE: int -RLIMIT_MEMLOCK: int -RLIMIT_VMEM: int -RLIMIT_AS: int - -class _RUsage(NamedTuple): - ru_utime: float - ru_stime: float - ru_maxrss: int - ru_ixrss: int - ru_idrss: int - ru_isrss: int - ru_minflt: int - ru_majflt: int - ru_nswap: int - ru_inblock: int - ru_oublock: int - ru_msgsnd: int - ru_msgrcv: int - ru_nsignals: int - ru_nvcsw: int - ru_nivcsw: int - -def getrusage(who: int) -> _RUsage: ... -def getpagesize() -> int: ... - -RUSAGE_SELF: int -RUSAGE_CHILDREN: int -RUSAGE_BOTH: int +if sys.platform != "win32": + class error(Exception): ... + RLIM_INFINITY: int + def getrlimit(resource: int) -> Tuple[int, int]: ... + def setrlimit(resource: int, limits: Tuple[int, int]) -> None: ... + RLIMIT_CORE: int + RLIMIT_CPU: int + RLIMIT_FSIZE: int + RLIMIT_DATA: int + RLIMIT_STACK: int + RLIMIT_RSS: int + RLIMIT_NPROC: int + RLIMIT_NOFILE: int + RLIMIT_OFILE: int + RLIMIT_MEMLOCK: int + RLIMIT_VMEM: int + RLIMIT_AS: int + class _RUsage(NamedTuple): + ru_utime: float + ru_stime: float + ru_maxrss: int + ru_ixrss: int + ru_idrss: int + ru_isrss: int + ru_minflt: int + ru_majflt: int + ru_nswap: int + ru_inblock: int + ru_oublock: int + ru_msgsnd: int + ru_msgrcv: int + ru_nsignals: int + ru_nvcsw: int + ru_nivcsw: int + def getrusage(who: int) -> _RUsage: ... + def getpagesize() -> int: ... + RUSAGE_SELF: int + RUSAGE_CHILDREN: int + RUSAGE_BOTH: int diff --git a/mypy/typeshed/stdlib/@python2/spwd.pyi b/mypy/typeshed/stdlib/@python2/spwd.pyi index 756c142a61da0..95122ce43d1ea 100644 --- a/mypy/typeshed/stdlib/@python2/spwd.pyi +++ b/mypy/typeshed/stdlib/@python2/spwd.pyi @@ -1,15 +1,16 @@ +import sys from typing import List, NamedTuple -class struct_spwd(NamedTuple): - sp_nam: str - sp_pwd: str - sp_lstchg: int - sp_min: int - sp_max: int - sp_warn: int - sp_inact: int - sp_expire: int - sp_flag: int - -def getspall() -> List[struct_spwd]: ... -def getspnam(name: str) -> struct_spwd: ... +if sys.platform != "win32": + class struct_spwd(NamedTuple): + sp_nam: str + sp_pwd: str + sp_lstchg: int + sp_min: int + sp_max: int + sp_warn: int + sp_inact: int + sp_expire: int + sp_flag: int + def getspall() -> List[struct_spwd]: ... + def getspnam(name: str) -> struct_spwd: ... diff --git a/mypy/typeshed/stdlib/@python2/syslog.pyi b/mypy/typeshed/stdlib/@python2/syslog.pyi index 49169f40db5c4..eaeeb7715e482 100644 --- a/mypy/typeshed/stdlib/@python2/syslog.pyi +++ b/mypy/typeshed/stdlib/@python2/syslog.pyi @@ -1,43 +1,44 @@ +import sys from typing import overload -LOG_ALERT: int -LOG_AUTH: int -LOG_CONS: int -LOG_CRIT: int -LOG_CRON: int -LOG_DAEMON: int -LOG_DEBUG: int -LOG_EMERG: int -LOG_ERR: int -LOG_INFO: int -LOG_KERN: int -LOG_LOCAL0: int -LOG_LOCAL1: int -LOG_LOCAL2: int -LOG_LOCAL3: int -LOG_LOCAL4: int -LOG_LOCAL5: int -LOG_LOCAL6: int -LOG_LOCAL7: int -LOG_LPR: int -LOG_MAIL: int -LOG_NDELAY: int -LOG_NEWS: int -LOG_NOTICE: int -LOG_NOWAIT: int -LOG_PERROR: int -LOG_PID: int -LOG_SYSLOG: int -LOG_USER: int -LOG_UUCP: int -LOG_WARNING: int - -def LOG_MASK(a: int) -> int: ... -def LOG_UPTO(a: int) -> int: ... -def closelog() -> None: ... -def openlog(ident: str = ..., logoption: int = ..., facility: int = ...) -> None: ... -def setlogmask(x: int) -> int: ... -@overload -def syslog(priority: int, message: str) -> None: ... -@overload -def syslog(message: str) -> None: ... +if sys.platform != "win32": + LOG_ALERT: int + LOG_AUTH: int + LOG_CONS: int + LOG_CRIT: int + LOG_CRON: int + LOG_DAEMON: int + LOG_DEBUG: int + LOG_EMERG: int + LOG_ERR: int + LOG_INFO: int + LOG_KERN: int + LOG_LOCAL0: int + LOG_LOCAL1: int + LOG_LOCAL2: int + LOG_LOCAL3: int + LOG_LOCAL4: int + LOG_LOCAL5: int + LOG_LOCAL6: int + LOG_LOCAL7: int + LOG_LPR: int + LOG_MAIL: int + LOG_NDELAY: int + LOG_NEWS: int + LOG_NOTICE: int + LOG_NOWAIT: int + LOG_PERROR: int + LOG_PID: int + LOG_SYSLOG: int + LOG_USER: int + LOG_UUCP: int + LOG_WARNING: int + def LOG_MASK(a: int) -> int: ... + def LOG_UPTO(a: int) -> int: ... + def closelog() -> None: ... + def openlog(ident: str = ..., logoption: int = ..., facility: int = ...) -> None: ... + def setlogmask(x: int) -> int: ... + @overload + def syslog(priority: int, message: str) -> None: ... + @overload + def syslog(message: str) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/termios.pyi b/mypy/typeshed/stdlib/@python2/termios.pyi index 0c627f4b72bdd..cee6b85f9ba57 100644 --- a/mypy/typeshed/stdlib/@python2/termios.pyi +++ b/mypy/typeshed/stdlib/@python2/termios.pyi @@ -1,246 +1,246 @@ +import sys from _typeshed import FileDescriptorLike from typing import Any, List, Union -_Attr = List[Union[int, List[Union[bytes, int]]]] +if sys.platform != "win32": + _Attr = List[Union[int, List[Union[bytes, int]]]] -# TODO constants not really documented -B0: int -B1000000: int -B110: int -B115200: int -B1152000: int -B1200: int -B134: int -B150: int -B1500000: int -B1800: int -B19200: int -B200: int -B2000000: int -B230400: int -B2400: int -B2500000: int -B300: int -B3000000: int -B3500000: int -B38400: int -B4000000: int -B460800: int -B4800: int -B50: int -B500000: int -B57600: int -B576000: int -B600: int -B75: int -B921600: int -B9600: int -BRKINT: int -BS0: int -BS1: int -BSDLY: int -CBAUD: int -CBAUDEX: int -CDSUSP: int -CEOF: int -CEOL: int -CEOT: int -CERASE: int -CFLUSH: int -CIBAUD: int -CINTR: int -CKILL: int -CLNEXT: int -CLOCAL: int -CQUIT: int -CR0: int -CR1: int -CR2: int -CR3: int -CRDLY: int -CREAD: int -CRPRNT: int -CRTSCTS: int -CS5: int -CS6: int -CS7: int -CS8: int -CSIZE: int -CSTART: int -CSTOP: int -CSTOPB: int -CSUSP: int -CWERASE: int -ECHO: int -ECHOCTL: int -ECHOE: int -ECHOK: int -ECHOKE: int -ECHONL: int -ECHOPRT: int -EXTA: int -EXTB: int -FF0: int -FF1: int -FFDLY: int -FIOASYNC: int -FIOCLEX: int -FIONBIO: int -FIONCLEX: int -FIONREAD: int -FLUSHO: int -HUPCL: int -ICANON: int -ICRNL: int -IEXTEN: int -IGNBRK: int -IGNCR: int -IGNPAR: int -IMAXBEL: int -INLCR: int -INPCK: int -IOCSIZE_MASK: int -IOCSIZE_SHIFT: int -ISIG: int -ISTRIP: int -IUCLC: int -IXANY: int -IXOFF: int -IXON: int -NCC: int -NCCS: int -NL0: int -NL1: int -NLDLY: int -NOFLSH: int -N_MOUSE: int -N_PPP: int -N_SLIP: int -N_STRIP: int -N_TTY: int -OCRNL: int -OFDEL: int -OFILL: int -OLCUC: int -ONLCR: int -ONLRET: int -ONOCR: int -OPOST: int -PARENB: int -PARMRK: int -PARODD: int -PENDIN: int -TAB0: int -TAB1: int -TAB2: int -TAB3: int -TABDLY: int -TCFLSH: int -TCGETA: int -TCGETS: int -TCIFLUSH: int -TCIOFF: int -TCIOFLUSH: int -TCION: int -TCOFLUSH: int -TCOOFF: int -TCOON: int -TCSADRAIN: int -TCSAFLUSH: int -TCSANOW: int -TCSBRK: int -TCSBRKP: int -TCSETA: int -TCSETAF: int -TCSETAW: int -TCSETS: int -TCSETSF: int -TCSETSW: int -TCXONC: int -TIOCCONS: int -TIOCEXCL: int -TIOCGETD: int -TIOCGICOUNT: int -TIOCGLCKTRMIOS: int -TIOCGPGRP: int -TIOCGSERIAL: int -TIOCGSOFTCAR: int -TIOCGWINSZ: int -TIOCINQ: int -TIOCLINUX: int -TIOCMBIC: int -TIOCMBIS: int -TIOCMGET: int -TIOCMIWAIT: int -TIOCMSET: int -TIOCM_CAR: int -TIOCM_CD: int -TIOCM_CTS: int -TIOCM_DSR: int -TIOCM_DTR: int -TIOCM_LE: int -TIOCM_RI: int -TIOCM_RNG: int -TIOCM_RTS: int -TIOCM_SR: int -TIOCM_ST: int -TIOCNOTTY: int -TIOCNXCL: int -TIOCOUTQ: int -TIOCPKT: int -TIOCPKT_DATA: int -TIOCPKT_DOSTOP: int -TIOCPKT_FLUSHREAD: int -TIOCPKT_FLUSHWRITE: int -TIOCPKT_NOSTOP: int -TIOCPKT_START: int -TIOCPKT_STOP: int -TIOCSCTTY: int -TIOCSERCONFIG: int -TIOCSERGETLSR: int -TIOCSERGETMULTI: int -TIOCSERGSTRUCT: int -TIOCSERGWILD: int -TIOCSERSETMULTI: int -TIOCSERSWILD: int -TIOCSER_TEMT: int -TIOCSETD: int -TIOCSLCKTRMIOS: int -TIOCSPGRP: int -TIOCSSERIAL: int -TIOCSSOFTCAR: int -TIOCSTI: int -TIOCSWINSZ: int -TOSTOP: int -VDISCARD: int -VEOF: int -VEOL: int -VEOL2: int -VERASE: int -VINTR: int -VKILL: int -VLNEXT: int -VMIN: int -VQUIT: int -VREPRINT: int -VSTART: int -VSTOP: int -VSUSP: int -VSWTC: int -VSWTCH: int -VT0: int -VT1: int -VTDLY: int -VTIME: int -VWERASE: int -XCASE: int -XTABS: int - -def tcgetattr(__fd: FileDescriptorLike) -> List[Any]: ... -def tcsetattr(__fd: FileDescriptorLike, __when: int, __attributes: _Attr) -> None: ... -def tcsendbreak(__fd: FileDescriptorLike, __duration: int) -> None: ... -def tcdrain(__fd: FileDescriptorLike) -> None: ... -def tcflush(__fd: FileDescriptorLike, __queue: int) -> None: ... -def tcflow(__fd: FileDescriptorLike, __action: int) -> None: ... - -class error(Exception): ... + # TODO constants not really documented + B0: int + B1000000: int + B110: int + B115200: int + B1152000: int + B1200: int + B134: int + B150: int + B1500000: int + B1800: int + B19200: int + B200: int + B2000000: int + B230400: int + B2400: int + B2500000: int + B300: int + B3000000: int + B3500000: int + B38400: int + B4000000: int + B460800: int + B4800: int + B50: int + B500000: int + B57600: int + B576000: int + B600: int + B75: int + B921600: int + B9600: int + BRKINT: int + BS0: int + BS1: int + BSDLY: int + CBAUD: int + CBAUDEX: int + CDSUSP: int + CEOF: int + CEOL: int + CEOT: int + CERASE: int + CFLUSH: int + CIBAUD: int + CINTR: int + CKILL: int + CLNEXT: int + CLOCAL: int + CQUIT: int + CR0: int + CR1: int + CR2: int + CR3: int + CRDLY: int + CREAD: int + CRPRNT: int + CRTSCTS: int + CS5: int + CS6: int + CS7: int + CS8: int + CSIZE: int + CSTART: int + CSTOP: int + CSTOPB: int + CSUSP: int + CWERASE: int + ECHO: int + ECHOCTL: int + ECHOE: int + ECHOK: int + ECHOKE: int + ECHONL: int + ECHOPRT: int + EXTA: int + EXTB: int + FF0: int + FF1: int + FFDLY: int + FIOASYNC: int + FIOCLEX: int + FIONBIO: int + FIONCLEX: int + FIONREAD: int + FLUSHO: int + HUPCL: int + ICANON: int + ICRNL: int + IEXTEN: int + IGNBRK: int + IGNCR: int + IGNPAR: int + IMAXBEL: int + INLCR: int + INPCK: int + IOCSIZE_MASK: int + IOCSIZE_SHIFT: int + ISIG: int + ISTRIP: int + IUCLC: int + IXANY: int + IXOFF: int + IXON: int + NCC: int + NCCS: int + NL0: int + NL1: int + NLDLY: int + NOFLSH: int + N_MOUSE: int + N_PPP: int + N_SLIP: int + N_STRIP: int + N_TTY: int + OCRNL: int + OFDEL: int + OFILL: int + OLCUC: int + ONLCR: int + ONLRET: int + ONOCR: int + OPOST: int + PARENB: int + PARMRK: int + PARODD: int + PENDIN: int + TAB0: int + TAB1: int + TAB2: int + TAB3: int + TABDLY: int + TCFLSH: int + TCGETA: int + TCGETS: int + TCIFLUSH: int + TCIOFF: int + TCIOFLUSH: int + TCION: int + TCOFLUSH: int + TCOOFF: int + TCOON: int + TCSADRAIN: int + TCSAFLUSH: int + TCSANOW: int + TCSBRK: int + TCSBRKP: int + TCSETA: int + TCSETAF: int + TCSETAW: int + TCSETS: int + TCSETSF: int + TCSETSW: int + TCXONC: int + TIOCCONS: int + TIOCEXCL: int + TIOCGETD: int + TIOCGICOUNT: int + TIOCGLCKTRMIOS: int + TIOCGPGRP: int + TIOCGSERIAL: int + TIOCGSOFTCAR: int + TIOCGWINSZ: int + TIOCINQ: int + TIOCLINUX: int + TIOCMBIC: int + TIOCMBIS: int + TIOCMGET: int + TIOCMIWAIT: int + TIOCMSET: int + TIOCM_CAR: int + TIOCM_CD: int + TIOCM_CTS: int + TIOCM_DSR: int + TIOCM_DTR: int + TIOCM_LE: int + TIOCM_RI: int + TIOCM_RNG: int + TIOCM_RTS: int + TIOCM_SR: int + TIOCM_ST: int + TIOCNOTTY: int + TIOCNXCL: int + TIOCOUTQ: int + TIOCPKT: int + TIOCPKT_DATA: int + TIOCPKT_DOSTOP: int + TIOCPKT_FLUSHREAD: int + TIOCPKT_FLUSHWRITE: int + TIOCPKT_NOSTOP: int + TIOCPKT_START: int + TIOCPKT_STOP: int + TIOCSCTTY: int + TIOCSERCONFIG: int + TIOCSERGETLSR: int + TIOCSERGETMULTI: int + TIOCSERGSTRUCT: int + TIOCSERGWILD: int + TIOCSERSETMULTI: int + TIOCSERSWILD: int + TIOCSER_TEMT: int + TIOCSETD: int + TIOCSLCKTRMIOS: int + TIOCSPGRP: int + TIOCSSERIAL: int + TIOCSSOFTCAR: int + TIOCSTI: int + TIOCSWINSZ: int + TOSTOP: int + VDISCARD: int + VEOF: int + VEOL: int + VEOL2: int + VERASE: int + VINTR: int + VKILL: int + VLNEXT: int + VMIN: int + VQUIT: int + VREPRINT: int + VSTART: int + VSTOP: int + VSUSP: int + VSWTC: int + VSWTCH: int + VT0: int + VT1: int + VTDLY: int + VTIME: int + VWERASE: int + XCASE: int + XTABS: int + def tcgetattr(__fd: FileDescriptorLike) -> List[Any]: ... + def tcsetattr(__fd: FileDescriptorLike, __when: int, __attributes: _Attr) -> None: ... + def tcsendbreak(__fd: FileDescriptorLike, __duration: int) -> None: ... + def tcdrain(__fd: FileDescriptorLike) -> None: ... + def tcflush(__fd: FileDescriptorLike, __queue: int) -> None: ... + def tcflow(__fd: FileDescriptorLike, __action: int) -> None: ... + class error(Exception): ... diff --git a/mypy/typeshed/stdlib/@python2/tty.pyi b/mypy/typeshed/stdlib/@python2/tty.pyi index c0dc418e9933c..56e85108c75ee 100644 --- a/mypy/typeshed/stdlib/@python2/tty.pyi +++ b/mypy/typeshed/stdlib/@python2/tty.pyi @@ -1,15 +1,16 @@ +import sys from typing import IO, Union _FD = Union[int, IO[str]] -# XXX: Undocumented integer constants -IFLAG: int -OFLAG: int -CFLAG: int -LFLAG: int -ISPEED: int -OSPEED: int -CC: int - -def setraw(fd: _FD, when: int = ...) -> None: ... -def setcbreak(fd: _FD, when: int = ...) -> None: ... +if sys.platform != "win32": + # XXX: Undocumented integer constants + IFLAG: int + OFLAG: int + CFLAG: int + LFLAG: int + ISPEED: int + OSPEED: int + CC: int + def setraw(fd: _FD, when: int = ...) -> None: ... + def setcbreak(fd: _FD, when: int = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/types.pyi b/mypy/typeshed/stdlib/@python2/types.pyi index 72b9321a860f3..0feee45305869 100644 --- a/mypy/typeshed/stdlib/@python2/types.pyi +++ b/mypy/typeshed/stdlib/@python2/types.pyi @@ -148,7 +148,7 @@ class FrameType: f_exc_traceback: None f_globals: Dict[str, Any] f_lasti: int - f_lineno: int + f_lineno: int | None f_locals: Dict[str, Any] f_restricted: bool f_trace: Callable[[], None] diff --git a/mypy/typeshed/stdlib/VERSIONS b/mypy/typeshed/stdlib/VERSIONS index 9b9271117fa73..e82161d97cb64 100644 --- a/mypy/typeshed/stdlib/VERSIONS +++ b/mypy/typeshed/stdlib/VERSIONS @@ -29,8 +29,8 @@ _compression: 3.6- _csv: 2.7- _curses: 2.7- _decimal: 3.6- -_dummy_thread: 3.6- -_dummy_threading: 2.7- +_dummy_thread: 3.6-3.8 +_dummy_threading: 2.7-3.8 _heapq: 2.7- _imp: 3.6- _json: 2.7- @@ -103,8 +103,9 @@ decimal: 2.7- difflib: 2.7- dis: 2.7- distutils: 2.7- +distutils.command.bdist_msi: 2.7-3.10 doctest: 2.7- -dummy_threading: 2.7- +dummy_threading: 2.7-3.8 email: 2.7- encodings: 2.7- ensurepip: 2.7- @@ -138,6 +139,7 @@ imghdr: 2.7- imp: 2.7- importlib: 2.7- importlib.metadata: 3.8- +importlib.metadata._meta: 3.10- importlib.resources: 3.7- inspect: 2.7- io: 2.7- @@ -259,6 +261,7 @@ typing: 3.5- typing_extensions: 2.7- unicodedata: 2.7- unittest: 2.7- +unittest._log: 3.9- urllib: 2.7- uu: 2.7- uuid: 2.7- diff --git a/mypy/typeshed/stdlib/_bisect.pyi b/mypy/typeshed/stdlib/_bisect.pyi index 6da6e7f588235..1f67dadd89a00 100644 --- a/mypy/typeshed/stdlib/_bisect.pyi +++ b/mypy/typeshed/stdlib/_bisect.pyi @@ -1,21 +1,31 @@ import sys -from _typeshed import SupportsLessThan +from _typeshed import SupportsRichComparison from typing import Callable, MutableSequence, Sequence, TypeVar _T = TypeVar("_T") if sys.version_info >= (3, 10): def bisect_left( - a: Sequence[_T], x: _T, lo: int = ..., hi: int | None = ..., *, key: Callable[[_T], SupportsLessThan] | None = ... + a: Sequence[_T], x: _T, lo: int = ..., hi: int | None = ..., *, key: Callable[[_T], SupportsRichComparison] | None = ... ) -> int: ... def bisect_right( - a: Sequence[_T], x: _T, lo: int = ..., hi: int | None = ..., *, key: Callable[[_T], SupportsLessThan] | None = ... + a: Sequence[_T], x: _T, lo: int = ..., hi: int | None = ..., *, key: Callable[[_T], SupportsRichComparison] | None = ... ) -> int: ... def insort_left( - a: MutableSequence[_T], x: _T, lo: int = ..., hi: int | None = ..., *, key: Callable[[_T], SupportsLessThan] | None = ... + a: MutableSequence[_T], + x: _T, + lo: int = ..., + hi: int | None = ..., + *, + key: Callable[[_T], SupportsRichComparison] | None = ..., ) -> None: ... def insort_right( - a: MutableSequence[_T], x: _T, lo: int = ..., hi: int | None = ..., *, key: Callable[[_T], SupportsLessThan] | None = ... + a: MutableSequence[_T], + x: _T, + lo: int = ..., + hi: int | None = ..., + *, + key: Callable[[_T], SupportsRichComparison] | None = ..., ) -> None: ... else: diff --git a/mypy/typeshed/stdlib/_codecs.pyi b/mypy/typeshed/stdlib/_codecs.pyi index 5e4a9ad6da3d9..470722a293a3e 100644 --- a/mypy/typeshed/stdlib/_codecs.pyi +++ b/mypy/typeshed/stdlib/_codecs.pyi @@ -1,13 +1,13 @@ import codecs import sys -from typing import Any, Callable, Dict, Tuple, Union +from typing import Any, Callable, Union # This type is not exposed; it is defined in unicodeobject.c class _EncodingMap: def size(self) -> int: ... -_MapT = Union[Dict[int, int], _EncodingMap] -_Handler = Callable[[Exception], Tuple[str, int]] +_MapT = Union[dict[int, int], _EncodingMap] +_Handler = Callable[[Exception], tuple[str, int]] def register(__search_function: Callable[[str], Any]) -> None: ... def register_error(__errors: str, __handler: _Handler) -> None: ... @@ -24,10 +24,22 @@ def escape_decode(__data: str | bytes, __errors: str | None = ...) -> tuple[str, def escape_encode(__data: bytes, __errors: str | None = ...) -> tuple[bytes, int]: ... def latin_1_decode(__data: bytes, __errors: str | None = ...) -> tuple[str, int]: ... def latin_1_encode(__str: str, __errors: str | None = ...) -> tuple[bytes, int]: ... -def raw_unicode_escape_decode(__data: str | bytes, __errors: str | None = ...) -> tuple[str, int]: ... + +if sys.version_info >= (3, 9): + def raw_unicode_escape_decode(__data: str | bytes, __errors: str | None = ..., __final: bool = ...) -> tuple[str, int]: ... + +else: + def raw_unicode_escape_decode(__data: str | bytes, __errors: str | None = ...) -> tuple[str, int]: ... + def raw_unicode_escape_encode(__str: str, __errors: str | None = ...) -> tuple[bytes, int]: ... def readbuffer_encode(__data: str | bytes, __errors: str | None = ...) -> tuple[bytes, int]: ... -def unicode_escape_decode(__data: str | bytes, __errors: str | None = ...) -> tuple[str, int]: ... + +if sys.version_info >= (3, 9): + def unicode_escape_decode(__data: str | bytes, __errors: str | None = ..., __final: bool = ...) -> tuple[str, int]: ... + +else: + def unicode_escape_decode(__data: str | bytes, __errors: str | None = ...) -> tuple[str, int]: ... + def unicode_escape_encode(__str: str, __errors: str | None = ...) -> tuple[bytes, int]: ... if sys.version_info < (3, 8): diff --git a/mypy/typeshed/stdlib/_compat_pickle.pyi b/mypy/typeshed/stdlib/_compat_pickle.pyi index 76aba3020321c..50fb22442cc92 100644 --- a/mypy/typeshed/stdlib/_compat_pickle.pyi +++ b/mypy/typeshed/stdlib/_compat_pickle.pyi @@ -1,10 +1,8 @@ -from typing import Tuple - IMPORT_MAPPING: dict[str, str] NAME_MAPPING: dict[tuple[str, str], tuple[str, str]] -PYTHON2_EXCEPTIONS: Tuple[str, ...] -MULTIPROCESSING_EXCEPTIONS: Tuple[str, ...] +PYTHON2_EXCEPTIONS: tuple[str, ...] +MULTIPROCESSING_EXCEPTIONS: tuple[str, ...] REVERSE_IMPORT_MAPPING: dict[str, str] REVERSE_NAME_MAPPING: dict[tuple[str, str], tuple[str, str]] -PYTHON3_OSERROR_EXCEPTIONS: Tuple[str, ...] -PYTHON3_IMPORTERROR_EXCEPTIONS: Tuple[str, ...] +PYTHON3_OSERROR_EXCEPTIONS: tuple[str, ...] +PYTHON3_IMPORTERROR_EXCEPTIONS: tuple[str, ...] diff --git a/mypy/typeshed/stdlib/_compression.pyi b/mypy/typeshed/stdlib/_compression.pyi index 8f81847ff4926..31940e3eb15b2 100644 --- a/mypy/typeshed/stdlib/_compression.pyi +++ b/mypy/typeshed/stdlib/_compression.pyi @@ -1,6 +1,6 @@ from _typeshed import WriteableBuffer from io import BufferedIOBase, RawIOBase -from typing import Any, Callable, Protocol, Tuple, Type +from typing import Any, Callable, Protocol, Type BUFFER_SIZE: Any @@ -16,7 +16,7 @@ class DecompressReader(RawIOBase): self, fp: _Reader, decomp_factory: Callable[..., object], - trailing_error: Type[Exception] | Tuple[Type[Exception], ...] = ..., + trailing_error: Type[Exception] | tuple[Type[Exception], ...] = ..., **decomp_args: Any, ) -> None: ... def readable(self) -> bool: ... diff --git a/mypy/typeshed/stdlib/_csv.pyi b/mypy/typeshed/stdlib/_csv.pyi index 1dc43780f6876..54e9099bbdcd3 100644 --- a/mypy/typeshed/stdlib/_csv.pyi +++ b/mypy/typeshed/stdlib/_csv.pyi @@ -1,4 +1,4 @@ -from typing import Any, Iterable, Iterator, List, Protocol, Type, Union +from typing import Any, Iterable, Iterator, Protocol, Type, Union QUOTE_ALL: int QUOTE_MINIMAL: int @@ -20,7 +20,7 @@ class Dialect: _DialectLike = Union[str, Dialect, Type[Dialect]] -class _reader(Iterator[List[str]]): +class _reader(Iterator[list[str]]): dialect: Dialect line_num: int def __next__(self) -> list[str]: ... @@ -31,7 +31,7 @@ class _writer: def writerows(self, rows: Iterable[Iterable[Any]]) -> None: ... class _Writer(Protocol): - def write(self, s: str) -> Any: ... + def write(self, __s: str) -> object: ... def writer(csvfile: _Writer, dialect: _DialectLike = ..., **fmtparams: Any) -> _writer: ... def reader(csvfile: Iterable[str], dialect: _DialectLike = ..., **fmtparams: Any) -> _reader: ... diff --git a/mypy/typeshed/stdlib/_curses.pyi b/mypy/typeshed/stdlib/_curses.pyi index e0f978c5cae11..9f23eeb1c6dc6 100644 --- a/mypy/typeshed/stdlib/_curses.pyi +++ b/mypy/typeshed/stdlib/_curses.pyi @@ -1,548 +1,547 @@ import sys -from typing import IO, Any, BinaryIO, NamedTuple, Union, overload +from _typeshed import SupportsRead +from typing import IO, Any, NamedTuple, Union, overload -_chtype = Union[str, bytes, int] +if sys.platform != "win32": + _chtype = Union[str, bytes, int] -# ACS codes are only initialized after initscr is called -ACS_BBSS: int -ACS_BLOCK: int -ACS_BOARD: int -ACS_BSBS: int -ACS_BSSB: int -ACS_BSSS: int -ACS_BTEE: int -ACS_BULLET: int -ACS_CKBOARD: int -ACS_DARROW: int -ACS_DEGREE: int -ACS_DIAMOND: int -ACS_GEQUAL: int -ACS_HLINE: int -ACS_LANTERN: int -ACS_LARROW: int -ACS_LEQUAL: int -ACS_LLCORNER: int -ACS_LRCORNER: int -ACS_LTEE: int -ACS_NEQUAL: int -ACS_PI: int -ACS_PLMINUS: int -ACS_PLUS: int -ACS_RARROW: int -ACS_RTEE: int -ACS_S1: int -ACS_S3: int -ACS_S7: int -ACS_S9: int -ACS_SBBS: int -ACS_SBSB: int -ACS_SBSS: int -ACS_SSBB: int -ACS_SSBS: int -ACS_SSSB: int -ACS_SSSS: int -ACS_STERLING: int -ACS_TTEE: int -ACS_UARROW: int -ACS_ULCORNER: int -ACS_URCORNER: int -ACS_VLINE: int -ALL_MOUSE_EVENTS: int -A_ALTCHARSET: int -A_ATTRIBUTES: int -A_BLINK: int -A_BOLD: int -A_CHARTEXT: int -A_COLOR: int -A_DIM: int -A_HORIZONTAL: int -A_INVIS: int -if sys.version_info >= (3, 7): - A_ITALIC: int -A_LEFT: int -A_LOW: int -A_NORMAL: int -A_PROTECT: int -A_REVERSE: int -A_RIGHT: int -A_STANDOUT: int -A_TOP: int -A_UNDERLINE: int -A_VERTICAL: int -BUTTON1_CLICKED: int -BUTTON1_DOUBLE_CLICKED: int -BUTTON1_PRESSED: int -BUTTON1_RELEASED: int -BUTTON1_TRIPLE_CLICKED: int -BUTTON2_CLICKED: int -BUTTON2_DOUBLE_CLICKED: int -BUTTON2_PRESSED: int -BUTTON2_RELEASED: int -BUTTON2_TRIPLE_CLICKED: int -BUTTON3_CLICKED: int -BUTTON3_DOUBLE_CLICKED: int -BUTTON3_PRESSED: int -BUTTON3_RELEASED: int -BUTTON3_TRIPLE_CLICKED: int -BUTTON4_CLICKED: int -BUTTON4_DOUBLE_CLICKED: int -BUTTON4_PRESSED: int -BUTTON4_RELEASED: int -BUTTON4_TRIPLE_CLICKED: int -# Darwin ncurses doesn't provide BUTTON5_* constants -if sys.version_info >= (3, 10) and sys.platform != "darwin": - BUTTON5_PRESSED: int - BUTTON5_RELEASED: int - BUTTON5_CLICKED: int - BUTTON5_DOUBLE_CLICKED: int - BUTTON5_TRIPLE_CLICKED: int -BUTTON_ALT: int -BUTTON_CTRL: int -BUTTON_SHIFT: int -COLOR_BLACK: int -COLOR_BLUE: int -COLOR_CYAN: int -COLOR_GREEN: int -COLOR_MAGENTA: int -COLOR_RED: int -COLOR_WHITE: int -COLOR_YELLOW: int -ERR: int -KEY_A1: int -KEY_A3: int -KEY_B2: int -KEY_BACKSPACE: int -KEY_BEG: int -KEY_BREAK: int -KEY_BTAB: int -KEY_C1: int -KEY_C3: int -KEY_CANCEL: int -KEY_CATAB: int -KEY_CLEAR: int -KEY_CLOSE: int -KEY_COMMAND: int -KEY_COPY: int -KEY_CREATE: int -KEY_CTAB: int -KEY_DC: int -KEY_DL: int -KEY_DOWN: int -KEY_EIC: int -KEY_END: int -KEY_ENTER: int -KEY_EOL: int -KEY_EOS: int -KEY_EXIT: int -KEY_F0: int -KEY_F1: int -KEY_F10: int -KEY_F11: int -KEY_F12: int -KEY_F13: int -KEY_F14: int -KEY_F15: int -KEY_F16: int -KEY_F17: int -KEY_F18: int -KEY_F19: int -KEY_F2: int -KEY_F20: int -KEY_F21: int -KEY_F22: int -KEY_F23: int -KEY_F24: int -KEY_F25: int -KEY_F26: int -KEY_F27: int -KEY_F28: int -KEY_F29: int -KEY_F3: int -KEY_F30: int -KEY_F31: int -KEY_F32: int -KEY_F33: int -KEY_F34: int -KEY_F35: int -KEY_F36: int -KEY_F37: int -KEY_F38: int -KEY_F39: int -KEY_F4: int -KEY_F40: int -KEY_F41: int -KEY_F42: int -KEY_F43: int -KEY_F44: int -KEY_F45: int -KEY_F46: int -KEY_F47: int -KEY_F48: int -KEY_F49: int -KEY_F5: int -KEY_F50: int -KEY_F51: int -KEY_F52: int -KEY_F53: int -KEY_F54: int -KEY_F55: int -KEY_F56: int -KEY_F57: int -KEY_F58: int -KEY_F59: int -KEY_F6: int -KEY_F60: int -KEY_F61: int -KEY_F62: int -KEY_F63: int -KEY_F7: int -KEY_F8: int -KEY_F9: int -KEY_FIND: int -KEY_HELP: int -KEY_HOME: int -KEY_IC: int -KEY_IL: int -KEY_LEFT: int -KEY_LL: int -KEY_MARK: int -KEY_MAX: int -KEY_MESSAGE: int -KEY_MIN: int -KEY_MOUSE: int -KEY_MOVE: int -KEY_NEXT: int -KEY_NPAGE: int -KEY_OPEN: int -KEY_OPTIONS: int -KEY_PPAGE: int -KEY_PREVIOUS: int -KEY_PRINT: int -KEY_REDO: int -KEY_REFERENCE: int -KEY_REFRESH: int -KEY_REPLACE: int -KEY_RESET: int -KEY_RESIZE: int -KEY_RESTART: int -KEY_RESUME: int -KEY_RIGHT: int -KEY_SAVE: int -KEY_SBEG: int -KEY_SCANCEL: int -KEY_SCOMMAND: int -KEY_SCOPY: int -KEY_SCREATE: int -KEY_SDC: int -KEY_SDL: int -KEY_SELECT: int -KEY_SEND: int -KEY_SEOL: int -KEY_SEXIT: int -KEY_SF: int -KEY_SFIND: int -KEY_SHELP: int -KEY_SHOME: int -KEY_SIC: int -KEY_SLEFT: int -KEY_SMESSAGE: int -KEY_SMOVE: int -KEY_SNEXT: int -KEY_SOPTIONS: int -KEY_SPREVIOUS: int -KEY_SPRINT: int -KEY_SR: int -KEY_SREDO: int -KEY_SREPLACE: int -KEY_SRESET: int -KEY_SRIGHT: int -KEY_SRSUME: int -KEY_SSAVE: int -KEY_SSUSPEND: int -KEY_STAB: int -KEY_SUNDO: int -KEY_SUSPEND: int -KEY_UNDO: int -KEY_UP: int -OK: int -REPORT_MOUSE_POSITION: int -_C_API: Any -version: bytes - -def baudrate() -> int: ... -def beep() -> None: ... -def can_change_color() -> bool: ... -def cbreak(__flag: bool = ...) -> None: ... -def color_content(__color_number: int) -> tuple[int, int, int]: ... - -# Changed in Python 3.8.8 and 3.9.2 -if sys.version_info >= (3, 8): - def color_pair(pair_number: int) -> int: ... - -else: - def color_pair(__color_number: int) -> int: ... - -def curs_set(__visibility: int) -> int: ... -def def_prog_mode() -> None: ... -def def_shell_mode() -> None: ... -def delay_output(__ms: int) -> None: ... -def doupdate() -> None: ... -def echo(__flag: bool = ...) -> None: ... -def endwin() -> None: ... -def erasechar() -> bytes: ... -def filter() -> None: ... -def flash() -> None: ... -def flushinp() -> None: ... -def getmouse() -> tuple[int, int, int, int, int]: ... -def getsyx() -> tuple[int, int]: ... -def getwin(__file: BinaryIO) -> _CursesWindow: ... -def halfdelay(__tenths: int) -> None: ... -def has_colors() -> bool: ... - -if sys.version_info >= (3, 10): - def has_extended_color_support() -> bool: ... - -def has_ic() -> bool: ... -def has_il() -> bool: ... -def has_key(__key: int) -> bool: ... -def init_color(__color_number: int, __r: int, __g: int, __b: int) -> None: ... -def init_pair(__pair_number: int, __fg: int, __bg: int) -> None: ... -def initscr() -> _CursesWindow: ... -def intrflush(__flag: bool) -> None: ... -def is_term_resized(__nlines: int, __ncols: int) -> bool: ... -def isendwin() -> bool: ... -def keyname(__key: int) -> bytes: ... -def killchar() -> bytes: ... -def longname() -> bytes: ... -def meta(__yes: bool) -> None: ... -def mouseinterval(__interval: int) -> None: ... -def mousemask(__newmask: int) -> tuple[int, int]: ... -def napms(__ms: int) -> int: ... -def newpad(__nlines: int, __ncols: int) -> _CursesWindow: ... -def newwin(__nlines: int, __ncols: int, __begin_y: int = ..., __begin_x: int = ...) -> _CursesWindow: ... -def nl(__flag: bool = ...) -> None: ... -def nocbreak() -> None: ... -def noecho() -> None: ... -def nonl() -> None: ... -def noqiflush() -> None: ... -def noraw() -> None: ... -def pair_content(__pair_number: int) -> tuple[int, int]: ... -def pair_number(__attr: int) -> int: ... -def putp(__string: bytes) -> None: ... -def qiflush(__flag: bool = ...) -> None: ... -def raw(__flag: bool = ...) -> None: ... -def reset_prog_mode() -> None: ... -def reset_shell_mode() -> None: ... -def resetty() -> None: ... -def resize_term(__nlines: int, __ncols: int) -> None: ... -def resizeterm(__nlines: int, __ncols: int) -> None: ... -def savetty() -> None: ... -def setsyx(__y: int, __x: int) -> None: ... -def setupterm(term: str | None = ..., fd: int = ...) -> None: ... -def start_color() -> None: ... -def termattrs() -> int: ... -def termname() -> bytes: ... -def tigetflag(__capname: str) -> int: ... -def tigetnum(__capname: str) -> int: ... -def tigetstr(__capname: str) -> bytes: ... -def tparm( - __str: bytes, - __i1: int = ..., - __i2: int = ..., - __i3: int = ..., - __i4: int = ..., - __i5: int = ..., - __i6: int = ..., - __i7: int = ..., - __i8: int = ..., - __i9: int = ..., -) -> bytes: ... -def typeahead(__fd: int) -> None: ... -def unctrl(__ch: _chtype) -> bytes: ... -def unget_wch(__ch: int | str) -> None: ... -def ungetch(__ch: _chtype) -> None: ... -def ungetmouse(__id: int, __x: int, __y: int, __z: int, __bstate: int) -> None: ... -def update_lines_cols() -> int: ... -def use_default_colors() -> None: ... -def use_env(__flag: bool) -> None: ... - -class error(Exception): ... - -class _CursesWindow: - encoding: str - @overload - def addch(self, ch: _chtype, attr: int = ...) -> None: ... - @overload - def addch(self, y: int, x: int, ch: _chtype, attr: int = ...) -> None: ... - @overload - def addnstr(self, str: str, n: int, attr: int = ...) -> None: ... - @overload - def addnstr(self, y: int, x: int, str: str, n: int, attr: int = ...) -> None: ... - @overload - def addstr(self, str: str, attr: int = ...) -> None: ... - @overload - def addstr(self, y: int, x: int, str: str, attr: int = ...) -> None: ... - def attroff(self, __attr: int) -> None: ... - def attron(self, __attr: int) -> None: ... - def attrset(self, __attr: int) -> None: ... - def bkgd(self, __ch: _chtype, __attr: int = ...) -> None: ... - def bkgdset(self, __ch: _chtype, __attr: int = ...) -> None: ... - def border( - self, - ls: _chtype = ..., - rs: _chtype = ..., - ts: _chtype = ..., - bs: _chtype = ..., - tl: _chtype = ..., - tr: _chtype = ..., - bl: _chtype = ..., - br: _chtype = ..., - ) -> None: ... - @overload - def box(self) -> None: ... - @overload - def box(self, vertch: _chtype = ..., horch: _chtype = ...) -> None: ... - @overload - def chgat(self, attr: int) -> None: ... - @overload - def chgat(self, num: int, attr: int) -> None: ... - @overload - def chgat(self, y: int, x: int, attr: int) -> None: ... - @overload - def chgat(self, y: int, x: int, num: int, attr: int) -> None: ... - def clear(self) -> None: ... - def clearok(self, yes: int) -> None: ... - def clrtobot(self) -> None: ... - def clrtoeol(self) -> None: ... - def cursyncup(self) -> None: ... - @overload - def delch(self) -> None: ... - @overload - def delch(self, y: int, x: int) -> None: ... - def deleteln(self) -> None: ... - @overload - def derwin(self, begin_y: int, begin_x: int) -> _CursesWindow: ... - @overload - def derwin(self, nlines: int, ncols: int, begin_y: int, begin_x: int) -> _CursesWindow: ... - def echochar(self, __ch: _chtype, __attr: int = ...) -> None: ... - def enclose(self, __y: int, __x: int) -> bool: ... - def erase(self) -> None: ... - def getbegyx(self) -> tuple[int, int]: ... - def getbkgd(self) -> tuple[int, int]: ... - @overload - def getch(self) -> int: ... - @overload - def getch(self, y: int, x: int) -> int: ... - @overload - def get_wch(self) -> int | str: ... - @overload - def get_wch(self, y: int, x: int) -> int | str: ... - @overload - def getkey(self) -> str: ... - @overload - def getkey(self, y: int, x: int) -> str: ... - def getmaxyx(self) -> tuple[int, int]: ... - def getparyx(self) -> tuple[int, int]: ... - @overload - def getstr(self) -> _chtype: ... - @overload - def getstr(self, n: int) -> _chtype: ... - @overload - def getstr(self, y: int, x: int) -> _chtype: ... - @overload - def getstr(self, y: int, x: int, n: int) -> _chtype: ... - def getyx(self) -> tuple[int, int]: ... - @overload - def hline(self, ch: _chtype, n: int) -> None: ... - @overload - def hline(self, y: int, x: int, ch: _chtype, n: int) -> None: ... - def idcok(self, flag: bool) -> None: ... - def idlok(self, yes: bool) -> None: ... - def immedok(self, flag: bool) -> None: ... - @overload - def inch(self) -> _chtype: ... - @overload - def inch(self, y: int, x: int) -> _chtype: ... - @overload - def insch(self, ch: _chtype, attr: int = ...) -> None: ... - @overload - def insch(self, y: int, x: int, ch: _chtype, attr: int = ...) -> None: ... - def insdelln(self, nlines: int) -> None: ... - def insertln(self) -> None: ... - @overload - def insnstr(self, str: str, n: int, attr: int = ...) -> None: ... - @overload - def insnstr(self, y: int, x: int, str: str, n: int, attr: int = ...) -> None: ... - @overload - def insstr(self, str: str, attr: int = ...) -> None: ... - @overload - def insstr(self, y: int, x: int, str: str, attr: int = ...) -> None: ... - @overload - def instr(self, n: int = ...) -> _chtype: ... - @overload - def instr(self, y: int, x: int, n: int = ...) -> _chtype: ... - def is_linetouched(self, __line: int) -> bool: ... - def is_wintouched(self) -> bool: ... - def keypad(self, yes: bool) -> None: ... - def leaveok(self, yes: bool) -> None: ... - def move(self, new_y: int, new_x: int) -> None: ... - def mvderwin(self, y: int, x: int) -> None: ... - def mvwin(self, new_y: int, new_x: int) -> None: ... - def nodelay(self, yes: bool) -> None: ... - def notimeout(self, yes: bool) -> None: ... - @overload - def noutrefresh(self) -> None: ... - @overload - def noutrefresh(self, pminrow: int, pmincol: int, sminrow: int, smincol: int, smaxrow: int, smaxcol: int) -> None: ... - @overload - def overlay(self, destwin: _CursesWindow) -> None: ... - @overload - def overlay( - self, destwin: _CursesWindow, sminrow: int, smincol: int, dminrow: int, dmincol: int, dmaxrow: int, dmaxcol: int - ) -> None: ... - @overload - def overwrite(self, destwin: _CursesWindow) -> None: ... - @overload - def overwrite( - self, destwin: _CursesWindow, sminrow: int, smincol: int, dminrow: int, dmincol: int, dmaxrow: int, dmaxcol: int - ) -> None: ... - def putwin(self, __file: IO[Any]) -> None: ... - def redrawln(self, __beg: int, __num: int) -> None: ... - def redrawwin(self) -> None: ... - @overload - def refresh(self) -> None: ... - @overload - def refresh(self, pminrow: int, pmincol: int, sminrow: int, smincol: int, smaxrow: int, smaxcol: int) -> None: ... - def resize(self, nlines: int, ncols: int) -> None: ... - def scroll(self, lines: int = ...) -> None: ... - def scrollok(self, flag: bool) -> None: ... - def setscrreg(self, __top: int, __bottom: int) -> None: ... - def standend(self) -> None: ... - def standout(self) -> None: ... - @overload - def subpad(self, begin_y: int, begin_x: int) -> _CursesWindow: ... - @overload - def subpad(self, nlines: int, ncols: int, begin_y: int, begin_x: int) -> _CursesWindow: ... - @overload - def subwin(self, begin_y: int, begin_x: int) -> _CursesWindow: ... - @overload - def subwin(self, nlines: int, ncols: int, begin_y: int, begin_x: int) -> _CursesWindow: ... - def syncdown(self) -> None: ... - def syncok(self, flag: bool) -> None: ... - def syncup(self) -> None: ... - def timeout(self, delay: int) -> None: ... - def touchline(self, start: int, count: int, changed: bool = ...) -> None: ... - def touchwin(self) -> None: ... - def untouchwin(self) -> None: ... - @overload - def vline(self, ch: _chtype, n: int) -> None: ... - @overload - def vline(self, y: int, x: int, ch: _chtype, n: int) -> None: ... - -if sys.version_info >= (3, 8): - class _ncurses_version(NamedTuple): - major: int - minor: int - patch: int - ncurses_version: _ncurses_version - window = _CursesWindow # undocumented + # ACS codes are only initialized after initscr is called + ACS_BBSS: int + ACS_BLOCK: int + ACS_BOARD: int + ACS_BSBS: int + ACS_BSSB: int + ACS_BSSS: int + ACS_BTEE: int + ACS_BULLET: int + ACS_CKBOARD: int + ACS_DARROW: int + ACS_DEGREE: int + ACS_DIAMOND: int + ACS_GEQUAL: int + ACS_HLINE: int + ACS_LANTERN: int + ACS_LARROW: int + ACS_LEQUAL: int + ACS_LLCORNER: int + ACS_LRCORNER: int + ACS_LTEE: int + ACS_NEQUAL: int + ACS_PI: int + ACS_PLMINUS: int + ACS_PLUS: int + ACS_RARROW: int + ACS_RTEE: int + ACS_S1: int + ACS_S3: int + ACS_S7: int + ACS_S9: int + ACS_SBBS: int + ACS_SBSB: int + ACS_SBSS: int + ACS_SSBB: int + ACS_SSBS: int + ACS_SSSB: int + ACS_SSSS: int + ACS_STERLING: int + ACS_TTEE: int + ACS_UARROW: int + ACS_ULCORNER: int + ACS_URCORNER: int + ACS_VLINE: int + ALL_MOUSE_EVENTS: int + A_ALTCHARSET: int + A_ATTRIBUTES: int + A_BLINK: int + A_BOLD: int + A_CHARTEXT: int + A_COLOR: int + A_DIM: int + A_HORIZONTAL: int + A_INVIS: int + if sys.version_info >= (3, 7): + A_ITALIC: int + A_LEFT: int + A_LOW: int + A_NORMAL: int + A_PROTECT: int + A_REVERSE: int + A_RIGHT: int + A_STANDOUT: int + A_TOP: int + A_UNDERLINE: int + A_VERTICAL: int + BUTTON1_CLICKED: int + BUTTON1_DOUBLE_CLICKED: int + BUTTON1_PRESSED: int + BUTTON1_RELEASED: int + BUTTON1_TRIPLE_CLICKED: int + BUTTON2_CLICKED: int + BUTTON2_DOUBLE_CLICKED: int + BUTTON2_PRESSED: int + BUTTON2_RELEASED: int + BUTTON2_TRIPLE_CLICKED: int + BUTTON3_CLICKED: int + BUTTON3_DOUBLE_CLICKED: int + BUTTON3_PRESSED: int + BUTTON3_RELEASED: int + BUTTON3_TRIPLE_CLICKED: int + BUTTON4_CLICKED: int + BUTTON4_DOUBLE_CLICKED: int + BUTTON4_PRESSED: int + BUTTON4_RELEASED: int + BUTTON4_TRIPLE_CLICKED: int + # Darwin ncurses doesn't provide BUTTON5_* constants + if sys.version_info >= (3, 10) and sys.platform != "darwin": + BUTTON5_PRESSED: int + BUTTON5_RELEASED: int + BUTTON5_CLICKED: int + BUTTON5_DOUBLE_CLICKED: int + BUTTON5_TRIPLE_CLICKED: int + BUTTON_ALT: int + BUTTON_CTRL: int + BUTTON_SHIFT: int + COLOR_BLACK: int + COLOR_BLUE: int + COLOR_CYAN: int + COLOR_GREEN: int + COLOR_MAGENTA: int + COLOR_RED: int + COLOR_WHITE: int + COLOR_YELLOW: int + ERR: int + KEY_A1: int + KEY_A3: int + KEY_B2: int + KEY_BACKSPACE: int + KEY_BEG: int + KEY_BREAK: int + KEY_BTAB: int + KEY_C1: int + KEY_C3: int + KEY_CANCEL: int + KEY_CATAB: int + KEY_CLEAR: int + KEY_CLOSE: int + KEY_COMMAND: int + KEY_COPY: int + KEY_CREATE: int + KEY_CTAB: int + KEY_DC: int + KEY_DL: int + KEY_DOWN: int + KEY_EIC: int + KEY_END: int + KEY_ENTER: int + KEY_EOL: int + KEY_EOS: int + KEY_EXIT: int + KEY_F0: int + KEY_F1: int + KEY_F10: int + KEY_F11: int + KEY_F12: int + KEY_F13: int + KEY_F14: int + KEY_F15: int + KEY_F16: int + KEY_F17: int + KEY_F18: int + KEY_F19: int + KEY_F2: int + KEY_F20: int + KEY_F21: int + KEY_F22: int + KEY_F23: int + KEY_F24: int + KEY_F25: int + KEY_F26: int + KEY_F27: int + KEY_F28: int + KEY_F29: int + KEY_F3: int + KEY_F30: int + KEY_F31: int + KEY_F32: int + KEY_F33: int + KEY_F34: int + KEY_F35: int + KEY_F36: int + KEY_F37: int + KEY_F38: int + KEY_F39: int + KEY_F4: int + KEY_F40: int + KEY_F41: int + KEY_F42: int + KEY_F43: int + KEY_F44: int + KEY_F45: int + KEY_F46: int + KEY_F47: int + KEY_F48: int + KEY_F49: int + KEY_F5: int + KEY_F50: int + KEY_F51: int + KEY_F52: int + KEY_F53: int + KEY_F54: int + KEY_F55: int + KEY_F56: int + KEY_F57: int + KEY_F58: int + KEY_F59: int + KEY_F6: int + KEY_F60: int + KEY_F61: int + KEY_F62: int + KEY_F63: int + KEY_F7: int + KEY_F8: int + KEY_F9: int + KEY_FIND: int + KEY_HELP: int + KEY_HOME: int + KEY_IC: int + KEY_IL: int + KEY_LEFT: int + KEY_LL: int + KEY_MARK: int + KEY_MAX: int + KEY_MESSAGE: int + KEY_MIN: int + KEY_MOUSE: int + KEY_MOVE: int + KEY_NEXT: int + KEY_NPAGE: int + KEY_OPEN: int + KEY_OPTIONS: int + KEY_PPAGE: int + KEY_PREVIOUS: int + KEY_PRINT: int + KEY_REDO: int + KEY_REFERENCE: int + KEY_REFRESH: int + KEY_REPLACE: int + KEY_RESET: int + KEY_RESIZE: int + KEY_RESTART: int + KEY_RESUME: int + KEY_RIGHT: int + KEY_SAVE: int + KEY_SBEG: int + KEY_SCANCEL: int + KEY_SCOMMAND: int + KEY_SCOPY: int + KEY_SCREATE: int + KEY_SDC: int + KEY_SDL: int + KEY_SELECT: int + KEY_SEND: int + KEY_SEOL: int + KEY_SEXIT: int + KEY_SF: int + KEY_SFIND: int + KEY_SHELP: int + KEY_SHOME: int + KEY_SIC: int + KEY_SLEFT: int + KEY_SMESSAGE: int + KEY_SMOVE: int + KEY_SNEXT: int + KEY_SOPTIONS: int + KEY_SPREVIOUS: int + KEY_SPRINT: int + KEY_SR: int + KEY_SREDO: int + KEY_SREPLACE: int + KEY_SRESET: int + KEY_SRIGHT: int + KEY_SRSUME: int + KEY_SSAVE: int + KEY_SSUSPEND: int + KEY_STAB: int + KEY_SUNDO: int + KEY_SUSPEND: int + KEY_UNDO: int + KEY_UP: int + OK: int + REPORT_MOUSE_POSITION: int + _C_API: Any + version: bytes + def baudrate() -> int: ... + def beep() -> None: ... + def can_change_color() -> bool: ... + def cbreak(__flag: bool = ...) -> None: ... + def color_content(__color_number: int) -> tuple[int, int, int]: ... + # Changed in Python 3.8.8 and 3.9.2 + if sys.version_info >= (3, 8): + def color_pair(pair_number: int) -> int: ... + else: + def color_pair(__color_number: int) -> int: ... + def curs_set(__visibility: int) -> int: ... + def def_prog_mode() -> None: ... + def def_shell_mode() -> None: ... + def delay_output(__ms: int) -> None: ... + def doupdate() -> None: ... + def echo(__flag: bool = ...) -> None: ... + def endwin() -> None: ... + def erasechar() -> bytes: ... + def filter() -> None: ... + def flash() -> None: ... + def flushinp() -> None: ... + if sys.version_info >= (3, 9): + def get_escdelay() -> int: ... + def get_tabsize() -> int: ... + def getmouse() -> tuple[int, int, int, int, int]: ... + def getsyx() -> tuple[int, int]: ... + def getwin(__file: SupportsRead[bytes]) -> _CursesWindow: ... + def halfdelay(__tenths: int) -> None: ... + def has_colors() -> bool: ... + if sys.version_info >= (3, 10): + def has_extended_color_support() -> bool: ... + def has_ic() -> bool: ... + def has_il() -> bool: ... + def has_key(__key: int) -> bool: ... + def init_color(__color_number: int, __r: int, __g: int, __b: int) -> None: ... + def init_pair(__pair_number: int, __fg: int, __bg: int) -> None: ... + def initscr() -> _CursesWindow: ... + def intrflush(__flag: bool) -> None: ... + def is_term_resized(__nlines: int, __ncols: int) -> bool: ... + def isendwin() -> bool: ... + def keyname(__key: int) -> bytes: ... + def killchar() -> bytes: ... + def longname() -> bytes: ... + def meta(__yes: bool) -> None: ... + def mouseinterval(__interval: int) -> None: ... + def mousemask(__newmask: int) -> tuple[int, int]: ... + def napms(__ms: int) -> int: ... + def newpad(__nlines: int, __ncols: int) -> _CursesWindow: ... + def newwin(__nlines: int, __ncols: int, __begin_y: int = ..., __begin_x: int = ...) -> _CursesWindow: ... + def nl(__flag: bool = ...) -> None: ... + def nocbreak() -> None: ... + def noecho() -> None: ... + def nonl() -> None: ... + def noqiflush() -> None: ... + def noraw() -> None: ... + def pair_content(__pair_number: int) -> tuple[int, int]: ... + def pair_number(__attr: int) -> int: ... + def putp(__string: bytes) -> None: ... + def qiflush(__flag: bool = ...) -> None: ... + def raw(__flag: bool = ...) -> None: ... + def reset_prog_mode() -> None: ... + def reset_shell_mode() -> None: ... + def resetty() -> None: ... + def resize_term(__nlines: int, __ncols: int) -> None: ... + def resizeterm(__nlines: int, __ncols: int) -> None: ... + def savetty() -> None: ... + if sys.version_info >= (3, 9): + def set_escdelay(__ms: int) -> None: ... + def set_tabsize(__size: int) -> None: ... + def setsyx(__y: int, __x: int) -> None: ... + def setupterm(term: str | None = ..., fd: int = ...) -> None: ... + def start_color() -> None: ... + def termattrs() -> int: ... + def termname() -> bytes: ... + def tigetflag(__capname: str) -> int: ... + def tigetnum(__capname: str) -> int: ... + def tigetstr(__capname: str) -> bytes | None: ... + def tparm( + __str: bytes, + __i1: int = ..., + __i2: int = ..., + __i3: int = ..., + __i4: int = ..., + __i5: int = ..., + __i6: int = ..., + __i7: int = ..., + __i8: int = ..., + __i9: int = ..., + ) -> bytes: ... + def typeahead(__fd: int) -> None: ... + def unctrl(__ch: _chtype) -> bytes: ... + def unget_wch(__ch: int | str) -> None: ... + def ungetch(__ch: _chtype) -> None: ... + def ungetmouse(__id: int, __x: int, __y: int, __z: int, __bstate: int) -> None: ... + def update_lines_cols() -> None: ... + def use_default_colors() -> None: ... + def use_env(__flag: bool) -> None: ... + class error(Exception): ... + class _CursesWindow: + encoding: str + @overload + def addch(self, ch: _chtype, attr: int = ...) -> None: ... + @overload + def addch(self, y: int, x: int, ch: _chtype, attr: int = ...) -> None: ... + @overload + def addnstr(self, str: str, n: int, attr: int = ...) -> None: ... + @overload + def addnstr(self, y: int, x: int, str: str, n: int, attr: int = ...) -> None: ... + @overload + def addstr(self, str: str, attr: int = ...) -> None: ... + @overload + def addstr(self, y: int, x: int, str: str, attr: int = ...) -> None: ... + def attroff(self, __attr: int) -> None: ... + def attron(self, __attr: int) -> None: ... + def attrset(self, __attr: int) -> None: ... + def bkgd(self, __ch: _chtype, __attr: int = ...) -> None: ... + def bkgdset(self, __ch: _chtype, __attr: int = ...) -> None: ... + def border( + self, + ls: _chtype = ..., + rs: _chtype = ..., + ts: _chtype = ..., + bs: _chtype = ..., + tl: _chtype = ..., + tr: _chtype = ..., + bl: _chtype = ..., + br: _chtype = ..., + ) -> None: ... + @overload + def box(self) -> None: ... + @overload + def box(self, vertch: _chtype = ..., horch: _chtype = ...) -> None: ... + @overload + def chgat(self, attr: int) -> None: ... + @overload + def chgat(self, num: int, attr: int) -> None: ... + @overload + def chgat(self, y: int, x: int, attr: int) -> None: ... + @overload + def chgat(self, y: int, x: int, num: int, attr: int) -> None: ... + def clear(self) -> None: ... + def clearok(self, yes: int) -> None: ... + def clrtobot(self) -> None: ... + def clrtoeol(self) -> None: ... + def cursyncup(self) -> None: ... + @overload + def delch(self) -> None: ... + @overload + def delch(self, y: int, x: int) -> None: ... + def deleteln(self) -> None: ... + @overload + def derwin(self, begin_y: int, begin_x: int) -> _CursesWindow: ... + @overload + def derwin(self, nlines: int, ncols: int, begin_y: int, begin_x: int) -> _CursesWindow: ... + def echochar(self, __ch: _chtype, __attr: int = ...) -> None: ... + def enclose(self, __y: int, __x: int) -> bool: ... + def erase(self) -> None: ... + def getbegyx(self) -> tuple[int, int]: ... + def getbkgd(self) -> tuple[int, int]: ... + @overload + def getch(self) -> int: ... + @overload + def getch(self, y: int, x: int) -> int: ... + @overload + def get_wch(self) -> int | str: ... + @overload + def get_wch(self, y: int, x: int) -> int | str: ... + @overload + def getkey(self) -> str: ... + @overload + def getkey(self, y: int, x: int) -> str: ... + def getmaxyx(self) -> tuple[int, int]: ... + def getparyx(self) -> tuple[int, int]: ... + @overload + def getstr(self) -> bytes: ... + @overload + def getstr(self, n: int) -> bytes: ... + @overload + def getstr(self, y: int, x: int) -> bytes: ... + @overload + def getstr(self, y: int, x: int, n: int) -> bytes: ... + def getyx(self) -> tuple[int, int]: ... + @overload + def hline(self, ch: _chtype, n: int) -> None: ... + @overload + def hline(self, y: int, x: int, ch: _chtype, n: int) -> None: ... + def idcok(self, flag: bool) -> None: ... + def idlok(self, yes: bool) -> None: ... + def immedok(self, flag: bool) -> None: ... + @overload + def inch(self) -> int: ... + @overload + def inch(self, y: int, x: int) -> int: ... + @overload + def insch(self, ch: _chtype, attr: int = ...) -> None: ... + @overload + def insch(self, y: int, x: int, ch: _chtype, attr: int = ...) -> None: ... + def insdelln(self, nlines: int) -> None: ... + def insertln(self) -> None: ... + @overload + def insnstr(self, str: str, n: int, attr: int = ...) -> None: ... + @overload + def insnstr(self, y: int, x: int, str: str, n: int, attr: int = ...) -> None: ... + @overload + def insstr(self, str: str, attr: int = ...) -> None: ... + @overload + def insstr(self, y: int, x: int, str: str, attr: int = ...) -> None: ... + @overload + def instr(self, n: int = ...) -> bytes: ... + @overload + def instr(self, y: int, x: int, n: int = ...) -> bytes: ... + def is_linetouched(self, __line: int) -> bool: ... + def is_wintouched(self) -> bool: ... + def keypad(self, yes: bool) -> None: ... + def leaveok(self, yes: bool) -> None: ... + def move(self, new_y: int, new_x: int) -> None: ... + def mvderwin(self, y: int, x: int) -> None: ... + def mvwin(self, new_y: int, new_x: int) -> None: ... + def nodelay(self, yes: bool) -> None: ... + def notimeout(self, yes: bool) -> None: ... + @overload + def noutrefresh(self) -> None: ... + @overload + def noutrefresh(self, pminrow: int, pmincol: int, sminrow: int, smincol: int, smaxrow: int, smaxcol: int) -> None: ... + @overload + def overlay(self, destwin: _CursesWindow) -> None: ... + @overload + def overlay( + self, destwin: _CursesWindow, sminrow: int, smincol: int, dminrow: int, dmincol: int, dmaxrow: int, dmaxcol: int + ) -> None: ... + @overload + def overwrite(self, destwin: _CursesWindow) -> None: ... + @overload + def overwrite( + self, destwin: _CursesWindow, sminrow: int, smincol: int, dminrow: int, dmincol: int, dmaxrow: int, dmaxcol: int + ) -> None: ... + def putwin(self, __file: IO[Any]) -> None: ... + def redrawln(self, __beg: int, __num: int) -> None: ... + def redrawwin(self) -> None: ... + @overload + def refresh(self) -> None: ... + @overload + def refresh(self, pminrow: int, pmincol: int, sminrow: int, smincol: int, smaxrow: int, smaxcol: int) -> None: ... + def resize(self, nlines: int, ncols: int) -> None: ... + def scroll(self, lines: int = ...) -> None: ... + def scrollok(self, flag: bool) -> None: ... + def setscrreg(self, __top: int, __bottom: int) -> None: ... + def standend(self) -> None: ... + def standout(self) -> None: ... + @overload + def subpad(self, begin_y: int, begin_x: int) -> _CursesWindow: ... + @overload + def subpad(self, nlines: int, ncols: int, begin_y: int, begin_x: int) -> _CursesWindow: ... + @overload + def subwin(self, begin_y: int, begin_x: int) -> _CursesWindow: ... + @overload + def subwin(self, nlines: int, ncols: int, begin_y: int, begin_x: int) -> _CursesWindow: ... + def syncdown(self) -> None: ... + def syncok(self, flag: bool) -> None: ... + def syncup(self) -> None: ... + def timeout(self, delay: int) -> None: ... + def touchline(self, start: int, count: int, changed: bool = ...) -> None: ... + def touchwin(self) -> None: ... + def untouchwin(self) -> None: ... + @overload + def vline(self, ch: _chtype, n: int) -> None: ... + @overload + def vline(self, y: int, x: int, ch: _chtype, n: int) -> None: ... + if sys.version_info >= (3, 8): + class _ncurses_version(NamedTuple): + major: int + minor: int + patch: int + ncurses_version: _ncurses_version + window = _CursesWindow # undocumented diff --git a/mypy/typeshed/stdlib/_dummy_thread.pyi b/mypy/typeshed/stdlib/_dummy_thread.pyi index 886d9d7397809..6e936726a48fe 100644 --- a/mypy/typeshed/stdlib/_dummy_thread.pyi +++ b/mypy/typeshed/stdlib/_dummy_thread.pyi @@ -1,15 +1,15 @@ -from typing import Any, Callable, NoReturn, Tuple +from typing import Any, Callable, NoReturn TIMEOUT_MAX: int error = RuntimeError -def start_new_thread(function: Callable[..., Any], args: Tuple[Any, ...], kwargs: dict[str, Any] = ...) -> None: ... +def start_new_thread(function: Callable[..., Any], args: tuple[Any, ...], kwargs: dict[str, Any] = ...) -> None: ... def exit() -> NoReturn: ... def get_ident() -> int: ... def allocate_lock() -> LockType: ... def stack_size(size: int | None = ...) -> int: ... -class LockType(object): +class LockType: locked_status: bool def __init__(self) -> None: ... def acquire(self, waitflag: bool | None = ..., timeout: int = ...) -> bool: ... diff --git a/mypy/typeshed/stdlib/_dummy_threading.pyi b/mypy/typeshed/stdlib/_dummy_threading.pyi index 64998d86bf9fa..075ea4637f73f 100644 --- a/mypy/typeshed/stdlib/_dummy_threading.pyi +++ b/mypy/typeshed/stdlib/_dummy_threading.pyi @@ -28,7 +28,7 @@ TIMEOUT_MAX: float class ThreadError(Exception): ... -class local(object): +class local: def __getattribute__(self, name: str) -> Any: ... def __setattr__(self, name: str, value: Any) -> None: ... def __delattr__(self, name: str) -> None: ... diff --git a/mypy/typeshed/stdlib/_imp.pyi b/mypy/typeshed/stdlib/_imp.pyi index b61c9f29b96dc..23272591df4ce 100644 --- a/mypy/typeshed/stdlib/_imp.pyi +++ b/mypy/typeshed/stdlib/_imp.pyi @@ -1,7 +1,11 @@ +import sys import types from importlib.machinery import ModuleSpec from typing import Any +if sys.version_info >= (3, 7): + check_hash_based_pycs: str + def create_builtin(__spec: ModuleSpec) -> types.ModuleType: ... def create_dynamic(__spec: ModuleSpec, __file: Any = ...) -> None: ... def acquire_lock() -> None: ... diff --git a/mypy/typeshed/stdlib/_markupbase.pyi b/mypy/typeshed/stdlib/_markupbase.pyi index 368d32bd5b4c0..2c497f65bb434 100644 --- a/mypy/typeshed/stdlib/_markupbase.pyi +++ b/mypy/typeshed/stdlib/_markupbase.pyi @@ -1,6 +1,17 @@ +import sys +from typing import Any + class ParserBase: def __init__(self) -> None: ... - def error(self, message: str) -> None: ... def reset(self) -> None: ... def getpos(self) -> tuple[int, int]: ... def unknown_decl(self, data: str) -> None: ... + def parse_comment(self, i: int, report: int = ...) -> int: ... # undocumented + def parse_declaration(self, i: int) -> int: ... # undocumented + def parse_marked_section(self, i: int, report: int = ...) -> int: ... # undocumented + def updatepos(self, i: int, j: int) -> int: ... # undocumented + if sys.version_info < (3, 10): + # Removed from ParserBase: https://bugs.python.org/issue31844 + def error(self, message: str) -> Any: ... # undocumented + lineno: int # undocumented + offset: int # undocumented diff --git a/mypy/typeshed/stdlib/_msi.pyi b/mypy/typeshed/stdlib/_msi.pyi index 754febe68da9e..b7e852f38ae9c 100644 --- a/mypy/typeshed/stdlib/_msi.pyi +++ b/mypy/typeshed/stdlib/_msi.pyi @@ -10,8 +10,8 @@ if sys.platform == "win32": def Modify(self, mode: int, record: _Record) -> None: ... def Close(self) -> None: ... # Don't exist at runtime - __new__: None # type: ignore - __init__: None # type: ignore + __new__: None # type: ignore[assignment] + __init__: None # type: ignore[assignment] # Actual typename Summary, not exposed by the implementation class _Summary: def GetProperty(self, propid: int) -> str | bytes | None: ... @@ -19,8 +19,8 @@ if sys.platform == "win32": def SetProperty(self, propid: int, value: str | bytes) -> None: ... def Persist(self) -> None: ... # Don't exist at runtime - __new__: None # type: ignore - __init__: None # type: ignore + __new__: None # type: ignore[assignment] + __init__: None # type: ignore[assignment] # Actual typename Database, not exposed by the implementation class _Database: def OpenView(self, sql: str) -> _View: ... @@ -28,8 +28,8 @@ if sys.platform == "win32": def GetSummaryInformation(self, updateCount: int) -> _Summary: ... def Close(self) -> None: ... # Don't exist at runtime - __new__: None # type: ignore - __init__: None # type: ignore + __new__: None # type: ignore[assignment] + __init__: None # type: ignore[assignment] # Actual typename Record, not exposed by the implementation class _Record: def GetFieldCount(self) -> int: ... @@ -40,8 +40,8 @@ if sys.platform == "win32": def SetInteger(self, field: int, int: int) -> None: ... def ClearData(self) -> None: ... # Don't exist at runtime - __new__: None # type: ignore - __init__: None # type: ignore + __new__: None # type: ignore[assignment] + __init__: None # type: ignore[assignment] def UuidCreate() -> str: ... def FCICreate(cabname: str, files: list[str]) -> None: ... def OpenDatabase(name: str, flags: int) -> _Database: ... diff --git a/mypy/typeshed/stdlib/_operator.pyi b/mypy/typeshed/stdlib/_operator.pyi index bea4388618869..77a88d4fa141b 100644 --- a/mypy/typeshed/stdlib/_operator.pyi +++ b/mypy/typeshed/stdlib/_operator.pyi @@ -1,60 +1,141 @@ -# In reality the import is the other way around, but this way we can keep the operator stub in 2and3 -from operator import ( - abs as abs, - add as add, - and_ as and_, - attrgetter as attrgetter, - concat as concat, - contains as contains, - countOf as countOf, - delitem as delitem, - eq as eq, - floordiv as floordiv, - ge as ge, - getitem as getitem, - gt as gt, - iadd as iadd, - iand as iand, - iconcat as iconcat, - ifloordiv as ifloordiv, - ilshift as ilshift, - imatmul as imatmul, - imod as imod, - imul as imul, - index as index, - indexOf as indexOf, - inv as inv, - invert as invert, - ior as ior, - ipow as ipow, - irshift as irshift, - is_ as is_, - is_not as is_not, - isub as isub, - itemgetter as itemgetter, - itruediv as itruediv, - ixor as ixor, - le as le, - length_hint as length_hint, - lshift as lshift, - lt as lt, - matmul as matmul, - methodcaller as methodcaller, - mod as mod, - mul as mul, - ne as ne, - neg as neg, - not_ as not_, - or_ as or_, - pos as pos, - pow as pow, - rshift as rshift, - setitem as setitem, - sub as sub, - truediv as truediv, - truth as truth, - xor as xor, +import sys +from _typeshed import SupportsAnyComparison +from typing import ( + Any, + AnyStr, + Callable, + Container, + Generic, + Iterable, + Mapping, + MutableMapping, + MutableSequence, + Protocol, + Sequence, + SupportsAbs, + TypeVar, + overload, ) -from typing import AnyStr +from typing_extensions import ParamSpec, SupportsIndex, final + +_R = TypeVar("_R") +_T = TypeVar("_T") +_T_co = TypeVar("_T_co", covariant=True) +_K = TypeVar("_K") +_V = TypeVar("_V") +_P = ParamSpec("_P") + +class _SupportsInversion(Protocol[_T_co]): + def __invert__(self) -> _T_co: ... + +class _SupportsNeg(Protocol[_T_co]): + def __neg__(self) -> _T_co: ... + +class _SupportsPos(Protocol[_T_co]): + def __pos__(self) -> _T_co: ... + +# All four comparison functions must have the same signature, or we get false-positive errors +def lt(__a: SupportsAnyComparison, __b: SupportsAnyComparison) -> Any: ... +def le(__a: SupportsAnyComparison, __b: SupportsAnyComparison) -> Any: ... +def eq(__a: object, __b: object) -> Any: ... +def ne(__a: object, __b: object) -> Any: ... +def ge(__a: SupportsAnyComparison, __b: SupportsAnyComparison) -> Any: ... +def gt(__a: SupportsAnyComparison, __b: SupportsAnyComparison) -> Any: ... +def not_(__a: object) -> bool: ... +def truth(__a: object) -> bool: ... +def is_(__a: object, __b: object) -> bool: ... +def is_not(__a: object, __b: object) -> bool: ... +def abs(__a: SupportsAbs[_T]) -> _T: ... +def add(__a: Any, __b: Any) -> Any: ... +def and_(__a: Any, __b: Any) -> Any: ... +def floordiv(__a: Any, __b: Any) -> Any: ... +def index(__a: SupportsIndex) -> int: ... +def inv(__a: _SupportsInversion[_T_co]) -> _T_co: ... +def invert(__a: _SupportsInversion[_T_co]) -> _T_co: ... +def lshift(__a: Any, __b: Any) -> Any: ... +def mod(__a: Any, __b: Any) -> Any: ... +def mul(__a: Any, __b: Any) -> Any: ... +def matmul(__a: Any, __b: Any) -> Any: ... +def neg(__a: _SupportsNeg[_T_co]) -> _T_co: ... +def or_(__a: Any, __b: Any) -> Any: ... +def pos(__a: _SupportsPos[_T_co]) -> _T_co: ... +def pow(__a: Any, __b: Any) -> Any: ... +def rshift(__a: Any, __b: Any) -> Any: ... +def sub(__a: Any, __b: Any) -> Any: ... +def truediv(__a: Any, __b: Any) -> Any: ... +def xor(__a: Any, __b: Any) -> Any: ... +def concat(__a: Sequence[_T], __b: Sequence[_T]) -> Sequence[_T]: ... +def contains(__a: Container[object], __b: object) -> bool: ... +def countOf(__a: Iterable[object], __b: object) -> int: ... +@overload +def delitem(__a: MutableSequence[Any], __b: SupportsIndex) -> None: ... +@overload +def delitem(__a: MutableSequence[Any], __b: slice) -> None: ... +@overload +def delitem(__a: MutableMapping[_K, Any], __b: _K) -> None: ... +@overload +def getitem(__a: Sequence[_T], __b: SupportsIndex) -> _T: ... +@overload +def getitem(__a: Sequence[_T], __b: slice) -> Sequence[_T]: ... +@overload +def getitem(__a: Mapping[_K, _V], __b: _K) -> _V: ... +def indexOf(__a: Iterable[_T], __b: _T) -> int: ... +@overload +def setitem(__a: MutableSequence[_T], __b: SupportsIndex, __c: _T) -> None: ... +@overload +def setitem(__a: MutableSequence[_T], __b: slice, __c: Sequence[_T]) -> None: ... +@overload +def setitem(__a: MutableMapping[_K, _V], __b: _K, __c: _V) -> None: ... +def length_hint(__obj: object, __default: int = ...) -> int: ... +@final +class attrgetter(Generic[_T_co]): + @overload + def __new__(cls, attr: str) -> attrgetter[Any]: ... + @overload + def __new__(cls, attr: str, __attr2: str) -> attrgetter[tuple[Any, Any]]: ... + @overload + def __new__(cls, attr: str, __attr2: str, __attr3: str) -> attrgetter[tuple[Any, Any, Any]]: ... + @overload + def __new__(cls, attr: str, __attr2: str, __attr3: str, __attr4: str) -> attrgetter[tuple[Any, Any, Any, Any]]: ... + @overload + def __new__(cls, attr: str, *attrs: str) -> attrgetter[tuple[Any, ...]]: ... + def __call__(self, obj: Any) -> _T_co: ... + +@final +class itemgetter(Generic[_T_co]): + @overload + def __new__(cls, item: Any) -> itemgetter[Any]: ... + @overload + def __new__(cls, item: Any, __item2: Any) -> itemgetter[tuple[Any, Any]]: ... + @overload + def __new__(cls, item: Any, __item2: Any, __item3: Any) -> itemgetter[tuple[Any, Any, Any]]: ... + @overload + def __new__(cls, item: Any, __item2: Any, __item3: Any, __item4: Any) -> itemgetter[tuple[Any, Any, Any, Any]]: ... + @overload + def __new__(cls, item: Any, *items: Any) -> itemgetter[tuple[Any, ...]]: ... + def __call__(self, obj: Any) -> _T_co: ... + +@final +class methodcaller: + def __init__(self, __name: str, *args: Any, **kwargs: Any) -> None: ... + def __call__(self, obj: Any) -> Any: ... + +def iadd(__a: Any, __b: Any) -> Any: ... +def iand(__a: Any, __b: Any) -> Any: ... +def iconcat(__a: Any, __b: Any) -> Any: ... +def ifloordiv(__a: Any, __b: Any) -> Any: ... +def ilshift(__a: Any, __b: Any) -> Any: ... +def imod(__a: Any, __b: Any) -> Any: ... +def imul(__a: Any, __b: Any) -> Any: ... +def imatmul(__a: Any, __b: Any) -> Any: ... +def ior(__a: Any, __b: Any) -> Any: ... +def ipow(__a: Any, __b: Any) -> Any: ... +def irshift(__a: Any, __b: Any) -> Any: ... +def isub(__a: Any, __b: Any) -> Any: ... +def itruediv(__a: Any, __b: Any) -> Any: ... +def ixor(__a: Any, __b: Any) -> Any: ... + +if sys.version_info >= (3, 11): + def call(__obj: Callable[_P, _R], *args: _P.args, **kwargs: _P.kwargs) -> _R: ... def _compare_digest(__a: AnyStr, __b: AnyStr) -> bool: ... diff --git a/mypy/typeshed/stdlib/_osx_support.pyi b/mypy/typeshed/stdlib/_osx_support.pyi index ce1fffc00e8cd..ffb25d5a2c0ed 100644 --- a/mypy/typeshed/stdlib/_osx_support.pyi +++ b/mypy/typeshed/stdlib/_osx_support.pyi @@ -1,4 +1,5 @@ -from typing import Iterable, Sequence, Tuple, TypeVar +import sys +from typing import Iterable, Sequence, TypeVar _T = TypeVar("_T") _K = TypeVar("_K") @@ -6,12 +7,18 @@ _V = TypeVar("_V") __all__: list[str] -_UNIVERSAL_CONFIG_VARS: Tuple[str, ...] # undocumented -_COMPILER_CONFIG_VARS: Tuple[str, ...] # undocumented +_UNIVERSAL_CONFIG_VARS: tuple[str, ...] # undocumented +_COMPILER_CONFIG_VARS: tuple[str, ...] # undocumented _INITPRE: str # undocumented def _find_executable(executable: str, path: str | None = ...) -> str | None: ... # undocumented -def _read_output(commandstring: str) -> str | None: ... # undocumented + +if sys.version_info >= (3, 8): + def _read_output(commandstring: str, capture_stderr: bool = ...) -> str | None: ... # undocumented + +else: + def _read_output(commandstring: str) -> str | None: ... # undocumented + def _find_build_tool(toolname: str) -> str: ... # undocumented _SYSTEM_VERSION: str | None # undocumented diff --git a/mypy/typeshed/stdlib/_posixsubprocess.pyi b/mypy/typeshed/stdlib/_posixsubprocess.pyi index 0eae723e7a670..5481100cacfc9 100644 --- a/mypy/typeshed/stdlib/_posixsubprocess.pyi +++ b/mypy/typeshed/stdlib/_posixsubprocess.pyi @@ -1,24 +1,24 @@ -# NOTE: These are incomplete! - +import sys from typing import Callable, Sequence -def cloexec_pipe() -> tuple[int, int]: ... -def fork_exec( - args: Sequence[str], - executable_list: Sequence[bytes], - close_fds: bool, - fds_to_keep: Sequence[int], - cwd: str, - env_list: Sequence[bytes], - p2cread: int, - p2cwrite: int, - c2pred: int, - c2pwrite: int, - errread: int, - errwrite: int, - errpipe_read: int, - errpipe_write: int, - restore_signals: int, - start_new_session: int, - preexec_fn: Callable[[], None], -) -> int: ... +if sys.platform != "win32": + def cloexec_pipe() -> tuple[int, int]: ... + def fork_exec( + args: Sequence[str], + executable_list: Sequence[bytes], + close_fds: bool, + fds_to_keep: Sequence[int], + cwd: str, + env_list: Sequence[bytes], + p2cread: int, + p2cwrite: int, + c2pred: int, + c2pwrite: int, + errread: int, + errwrite: int, + errpipe_read: int, + errpipe_write: int, + restore_signals: int, + start_new_session: int, + preexec_fn: Callable[[], None], + ) -> int: ... diff --git a/mypy/typeshed/stdlib/_py_abc.pyi b/mypy/typeshed/stdlib/_py_abc.pyi index 8d7938918271a..697a7f17111a2 100644 --- a/mypy/typeshed/stdlib/_py_abc.pyi +++ b/mypy/typeshed/stdlib/_py_abc.pyi @@ -1,4 +1,4 @@ -from typing import Any, Tuple, Type, TypeVar +from typing import Any, Type, TypeVar _T = TypeVar("_T") @@ -6,5 +6,5 @@ _T = TypeVar("_T") def get_cache_token() -> object: ... class ABCMeta(type): - def __new__(__mcls, __name: str, __bases: Tuple[Type[Any], ...], __namespace: dict[str, Any]) -> ABCMeta: ... + def __new__(__mcls, __name: str, __bases: tuple[Type[Any], ...], __namespace: dict[str, Any]) -> ABCMeta: ... def register(cls, subclass: Type[_T]) -> Type[_T]: ... diff --git a/mypy/typeshed/stdlib/_random.pyi b/mypy/typeshed/stdlib/_random.pyi index fa80c6d981449..9aff4b3cb0260 100644 --- a/mypy/typeshed/stdlib/_random.pyi +++ b/mypy/typeshed/stdlib/_random.pyi @@ -1,9 +1,7 @@ -from typing import Tuple - # Actually Tuple[(int,) * 625] -_State = Tuple[int, ...] +_State = tuple[int, ...] -class Random(object): +class Random: def __init__(self, seed: object = ...) -> None: ... def seed(self, __n: object = ...) -> None: ... def getstate(self) -> _State: ... diff --git a/mypy/typeshed/stdlib/_socket.pyi b/mypy/typeshed/stdlib/_socket.pyi index 846f64d5a433d..d7d7f73ea37d1 100644 --- a/mypy/typeshed/stdlib/_socket.pyi +++ b/mypy/typeshed/stdlib/_socket.pyi @@ -1,7 +1,7 @@ import sys from _typeshed import ReadableBuffer, WriteableBuffer from collections.abc import Iterable -from typing import Any, SupportsInt, Tuple, Union, overload +from typing import Any, SupportsInt, Union, overload if sys.version_info >= (3, 8): from typing import SupportsIndex @@ -10,12 +10,12 @@ if sys.version_info >= (3, 8): else: _FD = SupportsInt -_CMSG = Tuple[int, int, bytes] -_CMSGArg = Tuple[int, int, ReadableBuffer] +_CMSG = tuple[int, int, bytes] +_CMSGArg = tuple[int, int, ReadableBuffer] # Addresses can be either tuples of varying lengths (AF_INET, AF_INET6, # AF_NETLINK, AF_TIPC) or strings (AF_UNIX). -_Address = Union[Tuple[Any, ...], str] +_Address = Union[tuple[Any, ...], str] _RetAddress = Any # TODO Most methods allow bytes as address objects @@ -527,6 +527,8 @@ class socket: family: int type: int proto: int + @property + def timeout(self) -> float | None: ... def __init__(self, family: int = ..., type: int = ..., proto: int = ..., fileno: _FD | None = ...) -> None: ... def bind(self, __address: _Address | bytes) -> None: ... def close(self) -> None: ... diff --git a/mypy/typeshed/stdlib/_stat.pyi b/mypy/typeshed/stdlib/_stat.pyi index 634f7da025632..83d832e4dd8e7 100644 --- a/mypy/typeshed/stdlib/_stat.pyi +++ b/mypy/typeshed/stdlib/_stat.pyi @@ -1,54 +1,68 @@ -SF_APPEND: int -SF_ARCHIVED: int -SF_IMMUTABLE: int -SF_NOUNLINK: int -SF_SNAPSHOT: int -ST_ATIME: int -ST_CTIME: int -ST_DEV: int -ST_GID: int -ST_INO: int -ST_MODE: int -ST_MTIME: int -ST_NLINK: int -ST_SIZE: int -ST_UID: int -S_ENFMT: int -S_IEXEC: int -S_IFBLK: int -S_IFCHR: int -S_IFDIR: int +import sys +from typing_extensions import Literal + +SF_APPEND: Literal[0x00040000] +SF_ARCHIVED: Literal[0x00010000] +SF_IMMUTABLE: Literal[0x00020000] +SF_NOUNLINK: Literal[0x00100000] +SF_SNAPSHOT: Literal[0x00200000] + +ST_MODE: Literal[0] +ST_INO: Literal[1] +ST_DEV: Literal[2] +ST_NLINK: Literal[3] +ST_UID: Literal[4] +ST_GID: Literal[5] +ST_SIZE: Literal[6] +ST_ATIME: Literal[7] +ST_MTIME: Literal[8] +ST_CTIME: Literal[9] + +S_IFIFO: Literal[0o010000] +S_IFLNK: Literal[0o120000] +S_IFREG: Literal[0o100000] +S_IFSOCK: Literal[0o140000] +S_IFBLK: Literal[0o060000] +S_IFCHR: Literal[0o020000] +S_IFDIR: Literal[0o040000] + +# These are 0 on systems that don't support the specific kind of file. +# Example: Linux doesn't support door files, so S_IFDOOR is 0 on linux. S_IFDOOR: int -S_IFIFO: int -S_IFLNK: int S_IFPORT: int -S_IFREG: int -S_IFSOCK: int S_IFWHT: int -S_IREAD: int -S_IRGRP: int -S_IROTH: int -S_IRUSR: int -S_IRWXG: int -S_IRWXO: int -S_IRWXU: int -S_ISGID: int -S_ISUID: int -S_ISVTX: int -S_IWGRP: int -S_IWOTH: int -S_IWRITE: int -S_IWUSR: int -S_IXGRP: int -S_IXOTH: int -S_IXUSR: int -UF_APPEND: int -UF_COMPRESSED: int -UF_HIDDEN: int -UF_IMMUTABLE: int -UF_NODUMP: int -UF_NOUNLINK: int -UF_OPAQUE: int + +S_ISUID: Literal[0o4000] +S_ISGID: Literal[0o2000] +S_ISVTX: Literal[0o1000] + +S_IRWXU: Literal[0o0700] +S_IRUSR: Literal[0o0400] +S_IWUSR: Literal[0o0200] +S_IXUSR: Literal[0o0100] + +S_IRWXG: Literal[0o0070] +S_IRGRP: Literal[0o0040] +S_IWGRP: Literal[0o0020] +S_IXGRP: Literal[0o0010] + +S_IRWXO: Literal[0o0007] +S_IROTH: Literal[0o0004] +S_IWOTH: Literal[0o0002] +S_IXOTH: Literal[0o0001] + +S_ENFMT: Literal[0o2000] +S_IREAD: Literal[0o0400] +S_IWRITE: Literal[0o0200] +S_IEXEC: Literal[0o0100] + +UF_APPEND: Literal[0x00000004] +UF_COMPRESSED: Literal[0x00000020] # OS X 10.6+ only +UF_HIDDEN: Literal[0x00008000] # OX X 10.5+ only +UF_IMMUTABLE: Literal[0x00000002] +UF_NODUMP: Literal[0x00000001] +UF_NOUNLINK: Literal[0x00000010] +UF_OPAQUE: Literal[0x00000008] def S_IMODE(mode: int) -> int: ... def S_IFMT(mode: int) -> int: ... @@ -63,3 +77,27 @@ def S_ISREG(mode: int) -> bool: ... def S_ISSOCK(mode: int) -> bool: ... def S_ISWHT(mode: int) -> bool: ... def filemode(mode: int) -> str: ... + +if sys.platform == "win32" and sys.version_info >= (3, 8): + IO_REPARSE_TAG_SYMLINK: int + IO_REPARSE_TAG_MOUNT_POINT: int + IO_REPARSE_TAG_APPEXECLINK: int + +if sys.platform == "win32": + FILE_ATTRIBUTE_ARCHIVE: Literal[32] + FILE_ATTRIBUTE_COMPRESSED: Literal[2048] + FILE_ATTRIBUTE_DEVICE: Literal[64] + FILE_ATTRIBUTE_DIRECTORY: Literal[16] + FILE_ATTRIBUTE_ENCRYPTED: Literal[16384] + FILE_ATTRIBUTE_HIDDEN: Literal[2] + FILE_ATTRIBUTE_INTEGRITY_STREAM: Literal[32768] + FILE_ATTRIBUTE_NORMAL: Literal[128] + FILE_ATTRIBUTE_NOT_CONTENT_INDEXED: Literal[8192] + FILE_ATTRIBUTE_NO_SCRUB_DATA: Literal[131072] + FILE_ATTRIBUTE_OFFLINE: Literal[4096] + FILE_ATTRIBUTE_READONLY: Literal[1] + FILE_ATTRIBUTE_REPARSE_POINT: Literal[1024] + FILE_ATTRIBUTE_SPARSE_FILE: Literal[512] + FILE_ATTRIBUTE_SYSTEM: Literal[4] + FILE_ATTRIBUTE_TEMPORARY: Literal[256] + FILE_ATTRIBUTE_VIRTUAL: Literal[65536] diff --git a/mypy/typeshed/stdlib/_thread.pyi b/mypy/typeshed/stdlib/_thread.pyi index 2f4252981b68d..03318a0b2d413 100644 --- a/mypy/typeshed/stdlib/_thread.pyi +++ b/mypy/typeshed/stdlib/_thread.pyi @@ -1,7 +1,8 @@ import sys +from _typeshed import structseq from threading import Thread from types import TracebackType -from typing import Any, Callable, NoReturn, Optional, Tuple, Type +from typing import Any, Callable, NoReturn, Optional, Type from typing_extensions import final error = RuntimeError @@ -20,7 +21,7 @@ class LockType: self, type: Type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None ) -> None: ... -def start_new_thread(function: Callable[..., Any], args: Tuple[Any, ...], kwargs: dict[str, Any] = ...) -> int: ... +def start_new_thread(function: Callable[..., Any], args: tuple[Any, ...], kwargs: dict[str, Any] = ...) -> int: ... def interrupt_main() -> None: ... def exit() -> NoReturn: ... def allocate_lock() -> LockType: ... @@ -32,7 +33,9 @@ TIMEOUT_MAX: float if sys.version_info >= (3, 8): def get_native_id() -> int: ... # only available on some platforms @final - class _ExceptHookArgs(Tuple[Type[BaseException], Optional[BaseException], Optional[TracebackType], Optional[Thread]]): + class _ExceptHookArgs( + structseq[Any], tuple[Type[BaseException], Optional[BaseException], Optional[TracebackType], Optional[Thread]] + ): @property def exc_type(self) -> Type[BaseException]: ... @property diff --git a/mypy/typeshed/stdlib/_threading_local.pyi b/mypy/typeshed/stdlib/_threading_local.pyi index bab69a7c2e7dd..9e1e3f48d2868 100644 --- a/mypy/typeshed/stdlib/_threading_local.pyi +++ b/mypy/typeshed/stdlib/_threading_local.pyi @@ -1,7 +1,7 @@ -from typing import Any, Dict +from typing import Any from weakref import ReferenceType -localdict = Dict[Any, Any] +localdict = dict[Any, Any] class _localimpl: key: str diff --git a/mypy/typeshed/stdlib/_tkinter.pyi b/mypy/typeshed/stdlib/_tkinter.pyi index e97edf5b4fae6..b6c8ccd1c3807 100644 --- a/mypy/typeshed/stdlib/_tkinter.pyi +++ b/mypy/typeshed/stdlib/_tkinter.pyi @@ -1,3 +1,4 @@ +import sys from typing import Any from typing_extensions import Literal, final @@ -68,7 +69,8 @@ class TkappType: quit: Any record: Any setvar: Any - split: Any + if sys.version_info < (3, 11): + split: Any splitlist: Any unsetvar: Any wantobjects: Any diff --git a/mypy/typeshed/stdlib/_typeshed/__init__.pyi b/mypy/typeshed/stdlib/_typeshed/__init__.pyi index 0d4c42afc285e..a7f8c51471039 100644 --- a/mypy/typeshed/stdlib/_typeshed/__init__.pyi +++ b/mypy/typeshed/stdlib/_typeshed/__init__.pyi @@ -7,7 +7,7 @@ import ctypes import mmap import sys from os import PathLike -from typing import AbstractSet, Any, Awaitable, Container, Iterable, Protocol, TypeVar, Union +from typing import AbstractSet, Any, Awaitable, ClassVar, Container, Generic, Iterable, Protocol, Type, TypeVar, Union from typing_extensions import Literal, final _KT = TypeVar("_KT") @@ -35,16 +35,6 @@ class SupportsNext(Protocol[_T_co]): class SupportsAnext(Protocol[_T_co]): def __anext__(self) -> Awaitable[_T_co]: ... -class SupportsLessThan(Protocol): - def __lt__(self, __other: Any) -> bool: ... - -SupportsLessThanT = TypeVar("SupportsLessThanT", bound=SupportsLessThan) # noqa: Y001 - -class SupportsGreaterThan(Protocol): - def __gt__(self, __other: Any) -> bool: ... - -SupportsGreaterThanT = TypeVar("SupportsGreaterThanT", bound=SupportsGreaterThan) # noqa: Y001 - # Comparison protocols class SupportsDunderLT(Protocol): @@ -209,3 +199,20 @@ else: @final class NoneType: def __bool__(self) -> Literal[False]: ... + +# This is an internal CPython type that is like, but subtly different from, a NamedTuple +# Subclasses of this type are found in multiple modules. +# In typeshed, `structseq` is only ever used as a mixin in combination with a fixed-length `Tuple` +# See discussion at #6546 & #6560 +# `structseq` classes are unsubclassable, so are all decorated with `@final`. +class structseq(Generic[_T_co]): + n_fields: ClassVar[int] + n_unnamed_fields: ClassVar[int] + n_sequence_fields: ClassVar[int] + # The first parameter will generally only take an iterable of a specific length. + # E.g. `os.uname_result` takes any iterable of length exactly 5. + # + # The second parameter will accept a dict of any kind without raising an exception, + # but only has any meaning if you supply it a dict where the keys are strings. + # https://github.com/python/typeshed/pull/6560#discussion_r767149830 + def __new__(cls: Type[_T], sequence: Iterable[_T_co], dict: dict[str, Any] = ...) -> _T: ... diff --git a/mypy/typeshed/stdlib/_typeshed/dbapi.pyi b/mypy/typeshed/stdlib/_typeshed/dbapi.pyi new file mode 100644 index 0000000000000..eee4fc03874e5 --- /dev/null +++ b/mypy/typeshed/stdlib/_typeshed/dbapi.pyi @@ -0,0 +1,36 @@ +# PEP 249 Database API 2.0 Types +# https://www.python.org/dev/peps/pep-0249/ + +from collections.abc import Mapping, Sequence +from typing import Any, Protocol + +DBAPITypeCode = Any | None +# Strictly speaking, this should be a Sequence, but the type system does +# not support fixed-length sequences. +DBAPIColumnDescription = tuple[str, DBAPITypeCode, int | None, int | None, int | None, int | None, bool | None] + +class DBAPIConnection(Protocol): + def close(self) -> object: ... + def commit(self) -> object: ... + # optional: + # def rollback(self) -> Any: ... + def cursor(self) -> DBAPICursor: ... + +class DBAPICursor(Protocol): + @property + def description(self) -> Sequence[DBAPIColumnDescription] | None: ... + @property + def rowcount(self) -> int: ... + # optional: + # def callproc(self, __procname: str, __parameters: Sequence[Any] = ...) -> Sequence[Any]: ... + def close(self) -> object: ... + def execute(self, __operation: str, __parameters: Sequence[Any] | Mapping[str, Any] = ...) -> object: ... + def executemany(self, __operation: str, __seq_of_parameters: Sequence[Sequence[Any]]) -> object: ... + def fetchone(self) -> Sequence[Any] | None: ... + def fetchmany(self, __size: int = ...) -> Sequence[Sequence[Any]]: ... + def fetchall(self) -> Sequence[Sequence[Any]]: ... + # optional: + # def nextset(self) -> None | Literal[True]: ... + arraysize: int + def setinputsizes(self, __sizes: Sequence[DBAPITypeCode | int | None]) -> object: ... + def setoutputsize(self, __size: int, __column: int = ...) -> object: ... diff --git a/mypy/typeshed/stdlib/_typeshed/wsgi.pyi b/mypy/typeshed/stdlib/_typeshed/wsgi.pyi index 658b0fed2c6c7..031d1472b6c5f 100644 --- a/mypy/typeshed/stdlib/_typeshed/wsgi.pyi +++ b/mypy/typeshed/stdlib/_typeshed/wsgi.pyi @@ -3,7 +3,7 @@ # See the README.md file in this directory for more information. from sys import _OptExcInfo -from typing import Any, Callable, Dict, Iterable, Protocol +from typing import Any, Callable, Iterable, Protocol # stable class StartResponse(Protocol): @@ -11,7 +11,7 @@ class StartResponse(Protocol): self, status: str, headers: list[tuple[str, str]], exc_info: _OptExcInfo | None = ... ) -> Callable[[bytes], Any]: ... -WSGIEnvironment = Dict[str, Any] # stable +WSGIEnvironment = dict[str, Any] # stable WSGIApplication = Callable[[WSGIEnvironment, StartResponse], Iterable[bytes]] # stable # WSGI input streams per PEP 3333, stable diff --git a/mypy/typeshed/stdlib/_typeshed/xml.pyi b/mypy/typeshed/stdlib/_typeshed/xml.pyi index d53b743af2d37..231c2b86e9129 100644 --- a/mypy/typeshed/stdlib/_typeshed/xml.pyi +++ b/mypy/typeshed/stdlib/_typeshed/xml.pyi @@ -1,7 +1,6 @@ # See the README.md file in this directory for more information. -from typing import Any -from typing_extensions import Protocol +from typing import Any, Protocol # As defined https://docs.python.org/3/library/xml.dom.html#domimplementation-objects class DOMImplementation(Protocol): diff --git a/mypy/typeshed/stdlib/_weakref.pyi b/mypy/typeshed/stdlib/_weakref.pyi index dcaef25b3f0f6..00dc2d5114b8f 100644 --- a/mypy/typeshed/stdlib/_weakref.pyi +++ b/mypy/typeshed/stdlib/_weakref.pyi @@ -11,6 +11,7 @@ _T = TypeVar("_T") @final class CallableProxyType(Generic[_C]): # "weakcallableproxy" def __getattr__(self, attr: str) -> Any: ... + __call__: _C @final class ProxyType(Generic[_T]): # "weakproxy" diff --git a/mypy/typeshed/stdlib/_winapi.pyi b/mypy/typeshed/stdlib/_winapi.pyi index 83089d485c171..eba236597840b 100644 --- a/mypy/typeshed/stdlib/_winapi.pyi +++ b/mypy/typeshed/stdlib/_winapi.pyi @@ -2,133 +2,194 @@ import sys from typing import Any, NoReturn, Sequence, overload from typing_extensions import Literal, final -CREATE_NEW_CONSOLE: int -CREATE_NEW_PROCESS_GROUP: int -DUPLICATE_CLOSE_SOURCE: int -DUPLICATE_SAME_ACCESS: int -ERROR_ALREADY_EXISTS: int -ERROR_BROKEN_PIPE: int -ERROR_IO_PENDING: int -ERROR_MORE_DATA: int -ERROR_NETNAME_DELETED: int -ERROR_NO_DATA: int -ERROR_NO_SYSTEM_RESOURCES: int -ERROR_OPERATION_ABORTED: int -ERROR_PIPE_BUSY: int -ERROR_PIPE_CONNECTED: int -ERROR_SEM_TIMEOUT: int -FILE_FLAG_FIRST_PIPE_INSTANCE: int -FILE_FLAG_OVERLAPPED: int -FILE_GENERIC_READ: int -FILE_GENERIC_WRITE: int -GENERIC_READ: int -GENERIC_WRITE: int -INFINITE: int -NMPWAIT_WAIT_FOREVER: int -NULL: int -OPEN_EXISTING: int -PIPE_ACCESS_DUPLEX: int -PIPE_ACCESS_INBOUND: int -PIPE_READMODE_MESSAGE: int -PIPE_TYPE_MESSAGE: int -PIPE_UNLIMITED_INSTANCES: int -PIPE_WAIT: int -PROCESS_ALL_ACCESS: int -PROCESS_DUP_HANDLE: int -STARTF_USESHOWWINDOW: int -STARTF_USESTDHANDLES: int -STD_ERROR_HANDLE: int -STD_INPUT_HANDLE: int -STD_OUTPUT_HANDLE: int -STILL_ACTIVE: int -SW_HIDE: int -WAIT_ABANDONED_0: int -WAIT_OBJECT_0: int -WAIT_TIMEOUT: int +if sys.platform == "win32": + if sys.version_info >= (3, 7): + ABOVE_NORMAL_PRIORITY_CLASS: Literal[32768] + BELOW_NORMAL_PRIORITY_CLASS: Literal[16384] + CREATE_BREAKAWAY_FROM_JOB: Literal[16777216] + CREATE_DEFAULT_ERROR_MODE: Literal[67108864] + CREATE_NO_WINDOW: Literal[134217728] + CREATE_NEW_CONSOLE: Literal[16] + CREATE_NEW_PROCESS_GROUP: Literal[512] + if sys.version_info >= (3, 7): + DETACHED_PROCESS: Literal[8] + DUPLICATE_CLOSE_SOURCE: Literal[1] + DUPLICATE_SAME_ACCESS: Literal[2] -def CloseHandle(__handle: int) -> None: ... -@overload -def ConnectNamedPipe(handle: int, overlapped: Literal[True]) -> Overlapped: ... -@overload -def ConnectNamedPipe(handle: int, overlapped: Literal[False] = ...) -> None: ... -@overload -def ConnectNamedPipe(handle: int, overlapped: bool) -> Overlapped | None: ... -def CreateFile( - __file_name: str, - __desired_access: int, - __share_mode: int, - __security_attributes: int, - __creation_disposition: int, - __flags_and_attributes: int, - __template_file: int, -) -> int: ... -def CreateJunction(__src_path: str, __dst_path: str) -> None: ... -def CreateNamedPipe( - __name: str, - __open_mode: int, - __pipe_mode: int, - __max_instances: int, - __out_buffer_size: int, - __in_buffer_size: int, - __default_timeout: int, - __security_attributes: int, -) -> int: ... -def CreatePipe(__pipe_attrs: Any, __size: int) -> tuple[int, int]: ... -def CreateProcess( - __application_name: str | None, - __command_line: str | None, - __proc_attrs: Any, - __thread_attrs: Any, - __inherit_handles: bool, - __creation_flags: int, - __env_mapping: dict[str, str], - __current_directory: str | None, - __startup_info: Any, -) -> tuple[int, int, int, int]: ... -def DuplicateHandle( - __source_process_handle: int, - __source_handle: int, - __target_process_handle: int, - __desired_access: int, - __inherit_handle: bool, - __options: int = ..., -) -> int: ... -def ExitProcess(__ExitCode: int) -> NoReturn: ... + ERROR_ALREADY_EXISTS: Literal[183] + ERROR_BROKEN_PIPE: Literal[109] + ERROR_IO_PENDING: Literal[997] + ERROR_MORE_DATA: Literal[234] + ERROR_NETNAME_DELETED: Literal[64] + ERROR_NO_DATA: Literal[232] + ERROR_NO_SYSTEM_RESOURCES: Literal[1450] + ERROR_OPERATION_ABORTED: Literal[995] + ERROR_PIPE_BUSY: Literal[231] + ERROR_PIPE_CONNECTED: Literal[535] + ERROR_SEM_TIMEOUT: Literal[121] -if sys.version_info >= (3, 7): - def GetACP() -> int: ... - def GetFileType(handle: int) -> int: ... + FILE_FLAG_FIRST_PIPE_INSTANCE: Literal[524288] + FILE_FLAG_OVERLAPPED: Literal[1073741824] + FILE_GENERIC_READ: Literal[1179785] + FILE_GENERIC_WRITE: Literal[1179926] + if sys.version_info >= (3, 8): + FILE_MAP_ALL_ACCESS: Literal[983071] + FILE_MAP_COPY: Literal[1] + FILE_MAP_EXECUTE: Literal[32] + FILE_MAP_READ: Literal[4] + FILE_MAP_WRITE: Literal[2] + if sys.version_info >= (3, 7): + FILE_TYPE_CHAR: Literal[2] + FILE_TYPE_DISK: Literal[1] + FILE_TYPE_PIPE: Literal[3] + FILE_TYPE_REMOTE: Literal[32768] + FILE_TYPE_UNKNOWN: Literal[0] -def GetCurrentProcess() -> int: ... -def GetExitCodeProcess(__process: int) -> int: ... -def GetLastError() -> int: ... -def GetModuleFileName(__module_handle: int) -> str: ... -def GetStdHandle(__std_handle: int) -> int: ... -def GetVersion() -> int: ... -def OpenProcess(__desired_access: int, __inherit_handle: bool, __process_id: int) -> int: ... -def PeekNamedPipe(__handle: int, __size: int = ...) -> tuple[int, int] | tuple[bytes, int, int]: ... -@overload -def ReadFile(handle: int, size: int, overlapped: Literal[True]) -> tuple[Overlapped, int]: ... -@overload -def ReadFile(handle: int, size: int, overlapped: Literal[False] = ...) -> tuple[bytes, int]: ... -@overload -def ReadFile(handle: int, size: int, overlapped: int | bool) -> tuple[Any, int]: ... -def SetNamedPipeHandleState( - __named_pipe: int, __mode: int | None, __max_collection_count: int | None, __collect_data_timeout: int | None -) -> None: ... -def TerminateProcess(__handle: int, __exit_code: int) -> None: ... -def WaitForMultipleObjects(__handle_seq: Sequence[int], __wait_flag: bool, __milliseconds: int = ...) -> int: ... -def WaitForSingleObject(__handle: int, __milliseconds: int) -> int: ... -def WaitNamedPipe(__name: str, __timeout: int) -> None: ... -@overload -def WriteFile(handle: int, buffer: bytes, overlapped: Literal[True]) -> tuple[Overlapped, int]: ... -@overload -def WriteFile(handle: int, buffer: bytes, overlapped: Literal[False] = ...) -> tuple[int, int]: ... -@overload -def WriteFile(handle: int, buffer: bytes, overlapped: int | bool) -> tuple[Any, int]: ... -@final -class Overlapped: - event: int - def GetOverlappedResult(self, __wait: bool) -> tuple[int, int]: ... - def cancel(self) -> None: ... - def getbuffer(self) -> bytes | None: ... + GENERIC_READ: Literal[2147483648] + GENERIC_WRITE: Literal[1073741824] + if sys.version_info >= (3, 7): + HIGH_PRIORITY_CLASS: Literal[128] + INFINITE: Literal[4294967295] + if sys.version_info >= (3, 8): + INVALID_HANDLE_VALUE: int # very large number + if sys.version_info >= (3, 7): + IDLE_PRIORITY_CLASS: Literal[64] + NORMAL_PRIORITY_CLASS: Literal[32] + REALTIME_PRIORITY_CLASS: Literal[256] + NMPWAIT_WAIT_FOREVER: Literal[4294967295] + + if sys.version_info >= (3, 8): + MEM_COMMIT: Literal[4096] + MEM_FREE: Literal[65536] + MEM_IMAGE: Literal[16777216] + MEM_MAPPED: Literal[262144] + MEM_PRIVATE: Literal[131072] + MEM_RESERVE: Literal[8192] + + NULL: Literal[0] + OPEN_EXISTING: Literal[3] + + PIPE_ACCESS_DUPLEX: Literal[3] + PIPE_ACCESS_INBOUND: Literal[1] + PIPE_READMODE_MESSAGE: Literal[2] + PIPE_TYPE_MESSAGE: Literal[4] + PIPE_UNLIMITED_INSTANCES: Literal[255] + PIPE_WAIT: Literal[0] + if sys.version_info >= (3, 8): + PAGE_EXECUTE: Literal[16] + PAGE_EXECUTE_READ: Literal[32] + PAGE_EXECUTE_READWRITE: Literal[64] + PAGE_EXECUTE_WRITECOPY: Literal[128] + PAGE_GUARD: Literal[256] + PAGE_NOACCESS: Literal[1] + PAGE_NOCACHE: Literal[512] + PAGE_READONLY: Literal[2] + PAGE_READWRITE: Literal[4] + PAGE_WRITECOMBINE: Literal[1024] + PAGE_WRITECOPY: Literal[8] + + PROCESS_ALL_ACCESS: Literal[2097151] + PROCESS_DUP_HANDLE: Literal[64] + if sys.version_info >= (3, 8): + SEC_COMMIT: Literal[134217728] + SEC_IMAGE: Literal[16777216] + SEC_LARGE_PAGES: Literal[2147483648] + SEC_NOCACHE: Literal[268435456] + SEC_RESERVE: Literal[67108864] + SEC_WRITECOMBINE: Literal[1073741824] + STARTF_USESHOWWINDOW: Literal[1] + STARTF_USESTDHANDLES: Literal[256] + STD_ERROR_HANDLE: Literal[4294967284] + STD_INPUT_HANDLE: Literal[4294967286] + STD_OUTPUT_HANDLE: Literal[4294967285] + STILL_ACTIVE: Literal[259] + SW_HIDE: Literal[0] + if sys.version_info >= (3, 8): + SYNCHRONIZE: Literal[1048576] + WAIT_ABANDONED_0: Literal[128] + WAIT_OBJECT_0: Literal[0] + WAIT_TIMEOUT: Literal[258] + def CloseHandle(__handle: int) -> None: ... + @overload + def ConnectNamedPipe(handle: int, overlapped: Literal[True]) -> Overlapped: ... + @overload + def ConnectNamedPipe(handle: int, overlapped: Literal[False] = ...) -> None: ... + @overload + def ConnectNamedPipe(handle: int, overlapped: bool) -> Overlapped | None: ... + def CreateFile( + __file_name: str, + __desired_access: int, + __share_mode: int, + __security_attributes: int, + __creation_disposition: int, + __flags_and_attributes: int, + __template_file: int, + ) -> int: ... + def CreateJunction(__src_path: str, __dst_path: str) -> None: ... + def CreateNamedPipe( + __name: str, + __open_mode: int, + __pipe_mode: int, + __max_instances: int, + __out_buffer_size: int, + __in_buffer_size: int, + __default_timeout: int, + __security_attributes: int, + ) -> int: ... + def CreatePipe(__pipe_attrs: Any, __size: int) -> tuple[int, int]: ... + def CreateProcess( + __application_name: str | None, + __command_line: str | None, + __proc_attrs: Any, + __thread_attrs: Any, + __inherit_handles: bool, + __creation_flags: int, + __env_mapping: dict[str, str], + __current_directory: str | None, + __startup_info: Any, + ) -> tuple[int, int, int, int]: ... + def DuplicateHandle( + __source_process_handle: int, + __source_handle: int, + __target_process_handle: int, + __desired_access: int, + __inherit_handle: bool, + __options: int = ..., + ) -> int: ... + def ExitProcess(__ExitCode: int) -> NoReturn: ... + if sys.version_info >= (3, 7): + def GetACP() -> int: ... + def GetFileType(handle: int) -> int: ... + def GetCurrentProcess() -> int: ... + def GetExitCodeProcess(__process: int) -> int: ... + def GetLastError() -> int: ... + def GetModuleFileName(__module_handle: int) -> str: ... + def GetStdHandle(__std_handle: int) -> int: ... + def GetVersion() -> int: ... + def OpenProcess(__desired_access: int, __inherit_handle: bool, __process_id: int) -> int: ... + def PeekNamedPipe(__handle: int, __size: int = ...) -> tuple[int, int] | tuple[bytes, int, int]: ... + @overload + def ReadFile(handle: int, size: int, overlapped: Literal[True]) -> tuple[Overlapped, int]: ... + @overload + def ReadFile(handle: int, size: int, overlapped: Literal[False] = ...) -> tuple[bytes, int]: ... + @overload + def ReadFile(handle: int, size: int, overlapped: int | bool) -> tuple[Any, int]: ... + def SetNamedPipeHandleState( + __named_pipe: int, __mode: int | None, __max_collection_count: int | None, __collect_data_timeout: int | None + ) -> None: ... + def TerminateProcess(__handle: int, __exit_code: int) -> None: ... + def WaitForMultipleObjects(__handle_seq: Sequence[int], __wait_flag: bool, __milliseconds: int = ...) -> int: ... + def WaitForSingleObject(__handle: int, __milliseconds: int) -> int: ... + def WaitNamedPipe(__name: str, __timeout: int) -> None: ... + @overload + def WriteFile(handle: int, buffer: bytes, overlapped: Literal[True]) -> tuple[Overlapped, int]: ... + @overload + def WriteFile(handle: int, buffer: bytes, overlapped: Literal[False] = ...) -> tuple[int, int]: ... + @overload + def WriteFile(handle: int, buffer: bytes, overlapped: int | bool) -> tuple[Any, int]: ... + @final + class Overlapped: + event: int + def GetOverlappedResult(self, __wait: bool) -> tuple[int, int]: ... + def cancel(self) -> None: ... + def getbuffer(self) -> bytes | None: ... diff --git a/mypy/typeshed/stdlib/abc.pyi b/mypy/typeshed/stdlib/abc.pyi index 7896e910c81fc..3c53692e1b36a 100644 --- a/mypy/typeshed/stdlib/abc.pyi +++ b/mypy/typeshed/stdlib/abc.pyi @@ -1,5 +1,6 @@ +import sys from _typeshed import SupportsWrite -from typing import Any, Callable, Tuple, Type, TypeVar +from typing import Any, Callable, Type, TypeVar _T = TypeVar("_T") _FuncT = TypeVar("_FuncT", bound=Callable[..., Any]) @@ -7,7 +8,7 @@ _FuncT = TypeVar("_FuncT", bound=Callable[..., Any]) # These definitions have special processing in mypy class ABCMeta(type): __abstractmethods__: frozenset[str] - def __init__(self, name: str, bases: Tuple[type, ...], namespace: dict[str, Any]) -> None: ... + def __init__(self, name: str, bases: tuple[type, ...], namespace: dict[str, Any]) -> None: ... def __instancecheck__(cls: ABCMeta, instance: Any) -> Any: ... def __subclasscheck__(cls: ABCMeta, subclass: Any) -> Any: ... def _dump_registry(cls: ABCMeta, file: SupportsWrite[str] | None = ...) -> None: ... @@ -24,3 +25,6 @@ def abstractclassmethod(callable: _FuncT) -> _FuncT: ... class ABC(metaclass=ABCMeta): ... def get_cache_token() -> object: ... + +if sys.version_info >= (3, 10): + def update_abstractmethods(cls: Type[_T]) -> Type[_T]: ... diff --git a/mypy/typeshed/stdlib/aifc.pyi b/mypy/typeshed/stdlib/aifc.pyi index 79f470a366bbc..e19bf2478bf31 100644 --- a/mypy/typeshed/stdlib/aifc.pyi +++ b/mypy/typeshed/stdlib/aifc.pyi @@ -1,7 +1,7 @@ import sys from _typeshed import Self from types import TracebackType -from typing import IO, Any, NamedTuple, Tuple, Type, Union, overload +from typing import IO, Any, NamedTuple, Type, Union, overload from typing_extensions import Literal class Error(Exception): ... @@ -15,7 +15,7 @@ class _aifc_params(NamedTuple): compname: bytes _File = Union[str, IO[bytes]] -_Marker = Tuple[int, int, bytes] +_Marker = tuple[int, int, bytes] class Aifc_read: def __init__(self, f: _File) -> None: ... diff --git a/mypy/typeshed/stdlib/argparse.pyi b/mypy/typeshed/stdlib/argparse.pyi index b9a09f56a8124..51933dc66668e 100644 --- a/mypy/typeshed/stdlib/argparse.pyi +++ b/mypy/typeshed/stdlib/argparse.pyi @@ -1,20 +1,5 @@ import sys -from typing import ( - IO, - Any, - Callable, - Generator, - Generic, - Iterable, - NoReturn, - Pattern, - Protocol, - Sequence, - Tuple, - Type, - TypeVar, - overload, -) +from typing import IO, Any, Callable, Generator, Generic, Iterable, NoReturn, Pattern, Protocol, Sequence, Type, TypeVar, overload _T = TypeVar("_T") _ActionT = TypeVar("_ActionT", bound=Action) @@ -66,11 +51,11 @@ class _ActionsContainer: nargs: int | str = ..., const: Any = ..., default: Any = ..., - type: Callable[[str], _T] | Callable[[str], _T] | FileType = ..., + type: Callable[[str], _T] | FileType = ..., choices: Iterable[_T] | None = ..., required: bool = ..., help: str | None = ..., - metavar: str | Tuple[str, ...] | None = ..., + metavar: str | tuple[str, ...] | None = ..., dest: str | None = ..., version: str = ..., **kwargs: Any, @@ -143,11 +128,11 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): @overload def parse_args(self, args: Sequence[str] | None = ...) -> Namespace: ... @overload - def parse_args(self, args: Sequence[str] | None, namespace: None) -> Namespace: ... # type: ignore + def parse_args(self, args: Sequence[str] | None, namespace: None) -> Namespace: ... # type: ignore[misc] @overload def parse_args(self, args: Sequence[str] | None, namespace: _N) -> _N: ... @overload - def parse_args(self, *, namespace: None) -> Namespace: ... # type: ignore + def parse_args(self, *, namespace: None) -> Namespace: ... # type: ignore[misc] @overload def parse_args(self, *, namespace: _N) -> _N: ... if sys.version_info >= (3, 7): @@ -274,7 +259,7 @@ class HelpFormatter: def _format_text(self, text: str) -> str: ... def _format_action(self, action: Action) -> str: ... def _format_action_invocation(self, action: Action) -> str: ... - def _metavar_formatter(self, action: Action, default_metavar: str) -> Callable[[int], Tuple[str, ...]]: ... + def _metavar_formatter(self, action: Action, default_metavar: str) -> Callable[[int], tuple[str, ...]]: ... def _format_args(self, action: Action, default_metavar: str) -> str: ... def _expand_help(self, action: Action) -> str: ... def _iter_indented_subactions(self, action: Action) -> Generator[Action, None, None]: ... @@ -299,7 +284,7 @@ class Action(_AttributeHolder): choices: Iterable[Any] | None required: bool help: str | None - metavar: str | Tuple[str, ...] | None + metavar: str | tuple[str, ...] | None def __init__( self, option_strings: Sequence[str], @@ -311,7 +296,7 @@ class Action(_AttributeHolder): choices: Iterable[_T] | None = ..., required: bool = ..., help: str | None = ..., - metavar: str | Tuple[str, ...] | None = ..., + metavar: str | tuple[str, ...] | None = ..., ) -> None: ... def __call__( self, parser: ArgumentParser, namespace: Namespace, values: str | Sequence[Any] | None, option_string: str | None = ... @@ -330,7 +315,7 @@ if sys.version_info >= (3, 9): choices: Iterable[_T] | None = ..., required: bool = ..., help: str | None = ..., - metavar: str | Tuple[str, ...] | None = ..., + metavar: str | tuple[str, ...] | None = ..., ) -> None: ... class Namespace(_AttributeHolder): @@ -375,7 +360,7 @@ class _StoreConstAction(Action): default: Any = ..., required: bool = ..., help: str | None = ..., - metavar: str | Tuple[str, ...] | None = ..., + metavar: str | tuple[str, ...] | None = ..., ) -> None: ... # undocumented @@ -403,7 +388,7 @@ class _AppendConstAction(Action): default: Any = ..., required: bool = ..., help: str | None = ..., - metavar: str | Tuple[str, ...] | None = ..., + metavar: str | tuple[str, ...] | None = ..., ) -> None: ... # undocumented @@ -440,7 +425,7 @@ class _SubParsersAction(Action, Generic[_ArgumentParserT]): dest: str = ..., required: bool = ..., help: str | None = ..., - metavar: str | Tuple[str, ...] | None = ..., + metavar: str | tuple[str, ...] | None = ..., ) -> None: ... else: def __init__( @@ -450,7 +435,7 @@ class _SubParsersAction(Action, Generic[_ArgumentParserT]): parser_class: Type[_ArgumentParserT], dest: str = ..., help: str | None = ..., - metavar: str | Tuple[str, ...] | None = ..., + metavar: str | tuple[str, ...] | None = ..., ) -> None: ... # TODO: Type keyword args properly. def add_parser(self, name: str, **kwargs: Any) -> _ArgumentParserT: ... diff --git a/mypy/typeshed/stdlib/array.pyi b/mypy/typeshed/stdlib/array.pyi index 6f4444b10f96e..f49eb2c916c28 100644 --- a/mypy/typeshed/stdlib/array.pyi +++ b/mypy/typeshed/stdlib/array.pyi @@ -1,6 +1,6 @@ import sys from typing import Any, BinaryIO, Generic, Iterable, MutableSequence, TypeVar, Union, overload -from typing_extensions import Literal +from typing_extensions import Literal, SupportsIndex _IntTypeCode = Literal["b", "B", "h", "H", "i", "I", "l", "L", "q", "Q"] _FloatTypeCode = Literal["f", "d"] @@ -48,14 +48,14 @@ class array(MutableSequence[_T], Generic[_T]): def tostring(self) -> bytes: ... def __len__(self) -> int: ... @overload - def __getitem__(self, __i: int) -> _T: ... + def __getitem__(self, __i: SupportsIndex) -> _T: ... @overload def __getitem__(self, __s: slice) -> array[_T]: ... @overload # type: ignore # Overrides MutableSequence - def __setitem__(self, __i: int, __o: _T) -> None: ... + def __setitem__(self, __i: SupportsIndex, __o: _T) -> None: ... @overload def __setitem__(self, __s: slice, __o: array[_T]) -> None: ... - def __delitem__(self, __i: int | slice) -> None: ... + def __delitem__(self, __i: SupportsIndex | slice) -> None: ... def __add__(self, __x: array[_T]) -> array[_T]: ... def __ge__(self, __other: array[_T]) -> bool: ... def __gt__(self, __other: array[_T]) -> bool: ... diff --git a/mypy/typeshed/stdlib/ast.pyi b/mypy/typeshed/stdlib/ast.pyi index 00c62c30c0376..8494a3a99126d 100644 --- a/mypy/typeshed/stdlib/ast.pyi +++ b/mypy/typeshed/stdlib/ast.pyi @@ -8,7 +8,7 @@ # sys. import sys import typing as _typing -from _ast import * # type: ignore +from _ast import * from typing import Any, Iterator, TypeVar, overload from typing_extensions import Literal @@ -165,6 +165,57 @@ if sys.version_info >= (3, 8): feature_version: None | int | _typing.Tuple[int, int] = ..., ) -> Module: ... @overload + def parse( + source: str | bytes, + filename: str | bytes, + mode: Literal["eval"], + *, + type_comments: bool = ..., + feature_version: None | int | _typing.Tuple[int, int] = ..., + ) -> Expression: ... + @overload + def parse( + source: str | bytes, + filename: str | bytes, + mode: Literal["func_type"], + *, + type_comments: bool = ..., + feature_version: None | int | _typing.Tuple[int, int] = ..., + ) -> FunctionType: ... + @overload + def parse( + source: str | bytes, + filename: str | bytes, + mode: Literal["single"], + *, + type_comments: bool = ..., + feature_version: None | int | _typing.Tuple[int, int] = ..., + ) -> Interactive: ... + @overload + def parse( + source: str | bytes, + *, + mode: Literal["eval"], + type_comments: bool = ..., + feature_version: None | int | _typing.Tuple[int, int] = ..., + ) -> Expression: ... + @overload + def parse( + source: str | bytes, + *, + mode: Literal["func_type"], + type_comments: bool = ..., + feature_version: None | int | _typing.Tuple[int, int] = ..., + ) -> FunctionType: ... + @overload + def parse( + source: str | bytes, + *, + mode: Literal["single"], + type_comments: bool = ..., + feature_version: None | int | _typing.Tuple[int, int] = ..., + ) -> Interactive: ... + @overload def parse( source: str | bytes, filename: str | bytes = ..., @@ -178,6 +229,14 @@ else: @overload def parse(source: str | bytes, filename: str | bytes = ..., mode: Literal["exec"] = ...) -> Module: ... @overload + def parse(source: str | bytes, filename: str | bytes, mode: Literal["eval"]) -> Expression: ... + @overload + def parse(source: str | bytes, filename: str | bytes, mode: Literal["single"]) -> Interactive: ... + @overload + def parse(source: str | bytes, *, mode: Literal["eval"]) -> Expression: ... + @overload + def parse(source: str | bytes, *, mode: Literal["single"]) -> Interactive: ... + @overload def parse(source: str | bytes, filename: str | bytes = ..., mode: str = ...) -> AST: ... if sys.version_info >= (3, 9): diff --git a/mypy/typeshed/stdlib/asyncio/__init__.pyi b/mypy/typeshed/stdlib/asyncio/__init__.pyi index 42e7aa9ba6d85..f2f7c6b0d1654 100644 --- a/mypy/typeshed/stdlib/asyncio/__init__.pyi +++ b/mypy/typeshed/stdlib/asyncio/__init__.pyi @@ -2,7 +2,7 @@ import sys from typing import Type from .base_events import BaseEventLoop as BaseEventLoop -from .coroutines import coroutine as coroutine, iscoroutine as iscoroutine, iscoroutinefunction as iscoroutinefunction +from .coroutines import iscoroutine as iscoroutine, iscoroutinefunction as iscoroutinefunction from .events import ( AbstractEventLoop as AbstractEventLoop, AbstractEventLoopPolicy as AbstractEventLoopPolicy, @@ -71,39 +71,48 @@ from .transports import ( WriteTransport as WriteTransport, ) -if sys.version_info >= (3, 7): - from .events import get_running_loop as get_running_loop +if sys.version_info < (3, 11): + from .coroutines import coroutine as coroutine + +if sys.version_info >= (3, 9): + from .threads import to_thread as to_thread + if sys.version_info >= (3, 8): from .exceptions import ( CancelledError as CancelledError, IncompleteReadError as IncompleteReadError, InvalidStateError as InvalidStateError, LimitOverrunError as LimitOverrunError, - SendfileNotAvailableError as SendfileNotAvailableError, TimeoutError as TimeoutError, ) else: - if sys.version_info >= (3, 7): - from .events import SendfileNotAvailableError as SendfileNotAvailableError from .futures import CancelledError as CancelledError, InvalidStateError as InvalidStateError, TimeoutError as TimeoutError from .streams import IncompleteReadError as IncompleteReadError, LimitOverrunError as LimitOverrunError -if sys.version_info >= (3, 7): - from .protocols import BufferedProtocol as BufferedProtocol +if sys.version_info >= (3, 8): + from .exceptions import SendfileNotAvailableError as SendfileNotAvailableError +elif sys.version_info >= (3, 7): + from .events import SendfileNotAvailableError as SendfileNotAvailableError if sys.version_info >= (3, 7): + from .events import get_running_loop as get_running_loop + from .protocols import BufferedProtocol as BufferedProtocol from .runners import run as run - -if sys.version_info >= (3, 7): - from .tasks import all_tasks as all_tasks, create_task as create_task, current_task as current_task -if sys.version_info >= (3, 9): - from .threads import to_thread as to_thread + from .tasks import ( + _enter_task as _enter_task, + _leave_task as _leave_task, + _register_task as _register_task, + _unregister_task as _unregister_task, + all_tasks as all_tasks, + create_task as create_task, + current_task as current_task, + ) DefaultEventLoopPolicy: Type[AbstractEventLoopPolicy] + if sys.platform == "win32": from .windows_events import * - -if sys.platform != "win32": +else: from .streams import open_unix_connection as open_unix_connection, start_unix_server as start_unix_server from .unix_events import ( AbstractChildWatcher as AbstractChildWatcher, diff --git a/mypy/typeshed/stdlib/asyncio/base_events.pyi b/mypy/typeshed/stdlib/asyncio/base_events.pyi index 15471f54483f8..674baf49ba05c 100644 --- a/mypy/typeshed/stdlib/asyncio/base_events.pyi +++ b/mypy/typeshed/stdlib/asyncio/base_events.pyi @@ -9,18 +9,18 @@ from asyncio.tasks import Task from asyncio.transports import BaseTransport from collections.abc import Iterable from socket import AddressFamily, SocketKind, _Address, _RetAddress, socket -from typing import IO, Any, Awaitable, Callable, Dict, Generator, Sequence, Tuple, TypeVar, Union, overload +from typing import IO, Any, Awaitable, Callable, Generator, Sequence, TypeVar, Union, overload from typing_extensions import Literal if sys.version_info >= (3, 7): from contextvars import Context _T = TypeVar("_T") -_Context = Dict[str, Any] +_Context = dict[str, Any] _ExceptionHandler = Callable[[AbstractEventLoop, _Context], Any] _ProtocolFactory = Callable[[], BaseProtocol] _SSLContext = Union[bool, None, ssl.SSLContext] -_TransProtPair = Tuple[BaseTransport, BaseProtocol] +_TransProtPair = tuple[BaseTransport, BaseProtocol] class Server(AbstractServer): if sys.version_info >= (3, 7): @@ -37,7 +37,7 @@ class Server(AbstractServer): def __init__(self, loop: AbstractEventLoop, sockets: list[socket]) -> None: ... if sys.version_info >= (3, 8): @property - def sockets(self) -> Tuple[socket, ...]: ... + def sockets(self) -> tuple[socket, ...]: ... elif sys.version_info >= (3, 7): @property def sockets(self) -> list[socket]: ... @@ -285,20 +285,35 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): async def connect_accepted_socket( self, protocol_factory: _ProtocolFactory, sock: socket, *, ssl: _SSLContext = ... ) -> _TransProtPair: ... - async def create_datagram_endpoint( - self, - protocol_factory: _ProtocolFactory, - local_addr: tuple[str, int] | None = ..., - remote_addr: tuple[str, int] | None = ..., - *, - family: int = ..., - proto: int = ..., - flags: int = ..., - reuse_address: bool | None = ..., - reuse_port: bool | None = ..., - allow_broadcast: bool | None = ..., - sock: socket | None = ..., - ) -> _TransProtPair: ... + if sys.version_info >= (3, 11): + async def create_datagram_endpoint( + self, + protocol_factory: _ProtocolFactory, + local_addr: tuple[str, int] | None = ..., + remote_addr: tuple[str, int] | None = ..., + *, + family: int = ..., + proto: int = ..., + flags: int = ..., + reuse_port: bool | None = ..., + allow_broadcast: bool | None = ..., + sock: socket | None = ..., + ) -> _TransProtPair: ... + else: + async def create_datagram_endpoint( + self, + protocol_factory: _ProtocolFactory, + local_addr: tuple[str, int] | None = ..., + remote_addr: tuple[str, int] | None = ..., + *, + family: int = ..., + proto: int = ..., + flags: int = ..., + reuse_address: bool | None = ..., + reuse_port: bool | None = ..., + allow_broadcast: bool | None = ..., + sock: socket | None = ..., + ) -> _TransProtPair: ... # Pipes and subprocesses. async def connect_read_pipe(self, protocol_factory: _ProtocolFactory, pipe: Any) -> _TransProtPair: ... async def connect_write_pipe(self, protocol_factory: _ProtocolFactory, pipe: Any) -> _TransProtPair: ... diff --git a/mypy/typeshed/stdlib/asyncio/base_subprocess.pyi b/mypy/typeshed/stdlib/asyncio/base_subprocess.pyi index 23034790a4a9a..94c7c01dd1bc7 100644 --- a/mypy/typeshed/stdlib/asyncio/base_subprocess.pyi +++ b/mypy/typeshed/stdlib/asyncio/base_subprocess.pyi @@ -1,6 +1,6 @@ import subprocess from collections import deque -from typing import IO, Any, Callable, Optional, Sequence, Tuple, Union +from typing import IO, Any, Callable, Optional, Sequence, Union from . import events, futures, protocols, transports @@ -15,7 +15,7 @@ class BaseSubprocessTransport(transports.SubprocessTransport): _pid: int | None # undocumented _returncode: int | None # undocumented _exit_waiters: list[futures.Future[Any]] # undocumented - _pending_calls: deque[tuple[Callable[..., Any], Tuple[Any, ...]]] # undocumented + _pending_calls: deque[tuple[Callable[..., Any], tuple[Any, ...]]] # undocumented _pipes: dict[int, _File] # undocumented _finished: bool # undocumented def __init__( @@ -46,11 +46,11 @@ class BaseSubprocessTransport(transports.SubprocessTransport): def get_protocol(self) -> protocols.BaseProtocol: ... def is_closing(self) -> bool: ... def close(self) -> None: ... - def get_pid(self) -> int | None: ... # type: ignore + def get_pid(self) -> int | None: ... # type: ignore[override] def get_returncode(self) -> int | None: ... - def get_pipe_transport(self, fd: int) -> _File: ... # type: ignore + def get_pipe_transport(self, fd: int) -> _File: ... # type: ignore[override] def _check_proc(self) -> None: ... # undocumented - def send_signal(self, signal: int) -> None: ... # type: ignore + def send_signal(self, signal: int) -> None: ... # type: ignore[override] def terminate(self) -> None: ... def kill(self) -> None: ... async def _connect_pipes(self, waiter: futures.Future[Any] | None) -> None: ... # undocumented diff --git a/mypy/typeshed/stdlib/asyncio/constants.pyi b/mypy/typeshed/stdlib/asyncio/constants.pyi index 2010fe9123ae2..230cf4faf4837 100644 --- a/mypy/typeshed/stdlib/asyncio/constants.pyi +++ b/mypy/typeshed/stdlib/asyncio/constants.pyi @@ -1,12 +1,13 @@ import enum import sys +from typing_extensions import Literal -LOG_THRESHOLD_FOR_CONNLOST_WRITES: int -ACCEPT_RETRY_DELAY: int -DEBUG_STACK_DEPTH: int +LOG_THRESHOLD_FOR_CONNLOST_WRITES: Literal[5] +ACCEPT_RETRY_DELAY: Literal[1] +DEBUG_STACK_DEPTH: Literal[10] if sys.version_info >= (3, 7): SSL_HANDSHAKE_TIMEOUT: float - SENDFILE_FALLBACK_READBUFFER_SIZE: int + SENDFILE_FALLBACK_READBUFFER_SIZE: Literal[262144] class _SendfileMode(enum.Enum): UNSUPPORTED: int diff --git a/mypy/typeshed/stdlib/asyncio/coroutines.pyi b/mypy/typeshed/stdlib/asyncio/coroutines.pyi index df94d5ba156a2..6c2d8179d1f14 100644 --- a/mypy/typeshed/stdlib/asyncio/coroutines.pyi +++ b/mypy/typeshed/stdlib/asyncio/coroutines.pyi @@ -1,16 +1,20 @@ import sys import types -from collections.abc import Callable, Coroutine -from typing import Any, TypeVar +from collections.abc import Coroutine +from typing import Any from typing_extensions import TypeGuard -_F = TypeVar("_F", bound=Callable[..., Any]) +if sys.version_info < (3, 11): + from collections.abc import Callable + from typing import TypeVar + + _F = TypeVar("_F", bound=Callable[..., Any]) + def coroutine(func: _F) -> _F: ... -def coroutine(func: _F) -> _F: ... def iscoroutinefunction(func: object) -> bool: ... -if sys.version_info < (3, 8): - def iscoroutine(obj: object) -> TypeGuard[types.GeneratorType[Any, Any, Any] | Coroutine[Any, Any, Any]]: ... +if sys.version_info >= (3, 8): + def iscoroutine(obj: object) -> TypeGuard[Coroutine[Any, Any, Any]]: ... else: - def iscoroutine(obj: object) -> TypeGuard[Coroutine[Any, Any, Any]]: ... + def iscoroutine(obj: object) -> TypeGuard[types.GeneratorType[Any, Any, Any] | Coroutine[Any, Any, Any]]: ... diff --git a/mypy/typeshed/stdlib/asyncio/events.pyi b/mypy/typeshed/stdlib/asyncio/events.pyi index 6ef9117b64913..81b30b7e00651 100644 --- a/mypy/typeshed/stdlib/asyncio/events.pyi +++ b/mypy/typeshed/stdlib/asyncio/events.pyi @@ -3,7 +3,7 @@ import sys from _typeshed import FileDescriptorLike, Self from abc import ABCMeta, abstractmethod from socket import AddressFamily, SocketKind, _Address, _RetAddress, socket -from typing import IO, Any, Awaitable, Callable, Dict, Generator, Sequence, Tuple, TypeVar, Union, overload +from typing import IO, Any, Awaitable, Callable, Generator, Sequence, TypeVar, Union, overload from typing_extensions import Literal from .base_events import Server @@ -17,11 +17,11 @@ if sys.version_info >= (3, 7): from contextvars import Context _T = TypeVar("_T") -_Context = Dict[str, Any] +_Context = dict[str, Any] _ExceptionHandler = Callable[[AbstractEventLoop, _Context], Any] _ProtocolFactory = Callable[[], BaseProtocol] _SSLContext = Union[bool, None, ssl.SSLContext] -_TransProtPair = Tuple[BaseTransport, BaseProtocol] +_TransProtPair = tuple[BaseTransport, BaseProtocol] class Handle: _cancelled = False diff --git a/mypy/typeshed/stdlib/asyncio/proactor_events.pyi b/mypy/typeshed/stdlib/asyncio/proactor_events.pyi index 6c8c558e5dfa9..1e9cff1b1dd67 100644 --- a/mypy/typeshed/stdlib/asyncio/proactor_events.pyi +++ b/mypy/typeshed/stdlib/asyncio/proactor_events.pyi @@ -1,7 +1,7 @@ import sys from socket import socket -from typing import Any, Mapping, Type -from typing_extensions import Literal, Protocol +from typing import Any, Mapping, Protocol, Type +from typing_extensions import Literal from . import base_events, constants, events, futures, streams, transports diff --git a/mypy/typeshed/stdlib/asyncio/streams.pyi b/mypy/typeshed/stdlib/asyncio/streams.pyi index 595222280d589..6dae893e3b974 100644 --- a/mypy/typeshed/stdlib/asyncio/streams.pyi +++ b/mypy/typeshed/stdlib/asyncio/streams.pyi @@ -16,43 +16,71 @@ if sys.version_info < (3, 8): consumed: int def __init__(self, message: str, consumed: int) -> None: ... -async def open_connection( - host: str | None = ..., - port: int | str | None = ..., - *, - loop: events.AbstractEventLoop | None = ..., - limit: int = ..., - ssl_handshake_timeout: float | None = ..., - **kwds: Any, -) -> tuple[StreamReader, StreamWriter]: ... -async def start_server( - client_connected_cb: _ClientConnectedCallback, - host: str | None = ..., - port: int | str | None = ..., - *, - loop: events.AbstractEventLoop | None = ..., - limit: int = ..., - ssl_handshake_timeout: float | None = ..., - **kwds: Any, -) -> Server: ... +if sys.version_info >= (3, 10): + async def open_connection( + host: str | None = ..., + port: int | str | None = ..., + *, + limit: int = ..., + ssl_handshake_timeout: float | None = ..., + **kwds: Any, + ) -> tuple[StreamReader, StreamWriter]: ... + async def start_server( + client_connected_cb: _ClientConnectedCallback, + host: str | None = ..., + port: int | str | None = ..., + *, + limit: int = ..., + ssl_handshake_timeout: float | None = ..., + **kwds: Any, + ) -> Server: ... -if sys.platform != "win32": - if sys.version_info >= (3, 7): - _PathType = StrPath - else: - _PathType = str - async def open_unix_connection( - path: _PathType | None = ..., *, loop: events.AbstractEventLoop | None = ..., limit: int = ..., **kwds: Any +else: + async def open_connection( + host: str | None = ..., + port: int | str | None = ..., + *, + loop: events.AbstractEventLoop | None = ..., + limit: int = ..., + ssl_handshake_timeout: float | None = ..., + **kwds: Any, ) -> tuple[StreamReader, StreamWriter]: ... - async def start_unix_server( + async def start_server( client_connected_cb: _ClientConnectedCallback, - path: _PathType | None = ..., + host: str | None = ..., + port: int | str | None = ..., *, loop: events.AbstractEventLoop | None = ..., limit: int = ..., + ssl_handshake_timeout: float | None = ..., **kwds: Any, ) -> Server: ... +if sys.platform != "win32": + if sys.version_info >= (3, 7): + _PathType = StrPath + else: + _PathType = str + if sys.version_info >= (3, 10): + async def open_unix_connection( + path: _PathType | None = ..., *, limit: int = ..., **kwds: Any + ) -> tuple[StreamReader, StreamWriter]: ... + async def start_unix_server( + client_connected_cb: _ClientConnectedCallback, path: _PathType | None = ..., *, limit: int = ..., **kwds: Any + ) -> Server: ... + else: + async def open_unix_connection( + path: _PathType | None = ..., *, loop: events.AbstractEventLoop | None = ..., limit: int = ..., **kwds: Any + ) -> tuple[StreamReader, StreamWriter]: ... + async def start_unix_server( + client_connected_cb: _ClientConnectedCallback, + path: _PathType | None = ..., + *, + loop: events.AbstractEventLoop | None = ..., + limit: int = ..., + **kwds: Any, + ) -> Server: ... + class FlowControlMixin(protocols.Protocol): def __init__(self, loop: events.AbstractEventLoop | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/asyncio/tasks.pyi b/mypy/typeshed/stdlib/asyncio/tasks.pyi index 15c12909f3c30..71f9741cb33b7 100644 --- a/mypy/typeshed/stdlib/asyncio/tasks.pyi +++ b/mypy/typeshed/stdlib/asyncio/tasks.pyi @@ -21,9 +21,9 @@ _FT = TypeVar("_FT", bound=Future[Any]) _FutureT = Union[Future[_T], Generator[Any, None, _T], Awaitable[_T]] _TaskYieldType = Optional[Future[object]] -FIRST_EXCEPTION: str -FIRST_COMPLETED: str -ALL_COMPLETED: str +FIRST_COMPLETED = concurrent.futures.FIRST_COMPLETED +FIRST_EXCEPTION = concurrent.futures.FIRST_EXCEPTION +ALL_COMPLETED = concurrent.futures.ALL_COMPLETED if sys.version_info >= (3, 10): def as_completed(fs: Iterable[_FutureT[_T]], *, timeout: float | None = ...) -> Iterator[Future[_T]]: ... @@ -34,7 +34,7 @@ else: ) -> Iterator[Future[_T]]: ... @overload -def ensure_future(coro_or_future: _FT, *, loop: AbstractEventLoop | None = ...) -> _FT: ... # type: ignore +def ensure_future(coro_or_future: _FT, *, loop: AbstractEventLoop | None = ...) -> _FT: ... # type: ignore[misc] @overload def ensure_future(coro_or_future: Awaitable[_T], *, loop: AbstractEventLoop | None = ...) -> Task[_T]: ... @@ -230,25 +230,27 @@ def run_coroutine_threadsafe(coro: _FutureT[_T], loop: AbstractEventLoop) -> con if sys.version_info >= (3, 10): def shield(arg: _FutureT[_T]) -> Future[_T]: ... - def sleep(delay: float, result: _T = ...) -> Future[_T]: ... + async def sleep(delay: float, result: _T = ...) -> _T: ... @overload - def wait(fs: Iterable[_FT], *, timeout: float | None = ..., return_when: str = ...) -> Future[tuple[set[_FT], set[_FT]]]: ... # type: ignore + async def wait(fs: Iterable[_FT], *, timeout: float | None = ..., return_when: str = ...) -> tuple[set[_FT], set[_FT]]: ... # type: ignore[misc] @overload - def wait( + async def wait( fs: Iterable[Awaitable[_T]], *, timeout: float | None = ..., return_when: str = ... - ) -> Future[tuple[set[Task[_T]], set[Task[_T]]]]: ... - def wait_for(fut: _FutureT[_T], timeout: float | None) -> Future[_T]: ... + ) -> tuple[set[Task[_T]], set[Task[_T]]]: ... + async def wait_for(fut: _FutureT[_T], timeout: float | None) -> _T: ... else: def shield(arg: _FutureT[_T], *, loop: AbstractEventLoop | None = ...) -> Future[_T]: ... - def sleep(delay: float, result: _T = ..., *, loop: AbstractEventLoop | None = ...) -> Future[_T]: ... + async def sleep(delay: float, result: _T = ..., *, loop: AbstractEventLoop | None = ...) -> _T: ... @overload - def wait(fs: Iterable[_FT], *, loop: AbstractEventLoop | None = ..., timeout: float | None = ..., return_when: str = ...) -> Future[tuple[set[_FT], set[_FT]]]: ... # type: ignore + async def wait( # type: ignore[misc] + fs: Iterable[_FT], *, loop: AbstractEventLoop | None = ..., timeout: float | None = ..., return_when: str = ... + ) -> tuple[set[_FT], set[_FT]]: ... @overload - def wait( + async def wait( fs: Iterable[Awaitable[_T]], *, loop: AbstractEventLoop | None = ..., timeout: float | None = ..., return_when: str = ... - ) -> Future[tuple[set[Task[_T]], set[Task[_T]]]]: ... - def wait_for(fut: _FutureT[_T], timeout: float | None, *, loop: AbstractEventLoop | None = ...) -> Future[_T]: ... + ) -> tuple[set[Task[_T]], set[Task[_T]]]: ... + async def wait_for(fut: _FutureT[_T], timeout: float | None, *, loop: AbstractEventLoop | None = ...) -> _T: ... class Task(Future[_T], Generic[_T]): if sys.version_info >= (3, 8): @@ -291,3 +293,7 @@ if sys.version_info >= (3, 7): else: def create_task(coro: Generator[_TaskYieldType, None, _T] | Awaitable[_T]) -> Task[_T]: ... def current_task(loop: AbstractEventLoop | None = ...) -> Task[Any] | None: ... + def _enter_task(loop: AbstractEventLoop, task: Task[Any]) -> None: ... + def _leave_task(loop: AbstractEventLoop, task: Task[Any]) -> None: ... + def _register_task(task: Task[Any]) -> None: ... + def _unregister_task(task: Task[Any]) -> None: ... diff --git a/mypy/typeshed/stdlib/asyncio/threads.pyi b/mypy/typeshed/stdlib/asyncio/threads.pyi index 3f798d8ac862d..c13c0c6d11948 100644 --- a/mypy/typeshed/stdlib/asyncio/threads.pyi +++ b/mypy/typeshed/stdlib/asyncio/threads.pyi @@ -1,7 +1,9 @@ import sys -from typing import Any, Callable, TypeVar +from typing import Callable, TypeVar +from typing_extensions import ParamSpec -_T = TypeVar("_T") +_P = ParamSpec("_P") +_R = TypeVar("_R") if sys.version_info >= (3, 9): - async def to_thread(__func: Callable[..., _T], *args: Any, **kwargs: Any) -> _T: ... + async def to_thread(__func: Callable[_P, _R], *args: _P.args, **kwargs: _P.kwargs) -> _R: ... diff --git a/mypy/typeshed/stdlib/asyncio/trsock.pyi b/mypy/typeshed/stdlib/asyncio/trsock.pyi index 33ec5d67aaf90..55147f4fddd52 100644 --- a/mypy/typeshed/stdlib/asyncio/trsock.pyi +++ b/mypy/typeshed/stdlib/asyncio/trsock.pyi @@ -1,14 +1,14 @@ import socket import sys from types import TracebackType -from typing import Any, BinaryIO, Iterable, NoReturn, Tuple, Type, Union, overload +from typing import Any, BinaryIO, Iterable, NoReturn, Type, Union, overload if sys.version_info >= (3, 8): # These are based in socket, maybe move them out into _typeshed.pyi or such - _Address = Union[Tuple[Any, ...], str] + _Address = Union[tuple[Any, ...], str] _RetAddress = Any _WriteBuffer = Union[bytearray, memoryview] - _CMSG = Tuple[int, int, bytes] + _CMSG = tuple[int, int, bytes] class TransportSocket: def __init__(self, sock: socket.socket) -> None: ... def _na(self, what: str) -> None: ... diff --git a/mypy/typeshed/stdlib/asyncio/unix_events.pyi b/mypy/typeshed/stdlib/asyncio/unix_events.pyi index e8e57a20a765d..de3b320a4e242 100644 --- a/mypy/typeshed/stdlib/asyncio/unix_events.pyi +++ b/mypy/typeshed/stdlib/asyncio/unix_events.pyi @@ -8,6 +8,9 @@ from .base_events import Server from .events import AbstractEventLoop, BaseDefaultEventLoopPolicy, _ProtocolFactory, _SSLContext from .selector_events import BaseSelectorEventLoop +# This is also technically not available on Win, +# but other parts of typeshed need this defintion. +# So, it is special cased. class AbstractChildWatcher: def add_child_handler(self, pid: int, callback: Callable[..., Any], *args: Any) -> None: ... def remove_child_handler(self, pid: int) -> bool: ... @@ -18,44 +21,40 @@ class AbstractChildWatcher: if sys.version_info >= (3, 8): def is_active(self) -> bool: ... -class BaseChildWatcher(AbstractChildWatcher): - def __init__(self) -> None: ... - -class SafeChildWatcher(BaseChildWatcher): - def __enter__(self: Self) -> Self: ... - -class FastChildWatcher(BaseChildWatcher): - def __enter__(self: Self) -> Self: ... - -class _UnixSelectorEventLoop(BaseSelectorEventLoop): - if sys.version_info < (3, 7): - async def create_unix_server( - self, - protocol_factory: _ProtocolFactory, - path: str | None = ..., - *, - sock: socket | None = ..., - backlog: int = ..., - ssl: _SSLContext = ..., - ) -> Server: ... - -class _UnixDefaultEventLoopPolicy(BaseDefaultEventLoopPolicy): - def get_child_watcher(self) -> AbstractChildWatcher: ... - def set_child_watcher(self, watcher: AbstractChildWatcher | None) -> None: ... - -SelectorEventLoop = _UnixSelectorEventLoop - -DefaultEventLoopPolicy = _UnixDefaultEventLoopPolicy - -if sys.version_info >= (3, 8): - - from typing import Protocol - class _Warn(Protocol): - def __call__( - self, message: str, category: Type[Warning] | None = ..., stacklevel: int = ..., source: Any | None = ... - ) -> None: ... - class MultiLoopChildWatcher(AbstractChildWatcher): +if sys.platform != "win32": + class BaseChildWatcher(AbstractChildWatcher): + def __init__(self) -> None: ... + class SafeChildWatcher(BaseChildWatcher): def __enter__(self: Self) -> Self: ... - class ThreadedChildWatcher(AbstractChildWatcher): + class FastChildWatcher(BaseChildWatcher): def __enter__(self: Self) -> Self: ... - def __del__(self, _warn: _Warn = ...) -> None: ... + class _UnixSelectorEventLoop(BaseSelectorEventLoop): + if sys.version_info < (3, 7): + async def create_unix_server( + self, + protocol_factory: _ProtocolFactory, + path: str | None = ..., + *, + sock: socket | None = ..., + backlog: int = ..., + ssl: _SSLContext = ..., + ) -> Server: ... + class _UnixDefaultEventLoopPolicy(BaseDefaultEventLoopPolicy): + def get_child_watcher(self) -> AbstractChildWatcher: ... + def set_child_watcher(self, watcher: AbstractChildWatcher | None) -> None: ... + SelectorEventLoop = _UnixSelectorEventLoop + + DefaultEventLoopPolicy = _UnixDefaultEventLoopPolicy + + if sys.version_info >= (3, 8): + + from typing import Protocol + class _Warn(Protocol): + def __call__( + self, message: str, category: Type[Warning] | None = ..., stacklevel: int = ..., source: Any | None = ... + ) -> None: ... + class MultiLoopChildWatcher(AbstractChildWatcher): + def __enter__(self: Self) -> Self: ... + class ThreadedChildWatcher(AbstractChildWatcher): + def __enter__(self: Self) -> Self: ... + def __del__(self, _warn: _Warn = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/asyncio/windows_events.pyi b/mypy/typeshed/stdlib/asyncio/windows_events.pyi index f0a206a4e139d..d86b6af91a294 100644 --- a/mypy/typeshed/stdlib/asyncio/windows_events.pyi +++ b/mypy/typeshed/stdlib/asyncio/windows_events.pyi @@ -2,76 +2,76 @@ import socket import sys from _typeshed import WriteableBuffer from typing import IO, Any, Callable, ClassVar, NoReturn, Type +from typing_extensions import Literal from . import events, futures, proactor_events, selector_events, streams, windows_utils -__all__ = [ - "SelectorEventLoop", - "ProactorEventLoop", - "IocpProactor", - "DefaultEventLoopPolicy", - "WindowsSelectorEventLoopPolicy", - "WindowsProactorEventLoopPolicy", -] - -NULL: int -INFINITE: int -ERROR_CONNECTION_REFUSED: int -ERROR_CONNECTION_ABORTED: int -CONNECT_PIPE_INIT_DELAY: float -CONNECT_PIPE_MAX_DELAY: float - -class PipeServer: - def __init__(self, address: str) -> None: ... - def __del__(self) -> None: ... - def closed(self) -> bool: ... - def close(self) -> None: ... - -class _WindowsSelectorEventLoop(selector_events.BaseSelectorEventLoop): ... - -class ProactorEventLoop(proactor_events.BaseProactorEventLoop): - def __init__(self, proactor: IocpProactor | None = ...) -> None: ... - async def create_pipe_connection( - self, protocol_factory: Callable[[], streams.StreamReaderProtocol], address: str - ) -> tuple[proactor_events._ProactorDuplexPipeTransport, streams.StreamReaderProtocol]: ... - async def start_serving_pipe( - self, protocol_factory: Callable[[], streams.StreamReaderProtocol], address: str - ) -> list[PipeServer]: ... - -class IocpProactor: - def __init__(self, concurrency: int = ...) -> None: ... - def __repr__(self) -> str: ... - def __del__(self) -> None: ... - def set_loop(self, loop: events.AbstractEventLoop) -> None: ... - def select(self, timeout: int | None = ...) -> list[futures.Future[Any]]: ... - def recv(self, conn: socket.socket, nbytes: int, flags: int = ...) -> futures.Future[bytes]: ... - if sys.version_info >= (3, 7): - def recv_into(self, conn: socket.socket, buf: WriteableBuffer, flags: int = ...) -> futures.Future[Any]: ... - def send(self, conn: socket.socket, buf: WriteableBuffer, flags: int = ...) -> futures.Future[Any]: ... - def accept(self, listener: socket.socket) -> futures.Future[Any]: ... - def connect(self, conn: socket.socket, address: bytes) -> futures.Future[Any]: ... +if sys.platform == "win32": if sys.version_info >= (3, 7): - def sendfile(self, sock: socket.socket, file: IO[bytes], offset: int, count: int) -> futures.Future[Any]: ... - def accept_pipe(self, pipe: socket.socket) -> futures.Future[Any]: ... - async def connect_pipe(self, address: bytes) -> windows_utils.PipeHandle: ... - def wait_for_handle(self, handle: windows_utils.PipeHandle, timeout: int | None = ...) -> bool: ... - def close(self) -> None: ... + __all__ = ( + "SelectorEventLoop", + "ProactorEventLoop", + "IocpProactor", + "DefaultEventLoopPolicy", + "WindowsSelectorEventLoopPolicy", + "WindowsProactorEventLoopPolicy", + ) + else: + __all__ = ["SelectorEventLoop", "ProactorEventLoop", "IocpProactor", "DefaultEventLoopPolicy"] -SelectorEventLoop = _WindowsSelectorEventLoop + NULL: Literal[0] + INFINITE: Literal[0xFFFFFFFF] + ERROR_CONNECTION_REFUSED: Literal[1225] + ERROR_CONNECTION_ABORTED: Literal[1236] + CONNECT_PIPE_INIT_DELAY: float + CONNECT_PIPE_MAX_DELAY: float + class PipeServer: + def __init__(self, address: str) -> None: ... + def __del__(self) -> None: ... + def closed(self) -> bool: ... + def close(self) -> None: ... + class _WindowsSelectorEventLoop(selector_events.BaseSelectorEventLoop): ... + class ProactorEventLoop(proactor_events.BaseProactorEventLoop): + def __init__(self, proactor: IocpProactor | None = ...) -> None: ... + async def create_pipe_connection( + self, protocol_factory: Callable[[], streams.StreamReaderProtocol], address: str + ) -> tuple[proactor_events._ProactorDuplexPipeTransport, streams.StreamReaderProtocol]: ... + async def start_serving_pipe( + self, protocol_factory: Callable[[], streams.StreamReaderProtocol], address: str + ) -> list[PipeServer]: ... + class IocpProactor: + def __init__(self, concurrency: int = ...) -> None: ... + def __repr__(self) -> str: ... + def __del__(self) -> None: ... + def set_loop(self, loop: events.AbstractEventLoop) -> None: ... + def select(self, timeout: int | None = ...) -> list[futures.Future[Any]]: ... + def recv(self, conn: socket.socket, nbytes: int, flags: int = ...) -> futures.Future[bytes]: ... + if sys.version_info >= (3, 7): + def recv_into(self, conn: socket.socket, buf: WriteableBuffer, flags: int = ...) -> futures.Future[Any]: ... + def send(self, conn: socket.socket, buf: WriteableBuffer, flags: int = ...) -> futures.Future[Any]: ... + def accept(self, listener: socket.socket) -> futures.Future[Any]: ... + def connect(self, conn: socket.socket, address: bytes) -> futures.Future[Any]: ... + if sys.version_info >= (3, 7): + def sendfile(self, sock: socket.socket, file: IO[bytes], offset: int, count: int) -> futures.Future[Any]: ... + def accept_pipe(self, pipe: socket.socket) -> futures.Future[Any]: ... + async def connect_pipe(self, address: bytes) -> windows_utils.PipeHandle: ... + def wait_for_handle(self, handle: windows_utils.PipeHandle, timeout: int | None = ...) -> bool: ... + def close(self) -> None: ... + SelectorEventLoop = _WindowsSelectorEventLoop -if sys.version_info >= (3, 7): - class WindowsSelectorEventLoopPolicy(events.BaseDefaultEventLoopPolicy): - _loop_factory: ClassVar[Type[SelectorEventLoop]] - def get_child_watcher(self) -> NoReturn: ... - def set_child_watcher(self, watcher: Any) -> NoReturn: ... - class WindowsProactorEventLoopPolicy(events.BaseDefaultEventLoopPolicy): - _loop_factory: ClassVar[Type[ProactorEventLoop]] - def get_child_watcher(self) -> NoReturn: ... - def set_child_watcher(self, watcher: Any) -> NoReturn: ... - DefaultEventLoopPolicy = WindowsSelectorEventLoopPolicy -else: - class _WindowsDefaultEventLoopPolicy(events.BaseDefaultEventLoopPolicy): - _loop_factory: ClassVar[Type[SelectorEventLoop]] - def get_child_watcher(self) -> NoReturn: ... - def set_child_watcher(self, watcher: Any) -> NoReturn: ... - DefaultEventLoopPolicy = _WindowsDefaultEventLoopPolicy + if sys.version_info >= (3, 7): + class WindowsSelectorEventLoopPolicy(events.BaseDefaultEventLoopPolicy): + _loop_factory: ClassVar[Type[SelectorEventLoop]] + def get_child_watcher(self) -> NoReturn: ... + def set_child_watcher(self, watcher: Any) -> NoReturn: ... + class WindowsProactorEventLoopPolicy(events.BaseDefaultEventLoopPolicy): + _loop_factory: ClassVar[Type[ProactorEventLoop]] + def get_child_watcher(self) -> NoReturn: ... + def set_child_watcher(self, watcher: Any) -> NoReturn: ... + DefaultEventLoopPolicy = WindowsSelectorEventLoopPolicy + else: + class _WindowsDefaultEventLoopPolicy(events.BaseDefaultEventLoopPolicy): + _loop_factory: ClassVar[Type[SelectorEventLoop]] + def get_child_watcher(self) -> NoReturn: ... + def set_child_watcher(self, watcher: Any) -> NoReturn: ... + DefaultEventLoopPolicy = _WindowsDefaultEventLoopPolicy diff --git a/mypy/typeshed/stdlib/asyncio/windows_utils.pyi b/mypy/typeshed/stdlib/asyncio/windows_utils.pyi index bf9cdde25a78d..c387fc40f2118 100644 --- a/mypy/typeshed/stdlib/asyncio/windows_utils.pyi +++ b/mypy/typeshed/stdlib/asyncio/windows_utils.pyi @@ -1,27 +1,29 @@ +import subprocess import sys from _typeshed import Self from types import TracebackType from typing import Callable, Protocol, Type +from typing_extensions import Literal -class _WarnFunction(Protocol): - def __call__(self, message: str, category: Type[Warning] = ..., stacklevel: int = ..., source: PipeHandle = ...) -> None: ... - -BUFSIZE: int -PIPE: int -STDOUT: int - -def pipe(*, duplex: bool = ..., overlapped: tuple[bool, bool] = ..., bufsize: int = ...) -> tuple[int, int]: ... - -class PipeHandle: - def __init__(self, handle: int) -> None: ... - def __repr__(self) -> str: ... - if sys.version_info >= (3, 8): - def __del__(self, _warn: _WarnFunction = ...) -> None: ... - else: - def __del__(self) -> None: ... - def __enter__(self: Self) -> Self: ... - def __exit__(self, t: type | None, v: BaseException | None, tb: TracebackType | None) -> None: ... - @property - def handle(self) -> int: ... - def fileno(self) -> int: ... - def close(self, *, CloseHandle: Callable[[int], None] = ...) -> None: ... +if sys.platform == "win32": + class _WarnFunction(Protocol): + def __call__( + self, message: str, category: Type[Warning] = ..., stacklevel: int = ..., source: PipeHandle = ... + ) -> None: ... + BUFSIZE: Literal[8192] + PIPE = subprocess.PIPE + STDOUT = subprocess.STDOUT + def pipe(*, duplex: bool = ..., overlapped: tuple[bool, bool] = ..., bufsize: int = ...) -> tuple[int, int]: ... + class PipeHandle: + def __init__(self, handle: int) -> None: ... + def __repr__(self) -> str: ... + if sys.version_info >= (3, 8): + def __del__(self, _warn: _WarnFunction = ...) -> None: ... + else: + def __del__(self) -> None: ... + def __enter__(self: Self) -> Self: ... + def __exit__(self, t: type | None, v: BaseException | None, tb: TracebackType | None) -> None: ... + @property + def handle(self) -> int: ... + def fileno(self) -> int: ... + def close(self, *, CloseHandle: Callable[[int], None] = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/asyncore.pyi b/mypy/typeshed/stdlib/asyncore.pyi index e135221134a56..123da2677a7e2 100644 --- a/mypy/typeshed/stdlib/asyncore.pyi +++ b/mypy/typeshed/stdlib/asyncore.pyi @@ -1,10 +1,10 @@ import sys from _typeshed import FileDescriptorLike from socket import socket -from typing import Any, Dict, Tuple, overload +from typing import Any, overload # cyclic dependence with asynchat -_maptype = Dict[int, Any] +_maptype = dict[int, Any] _socket = socket socket_map: _maptype # undocumented @@ -41,8 +41,8 @@ class dispatcher: def readable(self) -> bool: ... def writable(self) -> bool: ... def listen(self, num: int) -> None: ... - def bind(self, addr: Tuple[Any, ...] | str) -> None: ... - def connect(self, address: Tuple[Any, ...] | str) -> None: ... + def bind(self, addr: tuple[Any, ...] | str) -> None: ... + def connect(self, address: tuple[Any, ...] | str) -> None: ... def accept(self) -> tuple[_socket, Any] | None: ... def send(self, data: bytes) -> int: ... def recv(self, buffer_size: int) -> bytes: ... diff --git a/mypy/typeshed/stdlib/atexit.pyi b/mypy/typeshed/stdlib/atexit.pyi index 9395c60678b84..ba0c7dfaf6b1f 100644 --- a/mypy/typeshed/stdlib/atexit.pyi +++ b/mypy/typeshed/stdlib/atexit.pyi @@ -7,5 +7,5 @@ _P = ParamSpec("_P") def _clear() -> None: ... def _ncallbacks() -> int: ... def _run_exitfuncs() -> None: ... -def register(func: Callable[_P, _T], *args: _P.args, **kwargs: _P.kwargs) -> Callable[_P, _T]: ... # type: ignore +def register(func: Callable[_P, _T], *args: _P.args, **kwargs: _P.kwargs) -> Callable[_P, _T]: ... def unregister(func: Callable[..., Any]) -> None: ... diff --git a/mypy/typeshed/stdlib/audioop.pyi b/mypy/typeshed/stdlib/audioop.pyi index 321bfe55c4b00..b08731b85b0ba 100644 --- a/mypy/typeshed/stdlib/audioop.pyi +++ b/mypy/typeshed/stdlib/audioop.pyi @@ -1,7 +1,5 @@ -from typing import Tuple - -AdpcmState = Tuple[int, int] -RatecvState = Tuple[int, Tuple[Tuple[int, int], ...]] +AdpcmState = tuple[int, int] +RatecvState = tuple[int, tuple[tuple[int, int], ...]] class error(Exception): ... diff --git a/mypy/typeshed/stdlib/bdb.pyi b/mypy/typeshed/stdlib/bdb.pyi index 1d03ddf19a0e1..3f6b6d3d8b7b7 100644 --- a/mypy/typeshed/stdlib/bdb.pyi +++ b/mypy/typeshed/stdlib/bdb.pyi @@ -1,9 +1,9 @@ from types import CodeType, FrameType, TracebackType -from typing import IO, Any, Callable, Iterable, Mapping, SupportsInt, Tuple, Type, TypeVar +from typing import IO, Any, Callable, Iterable, Mapping, SupportsInt, Type, TypeVar _T = TypeVar("_T") _TraceDispatch = Callable[[FrameType, str, Any], Any] # TODO: Recursive type -_ExcInfo = Tuple[Type[BaseException], BaseException, FrameType] +_ExcInfo = tuple[Type[BaseException], BaseException, FrameType] GENERATOR_AND_COROUTINE_FLAGS: int diff --git a/mypy/typeshed/stdlib/binascii.pyi b/mypy/typeshed/stdlib/binascii.pyi index 962f5666b2848..317bb9979b923 100644 --- a/mypy/typeshed/stdlib/binascii.pyi +++ b/mypy/typeshed/stdlib/binascii.pyi @@ -12,10 +12,13 @@ def a2b_base64(__data: str | bytes) -> bytes: ... def b2a_base64(__data: bytes, *, newline: bool = ...) -> bytes: ... def a2b_qp(data: str | bytes, header: bool = ...) -> bytes: ... def b2a_qp(data: bytes, quotetabs: bool = ..., istext: bool = ..., header: bool = ...) -> bytes: ... -def a2b_hqx(__data: str | bytes) -> bytes: ... -def rledecode_hqx(__data: bytes) -> bytes: ... -def rlecode_hqx(__data: bytes) -> bytes: ... -def b2a_hqx(__data: bytes) -> bytes: ... + +if sys.version_info < (3, 11): + def a2b_hqx(__data: str | bytes) -> bytes: ... + def rledecode_hqx(__data: bytes) -> bytes: ... + def rlecode_hqx(__data: bytes) -> bytes: ... + def b2a_hqx(__data: bytes) -> bytes: ... + def crc_hqx(__data: bytes, __crc: int) -> int: ... def crc32(__data: bytes, __crc: int = ...) -> int: ... def b2a_hex(__data: bytes) -> bytes: ... diff --git a/mypy/typeshed/stdlib/binhex.pyi b/mypy/typeshed/stdlib/binhex.pyi index 02d094faf9232..4e295b8ed9031 100644 --- a/mypy/typeshed/stdlib/binhex.pyi +++ b/mypy/typeshed/stdlib/binhex.pyi @@ -1,4 +1,4 @@ -from typing import IO, Any, Tuple, Union +from typing import IO, Any, Union class Error(Exception): ... @@ -12,7 +12,7 @@ class FInfo: Creator: str Flags: int -_FileInfoTuple = Tuple[str, FInfo, int, int] +_FileInfoTuple = tuple[str, FInfo, int, int] _FileHandleUnion = Union[str, IO[bytes]] def getfileinfo(name: str) -> _FileInfoTuple: ... diff --git a/mypy/typeshed/stdlib/builtins.pyi b/mypy/typeshed/stdlib/builtins.pyi index 1b2d3db12c3f9..5547afc217f64 100644 --- a/mypy/typeshed/stdlib/builtins.pyi +++ b/mypy/typeshed/stdlib/builtins.pyi @@ -23,13 +23,11 @@ from _typeshed import ( SupportsWrite, ) from io import BufferedRandom, BufferedReader, BufferedWriter, FileIO, TextIOWrapper -from types import CodeType, TracebackType +from types import CodeType, TracebackType, _Cell from typing import ( IO, AbstractSet, Any, - AsyncIterable, - AsyncIterator, BinaryIO, ByteString, Callable, @@ -51,7 +49,6 @@ from typing import ( SupportsFloat, SupportsInt, SupportsRound, - Tuple, Type, TypeVar, Union, @@ -76,6 +73,14 @@ _T5 = TypeVar("_T5") _TT = TypeVar("_TT", bound="type") _TBE = TypeVar("_TBE", bound="BaseException") _R = TypeVar("_R") # Return-type TypeVar +_SupportsNextT = TypeVar("_SupportsNextT", bound=SupportsNext[Any], covariant=True) +_SupportsAnextT = TypeVar("_SupportsAnextT", bound=SupportsAnext[Any], covariant=True) + +class _SupportsIter(Protocol[_T_co]): + def __iter__(self) -> _T_co: ... + +class _SupportsAiter(Protocol[_T_co]): + def __aiter__(self) -> _T_co: ... class object: __doc__: str | None @@ -102,11 +107,11 @@ class object: def __sizeof__(self) -> int: ... # return type of pickle methods is rather hard to express in the current type system # see #6661 and https://docs.python.org/3/library/pickle.html#object.__reduce__ - def __reduce__(self) -> str | Tuple[Any, ...]: ... + def __reduce__(self) -> str | tuple[Any, ...]: ... if sys.version_info >= (3, 8): - def __reduce_ex__(self, __protocol: SupportsIndex) -> str | Tuple[Any, ...]: ... + def __reduce_ex__(self, __protocol: SupportsIndex) -> str | tuple[Any, ...]: ... else: - def __reduce_ex__(self, __protocol: int) -> str | Tuple[Any, ...]: ... + def __reduce_ex__(self, __protocol: int) -> str | tuple[Any, ...]: ... def __dir__(self) -> Iterable[str]: ... def __init_subclass__(cls) -> None: ... @@ -133,16 +138,16 @@ class classmethod(Generic[_R]): # Special, only valid as a decorator. __qualname__: str __wrapped__: Callable[..., _R] -class type(object): +class type: __base__: type - __bases__: Tuple[type, ...] + __bases__: tuple[type, ...] __basicsize__: int __dict__: dict[str, Any] __dictoffset__: int __flags__: int __itemsize__: int __module__: str - __mro__: Tuple[type, ...] + __mro__: tuple[type, ...] __name__: str __qualname__: str __text_signature__: str | None @@ -150,11 +155,11 @@ class type(object): @overload def __init__(self, __o: object) -> None: ... @overload - def __init__(self, __name: str, __bases: Tuple[type, ...], __dict: dict[str, Any], **kwds: Any) -> None: ... + def __init__(self, __name: str, __bases: tuple[type, ...], __dict: dict[str, Any], **kwds: Any) -> None: ... @overload def __new__(cls, __o: object) -> type: ... @overload - def __new__(cls: Type[_TT], __name: str, __bases: Tuple[type, ...], __namespace: dict[str, Any], **kwds: Any) -> _TT: ... + def __new__(cls: Type[_TT], __name: str, __bases: tuple[type, ...], __namespace: dict[str, Any], **kwds: Any) -> _TT: ... def __call__(self, *args: Any, **kwds: Any) -> Any: ... def __subclasses__(self: _TT) -> list[_TT]: ... # Note: the documentation doesn't specify what the return type is, the standard @@ -163,12 +168,12 @@ class type(object): def __instancecheck__(self, __instance: Any) -> bool: ... def __subclasscheck__(self, __subclass: type) -> bool: ... @classmethod - def __prepare__(metacls, __name: str, __bases: Tuple[type, ...], **kwds: Any) -> Mapping[str, object]: ... + def __prepare__(metacls, __name: str, __bases: tuple[type, ...], **kwds: Any) -> Mapping[str, object]: ... if sys.version_info >= (3, 10): def __or__(self, __t: Any) -> types.UnionType: ... def __ror__(self, __t: Any) -> types.UnionType: ... -class super(object): +class super: @overload def __init__(self, __t: Any, __obj: Any) -> None: ... @overload @@ -347,6 +352,8 @@ class complex: def __abs__(self) -> float: ... def __hash__(self) -> int: ... def __bool__(self) -> bool: ... + if sys.version_info >= (3, 11): + def __complex__(self) -> complex: ... class _FormatMapMapping(Protocol): def __getitem__(self, __key: str) -> Any: ... @@ -362,7 +369,7 @@ class str(Sequence[str]): def count(self, x: str, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...) -> int: ... def encode(self, encoding: str = ..., errors: str = ...) -> bytes: ... def endswith( - self, __suffix: str | Tuple[str, ...], __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... + self, __suffix: str | tuple[str, ...], __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> bool: ... if sys.version_info >= (3, 8): def expandtabs(self, tabsize: SupportsIndex = ...) -> str: ... @@ -403,7 +410,7 @@ class str(Sequence[str]): def split(self, sep: str | None = ..., maxsplit: SupportsIndex = ...) -> list[str]: ... def splitlines(self, keepends: bool = ...) -> list[str]: ... def startswith( - self, __prefix: str | Tuple[str, ...], __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... + self, __prefix: str | tuple[str, ...], __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> bool: ... def strip(self, __chars: str | None = ...) -> str: ... def swapcase(self) -> str: ... @@ -422,7 +429,7 @@ class str(Sequence[str]): def __contains__(self, __o: str) -> bool: ... # type: ignore[override] def __eq__(self, __x: object) -> bool: ... def __ge__(self, __x: str) -> bool: ... - def __getitem__(self, __i: int | slice) -> str: ... + def __getitem__(self, __i: SupportsIndex | slice) -> str: ... def __gt__(self, __x: str) -> bool: ... def __hash__(self) -> int: ... def __iter__(self) -> Iterator[str]: ... @@ -455,7 +462,7 @@ class bytes(ByteString): ) -> int: ... def decode(self, encoding: str = ..., errors: str = ...) -> str: ... def endswith( - self, __suffix: bytes | Tuple[bytes, ...], __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... + self, __suffix: bytes | tuple[bytes, ...], __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> bool: ... if sys.version_info >= (3, 8): def expandtabs(self, tabsize: SupportsIndex = ...) -> bytes: ... @@ -502,7 +509,7 @@ class bytes(ByteString): def split(self, sep: bytes | None = ..., maxsplit: SupportsIndex = ...) -> list[bytes]: ... def splitlines(self, keepends: bool = ...) -> list[bytes]: ... def startswith( - self, __prefix: bytes | Tuple[bytes, ...], __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... + self, __prefix: bytes | tuple[bytes, ...], __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> bool: ... def strip(self, __bytes: bytes | None = ...) -> bytes: ... def swapcase(self) -> bytes: ... @@ -536,6 +543,8 @@ class bytes(ByteString): def __gt__(self, __x: bytes) -> bool: ... def __ge__(self, __x: bytes) -> bool: ... def __getnewargs__(self) -> tuple[bytes]: ... + if sys.version_info >= (3, 11): + def __bytes__(self) -> bytes: ... class bytearray(MutableSequence[int], ByteString): @overload @@ -555,7 +564,7 @@ class bytearray(MutableSequence[int], ByteString): def copy(self) -> bytearray: ... def decode(self, encoding: str = ..., errors: str = ...) -> str: ... def endswith( - self, __suffix: bytes | Tuple[bytes, ...], __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... + self, __suffix: bytes | tuple[bytes, ...], __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> bool: ... if sys.version_info >= (3, 8): def expandtabs(self, tabsize: SupportsIndex = ...) -> bytearray: ... @@ -604,7 +613,7 @@ class bytearray(MutableSequence[int], ByteString): def split(self, sep: bytes | None = ..., maxsplit: SupportsIndex = ...) -> list[bytearray]: ... def splitlines(self, keepends: bool = ...) -> list[bytearray]: ... def startswith( - self, __prefix: bytes | Tuple[bytes, ...], __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... + self, __prefix: bytes | tuple[bytes, ...], __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> bool: ... def strip(self, __bytes: bytes | None = ...) -> bytearray: ... def swapcase(self) -> bytearray: ... @@ -649,9 +658,9 @@ class bytearray(MutableSequence[int], ByteString): class memoryview(Sized, Sequence[int]): format: str itemsize: int - shape: Tuple[int, ...] | None - strides: Tuple[int, ...] | None - suboffsets: Tuple[int, ...] | None + shape: tuple[int, ...] | None + strides: tuple[int, ...] | None + suboffsets: tuple[int, ...] | None readonly: bool ndim: int @@ -665,7 +674,7 @@ class memoryview(Sized, Sequence[int]): def __exit__( self, __exc_type: Type[BaseException] | None, __exc_val: BaseException | None, __exc_tb: TracebackType | None ) -> None: ... - def cast(self, format: str, shape: list[int] | Tuple[int, ...] = ...) -> memoryview: ... + def cast(self, format: str, shape: list[int] | tuple[int, ...] = ...) -> memoryview: ... @overload def __getitem__(self, __i: SupportsIndex) -> int: ... @overload @@ -720,7 +729,7 @@ class bool(int): def __getnewargs__(self) -> tuple[int]: ... @final -class slice(object): +class slice: start: Any step: Any stop: Any @@ -736,48 +745,57 @@ class tuple(Sequence[_T_co], Generic[_T_co]): def __len__(self) -> int: ... def __contains__(self, __x: object) -> bool: ... @overload - def __getitem__(self, __x: int) -> _T_co: ... + def __getitem__(self, __x: SupportsIndex) -> _T_co: ... @overload - def __getitem__(self, __x: slice) -> Tuple[_T_co, ...]: ... + def __getitem__(self, __x: slice) -> tuple[_T_co, ...]: ... def __iter__(self) -> Iterator[_T_co]: ... - def __lt__(self, __x: Tuple[_T_co, ...]) -> bool: ... - def __le__(self, __x: Tuple[_T_co, ...]) -> bool: ... - def __gt__(self, __x: Tuple[_T_co, ...]) -> bool: ... - def __ge__(self, __x: Tuple[_T_co, ...]) -> bool: ... + def __lt__(self, __x: tuple[_T_co, ...]) -> bool: ... + def __le__(self, __x: tuple[_T_co, ...]) -> bool: ... + def __gt__(self, __x: tuple[_T_co, ...]) -> bool: ... + def __ge__(self, __x: tuple[_T_co, ...]) -> bool: ... @overload - def __add__(self, __x: Tuple[_T_co, ...]) -> Tuple[_T_co, ...]: ... + def __add__(self, __x: tuple[_T_co, ...]) -> tuple[_T_co, ...]: ... @overload - def __add__(self, __x: Tuple[_T, ...]) -> Tuple[_T_co | _T, ...]: ... - def __mul__(self, __n: SupportsIndex) -> Tuple[_T_co, ...]: ... - def __rmul__(self, __n: SupportsIndex) -> Tuple[_T_co, ...]: ... + def __add__(self, __x: tuple[_T, ...]) -> tuple[_T_co | _T, ...]: ... + def __mul__(self, __n: SupportsIndex) -> tuple[_T_co, ...]: ... + def __rmul__(self, __n: SupportsIndex) -> tuple[_T_co, ...]: ... def count(self, __value: Any) -> int: ... def index(self, __value: Any, __start: SupportsIndex = ..., __stop: SupportsIndex = ...) -> int: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, __item: Any) -> GenericAlias: ... +# Doesn't exist at runtime, but deleting this breaks mypy. See #2999 +@final class function: - # TODO not defined in builtins! - __name__: str - __module__: str + # Make sure this class definition stays roughly in line with `types.FunctionType` + __closure__: tuple[_Cell, ...] | None __code__: CodeType + __defaults__: tuple[Any, ...] | None + __dict__: dict[str, Any] + __globals__: dict[str, Any] + __name__: str __qualname__: str __annotations__: dict[str, Any] + __kwdefaults__: dict[str, Any] + __module__: str + # mypy uses `builtins.function.__get__` to represent methods, properties, and getset_descriptors so we type the return as Any. + def __get__(self, obj: object | None, type: type | None = ...) -> Any: ... class list(MutableSequence[_T], Generic[_T]): @overload def __init__(self) -> None: ... @overload def __init__(self, __iterable: Iterable[_T]) -> None: ... - def clear(self) -> None: ... def copy(self) -> list[_T]: ... def append(self, __object: _T) -> None: ... def extend(self, __iterable: Iterable[_T]) -> None: ... def pop(self, __index: SupportsIndex = ...) -> _T: ... + # Signature of `list.index` should be kept in line with `collections.UserList.index()` def index(self, __value: _T, __start: SupportsIndex = ..., __stop: SupportsIndex = ...) -> int: ... def count(self, __value: _T) -> int: ... def insert(self, __index: SupportsIndex, __object: _T) -> None: ... def remove(self, __value: _T) -> None: ... - def reverse(self) -> None: ... + # Signature of `list.sort` should be kept inline with `collections.UserList.sort()` @overload def sort(self: list[SupportsRichComparisonT], *, key: None = ..., reverse: bool = ...) -> None: ... @overload @@ -810,6 +828,7 @@ class list(MutableSequence[_T], Generic[_T]): def __class_getitem__(cls, __item: Any) -> GenericAlias: ... class dict(MutableMapping[_KT, _VT], Generic[_KT, _VT]): + # __init__ should be kept roughly in line with `collections.UserDict.__init__`, which has similar semantics @overload def __init__(self: dict[_KT, _VT]) -> None: ... @overload @@ -823,19 +842,13 @@ class dict(MutableMapping[_KT, _VT], Generic[_KT, _VT]): @overload def __init__(self: dict[str, str], __iterable: Iterable[list[str]]) -> None: ... def __new__(cls: Type[_T1], *args: Any, **kwargs: Any) -> _T1: ... - def clear(self) -> None: ... def copy(self) -> dict[_KT, _VT]: ... - def popitem(self) -> tuple[_KT, _VT]: ... - def setdefault(self, __key: _KT, __default: _VT = ...) -> _VT: ... - @overload - def update(self, __m: Mapping[_KT, _VT], **kwargs: _VT) -> None: ... - @overload - def update(self, __m: Iterable[tuple[_KT, _VT]], **kwargs: _VT) -> None: ... - @overload - def update(self, **kwargs: _VT) -> None: ... def keys(self) -> dict_keys[_KT, _VT]: ... def values(self) -> dict_values[_KT, _VT]: ... def items(self) -> dict_items[_KT, _VT]: ... + # Signature of `dict.fromkeys` should be kept identical to `fromkeys` methods of `OrderedDict`/`ChainMap`/`UserDict` in `collections` + # TODO: the true signature of `dict.fromkeys` is not expressable in the current type system. + # See #3800 & https://github.com/python/typing/issues/548#issuecomment-683336963. @classmethod @overload def fromkeys(cls, __iterable: Iterable[_T], __value: None = ...) -> dict[_T, Any | None]: ... @@ -860,7 +873,6 @@ class dict(MutableMapping[_KT, _VT], Generic[_KT, _VT]): class set(MutableSet[_T], Generic[_T]): def __init__(self, __iterable: Iterable[_T] = ...) -> None: ... def add(self, __element: _T) -> None: ... - def clear(self) -> None: ... def copy(self) -> set[_T]: ... def difference(self, *s: Iterable[Any]) -> set[_T]: ... def difference_update(self, *s: Iterable[Any]) -> None: ... @@ -870,7 +882,6 @@ class set(MutableSet[_T], Generic[_T]): def isdisjoint(self, __s: Iterable[Any]) -> bool: ... def issubset(self, __s: Iterable[Any]) -> bool: ... def issuperset(self, __s: Iterable[Any]) -> bool: ... - def pop(self) -> _T: ... def remove(self, __element: _T) -> None: ... def symmetric_difference(self, __s: Iterable[_T]) -> set[_T]: ... def symmetric_difference_update(self, __s: Iterable[_T]) -> None: ... @@ -921,7 +932,7 @@ class frozenset(AbstractSet[_T_co], Generic[_T_co]): if sys.version_info >= (3, 9): def __class_getitem__(cls, __item: Any) -> GenericAlias: ... -class enumerate(Iterator[Tuple[int, _T]], Generic[_T]): +class enumerate(Iterator[tuple[int, _T]], Generic[_T]): def __init__(self, iterable: Iterable[_T], start: int = ...) -> None: ... def __iter__(self) -> Iterator[tuple[int, _T]]: ... def __next__(self) -> tuple[int, _T]: ... @@ -949,7 +960,7 @@ class range(Sequence[int]): def __repr__(self) -> str: ... def __reversed__(self) -> Iterator[int]: ... -class property(object): +class property: fget: Callable[[Any], Any] | None fset: Callable[[Any, Any], None] | None fdel: Callable[[Any], None] | None @@ -995,7 +1006,7 @@ class _PathLike(Protocol[_AnyStr_co]): def __fspath__(self) -> _AnyStr_co: ... if sys.version_info >= (3, 10): - def aiter(__iterable: AsyncIterable[_T]) -> AsyncIterator[_T]: ... + def aiter(__async_iterable: _SupportsAiter[_SupportsAnextT]) -> _SupportsAnextT: ... @overload async def anext(__i: SupportsAnext[_T]) -> _T: ... @overload @@ -1073,12 +1084,12 @@ def getattr(__o: object, __name: str, __default: _T) -> Any | _T: ... def globals() -> dict[str, Any]: ... def hasattr(__obj: object, __name: str) -> bool: ... def hash(__obj: object) -> int: ... -def help(*args: Any, **kwds: Any) -> None: ... +def help(request: object = ...) -> None: ... def hex(__number: int | SupportsIndex) -> str: ... def id(__obj: object) -> int: ... def input(__prompt: object = ...) -> str: ... @overload -def iter(__iterable: Iterable[_T]) -> Iterator[_T]: ... +def iter(__iterable: _SupportsIter[_SupportsNextT]) -> _SupportsNextT: ... @overload def iter(__function: Callable[[], _T | None], __sentinel: None) -> Iterator[_T]: ... @overload @@ -1087,15 +1098,15 @@ def iter(__function: Callable[[], _T], __sentinel: object) -> Iterator[_T]: ... # We need recursive types to express the type of the second argument to `isinstance` properly, hence the use of `Any` if sys.version_info >= (3, 10): def isinstance( - __obj: object, __class_or_tuple: type | types.UnionType | Tuple[type | types.UnionType | Tuple[Any, ...], ...] + __obj: object, __class_or_tuple: type | types.UnionType | tuple[type | types.UnionType | tuple[Any, ...], ...] ) -> bool: ... def issubclass( - __cls: type, __class_or_tuple: type | types.UnionType | Tuple[type | types.UnionType | Tuple[Any, ...], ...] + __cls: type, __class_or_tuple: type | types.UnionType | tuple[type | types.UnionType | tuple[Any, ...], ...] ) -> bool: ... else: - def isinstance(__obj: object, __class_or_tuple: type | Tuple[type | Tuple[Any, ...], ...]) -> bool: ... - def issubclass(__cls: type, __class_or_tuple: type | Tuple[type | Tuple[Any, ...], ...]) -> bool: ... + def isinstance(__obj: object, __class_or_tuple: type | tuple[type | tuple[Any, ...], ...]) -> bool: ... + def issubclass(__cls: type, __class_or_tuple: type | tuple[type | tuple[Any, ...], ...]) -> bool: ... def len(__obj: Sized) -> int: ... def license() -> None: ... @@ -1382,19 +1393,21 @@ def round(number: SupportsRound[_T], ndigits: SupportsIndex) -> _T: ... # for why arg 3 of `setattr` should be annotated with `Any` and not `object` def setattr(__obj: object, __name: str, __value: Any) -> None: ... @overload -def sorted(__iterable: Iterable[SupportsRichComparisonT], *, key: None = ..., reverse: bool = ...) -> list[SupportsRichComparisonT]: ... +def sorted( + __iterable: Iterable[SupportsRichComparisonT], *, key: None = ..., reverse: bool = ... +) -> list[SupportsRichComparisonT]: ... @overload def sorted(__iterable: Iterable[_T], *, key: Callable[[_T], SupportsRichComparison], reverse: bool = ...) -> list[_T]: ... if sys.version_info >= (3, 8): @overload - def sum(__iterable: Iterable[_T]) -> _T | int: ... + def sum(__iterable: Iterable[_T]) -> _T | Literal[0]: ... @overload def sum(__iterable: Iterable[_T], start: _S) -> _T | _S: ... else: @overload - def sum(__iterable: Iterable[_T]) -> _T | int: ... + def sum(__iterable: Iterable[_T]) -> _T | Literal[0]: ... @overload def sum(__iterable: Iterable[_T], __start: _S) -> _T | _S: ... @@ -1444,7 +1457,7 @@ class zip(Iterator[_T_co], Generic[_T_co]): __iter6: Iterable[Any], *iterables: Iterable[Any], strict: bool = ..., - ) -> zip[Tuple[Any, ...]]: ... + ) -> zip[tuple[Any, ...]]: ... else: @overload def __new__(cls, __iter1: Iterable[_T1]) -> zip[tuple[_T1]]: ... @@ -1475,7 +1488,7 @@ class zip(Iterator[_T_co], Generic[_T_co]): __iter5: Iterable[Any], __iter6: Iterable[Any], *iterables: Iterable[Any], - ) -> zip[Tuple[Any, ...]]: ... + ) -> zip[tuple[Any, ...]]: ... def __iter__(self) -> Iterator[_T_co]: ... def __next__(self) -> _T_co: ... @@ -1496,12 +1509,14 @@ class ellipsis: ... Ellipsis: ellipsis -class BaseException(object): - args: Tuple[Any, ...] +class BaseException: + args: tuple[Any, ...] __cause__: BaseException | None __context__: BaseException | None __suppress_context__: bool __traceback__: TracebackType | None + if sys.version_info >= (3, 11): + __note__: str | None def __init__(self, *args: object) -> None: ... def __str__(self) -> str: ... def __repr__(self) -> str: ... @@ -1624,7 +1639,14 @@ class UnicodeEncodeError(UnicodeError): reason: str def __init__(self, __encoding: str, __object: str, __start: int, __end: int, __reason: str) -> None: ... -class UnicodeTranslateError(UnicodeError): ... +class UnicodeTranslateError(UnicodeError): + encoding: None + object: str + start: int + end: int + reason: str + def __init__(self, __object: str, __start: int, __end: int, __reason: str) -> None: ... + class Warning(Exception): ... class UserWarning(Warning): ... class DeprecationWarning(Warning): ... @@ -1639,3 +1661,19 @@ class ResourceWarning(Warning): ... if sys.version_info >= (3, 10): class EncodingWarning(Warning): ... + +if sys.version_info >= (3, 11): + _SplitCondition = type[BaseException] | tuple[type[BaseException, ...]] | Callable[[BaseException], bool] + class BaseExceptionGroup(BaseException): + def __new__(cls, __message: str, __exceptions: Sequence[BaseException]) -> BaseExceptionGroup | ExceptionGroup: ... + @property + def message(self) -> str: ... + @property + def exceptions(self) -> Sequence[BaseException]: ... + def subgroup(self: Self, __condition: _SplitCondition) -> Self | None: ... + def split(self: Self, __condition: _SplitCondition) -> tuple[Self | None, Self | None]: ... + def derive(self: Self, __excs: Sequence[BaseException]) -> Self: ... + class ExceptionGroup(BaseExceptionGroup, Exception): + def __new__(cls, __message: str, exceptions: Sequence[Exception]) -> ExceptionGroup: ... + @property + def exceptions(self) -> Sequence[Exception]: ... diff --git a/mypy/typeshed/stdlib/bz2.pyi b/mypy/typeshed/stdlib/bz2.pyi index c49832759fa8a..6aeaa3da4c60d 100644 --- a/mypy/typeshed/stdlib/bz2.pyi +++ b/mypy/typeshed/stdlib/bz2.pyi @@ -80,6 +80,15 @@ def open( errors: str | None = ..., newline: str | None = ..., ) -> TextIO: ... +@overload +def open( + filename: StrOrBytesPath | _ReadableFileobj | _WritableFileobj, + mode: str, + compresslevel: int = ..., + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., +) -> BZ2File | TextIO: ... class BZ2File(BaseStream, IO[bytes]): def __enter__(self: Self) -> Self: ... @@ -111,7 +120,7 @@ class BZ2File(BaseStream, IO[bytes]): ) -> None: ... def read(self, size: int | None = ...) -> bytes: ... def read1(self, size: int = ...) -> bytes: ... - def readline(self, size: SupportsIndex = ...) -> bytes: ... # type: ignore + def readline(self, size: SupportsIndex = ...) -> bytes: ... # type: ignore[override] def readinto(self, b: WriteableBuffer) -> int: ... def readlines(self, size: SupportsIndex = ...) -> list[bytes]: ... def seek(self, offset: int, whence: int = ...) -> int: ... @@ -119,13 +128,13 @@ class BZ2File(BaseStream, IO[bytes]): def writelines(self, seq: Iterable[ReadableBuffer]) -> None: ... @final -class BZ2Compressor(object): +class BZ2Compressor: def __init__(self, compresslevel: int = ...) -> None: ... def compress(self, __data: bytes) -> bytes: ... def flush(self) -> bytes: ... @final -class BZ2Decompressor(object): +class BZ2Decompressor: def decompress(self, data: bytes, max_length: int = ...) -> bytes: ... @property def eof(self) -> bool: ... diff --git a/mypy/typeshed/stdlib/cProfile.pyi b/mypy/typeshed/stdlib/cProfile.pyi index f4a7ab50cc110..e79524aa793e4 100644 --- a/mypy/typeshed/stdlib/cProfile.pyi +++ b/mypy/typeshed/stdlib/cProfile.pyi @@ -1,7 +1,7 @@ import sys from _typeshed import Self, StrOrBytesPath from types import CodeType -from typing import Any, Callable, Tuple, TypeVar +from typing import Any, Callable, TypeVar def run(statement: str, filename: str | None = ..., sort: str | int = ...) -> None: ... def runctx( @@ -9,7 +9,7 @@ def runctx( ) -> None: ... _T = TypeVar("_T") -_Label = Tuple[str, int, str] +_Label = tuple[str, int, str] class Profile: stats: dict[_Label, tuple[int, int, int, int, dict[_Label, tuple[int, int, int, int]]]] # undocumented diff --git a/mypy/typeshed/stdlib/calendar.pyi b/mypy/typeshed/stdlib/calendar.pyi index 26073fb7281ba..aa37928b87b12 100644 --- a/mypy/typeshed/stdlib/calendar.pyi +++ b/mypy/typeshed/stdlib/calendar.pyi @@ -1,9 +1,9 @@ import datetime import sys from time import struct_time -from typing import Any, Iterable, Optional, Sequence, Tuple +from typing import Any, Iterable, Optional, Sequence -_LocaleType = Tuple[Optional[str], Optional[str]] +_LocaleType = tuple[Optional[str], Optional[str]] class IllegalMonthError(ValueError): def __init__(self, month: int) -> None: ... @@ -97,7 +97,7 @@ c: TextCalendar def setfirstweekday(firstweekday: int) -> None: ... def format(cols: int, colwidth: int = ..., spacing: int = ...) -> str: ... def formatstring(cols: int, colwidth: int = ..., spacing: int = ...) -> str: ... -def timegm(tuple: Tuple[int, ...] | struct_time) -> int: ... +def timegm(tuple: tuple[int, ...] | struct_time) -> int: ... # Data attributes day_name: Sequence[str] diff --git a/mypy/typeshed/stdlib/cgi.pyi b/mypy/typeshed/stdlib/cgi.pyi index 3821de46ed754..c2c3ac261010a 100644 --- a/mypy/typeshed/stdlib/cgi.pyi +++ b/mypy/typeshed/stdlib/cgi.pyi @@ -57,7 +57,7 @@ class MiniFieldStorage: _list = list -class FieldStorage(object): +class FieldStorage: FieldStorageClass: _type | None keep_blank_values: int strict_parsing: int diff --git a/mypy/typeshed/stdlib/cgitb.pyi b/mypy/typeshed/stdlib/cgitb.pyi index 7576740fc1c03..a8f3912aa04cb 100644 --- a/mypy/typeshed/stdlib/cgitb.pyi +++ b/mypy/typeshed/stdlib/cgitb.pyi @@ -1,8 +1,8 @@ from _typeshed import StrOrBytesPath from types import FrameType, TracebackType -from typing import IO, Any, Callable, Optional, Tuple, Type +from typing import IO, Any, Callable, Optional, Type -_ExcInfo = Tuple[Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType]] +_ExcInfo = tuple[Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType]] def reset() -> str: ... # undocumented def small(text: str) -> str: ... # undocumented diff --git a/mypy/typeshed/stdlib/codecs.pyi b/mypy/typeshed/stdlib/codecs.pyi index ebd6911c3e630..e08672e514284 100644 --- a/mypy/typeshed/stdlib/codecs.pyi +++ b/mypy/typeshed/stdlib/codecs.pyi @@ -2,9 +2,14 @@ import sys import types from _typeshed import Self from abc import abstractmethod -from typing import IO, Any, BinaryIO, Callable, Generator, Iterable, Iterator, Protocol, TextIO, Tuple, Type, TypeVar, overload +from typing import IO, Any, BinaryIO, Callable, Generator, Iterable, Iterator, Protocol, TextIO, Type, TypeVar, overload from typing_extensions import Literal +BOM32_BE: bytes +BOM32_LE: bytes +BOM64_BE: bytes +BOM64_LE: bytes + # TODO: this only satisfies the most common interface, where # bytes is the raw form and str is the cooked form. # In the long run, both should become template parameters maybe? @@ -53,11 +58,11 @@ _BytesToBytesEncodingT = Literal[ @overload def encode(obj: bytes, encoding: _BytesToBytesEncodingT, errors: str = ...) -> bytes: ... @overload -def encode(obj: str, encoding: Literal["rot13", "rot_13"] = ..., errors: str = ...) -> str: ... # type: ignore +def encode(obj: str, encoding: Literal["rot13", "rot_13"] = ..., errors: str = ...) -> str: ... # type: ignore[misc] @overload def encode(obj: str, encoding: str = ..., errors: str = ...) -> bytes: ... @overload -def decode(obj: bytes, encoding: _BytesToBytesEncodingT, errors: str = ...) -> bytes: ... # type: ignore +def decode(obj: bytes, encoding: _BytesToBytesEncodingT, errors: str = ...) -> bytes: ... # type: ignore[misc] @overload def decode(obj: str, encoding: Literal["rot13", "rot_13"] = ..., errors: str = ...) -> str: ... @overload @@ -66,7 +71,7 @@ def lookup(__encoding: str) -> CodecInfo: ... def utf_16_be_decode(__data: bytes, __errors: str | None = ..., __final: bool = ...) -> tuple[str, int]: ... # undocumented def utf_16_be_encode(__str: str, __errors: str | None = ...) -> tuple[bytes, int]: ... # undocumented -class CodecInfo(Tuple[_Encoder, _Decoder, _StreamReader, _StreamWriter]): +class CodecInfo(tuple[_Encoder, _Decoder, _StreamReader, _StreamWriter]): @property def encode(self) -> _Encoder: ... @property diff --git a/mypy/typeshed/stdlib/collections/__init__.pyi b/mypy/typeshed/stdlib/collections/__init__.pyi index 66a76941beee7..adcdf29fa6908 100644 --- a/mypy/typeshed/stdlib/collections/__init__.pyi +++ b/mypy/typeshed/stdlib/collections/__init__.pyi @@ -1,8 +1,11 @@ import sys from _collections_abc import dict_items, dict_keys, dict_values -from _typeshed import Self -from typing import Any, Dict, Generic, NoReturn, Tuple, Type, TypeVar, overload -from typing_extensions import final +from _typeshed import Self, SupportsKeysAndGetItem, SupportsRichComparison, SupportsRichComparisonT +from typing import Any, Generic, NoReturn, Type, TypeVar, overload +from typing_extensions import SupportsIndex, final + +if sys.version_info >= (3, 9): + from types import GenericAlias if sys.version_info >= (3, 10): from typing import Callable, Iterable, Iterator, Mapping, MutableMapping, MutableSequence, Reversible, Sequence @@ -25,16 +28,26 @@ if sys.version_info >= (3, 7): rename: bool = ..., module: str | None = ..., defaults: Iterable[Any] | None = ..., - ) -> Type[Tuple[Any, ...]]: ... + ) -> Type[tuple[Any, ...]]: ... else: def namedtuple( typename: str, field_names: str | Iterable[str], *, verbose: bool = ..., rename: bool = ..., module: str | None = ... - ) -> Type[Tuple[Any, ...]]: ... + ) -> Type[tuple[Any, ...]]: ... -class UserDict(MutableMapping[_KT, _VT]): +class UserDict(MutableMapping[_KT, _VT], Generic[_KT, _VT]): data: dict[_KT, _VT] - def __init__(self, __dict: Mapping[_KT, _VT] | None = ..., **kwargs: _VT) -> None: ... + # __init__ should be kept roughly in line with `dict.__init__`, which has the same semantics + @overload + def __init__(self: UserDict[_KT, _VT], __dict: None = ...) -> None: ... + @overload + def __init__(self: UserDict[str, _VT], __dict: None = ..., **kwargs: _VT) -> None: ... + @overload + def __init__(self, __dict: SupportsKeysAndGetItem[_KT, _VT], **kwargs: _VT) -> None: ... + @overload + def __init__(self, __iterable: Iterable[tuple[_KT, _VT]], **kwargs: _VT) -> None: ... + @overload + def __init__(self: UserDict[str, str], __iterable: Iterable[list[str]]) -> None: ... def __len__(self) -> int: ... def __getitem__(self, key: _KT) -> _VT: ... def __setitem__(self, key: _KT, item: _VT) -> None: ... @@ -42,27 +55,34 @@ class UserDict(MutableMapping[_KT, _VT]): def __iter__(self) -> Iterator[_KT]: ... def __contains__(self, key: object) -> bool: ... def copy(self: Self) -> Self: ... + # `UserDict.fromkeys` has the same semantics as `dict.fromkeys`, so should be kept in line with `dict.fromkeys`. + # TODO: Much like `dict.fromkeys`, the true signature of `UserDict.fromkeys` is inexpressable in the current type system. + # See #3800 & https://github.com/python/typing/issues/548#issuecomment-683336963. + @classmethod + @overload + def fromkeys(cls, iterable: Iterable[_T], value: None = ...) -> UserDict[_T, Any | None]: ... @classmethod - def fromkeys(cls: Type[Self], iterable: Iterable[_KT], value: _VT | None = ...) -> Self: ... + @overload + def fromkeys(cls, iterable: Iterable[_T], value: _S) -> UserDict[_T, _S]: ... class UserList(MutableSequence[_T]): data: list[_T] def __init__(self, initlist: Iterable[_T] | None = ...) -> None: ... - def __lt__(self, other: object) -> bool: ... - def __le__(self, other: object) -> bool: ... - def __gt__(self, other: object) -> bool: ... - def __ge__(self, other: object) -> bool: ... + def __lt__(self, other: list[_T] | UserList[_T]) -> bool: ... + def __le__(self, other: list[_T] | UserList[_T]) -> bool: ... + def __gt__(self, other: list[_T] | UserList[_T]) -> bool: ... + def __ge__(self, other: list[_T] | UserList[_T]) -> bool: ... def __contains__(self, item: object) -> bool: ... def __len__(self) -> int: ... @overload - def __getitem__(self, i: int) -> _T: ... + def __getitem__(self, i: SupportsIndex) -> _T: ... @overload def __getitem__(self: Self, i: slice) -> Self: ... @overload - def __setitem__(self, i: int, o: _T) -> None: ... + def __setitem__(self, i: SupportsIndex, o: _T) -> None: ... @overload def __setitem__(self, i: slice, o: Iterable[_T]) -> None: ... - def __delitem__(self, i: int | slice) -> None: ... + def __delitem__(self, i: SupportsIndex | slice) -> None: ... def __add__(self: _S, other: Iterable[_T]) -> _S: ... def __iadd__(self: _S, other: Iterable[_T]) -> _S: ... def __mul__(self: _S, n: int) -> _S: ... @@ -71,12 +91,15 @@ class UserList(MutableSequence[_T]): def insert(self, i: int, item: _T) -> None: ... def pop(self, i: int = ...) -> _T: ... def remove(self, item: _T) -> None: ... - def clear(self) -> None: ... def copy(self: _S) -> _S: ... def count(self, item: _T) -> int: ... - def index(self, item: _T, *args: Any) -> int: ... - def reverse(self) -> None: ... - def sort(self, *args: Any, **kwds: Any) -> None: ... + # All arguments are passed to `list.index` at runtime, so the signature should be kept in line with `list.index`. + def index(self, item: _T, __start: SupportsIndex = ..., __stop: SupportsIndex = ...) -> int: ... + # All arguments are passed to `list.sort` at runtime, so the signature should be kept in line with `list.sort`. + @overload + def sort(self: UserList[SupportsRichComparisonT], *, key: None = ..., reverse: bool = ...) -> None: ... + @overload + def sort(self, *, key: Callable[[_T], SupportsRichComparison], reverse: bool = ...) -> None: ... def extend(self, other: Iterable[_T]) -> None: ... _UserStringT = TypeVar("_UserStringT", bound=UserString) @@ -95,9 +118,9 @@ class UserString(Sequence[str]): def __contains__(self, char: object) -> bool: ... def __len__(self) -> int: ... # It should return a str to implement Sequence correctly, but it doesn't. - def __getitem__(self: _UserStringT, i: int | slice) -> _UserStringT: ... # type: ignore - def __iter__(self: _UserStringT) -> Iterator[_UserStringT]: ... # type: ignore - def __reversed__(self: _UserStringT) -> Iterator[_UserStringT]: ... # type: ignore + def __getitem__(self: _UserStringT, i: SupportsIndex | slice) -> _UserStringT: ... # type: ignore[override] + def __iter__(self: _UserStringT) -> Iterator[_UserStringT]: ... # type: ignore[override] + def __reversed__(self: _UserStringT) -> Iterator[_UserStringT]: ... # type: ignore[override] def __add__(self: _UserStringT, other: object) -> _UserStringT: ... def __mul__(self: _UserStringT, n: int) -> _UserStringT: ... def __mod__(self: _UserStringT, args: Any) -> _UserStringT: ... @@ -109,7 +132,7 @@ class UserString(Sequence[str]): def encode(self: UserString, encoding: str | None = ..., errors: str | None = ...) -> bytes: ... else: def encode(self: _UserStringT, encoding: str | None = ..., errors: str | None = ...) -> _UserStringT: ... - def endswith(self, suffix: str | Tuple[str, ...], start: int | None = ..., end: int | None = ...) -> bool: ... + def endswith(self, suffix: str | tuple[str, ...], start: int | None = ..., end: int | None = ...) -> bool: ... def expandtabs(self: _UserStringT, tabsize: int = ...) -> _UserStringT: ... def find(self, sub: str | UserString, start: int = ..., end: int = ...) -> int: ... def format(self, *args: Any, **kwds: Any) -> str: ... @@ -126,6 +149,8 @@ class UserString(Sequence[str]): def isspace(self) -> bool: ... def istitle(self) -> bool: ... def isupper(self) -> bool: ... + if sys.version_info >= (3, 7): + def isascii(self) -> bool: ... def join(self, seq: Iterable[str]) -> str: ... def ljust(self: _UserStringT, width: int, *args: Any) -> _UserStringT: ... def lower(self: _UserStringT) -> _UserStringT: ... @@ -149,7 +174,7 @@ class UserString(Sequence[str]): def split(self, sep: str | None = ..., maxsplit: int = ...) -> list[str]: ... def rsplit(self, sep: str | None = ..., maxsplit: int = ...) -> list[str]: ... def splitlines(self, keepends: bool = ...) -> list[str]: ... - def startswith(self, prefix: str | Tuple[str, ...], start: int | None = ..., end: int | None = ...) -> bool: ... + def startswith(self, prefix: str | tuple[str, ...], start: int | None = ..., end: int | None = ...) -> bool: ... def strip(self: _UserStringT, chars: str | None = ...) -> _UserStringT: ... def swapcase(self: _UserStringT) -> _UserStringT: ... def title(self: _UserStringT) -> _UserStringT: ... @@ -163,56 +188,44 @@ class deque(MutableSequence[_T], Generic[_T]): def __init__(self, iterable: Iterable[_T] = ..., maxlen: int | None = ...) -> None: ... def append(self, __x: _T) -> None: ... def appendleft(self, __x: _T) -> None: ... - def clear(self) -> None: ... def copy(self: _S) -> _S: ... def count(self, __x: _T) -> int: ... def extend(self, __iterable: Iterable[_T]) -> None: ... def extendleft(self, __iterable: Iterable[_T]) -> None: ... def insert(self, __i: int, __x: _T) -> None: ... def index(self, __x: _T, __start: int = ..., __stop: int = ...) -> int: ... - def pop(self) -> _T: ... # type: ignore + def pop(self) -> _T: ... # type: ignore[override] def popleft(self) -> _T: ... def remove(self, __value: _T) -> None: ... - def reverse(self) -> None: ... def rotate(self, __n: int = ...) -> None: ... def __copy__(self: _S) -> _S: ... def __len__(self) -> int: ... - def __iter__(self) -> Iterator[_T]: ... def __str__(self) -> str: ... - # These methods of deque don't really take slices, but we need to - # define them as taking a slice to satisfy MutableSequence. - @overload - def __getitem__(self, __index: int) -> _T: ... - @overload - def __getitem__(self, __s: slice) -> MutableSequence[_T]: ... - @overload - def __setitem__(self, __i: int, __x: _T) -> None: ... - @overload - def __setitem__(self, __s: slice, __o: Iterable[_T]) -> None: ... - @overload - def __delitem__(self, __i: int) -> None: ... - @overload - def __delitem__(self, __s: slice) -> None: ... + # These methods of deque don't take slices, unlike MutableSequence, hence the type: ignores + def __getitem__(self, __index: SupportsIndex) -> _T: ... # type: ignore[override] + def __setitem__(self, __i: SupportsIndex, __x: _T) -> None: ... # type: ignore[override] + def __delitem__(self, __i: SupportsIndex) -> None: ... # type: ignore[override] def __contains__(self, __o: object) -> bool: ... def __reduce__(self: Self) -> tuple[Type[Self], tuple[()], None, Iterator[_T]]: ... - def __reversed__(self) -> Iterator[_T]: ... def __iadd__(self: _S, __iterable: Iterable[_T]) -> _S: ... def __add__(self: _S, __other: _S) -> _S: ... def __mul__(self: _S, __other: int) -> _S: ... def __imul__(self: _S, __other: int) -> _S: ... + if sys.version_info >= (3, 9): + def __class_getitem__(cls, __item: Any) -> GenericAlias: ... -class Counter(Dict[_T, int], Generic[_T]): +class Counter(dict[_T, int], Generic[_T]): @overload def __init__(self, __iterable: None = ..., **kwargs: int) -> None: ... @overload - def __init__(self, __mapping: Mapping[_T, int]) -> None: ... + def __init__(self, __mapping: SupportsKeysAndGetItem[_T, int]) -> None: ... @overload def __init__(self, __iterable: Iterable[_T]) -> None: ... def copy(self: Self) -> Self: ... def elements(self) -> Iterator[_T]: ... def most_common(self, n: int | None = ...) -> list[tuple[_T, int]]: ... @classmethod - def fromkeys(cls, iterable: Any, v: int | None = ...) -> NoReturn: ... # type: ignore + def fromkeys(cls, iterable: Any, v: int | None = ...) -> NoReturn: ... # type: ignore[override] @overload def subtract(self, __iterable: None = ...) -> None: ... @overload @@ -225,7 +238,7 @@ class Counter(Dict[_T, int], Generic[_T]): # Dict.update. Not sure if we should use '# type: ignore' instead # and omit the type from the union. @overload - def update(self, __m: Mapping[_T, int], **kwargs: int) -> None: ... + def update(self, __m: SupportsKeysAndGetItem[_T, int], **kwargs: int) -> None: ... @overload def update(self, __m: Iterable[_T] | Iterable[tuple[_T, int]], **kwargs: int) -> None: ... @overload @@ -233,27 +246,29 @@ class Counter(Dict[_T, int], Generic[_T]): def __add__(self, other: Counter[_T]) -> Counter[_T]: ... def __sub__(self, other: Counter[_T]) -> Counter[_T]: ... def __and__(self, other: Counter[_T]) -> Counter[_T]: ... - def __or__(self, other: Counter[_T]) -> Counter[_T]: ... # type: ignore + def __or__(self, other: Counter[_T]) -> Counter[_T]: ... # type: ignore[override] def __pos__(self) -> Counter[_T]: ... def __neg__(self) -> Counter[_T]: ... def __iadd__(self, other: Counter[_T]) -> Counter[_T]: ... def __isub__(self, other: Counter[_T]) -> Counter[_T]: ... def __iand__(self, other: Counter[_T]) -> Counter[_T]: ... - def __ior__(self, other: Counter[_T]) -> Counter[_T]: ... # type: ignore + def __ior__(self, other: Counter[_T]) -> Counter[_T]: ... # type: ignore[override] + if sys.version_info >= (3, 10): + def total(self) -> int: ... @final class _OrderedDictKeysView(dict_keys[_KT_co, _VT_co], Reversible[_KT_co]): # type: ignore[misc] def __reversed__(self) -> Iterator[_KT_co]: ... @final -class _OrderedDictItemsView(dict_items[_KT_co, _VT_co], Reversible[Tuple[_KT_co, _VT_co]]): # type: ignore[misc] +class _OrderedDictItemsView(dict_items[_KT_co, _VT_co], Reversible[tuple[_KT_co, _VT_co]]): # type: ignore[misc] def __reversed__(self) -> Iterator[tuple[_KT_co, _VT_co]]: ... @final class _OrderedDictValuesView(dict_values[_KT_co, _VT_co], Reversible[_VT_co], Generic[_KT_co, _VT_co]): # type: ignore[misc] def __reversed__(self) -> Iterator[_VT_co]: ... -class OrderedDict(Dict[_KT, _VT], Reversible[_KT], Generic[_KT, _VT]): +class OrderedDict(dict[_KT, _VT], Reversible[_KT], Generic[_KT, _VT]): def popitem(self, last: bool = ...) -> tuple[_KT, _VT]: ... def move_to_end(self, key: _KT, last: bool = ...) -> None: ... def copy(self: Self) -> Self: ... @@ -261,8 +276,17 @@ class OrderedDict(Dict[_KT, _VT], Reversible[_KT], Generic[_KT, _VT]): def keys(self) -> _OrderedDictKeysView[_KT, _VT]: ... def items(self) -> _OrderedDictItemsView[_KT, _VT]: ... def values(self) -> _OrderedDictValuesView[_KT, _VT]: ... + # `fromkeys` is actually inherited from `dict` at runtime, so the signature should be kept in line with `dict.fromkeys`. + # Ideally we would not redefine it here, but the true signature of `dict.fromkeys` is not expressable in the current type system. + # See #3800 & https://github.com/python/typing/issues/548#issuecomment-683336963. + @classmethod + @overload + def fromkeys(cls, __iterable: Iterable[_T], __value: None = ...) -> OrderedDict[_T, Any | None]: ... + @classmethod + @overload + def fromkeys(cls, __iterable: Iterable[_T], __value: _S) -> OrderedDict[_T, _S]: ... -class defaultdict(Dict[_KT, _VT], Generic[_KT, _VT]): +class defaultdict(dict[_KT, _VT], Generic[_KT, _VT]): default_factory: Callable[[], _VT] | None @overload def __init__(self, **kwargs: _VT) -> None: ... @@ -271,9 +295,11 @@ class defaultdict(Dict[_KT, _VT], Generic[_KT, _VT]): @overload def __init__(self, __default_factory: Callable[[], _VT] | None, **kwargs: _VT) -> None: ... @overload - def __init__(self, __default_factory: Callable[[], _VT] | None, __map: Mapping[_KT, _VT]) -> None: ... + def __init__(self, __default_factory: Callable[[], _VT] | None, __map: SupportsKeysAndGetItem[_KT, _VT]) -> None: ... @overload - def __init__(self, __default_factory: Callable[[], _VT] | None, __map: Mapping[_KT, _VT], **kwargs: _VT) -> None: ... + def __init__( + self, __default_factory: Callable[[], _VT] | None, __map: SupportsKeysAndGetItem[_KT, _VT], **kwargs: _VT + ) -> None: ... @overload def __init__(self, __default_factory: Callable[[], _VT] | None, __iterable: Iterable[tuple[_KT, _VT]]) -> None: ... @overload @@ -301,3 +327,11 @@ class ChainMap(MutableMapping[_KT, _VT], Generic[_KT, _VT]): def pop(self, key: _KT) -> _VT: ... @overload def pop(self, key: _KT, default: _VT | _T = ...) -> _VT | _T: ... + def copy(self: Self) -> Self: ... + # All arguments to `fromkeys` are passed to `dict.fromkeys` at runtime, so the signature should be kept in line with `dict.fromkeys`. + @classmethod + @overload + def fromkeys(cls, iterable: Iterable[_T], __value: None = ...) -> ChainMap[_T, Any | None]: ... + @classmethod + @overload + def fromkeys(cls, __iterable: Iterable[_T], __value: _S) -> ChainMap[_T, _S]: ... diff --git a/mypy/typeshed/stdlib/concurrent/futures/_base.pyi b/mypy/typeshed/stdlib/concurrent/futures/_base.pyi index fd7333420b391..b55351aacc6f2 100644 --- a/mypy/typeshed/stdlib/concurrent/futures/_base.pyi +++ b/mypy/typeshed/stdlib/concurrent/futures/_base.pyi @@ -4,19 +4,20 @@ from _typeshed import Self from abc import abstractmethod from collections.abc import Container, Iterable, Iterator, Sequence from logging import Logger -from typing import Any, Callable, Generic, Protocol, Set, TypeVar, overload +from typing import Any, Callable, Generic, Protocol, TypeVar, overload +from typing_extensions import Literal, SupportsIndex if sys.version_info >= (3, 9): from types import GenericAlias -FIRST_COMPLETED: str -FIRST_EXCEPTION: str -ALL_COMPLETED: str -PENDING: str -RUNNING: str -CANCELLED: str -CANCELLED_AND_NOTIFIED: str -FINISHED: str +FIRST_COMPLETED: Literal["FIRST_COMPLETED"] +FIRST_EXCEPTION: Literal["FIRST_EXCEPTION"] +ALL_COMPLETED: Literal["ALL_COMPLETED"] +PENDING: Literal["PENDING"] +RUNNING: Literal["RUNNING"] +CANCELLED: Literal["CANCELLED"] +CANCELLED_AND_NOTIFIED: Literal["CANCELLED_AND_NOTIFIED"] +FINISHED: Literal["FINISHED"] _FUTURE_STATES: list[str] _STATE_TO_DESCRIPTION_MAP: dict[str, str] LOGGER: Logger @@ -75,13 +76,13 @@ class Executor: def as_completed(fs: Iterable[Future[_T]], timeout: float | None = ...) -> Iterator[Future[_T]]: ... # Ideally this would be a namedtuple, but mypy doesn't support generic tuple types. See #1976 -class DoneAndNotDoneFutures(Sequence[Set[Future[_T]]]): +class DoneAndNotDoneFutures(Sequence[set[Future[_T]]]): done: set[Future[_T]] not_done: set[Future[_T]] def __new__(_cls, done: set[Future[_T]], not_done: set[Future[_T]]) -> DoneAndNotDoneFutures[_T]: ... def __len__(self) -> int: ... @overload - def __getitem__(self, i: int) -> set[Future[_T]]: ... + def __getitem__(self, i: SupportsIndex) -> set[Future[_T]]: ... @overload def __getitem__(self, s: slice) -> DoneAndNotDoneFutures[_T]: ... diff --git a/mypy/typeshed/stdlib/concurrent/futures/process.pyi b/mypy/typeshed/stdlib/concurrent/futures/process.pyi index cc48f48f0023c..6435901a8f13c 100644 --- a/mypy/typeshed/stdlib/concurrent/futures/process.pyi +++ b/mypy/typeshed/stdlib/concurrent/futures/process.pyi @@ -5,7 +5,7 @@ from multiprocessing.context import BaseContext, Process from multiprocessing.queues import Queue, SimpleQueue from threading import Lock, Semaphore, Thread from types import TracebackType -from typing import Any, Callable, Generic, Tuple, TypeVar +from typing import Any, Callable, Generic, TypeVar from weakref import ref from ._base import Executor, Future @@ -37,7 +37,7 @@ class _ExceptionWithTraceback: exc: BaseException tb: TracebackType def __init__(self, exc: BaseException, tb: TracebackType) -> None: ... - def __reduce__(self) -> str | Tuple[Any, ...]: ... + def __reduce__(self) -> str | tuple[Any, ...]: ... def _rebuild_exc(exc: Exception, tb: str) -> Exception: ... @@ -84,7 +84,7 @@ if sys.version_info >= (3, 7): ) -> None: ... def _on_queue_feeder_error(self, e: Exception, obj: _CallItem) -> None: ... -def _get_chunks(*iterables: Any, chunksize: int) -> Generator[Tuple[Any, ...], None, None]: ... +def _get_chunks(*iterables: Any, chunksize: int) -> Generator[tuple[Any, ...], None, None]: ... def _process_chunk(fn: Callable[..., Any], chunk: tuple[Any, None, None]) -> Generator[Any, None, None]: ... def _sendback_result( result_queue: SimpleQueue[_WorkItem[Any]], work_id: int, result: Any | None = ..., exception: Exception | None = ... @@ -95,7 +95,7 @@ if sys.version_info >= (3, 7): call_queue: Queue[_CallItem], result_queue: SimpleQueue[_ResultItem], initializer: Callable[..., None] | None, - initargs: Tuple[Any, ...], + initargs: tuple[Any, ...], ) -> None: ... else: @@ -139,7 +139,7 @@ else: class ProcessPoolExecutor(Executor): _mp_context: BaseContext | None = ... _initializer: Callable[..., None] | None = ... - _initargs: Tuple[Any, ...] = ... + _initargs: tuple[Any, ...] = ... _executor_manager_thread: _ThreadWakeup _processes: MutableMapping[int, Process] _shutdown_thread: bool @@ -158,7 +158,7 @@ class ProcessPoolExecutor(Executor): max_workers: int | None = ..., mp_context: BaseContext | None = ..., initializer: Callable[..., None] | None = ..., - initargs: Tuple[Any, ...] = ..., + initargs: tuple[Any, ...] = ..., ) -> None: ... else: def __init__(self, max_workers: int | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/concurrent/futures/thread.pyi b/mypy/typeshed/stdlib/concurrent/futures/thread.pyi index 5ad5b65d3becb..f27c43c3403ca 100644 --- a/mypy/typeshed/stdlib/concurrent/futures/thread.pyi +++ b/mypy/typeshed/stdlib/concurrent/futures/thread.pyi @@ -1,8 +1,8 @@ import queue import sys -from collections.abc import Iterable, Mapping, Set # equivalent to typing.AbstractSet, not builtins.set +from collections.abc import Iterable, Mapping, Set as AbstractSet from threading import Lock, Semaphore, Thread -from typing import Any, Callable, Generic, Tuple, TypeVar +from typing import Any, Callable, Generic, TypeVar from weakref import ref from ._base import Executor, Future @@ -33,7 +33,7 @@ if sys.version_info >= (3, 7): executor_reference: ref[Any], work_queue: queue.SimpleQueue[Any], initializer: Callable[..., None], - initargs: Tuple[Any, ...], + initargs: tuple[Any, ...], ) -> None: ... else: @@ -46,13 +46,13 @@ if sys.version_info >= (3, 7): class ThreadPoolExecutor(Executor): _max_workers: int _idle_semaphore: Semaphore - _threads: Set[Thread] + _threads: AbstractSet[Thread] _broken: bool _shutdown: bool _shutdown_lock: Lock _thread_name_prefix: str | None = ... _initializer: Callable[..., None] | None = ... - _initargs: Tuple[Any, ...] = ... + _initargs: tuple[Any, ...] = ... if sys.version_info >= (3, 7): _work_queue: queue.SimpleQueue[_WorkItem[Any]] else: @@ -63,7 +63,7 @@ class ThreadPoolExecutor(Executor): max_workers: int | None = ..., thread_name_prefix: str = ..., initializer: Callable[..., None] | None = ..., - initargs: Tuple[Any, ...] = ..., + initargs: tuple[Any, ...] = ..., ) -> None: ... else: def __init__(self, max_workers: int | None = ..., thread_name_prefix: str = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/configparser.pyi b/mypy/typeshed/stdlib/configparser.pyi index a0efa30416dd9..dc81cb78577a8 100644 --- a/mypy/typeshed/stdlib/configparser.pyi +++ b/mypy/typeshed/stdlib/configparser.pyi @@ -1,14 +1,14 @@ import sys from _typeshed import StrOrBytesPath, StrPath, SupportsWrite from collections.abc import Callable, ItemsView, Iterable, Iterator, Mapping, MutableMapping, Sequence -from typing import Any, ClassVar, Dict, Optional, Pattern, Type, TypeVar, overload +from typing import Any, ClassVar, Optional, Pattern, Type, TypeVar, overload from typing_extensions import Literal # Internal type aliases _section = Mapping[str, str] _parser = MutableMapping[str, _section] _converter = Callable[[str], Any] -_converters = Dict[str, _converter] +_converters = dict[str, _converter] _T = TypeVar("_T") if sys.version_info >= (3, 7): @@ -122,7 +122,7 @@ class RawConfigParser(_parser): fallback: _T = ..., ) -> _T: ... # This is incompatible with MutableMapping so we ignore the type - @overload # type: ignore + @overload # type: ignore[override] def get(self, section: str, option: str, *, raw: bool = ..., vars: _section | None = ...) -> str: ... @overload def get(self, section: str, option: str, *, raw: bool = ..., vars: _section | None = ..., fallback: _T) -> str | _T: ... @@ -137,7 +137,9 @@ class RawConfigParser(_parser): def optionxform(self, optionstr: str) -> str: ... class ConfigParser(RawConfigParser): ... -class SafeConfigParser(ConfigParser): ... + +if sys.version_info < (3, 11): + class SafeConfigParser(ConfigParser): ... class SectionProxy(MutableMapping[str, str]): def __init__(self, parser: RawConfigParser, name: str) -> None: ... @@ -151,7 +153,16 @@ class SectionProxy(MutableMapping[str, str]): def parser(self) -> RawConfigParser: ... @property def name(self) -> str: ... - def get(self, option: str, fallback: str | None = ..., *, raw: bool = ..., vars: _section | None = ..., _impl: Any | None = ..., **kwargs: Any) -> str: ... # type: ignore + def get( # type: ignore[override] + self, + option: str, + fallback: str | None = ..., + *, + raw: bool = ..., + vars: _section | None = ..., + _impl: Any | None = ..., + **kwargs: Any, + ) -> str: ... # These are partially-applied version of the methods with the same names in # RawConfigParser; the stubs should be kept updated together @overload diff --git a/mypy/typeshed/stdlib/contextlib.pyi b/mypy/typeshed/stdlib/contextlib.pyi index 9d968e092ca51..b536c36678a26 100644 --- a/mypy/typeshed/stdlib/contextlib.pyi +++ b/mypy/typeshed/stdlib/contextlib.pyi @@ -4,18 +4,21 @@ from types import TracebackType from typing import ( IO, Any, + AsyncGenerator, AsyncIterator, Awaitable, Callable, ContextManager, + Generator, Generic, Iterator, Optional, + Protocol, Type, TypeVar, overload, ) -from typing_extensions import ParamSpec, Protocol +from typing_extensions import ParamSpec AbstractContextManager = ContextManager if sys.version_info >= (3, 7): @@ -32,14 +35,44 @@ _P = ParamSpec("_P") _ExitFunc = Callable[[Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType]], bool] _CM_EF = TypeVar("_CM_EF", AbstractContextManager[Any], _ExitFunc) -class _GeneratorContextManager(AbstractContextManager[_T_co]): +class ContextDecorator: def __call__(self, func: _F) -> _F: ... -# type ignore to deal with incomplete ParamSpec support in mypy -def contextmanager(func: Callable[_P, Iterator[_T]]) -> Callable[_P, _GeneratorContextManager[_T]]: ... # type: ignore +class _GeneratorContextManager(AbstractContextManager[_T_co], ContextDecorator, Generic[_T_co]): + # In Python <= 3.6, __init__ and all instance attributes are defined directly on this class. + # In Python >= 3.7, __init__ and all instance attributes are inherited from _GeneratorContextManagerBase + # _GeneratorContextManagerBase is more trouble than it's worth to include in the stub; see #6676 + def __init__(self, func: Callable[..., Iterator[_T_co]], args: tuple[Any, ...], kwds: dict[str, Any]) -> None: ... + gen: Generator[_T_co, Any, Any] + func: Callable[..., Generator[_T_co, Any, Any]] + args: tuple[Any, ...] + kwds: dict[str, Any] + +def contextmanager(func: Callable[_P, Iterator[_T_co]]) -> Callable[_P, _GeneratorContextManager[_T_co]]: ... + +if sys.version_info >= (3, 10): + _AF = TypeVar("_AF", bound=Callable[..., Awaitable[Any]]) + class AsyncContextDecorator: + def __call__(self, func: _AF) -> _AF: ... + class _AsyncGeneratorContextManager(AbstractAsyncContextManager[_T_co], AsyncContextDecorator, Generic[_T_co]): + # __init__ and these attributes are actually defined in the base class _GeneratorContextManagerBase, + # which is more trouble than it's worth to include in the stub (see #6676) + def __init__(self, func: Callable[..., AsyncIterator[_T_co]], args: tuple[Any, ...], kwds: dict[str, Any]) -> None: ... + gen: AsyncGenerator[_T_co, Any] + func: Callable[..., AsyncGenerator[_T_co, Any]] + args: tuple[Any, ...] + kwds: dict[str, Any] + +elif sys.version_info >= (3, 7): + class _AsyncGeneratorContextManager(AbstractAsyncContextManager[_T_co], Generic[_T_co]): + def __init__(self, func: Callable[..., AsyncIterator[_T_co]], args: tuple[Any, ...], kwds: dict[str, Any]) -> None: ... + gen: AsyncGenerator[_T_co, Any] + func: Callable[..., AsyncGenerator[_T_co, Any]] + args: tuple[Any, ...] + kwds: dict[str, Any] if sys.version_info >= (3, 7): - def asynccontextmanager(func: Callable[_P, AsyncIterator[_T]]) -> Callable[_P, AbstractAsyncContextManager[_T]]: ... # type: ignore + def asynccontextmanager(func: Callable[_P, AsyncIterator[_T_co]]) -> Callable[_P, _AsyncGeneratorContextManager[_T_co]]: ... class _SupportsClose(Protocol): def close(self) -> object: ... @@ -55,9 +88,6 @@ if sys.version_info >= (3, 10): _SupportsAcloseT = TypeVar("_SupportsAcloseT", bound=_SupportsAclose) class aclosing(AbstractAsyncContextManager[_SupportsAcloseT]): def __init__(self, thing: _SupportsAcloseT) -> None: ... - _AF = TypeVar("_AF", bound=Callable[..., Awaitable[Any]]) - class AsyncContextDecorator: - def __call__(self, func: _AF) -> _AF: ... class suppress(AbstractContextManager[None]): def __init__(self, *exceptions: Type[BaseException]) -> None: ... @@ -71,9 +101,6 @@ class redirect_stdout(AbstractContextManager[_T_io]): class redirect_stderr(AbstractContextManager[_T_io]): def __init__(self, new_target: _T_io) -> None: ... -class ContextDecorator: - def __call__(self, func: _F) -> _F: ... - class ExitStack(AbstractContextManager[ExitStack]): def __init__(self) -> None: ... def enter_context(self, cm: AbstractContextManager[_T]) -> _T: ... diff --git a/mypy/typeshed/stdlib/copyreg.pyi b/mypy/typeshed/stdlib/copyreg.pyi index 320097b3a204f..6097670833c0c 100644 --- a/mypy/typeshed/stdlib/copyreg.pyi +++ b/mypy/typeshed/stdlib/copyreg.pyi @@ -1,7 +1,7 @@ -from typing import Any, Callable, Hashable, Optional, SupportsInt, Tuple, TypeVar, Union +from typing import Any, Callable, Hashable, Optional, SupportsInt, TypeVar, Union _TypeT = TypeVar("_TypeT", bound=type) -_Reduce = Union[Tuple[Callable[..., _TypeT], Tuple[Any, ...]], Tuple[Callable[..., _TypeT], Tuple[Any, ...], Optional[Any]]] +_Reduce = Union[tuple[Callable[..., _TypeT], tuple[Any, ...]], tuple[Callable[..., _TypeT], tuple[Any, ...], Optional[Any]]] __all__: list[str] diff --git a/mypy/typeshed/stdlib/crypt.pyi b/mypy/typeshed/stdlib/crypt.pyi index 27e30433f7028..a8342859e7700 100644 --- a/mypy/typeshed/stdlib/crypt.pyi +++ b/mypy/typeshed/stdlib/crypt.pyi @@ -1,20 +1,18 @@ import sys -class _Method: ... +if sys.platform != "win32": + class _Method: ... + METHOD_CRYPT: _Method + METHOD_MD5: _Method + METHOD_SHA256: _Method + METHOD_SHA512: _Method + if sys.version_info >= (3, 7): + METHOD_BLOWFISH: _Method -METHOD_CRYPT: _Method -METHOD_MD5: _Method -METHOD_SHA256: _Method -METHOD_SHA512: _Method -if sys.version_info >= (3, 7): - METHOD_BLOWFISH: _Method + methods: list[_Method] -methods: list[_Method] - -if sys.version_info >= (3, 7): - def mksalt(method: _Method | None = ..., *, rounds: int | None = ...) -> str: ... - -else: - def mksalt(method: _Method | None = ...) -> str: ... - -def crypt(word: str, salt: str | _Method | None = ...) -> str: ... + if sys.version_info >= (3, 7): + def mksalt(method: _Method | None = ..., *, rounds: int | None = ...) -> str: ... + else: + def mksalt(method: _Method | None = ...) -> str: ... + def crypt(word: str, salt: str | _Method | None = ...) -> str: ... diff --git a/mypy/typeshed/stdlib/csv.pyi b/mypy/typeshed/stdlib/csv.pyi index 0b69cb2272d31..63999be059f66 100644 --- a/mypy/typeshed/stdlib/csv.pyi +++ b/mypy/typeshed/stdlib/csv.pyi @@ -21,7 +21,7 @@ from collections.abc import Collection, Iterable, Iterator, Mapping, Sequence from typing import Any, Generic, Type, TypeVar, overload if sys.version_info >= (3, 8): - from typing import Dict as _DictReadMapping + from builtins import dict as _DictReadMapping else: from collections import OrderedDict as _DictReadMapping @@ -100,7 +100,7 @@ class DictWriter(Generic[_T]): def writerow(self, rowdict: Mapping[_T, Any]) -> Any: ... def writerows(self, rowdicts: Iterable[Mapping[_T, Any]]) -> None: ... -class Sniffer(object): +class Sniffer: preferred: list[str] def __init__(self) -> None: ... def sniff(self, sample: str, delimiters: str | None = ...) -> Type[Dialect]: ... diff --git a/mypy/typeshed/stdlib/ctypes/__init__.pyi b/mypy/typeshed/stdlib/ctypes/__init__.pyi index bbe083f5d4c40..7f2eba011d0fd 100644 --- a/mypy/typeshed/stdlib/ctypes/__init__.pyi +++ b/mypy/typeshed/stdlib/ctypes/__init__.pyi @@ -1,5 +1,6 @@ import sys from _typeshed import ReadableBuffer, WriteableBuffer +from abc import abstractmethod from typing import ( Any, Callable, @@ -10,7 +11,6 @@ from typing import ( Mapping, Optional, Sequence, - Tuple, Type, TypeVar, Union as _UnionT, @@ -28,7 +28,7 @@ RTLD_GLOBAL: int RTLD_LOCAL: int DEFAULT_MODE: int -class CDLL(object): +class CDLL: _func_flags_: ClassVar[int] _func_restype_: ClassVar[_CData] _name: str @@ -76,8 +76,8 @@ class _CDataMeta(type): # By default mypy complains about the following two methods, because strictly speaking cls # might not be a Type[_CT]. However this can never actually happen, because the only class that # uses _CDataMeta as its metaclass is _CData. So it's safe to ignore the errors here. - def __mul__(cls: Type[_CT], other: int) -> Type[Array[_CT]]: ... # type: ignore - def __rmul__(cls: Type[_CT], other: int) -> Type[Array[_CT]]: ... # type: ignore + def __mul__(cls: Type[_CT], other: int) -> Type[Array[_CT]]: ... # type: ignore[misc] + def __rmul__(cls: Type[_CT], other: int) -> Type[Array[_CT]]: ... # type: ignore[misc] class _CData(metaclass=_CDataMeta): _b_base: int @@ -97,8 +97,8 @@ class _CData(metaclass=_CDataMeta): class _CanCastTo(_CData): ... class _PointerLike(_CanCastTo): ... -_ECT = Callable[[Optional[Type[_CData]], _FuncPointer, Tuple[_CData, ...]], _CData] -_PF = _UnionT[Tuple[int], Tuple[int, str], Tuple[int, str, Any]] +_ECT = Callable[[Optional[Type[_CData]], _FuncPointer, tuple[_CData, ...]], _CData] +_PF = _UnionT[tuple[int], tuple[int, str], tuple[int, str, Any]] class _FuncPointer(_PointerLike, _CData): restype: Type[_CData] | Callable[[int], Any] | None @@ -109,9 +109,9 @@ class _FuncPointer(_PointerLike, _CData): @overload def __init__(self, callable: Callable[..., Any]) -> None: ... @overload - def __init__(self, func_spec: tuple[str | int, CDLL], paramflags: Tuple[_PF, ...] = ...) -> None: ... + def __init__(self, func_spec: tuple[str | int, CDLL], paramflags: tuple[_PF, ...] = ...) -> None: ... @overload - def __init__(self, vtlb_index: int, name: str, paramflags: Tuple[_PF, ...] = ..., iid: pointer[c_int] = ...) -> None: ... + def __init__(self, vtlb_index: int, name: str, paramflags: tuple[_PF, ...] = ..., iid: pointer[c_int] = ...) -> None: ... def __call__(self, *args: Any, **kwargs: Any) -> Any: ... class _NamedFuncPointer(_FuncPointer): @@ -157,7 +157,7 @@ def create_unicode_buffer(init: int | str, size: int | None = ...) -> Array[c_wc if sys.platform == "win32": def DllCanUnloadNow() -> int: ... def DllGetClassObject(rclsid: Any, riid: Any, ppv: Any) -> int: ... # TODO not documented - def FormatError(code: int) -> str: ... + def FormatError(code: int = ...) -> str: ... def GetLastError() -> int: ... def get_errno() -> int: ... @@ -268,8 +268,16 @@ class BigEndianStructure(Structure): ... class LittleEndianStructure(Structure): ... class Array(Generic[_CT], _CData): - _length_: int - _type_: Type[_CT] + @property + @abstractmethod + def _length_(self) -> int: ... + @_length_.setter + def _length_(self, value: int) -> None: ... + @property + @abstractmethod + def _type_(self) -> Type[_CT]: ... + @_type_.setter + def _type_(self, value: Type[_CT]) -> None: ... raw: bytes # Note: only available if _CT == c_char value: Any # Note: bytes if _CT == c_char, str if _CT == c_wchar, unavailable otherwise # TODO These methods cannot be annotated correctly at the moment. diff --git a/mypy/typeshed/stdlib/curses/__init__.pyi b/mypy/typeshed/stdlib/curses/__init__.pyi index 73e84fba3763e..aef2d9b95ed5d 100644 --- a/mypy/typeshed/stdlib/curses/__init__.pyi +++ b/mypy/typeshed/stdlib/curses/__init__.pyi @@ -1,15 +1,17 @@ -from _curses import * # noqa: F403 -from _curses import _CursesWindow as _CursesWindow +import sys from typing import Any, Callable, TypeVar -_T = TypeVar("_T") +if sys.platform != "win32": + from _curses import * # noqa: F403 + from _curses import _CursesWindow as _CursesWindow -# available after calling `curses.initscr()` -LINES: int -COLS: int + _T = TypeVar("_T") -# available after calling `curses.start_color()` -COLORS: int -COLOR_PAIRS: int + # available after calling `curses.initscr()` + LINES: int + COLS: int -def wrapper(__func: Callable[..., _T], *arg: Any, **kwds: Any) -> _T: ... + # available after calling `curses.start_color()` + COLORS: int + COLOR_PAIRS: int + def wrapper(__func: Callable[..., _T], *arg: Any, **kwds: Any) -> _T: ... diff --git a/mypy/typeshed/stdlib/curses/ascii.pyi b/mypy/typeshed/stdlib/curses/ascii.pyi index 66efbe36a7df2..25de8f605bdaf 100644 --- a/mypy/typeshed/stdlib/curses/ascii.pyi +++ b/mypy/typeshed/stdlib/curses/ascii.pyi @@ -1,62 +1,63 @@ +import sys from typing import TypeVar -_CharT = TypeVar("_CharT", str, int) +if sys.platform != "win32": + _CharT = TypeVar("_CharT", str, int) -NUL: int -SOH: int -STX: int -ETX: int -EOT: int -ENQ: int -ACK: int -BEL: int -BS: int -TAB: int -HT: int -LF: int -NL: int -VT: int -FF: int -CR: int -SO: int -SI: int -DLE: int -DC1: int -DC2: int -DC3: int -DC4: int -NAK: int -SYN: int -ETB: int -CAN: int -EM: int -SUB: int -ESC: int -FS: int -GS: int -RS: int -US: int -SP: int -DEL: int + NUL: int + SOH: int + STX: int + ETX: int + EOT: int + ENQ: int + ACK: int + BEL: int + BS: int + TAB: int + HT: int + LF: int + NL: int + VT: int + FF: int + CR: int + SO: int + SI: int + DLE: int + DC1: int + DC2: int + DC3: int + DC4: int + NAK: int + SYN: int + ETB: int + CAN: int + EM: int + SUB: int + ESC: int + FS: int + GS: int + RS: int + US: int + SP: int + DEL: int -controlnames: list[int] - -def isalnum(c: str | int) -> bool: ... -def isalpha(c: str | int) -> bool: ... -def isascii(c: str | int) -> bool: ... -def isblank(c: str | int) -> bool: ... -def iscntrl(c: str | int) -> bool: ... -def isdigit(c: str | int) -> bool: ... -def isgraph(c: str | int) -> bool: ... -def islower(c: str | int) -> bool: ... -def isprint(c: str | int) -> bool: ... -def ispunct(c: str | int) -> bool: ... -def isspace(c: str | int) -> bool: ... -def isupper(c: str | int) -> bool: ... -def isxdigit(c: str | int) -> bool: ... -def isctrl(c: str | int) -> bool: ... -def ismeta(c: str | int) -> bool: ... -def ascii(c: _CharT) -> _CharT: ... -def ctrl(c: _CharT) -> _CharT: ... -def alt(c: _CharT) -> _CharT: ... -def unctrl(c: str | int) -> str: ... + controlnames: list[int] + def isalnum(c: str | int) -> bool: ... + def isalpha(c: str | int) -> bool: ... + def isascii(c: str | int) -> bool: ... + def isblank(c: str | int) -> bool: ... + def iscntrl(c: str | int) -> bool: ... + def isdigit(c: str | int) -> bool: ... + def isgraph(c: str | int) -> bool: ... + def islower(c: str | int) -> bool: ... + def isprint(c: str | int) -> bool: ... + def ispunct(c: str | int) -> bool: ... + def isspace(c: str | int) -> bool: ... + def isupper(c: str | int) -> bool: ... + def isxdigit(c: str | int) -> bool: ... + def isctrl(c: str | int) -> bool: ... + def ismeta(c: str | int) -> bool: ... + def ascii(c: _CharT) -> _CharT: ... + def ctrl(c: _CharT) -> _CharT: ... + def alt(c: _CharT) -> _CharT: ... + def unctrl(c: str | int) -> str: ... diff --git a/mypy/typeshed/stdlib/curses/panel.pyi b/mypy/typeshed/stdlib/curses/panel.pyi index 138e4a9f727e2..ed13a6e050e94 100644 --- a/mypy/typeshed/stdlib/curses/panel.pyi +++ b/mypy/typeshed/stdlib/curses/panel.pyi @@ -1,20 +1,23 @@ -from _curses import _CursesWindow +import sys -class _Curses_Panel: # type is (note the space in the class name) - def above(self) -> _Curses_Panel: ... - def below(self) -> _Curses_Panel: ... - def bottom(self) -> None: ... - def hidden(self) -> bool: ... - def hide(self) -> None: ... - def move(self, y: int, x: int) -> None: ... - def replace(self, win: _CursesWindow) -> None: ... - def set_userptr(self, obj: object) -> None: ... - def show(self) -> None: ... - def top(self) -> None: ... - def userptr(self) -> object: ... - def window(self) -> _CursesWindow: ... +if sys.platform != "win32": + from _curses import _CursesWindow -def bottom_panel() -> _Curses_Panel: ... -def new_panel(__win: _CursesWindow) -> _Curses_Panel: ... -def top_panel() -> _Curses_Panel: ... -def update_panels() -> _Curses_Panel: ... + version: str + class _Curses_Panel: # type is (note the space in the class name) + def above(self) -> _Curses_Panel: ... + def below(self) -> _Curses_Panel: ... + def bottom(self) -> None: ... + def hidden(self) -> bool: ... + def hide(self) -> None: ... + def move(self, y: int, x: int) -> None: ... + def replace(self, win: _CursesWindow) -> None: ... + def set_userptr(self, obj: object) -> None: ... + def show(self) -> None: ... + def top(self) -> None: ... + def userptr(self) -> object: ... + def window(self) -> _CursesWindow: ... + def bottom_panel() -> _Curses_Panel: ... + def new_panel(__win: _CursesWindow) -> _Curses_Panel: ... + def top_panel() -> _Curses_Panel: ... + def update_panels() -> _Curses_Panel: ... diff --git a/mypy/typeshed/stdlib/curses/textpad.pyi b/mypy/typeshed/stdlib/curses/textpad.pyi index 578a579fda38b..eb68796038537 100644 --- a/mypy/typeshed/stdlib/curses/textpad.pyi +++ b/mypy/typeshed/stdlib/curses/textpad.pyi @@ -1,11 +1,12 @@ -from _curses import _CursesWindow +import sys from typing import Callable -def rectangle(win: _CursesWindow, uly: int, ulx: int, lry: int, lrx: int) -> None: ... - -class Textbox: - stripspaces: bool - def __init__(self, win: _CursesWindow, insert_mode: bool = ...) -> None: ... - def edit(self, validate: Callable[[int], int] | None = ...) -> str: ... - def do_command(self, ch: str | int) -> None: ... - def gather(self) -> str: ... +if sys.platform != "win32": + from _curses import _CursesWindow + def rectangle(win: _CursesWindow, uly: int, ulx: int, lry: int, lrx: int) -> None: ... + class Textbox: + stripspaces: bool + def __init__(self, win: _CursesWindow, insert_mode: bool = ...) -> None: ... + def edit(self, validate: Callable[[int], int] | None = ...) -> str: ... + def do_command(self, ch: str | int) -> None: ... + def gather(self) -> str: ... diff --git a/mypy/typeshed/stdlib/dataclasses.pyi b/mypy/typeshed/stdlib/dataclasses.pyi index 59efbe77aed60..885facb9c0db0 100644 --- a/mypy/typeshed/stdlib/dataclasses.pyi +++ b/mypy/typeshed/stdlib/dataclasses.pyi @@ -1,7 +1,6 @@ import sys import types -from typing import Any, Callable, Generic, Iterable, Mapping, Tuple, Type, TypeVar, overload -from typing_extensions import Protocol +from typing import Any, Callable, Generic, Iterable, Mapping, Protocol, Type, TypeVar, overload if sys.version_info >= (3, 9): from types import GenericAlias @@ -21,7 +20,7 @@ def asdict(obj: Any) -> dict[str, Any]: ... @overload def asdict(obj: Any, *, dict_factory: Callable[[list[tuple[str, Any]]], _T]) -> _T: ... @overload -def astuple(obj: Any) -> Tuple[Any, ...]: ... +def astuple(obj: Any) -> tuple[Any, ...]: ... @overload def astuple(obj: Any, *, tuple_factory: Callable[[list[Any]], _T]) -> _T: ... @@ -173,7 +172,7 @@ else: metadata: Mapping[Any, Any] | None = ..., ) -> Any: ... -def fields(class_or_instance: Any) -> Tuple[Field[Any], ...]: ... +def fields(class_or_instance: Any) -> tuple[Field[Any], ...]: ... def is_dataclass(obj: Any) -> bool: ... class FrozenInstanceError(AttributeError): ... @@ -192,7 +191,7 @@ if sys.version_info >= (3, 10): cls_name: str, fields: Iterable[str | tuple[str, type] | tuple[str, type, Field[Any]]], *, - bases: Tuple[type, ...] = ..., + bases: tuple[type, ...] = ..., namespace: dict[str, Any] | None = ..., init: bool = ..., repr: bool = ..., @@ -201,6 +200,7 @@ if sys.version_info >= (3, 10): unsafe_hash: bool = ..., frozen: bool = ..., match_args: bool = ..., + kw_only: bool = ..., slots: bool = ..., ) -> type: ... @@ -209,7 +209,7 @@ else: cls_name: str, fields: Iterable[str | tuple[str, type] | tuple[str, type, Field[Any]]], *, - bases: Tuple[type, ...] = ..., + bases: tuple[type, ...] = ..., namespace: dict[str, Any] | None = ..., init: bool = ..., repr: bool = ..., diff --git a/mypy/typeshed/stdlib/datetime.pyi b/mypy/typeshed/stdlib/datetime.pyi index bd4d47e051ec7..e0ce085c29670 100644 --- a/mypy/typeshed/stdlib/datetime.pyi +++ b/mypy/typeshed/stdlib/datetime.pyi @@ -56,7 +56,7 @@ class date: @property def day(self) -> int: ... def ctime(self) -> str: ... - def strftime(self, fmt: str) -> str: ... + def strftime(self, __format: str) -> str: ... def __format__(self, __fmt: str) -> str: ... def isoformat(self) -> str: ... def timetuple(self) -> struct_time: ... @@ -128,7 +128,7 @@ class time: if sys.version_info >= (3, 7): @classmethod def fromisoformat(cls: Type[_S], __time_string: str) -> _S: ... - def strftime(self, fmt: str) -> str: ... + def strftime(self, __format: str) -> str: ... def __format__(self, __fmt: str) -> str: ... def utcoffset(self) -> timedelta | None: ... def tzname(self) -> str | None: ... @@ -276,10 +276,10 @@ class datetime(date): def utcoffset(self) -> timedelta | None: ... def tzname(self) -> str | None: ... def dst(self) -> timedelta | None: ... - def __le__(self, __other: datetime) -> bool: ... # type: ignore - def __lt__(self, __other: datetime) -> bool: ... # type: ignore - def __ge__(self, __other: datetime) -> bool: ... # type: ignore - def __gt__(self, __other: datetime) -> bool: ... # type: ignore + def __le__(self, __other: datetime) -> bool: ... # type: ignore[override] + def __lt__(self, __other: datetime) -> bool: ... # type: ignore[override] + def __ge__(self, __other: datetime) -> bool: ... # type: ignore[override] + def __gt__(self, __other: datetime) -> bool: ... # type: ignore[override] if sys.version_info >= (3, 8): @overload # type: ignore[override] def __sub__(self: _D, __other: timedelta) -> _D: ... diff --git a/mypy/typeshed/stdlib/dbm/__init__.pyi b/mypy/typeshed/stdlib/dbm/__init__.pyi index 9b9f92ccaa86f..5ecacd91b4ed8 100644 --- a/mypy/typeshed/stdlib/dbm/__init__.pyi +++ b/mypy/typeshed/stdlib/dbm/__init__.pyi @@ -1,6 +1,6 @@ from _typeshed import Self from types import TracebackType -from typing import Iterator, MutableMapping, Tuple, Type, Union +from typing import Iterator, MutableMapping, Type, Union from typing_extensions import Literal _KeyType = Union[str, bytes] @@ -87,7 +87,7 @@ class _Database(MutableMapping[_KeyType, bytes]): class _error(Exception): ... -error = Tuple[Type[_error], Type[OSError]] +error: tuple[Type[_error], Type[OSError]] def whichdb(filename: str) -> str: ... def open(file: str, flag: _TFlags = ..., mode: int = ...) -> _Database: ... diff --git a/mypy/typeshed/stdlib/dbm/gnu.pyi b/mypy/typeshed/stdlib/dbm/gnu.pyi index 7cec827e89929..702f62d11b758 100644 --- a/mypy/typeshed/stdlib/dbm/gnu.pyi +++ b/mypy/typeshed/stdlib/dbm/gnu.pyi @@ -6,6 +6,8 @@ _T = TypeVar("_T") _KeyType = Union[str, bytes] _ValueType = Union[str, bytes] +open_flags: str + class error(OSError): ... # Actual typename gdbm, not exposed by the implementation @@ -31,7 +33,7 @@ class _gdbm: def keys(self) -> list[bytes]: ... def setdefault(self, k: _KeyType, default: _ValueType = ...) -> bytes: ... # Don't exist at runtime - __new__: None # type: ignore - __init__: None # type: ignore + __new__: None # type: ignore[assignment] + __init__: None # type: ignore[assignment] def open(__filename: str, __flags: str = ..., __mode: int = ...) -> _gdbm: ... diff --git a/mypy/typeshed/stdlib/dbm/ndbm.pyi b/mypy/typeshed/stdlib/dbm/ndbm.pyi index a4b35a309dbd6..7b04c5385dbe6 100644 --- a/mypy/typeshed/stdlib/dbm/ndbm.pyi +++ b/mypy/typeshed/stdlib/dbm/ndbm.pyi @@ -29,7 +29,7 @@ class _dbm: def keys(self) -> list[bytes]: ... def setdefault(self, k: _KeyType, default: _ValueType = ...) -> bytes: ... # Don't exist at runtime - __new__: None # type: ignore - __init__: None # type: ignore + __new__: None # type: ignore[assignment] + __init__: None # type: ignore[assignment] def open(__filename: str, __flags: str = ..., __mode: int = ...) -> _dbm: ... diff --git a/mypy/typeshed/stdlib/decimal.pyi b/mypy/typeshed/stdlib/decimal.pyi index 30c8e973348db..07f9ca1bfdf09 100644 --- a/mypy/typeshed/stdlib/decimal.pyi +++ b/mypy/typeshed/stdlib/decimal.pyi @@ -1,15 +1,16 @@ import numbers +import sys from types import TracebackType -from typing import Any, Container, NamedTuple, Sequence, Tuple, Type, TypeVar, Union, overload +from typing import Any, Container, NamedTuple, Sequence, Type, TypeVar, Union, overload _Decimal = Union[Decimal, int] -_DecimalNew = Union[Decimal, float, str, Tuple[int, Sequence[int], int]] +_DecimalNew = Union[Decimal, float, str, tuple[int, Sequence[int], int]] _ComparableNum = Union[Decimal, float, numbers.Rational] _DecimalT = TypeVar("_DecimalT", bound=Decimal) class DecimalTuple(NamedTuple): sign: int - digits: Tuple[int, ...] + digits: tuple[int, ...] exponent: int ROUND_DOWN: str @@ -21,6 +22,8 @@ ROUND_UP: str ROUND_HALF_DOWN: str ROUND_05UP: str +if sys.version_info >= (3, 7): + HAVE_CONTEXTVAR: bool HAVE_THREADS: bool MAX_EMAX: int MAX_PREC: int @@ -46,7 +49,7 @@ def setcontext(__context: Context) -> None: ... def getcontext() -> Context: ... def localcontext(ctx: Context | None = ...) -> _ContextManager: ... -class Decimal(object): +class Decimal: def __new__(cls: Type[_DecimalT], value: _DecimalNew = ..., context: Context | None = ...) -> _DecimalT: ... @classmethod def from_float(cls, __f: float) -> Decimal: ... @@ -148,7 +151,7 @@ class Decimal(object): def __deepcopy__(self, __memo: Any) -> Decimal: ... def __format__(self, __specifier: str, __context: Context | None = ...) -> str: ... -class _ContextManager(object): +class _ContextManager: new_context: Context saved_context: Context def __init__(self, new_context: Context) -> None: ... @@ -157,7 +160,7 @@ class _ContextManager(object): _TrapType = Type[DecimalException] -class Context(object): +class Context: prec: int rounding: str Emin: int @@ -181,7 +184,7 @@ class Context(object): # __setattr__() only allows to set a specific set of attributes, # already defined above. def __delattr__(self, __name: str) -> None: ... - def __reduce__(self) -> tuple[Type[Context], Tuple[Any, ...]]: ... + def __reduce__(self) -> tuple[Type[Context], tuple[Any, ...]]: ... def clear_flags(self) -> None: ... def clear_traps(self) -> None: ... def copy(self) -> Context: ... diff --git a/mypy/typeshed/stdlib/difflib.pyi b/mypy/typeshed/stdlib/difflib.pyi index 7c4ae8e2f246f..d259e77dfe8c2 100644 --- a/mypy/typeshed/stdlib/difflib.pyi +++ b/mypy/typeshed/stdlib/difflib.pyi @@ -34,9 +34,7 @@ class SequenceMatcher(Generic[_T]): # mypy thinks the signatures of the overloads overlap, but the types still work fine @overload -def get_close_matches( # type: ignore - word: AnyStr, possibilities: Iterable[AnyStr], n: int = ..., cutoff: float = ... -) -> list[AnyStr]: ... +def get_close_matches(word: AnyStr, possibilities: Iterable[AnyStr], n: int = ..., cutoff: float = ...) -> list[AnyStr]: ... # type: ignore[misc] @overload def get_close_matches( word: Sequence[_T], possibilities: Iterable[Sequence[_T]], n: int = ..., cutoff: float = ... @@ -72,7 +70,7 @@ def ndiff( a: Sequence[str], b: Sequence[str], linejunk: _JunkCallback | None = ..., charjunk: _JunkCallback | None = ... ) -> Iterator[str]: ... -class HtmlDiff(object): +class HtmlDiff: def __init__( self, tabsize: int = ..., diff --git a/mypy/typeshed/stdlib/dis.pyi b/mypy/typeshed/stdlib/dis.pyi index a6ea3e950b952..ac0632d25c9ca 100644 --- a/mypy/typeshed/stdlib/dis.pyi +++ b/mypy/typeshed/stdlib/dis.pyi @@ -20,8 +20,8 @@ from typing import IO, Any, Callable, Iterator, NamedTuple, Union # Strictly this should not have to include Callable, but mypy doesn't use FunctionType # for functions (python/mypy#3171) -_have_code = Union[types.MethodType, types.FunctionType, types.CodeType, type, Callable[..., Any]] -_have_code_or_string = Union[_have_code, str, bytes] +_HaveCodeType = Union[types.MethodType, types.FunctionType, types.CodeType, type, Callable[..., Any]] +_HaveCodeOrStringType = Union[_HaveCodeType, str, bytes] class Instruction(NamedTuple): opname: str @@ -36,7 +36,7 @@ class Instruction(NamedTuple): class Bytecode: codeobj: types.CodeType first_line: int - def __init__(self, x: _have_code_or_string, *, first_line: int | None = ..., current_offset: int | None = ...) -> None: ... + def __init__(self, x: _HaveCodeOrStringType, *, first_line: int | None = ..., current_offset: int | None = ...) -> None: ... def __iter__(self) -> Iterator[Instruction]: ... def __repr__(self) -> str: ... def info(self) -> str: ... @@ -46,19 +46,19 @@ class Bytecode: COMPILER_FLAG_NAMES: dict[int, str] -def findlabels(code: _have_code) -> list[int]: ... -def findlinestarts(code: _have_code) -> Iterator[tuple[int, int]]: ... +def findlabels(code: _HaveCodeType) -> list[int]: ... +def findlinestarts(code: _HaveCodeType) -> Iterator[tuple[int, int]]: ... def pretty_flags(flags: int) -> str: ... -def code_info(x: _have_code_or_string) -> str: ... +def code_info(x: _HaveCodeOrStringType) -> str: ... if sys.version_info >= (3, 7): - def dis(x: _have_code_or_string | None = ..., *, file: IO[str] | None = ..., depth: int | None = ...) -> None: ... + def dis(x: _HaveCodeOrStringType | None = ..., *, file: IO[str] | None = ..., depth: int | None = ...) -> None: ... else: - def dis(x: _have_code_or_string | None = ..., *, file: IO[str] | None = ...) -> None: ... + def dis(x: _HaveCodeOrStringType | None = ..., *, file: IO[str] | None = ...) -> None: ... def distb(tb: types.TracebackType | None = ..., *, file: IO[str] | None = ...) -> None: ... -def disassemble(co: _have_code, lasti: int = ..., *, file: IO[str] | None = ...) -> None: ... -def disco(co: _have_code, lasti: int = ..., *, file: IO[str] | None = ...) -> None: ... -def show_code(co: _have_code, *, file: IO[str] | None = ...) -> None: ... -def get_instructions(x: _have_code, *, first_line: int | None = ...) -> Iterator[Instruction]: ... +def disassemble(co: _HaveCodeType, lasti: int = ..., *, file: IO[str] | None = ...) -> None: ... +def disco(co: _HaveCodeType, lasti: int = ..., *, file: IO[str] | None = ...) -> None: ... +def show_code(co: _HaveCodeType, *, file: IO[str] | None = ...) -> None: ... +def get_instructions(x: _HaveCodeType, *, first_line: int | None = ...) -> Iterator[Instruction]: ... diff --git a/mypy/typeshed/stdlib/distutils/ccompiler.pyi b/mypy/typeshed/stdlib/distutils/ccompiler.pyi index d21de46915034..7c7023ed0b657 100644 --- a/mypy/typeshed/stdlib/distutils/ccompiler.pyi +++ b/mypy/typeshed/stdlib/distutils/ccompiler.pyi @@ -1,6 +1,6 @@ -from typing import Any, Callable, Optional, Tuple, Union +from typing import Any, Callable, Optional, Union -_Macro = Union[Tuple[str], Tuple[str, Optional[str]]] +_Macro = Union[tuple[str], tuple[str, Optional[str]]] def gen_lib_options( compiler: CCompiler, library_dirs: list[str], runtime_library_dirs: list[str], libraries: list[str] @@ -141,7 +141,7 @@ class CCompiler: def library_filename(self, libname: str, lib_type: str = ..., strip_dir: int = ..., output_dir: str = ...) -> str: ... def object_filenames(self, source_filenames: list[str], strip_dir: int = ..., output_dir: str = ...) -> list[str]: ... def shared_object_filename(self, basename: str, strip_dir: int = ..., output_dir: str = ...) -> str: ... - def execute(self, func: Callable[..., None], args: Tuple[Any, ...], msg: str | None = ..., level: int = ...) -> None: ... + def execute(self, func: Callable[..., None], args: tuple[Any, ...], msg: str | None = ..., level: int = ...) -> None: ... def spawn(self, cmd: list[str]) -> None: ... def mkpath(self, name: str, mode: int = ...) -> None: ... def move_file(self, src: str, dst: str) -> str: ... diff --git a/mypy/typeshed/stdlib/distutils/command/__init__.pyi b/mypy/typeshed/stdlib/distutils/command/__init__.pyi index e69de29bb2d1d..a4b9b1c2bd1b7 100644 --- a/mypy/typeshed/stdlib/distutils/command/__init__.pyi +++ b/mypy/typeshed/stdlib/distutils/command/__init__.pyi @@ -0,0 +1,40 @@ +from . import ( + bdist_dumb as bdist_dumb, + bdist_rpm as bdist_rpm, + build as build, + build_clib as build_clib, + build_ext as build_ext, + build_py as build_py, + build_scripts as build_scripts, + check as check, + clean as clean, + install as install, + install_data as install_data, + install_headers as install_headers, + install_lib as install_lib, + register as register, + sdist as sdist, + upload as upload, +) + +__all__ = [ + "build", + "build_py", + "build_ext", + "build_clib", + "build_scripts", + "clean", + "install", + "install_lib", + "install_headers", + "install_scripts", + "install_data", + "sdist", + "register", + "bdist", + "bdist_dumb", + "bdist_rpm", + "bdist_wininst", + "check", + "upload", +] diff --git a/mypy/typeshed/stdlib/distutils/command/check.pyi b/mypy/typeshed/stdlib/distutils/command/check.pyi index 9149b540f7150..36895d2c16f1c 100644 --- a/mypy/typeshed/stdlib/distutils/command/check.pyi +++ b/mypy/typeshed/stdlib/distutils/command/check.pyi @@ -5,7 +5,7 @@ from ..cmd import Command _Reporter = Any # really docutils.utils.Reporter # Only defined if docutils is installed. -class SilentReporter(_Reporter): # type: ignore +class SilentReporter(_Reporter): messages: Any def __init__( self, diff --git a/mypy/typeshed/stdlib/distutils/command/install.pyi b/mypy/typeshed/stdlib/distutils/command/install.pyi index 47fa8b08d1b2b..661d256e6f078 100644 --- a/mypy/typeshed/stdlib/distutils/command/install.pyi +++ b/mypy/typeshed/stdlib/distutils/command/install.pyi @@ -1,9 +1,9 @@ -from typing import Any, Tuple +from typing import Any from ..cmd import Command HAS_USER_SITE: bool -SCHEME_KEYS: Tuple[str, ...] +SCHEME_KEYS: tuple[str, ...] INSTALL_SCHEMES: dict[str, dict[Any, Any]] class install(Command): diff --git a/mypy/typeshed/stdlib/distutils/fancy_getopt.pyi b/mypy/typeshed/stdlib/distutils/fancy_getopt.pyi index 06a0847e46874..dce8394b6289d 100644 --- a/mypy/typeshed/stdlib/distutils/fancy_getopt.pyi +++ b/mypy/typeshed/stdlib/distutils/fancy_getopt.pyi @@ -1,7 +1,7 @@ -from typing import Any, Iterable, List, Mapping, Optional, Tuple, overload +from typing import Any, Iterable, Mapping, Optional, overload -_Option = Tuple[str, Optional[str], str] -_GR = Tuple[List[str], OptionDummy] +_Option = tuple[str, Optional[str], str] +_GR = tuple[list[str], OptionDummy] def fancy_getopt( options: list[_Option], negative_opt: Mapping[_Option, _Option], object: Any, args: list[str] | None diff --git a/mypy/typeshed/stdlib/distutils/util.pyi b/mypy/typeshed/stdlib/distutils/util.pyi index 9b0915570ecee..03ee0185cac46 100644 --- a/mypy/typeshed/stdlib/distutils/util.pyi +++ b/mypy/typeshed/stdlib/distutils/util.pyi @@ -1,6 +1,6 @@ from _typeshed import StrPath from collections.abc import Callable, Container, Iterable, Mapping -from typing import Any, Tuple +from typing import Any def get_platform() -> str: ... def convert_path(pathname: str) -> str: ... @@ -9,7 +9,7 @@ def check_environ() -> None: ... def subst_vars(s: str, local_vars: Mapping[str, str]) -> None: ... def split_quoted(s: str) -> list[str]: ... def execute( - func: Callable[..., None], args: Tuple[Any, ...], msg: str | None = ..., verbose: bool = ..., dry_run: bool = ... + func: Callable[..., None], args: tuple[Any, ...], msg: str | None = ..., verbose: bool = ..., dry_run: bool = ... ) -> None: ... def strtobool(val: str) -> bool: ... def byte_compile( diff --git a/mypy/typeshed/stdlib/distutils/version.pyi b/mypy/typeshed/stdlib/distutils/version.pyi index 9921dde39af6d..1908cdeda97ad 100644 --- a/mypy/typeshed/stdlib/distutils/version.pyi +++ b/mypy/typeshed/stdlib/distutils/version.pyi @@ -1,5 +1,5 @@ from abc import abstractmethod -from typing import Pattern, Tuple, TypeVar +from typing import Pattern, TypeVar _T = TypeVar("_T", bound=Version) @@ -31,7 +31,7 @@ class StrictVersion(Version): class LooseVersion(Version): component_re: Pattern[str] vstring: str - version: Tuple[str | int, ...] + version: tuple[str | int, ...] def __init__(self, vstring: str | None = ...) -> None: ... def parse(self: _T, vstring: str) -> _T: ... def __str__(self) -> str: ... diff --git a/mypy/typeshed/stdlib/doctest.pyi b/mypy/typeshed/stdlib/doctest.pyi index 9a9f83b0d8fe3..611137740ac4e 100644 --- a/mypy/typeshed/stdlib/doctest.pyi +++ b/mypy/typeshed/stdlib/doctest.pyi @@ -1,6 +1,6 @@ import types import unittest -from typing import Any, Callable, NamedTuple, Tuple, Type +from typing import Any, Callable, NamedTuple, Type class TestResults(NamedTuple): failed: int @@ -86,7 +86,7 @@ class DocTestFinder: ) -> list[DocTest]: ... _Out = Callable[[str], Any] -_ExcInfo = Tuple[Type[BaseException], BaseException, types.TracebackType] +_ExcInfo = tuple[Type[BaseException], BaseException, types.TracebackType] class DocTestRunner: DIVIDER: str diff --git a/mypy/typeshed/stdlib/email/_header_value_parser.pyi b/mypy/typeshed/stdlib/email/_header_value_parser.pyi index f1b08b5d58054..ddb9d9e45913f 100644 --- a/mypy/typeshed/stdlib/email/_header_value_parser.pyi +++ b/mypy/typeshed/stdlib/email/_header_value_parser.pyi @@ -1,7 +1,7 @@ import sys from email.errors import HeaderParseError, MessageDefect from email.policy import Policy -from typing import Any, Iterable, Iterator, List, Pattern, Type, TypeVar, Union +from typing import Any, Iterable, Iterator, Pattern, Type, TypeVar, Union from typing_extensions import Final _T = TypeVar("_T") @@ -23,7 +23,7 @@ def quote_string(value: Any) -> str: ... if sys.version_info >= (3, 7): rfc2047_matcher: Pattern[str] -class TokenList(List[Union[TokenList, Terminal]]): +class TokenList(list[Union[TokenList, Terminal]]): token_type: str | None syntactic_break: bool ew_combine_allowed: bool @@ -334,7 +334,7 @@ class Terminal(str): def pop_trailing_ws(self) -> None: ... @property def comments(self) -> list[str]: ... - def __getnewargs__(self) -> tuple[str, str]: ... # type: ignore + def __getnewargs__(self) -> tuple[str, str]: ... # type: ignore[override] class WhiteSpaceTerminal(Terminal): @property diff --git a/mypy/typeshed/stdlib/email/base64mime.pyi b/mypy/typeshed/stdlib/email/base64mime.pyi new file mode 100644 index 0000000000000..a8030a9789235 --- /dev/null +++ b/mypy/typeshed/stdlib/email/base64mime.pyi @@ -0,0 +1,7 @@ +def header_length(bytearray: str | bytes) -> int: ... +def header_encode(header_bytes: str | bytes, charset: str = ...) -> str: ... +def body_encode(s: bytes, maxlinelen: int = ..., eol: str = ...) -> str: ... +def decode(string: str | bytes) -> bytes: ... + +body_decode = decode +decodestring = decode diff --git a/mypy/typeshed/stdlib/email/headerregistry.pyi b/mypy/typeshed/stdlib/email/headerregistry.pyi index 69e7bf315d9f7..abf10ed4a4fdd 100644 --- a/mypy/typeshed/stdlib/email/headerregistry.pyi +++ b/mypy/typeshed/stdlib/email/headerregistry.pyi @@ -1,5 +1,6 @@ import sys import types +from collections.abc import Iterable, Mapping from datetime import datetime as _datetime from email._header_value_parser import ( AddressList, @@ -12,28 +13,33 @@ from email._header_value_parser import ( ) from email.errors import MessageDefect from email.policy import Policy -from typing import Any, Iterable, Tuple, Type +from typing import Any, ClassVar, Type +from typing_extensions import Literal class BaseHeader(str): + # max_count is actually more of an abstract ClassVar (not defined on the base class, but expected to be defined in subclasses) + max_count: ClassVar[Literal[1] | None] @property def name(self) -> str: ... @property - def defects(self) -> Tuple[MessageDefect, ...]: ... - @property - def max_count(self) -> int | None: ... + def defects(self) -> tuple[MessageDefect, ...]: ... def __new__(cls, name: str, value: Any) -> BaseHeader: ... def init(self, name: str, *, parse_tree: TokenList, defects: Iterable[MessageDefect]) -> None: ... def fold(self, *, policy: Policy) -> str: ... class UnstructuredHeader: + max_count: ClassVar[Literal[1] | None] @staticmethod def value_parser(value: str) -> UnstructuredTokenList: ... @classmethod def parse(cls, value: str, kwds: dict[str, Any]) -> None: ... -class UniqueUnstructuredHeader(UnstructuredHeader): ... +class UniqueUnstructuredHeader(UnstructuredHeader): + max_count: ClassVar[Literal[1]] class DateHeader: + max_count: ClassVar[Literal[1] | None] + def init(self, name: str, *, parse_tree: TokenList, defects: Iterable[MessageDefect], datetime: _datetime) -> None: ... @property def datetime(self) -> _datetime: ... @staticmethod @@ -41,27 +47,43 @@ class DateHeader: @classmethod def parse(cls, value: str | _datetime, kwds: dict[str, Any]) -> None: ... -class UniqueDateHeader(DateHeader): ... +class UniqueDateHeader(DateHeader): + max_count: ClassVar[Literal[1]] class AddressHeader: + max_count: ClassVar[Literal[1] | None] + def init(self, name: str, *, parse_tree: TokenList, defects: Iterable[MessageDefect], groups: Iterable[Group]) -> None: ... @property - def groups(self) -> Tuple[Group, ...]: ... + def groups(self) -> tuple[Group, ...]: ... @property - def addresses(self) -> Tuple[Address, ...]: ... + def addresses(self) -> tuple[Address, ...]: ... @staticmethod def value_parser(value: str) -> AddressList: ... @classmethod def parse(cls, value: str, kwds: dict[str, Any]) -> None: ... -class UniqueAddressHeader(AddressHeader): ... +class UniqueAddressHeader(AddressHeader): + max_count: ClassVar[Literal[1]] class SingleAddressHeader(AddressHeader): @property def address(self) -> Address: ... -class UniqueSingleAddressHeader(SingleAddressHeader): ... +class UniqueSingleAddressHeader(SingleAddressHeader): + max_count: ClassVar[Literal[1]] class MIMEVersionHeader: + max_count: ClassVar[Literal[1]] + def init( + self, + name: str, + *, + parse_tree: TokenList, + defects: Iterable[MessageDefect], + version: str | None, + major: int | None, + minor: int | None, + ) -> None: ... @property def version(self) -> str | None: ... @property @@ -74,6 +96,8 @@ class MIMEVersionHeader: def parse(cls, value: str, kwds: dict[str, Any]) -> None: ... class ParameterizedMIMEHeader: + max_count: ClassVar[Literal[1]] + def init(self, name: str, *, parse_tree: TokenList, defects: Iterable[MessageDefect], params: Mapping[str, Any]) -> None: ... @property def params(self) -> types.MappingProxyType[str, Any]: ... @classmethod @@ -90,12 +114,15 @@ class ContentTypeHeader(ParameterizedMIMEHeader): def value_parser(value: str) -> ContentType: ... class ContentDispositionHeader(ParameterizedMIMEHeader): + # init is redefined but has the same signature as parent class, so is omitted from the stub @property - def content_disposition(self) -> str: ... + def content_disposition(self) -> str | None: ... @staticmethod def value_parser(value: str) -> ContentDisposition: ... class ContentTransferEncodingHeader: + max_count: ClassVar[Literal[1]] + def init(self, name: str, *, parse_tree: TokenList, defects: Iterable[MessageDefect]) -> None: ... @property def cte(self) -> str: ... @classmethod @@ -106,6 +133,7 @@ class ContentTransferEncodingHeader: if sys.version_info >= (3, 8): from email._header_value_parser import MessageID class MessageIDHeader: + max_count: ClassVar[Literal[1]] @classmethod def parse(cls, value: str, kwds: dict[str, Any]) -> None: ... @staticmethod @@ -137,6 +165,6 @@ class Group: @property def display_name(self) -> str | None: ... @property - def addresses(self) -> Tuple[Address, ...]: ... + def addresses(self) -> tuple[Address, ...]: ... def __init__(self, display_name: str | None = ..., addresses: Iterable[Address] | None = ...) -> None: ... def __str__(self) -> str: ... diff --git a/mypy/typeshed/stdlib/email/message.pyi b/mypy/typeshed/stdlib/email/message.pyi index a1749a4cfc2ee..7d5eb4500d8f9 100644 --- a/mypy/typeshed/stdlib/email/message.pyi +++ b/mypy/typeshed/stdlib/email/message.pyi @@ -2,14 +2,14 @@ from email.charset import Charset from email.contentmanager import ContentManager from email.errors import MessageDefect from email.policy import Policy -from typing import Any, Generator, Iterator, List, Optional, Sequence, Tuple, TypeVar, Union +from typing import Any, Generator, Iterator, Optional, Sequence, TypeVar, Union _T = TypeVar("_T") -_PayloadType = Union[List[Message], str, bytes] +_PayloadType = Union[list[Message], str, bytes] _CharsetType = Union[Charset, str, None] -_ParamsType = Union[str, None, Tuple[str, Optional[str], str]] -_ParamType = Union[str, Tuple[Optional[str], Optional[str], str]] +_ParamsType = Union[str, None, tuple[str, Optional[str], str]] +_ParamType = Union[str, tuple[Optional[str], Optional[str], str]] _HeaderType = Any class Message: @@ -69,6 +69,9 @@ class Message: replace: bool = ..., ) -> None: ... def __init__(self, policy: Policy = ...) -> None: ... + # The following two methods are undocumented, but a source code comment states that they are public API + def set_raw(self, name: str, value: str) -> None: ... + def raw_items(self) -> Iterator[tuple[str, str]]: ... class MIMEPart(Message): def __init__(self, policy: Policy | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/email/mime/application.pyi b/mypy/typeshed/stdlib/email/mime/application.pyi index 11fc470e9dd1e..d176cd613e272 100644 --- a/mypy/typeshed/stdlib/email/mime/application.pyi +++ b/mypy/typeshed/stdlib/email/mime/application.pyi @@ -1,8 +1,8 @@ from email.mime.nonmultipart import MIMENonMultipart from email.policy import Policy -from typing import Callable, Optional, Tuple, Union +from typing import Callable, Optional, Union -_ParamsType = Union[str, None, Tuple[str, Optional[str], str]] +_ParamsType = Union[str, None, tuple[str, Optional[str], str]] class MIMEApplication(MIMENonMultipart): def __init__( diff --git a/mypy/typeshed/stdlib/email/mime/audio.pyi b/mypy/typeshed/stdlib/email/mime/audio.pyi index ee6de410bf53d..38657c932e2f7 100644 --- a/mypy/typeshed/stdlib/email/mime/audio.pyi +++ b/mypy/typeshed/stdlib/email/mime/audio.pyi @@ -1,8 +1,8 @@ from email.mime.nonmultipart import MIMENonMultipart from email.policy import Policy -from typing import Callable, Optional, Tuple, Union +from typing import Callable, Optional, Union -_ParamsType = Union[str, None, Tuple[str, Optional[str], str]] +_ParamsType = Union[str, None, tuple[str, Optional[str], str]] class MIMEAudio(MIMENonMultipart): def __init__( diff --git a/mypy/typeshed/stdlib/email/mime/base.pyi b/mypy/typeshed/stdlib/email/mime/base.pyi index b88dfd4925542..cb655607b0327 100644 --- a/mypy/typeshed/stdlib/email/mime/base.pyi +++ b/mypy/typeshed/stdlib/email/mime/base.pyi @@ -1,8 +1,8 @@ import email.message from email.policy import Policy -from typing import Optional, Tuple, Union +from typing import Optional, Union -_ParamsType = Union[str, None, Tuple[str, Optional[str], str]] +_ParamsType = Union[str, None, tuple[str, Optional[str], str]] class MIMEBase(email.message.Message): def __init__(self, _maintype: str, _subtype: str, *, policy: Policy | None = ..., **_params: _ParamsType) -> None: ... diff --git a/mypy/typeshed/stdlib/email/mime/image.pyi b/mypy/typeshed/stdlib/email/mime/image.pyi index 886aa74d5fe5c..0325d9e594da7 100644 --- a/mypy/typeshed/stdlib/email/mime/image.pyi +++ b/mypy/typeshed/stdlib/email/mime/image.pyi @@ -1,8 +1,8 @@ from email.mime.nonmultipart import MIMENonMultipart from email.policy import Policy -from typing import Callable, Optional, Tuple, Union +from typing import Callable, Optional, Union -_ParamsType = Union[str, None, Tuple[str, Optional[str], str]] +_ParamsType = Union[str, None, tuple[str, Optional[str], str]] class MIMEImage(MIMENonMultipart): def __init__( diff --git a/mypy/typeshed/stdlib/email/mime/multipart.pyi b/mypy/typeshed/stdlib/email/mime/multipart.pyi index 6259ddf5ab8fb..6c316c055329f 100644 --- a/mypy/typeshed/stdlib/email/mime/multipart.pyi +++ b/mypy/typeshed/stdlib/email/mime/multipart.pyi @@ -1,9 +1,9 @@ from email.message import Message from email.mime.base import MIMEBase from email.policy import Policy -from typing import Optional, Sequence, Tuple, Union +from typing import Optional, Sequence, Union -_ParamsType = Union[str, None, Tuple[str, Optional[str], str]] +_ParamsType = Union[str, None, tuple[str, Optional[str], str]] class MIMEMultipart(MIMEBase): def __init__( diff --git a/mypy/typeshed/stdlib/email/policy.pyi b/mypy/typeshed/stdlib/email/policy.pyi index 72a54bcfbf083..15991c7e084b8 100644 --- a/mypy/typeshed/stdlib/email/policy.pyi +++ b/mypy/typeshed/stdlib/email/policy.pyi @@ -1,17 +1,27 @@ -from abc import abstractmethod +from abc import ABCMeta, abstractmethod from email.contentmanager import ContentManager from email.errors import MessageDefect from email.header import Header from email.message import Message from typing import Any, Callable -class Policy: +class Policy(metaclass=ABCMeta): max_line_length: int | None linesep: str cte_type: str raise_on_defect: bool - mange_from: bool - def __init__(self, **kw: Any) -> None: ... + mangle_from_: bool + message_factory: Callable[[Policy], Message] | None + def __init__( + self, + *, + max_line_length: int | None = ..., + linesep: str = ..., + cte_type: str = ..., + raise_on_defect: bool = ..., + mangle_from_: bool = ..., + message_factory: Callable[[Policy], Message] | None = ..., + ) -> None: ... def clone(self, **kw: Any) -> Policy: ... def handle_defect(self, obj: Message, defect: MessageDefect) -> None: ... def register_defect(self, obj: Message, defect: MessageDefect) -> None: ... @@ -30,7 +40,7 @@ class Policy: class Compat32(Policy): def header_source_parse(self, sourcelines: list[str]) -> tuple[str, str]: ... def header_store_parse(self, name: str, value: str) -> tuple[str, str]: ... - def header_fetch_parse(self, name: str, value: str) -> str | Header: ... # type: ignore + def header_fetch_parse(self, name: str, value: str) -> str | Header: ... # type: ignore[override] def fold(self, name: str, value: str) -> str: ... def fold_binary(self, name: str, value: str) -> bytes: ... @@ -41,6 +51,20 @@ class EmailPolicy(Policy): refold_source: str header_factory: Callable[[str, str], str] content_manager: ContentManager + def __init__( + self, + *, + max_line_length: int | None = ..., + linesep: str = ..., + cte_type: str = ..., + raise_on_defect: bool = ..., + mangle_from_: bool = ..., + message_factory: Callable[[Policy], Message] | None = ..., + utf8: bool = ..., + refold_source: str = ..., + header_factory: Callable[[str, str], str] = ..., + content_manager: ContentManager = ..., + ) -> None: ... def header_source_parse(self, sourcelines: list[str]) -> tuple[str, str]: ... def header_store_parse(self, name: str, value: str) -> tuple[str, str]: ... def header_fetch_parse(self, name: str, value: str) -> str: ... diff --git a/mypy/typeshed/stdlib/email/quoprimime.pyi b/mypy/typeshed/stdlib/email/quoprimime.pyi new file mode 100644 index 0000000000000..41c4bd8cca9e3 --- /dev/null +++ b/mypy/typeshed/stdlib/email/quoprimime.pyi @@ -0,0 +1,13 @@ +def header_check(octet: int) -> bool: ... +def body_check(octet: int) -> bool: ... +def header_length(bytearray: bytes) -> int: ... +def body_length(bytearray: bytes) -> int: ... +def unquote(s: str | bytes) -> str: ... +def quote(c: str | bytes) -> str: ... +def header_encode(header_bytes: bytes, charset: str = ...) -> str: ... +def body_encode(body: str, maxlinelen: int = ..., eol: str = ...) -> str: ... +def decode(encoded: str, eol: str = ...) -> str: ... +def header_decode(s: str) -> str: ... + +body_decode = decode +decodestring = decode diff --git a/mypy/typeshed/stdlib/email/utils.pyi b/mypy/typeshed/stdlib/email/utils.pyi index 3c07e98079fc2..728a5a53f230f 100644 --- a/mypy/typeshed/stdlib/email/utils.pyi +++ b/mypy/typeshed/stdlib/email/utils.pyi @@ -1,10 +1,10 @@ import datetime import sys from email.charset import Charset -from typing import Optional, Tuple, Union, overload +from typing import Optional, Union, overload -_ParamType = Union[str, Tuple[Optional[str], Optional[str], str]] -_PDTZ = Tuple[int, int, int, int, int, int, int, int, int, Optional[int]] +_ParamType = Union[str, tuple[Optional[str], Optional[str], str]] +_PDTZ = tuple[int, int, int, int, int, int, int, int, int, Optional[int]] def quote(str: str) -> str: ... def unquote(str: str) -> str: ... diff --git a/mypy/typeshed/stdlib/encodings/utf_8_sig.pyi b/mypy/typeshed/stdlib/encodings/utf_8_sig.pyi new file mode 100644 index 0000000000000..bf52e8a6f3d32 --- /dev/null +++ b/mypy/typeshed/stdlib/encodings/utf_8_sig.pyi @@ -0,0 +1,27 @@ +import codecs + +class IncrementalEncoder(codecs.IncrementalEncoder): + def __init__(self, errors: str = ...) -> None: ... + def encode(self, input: str, final: bool = ...) -> bytes: ... + def reset(self) -> None: ... + def getstate(self) -> int: ... # type: ignore[override] + def setstate(self, state: int) -> None: ... # type: ignore[override] + +class IncrementalDecoder(codecs.BufferedIncrementalDecoder): + def __init__(self, errors: str = ...) -> None: ... + def _buffer_decode(self, input: bytes, errors: str | None, final: bool) -> tuple[str, int]: ... + def reset(self) -> None: ... + def getstate(self) -> tuple[bytes, int]: ... + def setstate(self, state: tuple[bytes, int]) -> None: ... + +class StreamWriter(codecs.StreamWriter): + def reset(self) -> None: ... + def encode(self, input: str, errors: str | None = ...) -> tuple[bytes, int]: ... + +class StreamReader(codecs.StreamReader): + def reset(self) -> None: ... + def decode(self, input: bytes, errors: str | None = ...) -> tuple[str, int]: ... + +def getregentry() -> codecs.CodecInfo: ... +def encode(input: str, errors: str | None = ...) -> tuple[bytes, int]: ... +def decode(input: bytes, errors: str | None = ...) -> tuple[str, int]: ... diff --git a/mypy/typeshed/stdlib/enum.pyi b/mypy/typeshed/stdlib/enum.pyi index 07fea104cec75..a80a022ad6f50 100644 --- a/mypy/typeshed/stdlib/enum.pyi +++ b/mypy/typeshed/stdlib/enum.pyi @@ -2,17 +2,49 @@ import sys import types from abc import ABCMeta from builtins import property as _builtins_property -from typing import Any, Iterator, Type, TypeVar +from collections.abc import Iterable, Iterator, Mapping +from typing import Any, Type, TypeVar, Union, overload _T = TypeVar("_T") _S = TypeVar("_S", bound=Type[Enum]) +# The following all work: +# >>> from enum import Enum +# >>> from string import ascii_lowercase +# >>> Enum('Foo', names='RED YELLOW GREEN') +# +# >>> Enum('Foo', names=[('RED', 1), ('YELLOW, 2)]) +# +# >>> Enum('Foo', names=((x for x in (ascii_lowercase[i], i)) for i in range(5))) +# +# >>> Enum('Foo', names={'RED': 1, 'YELLOW': 2}) +# +_EnumNames = Union[str, Iterable[str], Iterable[Iterable[Union[str, Any]]], Mapping[str, Any]] + +class _EnumDict(dict[str, Any]): + def __init__(self) -> None: ... + # Note: EnumMeta actually subclasses type directly, not ABCMeta. # This is a temporary workaround to allow multiple creation of enums with builtins # such as str as mixins, which due to the handling of ABCs of builtin types, cause # spurious inconsistent metaclass structure. See #1595. # Structurally: Iterable[T], Reversible[T], Container[T] where T is the enum itself class EnumMeta(ABCMeta): + if sys.version_info >= (3, 11): + def __new__( + metacls: Type[_T], + cls: str, + bases: tuple[type, ...], + classdict: _EnumDict, + *, + boundary: FlagBoundary | None = ..., + _simple: bool = ..., + **kwds: Any, + ) -> _T: ... + elif sys.version_info >= (3, 9): + def __new__(metacls: Type[_T], cls: str, bases: tuple[type, ...], classdict: _EnumDict, **kwds: Any) -> _T: ... # type: ignore + else: + def __new__(metacls: Type[_T], cls: str, bases: tuple[type, ...], classdict: _EnumDict) -> _T: ... # type: ignore def __iter__(self: Type[_T]) -> Iterator[_T]: ... def __reversed__(self: Type[_T]) -> Iterator[_T]: ... def __contains__(self: Type[Any], member: object) -> bool: ... @@ -20,13 +52,56 @@ class EnumMeta(ABCMeta): @_builtins_property def __members__(self: Type[_T]) -> types.MappingProxyType[str, _T]: ... def __len__(self) -> int: ... + if sys.version_info >= (3, 11): + # Simple value lookup + @overload # type: ignore[override] + def __call__(cls: Type[_T], value: Any, names: None = ...) -> _T: ... + # Functional Enum API + @overload + def __call__( + cls, + value: str, + names: _EnumNames, + *, + module: str | None = ..., + qualname: str | None = ..., + type: type | None = ..., + start: int = ..., + boundary: FlagBoundary | None = ..., + ) -> Type[Enum]: ... + else: + @overload # type: ignore[override] + def __call__(cls: Type[_T], value: Any, names: None = ...) -> _T: ... + @overload + def __call__( + cls, + value: str, + names: _EnumNames, + *, + module: str | None = ..., + qualname: str | None = ..., + type: type | None = ..., + start: int = ..., + ) -> Type[Enum]: ... _member_names_: list[str] # undocumented _member_map_: dict[str, Enum] # undocumented _value2member_map_: dict[Any, Enum] # undocumented +if sys.version_info >= (3, 11): + # In 3.11 `EnumMeta` metaclass is renamed to `EnumType`, but old name also exists. + EnumType = EnumMeta + class Enum(metaclass=EnumMeta): - name: str - value: Any + if sys.version_info >= (3, 11): + @property + def name(self) -> str: ... + @property + def value(self) -> Any: ... + else: + @types.DynamicClassAttribute + def name(self) -> str: ... + @types.DynamicClassAttribute + def value(self) -> Any: ... _name_: str _value_: Any if sys.version_info >= (3, 7): @@ -46,7 +121,13 @@ class Enum(metaclass=EnumMeta): def __reduce_ex__(self, proto: object) -> Any: ... class IntEnum(int, Enum): - value: int + _value_: int + if sys.version_info >= (3, 11): + @property + def value(self) -> int: ... + else: + @types.DynamicClassAttribute + def value(self) -> int: ... def __new__(cls: Type[_T], value: int | _T) -> _T: ... def unique(enumeration: _S) -> _S: ... @@ -55,12 +136,28 @@ _auto_null: Any # subclassing IntFlag so it picks up all implemented base functions, best modeling behavior of enum.auto() class auto(IntFlag): - value: Any + _value_: Any + if sys.version_info >= (3, 11): + @property + def value(self) -> Any: ... + else: + @types.DynamicClassAttribute + def value(self) -> Any: ... def __new__(cls: Type[_T]) -> _T: ... class Flag(Enum): - name: str | None # type: ignore - value: int + _name_: str | None # type: ignore[assignment] + _value_: int + if sys.version_info >= (3, 11): + @property + def name(self) -> str | None: ... # type: ignore[override] + @property + def value(self) -> int: ... + else: + @types.DynamicClassAttribute + def name(self) -> str | None: ... # type: ignore[override] + @types.DynamicClassAttribute + def value(self) -> int: ... def __contains__(self: _T, other: _T) -> bool: ... def __repr__(self) -> str: ... def __str__(self) -> str: ... @@ -81,7 +178,10 @@ class IntFlag(int, Flag): if sys.version_info >= (3, 11): class StrEnum(str, Enum): - def __new__(cls: Type[_T], value: int | _T) -> _T: ... + def __new__(cls: Type[_T], value: str | _T) -> _T: ... + _value_: str + @property + def value(self) -> str: ... class FlagBoundary(StrEnum): STRICT: str CONFORM: str @@ -91,7 +191,10 @@ if sys.version_info >= (3, 11): CONFORM = FlagBoundary.CONFORM EJECT = FlagBoundary.EJECT KEEP = FlagBoundary.KEEP - class property(_builtins_property): ... + class property(types.DynamicClassAttribute): + def __set_name__(self, ownerclass: Type[Enum], name: str) -> None: ... + name: str + clsname: str def global_enum(cls: _S) -> _S: ... def global_enum_repr(self: Enum) -> str: ... def global_flag_repr(self: Flag) -> str: ... diff --git a/mypy/typeshed/stdlib/fcntl.pyi b/mypy/typeshed/stdlib/fcntl.pyi index 141f9ee9360a0..47766357c83fb 100644 --- a/mypy/typeshed/stdlib/fcntl.pyi +++ b/mypy/typeshed/stdlib/fcntl.pyi @@ -3,94 +3,94 @@ from _typeshed import FileDescriptorLike, ReadOnlyBuffer, WriteableBuffer from typing import Any, overload from typing_extensions import Literal -FASYNC: int -FD_CLOEXEC: int -DN_ACCESS: int -DN_ATTRIB: int -DN_CREATE: int -DN_DELETE: int -DN_MODIFY: int -DN_MULTISHOT: int -DN_RENAME: int -F_DUPFD: int -F_DUPFD_CLOEXEC: int -F_FULLFSYNC: int -F_EXLCK: int -F_GETFD: int -F_GETFL: int -F_GETLEASE: int -F_GETLK: int -F_GETLK64: int -F_GETOWN: int -F_NOCACHE: int -F_GETSIG: int -F_NOTIFY: int -F_RDLCK: int -F_SETFD: int -F_SETFL: int -F_SETLEASE: int -F_SETLK: int -F_SETLK64: int -F_SETLKW: int -F_SETLKW64: int -if sys.version_info >= (3, 9) and sys.platform == "linux": - F_OFD_GETLK: int - F_OFD_SETLK: int - F_OFD_SETLKW: int -F_SETOWN: int -F_SETSIG: int -F_SHLCK: int -F_UNLCK: int -F_WRLCK: int -I_ATMARK: int -I_CANPUT: int -I_CKBAND: int -I_FDINSERT: int -I_FIND: int -I_FLUSH: int -I_FLUSHBAND: int -I_GETBAND: int -I_GETCLTIME: int -I_GETSIG: int -I_GRDOPT: int -I_GWROPT: int -I_LINK: int -I_LIST: int -I_LOOK: int -I_NREAD: int -I_PEEK: int -I_PLINK: int -I_POP: int -I_PUNLINK: int -I_PUSH: int -I_RECVFD: int -I_SENDFD: int -I_SETCLTIME: int -I_SETSIG: int -I_SRDOPT: int -I_STR: int -I_SWROPT: int -I_UNLINK: int -LOCK_EX: int -LOCK_MAND: int -LOCK_NB: int -LOCK_READ: int -LOCK_RW: int -LOCK_SH: int -LOCK_UN: int -LOCK_WRITE: int - -@overload -def fcntl(__fd: FileDescriptorLike, __cmd: int, __arg: int = ...) -> int: ... -@overload -def fcntl(__fd: FileDescriptorLike, __cmd: int, __arg: bytes) -> bytes: ... -@overload -def ioctl(__fd: FileDescriptorLike, __request: int, __arg: int = ..., __mutate_flag: bool = ...) -> int: ... -@overload -def ioctl(__fd: FileDescriptorLike, __request: int, __arg: WriteableBuffer, __mutate_flag: Literal[True] = ...) -> int: ... -@overload -def ioctl(__fd: FileDescriptorLike, __request: int, __arg: WriteableBuffer, __mutate_flag: Literal[False]) -> bytes: ... -@overload -def ioctl(__fd: FileDescriptorLike, __request: int, __arg: ReadOnlyBuffer, __mutate_flag: bool = ...) -> bytes: ... -def flock(__fd: FileDescriptorLike, __operation: int) -> None: ... -def lockf(__fd: FileDescriptorLike, __cmd: int, __len: int = ..., __start: int = ..., __whence: int = ...) -> Any: ... +if sys.platform != "win32": + FASYNC: int + FD_CLOEXEC: int + DN_ACCESS: int + DN_ATTRIB: int + DN_CREATE: int + DN_DELETE: int + DN_MODIFY: int + DN_MULTISHOT: int + DN_RENAME: int + F_DUPFD: int + F_DUPFD_CLOEXEC: int + F_FULLFSYNC: int + F_EXLCK: int + F_GETFD: int + F_GETFL: int + F_GETLEASE: int + F_GETLK: int + F_GETLK64: int + F_GETOWN: int + F_NOCACHE: int + F_GETSIG: int + F_NOTIFY: int + F_RDLCK: int + F_SETFD: int + F_SETFL: int + F_SETLEASE: int + F_SETLK: int + F_SETLK64: int + F_SETLKW: int + F_SETLKW64: int + if sys.version_info >= (3, 9) and sys.platform == "linux": + F_OFD_GETLK: int + F_OFD_SETLK: int + F_OFD_SETLKW: int + F_SETOWN: int + F_SETSIG: int + F_SHLCK: int + F_UNLCK: int + F_WRLCK: int + I_ATMARK: int + I_CANPUT: int + I_CKBAND: int + I_FDINSERT: int + I_FIND: int + I_FLUSH: int + I_FLUSHBAND: int + I_GETBAND: int + I_GETCLTIME: int + I_GETSIG: int + I_GRDOPT: int + I_GWROPT: int + I_LINK: int + I_LIST: int + I_LOOK: int + I_NREAD: int + I_PEEK: int + I_PLINK: int + I_POP: int + I_PUNLINK: int + I_PUSH: int + I_RECVFD: int + I_SENDFD: int + I_SETCLTIME: int + I_SETSIG: int + I_SRDOPT: int + I_STR: int + I_SWROPT: int + I_UNLINK: int + LOCK_EX: int + LOCK_MAND: int + LOCK_NB: int + LOCK_READ: int + LOCK_RW: int + LOCK_SH: int + LOCK_UN: int + LOCK_WRITE: int + @overload + def fcntl(__fd: FileDescriptorLike, __cmd: int, __arg: int = ...) -> int: ... + @overload + def fcntl(__fd: FileDescriptorLike, __cmd: int, __arg: bytes) -> bytes: ... + @overload + def ioctl(__fd: FileDescriptorLike, __request: int, __arg: int = ..., __mutate_flag: bool = ...) -> int: ... + @overload + def ioctl(__fd: FileDescriptorLike, __request: int, __arg: WriteableBuffer, __mutate_flag: Literal[True] = ...) -> int: ... + @overload + def ioctl(__fd: FileDescriptorLike, __request: int, __arg: WriteableBuffer, __mutate_flag: Literal[False]) -> bytes: ... + @overload + def ioctl(__fd: FileDescriptorLike, __request: int, __arg: ReadOnlyBuffer, __mutate_flag: bool = ...) -> bytes: ... + def flock(__fd: FileDescriptorLike, __operation: int) -> None: ... + def lockf(__fd: FileDescriptorLike, __cmd: int, __len: int = ..., __start: int = ..., __whence: int = ...) -> Any: ... diff --git a/mypy/typeshed/stdlib/fileinput.pyi b/mypy/typeshed/stdlib/fileinput.pyi index 3c14b736ca50a..576822059560d 100644 --- a/mypy/typeshed/stdlib/fileinput.pyi +++ b/mypy/typeshed/stdlib/fileinput.pyi @@ -85,7 +85,8 @@ class FileInput(Iterable[AnyStr], Generic[AnyStr]): def __exit__(self, type: Any, value: Any, traceback: Any) -> None: ... def __iter__(self) -> Iterator[AnyStr]: ... def __next__(self) -> AnyStr: ... - def __getitem__(self, i: int) -> AnyStr: ... + if sys.version_info < (3, 11): + def __getitem__(self, i: int) -> AnyStr: ... def nextfile(self) -> None: ... def readline(self) -> AnyStr: ... def filename(self) -> str: ... diff --git a/mypy/typeshed/stdlib/formatter.pyi b/mypy/typeshed/stdlib/formatter.pyi index 7c3b97688dbd8..f5d8348d08a1d 100644 --- a/mypy/typeshed/stdlib/formatter.pyi +++ b/mypy/typeshed/stdlib/formatter.pyi @@ -1,8 +1,8 @@ -from typing import IO, Any, Iterable, Tuple +from typing import IO, Any, Iterable AS_IS: None -_FontType = Tuple[str, bool, bool, bool] -_StylesType = Tuple[Any, ...] +_FontType = tuple[str, bool, bool, bool] +_StylesType = tuple[Any, ...] class NullFormatter: writer: NullWriter | None @@ -68,7 +68,7 @@ class NullWriter: def new_font(self, font: _FontType) -> None: ... def new_margin(self, margin: int, level: int) -> None: ... def new_spacing(self, spacing: str | None) -> None: ... - def new_styles(self, styles: Tuple[Any, ...]) -> None: ... + def new_styles(self, styles: tuple[Any, ...]) -> None: ... def send_paragraph(self, blankline: int) -> None: ... def send_line_break(self) -> None: ... def send_hor_rule(self, *args: Any, **kw: Any) -> None: ... @@ -81,7 +81,7 @@ class AbstractWriter(NullWriter): def new_font(self, font: _FontType) -> None: ... def new_margin(self, margin: int, level: int) -> None: ... def new_spacing(self, spacing: str | None) -> None: ... - def new_styles(self, styles: Tuple[Any, ...]) -> None: ... + def new_styles(self, styles: tuple[Any, ...]) -> None: ... def send_paragraph(self, blankline: int) -> None: ... def send_line_break(self) -> None: ... def send_hor_rule(self, *args: Any, **kw: Any) -> None: ... diff --git a/mypy/typeshed/stdlib/fractions.pyi b/mypy/typeshed/stdlib/fractions.pyi index 3c68086512752..8de5ae20971c9 100644 --- a/mypy/typeshed/stdlib/fractions.pyi +++ b/mypy/typeshed/stdlib/fractions.pyi @@ -134,6 +134,8 @@ class Fraction(Rational): def __le__(self, other: _ComparableNum) -> bool: ... def __ge__(self, other: _ComparableNum) -> bool: ... def __bool__(self) -> bool: ... + if sys.version_info >= (3, 11): + def __int__(self) -> int: ... # Not actually defined within fractions.py, but provides more useful # overrides @property diff --git a/mypy/typeshed/stdlib/ftplib.pyi b/mypy/typeshed/stdlib/ftplib.pyi index 3f4f892bb516f..f84199c168e98 100644 --- a/mypy/typeshed/stdlib/ftplib.pyi +++ b/mypy/typeshed/stdlib/ftplib.pyi @@ -3,7 +3,7 @@ from _typeshed import Self, SupportsRead, SupportsReadline from socket import socket from ssl import SSLContext from types import TracebackType -from typing import Any, Callable, Iterable, Iterator, TextIO, Tuple, Type +from typing import Any, Callable, Iterable, Iterator, TextIO, Type from typing_extensions import Literal MSG_OOB: int @@ -18,7 +18,7 @@ class error_temp(Error): ... class error_perm(Error): ... class error_proto(Error): ... -all_errors: Tuple[Type[Exception], ...] +all_errors: tuple[Type[Exception], ...] class FTP: debugging: int @@ -33,10 +33,6 @@ class FTP: lastresp: str file: TextIO | None encoding: str - - # The following variable is intentionally left undocumented. - # See https://bugs.python.org/issue43285 for relevant discussion - # trust_server_pasv_ipv4_address: bool def __enter__(self: Self) -> Self: ... def __exit__( self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None diff --git a/mypy/typeshed/stdlib/functools.pyi b/mypy/typeshed/stdlib/functools.pyi index b5e52bf599205..990fed20d80da 100644 --- a/mypy/typeshed/stdlib/functools.pyi +++ b/mypy/typeshed/stdlib/functools.pyi @@ -1,7 +1,7 @@ import sys import types -from _typeshed import SupportsItems, SupportsLessThan -from typing import Any, Callable, Generic, Hashable, Iterable, NamedTuple, Sequence, Sized, Tuple, Type, TypeVar, overload +from _typeshed import SupportsAllComparisons, SupportsItems +from typing import Any, Callable, Generic, Hashable, Iterable, NamedTuple, Sequence, Sized, Type, TypeVar, overload from typing_extensions import final if sys.version_info >= (3, 9): @@ -45,13 +45,13 @@ WRAPPER_UPDATES: Sequence[str] def update_wrapper(wrapper: _T, wrapped: _AnyCallable, assigned: Sequence[str] = ..., updated: Sequence[str] = ...) -> _T: ... def wraps(wrapped: _AnyCallable, assigned: Sequence[str] = ..., updated: Sequence[str] = ...) -> Callable[[_T], _T]: ... def total_ordering(cls: Type[_T]) -> Type[_T]: ... -def cmp_to_key(mycmp: Callable[[_T, _T], int]) -> Callable[[_T], SupportsLessThan]: ... +def cmp_to_key(mycmp: Callable[[_T, _T], int]) -> Callable[[_T], SupportsAllComparisons]: ... class partial(Generic[_T]): func: Callable[..., _T] - args: Tuple[Any, ...] + args: tuple[Any, ...] keywords: dict[str, Any] - def __init__(self, func: Callable[..., _T], *args: Any, **kwargs: Any) -> None: ... + def __new__(cls: Type[_S], __func: Callable[..., _T], *args: Any, **kwargs: Any) -> _S: ... def __call__(self, *args: Any, **kwargs: Any) -> _T: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... @@ -61,7 +61,7 @@ _Descriptor = Any class partialmethod(Generic[_T]): func: Callable[..., _T] | _Descriptor - args: Tuple[Any, ...] + args: tuple[Any, ...] keywords: dict[str, Any] @overload def __init__(self, __func: Callable[..., _T], *args: Any, **keywords: Any) -> None: ... @@ -120,10 +120,10 @@ if sys.version_info >= (3, 9): def cache(__user_function: Callable[..., _T]) -> _lru_cache_wrapper[_T]: ... def _make_key( - args: Tuple[Hashable, ...], + args: tuple[Hashable, ...], kwds: SupportsItems[Any, Any], typed: bool, - kwd_mark: Tuple[object, ...] = ..., + kwd_mark: tuple[object, ...] = ..., fasttypes: set[type] = ..., tuple: type = ..., type: Any = ..., diff --git a/mypy/typeshed/stdlib/genericpath.pyi b/mypy/typeshed/stdlib/genericpath.pyi index 56683e323178c..f9518750d3f1f 100644 --- a/mypy/typeshed/stdlib/genericpath.pyi +++ b/mypy/typeshed/stdlib/genericpath.pyi @@ -1,6 +1,6 @@ import os -from _typeshed import BytesPath, StrOrBytesPath, StrPath, SupportsLessThanT -from typing import Sequence, Tuple, overload +from _typeshed import BytesPath, StrOrBytesPath, StrPath, SupportsRichComparisonT +from typing import Sequence, overload from typing_extensions import Literal # All overloads can return empty string. Ideally, Literal[""] would be a valid @@ -11,9 +11,9 @@ def commonprefix(m: Sequence[StrPath]) -> str: ... @overload def commonprefix(m: Sequence[BytesPath]) -> bytes | Literal[""]: ... @overload -def commonprefix(m: Sequence[list[SupportsLessThanT]]) -> Sequence[SupportsLessThanT]: ... +def commonprefix(m: Sequence[list[SupportsRichComparisonT]]) -> Sequence[SupportsRichComparisonT]: ... @overload -def commonprefix(m: Sequence[Tuple[SupportsLessThanT, ...]]) -> Sequence[SupportsLessThanT]: ... +def commonprefix(m: Sequence[tuple[SupportsRichComparisonT, ...]]) -> Sequence[SupportsRichComparisonT]: ... def exists(path: StrOrBytesPath | int) -> bool: ... def getsize(filename: StrOrBytesPath | int) -> int: ... def isfile(path: StrOrBytesPath | int) -> bool: ... diff --git a/mypy/typeshed/stdlib/gettext.pyi b/mypy/typeshed/stdlib/gettext.pyi index b408d3f7485c4..21be9fb1ff299 100644 --- a/mypy/typeshed/stdlib/gettext.pyi +++ b/mypy/typeshed/stdlib/gettext.pyi @@ -16,8 +16,9 @@ class NullTranslations: def npgettext(self, context: str, msgid1: str, msgid2: str, n: int) -> str: ... def info(self) -> Any: ... def charset(self) -> Any: ... - def output_charset(self) -> Any: ... - def set_output_charset(self, charset: str) -> None: ... + if sys.version_info < (3, 11): + def output_charset(self) -> Any: ... + def set_output_charset(self, charset: str) -> None: ... def install(self, names: Container[str] | None = ...) -> None: ... class GNUTranslations(NullTranslations): @@ -30,47 +31,71 @@ def find(domain: str, localedir: StrPath | None = ..., languages: Iterable[str] _T = TypeVar("_T") -@overload -def translation( - domain: str, - localedir: StrPath | None = ..., - languages: Iterable[str] | None = ..., - class_: None = ..., - fallback: bool = ..., - codeset: str | None = ..., -) -> NullTranslations: ... -@overload -def translation( - domain: str, - localedir: StrPath | None = ..., - languages: Iterable[str] | None = ..., - class_: Type[_T] = ..., - fallback: Literal[False] = ..., - codeset: str | None = ..., -) -> _T: ... -@overload -def translation( - domain: str, - localedir: StrPath | None = ..., - languages: Iterable[str] | None = ..., - class_: Type[Any] = ..., - fallback: Literal[True] = ..., - codeset: str | None = ..., -) -> Any: ... -def install( - domain: str, localedir: StrPath | None = ..., codeset: str | None = ..., names: Container[str] | None = ... -) -> None: ... +if sys.version_info >= (3, 11): + @overload + def translation( + domain: str, + localedir: StrPath | None = ..., + languages: Iterable[str] | None = ..., + class_: None = ..., + fallback: bool = ..., + ) -> NullTranslations: ... + @overload + def translation( + domain: str, + localedir: StrPath | None = ..., + languages: Iterable[str] | None = ..., + class_: Type[_T] = ..., + fallback: Literal[False] = ..., + ) -> _T: ... + @overload + def translation( + domain: str, + localedir: StrPath | None = ..., + languages: Iterable[str] | None = ..., + class_: Type[Any] = ..., + fallback: Literal[True] = ..., + ) -> Any: ... + def install(domain: str, localedir: StrPath | None = ..., names: Container[str] | None = ...) -> None: ... + +else: + @overload + def translation( + domain: str, + localedir: StrPath | None = ..., + languages: Iterable[str] | None = ..., + class_: None = ..., + fallback: bool = ..., + codeset: str | None = ..., + ) -> NullTranslations: ... + @overload + def translation( + domain: str, + localedir: StrPath | None = ..., + languages: Iterable[str] | None = ..., + class_: Type[_T] = ..., + fallback: Literal[False] = ..., + codeset: str | None = ..., + ) -> _T: ... + @overload + def translation( + domain: str, + localedir: StrPath | None = ..., + languages: Iterable[str] | None = ..., + class_: Type[Any] = ..., + fallback: Literal[True] = ..., + codeset: str | None = ..., + ) -> Any: ... + def install( + domain: str, localedir: StrPath | None = ..., codeset: str | None = ..., names: Container[str] | None = ... + ) -> None: ... + def textdomain(domain: str | None = ...) -> str: ... def bindtextdomain(domain: str, localedir: StrPath | None = ...) -> str: ... -def bind_textdomain_codeset(domain: str, codeset: str | None = ...) -> str: ... def dgettext(domain: str, message: str) -> str: ... -def ldgettext(domain: str, message: str) -> str: ... def dngettext(domain: str, msgid1: str, msgid2: str, n: int) -> str: ... -def ldngettext(domain: str, msgid1: str, msgid2: str, n: int) -> str: ... def gettext(message: str) -> str: ... -def lgettext(message: str) -> str: ... def ngettext(msgid1: str, msgid2: str, n: int) -> str: ... -def lngettext(msgid1: str, msgid2: str, n: int) -> str: ... if sys.version_info >= (3, 8): def pgettext(context: str, message: str) -> str: ... @@ -78,4 +103,11 @@ if sys.version_info >= (3, 8): def npgettext(context: str, msgid1: str, msgid2: str, n: int) -> str: ... def dnpgettext(domain: str, context: str, msgid1: str, msgid2: str, n: int) -> str: ... +if sys.version_info < (3, 11): + def lgettext(message: str) -> str: ... + def ldgettext(domain: str, message: str) -> str: ... + def lngettext(msgid1: str, msgid2: str, n: int) -> str: ... + def ldngettext(domain: str, msgid1: str, msgid2: str, n: int) -> str: ... + def bind_textdomain_codeset(domain: str, codeset: str | None = ...) -> str: ... + Catalog = translation diff --git a/mypy/typeshed/stdlib/graphlib.pyi b/mypy/typeshed/stdlib/graphlib.pyi index 0872af4a54a4f..96d64cbce18cc 100644 --- a/mypy/typeshed/stdlib/graphlib.pyi +++ b/mypy/typeshed/stdlib/graphlib.pyi @@ -1,5 +1,5 @@ from _typeshed import SupportsItems -from typing import Generic, Iterable, Tuple, TypeVar +from typing import Generic, Iterable, TypeVar _T = TypeVar("_T") @@ -10,7 +10,7 @@ class TopologicalSorter(Generic[_T]): def is_active(self) -> bool: ... def __bool__(self) -> bool: ... def done(self, *nodes: _T) -> None: ... - def get_ready(self) -> Tuple[_T, ...]: ... + def get_ready(self) -> tuple[_T, ...]: ... def static_order(self) -> Iterable[_T]: ... class CycleError(ValueError): ... diff --git a/mypy/typeshed/stdlib/grp.pyi b/mypy/typeshed/stdlib/grp.pyi index 08cbe6b86476e..b416269921d6d 100644 --- a/mypy/typeshed/stdlib/grp.pyi +++ b/mypy/typeshed/stdlib/grp.pyi @@ -1,11 +1,19 @@ -from typing import NamedTuple +import sys +from _typeshed import structseq +from typing import Any, Optional +from typing_extensions import final -class struct_group(NamedTuple): - gr_name: str - gr_passwd: str | None - gr_gid: int - gr_mem: list[str] - -def getgrall() -> list[struct_group]: ... -def getgrgid(id: int) -> struct_group: ... -def getgrnam(name: str) -> struct_group: ... +if sys.platform != "win32": + @final + class struct_group(structseq[Any], tuple[str, Optional[str], int, list[str]]): + @property + def gr_name(self) -> str: ... + @property + def gr_passwd(self) -> str | None: ... + @property + def gr_gid(self) -> int: ... + @property + def gr_mem(self) -> list[str]: ... + def getgrall() -> list[struct_group]: ... + def getgrgid(id: int) -> struct_group: ... + def getgrnam(name: str) -> struct_group: ... diff --git a/mypy/typeshed/stdlib/hashlib.pyi b/mypy/typeshed/stdlib/hashlib.pyi index e39f2f25326ef..fad3c5aad457c 100644 --- a/mypy/typeshed/stdlib/hashlib.pyi +++ b/mypy/typeshed/stdlib/hashlib.pyi @@ -2,7 +2,7 @@ import sys from _typeshed import ReadableBuffer, Self from typing import AbstractSet -class _Hash(object): +class _Hash: @property def digest_size(self) -> int: ... @property @@ -49,7 +49,7 @@ def pbkdf2_hmac( hash_name: str, password: ReadableBuffer, salt: ReadableBuffer, iterations: int, dklen: int | None = ... ) -> bytes: ... -class _VarLenHash(object): +class _VarLenHash: digest_size: int block_size: int name: str diff --git a/mypy/typeshed/stdlib/heapq.pyi b/mypy/typeshed/stdlib/heapq.pyi index 81ee02582a6af..fd3c2db8ad668 100644 --- a/mypy/typeshed/stdlib/heapq.pyi +++ b/mypy/typeshed/stdlib/heapq.pyi @@ -1,4 +1,4 @@ -from _typeshed import SupportsLessThan +from _typeshed import SupportsRichComparison from typing import Any, Callable, Iterable, TypeVar _T = TypeVar("_T") @@ -9,6 +9,6 @@ def heappushpop(__heap: list[_T], __item: _T) -> _T: ... def heapify(__heap: list[Any]) -> None: ... def heapreplace(__heap: list[_T], __item: _T) -> _T: ... def merge(*iterables: Iterable[_T], key: Callable[[_T], Any] | None = ..., reverse: bool = ...) -> Iterable[_T]: ... -def nlargest(n: int, iterable: Iterable[_T], key: Callable[[_T], SupportsLessThan] | None = ...) -> list[_T]: ... -def nsmallest(n: int, iterable: Iterable[_T], key: Callable[[_T], SupportsLessThan] | None = ...) -> list[_T]: ... +def nlargest(n: int, iterable: Iterable[_T], key: Callable[[_T], SupportsRichComparison] | None = ...) -> list[_T]: ... +def nsmallest(n: int, iterable: Iterable[_T], key: Callable[[_T], SupportsRichComparison] | None = ...) -> list[_T]: ... def _heapify_max(__x: list[Any]) -> None: ... # undocumented diff --git a/mypy/typeshed/stdlib/hmac.pyi b/mypy/typeshed/stdlib/hmac.pyi index 440bddd7919c3..88c88631f99a1 100644 --- a/mypy/typeshed/stdlib/hmac.pyi +++ b/mypy/typeshed/stdlib/hmac.pyi @@ -7,6 +7,9 @@ from typing import Any, AnyStr, Callable, Union, overload _Hash = Any _DigestMod = Union[str, Callable[[], _Hash], ModuleType] +trans_5C: bytes +trans_36: bytes + digest_size: None if sys.version_info >= (3, 8): diff --git a/mypy/typeshed/stdlib/html/parser.pyi b/mypy/typeshed/stdlib/html/parser.pyi index fec3f3509522d..60e0de51d3b8a 100644 --- a/mypy/typeshed/stdlib/html/parser.pyi +++ b/mypy/typeshed/stdlib/html/parser.pyi @@ -1,5 +1,5 @@ from _markupbase import ParserBase -from typing import Tuple +from typing import Pattern class HTMLParser(ParserBase): def __init__(self, *, convert_charrefs: bool = ...) -> None: ... @@ -18,7 +18,7 @@ class HTMLParser(ParserBase): def handle_decl(self, decl: str) -> None: ... def handle_pi(self, data: str) -> None: ... def unknown_decl(self, data: str) -> None: ... - CDATA_CONTENT_ELEMENTS: Tuple[str, ...] + CDATA_CONTENT_ELEMENTS: tuple[str, ...] def check_for_whole_start_tag(self, i: int) -> int: ... # undocumented def clear_cdata_mode(self) -> None: ... # undocumented def goahead(self, end: bool) -> None: ... # undocumented @@ -28,3 +28,8 @@ class HTMLParser(ParserBase): def parse_pi(self, i: int) -> int: ... # undocumented def parse_starttag(self, i: int) -> int: ... # undocumented def set_cdata_mode(self, elem: str) -> None: ... # undocumented + rawdata: str # undocumented + cdata_elem: str | None # undocumented + convert_charrefs: bool # undocumented + interesting: Pattern[str] # undocumented + lasttag: str # undocumented diff --git a/mypy/typeshed/stdlib/http/client.pyi b/mypy/typeshed/stdlib/http/client.pyi index c450db587135b..1558f6ff46e89 100644 --- a/mypy/typeshed/stdlib/http/client.pyi +++ b/mypy/typeshed/stdlib/http/client.pyi @@ -96,7 +96,7 @@ class HTTPResponse(io.BufferedIOBase, BinaryIO): def read(self, amt: int | None = ...) -> bytes: ... def read1(self, n: int = ...) -> bytes: ... def readinto(self, b: WriteableBuffer) -> int: ... - def readline(self, limit: int = ...) -> bytes: ... # type: ignore + def readline(self, limit: int = ...) -> bytes: ... # type: ignore[override] @overload def getheader(self, name: str) -> str | None: ... @overload diff --git a/mypy/typeshed/stdlib/http/cookiejar.pyi b/mypy/typeshed/stdlib/http/cookiejar.pyi index f37fb19cebe9d..6bfa7f385e695 100644 --- a/mypy/typeshed/stdlib/http/cookiejar.pyi +++ b/mypy/typeshed/stdlib/http/cookiejar.pyi @@ -1,7 +1,7 @@ import sys from _typeshed import StrPath from http.client import HTTPResponse -from typing import ClassVar, Iterable, Iterator, Pattern, Sequence, Tuple, TypeVar, overload +from typing import ClassVar, Iterable, Iterator, Pattern, Sequence, TypeVar, overload from urllib.request import Request _T = TypeVar("_T") @@ -102,10 +102,10 @@ class DefaultCookiePolicy(CookiePolicy): strict_ns_set_initial_dollar: bool = ..., strict_ns_set_path: bool = ..., ) -> None: ... - def blocked_domains(self) -> Tuple[str, ...]: ... + def blocked_domains(self) -> tuple[str, ...]: ... def set_blocked_domains(self, blocked_domains: Sequence[str]) -> None: ... def is_blocked(self, domain: str) -> bool: ... - def allowed_domains(self) -> Tuple[str, ...] | None: ... + def allowed_domains(self) -> tuple[str, ...] | None: ... def set_allowed_domains(self, allowed_domains: Sequence[str] | None) -> None: ... def is_not_allowed(self, domain: str) -> bool: ... def set_ok_version(self, cookie: Cookie, request: Request) -> bool: ... # undocumented diff --git a/mypy/typeshed/stdlib/http/cookies.pyi b/mypy/typeshed/stdlib/http/cookies.pyi index 7e9513adb1a16..211fd37662d4c 100644 --- a/mypy/typeshed/stdlib/http/cookies.pyi +++ b/mypy/typeshed/stdlib/http/cookies.pyi @@ -1,5 +1,5 @@ import sys -from typing import Any, Dict, Generic, Iterable, Mapping, TypeVar, Union, overload +from typing import Any, Generic, Iterable, Mapping, TypeVar, Union, overload if sys.version_info >= (3, 9): from types import GenericAlias @@ -18,7 +18,7 @@ def _unquote(str: str) -> str: ... class CookieError(Exception): ... -class Morsel(Dict[str, Any], Generic[_T]): +class Morsel(dict[str, Any], Generic[_T]): value: str coded_value: _T key: str @@ -29,7 +29,7 @@ class Morsel(Dict[str, Any], Generic[_T]): def set(self, key: str, val: str, coded_val: _T, LegalChars: str = ...) -> None: ... def setdefault(self, key: str, val: str | None = ...) -> str: ... # The dict update can also get a keywords argument so this is incompatible - @overload # type: ignore + @overload # type: ignore[override] def update(self, values: Mapping[str, str]) -> None: ... @overload def update(self, values: Iterable[tuple[str, str]]) -> None: ... @@ -40,7 +40,7 @@ class Morsel(Dict[str, Any], Generic[_T]): if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... -class BaseCookie(Dict[str, Morsel[_T]], Generic[_T]): +class BaseCookie(dict[str, Morsel[_T]], Generic[_T]): def __init__(self, input: _DataType | None = ...) -> None: ... def value_decode(self, val: str) -> _T: ... def value_encode(self, val: _T) -> str: ... diff --git a/mypy/typeshed/stdlib/imaplib.pyi b/mypy/typeshed/stdlib/imaplib.pyi index a9f19048c9ae1..1b2774d8fde06 100644 --- a/mypy/typeshed/stdlib/imaplib.pyi +++ b/mypy/typeshed/stdlib/imaplib.pyi @@ -5,14 +5,14 @@ from _typeshed import Self from socket import socket as _socket from ssl import SSLContext, SSLSocket from types import TracebackType -from typing import IO, Any, Callable, List, Pattern, Tuple, Type, Union +from typing import IO, Any, Callable, Pattern, Type, Union from typing_extensions import Literal # TODO: Commands should use their actual return types, not this type alias. # E.g. Tuple[Literal["OK"], List[bytes]] -_CommandResults = Tuple[str, List[Any]] +_CommandResults = tuple[str, list[Any]] -_AnyResponseData = Union[List[None], List[Union[bytes, Tuple[bytes, bytes]]]] +_AnyResponseData = Union[list[None], list[Union[bytes, tuple[bytes, bytes]]]] _list = list # conflicts with a method named "list" diff --git a/mypy/typeshed/stdlib/importlib/abc.pyi b/mypy/typeshed/stdlib/importlib/abc.pyi index 2e18f3f899a2e..9bb370dfd7e83 100644 --- a/mypy/typeshed/stdlib/importlib/abc.pyi +++ b/mypy/typeshed/stdlib/importlib/abc.pyi @@ -12,8 +12,8 @@ from _typeshed import ( from abc import ABCMeta, abstractmethod from importlib.machinery import ModuleSpec from io import BufferedRandom, BufferedReader, BufferedWriter, FileIO, TextIOWrapper -from typing import IO, Any, BinaryIO, Iterator, Mapping, Protocol, Sequence, Union, overload -from typing_extensions import Literal, runtime_checkable +from typing import IO, Any, BinaryIO, Iterator, Mapping, NoReturn, Protocol, Sequence, Union, overload, runtime_checkable +from typing_extensions import Literal _Path = Union[bytes, str] @@ -85,8 +85,12 @@ if sys.version_info >= (3, 7): def open_resource(self, resource: StrOrBytesPath) -> IO[bytes]: ... @abstractmethod def resource_path(self, resource: StrOrBytesPath) -> str: ... - @abstractmethod - def is_resource(self, name: str) -> bool: ... + if sys.version_info >= (3, 10): + @abstractmethod + def is_resource(self, path: str) -> bool: ... + else: + @abstractmethod + def is_resource(self, name: str) -> bool: ... @abstractmethod def contents(self) -> Iterator[str]: ... @@ -169,3 +173,10 @@ if sys.version_info >= (3, 9): def read_bytes(self) -> bytes: ... @abstractmethod def read_text(self, encoding: str | None = ...) -> str: ... + class TraversableResources(ResourceReader): + @abstractmethod + def files(self) -> Traversable: ... + def open_resource(self, resource: StrPath) -> BufferedReader: ... # type: ignore[override] + def resource_path(self, resource: Any) -> NoReturn: ... + def is_resource(self, path: StrPath) -> bool: ... + def contents(self) -> Iterator[str]: ... diff --git a/mypy/typeshed/stdlib/importlib/machinery.pyi b/mypy/typeshed/stdlib/importlib/machinery.pyi index 432bec9011613..b73f9c5275836 100644 --- a/mypy/typeshed/stdlib/importlib/machinery.pyi +++ b/mypy/typeshed/stdlib/importlib/machinery.pyi @@ -1,6 +1,10 @@ import importlib.abc +import sys import types -from typing import Any, Callable, Sequence +from typing import Any, Callable, Iterable, Sequence + +if sys.version_info >= (3, 8): + from importlib.metadata import DistributionFinder, PathDistribution class ModuleSpec: def __init__( @@ -41,10 +45,16 @@ class BuiltinImporter(importlib.abc.MetaPathFinder, importlib.abc.InspectLoader) # Loader @staticmethod def module_repr(module: types.ModuleType) -> str: ... - @classmethod - def create_module(cls, spec: ModuleSpec) -> types.ModuleType | None: ... - @classmethod - def exec_module(cls, module: types.ModuleType) -> None: ... + if sys.version_info >= (3, 10): + @staticmethod + def create_module(spec: ModuleSpec) -> types.ModuleType | None: ... + @staticmethod + def exec_module(module: types.ModuleType) -> None: ... + else: + @classmethod + def create_module(cls, spec: ModuleSpec) -> types.ModuleType | None: ... + @classmethod + def exec_module(cls, module: types.ModuleType) -> None: ... class FrozenImporter(importlib.abc.MetaPathFinder, importlib.abc.InspectLoader): # MetaPathFinder @@ -66,8 +76,12 @@ class FrozenImporter(importlib.abc.MetaPathFinder, importlib.abc.InspectLoader): # Loader @staticmethod def module_repr(m: types.ModuleType) -> str: ... - @classmethod - def create_module(cls, spec: ModuleSpec) -> types.ModuleType | None: ... + if sys.version_info >= (3, 10): + @staticmethod + def create_module(spec: ModuleSpec) -> types.ModuleType | None: ... + else: + @classmethod + def create_module(cls, spec: ModuleSpec) -> types.ModuleType | None: ... @staticmethod def exec_module(module: types.ModuleType) -> None: ... @@ -80,8 +94,18 @@ class WindowsRegistryFinder(importlib.abc.MetaPathFinder): ) -> ModuleSpec | None: ... class PathFinder: - @classmethod - def invalidate_caches(cls) -> None: ... + if sys.version_info >= (3, 10): + @staticmethod + def invalidate_caches() -> None: ... + else: + @classmethod + def invalidate_caches(cls) -> None: ... + if sys.version_info >= (3, 10): + @staticmethod + def find_distributions(context: DistributionFinder.Context = ...) -> Iterable[PathDistribution]: ... + elif sys.version_info >= (3, 8): + @classmethod + def find_distributions(cls, context: DistributionFinder.Context = ...) -> Iterable[PathDistribution]: ... @classmethod def find_spec( cls, fullname: str, path: Sequence[bytes | str] | None = ..., target: types.ModuleType | None = ... diff --git a/mypy/typeshed/stdlib/importlib/metadata.pyi b/mypy/typeshed/stdlib/importlib/metadata/__init__.pyi similarity index 80% rename from mypy/typeshed/stdlib/importlib/metadata.pyi rename to mypy/typeshed/stdlib/importlib/metadata/__init__.pyi index 2c1041b765035..a9e223149b52c 100644 --- a/mypy/typeshed/stdlib/importlib/metadata.pyi +++ b/mypy/typeshed/stdlib/importlib/metadata/__init__.pyi @@ -7,9 +7,10 @@ from email.message import Message from importlib.abc import MetaPathFinder from os import PathLike from pathlib import Path -from typing import Any, Iterable, NamedTuple, Tuple, overload +from typing import Any, ClassVar, Iterable, NamedTuple, Pattern, overload if sys.version_info >= (3, 10): + from importlib.metadata._meta import PackageMetadata as PackageMetadata def packages_distributions() -> Mapping[str, list[str]]: ... if sys.version_info >= (3, 8): @@ -19,9 +20,18 @@ if sys.version_info >= (3, 8): value: str group: str class EntryPoint(_EntryPointBase): + pattern: ClassVar[Pattern[str]] def load(self) -> Any: ... # Callable[[], Any] or an importable module @property def extras(self) -> list[str]: ... + if sys.version_info >= (3, 9): + @property + def module(self) -> str: ... + @property + def attr(self) -> str: ... + if sys.version_info >= (3, 10): + dist: ClassVar[Distribution | None] + def matches(self, **params: Any) -> bool: ... # undocumented class PackagePath(pathlib.PurePosixPath): def read_text(self, encoding: str = ...) -> str: ... def read_binary(self) -> bytes: ... @@ -61,6 +71,9 @@ if sys.version_info >= (3, 8): def files(self) -> list[PackagePath] | None: ... @property def requires(self) -> list[str] | None: ... + if sys.version_info >= (3, 10): + @property + def name(self) -> str: ... class DistributionFinder(MetaPathFinder): class Context: name: str | None @@ -72,6 +85,9 @@ if sys.version_info >= (3, 8): class MetadataPathFinder(DistributionFinder): @classmethod def find_distributions(cls, context: DistributionFinder.Context = ...) -> Iterable[PathDistribution]: ... + if sys.version_info >= (3, 10): + # Yes, this is an instance method that has argumend named "cls" + def invalidate_caches(cls) -> None: ... # type: ignore class PathDistribution(Distribution): def __init__(self, path: Path) -> None: ... def read_text(self, filename: StrPath) -> str: ... @@ -85,6 +101,6 @@ if sys.version_info >= (3, 8): ) -> Iterable[Distribution]: ... def metadata(distribution_name: str) -> Message: ... def version(distribution_name: str) -> str: ... - def entry_points() -> dict[str, Tuple[EntryPoint, ...]]: ... + def entry_points() -> dict[str, tuple[EntryPoint, ...]]: ... def files(distribution_name: str) -> list[PackagePath] | None: ... def requires(distribution_name: str) -> list[str] | None: ... diff --git a/mypy/typeshed/stdlib/importlib/metadata/_meta.pyi b/mypy/typeshed/stdlib/importlib/metadata/_meta.pyi new file mode 100644 index 0000000000000..a5e5733396d73 --- /dev/null +++ b/mypy/typeshed/stdlib/importlib/metadata/_meta.pyi @@ -0,0 +1,18 @@ +from typing import Any, Iterator, Protocol, TypeVar + +_T = TypeVar("_T") + +class PackageMetadata(Protocol): + def __len__(self) -> int: ... + def __contains__(self, item: str) -> bool: ... + def __getitem__(self, key: str) -> str: ... + def __iter__(self) -> Iterator[str]: ... + def get_all(self, name: str, failobj: _T = ...) -> list[Any] | _T: ... + @property + def json(self) -> dict[str, str | list[str]]: ... + +class SimplePath(Protocol): + def joinpath(self) -> SimplePath: ... + def __div__(self) -> SimplePath: ... + def parent(self) -> SimplePath: ... + def read_text(self) -> str: ... diff --git a/mypy/typeshed/stdlib/importlib/resources.pyi b/mypy/typeshed/stdlib/importlib/resources.pyi index 194c0bac2b6a6..b484d7126b21c 100644 --- a/mypy/typeshed/stdlib/importlib/resources.pyi +++ b/mypy/typeshed/stdlib/importlib/resources.pyi @@ -23,3 +23,6 @@ if sys.version_info >= (3, 9): from importlib.abc import Traversable def files(package: Package) -> Traversable: ... def as_file(path: Traversable) -> AbstractContextManager[Path]: ... + +if sys.version_info >= (3, 10): + from importlib.abc import ResourceReader as ResourceReader diff --git a/mypy/typeshed/stdlib/importlib/util.pyi b/mypy/typeshed/stdlib/importlib/util.pyi index 30b8765fad046..c759d7def5bed 100644 --- a/mypy/typeshed/stdlib/importlib/util.pyi +++ b/mypy/typeshed/stdlib/importlib/util.pyi @@ -1,5 +1,6 @@ import importlib.abc import importlib.machinery +import sys import types from _typeshed import StrOrBytesPath from typing import Any, Callable @@ -7,9 +8,9 @@ from typing_extensions import ParamSpec _P = ParamSpec("_P") -def module_for_loader(fxn: Callable[_P, types.ModuleType]) -> Callable[_P, types.ModuleType]: ... # type: ignore -def set_loader(fxn: Callable[_P, types.ModuleType]) -> Callable[_P, types.ModuleType]: ... # type: ignore -def set_package(fxn: Callable[_P, types.ModuleType]) -> Callable[_P, types.ModuleType]: ... # type: ignore +def module_for_loader(fxn: Callable[_P, types.ModuleType]) -> Callable[_P, types.ModuleType]: ... +def set_loader(fxn: Callable[_P, types.ModuleType]) -> Callable[_P, types.ModuleType]: ... +def set_package(fxn: Callable[_P, types.ModuleType]) -> Callable[_P, types.ModuleType]: ... def resolve_name(name: str, package: str | None) -> str: ... MAGIC_NUMBER: bytes @@ -36,3 +37,6 @@ class LazyLoader(importlib.abc.Loader): def factory(cls, loader: importlib.abc.Loader) -> Callable[..., LazyLoader]: ... def create_module(self, spec: importlib.machinery.ModuleSpec) -> types.ModuleType | None: ... def exec_module(self, module: types.ModuleType) -> None: ... + +if sys.version_info >= (3, 7): + def source_hash(source_bytes: bytes) -> int: ... diff --git a/mypy/typeshed/stdlib/inspect.pyi b/mypy/typeshed/stdlib/inspect.pyi index 88002cf205b15..a96e30865a59a 100644 --- a/mypy/typeshed/stdlib/inspect.pyi +++ b/mypy/typeshed/stdlib/inspect.pyi @@ -23,7 +23,7 @@ from types import ( if sys.version_info >= (3, 7): from types import ClassMethodDescriptorType, WrapperDescriptorType, MemberDescriptorType, MethodDescriptorType -from typing import Any, ClassVar, NamedTuple, Protocol, Tuple, Type, TypeVar, Union +from typing import Any, ClassVar, Coroutine, NamedTuple, Protocol, Type, TypeVar, Union from typing_extensions import Literal, TypeGuard # @@ -41,17 +41,19 @@ class BlockFinder: last: int def tokeneater(self, type: int, token: str, srowcol: tuple[int, int], erowcol: tuple[int, int], line: str) -> None: ... -CO_OPTIMIZED: int -CO_NEWLOCALS: int -CO_VARARGS: int -CO_VARKEYWORDS: int -CO_NESTED: int -CO_GENERATOR: int -CO_NOFREE: int -CO_COROUTINE: int -CO_ITERABLE_COROUTINE: int -CO_ASYNC_GENERATOR: int -TPFLAGS_IS_ABSTRACT: int +CO_OPTIMIZED: Literal[1] +CO_NEWLOCALS: Literal[2] +CO_VARARGS: Literal[4] +CO_VARKEYWORDS: Literal[8] +CO_NESTED: Literal[16] +CO_GENERATOR: Literal[32] +CO_NOFREE: Literal[64] +CO_COROUTINE: Literal[128] +CO_ITERABLE_COROUTINE: Literal[256] +CO_ASYNC_GENERATOR: Literal[512] +TPFLAGS_IS_ABSTRACT: Literal[1048576] + +modulesbyfile: dict[str, Any] def getmembers(object: object, predicate: Callable[[Any], bool] | None = ...) -> list[tuple[str, Any]]: ... def getmodulename(path: str) -> str | None: ... @@ -93,14 +95,7 @@ def isframe(object: object) -> TypeGuard[FrameType]: ... def iscode(object: object) -> TypeGuard[CodeType]: ... def isbuiltin(object: object) -> TypeGuard[BuiltinFunctionType]: ... -if sys.version_info < (3, 7): - def isroutine( - object: object, - ) -> TypeGuard[FunctionType | LambdaType | MethodType | BuiltinFunctionType | BuiltinMethodType]: ... - def ismethoddescriptor(object: object) -> bool: ... - def ismemberdescriptor(object: object) -> bool: ... - -else: +if sys.version_info >= (3, 7): def isroutine( object: object, ) -> TypeGuard[ @@ -116,6 +111,13 @@ else: def ismethoddescriptor(object: object) -> TypeGuard[MethodDescriptorType]: ... def ismemberdescriptor(object: object) -> TypeGuard[MemberDescriptorType]: ... +else: + def isroutine( + object: object, + ) -> TypeGuard[FunctionType | LambdaType | MethodType | BuiltinFunctionType | BuiltinMethodType]: ... + def ismethoddescriptor(object: object) -> bool: ... + def ismemberdescriptor(object: object) -> bool: ... + def isabstract(object: object) -> bool: ... def isgetsetdescriptor(object: object) -> TypeGuard[GetSetDescriptorType]: ... def isdatadescriptor(object: object) -> TypeGuard[_SupportsSet[Any, Any] | _SupportsDelete[Any]]: ... @@ -205,21 +207,26 @@ class _ParameterKind(enum.IntEnum): VAR_KEYWORD: int if sys.version_info >= (3, 8): - description: str + @property + def description(self) -> str: ... class Parameter: def __init__(self, name: str, kind: _ParameterKind, *, default: Any = ..., annotation: Any = ...) -> None: ... empty = _empty - name: str - default: Any - annotation: Any - kind: _ParameterKind POSITIONAL_ONLY: ClassVar[Literal[_ParameterKind.POSITIONAL_ONLY]] POSITIONAL_OR_KEYWORD: ClassVar[Literal[_ParameterKind.POSITIONAL_OR_KEYWORD]] VAR_POSITIONAL: ClassVar[Literal[_ParameterKind.VAR_POSITIONAL]] KEYWORD_ONLY: ClassVar[Literal[_ParameterKind.KEYWORD_ONLY]] VAR_KEYWORD: ClassVar[Literal[_ParameterKind.VAR_KEYWORD]] + @property + def name(self) -> str: ... + @property + def default(self) -> Any: ... + @property + def kind(self) -> _ParameterKind: ... + @property + def annotation(self) -> Any: ... def replace( self: Self, *, @@ -231,7 +238,7 @@ class Parameter: class BoundArguments: arguments: OrderedDict[str, Any] - args: Tuple[Any, ...] + args: tuple[Any, ...] kwargs: dict[str, Any] signature: Signature def __init__(self, signature: Signature, arguments: OrderedDict[str, Any]) -> None: ... @@ -247,25 +254,26 @@ class BoundArguments: def getclasstree(classes: list[type], unique: bool = ...) -> list[Any]: ... def walktree(classes: list[type], children: dict[Type[Any], list[type]], parent: Type[Any] | None) -> list[Any]: ... -class ArgSpec(NamedTuple): - args: list[str] - varargs: str | None - keywords: str | None - defaults: Tuple[Any, ...] - class Arguments(NamedTuple): args: list[str] varargs: str | None varkw: str | None def getargs(co: CodeType) -> Arguments: ... -def getargspec(func: object) -> ArgSpec: ... + +if sys.version_info < (3, 11): + class ArgSpec(NamedTuple): + args: list[str] + varargs: str | None + keywords: str | None + defaults: tuple[Any, ...] + def getargspec(func: object) -> ArgSpec: ... class FullArgSpec(NamedTuple): args: list[str] varargs: str | None varkw: str | None - defaults: Tuple[Any, ...] | None + defaults: tuple[Any, ...] | None kwonlyargs: list[str] kwonlydefaults: dict[str, Any] | None annotations: dict[str, Any] @@ -281,21 +289,24 @@ class ArgInfo(NamedTuple): def getargvalues(frame: FrameType) -> ArgInfo: ... def formatannotation(annotation: object, base_module: str | None = ...) -> str: ... def formatannotationrelativeto(object: object) -> Callable[[object], str]: ... -def formatargspec( - args: list[str], - varargs: str | None = ..., - varkw: str | None = ..., - defaults: Tuple[Any, ...] | None = ..., - kwonlyargs: Sequence[str] | None = ..., - kwonlydefaults: dict[str, Any] | None = ..., - annotations: dict[str, Any] = ..., - formatarg: Callable[[str], str] = ..., - formatvarargs: Callable[[str], str] = ..., - formatvarkw: Callable[[str], str] = ..., - formatvalue: Callable[[Any], str] = ..., - formatreturns: Callable[[Any], str] = ..., - formatannotation: Callable[[Any], str] = ..., -) -> str: ... + +if sys.version_info < (3, 11): + def formatargspec( + args: list[str], + varargs: str | None = ..., + varkw: str | None = ..., + defaults: tuple[Any, ...] | None = ..., + kwonlyargs: Sequence[str] | None = ..., + kwonlydefaults: dict[str, Any] | None = ..., + annotations: dict[str, Any] = ..., + formatarg: Callable[[str], str] = ..., + formatvarargs: Callable[[str], str] = ..., + formatvarkw: Callable[[str], str] = ..., + formatvalue: Callable[[Any], str] = ..., + formatreturns: Callable[[Any], str] = ..., + formatannotation: Callable[[Any], str] = ..., + ) -> str: ... + def formatargvalues( args: list[str], varargs: str | None, @@ -306,7 +317,7 @@ def formatargvalues( formatvarkw: Callable[[str], str] | None = ..., formatvalue: Callable[[Any], str] | None = ..., ) -> str: ... -def getmro(cls: type) -> Tuple[type, ...]: ... +def getmro(cls: type) -> tuple[type, ...]: ... def getcallargs(__func: Callable[..., Any], *args: Any, **kwds: Any) -> dict[str, Any]: ... class ClosureVars(NamedTuple): @@ -327,7 +338,7 @@ class Traceback(NamedTuple): lineno: int function: str code_context: list[str] | None - index: int | None # type: ignore + index: int | None # type: ignore[assignment] class FrameInfo(NamedTuple): frame: FrameType @@ -335,7 +346,7 @@ class FrameInfo(NamedTuple): lineno: int function: str code_context: list[str] | None - index: int | None # type: ignore + index: int | None # type: ignore[assignment] def getframeinfo(frame: FrameType | TracebackType, context: int = ...) -> Traceback: ... def getouterframes(frame: Any, context: int = ...) -> list[FrameInfo]: ... @@ -355,26 +366,25 @@ def getattr_static(obj: object, attr: str, default: Any | None = ...) -> Any: .. # Current State of Generators and Coroutines # -# TODO In the next two blocks of code, can we be more specific regarding the -# type of the "enums"? +GEN_CREATED: Literal["GEN_CREATED"] +GEN_RUNNING: Literal["GEN_RUNNING"] +GEN_SUSPENDED: Literal["GEN_SUSPENDED"] +GEN_CLOSED: Literal["GEN_CLOSED"] -GEN_CREATED: str -GEN_RUNNING: str -GEN_SUSPENDED: str -GEN_CLOSED: str +def getgeneratorstate( + generator: Generator[Any, Any, Any] +) -> Literal["GEN_CREATED", "GEN_RUNNING", "GEN_SUSPENDED", "GEN_CLOSED"]: ... -def getgeneratorstate(generator: Generator[Any, Any, Any]) -> str: ... +CORO_CREATED: Literal["CORO_CREATED"] +CORO_RUNNING: Literal["CORO_RUNNING"] +CORO_SUSPENDED: Literal["CORO_SUSPENDED"] +CORO_CLOSED: Literal["CORO_CLOSED"] -CORO_CREATED: str -CORO_RUNNING: str -CORO_SUSPENDED: str -CORO_CLOSED: str -# TODO can we be more specific than "object"? -def getcoroutinestate(coroutine: object) -> str: ... +def getcoroutinestate( + coroutine: Coroutine[Any, Any, Any] +) -> Literal["CORO_CREATED", "CORO_RUNNING", "CORO_SUSPENDED", "CORO_CLOSED"]: ... def getgeneratorlocals(generator: Generator[Any, Any, Any]) -> dict[str, Any]: ... - -# TODO can we be more specific than "object"? -def getcoroutinelocals(coroutine: object) -> dict[str, Any]: ... +def getcoroutinelocals(coroutine: Coroutine[Any, Any, Any]) -> dict[str, Any]: ... # Create private type alias to avoid conflict with symbol of same # name created in Attribute class. diff --git a/mypy/typeshed/stdlib/io.pyi b/mypy/typeshed/stdlib/io.pyi index 6342907004d54..50452917c6f31 100644 --- a/mypy/typeshed/stdlib/io.pyi +++ b/mypy/typeshed/stdlib/io.pyi @@ -4,7 +4,7 @@ import sys from _typeshed import ReadableBuffer, Self, StrOrBytesPath, WriteableBuffer from os import _Opener from types import TracebackType -from typing import IO, Any, BinaryIO, Callable, Iterable, Iterator, TextIO, Tuple, Type +from typing import IO, Any, BinaryIO, Callable, Iterable, Iterator, TextIO, Type DEFAULT_BUFFER_SIZE: int @@ -65,7 +65,7 @@ class BufferedIOBase(IOBase): class FileIO(RawIOBase, BinaryIO): mode: str - name: StrOrBytesPath | int # type: ignore + name: StrOrBytesPath | int # type: ignore[assignment] def __init__( self, file: StrOrBytesPath | int, mode: str = ..., closefd: bool = ..., opener: _Opener | None = ... ) -> None: ... @@ -87,7 +87,7 @@ class BytesIO(BufferedIOBase, BinaryIO): if sys.version_info >= (3, 7): def read1(self, __size: int | None = ...) -> bytes: ... else: - def read1(self, __size: int | None) -> bytes: ... # type: ignore + def read1(self, __size: int | None) -> bytes: ... # type: ignore[override] class BufferedReader(BufferedIOBase, BinaryIO): def __enter__(self: Self) -> Self: ... @@ -96,7 +96,7 @@ class BufferedReader(BufferedIOBase, BinaryIO): if sys.version_info >= (3, 7): def read1(self, __size: int = ...) -> bytes: ... else: - def read1(self, __size: int) -> bytes: ... # type: ignore + def read1(self, __size: int) -> bytes: ... # type: ignore[override] class BufferedWriter(BufferedIOBase, BinaryIO): def __enter__(self: Self) -> Self: ... @@ -110,7 +110,7 @@ class BufferedRandom(BufferedReader, BufferedWriter): if sys.version_info >= (3, 7): def read1(self, __size: int = ...) -> bytes: ... else: - def read1(self, __size: int) -> bytes: ... # type: ignore + def read1(self, __size: int) -> bytes: ... # type: ignore[override] class BufferedRWPair(BufferedIOBase): def __init__(self, reader: RawIOBase, writer: RawIOBase, buffer_size: int = ...) -> None: ... @@ -119,14 +119,14 @@ class BufferedRWPair(BufferedIOBase): class TextIOBase(IOBase): encoding: str errors: str | None - newlines: str | Tuple[str, ...] | None - def __iter__(self) -> Iterator[str]: ... # type: ignore - def __next__(self) -> str: ... # type: ignore + newlines: str | tuple[str, ...] | None + def __iter__(self) -> Iterator[str]: ... # type: ignore[override] + def __next__(self) -> str: ... # type: ignore[override] def detach(self) -> BinaryIO: ... def write(self, __s: str) -> int: ... - def writelines(self, __lines: Iterable[str]) -> None: ... # type: ignore - def readline(self, __size: int = ...) -> str: ... # type: ignore - def readlines(self, __hint: int = ...) -> list[str]: ... # type: ignore + def writelines(self, __lines: Iterable[str]) -> None: ... # type: ignore[override] + def readline(self, __size: int = ...) -> str: ... # type: ignore[override] + def readlines(self, __hint: int = ...) -> list[str]: ... # type: ignore[override] def read(self, __size: int | None = ...) -> str: ... def tell(self) -> int: ... @@ -160,11 +160,11 @@ class TextIOWrapper(TextIOBase, TextIO): ) -> None: ... # These are inherited from TextIOBase, but must exist in the stub to satisfy mypy. def __enter__(self: Self) -> Self: ... - def __iter__(self) -> Iterator[str]: ... # type: ignore - def __next__(self) -> str: ... # type: ignore - def writelines(self, __lines: Iterable[str]) -> None: ... # type: ignore - def readline(self, __size: int = ...) -> str: ... # type: ignore - def readlines(self, __hint: int = ...) -> list[str]: ... # type: ignore + def __iter__(self) -> Iterator[str]: ... # type: ignore[override] + def __next__(self) -> str: ... # type: ignore[override] + def writelines(self, __lines: Iterable[str]) -> None: ... # type: ignore[override] + def readline(self, __size: int = ...) -> str: ... # type: ignore[override] + def readlines(self, __hint: int = ...) -> list[str]: ... # type: ignore[override] def seek(self, __cookie: int, __whence: int = ...) -> int: ... class StringIO(TextIOWrapper): @@ -179,4 +179,4 @@ class IncrementalNewlineDecoder(codecs.IncrementalDecoder): def __init__(self, decoder: codecs.IncrementalDecoder | None, translate: bool, errors: str = ...) -> None: ... def decode(self, input: bytes | str, final: bool = ...) -> str: ... @property - def newlines(self) -> str | Tuple[str, ...] | None: ... + def newlines(self) -> str | tuple[str, ...] | None: ... diff --git a/mypy/typeshed/stdlib/ipaddress.pyi b/mypy/typeshed/stdlib/ipaddress.pyi index 0ded1ef19b47c..6af3ebc3a2bd4 100644 --- a/mypy/typeshed/stdlib/ipaddress.pyi +++ b/mypy/typeshed/stdlib/ipaddress.pyi @@ -9,9 +9,9 @@ _A = TypeVar("_A", IPv4Address, IPv6Address) _N = TypeVar("_N", IPv4Network, IPv6Network) _T = TypeVar("_T") -def ip_address(address: object) -> Any: ... # morally IPv4Address | IPv6Address -def ip_network(address: object, strict: bool = ...) -> Any: ... # morally IPv4Network | IPv6Network -def ip_interface(address: object) -> Any: ... # morally IPv4Interface | IPv6Interface +def ip_address(address: object) -> IPv4Address | IPv6Address: ... +def ip_network(address: object, strict: bool = ...) -> IPv4Network | IPv6Network: ... +def ip_interface(address: object) -> IPv4Interface | IPv6Interface: ... class _IPAddressBase: def __eq__(self, other: Any) -> bool: ... @@ -127,6 +127,9 @@ class IPv6Address(_BaseAddress): def sixtofour(self) -> IPv4Address | None: ... @property def teredo(self) -> tuple[IPv4Address, IPv4Address] | None: ... + if sys.version_info >= (3, 9): + @property + def scope_id(self) -> str | None: ... class IPv6Network(_BaseNetwork[IPv6Address]): @property @@ -136,10 +139,16 @@ class IPv6Interface(IPv6Address, _BaseInterface[IPv6Address, IPv6Network]): ... def v4_int_to_packed(address: int) -> bytes: ... def v6_int_to_packed(address: int) -> bytes: ... + +# Third overload is technically incorrect, but convenient when first and last are return values of ip_address() @overload def summarize_address_range(first: IPv4Address, last: IPv4Address) -> Iterator[IPv4Network]: ... @overload def summarize_address_range(first: IPv6Address, last: IPv6Address) -> Iterator[IPv6Network]: ... +@overload +def summarize_address_range( + first: IPv4Address | IPv6Address, last: IPv4Address | IPv6Address +) -> Iterator[IPv4Network] | Iterator[IPv6Network]: ... def collapse_addresses(addresses: Iterable[_N]) -> Iterator[_N]: ... @overload def get_mixed_type_key(obj: _A) -> tuple[int, _A]: ... diff --git a/mypy/typeshed/stdlib/itertools.pyi b/mypy/typeshed/stdlib/itertools.pyi index 9d666d6817818..a5a7f4f1b62f8 100644 --- a/mypy/typeshed/stdlib/itertools.pyi +++ b/mypy/typeshed/stdlib/itertools.pyi @@ -9,7 +9,6 @@ from typing import ( SupportsComplex, SupportsFloat, SupportsInt, - Tuple, Type, TypeVar, Union, @@ -17,6 +16,9 @@ from typing import ( ) from typing_extensions import Literal, SupportsIndex +if sys.version_info >= (3, 9): + from types import GenericAlias + _T = TypeVar("_T") _S = TypeVar("_S") _N = TypeVar("_N", int, float, SupportsFloat, SupportsInt, SupportsIndex, SupportsComplex) @@ -67,6 +69,8 @@ class chain(Iterator[_T], Generic[_T]): @classmethod # We use Type and not Type[_S] to not lose the type inference from __iterable def from_iterable(cls: Type[Any], __iterable: Iterable[Iterable[_S]]) -> Iterator[_S]: ... + if sys.version_info >= (3, 9): + def __class_getitem__(cls, __item: Any) -> GenericAlias: ... class compress(Iterator[_T], Generic[_T]): def __init__(self, data: Iterable[_T], selectors: Iterable[Any]) -> None: ... @@ -86,7 +90,7 @@ class filterfalse(Iterator[_T], Generic[_T]): _T1 = TypeVar("_T1") _T2 = TypeVar("_T2") -class groupby(Iterator[Tuple[_T, Iterator[_S]]], Generic[_T, _S]): +class groupby(Iterator[tuple[_T, Iterator[_S]]], Generic[_T, _S]): @overload def __new__(cls, iterable: Iterable[_T1], key: None = ...) -> groupby[_T1, _T1]: ... @overload @@ -112,7 +116,7 @@ class takewhile(Iterator[_T], Generic[_T]): def __iter__(self) -> Iterator[_T]: ... def __next__(self) -> _T: ... -def tee(__iterable: Iterable[_T], __n: int = ...) -> Tuple[Iterator[_T], ...]: ... +def tee(__iterable: Iterable[_T], __n: int = ...) -> tuple[Iterator[_T], ...]: ... class zip_longest(Iterator[Any]): def __init__(self, *p: Iterable[Any], fillvalue: Any = ...) -> None: ... @@ -165,18 +169,18 @@ class product(Iterator[_T_co], Generic[_T_co]): __iter6: Iterable[Any], __iter7: Iterable[Any], *iterables: Iterable[Any], - ) -> product[Tuple[Any, ...]]: ... + ) -> product[tuple[Any, ...]]: ... @overload - def __new__(cls, *iterables: Iterable[_T1], repeat: int) -> product[Tuple[_T1, ...]]: ... + def __new__(cls, *iterables: Iterable[_T1], repeat: int) -> product[tuple[_T1, ...]]: ... @overload - def __new__(cls, *iterables: Iterable[Any], repeat: int = ...) -> product[Tuple[Any, ...]]: ... + def __new__(cls, *iterables: Iterable[Any], repeat: int = ...) -> product[tuple[Any, ...]]: ... def __iter__(self) -> Iterator[_T_co]: ... def __next__(self) -> _T_co: ... -class permutations(Iterator[Tuple[_T, ...]], Generic[_T]): +class permutations(Iterator[tuple[_T, ...]], Generic[_T]): def __init__(self, iterable: Iterable[_T], r: int | None = ...) -> None: ... - def __iter__(self) -> Iterator[Tuple[_T, ...]]: ... - def __next__(self) -> Tuple[_T, ...]: ... + def __iter__(self) -> Iterator[tuple[_T, ...]]: ... + def __next__(self) -> tuple[_T, ...]: ... class combinations(Iterator[_T_co], Generic[_T_co]): @overload @@ -188,14 +192,14 @@ class combinations(Iterator[_T_co], Generic[_T_co]): @overload def __new__(cls, iterable: Iterable[_T], r: Literal[5]) -> combinations[tuple[_T, _T, _T, _T, _T]]: ... @overload - def __new__(cls, iterable: Iterable[_T], r: int) -> combinations[Tuple[_T, ...]]: ... + def __new__(cls, iterable: Iterable[_T], r: int) -> combinations[tuple[_T, ...]]: ... def __iter__(self) -> Iterator[_T_co]: ... def __next__(self) -> _T_co: ... -class combinations_with_replacement(Iterator[Tuple[_T, ...]], Generic[_T]): +class combinations_with_replacement(Iterator[tuple[_T, ...]], Generic[_T]): def __init__(self, iterable: Iterable[_T], r: int) -> None: ... - def __iter__(self) -> Iterator[Tuple[_T, ...]]: ... - def __next__(self) -> Tuple[_T, ...]: ... + def __iter__(self) -> Iterator[tuple[_T, ...]]: ... + def __next__(self) -> tuple[_T, ...]: ... if sys.version_info >= (3, 10): class pairwise(Iterator[_T_co], Generic[_T_co]): diff --git a/mypy/typeshed/stdlib/json/encoder.pyi b/mypy/typeshed/stdlib/json/encoder.pyi index 9557a96eee784..6dd74896e5a09 100644 --- a/mypy/typeshed/stdlib/json/encoder.pyi +++ b/mypy/typeshed/stdlib/json/encoder.pyi @@ -1,4 +1,10 @@ -from typing import Any, Callable, Iterator +from typing import Any, Callable, Iterator, Pattern + +ESCAPE: Pattern[str] +ESCAPE_ASCII: Pattern[str] +HAS_UTF8: Pattern[bytes] +ESCAPE_DCT: dict[str, str] +INFINITY: float def py_encode_basestring(s: str) -> str: ... # undocumented def py_encode_basestring_ascii(s: str) -> str: ... # undocumented diff --git a/mypy/typeshed/stdlib/lib2to3/pgen2/grammar.pyi b/mypy/typeshed/stdlib/lib2to3/pgen2/grammar.pyi index 48cb4eae916c0..77cc6aec3d67b 100644 --- a/mypy/typeshed/stdlib/lib2to3/pgen2/grammar.pyi +++ b/mypy/typeshed/stdlib/lib2to3/pgen2/grammar.pyi @@ -1,10 +1,10 @@ from _typeshed import StrPath -from typing import Dict, List, Optional, Tuple, TypeVar +from typing import Optional, TypeVar _P = TypeVar("_P") -_Label = Tuple[int, Optional[str]] -_DFA = List[List[Tuple[int, int]]] -_DFAS = Tuple[_DFA, Dict[int, int]] +_Label = tuple[int, Optional[str]] +_DFA = list[list[tuple[int, int]]] +_DFAS = tuple[_DFA, dict[int, int]] class Grammar: symbol2number: dict[str, int] diff --git a/mypy/typeshed/stdlib/lib2to3/pgen2/token.pyi b/mypy/typeshed/stdlib/lib2to3/pgen2/token.pyi index c4ab376eca64c..2f944c40a02c1 100644 --- a/mypy/typeshed/stdlib/lib2to3/pgen2/token.pyi +++ b/mypy/typeshed/stdlib/lib2to3/pgen2/token.pyi @@ -1,3 +1,5 @@ +import sys + ENDMARKER: int NAME: int NUMBER: int @@ -57,6 +59,8 @@ ATEQUAL: int AWAIT: int ASYNC: int ERRORTOKEN: int +if sys.version_info >= (3, 7): + COLONEQUAL: int N_TOKENS: int NT_OFFSET: int tok_name: dict[int, str] diff --git a/mypy/typeshed/stdlib/lib2to3/pgen2/tokenize.pyi b/mypy/typeshed/stdlib/lib2to3/pgen2/tokenize.pyi index e96a0d8c8eb35..3679caee93140 100644 --- a/mypy/typeshed/stdlib/lib2to3/pgen2/tokenize.pyi +++ b/mypy/typeshed/stdlib/lib2to3/pgen2/tokenize.pyi @@ -1,9 +1,9 @@ from lib2to3.pgen2.token import * # noqa -from typing import Callable, Iterable, Iterator, Tuple +from typing import Callable, Iterable, Iterator -_Coord = Tuple[int, int] +_Coord = tuple[int, int] _TokenEater = Callable[[int, str, _Coord, _Coord, str], None] -_TokenInfo = Tuple[int, str, _Coord, _Coord, str] +_TokenInfo = tuple[int, str, _Coord, _Coord, str] class TokenError(Exception): ... class StopTokenizing(Exception): ... diff --git a/mypy/typeshed/stdlib/lib2to3/pytree.pyi b/mypy/typeshed/stdlib/lib2to3/pytree.pyi index eab82cbc200d3..2ed9a2788d846 100644 --- a/mypy/typeshed/stdlib/lib2to3/pytree.pyi +++ b/mypy/typeshed/stdlib/lib2to3/pytree.pyi @@ -1,11 +1,11 @@ from lib2to3.pgen2.grammar import Grammar -from typing import Any, Callable, Dict, Iterator, List, Optional, Tuple, TypeVar, Union +from typing import Any, Callable, Iterator, Optional, TypeVar, Union _P = TypeVar("_P") _NL = Union[Node, Leaf] -_Context = Tuple[str, int, int] -_Results = Dict[str, _NL] -_RawNode = Tuple[int, str, _Context, Optional[List[_NL]]] +_Context = tuple[str, int, int] +_Results = dict[str, _NL] +_RawNode = tuple[int, str, _Context, Optional[list[_NL]]] _Convert = Callable[[Grammar, _RawNode], Any] HUGE: int diff --git a/mypy/typeshed/stdlib/linecache.pyi b/mypy/typeshed/stdlib/linecache.pyi index a66614bf6b37a..e53d3efea5b20 100644 --- a/mypy/typeshed/stdlib/linecache.pyi +++ b/mypy/typeshed/stdlib/linecache.pyi @@ -1,7 +1,7 @@ -from typing import Any, Dict, List, Protocol, Tuple +from typing import Any, Protocol -_ModuleGlobals = Dict[str, Any] -_ModuleMetadata = Tuple[int, float, List[str], str] +_ModuleGlobals = dict[str, Any] +_ModuleMetadata = tuple[int, float, list[str], str] class _SourceLoader(Protocol): def __call__(self) -> str | None: ... diff --git a/mypy/typeshed/stdlib/locale.pyi b/mypy/typeshed/stdlib/locale.pyi index 1f80c8a624834..f3942102716ac 100644 --- a/mypy/typeshed/stdlib/locale.pyi +++ b/mypy/typeshed/stdlib/locale.pyi @@ -4,7 +4,7 @@ import sys # as a type annotation or type alias. from builtins import str as _str from decimal import Decimal -from typing import Any, Callable, Iterable, Mapping, Sequence, Tuple +from typing import Any, Callable, Iterable, Mapping, Sequence CODESET: int D_T_FMT: int @@ -82,13 +82,13 @@ class Error(Exception): ... def setlocale(category: int, locale: _str | Iterable[_str] | None = ...) -> _str: ... def localeconv() -> Mapping[_str, int | _str | list[int]]: ... def nl_langinfo(__key: int) -> _str: ... -def getdefaultlocale(envvars: Tuple[_str, ...] = ...) -> tuple[_str | None, _str | None]: ... +def getdefaultlocale(envvars: tuple[_str, ...] = ...) -> tuple[_str | None, _str | None]: ... def getlocale(category: int = ...) -> Sequence[_str]: ... def getpreferredencoding(do_setlocale: bool = ...) -> _str: ... def normalize(localename: _str) -> _str: ... def resetlocale(category: int = ...) -> None: ... -def strcoll(string1: _str, string2: _str) -> int: ... -def strxfrm(string: _str) -> _str: ... +def strcoll(__os1: _str, __os2: _str) -> int: ... +def strxfrm(__string: _str) -> _str: ... def format(percent: _str, value: float | Decimal, grouping: bool = ..., monetary: bool = ..., *additional: Any) -> _str: ... if sys.version_info >= (3, 7): diff --git a/mypy/typeshed/stdlib/logging/__init__.pyi b/mypy/typeshed/stdlib/logging/__init__.pyi index c972559c9b60d..d0d50041a0cf7 100644 --- a/mypy/typeshed/stdlib/logging/__init__.pyi +++ b/mypy/typeshed/stdlib/logging/__init__.pyi @@ -1,17 +1,17 @@ import sys import threading -from _typeshed import StrPath, SupportsWrite +from _typeshed import Self, StrPath, SupportsWrite from collections.abc import Callable, Iterable, Mapping, MutableMapping, Sequence from io import TextIOWrapper from string import Template from time import struct_time from types import FrameType, TracebackType -from typing import Any, ClassVar, Generic, Optional, Pattern, TextIO, Tuple, Type, TypeVar, Union, overload +from typing import Any, ClassVar, Generic, Optional, Pattern, TextIO, Type, TypeVar, Union, overload from typing_extensions import Literal -_SysExcInfoType = Union[Tuple[Type[BaseException], BaseException, Optional[TracebackType]], Tuple[None, None, None]] +_SysExcInfoType = Union[tuple[Type[BaseException], BaseException, Optional[TracebackType]], tuple[None, None, None]] _ExcInfoType = Union[None, bool, _SysExcInfoType, BaseException] -_ArgsType = Union[Tuple[object, ...], Mapping[str, object]] +_ArgsType = Union[tuple[object, ...], Mapping[str, object]] _FilterType = Union[Filter, Callable[[LogRecord], int]] _Level = Union[int, str] _FormatStyle = Literal["%", "{", "$"] @@ -27,14 +27,14 @@ def currentframe() -> FrameType: ... _levelToName: dict[int, str] _nameToLevel: dict[str, int] -class Filterer(object): +class Filterer: filters: list[Filter] def __init__(self) -> None: ... def addFilter(self, filter: _FilterType) -> None: ... def removeFilter(self, filter: _FilterType) -> None: ... def filter(self, record: LogRecord) -> bool: ... -class Manager(object): # undocumented +class Manager: # undocumented root: RootLogger disable: int emittedNoHandlerWarning: bool @@ -59,7 +59,7 @@ class Logger(Filterer): def setLevel(self, level: _Level) -> None: ... def isEnabledFor(self, level: int) -> bool: ... def getEffectiveLevel(self) -> int: ... - def getChild(self, suffix: str) -> Logger: ... + def getChild(self: Self, suffix: str) -> Self: ... # see python/typing#980 if sys.version_info >= (3, 8): def debug( self, @@ -244,14 +244,14 @@ class Logger(Filterer): def hasHandlers(self) -> bool: ... def callHandlers(self, record: LogRecord) -> None: ... # undocumented -CRITICAL: int -FATAL: int -ERROR: int -WARNING: int -WARN: int -INFO: int -DEBUG: int -NOTSET: int +CRITICAL: Literal[50] +FATAL: Literal[50] +ERROR: Literal[40] +WARNING: Literal[30] +WARN: Literal[30] +INFO: Literal[20] +DEBUG: Literal[10] +NOTSET: Literal[0] class Handler(Filterer): level: int # undocumented @@ -285,7 +285,17 @@ class Formatter: else: default_msec_format: str - if sys.version_info >= (3, 8): + if sys.version_info >= (3, 10): + def __init__( + self, + fmt: str | None = ..., + datefmt: str | None = ..., + style: _FormatStyle = ..., + validate: bool = ..., + *, + defaults: Mapping[str, Any] | None = ..., + ) -> None: ... + elif sys.version_info >= (3, 8): def __init__( self, fmt: str | None = ..., datefmt: str | None = ..., style: _FormatStyle = ..., validate: bool = ... ) -> None: ... @@ -326,6 +336,7 @@ class LogRecord: lineno: int module: str msecs: float + # Only created when logging.Formatter.format is called. See #6132. message: str msg: str name: str @@ -357,7 +368,7 @@ class LoggerAdapter(Generic[_L]): manager: Manager # undocumented if sys.version_info >= (3, 10): extra: Mapping[str, object] | None - def __init__(self, logger: _L, extra: Mapping[str, object] | None) -> None: ... + def __init__(self, logger: _L, extra: Mapping[str, object] | None = ...) -> None: ... else: extra: Mapping[str, object] def __init__(self, logger: _L, extra: Mapping[str, object]) -> None: ... @@ -738,14 +749,17 @@ class RootLogger(Logger): root: RootLogger -class PercentStyle(object): # undocumented +class PercentStyle: # undocumented default_format: str asctime_format: str asctime_search: str if sys.version_info >= (3, 8): validation_pattern: Pattern[str] _fmt: str - def __init__(self, fmt: str) -> None: ... + if sys.version_info >= (3, 10): + def __init__(self, fmt: str, *, defaults: Mapping[str, Any] | None = ...) -> None: ... + else: + def __init__(self, fmt: str) -> None: ... def usesTime(self) -> bool: ... if sys.version_info >= (3, 8): def validate(self) -> None: ... diff --git a/mypy/typeshed/stdlib/logging/handlers.pyi b/mypy/typeshed/stdlib/logging/handlers.pyi index 5be624872a141..50d6d05835567 100644 --- a/mypy/typeshed/stdlib/logging/handlers.pyi +++ b/mypy/typeshed/stdlib/logging/handlers.pyi @@ -128,7 +128,7 @@ class SocketHandler(Handler): def createSocket(self) -> None: ... class DatagramHandler(SocketHandler): - def makeSocket(self) -> socket: ... # type: ignore + def makeSocket(self) -> socket: ... # type: ignore[override] class SysLogHandler(Handler): LOG_EMERG: int diff --git a/mypy/typeshed/stdlib/lzma.pyi b/mypy/typeshed/stdlib/lzma.pyi index e1da3024c4ac1..e4bd977d7eab6 100644 --- a/mypy/typeshed/stdlib/lzma.pyi +++ b/mypy/typeshed/stdlib/lzma.pyi @@ -41,7 +41,7 @@ PRESET_EXTREME: int # from _lzma.c @final -class LZMADecompressor(object): +class LZMADecompressor: def __init__(self, format: int | None = ..., memlimit: int | None = ..., filters: _FilterChain | None = ...) -> None: ... def decompress(self, data: bytes, max_length: int = ...) -> bytes: ... @property @@ -55,7 +55,7 @@ class LZMADecompressor(object): # from _lzma.c @final -class LZMACompressor(object): +class LZMACompressor: def __init__( self, format: int | None = ..., check: int = ..., preset: int | None = ..., filters: _FilterChain | None = ... ) -> None: ... diff --git a/mypy/typeshed/stdlib/mailcap.pyi b/mypy/typeshed/stdlib/mailcap.pyi index 9eaa771ed3d37..56218d1370fe0 100644 --- a/mypy/typeshed/stdlib/mailcap.pyi +++ b/mypy/typeshed/stdlib/mailcap.pyi @@ -1,6 +1,6 @@ -from typing import Dict, Mapping, Sequence, Union +from typing import Mapping, Sequence, Union -_Cap = Dict[str, Union[str, int]] +_Cap = dict[str, Union[str, int]] def findmatch( caps: Mapping[str, list[_Cap]], MIMEtype: str, key: str = ..., filename: str = ..., plist: Sequence[str] = ... diff --git a/mypy/typeshed/stdlib/math.pyi b/mypy/typeshed/stdlib/math.pyi index f92a3d94f9781..d5e6f99dfa680 100644 --- a/mypy/typeshed/stdlib/math.pyi +++ b/mypy/typeshed/stdlib/math.pyi @@ -21,6 +21,10 @@ def asinh(__x: _SupportsFloatOrIndex) -> float: ... def atan(__x: _SupportsFloatOrIndex) -> float: ... def atan2(__y: _SupportsFloatOrIndex, __x: _SupportsFloatOrIndex) -> float: ... def atanh(__x: _SupportsFloatOrIndex) -> float: ... + +if sys.version_info >= (3, 11): + def cbrt(__x: _SupportsFloatOrIndex) -> float: ... + def ceil(__x: _SupportsFloatOrIndex) -> int: ... if sys.version_info >= (3, 8): @@ -99,7 +103,7 @@ def pow(__x: _SupportsFloatOrIndex, __y: _SupportsFloatOrIndex) -> float: ... if sys.version_info >= (3, 8): @overload - def prod(__iterable: Iterable[SupportsIndex], *, start: SupportsIndex = ...) -> int: ... # type: ignore + def prod(__iterable: Iterable[SupportsIndex], *, start: SupportsIndex = ...) -> int: ... # type: ignore[misc] @overload def prod(__iterable: Iterable[_SupportsFloatOrIndex], *, start: _SupportsFloatOrIndex = ...) -> float: ... diff --git a/mypy/typeshed/stdlib/mimetypes.pyi b/mypy/typeshed/stdlib/mimetypes.pyi index 90c87d2cf385c..8f51c1580eeca 100644 --- a/mypy/typeshed/stdlib/mimetypes.pyi +++ b/mypy/typeshed/stdlib/mimetypes.pyi @@ -1,6 +1,6 @@ import sys from _typeshed import StrPath -from typing import IO, Sequence, Tuple +from typing import IO, Sequence if sys.version_info >= (3, 8): def guess_type(url: StrPath, strict: bool = ...) -> tuple[str | None, str | None]: ... @@ -26,9 +26,12 @@ class MimeTypes: encodings_map: dict[str, str] types_map: tuple[dict[str, str], dict[str, str]] types_map_inv: tuple[dict[str, str], dict[str, str]] - def __init__(self, filenames: Tuple[str, ...] = ..., strict: bool = ...) -> None: ... + def __init__(self, filenames: tuple[str, ...] = ..., strict: bool = ...) -> None: ... def guess_extension(self, type: str, strict: bool = ...) -> str | None: ... - def guess_type(self, url: str, strict: bool = ...) -> tuple[str | None, str | None]: ... + if sys.version_info >= (3, 8): + def guess_type(self, url: StrPath, strict: bool = ...) -> tuple[str | None, str | None]: ... + else: + def guess_type(self, url: str, strict: bool = ...) -> tuple[str | None, str | None]: ... def guess_all_extensions(self, type: str, strict: bool = ...) -> list[str]: ... def read(self, filename: str, strict: bool = ...) -> None: ... def readfp(self, fp: IO[str], strict: bool = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/mmap.pyi b/mypy/typeshed/stdlib/mmap.pyi index 4dd8f8cd2cddf..b79ab92f0c871 100644 --- a/mypy/typeshed/stdlib/mmap.pyi +++ b/mypy/typeshed/stdlib/mmap.pyi @@ -1,6 +1,7 @@ import sys from _typeshed import ReadableBuffer -from typing import ContextManager, Iterable, Iterator, NoReturn, Sized, overload +from contextlib import AbstractContextManager +from typing import Iterable, Iterator, NoReturn, Sized, overload ACCESS_DEFAULT: int ACCESS_READ: int @@ -24,7 +25,7 @@ if sys.platform != "win32": PAGESIZE: int -class mmap(ContextManager[mmap], Iterable[int], Sized): +class mmap(AbstractContextManager[mmap], Iterable[int], Sized): if sys.platform == "win32": def __init__(self, fileno: int, length: int, tagname: str | None = ..., access: int = ..., offset: int = ...) -> None: ... else: diff --git a/mypy/typeshed/stdlib/modulefinder.pyi b/mypy/typeshed/stdlib/modulefinder.pyi index e77a108e9525b..3e7694ccffc9b 100644 --- a/mypy/typeshed/stdlib/modulefinder.pyi +++ b/mypy/typeshed/stdlib/modulefinder.pyi @@ -1,6 +1,6 @@ import sys from types import CodeType -from typing import IO, Any, Container, Iterable, Iterator, Sequence, Tuple +from typing import IO, Any, Container, Iterable, Iterator, Sequence LOAD_CONST: int # undocumented IMPORT_NAME: int # undocumented @@ -62,7 +62,7 @@ class ModuleFinder: def find_all_submodules(self, m: Module) -> Iterable[str]: ... # undocumented def import_module(self, partname: str, fqname: str, parent: Module) -> Module | None: ... # undocumented def load_module(self, fqname: str, fp: IO[str], pathname: str, file_info: tuple[str, str, str]) -> Module: ... # undocumented - def scan_opcodes(self, co: CodeType) -> Iterator[tuple[str, Tuple[Any, ...]]]: ... # undocumented + def scan_opcodes(self, co: CodeType) -> Iterator[tuple[str, tuple[Any, ...]]]: ... # undocumented def scan_code(self, co: CodeType, m: Module) -> None: ... # undocumented def load_package(self, fqname: str, pathname: str) -> Module: ... # undocumented def add_module(self, fqname: str) -> Module: ... # undocumented diff --git a/mypy/typeshed/stdlib/msilib/__init__.pyi b/mypy/typeshed/stdlib/msilib/__init__.pyi index 4e1a7e6a7c02b..b5866492a0977 100644 --- a/mypy/typeshed/stdlib/msilib/__init__.pyi +++ b/mypy/typeshed/stdlib/msilib/__init__.pyi @@ -1,6 +1,6 @@ import sys from types import ModuleType -from typing import Any, Container, Iterable, Sequence, Tuple, Type +from typing import Any, Container, Iterable, Sequence, Type from typing_extensions import Literal if sys.platform == "win32": @@ -37,7 +37,7 @@ if sys.platform == "win32": seqno: int | Type[_Unspecified] = ..., cond: str | Type[_Unspecified] = ..., ) -> None: ... - def add_data(db: _Database, table: str, values: Iterable[Tuple[Any, ...]]) -> None: ... + def add_data(db: _Database, table: str, values: Iterable[tuple[Any, ...]]) -> None: ... def add_stream(db: _Database, name: str, path: str) -> None: ... def init_database( name: str, schema: ModuleType, ProductName: str, ProductCode: str, ProductVersion: str, Manufacturer: str diff --git a/mypy/typeshed/stdlib/msilib/sequence.pyi b/mypy/typeshed/stdlib/msilib/sequence.pyi index 123d232886f7a..87dff754009d5 100644 --- a/mypy/typeshed/stdlib/msilib/sequence.pyi +++ b/mypy/typeshed/stdlib/msilib/sequence.pyi @@ -1,9 +1,9 @@ import sys -from typing import List, Optional, Tuple +from typing import Optional if sys.platform == "win32": - _SequenceType = List[Tuple[str, Optional[str], int]] + _SequenceType = list[tuple[str, Optional[str], int]] AdminExecuteSequence: _SequenceType AdminUISequence: _SequenceType diff --git a/mypy/typeshed/stdlib/multiprocessing/connection.pyi b/mypy/typeshed/stdlib/multiprocessing/connection.pyi index 56ea5c7c0b0bb..56db4594edc0a 100644 --- a/mypy/typeshed/stdlib/multiprocessing/connection.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/connection.pyi @@ -2,13 +2,13 @@ import socket import sys import types from _typeshed import Self -from typing import Any, Iterable, Tuple, Type, Union +from typing import Any, Iterable, Type, Union if sys.version_info >= (3, 8): from typing import SupportsIndex # https://docs.python.org/3/library/multiprocessing.html#address-formats -_Address = Union[str, Tuple[str, int]] +_Address = Union[str, tuple[str, int]] class _ConnectionBase: if sys.version_info >= (3, 8): diff --git a/mypy/typeshed/stdlib/multiprocessing/context.pyi b/mypy/typeshed/stdlib/multiprocessing/context.pyi index e65a387819bc1..83e1b7884efc0 100644 --- a/mypy/typeshed/stdlib/multiprocessing/context.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/context.pyi @@ -19,7 +19,7 @@ class BufferTooShort(ProcessError): ... class TimeoutError(ProcessError): ... class AuthenticationError(ProcessError): ... -class BaseContext(object): +class BaseContext: Process: Type[BaseProcess] ProcessError: Type[Exception] BufferTooShort: Type[Exception] diff --git a/mypy/typeshed/stdlib/multiprocessing/dummy/connection.pyi b/mypy/typeshed/stdlib/multiprocessing/dummy/connection.pyi index 4ef3d095911fa..9500a38364f0a 100644 --- a/mypy/typeshed/stdlib/multiprocessing/dummy/connection.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/dummy/connection.pyi @@ -1,13 +1,13 @@ from _typeshed import Self from queue import Queue from types import TracebackType -from typing import Any, Tuple, Type, Union +from typing import Any, Type, Union families: list[None] -_Address = Union[str, Tuple[str, int]] +_Address = Union[str, tuple[str, int]] -class Connection(object): +class Connection: _in: Any _out: Any recv: Any @@ -22,7 +22,7 @@ class Connection(object): def close(self) -> None: ... def poll(self, timeout: float = ...) -> bool: ... -class Listener(object): +class Listener: _backlog_queue: Queue[Any] | None @property def address(self) -> Queue[Any] | None: ... diff --git a/mypy/typeshed/stdlib/multiprocessing/managers.pyi b/mypy/typeshed/stdlib/multiprocessing/managers.pyi index 22a33f226c0b6..79310614efc11 100644 --- a/mypy/typeshed/stdlib/multiprocessing/managers.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/managers.pyi @@ -1,9 +1,8 @@ -# NOTE: These are incomplete! - import queue import sys import threading -from typing import Any, AnyStr, Callable, ContextManager, Generic, Iterable, Mapping, Sequence, Tuple, TypeVar +from contextlib import AbstractContextManager +from typing import Any, AnyStr, Callable, Generic, Iterable, Mapping, Sequence, TypeVar from .connection import Connection from .context import BaseContext @@ -28,7 +27,7 @@ class Namespace: _Namespace = Namespace -class Token(object): +class Token: typeid: str | bytes | None address: tuple[str | bytes, int] id: str | bytes | int | None @@ -37,7 +36,7 @@ class Token(object): def __getstate__(self) -> tuple[str | bytes | None, tuple[str | bytes, int], str | bytes | int | None]: ... def __setstate__(self, state: tuple[str | bytes | None, tuple[str | bytes, int], str | bytes | int | None]) -> None: ... -class BaseProxy(object): +class BaseProxy: _address_to_local: dict[Any, Any] _mutex: Any def __init__( @@ -51,7 +50,7 @@ class BaseProxy(object): manager_owned: bool = ..., ) -> None: ... def __deepcopy__(self, memo: Any | None) -> Any: ... - def _callmethod(self, methodname: str, args: Tuple[Any, ...] = ..., kwds: dict[Any, Any] = ...) -> None: ... + def _callmethod(self, methodname: str, args: tuple[Any, ...] = ..., kwds: dict[Any, Any] = ...) -> None: ... def _getvalue(self) -> Any: ... def __reduce__(self) -> tuple[Any, tuple[Any, Any, str, dict[Any, Any]]]: ... @@ -71,7 +70,7 @@ class Server: def serve_forever(self) -> None: ... def accept_connection(self, c: Connection, name: str) -> None: ... -class BaseManager(ContextManager[BaseManager]): +class BaseManager(AbstractContextManager[BaseManager]): def __init__( self, address: Any | None = ..., authkey: bytes | None = ..., serializer: str = ..., ctx: BaseContext | None = ... ) -> None: ... @@ -97,7 +96,7 @@ class BaseManager(ContextManager[BaseManager]): _dict = dict _list = list -class SyncManager(BaseManager, ContextManager[SyncManager]): +class SyncManager(BaseManager, AbstractContextManager[SyncManager]): def BoundedSemaphore(self, value: Any = ...) -> threading.BoundedSemaphore: ... def Condition(self, lock: Any = ...) -> threading.Condition: ... def Event(self) -> threading.Event: ... diff --git a/mypy/typeshed/stdlib/multiprocessing/pool.pyi b/mypy/typeshed/stdlib/multiprocessing/pool.pyi index 75583aae80123..518e4b7364d75 100644 --- a/mypy/typeshed/stdlib/multiprocessing/pool.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/pool.pyi @@ -1,10 +1,14 @@ import sys from _typeshed import Self -from typing import Any, Callable, ContextManager, Generic, Iterable, Iterator, List, Mapping, TypeVar +from contextlib import AbstractContextManager +from typing import Any, Callable, Generic, Iterable, Iterator, Mapping, TypeVar +from typing_extensions import Literal if sys.version_info >= (3, 9): from types import GenericAlias +__all__ = ["Pool", "ThreadPool"] + _PT = TypeVar("_PT", bound=Pool) _S = TypeVar("_S") _T = TypeVar("_T") @@ -31,7 +35,7 @@ class ApplyResult(Generic[_T]): # alias created during issue #17805 AsyncResult = ApplyResult -class MapResult(ApplyResult[List[_T]]): +class MapResult(ApplyResult[list[_T]]): if sys.version_info >= (3, 8): def __init__( self, @@ -62,7 +66,7 @@ class IMapIterator(Iterator[_T]): class IMapUnorderedIterator(IMapIterator[_T]): ... -class Pool(ContextManager[Pool]): +class Pool(AbstractContextManager[Pool]): def __init__( self, processes: int | None = ..., @@ -107,18 +111,18 @@ class Pool(ContextManager[Pool]): def join(self) -> None: ... def __enter__(self: Self) -> Self: ... -class ThreadPool(Pool, ContextManager[ThreadPool]): +class ThreadPool(Pool, AbstractContextManager[ThreadPool]): def __init__( self, processes: int | None = ..., initializer: Callable[..., Any] | None = ..., initargs: Iterable[Any] = ... ) -> None: ... # undocumented if sys.version_info >= (3, 8): - INIT: str - RUN: str - CLOSE: str - TERMINATE: str + INIT: Literal["INIT"] + RUN: Literal["RUN"] + CLOSE: Literal["CLOSE"] + TERMINATE: Literal["TERMINATE"] else: - RUN: int - CLOSE: int - TERMINATE: int + RUN: Literal[0] + CLOSE: Literal[1] + TERMINATE: Literal[2] diff --git a/mypy/typeshed/stdlib/multiprocessing/process.pyi b/mypy/typeshed/stdlib/multiprocessing/process.pyi index 32c22d19f6e5e..4746c78b1b4d8 100644 --- a/mypy/typeshed/stdlib/multiprocessing/process.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/process.pyi @@ -1,17 +1,17 @@ import sys -from typing import Any, Callable, Mapping, Tuple +from typing import Any, Callable, Mapping class BaseProcess: name: str daemon: bool authkey: bytes - _identity: Tuple[int, ...] # undocumented + _identity: tuple[int, ...] # undocumented def __init__( self, group: None = ..., target: Callable[..., Any] | None = ..., name: str | None = ..., - args: Tuple[Any, ...] = ..., + args: tuple[Any, ...] = ..., kwargs: Mapping[str, Any] = ..., *, daemon: bool | None = ..., diff --git a/mypy/typeshed/stdlib/multiprocessing/shared_memory.pyi b/mypy/typeshed/stdlib/multiprocessing/shared_memory.pyi index 6ffc2542087af..1b51da38bc430 100644 --- a/mypy/typeshed/stdlib/multiprocessing/shared_memory.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/shared_memory.pyi @@ -1,5 +1,5 @@ import sys -from typing import Any, Generic, Iterable, Tuple, TypeVar +from typing import Any, Generic, Iterable, TypeVar if sys.version_info >= (3, 9): from types import GenericAlias @@ -23,7 +23,7 @@ if sys.version_info >= (3, 8): def __init__(self, sequence: Iterable[_SLT] | None = ..., *, name: str | None = ...) -> None: ... def __getitem__(self, position: int) -> _SLT: ... def __setitem__(self, position: int, value: _SLT) -> None: ... - def __reduce__(self: _S) -> tuple[_S, Tuple[_SLT, ...]]: ... + def __reduce__(self: _S) -> tuple[_S, tuple[_SLT, ...]]: ... def __len__(self) -> int: ... @property def format(self) -> str: ... diff --git a/mypy/typeshed/stdlib/multiprocessing/synchronize.pyi b/mypy/typeshed/stdlib/multiprocessing/synchronize.pyi index 1741885f13bf5..c32c9aafe9a4d 100644 --- a/mypy/typeshed/stdlib/multiprocessing/synchronize.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/synchronize.pyi @@ -1,7 +1,8 @@ import sys import threading +from contextlib import AbstractContextManager from multiprocessing.context import BaseContext -from typing import Any, Callable, ContextManager, Union +from typing import Any, Callable, Union _LockLike = Union[Lock, RLock] @@ -13,7 +14,7 @@ class Barrier(threading.Barrier): class BoundedSemaphore(Semaphore): def __init__(self, value: int = ..., *, ctx: BaseContext) -> None: ... -class Condition(ContextManager[bool]): +class Condition(AbstractContextManager[bool]): def __init__(self, lock: _LockLike | None = ..., *, ctx: BaseContext) -> None: ... if sys.version_info >= (3, 7): def notify(self, n: int = ...) -> None: ... @@ -25,7 +26,7 @@ class Condition(ContextManager[bool]): def acquire(self, block: bool = ..., timeout: float | None = ...) -> bool: ... def release(self) -> None: ... -class Event(ContextManager[bool]): +class Event(AbstractContextManager[bool]): def __init__(self, lock: _LockLike | None = ..., *, ctx: BaseContext) -> None: ... def is_set(self) -> bool: ... def set(self) -> None: ... @@ -42,6 +43,6 @@ class Semaphore(SemLock): def __init__(self, value: int = ..., *, ctx: BaseContext) -> None: ... # Not part of public API -class SemLock(ContextManager[bool]): +class SemLock(AbstractContextManager[bool]): def acquire(self, block: bool = ..., timeout: float | None = ...) -> bool: ... def release(self) -> None: ... diff --git a/mypy/typeshed/stdlib/netrc.pyi b/mypy/typeshed/stdlib/netrc.pyi index b8eac307740a2..7c1c2068aff69 100644 --- a/mypy/typeshed/stdlib/netrc.pyi +++ b/mypy/typeshed/stdlib/netrc.pyi @@ -1,5 +1,5 @@ from _typeshed import StrOrBytesPath -from typing import Optional, Tuple +from typing import Optional class NetrcParseError(Exception): filename: str | None @@ -8,7 +8,7 @@ class NetrcParseError(Exception): def __init__(self, msg: str, filename: StrOrBytesPath | None = ..., lineno: int | None = ...) -> None: ... # (login, account, password) tuple -_NetrcTuple = Tuple[str, Optional[str], Optional[str]] +_NetrcTuple = tuple[str, Optional[str], Optional[str]] class netrc: hosts: dict[str, _NetrcTuple] diff --git a/mypy/typeshed/stdlib/nntplib.pyi b/mypy/typeshed/stdlib/nntplib.pyi index 508b5f679bc38..f0a0fb42da5c9 100644 --- a/mypy/typeshed/stdlib/nntplib.pyi +++ b/mypy/typeshed/stdlib/nntplib.pyi @@ -3,7 +3,7 @@ import socket import ssl import sys from _typeshed import Self -from typing import IO, Any, Iterable, NamedTuple, Tuple, Union +from typing import IO, Any, Iterable, NamedTuple, Union _File = Union[IO[bytes], bytes, str, None] @@ -72,7 +72,7 @@ class _NNTPBase: def xhdr(self, hdr: str, str: Any, *, file: _File = ...) -> tuple[str, _list[str]]: ... def xover(self, start: int, end: int, *, file: _File = ...) -> tuple[str, _list[tuple[int, dict[str, str]]]]: ... def over( - self, message_spec: None | str | _list[Any] | Tuple[Any, ...], *, file: _File = ... + self, message_spec: None | str | _list[Any] | tuple[Any, ...], *, file: _File = ... ) -> tuple[str, _list[tuple[int, dict[str, str]]]]: ... if sys.version_info < (3, 9): def xgtitle(self, group: str, *, file: _File = ...) -> tuple[str, _list[tuple[str, str]]]: ... diff --git a/mypy/typeshed/stdlib/ntpath.pyi b/mypy/typeshed/stdlib/ntpath.pyi index 45d715704157e..f691356cb702c 100644 --- a/mypy/typeshed/stdlib/ntpath.pyi +++ b/mypy/typeshed/stdlib/ntpath.pyi @@ -48,11 +48,13 @@ altsep: str if sys.version_info < (3, 7) and sys.platform == "win32": def splitunc(p: AnyStr) -> tuple[AnyStr, AnyStr]: ... # deprecated -# Similar to posixpath, but have slightly different argument names +# First parameter is not actually pos-only, +# but must be defined as pos-only in the stub or cross-platform code doesn't type-check, +# as the parameter name is different in posixpath.join() @overload -def join(path: StrPath, *paths: StrPath) -> str: ... +def join(__path: StrPath, *paths: StrPath) -> str: ... @overload -def join(path: BytesPath, *paths: BytesPath) -> bytes: ... +def join(__path: BytesPath, *paths: BytesPath) -> bytes: ... if sys.platform == "win32": if sys.version_info >= (3, 10): diff --git a/mypy/typeshed/stdlib/operator.pyi b/mypy/typeshed/stdlib/operator.pyi index bb8e23733f87d..180bd161c0457 100644 --- a/mypy/typeshed/stdlib/operator.pyi +++ b/mypy/typeshed/stdlib/operator.pyi @@ -1,179 +1,51 @@ -from typing import ( - Any, - Container, - Generic, - Mapping, - MutableMapping, - MutableSequence, - Sequence, - SupportsAbs, - Tuple, - TypeVar, - overload, -) -from typing_extensions import final +import sys -_T = TypeVar("_T") -_T_co = TypeVar("_T_co", covariant=True) -_K = TypeVar("_K") -_V = TypeVar("_V") +from _operator import * -def lt(__a: Any, __b: Any) -> Any: ... -def le(__a: Any, __b: Any) -> Any: ... -def eq(__a: Any, __b: Any) -> Any: ... -def ne(__a: Any, __b: Any) -> Any: ... -def ge(__a: Any, __b: Any) -> Any: ... -def gt(__a: Any, __b: Any) -> Any: ... -def __lt__(a: Any, b: Any) -> Any: ... -def __le__(a: Any, b: Any) -> Any: ... -def __eq__(a: Any, b: Any) -> Any: ... -def __ne__(a: Any, b: Any) -> Any: ... -def __ge__(a: Any, b: Any) -> Any: ... -def __gt__(a: Any, b: Any) -> Any: ... -def not_(__a: Any) -> bool: ... -def __not__(a: Any) -> bool: ... -def truth(__a: Any) -> bool: ... -def is_(__a: Any, __b: Any) -> bool: ... -def is_not(__a: Any, __b: Any) -> bool: ... -def abs(__a: SupportsAbs[_T]) -> _T: ... -def __abs__(a: SupportsAbs[_T]) -> _T: ... -def add(__a: Any, __b: Any) -> Any: ... -def __add__(a: Any, b: Any) -> Any: ... -def and_(__a: Any, __b: Any) -> Any: ... -def __and__(a: Any, b: Any) -> Any: ... -def floordiv(__a: Any, __b: Any) -> Any: ... -def __floordiv__(a: Any, b: Any) -> Any: ... -def index(__a: Any) -> int: ... -def __index__(a: Any) -> int: ... -def inv(__a: Any) -> Any: ... -def invert(__a: Any) -> Any: ... -def __inv__(a: Any) -> Any: ... -def __invert__(a: Any) -> Any: ... -def lshift(__a: Any, __b: Any) -> Any: ... -def __lshift__(a: Any, b: Any) -> Any: ... -def mod(__a: Any, __b: Any) -> Any: ... -def __mod__(a: Any, b: Any) -> Any: ... -def mul(__a: Any, __b: Any) -> Any: ... -def __mul__(a: Any, b: Any) -> Any: ... -def matmul(__a: Any, __b: Any) -> Any: ... -def __matmul__(a: Any, b: Any) -> Any: ... -def neg(__a: Any) -> Any: ... -def __neg__(a: Any) -> Any: ... -def or_(__a: Any, __b: Any) -> Any: ... -def __or__(a: Any, b: Any) -> Any: ... -def pos(__a: Any) -> Any: ... -def __pos__(a: Any) -> Any: ... -def pow(__a: Any, __b: Any) -> Any: ... -def __pow__(a: Any, b: Any) -> Any: ... -def rshift(__a: Any, __b: Any) -> Any: ... -def __rshift__(a: Any, b: Any) -> Any: ... -def sub(__a: Any, __b: Any) -> Any: ... -def __sub__(a: Any, b: Any) -> Any: ... -def truediv(__a: Any, __b: Any) -> Any: ... -def __truediv__(a: Any, b: Any) -> Any: ... -def xor(__a: Any, __b: Any) -> Any: ... -def __xor__(a: Any, b: Any) -> Any: ... -def concat(__a: Sequence[_T], __b: Sequence[_T]) -> Sequence[_T]: ... -def __concat__(a: Sequence[_T], b: Sequence[_T]) -> Sequence[_T]: ... -def contains(__a: Container[Any], __b: Any) -> bool: ... -def __contains__(a: Container[Any], b: Any) -> bool: ... -def countOf(__a: Container[Any], __b: Any) -> int: ... -@overload -def delitem(__a: MutableSequence[Any], __b: int) -> None: ... -@overload -def delitem(__a: MutableSequence[Any], __b: slice) -> None: ... -@overload -def delitem(__a: MutableMapping[_K, Any], __b: _K) -> None: ... -@overload -def __delitem__(a: MutableSequence[Any], b: int) -> None: ... -@overload -def __delitem__(a: MutableSequence[Any], b: slice) -> None: ... -@overload -def __delitem__(a: MutableMapping[_K, Any], b: _K) -> None: ... -@overload -def getitem(__a: Sequence[_T], __b: int) -> _T: ... -@overload -def getitem(__a: Sequence[_T], __b: slice) -> Sequence[_T]: ... -@overload -def getitem(__a: Mapping[_K, _V], __b: _K) -> _V: ... -@overload -def __getitem__(a: Sequence[_T], b: int) -> _T: ... -@overload -def __getitem__(a: Sequence[_T], b: slice) -> Sequence[_T]: ... -@overload -def __getitem__(a: Mapping[_K, _V], b: _K) -> _V: ... -def indexOf(__a: Sequence[_T], __b: _T) -> int: ... -@overload -def setitem(__a: MutableSequence[_T], __b: int, __c: _T) -> None: ... -@overload -def setitem(__a: MutableSequence[_T], __b: slice, __c: Sequence[_T]) -> None: ... -@overload -def setitem(__a: MutableMapping[_K, _V], __b: _K, __c: _V) -> None: ... -@overload -def __setitem__(a: MutableSequence[_T], b: int, c: _T) -> None: ... -@overload -def __setitem__(a: MutableSequence[_T], b: slice, c: Sequence[_T]) -> None: ... -@overload -def __setitem__(a: MutableMapping[_K, _V], b: _K, c: _V) -> None: ... -def length_hint(__obj: Any, __default: int = ...) -> int: ... -@final -class attrgetter(Generic[_T_co]): - @overload - def __new__(cls, attr: str) -> attrgetter[Any]: ... - @overload - def __new__(cls, attr: str, __attr2: str) -> attrgetter[tuple[Any, Any]]: ... - @overload - def __new__(cls, attr: str, __attr2: str, __attr3: str) -> attrgetter[tuple[Any, Any, Any]]: ... - @overload - def __new__(cls, attr: str, __attr2: str, __attr3: str, __attr4: str) -> attrgetter[tuple[Any, Any, Any, Any]]: ... - @overload - def __new__(cls, attr: str, *attrs: str) -> attrgetter[Tuple[Any, ...]]: ... - def __call__(self, obj: Any) -> _T_co: ... - -@final -class itemgetter(Generic[_T_co]): - @overload - def __new__(cls, item: Any) -> itemgetter[Any]: ... - @overload - def __new__(cls, item: Any, __item2: Any) -> itemgetter[tuple[Any, Any]]: ... - @overload - def __new__(cls, item: Any, __item2: Any, __item3: Any) -> itemgetter[tuple[Any, Any, Any]]: ... - @overload - def __new__(cls, item: Any, __item2: Any, __item3: Any, __item4: Any) -> itemgetter[tuple[Any, Any, Any, Any]]: ... - @overload - def __new__(cls, item: Any, *items: Any) -> itemgetter[Tuple[Any, ...]]: ... - def __call__(self, obj: Any) -> _T_co: ... - -@final -class methodcaller: - def __init__(self, __name: str, *args: Any, **kwargs: Any) -> None: ... - def __call__(self, obj: Any) -> Any: ... - -def iadd(__a: Any, __b: Any) -> Any: ... -def __iadd__(a: Any, b: Any) -> Any: ... -def iand(__a: Any, __b: Any) -> Any: ... -def __iand__(a: Any, b: Any) -> Any: ... -def iconcat(__a: Any, __b: Any) -> Any: ... -def __iconcat__(a: Any, b: Any) -> Any: ... -def ifloordiv(__a: Any, __b: Any) -> Any: ... -def __ifloordiv__(a: Any, b: Any) -> Any: ... -def ilshift(__a: Any, __b: Any) -> Any: ... -def __ilshift__(a: Any, b: Any) -> Any: ... -def imod(__a: Any, __b: Any) -> Any: ... -def __imod__(a: Any, b: Any) -> Any: ... -def imul(__a: Any, __b: Any) -> Any: ... -def __imul__(a: Any, b: Any) -> Any: ... -def imatmul(__a: Any, __b: Any) -> Any: ... -def __imatmul__(a: Any, b: Any) -> Any: ... -def ior(__a: Any, __b: Any) -> Any: ... -def __ior__(a: Any, b: Any) -> Any: ... -def ipow(__a: Any, __b: Any) -> Any: ... -def __ipow__(a: Any, b: Any) -> Any: ... -def irshift(__a: Any, __b: Any) -> Any: ... -def __irshift__(a: Any, b: Any) -> Any: ... -def isub(__a: Any, __b: Any) -> Any: ... -def __isub__(a: Any, b: Any) -> Any: ... -def itruediv(__a: Any, __b: Any) -> Any: ... -def __itruediv__(a: Any, b: Any) -> Any: ... -def ixor(__a: Any, __b: Any) -> Any: ... -def __ixor__(a: Any, b: Any) -> Any: ... +__lt__ = lt +__le__ = le +__eq__ = eq +__ne__ = ne +__ge__ = ge +__gt__ = gt +__not__ = not_ +__abs__ = abs +__add__ = add +__and__ = and_ +__floordiv__ = floordiv +__index__ = index +__inv__ = inv +__invert__ = invert +__lshift__ = lshift +__mod__ = mod +__mul__ = mul +__matmul__ = matmul +__neg__ = neg +__or__ = or_ +__pos__ = pos +__pow__ = pow +__rshift__ = rshift +__sub__ = sub +__truediv__ = truediv +__xor__ = xor +__concat__ = concat +__contains__ = contains +__delitem__ = delitem +__getitem__ = getitem +__setitem__ = setitem +__iadd__ = iadd +__iand__ = iand +__iconcat__ = iconcat +__ifloordiv__ = ifloordiv +__ilshift__ = ilshift +__imod__ = imod +__imul__ = imul +__imatmul__ = imatmul +__ior__ = ior +__ipow__ = ipow +__irshift__ = irshift +__isub__ = isub +__itruediv__ = itruediv +__ixor__ = ixor +if sys.version_info >= (3, 11): + __call__ = call diff --git a/mypy/typeshed/stdlib/optparse.pyi b/mypy/typeshed/stdlib/optparse.pyi index b8ea9d2fff387..416bc5446cc5e 100644 --- a/mypy/typeshed/stdlib/optparse.pyi +++ b/mypy/typeshed/stdlib/optparse.pyi @@ -1,6 +1,6 @@ -from typing import IO, Any, AnyStr, Callable, Iterable, Mapping, Sequence, Tuple, Type, overload +from typing import IO, Any, AnyStr, Callable, Iterable, Mapping, Sequence, Type, overload -NO_DEFAULT: Tuple[str, ...] +NO_DEFAULT: tuple[str, ...] SUPPRESS_HELP: str SUPPRESS_USAGE: str @@ -72,14 +72,14 @@ class TitledHelpFormatter(HelpFormatter): def format_usage(self, usage: str) -> str: ... class Option: - ACTIONS: Tuple[str, ...] - ALWAYS_TYPED_ACTIONS: Tuple[str, ...] + ACTIONS: tuple[str, ...] + ALWAYS_TYPED_ACTIONS: tuple[str, ...] ATTRS: list[str] CHECK_METHODS: list[Callable[..., Any]] | None - CONST_ACTIONS: Tuple[str, ...] - STORE_ACTIONS: Tuple[str, ...] - TYPED_ACTIONS: Tuple[str, ...] - TYPES: Tuple[str, ...] + CONST_ACTIONS: tuple[str, ...] + STORE_ACTIONS: tuple[str, ...] + TYPED_ACTIONS: tuple[str, ...] + TYPES: tuple[str, ...] TYPE_CHECKER: dict[str, Callable[..., Any]] _long_opts: list[str] _short_opts: list[str] @@ -89,7 +89,7 @@ class Option: nargs: int type: Any callback: Callable[..., Any] | None - callback_args: Tuple[Any, ...] | None + callback_args: tuple[Any, ...] | None callback_kwargs: dict[str, Any] | None help: str | None metavar: str | None diff --git a/mypy/typeshed/stdlib/os/__init__.pyi b/mypy/typeshed/stdlib/os/__init__.pyi index b432f6931a3fc..5308416adff42 100644 --- a/mypy/typeshed/stdlib/os/__init__.pyi +++ b/mypy/typeshed/stdlib/os/__init__.pyi @@ -9,10 +9,11 @@ from _typeshed import ( Self, StrOrBytesPath, StrPath, + structseq, ) from builtins import OSError +from contextlib import AbstractContextManager from io import BufferedRandom, BufferedReader, BufferedWriter, FileIO, TextIOWrapper as _TextIOWrapper -from posix import listdir as listdir, times_result from subprocess import Popen from typing import ( IO, @@ -20,17 +21,14 @@ from typing import ( AnyStr, BinaryIO, Callable, - ContextManager, Generic, Iterable, Iterator, - List, Mapping, MutableMapping, NoReturn, Protocol, Sequence, - Tuple, TypeVar, Union, overload, @@ -92,6 +90,9 @@ if sys.platform != "win32": P_PGID: int P_ALL: int + if sys.platform == "linux" and sys.version_info >= (3, 9): + P_PIDFD: int + WEXITED: int WSTOPPED: int WNOWAIT: int @@ -101,6 +102,12 @@ if sys.platform != "win32": CLD_TRAPPED: int CLD_CONTINUED: int + if sys.version_info >= (3, 9): + CLD_KILLED: int + CLD_STOPPED: int + + # TODO: SCHED_RESET_ON_FORK not available on darwin? + # TODO: SCHED_BATCH and SCHED_IDLE are linux only? SCHED_OTHER: int # some flavors of Unix SCHED_BATCH: int # some flavors of Unix SCHED_IDLE: int # some flavors of Unix @@ -119,6 +126,8 @@ if sys.platform != "win32": if sys.platform == "linux": RTLD_DEEPBIND: int + GRND_NONBLOCK: int + GRND_RANDOM: int SEEK_SET: int SEEK_CUR: int @@ -161,6 +170,24 @@ O_NOATIME: int # Gnu extension if in C library O_PATH: int # Gnu extension if in C library O_TMPFILE: int # Gnu extension if in C library O_LARGEFILE: int # Gnu extension if in C library +O_ACCMODE: int # TODO: when does this exist? + +if sys.platform != "win32" and sys.platform != "darwin": + # posix, but apparently missing on macos + ST_APPEND: int + ST_MANDLOCK: int + ST_NOATIME: int + ST_NODEV: int + ST_NODIRATIME: int + ST_NOEXEC: int + ST_RELATIME: int + ST_SYNCHRONOUS: int + ST_WRITE: int + +if sys.platform != "win32": + NGROUPS_MAX: int + ST_NOSUID: int + ST_RDONLY: int curdir: str pardir: str @@ -210,7 +237,7 @@ class _Environ(MutableMapping[AnyStr, AnyStr], Generic[AnyStr]): putenv: Callable[[AnyStr, AnyStr], None], unsetenv: Callable[[AnyStr, AnyStr], None], ) -> None: ... - def setdefault(self, key: AnyStr, value: AnyStr) -> AnyStr: ... # type: ignore + def setdefault(self, key: AnyStr, value: AnyStr) -> AnyStr: ... # type: ignore[override] def copy(self) -> dict[AnyStr, AnyStr]: ... def __delitem__(self, key: AnyStr) -> None: ... def __getitem__(self, key: AnyStr) -> AnyStr: ... @@ -262,55 +289,84 @@ TMP_MAX: int # Undocumented, but used by tempfile # ----- os classes (structures) ----- @final -class stat_result: - # For backward compatibility, the return value of stat() is also - # accessible as a tuple of at least 10 integers giving the most important - # (and portable) members of the stat structure, in the order st_mode, - # st_ino, st_dev, st_nlink, st_uid, st_gid, st_size, st_atime, st_mtime, - # st_ctime. More items may be added at the end by some implementations. - - st_mode: int # protection bits, - st_ino: int # inode number, - st_dev: int # device, - st_nlink: int # number of hard links, - st_uid: int # user id of owner, - st_gid: int # group id of owner, - st_size: int # size of file, in bytes, - st_atime: float # time of most recent access, - st_mtime: float # time of most recent content modification, - st_ctime: float # platform dependent (time of most recent metadata change on Unix, or the time of creation on Windows) - st_atime_ns: int # time of most recent access, in nanoseconds - st_mtime_ns: int # time of most recent content modification in nanoseconds - st_ctime_ns: int # platform dependent (time of most recent metadata change on Unix, or the time of creation on Windows) in nanoseconds - if sys.version_info >= (3, 8) and sys.platform == "win32": - st_reparse_tag: int +class stat_result(structseq[float], tuple[int, int, int, int, int, int, int, float, float, float]): + # The constructor of this class takes an iterable of variable length (though it must be at least 10). + # + # However, this class behaves like a tuple of 10 elements, + # no matter how long the iterable supplied to the constructor is. + # https://github.com/python/typeshed/pull/6560#discussion_r767162532 + # + # The 10 elements always present are st_mode, st_ino, st_dev, st_nlink, + # st_uid, st_gid, st_size, st_atime, st_mtime, st_ctime. + # + # More items may be added at the end by some implementations. + @property + def st_mode(self) -> int: ... # protection bits, + @property + def st_ino(self) -> int: ... # inode number, + @property + def st_dev(self) -> int: ... # device, + @property + def st_nlink(self) -> int: ... # number of hard links, + @property + def st_uid(self) -> int: ... # user id of owner, + @property + def st_gid(self) -> int: ... # group id of owner, + @property + def st_size(self) -> int: ... # size of file, in bytes, + @property + def st_atime(self) -> float: ... # time of most recent access, + @property + def st_mtime(self) -> float: ... # time of most recent content modification, + # platform dependent (time of most recent metadata change on Unix, or the time of creation on Windows) + @property + def st_ctime(self) -> float: ... + @property + def st_atime_ns(self) -> int: ... # time of most recent access, in nanoseconds + @property + def st_mtime_ns(self) -> int: ... # time of most recent content modification in nanoseconds + # platform dependent (time of most recent metadata change on Unix, or the time of creation on Windows) in nanoseconds + @property + def st_ctime_ns(self) -> int: ... if sys.platform == "win32": - st_file_attributes: int - def __getitem__(self, i: int) -> int: ... - # not documented - def __init__(self, tuple: Tuple[int, ...]) -> None: ... - # On some Unix systems (such as Linux), the following attributes may also - # be available: - st_blocks: int # number of blocks allocated for file - st_blksize: int # filesystem blocksize - st_rdev: int # type of device if an inode device - st_flags: int # user defined flags for file - - # On other Unix systems (such as FreeBSD), the following attributes may be - # available (but may be only filled out if root tries to use them): - st_gen: int # file generation number - st_birthtime: int # time of file creation - - # On Mac OS systems, the following attributes may also be available: - st_rsize: int - st_creator: int - st_type: int + @property + def st_file_attributes(self) -> int: ... + if sys.version_info >= (3, 8): + @property + def st_reparse_tag(self) -> int: ... + else: + @property + def st_blocks(self) -> int: ... # number of blocks allocated for file + @property + def st_blksize(self) -> int: ... # filesystem blocksize + @property + def st_rdev(self) -> int: ... # type of device if an inode device + if sys.platform != "linux": + # These properties are available on MacOS, but not on Windows or Ubuntu. + # On other Unix systems (such as FreeBSD), the following attributes may be + # available (but may be only filled out if root tries to use them): + @property + def st_gen(self) -> int: ... # file generation number + @property + def st_birthtime(self) -> int: ... # time of file creation + if sys.platform == "darwin": + @property + def st_flags(self) -> int: ... # user defined flags for file + # Atributes documented as sometimes appearing, but deliberately omitted from the stub: `st_creator`, `st_rsize`, `st_type`. + # See https://github.com/python/typeshed/pull/6560#issuecomment-991253327 @runtime_checkable class PathLike(Protocol[_AnyStr_co]): def __fspath__(self) -> _AnyStr_co: ... - if sys.version_info >= (3, 9): - def __class_getitem__(cls, item: Any) -> GenericAlias: ... + +@overload +def listdir(path: str | None = ...) -> list[str]: ... +@overload +def listdir(path: bytes) -> list[bytes]: ... +@overload +def listdir(path: int) -> list[str]: ... +@overload +def listdir(path: PathLike[str]) -> list[str]: ... _FdOrAnyPath = Union[int, StrOrBytesPath] @@ -330,45 +386,55 @@ class DirEntry(Generic[AnyStr]): if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... -if sys.platform != "win32": - _Tuple10Int = Tuple[int, int, int, int, int, int, int, int, int, int] - _Tuple11Int = Tuple[int, int, int, int, int, int, int, int, int, int, int] - if sys.version_info >= (3, 7): - # f_fsid was added in https://github.com/python/cpython/pull/4571 - @final - class statvfs_result(_Tuple10Int): # Unix only - def __new__(cls, seq: _Tuple10Int | _Tuple11Int, dict: dict[str, int] = ...) -> statvfs_result: ... - n_fields: int - n_sequence_fields: int - n_unnamed_fields: int - - f_bsize: int - f_frsize: int - f_blocks: int - f_bfree: int - f_bavail: int - f_files: int - f_ffree: int - f_favail: int - f_flag: int - f_namemax: int - f_fsid: int - else: - class statvfs_result(_Tuple10Int): # Unix only - n_fields: int - n_sequence_fields: int - n_unnamed_fields: int - - f_bsize: int - f_frsize: int - f_blocks: int - f_bfree: int - f_bavail: int - f_files: int - f_ffree: int - f_favail: int - f_flag: int - f_namemax: int +if sys.version_info >= (3, 7): + @final + class statvfs_result(structseq[int], tuple[int, int, int, int, int, int, int, int, int, int, int]): + @property + def f_bsize(self) -> int: ... + @property + def f_frsize(self) -> int: ... + @property + def f_blocks(self) -> int: ... + @property + def f_bfree(self) -> int: ... + @property + def f_bavail(self) -> int: ... + @property + def f_files(self) -> int: ... + @property + def f_ffree(self) -> int: ... + @property + def f_favail(self) -> int: ... + @property + def f_flag(self) -> int: ... + @property + def f_namemax(self) -> int: ... + @property + def f_fsid(self) -> int: ... + +else: + @final + class statvfs_result(structseq[int], tuple[int, int, int, int, int, int, int, int, int, int]): + @property + def f_bsize(self) -> int: ... + @property + def f_frsize(self) -> int: ... + @property + def f_blocks(self) -> int: ... + @property + def f_bfree(self) -> int: ... + @property + def f_bavail(self) -> int: ... + @property + def f_files(self) -> int: ... + @property + def f_ffree(self) -> int: ... + @property + def f_favail(self) -> int: ... + @property + def f_flag(self) -> int: ... + @property + def f_namemax(self) -> int: ... # ----- os function stubs ----- def fsencode(filename: StrOrBytesPath) -> bytes: ... @@ -385,9 +451,20 @@ def getpid() -> int: ... def getppid() -> int: ... def strerror(__code: int) -> str: ... def umask(__mask: int) -> int: ... +@final +class uname_result(structseq[str], tuple[str, str, str, str, str]): + @property + def sysname(self) -> str: ... + @property + def nodename(self) -> str: ... + @property + def release(self) -> str: ... + @property + def version(self) -> str: ... + @property + def machine(self) -> str: ... if sys.platform != "win32": - # Unix only def ctermid() -> str: ... def getegid() -> int: ... def geteuid() -> int: ... @@ -417,7 +494,6 @@ if sys.platform != "win32": def getsid(__pid: int) -> int: ... def setsid() -> None: ... def setuid(__uid: int) -> None: ... - from posix import uname_result def uname() -> uname_result: ... @overload @@ -433,7 +509,7 @@ if sys.platform != "win32": def putenv(__name: bytes | str, __value: bytes | str) -> None: ... -if sys.platform != "win32": +if sys.platform != "win32" or sys.version_info >= (3, 9): def unsetenv(__name: bytes | str) -> None: ... _Opener = Callable[[str, int], int] @@ -527,7 +603,9 @@ else: def dup2(fd: int, fd2: int, inheritable: bool = ...) -> None: ... def fstat(fd: int) -> stat_result: ... +def ftruncate(__fd: int, __length: int) -> None: ... def fsync(fd: FileDescriptorLike) -> None: ... +def isatty(__fd: int) -> bool: ... def lseek(__fd: int, __position: int, __how: int) -> int: ... def open(path: StrOrBytesPath, flags: int, mode: int = ..., *, dir_fd: int | None = ...) -> int: ... def pipe() -> tuple[int, int]: ... @@ -537,22 +615,29 @@ if sys.platform != "win32": # Unix only def fchmod(fd: int, mode: int) -> None: ... def fchown(fd: int, uid: int, gid: int) -> None: ... - if sys.platform != "darwin": - def fdatasync(fd: FileDescriptorLike) -> None: ... # Unix only, not Mac def fpathconf(__fd: int, __name: str | int) -> int: ... def fstatvfs(__fd: int) -> statvfs_result: ... - def ftruncate(__fd: int, __length: int) -> None: ... def get_blocking(__fd: int) -> bool: ... def set_blocking(__fd: int, __blocking: bool) -> None: ... - def isatty(__fd: int) -> bool: ... def lockf(__fd: int, __command: int, __length: int) -> None: ... def openpty() -> tuple[int, int]: ... # some flavors of Unix if sys.platform != "darwin": - def pipe2(flags: int) -> tuple[int, int]: ... # some flavors of Unix + def fdatasync(fd: FileDescriptorLike) -> None: ... + def pipe2(__flags: int) -> tuple[int, int]: ... # some flavors of Unix def posix_fallocate(fd: int, offset: int, length: int) -> None: ... def posix_fadvise(fd: int, offset: int, length: int, advice: int) -> None: ... def pread(__fd: int, __length: int, __offset: int) -> bytes: ... def pwrite(__fd: int, __buffer: bytes, __offset: int) -> int: ... + if sys.platform != "darwin": + if sys.version_info >= (3, 10): + RWF_APPEND: int # docs say available on 3.7+, stubtest says otherwise + if sys.version_info >= (3, 7): + def preadv(__fd: int, __buffers: Iterable[bytes], __offset: int, __flags: int = ...) -> int: ... + def pwritev(__fd: int, __buffers: Iterable[bytes], __offset: int, __flags: int = ...) -> int: ... + RWF_DSYNC: int + RWF_SYNC: int + RWF_HIPRI: int + RWF_NOWAIT: int @overload def sendfile(out_fd: int, in_fd: int, offset: int | None, count: int) -> int: ... @overload @@ -569,9 +654,11 @@ if sys.platform != "win32": def writev(__fd: int, __buffers: Sequence[bytes]) -> int: ... @final -class terminal_size(Tuple[int, int]): - columns: int - lines: int +class terminal_size(structseq[int], tuple[int, int]): + @property + def columns(self) -> int: ... + @property + def lines(self) -> int: ... def get_terminal_size(fd: int = ...) -> terminal_size: ... def get_inheritable(__fd: int) -> bool: ... @@ -596,17 +683,14 @@ def getcwd() -> str: ... def getcwdb() -> bytes: ... def chmod(path: _FdOrAnyPath, mode: int, *, dir_fd: int | None = ..., follow_symlinks: bool = ...) -> None: ... -if sys.platform != "win32": +if sys.platform != "win32" and sys.platform != "linux": def chflags(path: StrOrBytesPath, flags: int, follow_symlinks: bool = ...) -> None: ... # some flavors of Unix - def chown( - path: _FdOrAnyPath, uid: int, gid: int, *, dir_fd: int | None = ..., follow_symlinks: bool = ... - ) -> None: ... # Unix only + def lchflags(path: StrOrBytesPath, flags: int) -> None: ... + def lchmod(path: StrOrBytesPath, mode: int) -> None: ... if sys.platform != "win32": - # Unix only def chroot(path: StrOrBytesPath) -> None: ... - def lchflags(path: StrOrBytesPath, flags: int) -> None: ... - def lchmod(path: StrOrBytesPath, mode: int) -> None: ... + def chown(path: _FdOrAnyPath, uid: int, gid: int, *, dir_fd: int | None = ..., follow_symlinks: bool = ...) -> None: ... def lchown(path: StrOrBytesPath, uid: int, gid: int) -> None: ... def link( @@ -640,7 +724,7 @@ def renames(old: StrOrBytesPath, new: StrOrBytesPath) -> None: ... def replace(src: StrOrBytesPath, dst: StrOrBytesPath, *, src_dir_fd: int | None = ..., dst_dir_fd: int | None = ...) -> None: ... def rmdir(path: StrOrBytesPath, *, dir_fd: int | None = ...) -> None: ... -class _ScandirIterator(Iterator[DirEntry[AnyStr]], ContextManager[_ScandirIterator[AnyStr]]): +class _ScandirIterator(Iterator[DirEntry[AnyStr]], AbstractContextManager[_ScandirIterator[AnyStr]]): def __next__(self) -> DirEntry[AnyStr]: ... def close(self) -> None: ... @@ -744,14 +828,14 @@ def execlpe(file: StrOrBytesPath, __arg0: StrOrBytesPath, *args: Any) -> NoRetur # in practice, and doing so would explode the number of combinations in this already long union. # All these combinations are necessary due to list being invariant. _ExecVArgs = Union[ - Tuple[StrOrBytesPath, ...], - List[bytes], - List[str], - List[PathLike[Any]], - List[Union[bytes, str]], - List[Union[bytes, PathLike[Any]]], - List[Union[str, PathLike[Any]]], - List[Union[bytes, str, PathLike[Any]]], + tuple[StrOrBytesPath, ...], + list[bytes], + list[str], + list[PathLike[Any]], + list[Union[bytes, str]], + list[Union[bytes, PathLike[Any]]], + list[Union[str, PathLike[Any]]], + list[Union[bytes, str, PathLike[Any]]], ] _ExecEnv = Union[Mapping[bytes, Union[bytes, str]], Mapping[str, Union[bytes, str]]] @@ -773,7 +857,7 @@ if sys.platform != "win32": class _wrap_close(_TextIOWrapper): def __init__(self, stream: _TextIOWrapper, proc: Popen[str]) -> None: ... - def close(self) -> int | None: ... # type: ignore + def close(self) -> int | None: ... # type: ignore[override] def popen(cmd: str, mode: str = ..., buffering: int = ...) -> _wrap_close: ... def spawnl(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: StrOrBytesPath) -> int: ... @@ -788,6 +872,19 @@ else: def spawnve(__mode: int, __path: StrOrBytesPath, __argv: _ExecVArgs, __env: _ExecEnv) -> int: ... def system(command: StrOrBytesPath) -> int: ... +@final +class times_result(structseq[float], tuple[float, float, float, float, float]): + @property + def user(self) -> float: ... + @property + def system(self) -> float: ... + @property + def children_user(self) -> float: ... + @property + def children_system(self) -> float: ... + @property + def elapsed(self) -> float: ... + def times() -> times_result: ... def waitpid(__pid: int, __options: int) -> tuple[int, int]: ... @@ -795,14 +892,24 @@ if sys.platform == "win32": def startfile(path: StrOrBytesPath, operation: str | None = ...) -> None: ... else: - # Unix only def spawnlp(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: StrOrBytesPath) -> int: ... def spawnlpe(mode: int, file: StrOrBytesPath, arg0: StrOrBytesPath, *args: Any) -> int: ... # Imprecise signature def spawnvp(mode: int, file: StrOrBytesPath, args: _ExecVArgs) -> int: ... def spawnvpe(mode: int, file: StrOrBytesPath, args: _ExecVArgs, env: _ExecEnv) -> int: ... def wait() -> tuple[int, int]: ... # Unix only if sys.platform != "darwin": - from posix import waitid_result + @final + class waitid_result(structseq[int], tuple[int, int, int, int, int]): + @property + def si_pid(self) -> int: ... + @property + def si_uid(self) -> int: ... + @property + def si_signo(self) -> int: ... + @property + def si_status(self) -> int: ... + @property + def si_code(self) -> int: ... def waitid(idtype: int, ident: int, options: int) -> waitid_result: ... def wait3(options: int) -> tuple[int, int, Any]: ... def wait4(pid: int, options: int) -> tuple[int, int, Any]: ... @@ -815,10 +922,42 @@ else: def WSTOPSIG(status: int) -> int: ... def WTERMSIG(status: int) -> int: ... if sys.version_info >= (3, 8): - from posix import posix_spawn as posix_spawn, posix_spawnp as posix_spawnp + def posix_spawn( + path: StrOrBytesPath, + argv: _ExecVArgs, + env: _ExecEnv, + *, + file_actions: Sequence[tuple[Any, ...]] | None = ..., + setpgroup: int | None = ..., + resetids: bool = ..., + setsid: bool = ..., + setsigmask: Iterable[int] = ..., + setsigdef: Iterable[int] = ..., + scheduler: tuple[Any, sched_param] | None = ..., + ) -> int: ... + def posix_spawnp( + path: StrOrBytesPath, + argv: _ExecVArgs, + env: _ExecEnv, + *, + file_actions: Sequence[tuple[Any, ...]] | None = ..., + setpgroup: int | None = ..., + resetids: bool = ..., + setsid: bool = ..., + setsigmask: Iterable[int] = ..., + setsigdef: Iterable[int] = ..., + scheduler: tuple[Any, sched_param] | None = ..., + ) -> int: ... + POSIX_SPAWN_OPEN: int + POSIX_SPAWN_CLOSE: int + POSIX_SPAWN_DUP2: int if sys.platform != "win32": - from posix import sched_param + @final + class sched_param(structseq[int], tuple[int]): + def __new__(cls, sched_priority: int) -> sched_param: ... + @property + def sched_priority(self) -> int: ... def sched_get_priority_min(policy: int) -> int: ... # some flavors of Unix def sched_get_priority_max(policy: int) -> int: ... # some flavors of Unix def sched_yield() -> None: ... # some flavors of Unix @@ -880,3 +1019,6 @@ if sys.version_info >= (3, 8): MFD_HUGE_2GB: int MFD_HUGE_16GB: int def memfd_create(name: str, flags: int = ...) -> int: ... + +if sys.version_info >= (3, 9): + def waitstatus_to_exitcode(status: int) -> int: ... diff --git a/mypy/typeshed/stdlib/parser.pyi b/mypy/typeshed/stdlib/parser.pyi index aecf3244ca8dc..ab819a71a15f8 100644 --- a/mypy/typeshed/stdlib/parser.pyi +++ b/mypy/typeshed/stdlib/parser.pyi @@ -1,13 +1,13 @@ from _typeshed import StrOrBytesPath from types import CodeType -from typing import Any, Sequence, Tuple +from typing import Any, Sequence def expr(source: str) -> STType: ... def suite(source: str) -> STType: ... def sequence2st(sequence: Sequence[Any]) -> STType: ... def tuple2st(sequence: Sequence[Any]) -> STType: ... def st2list(st: STType, line_info: bool = ..., col_info: bool = ...) -> list[Any]: ... -def st2tuple(st: STType, line_info: bool = ..., col_info: bool = ...) -> Tuple[Any, ...]: ... +def st2tuple(st: STType, line_info: bool = ..., col_info: bool = ...) -> tuple[Any, ...]: ... def compilest(st: STType, filename: StrOrBytesPath = ...) -> CodeType: ... def isexpr(st: STType) -> bool: ... def issuite(st: STType) -> bool: ... @@ -19,4 +19,4 @@ class STType: def isexpr(self) -> bool: ... def issuite(self) -> bool: ... def tolist(self, line_info: bool = ..., col_info: bool = ...) -> list[Any]: ... - def totuple(self, line_info: bool = ..., col_info: bool = ...) -> Tuple[Any, ...]: ... + def totuple(self, line_info: bool = ..., col_info: bool = ...) -> tuple[Any, ...]: ... diff --git a/mypy/typeshed/stdlib/pathlib.pyi b/mypy/typeshed/stdlib/pathlib.pyi index 7d5f7ff2dba80..b541345c06d4c 100644 --- a/mypy/typeshed/stdlib/pathlib.pyi +++ b/mypy/typeshed/stdlib/pathlib.pyi @@ -11,7 +11,7 @@ from _typeshed import ( from io import BufferedRandom, BufferedReader, BufferedWriter, FileIO, TextIOWrapper from os import PathLike, stat_result from types import TracebackType -from typing import IO, Any, BinaryIO, Generator, Sequence, Tuple, Type, TypeVar, overload +from typing import IO, Any, BinaryIO, Generator, Sequence, Type, TypeVar, overload from typing_extensions import Literal if sys.version_info >= (3, 9): @@ -20,7 +20,7 @@ if sys.version_info >= (3, 9): _P = TypeVar("_P", bound=PurePath) class PurePath(PathLike[str]): - parts: Tuple[str, ...] + parts: tuple[str, ...] drive: str root: str anchor: str diff --git a/mypy/typeshed/stdlib/pickle.pyi b/mypy/typeshed/stdlib/pickle.pyi index cef1ffe9eb9b9..46c349137459c 100644 --- a/mypy/typeshed/stdlib/pickle.pyi +++ b/mypy/typeshed/stdlib/pickle.pyi @@ -1,11 +1,11 @@ import sys -from typing import Any, Callable, ClassVar, Iterable, Iterator, Mapping, Optional, Protocol, Tuple, Type, Union +from typing import Any, Callable, ClassVar, Iterable, Iterator, Mapping, Optional, Protocol, Type, Union from typing_extensions import final HIGHEST_PROTOCOL: int DEFAULT_PROTOCOL: int -bytes_types: Tuple[Type[Any], ...] # undocumented +bytes_types: tuple[Type[Any], ...] # undocumented class _ReadableFileobj(Protocol): def read(self, __n: int) -> bytes: ... @@ -58,10 +58,10 @@ class UnpicklingError(PickleError): ... _reducedtype = Union[ str, - Tuple[Callable[..., Any], Tuple[Any, ...]], - Tuple[Callable[..., Any], Tuple[Any, ...], Any], - Tuple[Callable[..., Any], Tuple[Any, ...], Any, Optional[Iterator[Any]]], - Tuple[Callable[..., Any], Tuple[Any, ...], Any, Optional[Iterator[Any]], Optional[Iterator[Any]]], + tuple[Callable[..., Any], tuple[Any, ...]], + tuple[Callable[..., Any], tuple[Any, ...], Any], + tuple[Callable[..., Any], tuple[Any, ...], Any, Optional[Iterator[Any]]], + tuple[Callable[..., Any], tuple[Any, ...], Any, Optional[Iterator[Any]], Optional[Iterator[Any]]], ] class Pickler: diff --git a/mypy/typeshed/stdlib/pickletools.pyi b/mypy/typeshed/stdlib/pickletools.pyi index 9fa51a3848eee..04a695f5f1037 100644 --- a/mypy/typeshed/stdlib/pickletools.pyi +++ b/mypy/typeshed/stdlib/pickletools.pyi @@ -1,7 +1,7 @@ -from typing import IO, Any, Callable, Iterator, MutableMapping, Tuple, Type +from typing import IO, Any, Callable, Iterator, MutableMapping, Type _Reader = Callable[[IO[bytes]], Any] -bytes_types: Tuple[Type[Any], ...] +bytes_types: tuple[Type[Any], ...] UP_TO_NEWLINE: int TAKEN_FROM_ARGUMENT1: int @@ -9,7 +9,7 @@ TAKEN_FROM_ARGUMENT4: int TAKEN_FROM_ARGUMENT4U: int TAKEN_FROM_ARGUMENT8U: int -class ArgumentDescriptor(object): +class ArgumentDescriptor: name: str n: int reader: _Reader @@ -106,11 +106,11 @@ def read_long4(f: IO[bytes]) -> int: ... long4: ArgumentDescriptor -class StackObject(object): +class StackObject: name: str - obtype: Type[Any] | Tuple[Type[Any], ...] + obtype: Type[Any] | tuple[Type[Any], ...] doc: str - def __init__(self, name: str, obtype: Type[Any] | Tuple[Type[Any], ...], doc: str) -> None: ... + def __init__(self, name: str, obtype: Type[Any] | tuple[Type[Any], ...], doc: str) -> None: ... pyint: StackObject pylong: StackObject @@ -131,7 +131,7 @@ anyobject: StackObject markobject: StackObject stackslice: StackObject -class OpcodeInfo(object): +class OpcodeInfo: name: str code: str arg: ArgumentDescriptor | None diff --git a/mypy/typeshed/stdlib/platform.pyi b/mypy/typeshed/stdlib/platform.pyi index 7db2d59ff7ea5..765a7a5ea5f93 100644 --- a/mypy/typeshed/stdlib/platform.pyi +++ b/mypy/typeshed/stdlib/platform.pyi @@ -4,7 +4,7 @@ if sys.version_info < (3, 8): import os DEV_NULL = os.devnull -from typing import NamedTuple, Tuple +from typing import NamedTuple if sys.version_info >= (3, 8): def libc_ver(executable: str | None = ..., lib: str = ..., version: str = ..., chunksize: int = ...) -> tuple[str, str]: ... @@ -17,11 +17,11 @@ if sys.version_info < (3, 8): distname: str = ..., version: str = ..., id: str = ..., - supported_dists: Tuple[str, ...] = ..., + supported_dists: tuple[str, ...] = ..., full_distribution_name: bool = ..., ) -> tuple[str, str, str]: ... def dist( - distname: str = ..., version: str = ..., id: str = ..., supported_dists: Tuple[str, ...] = ... + distname: str = ..., version: str = ..., id: str = ..., supported_dists: tuple[str, ...] = ... ) -> tuple[str, str, str]: ... def win32_ver(release: str = ..., version: str = ..., csd: str = ..., ptype: str = ...) -> tuple[str, str, str, str]: ... @@ -62,3 +62,6 @@ def python_revision() -> str: ... def python_build() -> tuple[str, str]: ... def python_compiler() -> str: ... def platform(aliased: bool = ..., terse: bool = ...) -> str: ... + +if sys.version_info >= (3, 10): + def freedesktop_os_release() -> dict[str, str]: ... diff --git a/mypy/typeshed/stdlib/plistlib.pyi b/mypy/typeshed/stdlib/plistlib.pyi index 07b6963746be0..7abe9dd2942be 100644 --- a/mypy/typeshed/stdlib/plistlib.pyi +++ b/mypy/typeshed/stdlib/plistlib.pyi @@ -1,7 +1,7 @@ import sys from datetime import datetime from enum import Enum -from typing import IO, Any, Dict as _Dict, Mapping, MutableMapping, Tuple, Type +from typing import IO, Any, Mapping, MutableMapping, Type class PlistFormat(Enum): FMT_XML: int @@ -31,7 +31,7 @@ else: ) -> Any: ... def dump( - value: Mapping[str, Any] | list[Any] | Tuple[Any, ...] | str | bool | float | bytes | datetime, + value: Mapping[str, Any] | list[Any] | tuple[Any, ...] | str | bool | float | bytes | datetime, fp: IO[bytes], *, fmt: PlistFormat = ..., @@ -39,7 +39,7 @@ def dump( skipkeys: bool = ..., ) -> None: ... def dumps( - value: Mapping[str, Any] | list[Any] | Tuple[Any, ...] | str | bool | float | bytes | datetime, + value: Mapping[str, Any] | list[Any] | tuple[Any, ...] | str | bool | float | bytes | datetime, *, fmt: PlistFormat = ..., skipkeys: bool = ..., @@ -53,7 +53,7 @@ if sys.version_info < (3, 9): def writePlistToBytes(value: Mapping[str, Any]) -> bytes: ... if sys.version_info < (3, 7): - class Dict(_Dict[str, Any]): + class Dict(dict[str, Any]): def __getattr__(self, attr: str) -> Any: ... def __setattr__(self, attr: str, value: Any) -> None: ... def __delattr__(self, attr: str) -> None: ... diff --git a/mypy/typeshed/stdlib/poplib.pyi b/mypy/typeshed/stdlib/poplib.pyi index 28fba4ce951f3..028af412847b3 100644 --- a/mypy/typeshed/stdlib/poplib.pyi +++ b/mypy/typeshed/stdlib/poplib.pyi @@ -1,8 +1,8 @@ import socket import ssl -from typing import Any, BinaryIO, List, Pattern, Tuple, overload +from typing import Any, BinaryIO, Pattern, overload -_LongResp = Tuple[bytes, List[bytes], int] +_LongResp = tuple[bytes, list[bytes], int] class error_proto(Exception): ... diff --git a/mypy/typeshed/stdlib/posix.pyi b/mypy/typeshed/stdlib/posix.pyi index 14cea87cde29b..9f658039bcf25 100644 --- a/mypy/typeshed/stdlib/posix.pyi +++ b/mypy/typeshed/stdlib/posix.pyi @@ -1,204 +1,322 @@ import sys -from _typeshed import StrOrBytesPath -from os import PathLike, _ExecEnv, _ExecVArgs, stat_result as stat_result -from typing import Any, Iterable, NamedTuple, Sequence, Tuple, overload -from typing_extensions import final -@final -class uname_result(NamedTuple): - sysname: str - nodename: str - release: str - version: str - machine: str +if sys.platform != "win32": + # Actually defined here, but defining in os allows sharing code with windows + from os import ( + CLD_CONTINUED as CLD_CONTINUED, + CLD_DUMPED as CLD_DUMPED, + CLD_EXITED as CLD_EXITED, + CLD_TRAPPED as CLD_TRAPPED, + EX_CANTCREAT as EX_CANTCREAT, + EX_CONFIG as EX_CONFIG, + EX_DATAERR as EX_DATAERR, + EX_IOERR as EX_IOERR, + EX_NOHOST as EX_NOHOST, + EX_NOINPUT as EX_NOINPUT, + EX_NOPERM as EX_NOPERM, + EX_NOTFOUND as EX_NOTFOUND, + EX_NOUSER as EX_NOUSER, + EX_OK as EX_OK, + EX_OSERR as EX_OSERR, + EX_OSFILE as EX_OSFILE, + EX_PROTOCOL as EX_PROTOCOL, + EX_SOFTWARE as EX_SOFTWARE, + EX_TEMPFAIL as EX_TEMPFAIL, + EX_UNAVAILABLE as EX_UNAVAILABLE, + EX_USAGE as EX_USAGE, + F_LOCK as F_LOCK, + F_OK as F_OK, + F_TEST as F_TEST, + F_TLOCK as F_TLOCK, + F_ULOCK as F_ULOCK, + O_APPEND as O_APPEND, + O_ASYNC as O_ASYNC, + O_CREAT as O_CREAT, + O_DIRECT as O_DIRECT, + O_DIRECTORY as O_DIRECTORY, + O_DSYNC as O_DSYNC, + O_EXCL as O_EXCL, + O_LARGEFILE as O_LARGEFILE, + O_NDELAY as O_NDELAY, + O_NOATIME as O_NOATIME, + O_NOCTTY as O_NOCTTY, + O_NOFOLLOW as O_NOFOLLOW, + O_NONBLOCK as O_NONBLOCK, + O_RDONLY as O_RDONLY, + O_RDWR as O_RDWR, + O_RSYNC as O_RSYNC, + O_SYNC as O_SYNC, + O_TRUNC as O_TRUNC, + O_WRONLY as O_WRONLY, + P_ALL as P_ALL, + P_PGID as P_PGID, + P_PID as P_PID, + PRIO_PGRP as PRIO_PGRP, + PRIO_PROCESS as PRIO_PROCESS, + PRIO_USER as PRIO_USER, + R_OK as R_OK, + RTLD_GLOBAL as RTLD_GLOBAL, + RTLD_LAZY as RTLD_LAZY, + RTLD_LOCAL as RTLD_LOCAL, + RTLD_NODELETE as RTLD_NODELETE, + RTLD_NOLOAD as RTLD_NOLOAD, + RTLD_NOW as RTLD_NOW, + SCHED_BATCH as SCHED_BATCH, + SCHED_FIFO as SCHED_FIFO, + SCHED_IDLE as SCHED_IDLE, + SCHED_OTHER as SCHED_OTHER, + SCHED_RESET_ON_FORK as SCHED_RESET_ON_FORK, + SCHED_RR as SCHED_RR, + SCHED_SPORADIC as SCHED_SPORADIC, + SEEK_DATA as SEEK_DATA, + SEEK_HOLE as SEEK_HOLE, + ST_NOSUID as ST_NOSUID, + ST_RDONLY as ST_RDONLY, + TMP_MAX as TMP_MAX, + W_OK as W_OK, + WCONTINUED as WCONTINUED, + WCOREDUMP as WCOREDUMP, + WEXITED as WEXITED, + WEXITSTATUS as WEXITSTATUS, + WIFCONTINUED as WIFCONTINUED, + WIFEXITED as WIFEXITED, + WIFSIGNALED as WIFSIGNALED, + WIFSTOPPED as WIFSTOPPED, + WNOHANG as WNOHANG, + WNOWAIT as WNOWAIT, + WSTOPPED as WSTOPPED, + WSTOPSIG as WSTOPSIG, + WTERMSIG as WTERMSIG, + WUNTRACED as WUNTRACED, + X_OK as X_OK, + DirEntry as DirEntry, + _exit as _exit, + abort as abort, + access as access, + chdir as chdir, + chmod as chmod, + chown as chown, + chroot as chroot, + close as close, + closerange as closerange, + confstr as confstr, + confstr_names as confstr_names, + cpu_count as cpu_count, + ctermid as ctermid, + device_encoding as device_encoding, + dup as dup, + dup2 as dup2, + error as error, + execv as execv, + execve as execve, + fchdir as fchdir, + fchmod as fchmod, + fchown as fchown, + fork as fork, + forkpty as forkpty, + fpathconf as fpathconf, + fspath as fspath, + fstat as fstat, + fstatvfs as fstatvfs, + fsync as fsync, + ftruncate as ftruncate, + get_blocking as get_blocking, + get_inheritable as get_inheritable, + get_terminal_size as get_terminal_size, + getcwd as getcwd, + getcwdb as getcwdb, + getegid as getegid, + geteuid as geteuid, + getgid as getgid, + getgrouplist as getgrouplist, + getgroups as getgroups, + getloadavg as getloadavg, + getlogin as getlogin, + getpgid as getpgid, + getpgrp as getpgrp, + getpid as getpid, + getppid as getppid, + getpriority as getpriority, + getsid as getsid, + getuid as getuid, + initgroups as initgroups, + isatty as isatty, + kill as kill, + killpg as killpg, + lchown as lchown, + link as link, + listdir as listdir, + lockf as lockf, + lseek as lseek, + lstat as lstat, + major as major, + makedev as makedev, + minor as minor, + mkdir as mkdir, + mkfifo as mkfifo, + mknod as mknod, + nice as nice, + open as open, + openpty as openpty, + pathconf as pathconf, + pathconf_names as pathconf_names, + pipe as pipe, + pread as pread, + putenv as putenv, + pwrite as pwrite, + read as read, + readlink as readlink, + readv as readv, + remove as remove, + rename as rename, + replace as replace, + rmdir as rmdir, + scandir as scandir, + sched_get_priority_max as sched_get_priority_max, + sched_get_priority_min as sched_get_priority_min, + sched_param as sched_param, + sched_yield as sched_yield, + sendfile as sendfile, + set_blocking as set_blocking, + set_inheritable as set_inheritable, + setegid as setegid, + seteuid as seteuid, + setgid as setgid, + setgroups as setgroups, + setpgid as setpgid, + setpgrp as setpgrp, + setpriority as setpriority, + setregid as setregid, + setreuid as setreuid, + setsid as setsid, + setuid as setuid, + stat as stat, + stat_result as stat_result, + statvfs as statvfs, + statvfs_result as statvfs_result, + strerror as strerror, + symlink as symlink, + sync as sync, + sysconf as sysconf, + sysconf_names as sysconf_names, + system as system, + tcgetpgrp as tcgetpgrp, + tcsetpgrp as tcsetpgrp, + terminal_size as terminal_size, + times as times, + times_result as times_result, + truncate as truncate, + ttyname as ttyname, + umask as umask, + uname as uname, + uname_result as uname_result, + unlink as unlink, + unsetenv as unsetenv, + urandom as urandom, + utime as utime, + wait as wait, + wait3 as wait3, + wait4 as wait4, + waitpid as waitpid, + write as write, + writev as writev, + ) -@final -class times_result(NamedTuple): - user: float - system: float - children_user: float - children_system: float - elapsed: float + if sys.platform == "linux": + from os import ( + GRND_NONBLOCK as GRND_NONBLOCK, + GRND_RANDOM as GRND_RANDOM, + RTLD_DEEPBIND as RTLD_DEEPBIND, + XATTR_CREATE as XATTR_CREATE, + XATTR_REPLACE as XATTR_REPLACE, + XATTR_SIZE_MAX as XATTR_SIZE_MAX, + getrandom as getrandom, + getxattr as getxattr, + listxattr as listxattr, + removexattr as removexattr, + setxattr as setxattr, + ) + else: + from os import chflags as chflags, lchflags as lchflags, lchmod as lchmod -if sys.platform != "darwin": - class waitid_result(NamedTuple): - si_pid: int - si_uid: int - si_signo: int - si_status: int - si_code: int + if sys.platform != "darwin": + from os import ( + POSIX_FADV_DONTNEED as POSIX_FADV_DONTNEED, + POSIX_FADV_NOREUSE as POSIX_FADV_NOREUSE, + POSIX_FADV_NORMAL as POSIX_FADV_NORMAL, + POSIX_FADV_RANDOM as POSIX_FADV_RANDOM, + POSIX_FADV_SEQUENTIAL as POSIX_FADV_SEQUENTIAL, + POSIX_FADV_WILLNEED as POSIX_FADV_WILLNEED, + fdatasync as fdatasync, + getresgid as getresgid, + getresuid as getresuid, + pipe2 as pipe2, + posix_fadvise as posix_fadvise, + posix_fallocate as posix_fallocate, + sched_getaffinity as sched_getaffinity, + sched_getparam as sched_getparam, + sched_getscheduler as sched_getscheduler, + sched_rr_get_interval as sched_rr_get_interval, + sched_setaffinity as sched_setaffinity, + sched_setparam as sched_setparam, + sched_setscheduler as sched_setscheduler, + setresgid as setresgid, + setresuid as setresuid, + waitid as waitid, + waitid_result as waitid_result, + ) -class sched_param(NamedTuple): - sched_priority: int + if sys.version_info >= (3, 10): + from os import RWF_APPEND as RWF_APPEND -CLD_CONTINUED: int -CLD_DUMPED: int -CLD_EXITED: int -CLD_TRAPPED: int + if sys.version_info >= (3, 9): + from os import CLD_KILLED as CLD_KILLED, CLD_STOPPED as CLD_STOPPED, waitstatus_to_exitcode as waitstatus_to_exitcode -EX_CANTCREAT: int -EX_CONFIG: int -EX_DATAERR: int -EX_IOERR: int -EX_NOHOST: int -EX_NOINPUT: int -EX_NOPERM: int -EX_NOTFOUND: int -EX_NOUSER: int -EX_OK: int -EX_OSERR: int -EX_OSFILE: int -EX_PROTOCOL: int -EX_SOFTWARE: int -EX_TEMPFAIL: int -EX_UNAVAILABLE: int -EX_USAGE: int + if sys.platform == "linux": + from os import P_PIDFD as P_PIDFD + if sys.version_info >= (3, 8): + from os import ( + POSIX_SPAWN_CLOSE as POSIX_SPAWN_CLOSE, + POSIX_SPAWN_DUP2 as POSIX_SPAWN_DUP2, + POSIX_SPAWN_OPEN as POSIX_SPAWN_OPEN, + posix_spawn as posix_spawn, + posix_spawnp as posix_spawnp, + ) -F_OK: int -R_OK: int -W_OK: int -X_OK: int + if sys.platform == "linux": + from os import ( + MFD_ALLOW_SEALING as MFD_ALLOW_SEALING, + MFD_CLOEXEC as MFD_CLOEXEC, + MFD_HUGE_1GB as MFD_HUGE_1GB, + MFD_HUGE_1MB as MFD_HUGE_1MB, + MFD_HUGE_2GB as MFD_HUGE_2GB, + MFD_HUGE_2MB as MFD_HUGE_2MB, + MFD_HUGE_8MB as MFD_HUGE_8MB, + MFD_HUGE_16GB as MFD_HUGE_16GB, + MFD_HUGE_16MB as MFD_HUGE_16MB, + MFD_HUGE_32MB as MFD_HUGE_32MB, + MFD_HUGE_64KB as MFD_HUGE_64KB, + MFD_HUGE_256MB as MFD_HUGE_256MB, + MFD_HUGE_512KB as MFD_HUGE_512KB, + MFD_HUGE_512MB as MFD_HUGE_512MB, + MFD_HUGE_MASK as MFD_HUGE_MASK, + MFD_HUGE_SHIFT as MFD_HUGE_SHIFT, + MFD_HUGETLB as MFD_HUGETLB, + memfd_create as memfd_create, + ) + if sys.version_info >= (3, 7): + from os import register_at_fork as register_at_fork -F_LOCK: int -F_TEST: int -F_TLOCK: int -F_ULOCK: int + if sys.platform != "darwin": + from os import ( + RWF_DSYNC as RWF_DSYNC, + RWF_HIPRI as RWF_HIPRI, + RWF_NOWAIT as RWF_NOWAIT, + RWF_SYNC as RWF_SYNC, + preadv as preadv, + pwritev as pwritev, + ) -if sys.platform == "linux": - GRND_NONBLOCK: int - GRND_RANDOM: int -NGROUPS_MAX: int - -O_APPEND: int -O_ACCMODE: int -O_ASYNC: int -O_CREAT: int -O_DIRECT: int -O_DIRECTORY: int -O_DSYNC: int -O_EXCL: int -O_LARGEFILE: int -O_NDELAY: int -O_NOATIME: int -O_NOCTTY: int -O_NOFOLLOW: int -O_NONBLOCK: int -O_RDONLY: int -O_RDWR: int -O_RSYNC: int -O_SYNC: int -O_TRUNC: int -O_WRONLY: int - -if sys.platform != "darwin": - POSIX_FADV_DONTNEED: int - POSIX_FADV_NOREUSE: int - POSIX_FADV_NORMAL: int - POSIX_FADV_RANDOM: int - POSIX_FADV_SEQUENTIAL: int - POSIX_FADV_WILLNEED: int - -PRIO_PGRP: int -PRIO_PROCESS: int -PRIO_USER: int - -P_ALL: int -P_PGID: int -P_PID: int - -if sys.platform == "linux": - RTLD_DEEPBIND: int -RTLD_GLOBAL: int -RTLD_LAZY: int -RTLD_LOCAL: int -RTLD_NODELETE: int -RTLD_NOLOAD: int -RTLD_NOW: int - -SCHED_FIFO: int -SCHED_OTHER: int -SCHED_RR: int - -if sys.platform == "linux": - SCHED_BATCH: int - SCHED_IDLE: int -if sys.platform != "darwin": - SCHED_RESET_ON_FORK: int - -SEEK_DATA: int -SEEK_HOLE: int - -ST_APPEND: int -ST_MANDLOCK: int -ST_NOATIME: int -ST_NODEV: int -ST_NODIRATIME: int -ST_NOEXEC: int -ST_NOSUID: int -ST_RDONLY: int -ST_RELATIME: int -ST_SYNCHRONOUS: int -ST_WRITE: int - -TMP_MAX: int -WCONTINUED: int - -def WCOREDUMP(__status: int) -> bool: ... -def WEXITSTATUS(status: int) -> int: ... -def WIFCONTINUED(status: int) -> bool: ... -def WIFEXITED(status: int) -> bool: ... -def WIFSIGNALED(status: int) -> bool: ... -def WIFSTOPPED(status: int) -> bool: ... - -WNOHANG: int - -def WSTOPSIG(status: int) -> int: ... -def WTERMSIG(status: int) -> int: ... - -WUNTRACED: int - -XATTR_CREATE: int -XATTR_REPLACE: int -XATTR_SIZE_MAX: int - -@overload -def listdir(path: str | None = ...) -> list[str]: ... -@overload -def listdir(path: bytes) -> list[bytes]: ... -@overload -def listdir(path: int) -> list[str]: ... -@overload -def listdir(path: PathLike[str]) -> list[str]: ... - -if sys.platform != "win32" and sys.version_info >= (3, 8): - def posix_spawn( - path: StrOrBytesPath, - argv: _ExecVArgs, - env: _ExecEnv, - *, - file_actions: Sequence[Tuple[Any, ...]] | None = ..., - setpgroup: int | None = ..., - resetids: bool = ..., - setsid: bool = ..., - setsigmask: Iterable[int] = ..., - setsigdef: Iterable[int] = ..., - scheduler: tuple[Any, sched_param] | None = ..., - ) -> int: ... - def posix_spawnp( - path: StrOrBytesPath, - argv: _ExecVArgs, - env: _ExecEnv, - *, - file_actions: Sequence[Tuple[Any, ...]] | None = ..., - setpgroup: int | None = ..., - resetids: bool = ..., - setsid: bool = ..., - setsigmask: Iterable[int] = ..., - setsigdef: Iterable[int] = ..., - scheduler: tuple[Any, sched_param] | None = ..., - ) -> int: ... - -if sys.platform == "win32": - environ: dict[str, str] -else: + # Not same as os.environ or os.environb + # Because of this variable, we can't do "from posix import *" in os/__init__.pyi environ: dict[bytes, bytes] diff --git a/mypy/typeshed/stdlib/posixpath.pyi b/mypy/typeshed/stdlib/posixpath.pyi index ae3d0d5cc65f1..58cadb4de03cc 100644 --- a/mypy/typeshed/stdlib/posixpath.pyi +++ b/mypy/typeshed/stdlib/posixpath.pyi @@ -60,10 +60,14 @@ def normpath(path: AnyStr) -> AnyStr: ... def commonpath(paths: Sequence[StrPath]) -> str: ... @overload def commonpath(paths: Sequence[BytesPath]) -> bytes: ... + +# First parameter is not actually pos-only, +# but must be defined as pos-only in the stub or cross-platform code doesn't type-check, +# as the parameter name is different in ntpath.join() @overload -def join(a: StrPath, *paths: StrPath) -> str: ... +def join(__a: StrPath, *paths: StrPath) -> str: ... @overload -def join(a: BytesPath, *paths: BytesPath) -> bytes: ... +def join(__a: BytesPath, *paths: BytesPath) -> bytes: ... if sys.version_info >= (3, 10): @overload diff --git a/mypy/typeshed/stdlib/profile.pyi b/mypy/typeshed/stdlib/profile.pyi index cb0cbf7c93886..7581c0122c9c1 100644 --- a/mypy/typeshed/stdlib/profile.pyi +++ b/mypy/typeshed/stdlib/profile.pyi @@ -1,5 +1,5 @@ from _typeshed import StrOrBytesPath -from typing import Any, Callable, Tuple, TypeVar +from typing import Any, Callable, TypeVar def run(statement: str, filename: str | None = ..., sort: str | int = ...) -> None: ... def runctx( @@ -8,7 +8,7 @@ def runctx( _SelfT = TypeVar("_SelfT", bound=Profile) _T = TypeVar("_T") -_Label = Tuple[str, int, str] +_Label = tuple[str, int, str] class Profile: bias: int diff --git a/mypy/typeshed/stdlib/pstats.pyi b/mypy/typeshed/stdlib/pstats.pyi index e8256f9f98ab4..6e008c823ff2a 100644 --- a/mypy/typeshed/stdlib/pstats.pyi +++ b/mypy/typeshed/stdlib/pstats.pyi @@ -2,7 +2,7 @@ import sys from _typeshed import StrOrBytesPath from cProfile import Profile as _cProfile from profile import Profile -from typing import IO, Any, Iterable, Tuple, TypeVar, Union, overload +from typing import IO, Any, Iterable, TypeVar, Union, overload _Selector = Union[str, float, int] _T = TypeVar("_T", bound=Stats) @@ -33,7 +33,7 @@ class Stats: def get_top_level_stats(self) -> None: ... def add(self: _T, *arg_list: None | str | Profile | _cProfile | _T) -> _T: ... def dump_stats(self, filename: StrOrBytesPath) -> None: ... - def get_sort_arg_defs(self) -> dict[str, tuple[Tuple[tuple[int, int], ...], str]]: ... + def get_sort_arg_defs(self) -> dict[str, tuple[tuple[tuple[int, int], ...], str]]: ... @overload def sort_stats(self: _T, field: int) -> _T: ... @overload diff --git a/mypy/typeshed/stdlib/pty.pyi b/mypy/typeshed/stdlib/pty.pyi index f943cebdb157a..73c6ddfbd0c4e 100644 --- a/mypy/typeshed/stdlib/pty.pyi +++ b/mypy/typeshed/stdlib/pty.pyi @@ -1,15 +1,18 @@ +import sys from typing import Callable, Iterable +from typing_extensions import Literal -_Reader = Callable[[int], bytes] +if sys.platform != "win32": + __all__ = ["openpty", "fork", "spawn"] + _Reader = Callable[[int], bytes] -STDIN_FILENO: int -STDOUT_FILENO: int -STDERR_FILENO: int + STDIN_FILENO: Literal[0] + STDOUT_FILENO: Literal[1] + STDERR_FILENO: Literal[2] -CHILD: int - -def openpty() -> tuple[int, int]: ... -def master_open() -> tuple[int, str]: ... -def slave_open(tty_name: str) -> int: ... -def fork() -> tuple[int, int]: ... -def spawn(argv: str | Iterable[str], master_read: _Reader = ..., stdin_read: _Reader = ...) -> int: ... + CHILD: Literal[0] + def openpty() -> tuple[int, int]: ... + def master_open() -> tuple[int, str]: ... # deprecated, use openpty() + def slave_open(tty_name: str) -> int: ... # deprecated, use openpty() + def fork() -> tuple[int, int]: ... + def spawn(argv: str | Iterable[str], master_read: _Reader = ..., stdin_read: _Reader = ...) -> int: ... diff --git a/mypy/typeshed/stdlib/pwd.pyi b/mypy/typeshed/stdlib/pwd.pyi index 2b931248edda3..08a9facf642e9 100644 --- a/mypy/typeshed/stdlib/pwd.pyi +++ b/mypy/typeshed/stdlib/pwd.pyi @@ -1,18 +1,25 @@ -from typing import ClassVar, Tuple +import sys +from _typeshed import structseq +from typing import Any +from typing_extensions import final -class struct_passwd(Tuple[str, str, int, int, str, str, str]): - pw_name: str - pw_passwd: str - pw_uid: int - pw_gid: int - pw_gecos: str - pw_dir: str - pw_shell: str - - n_fields: ClassVar[int] - n_sequence_fields: ClassVar[int] - n_unnamed_fields: ClassVar[int] - -def getpwall() -> list[struct_passwd]: ... -def getpwuid(__uid: int) -> struct_passwd: ... -def getpwnam(__name: str) -> struct_passwd: ... +if sys.platform != "win32": + @final + class struct_passwd(structseq[Any], tuple[str, str, int, int, str, str, str]): + @property + def pw_name(self) -> str: ... + @property + def pw_passwd(self) -> str: ... + @property + def pw_uid(self) -> int: ... + @property + def pw_gid(self) -> int: ... + @property + def pw_gecos(self) -> str: ... + @property + def pw_dir(self) -> str: ... + @property + def pw_shell(self) -> str: ... + def getpwall() -> list[struct_passwd]: ... + def getpwuid(__uid: int) -> struct_passwd: ... + def getpwnam(__name: str) -> struct_passwd: ... diff --git a/mypy/typeshed/stdlib/pydoc.pyi b/mypy/typeshed/stdlib/pydoc.pyi index 97e71f389616d..a1d4359d28fc9 100644 --- a/mypy/typeshed/stdlib/pydoc.pyi +++ b/mypy/typeshed/stdlib/pydoc.pyi @@ -1,10 +1,10 @@ from _typeshed import SupportsWrite from reprlib import Repr from types import MethodType, ModuleType, TracebackType -from typing import IO, Any, AnyStr, Callable, Container, Mapping, MutableMapping, NoReturn, Optional, Tuple, Type +from typing import IO, Any, AnyStr, Callable, Container, Mapping, MutableMapping, NoReturn, Optional, Type # the return type of sys.exc_info(), used by ErrorDuringImport.__init__ -_Exc_Info = Tuple[Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType]] +_Exc_Info = tuple[Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType]] __author__: str __date__: str @@ -96,7 +96,7 @@ class HTMLDoc(Doc): methods: Mapping[str, str] = ..., ) -> str: ... def formattree( - self, tree: list[tuple[type, Tuple[type, ...]] | list[Any]], modname: str, parent: type | None = ... + self, tree: list[tuple[type, tuple[type, ...]] | list[Any]], modname: str, parent: type | None = ... ) -> str: ... def docmodule(self, object: object, name: str | None = ..., mod: str | None = ..., *ignored: Any) -> str: ... def docclass( @@ -109,7 +109,7 @@ class HTMLDoc(Doc): *ignored: Any, ) -> str: ... def formatvalue(self, object: object) -> str: ... - def docroutine( + def docroutine( # type: ignore[override] self, object: object, name: str | None = ..., @@ -118,15 +118,10 @@ class HTMLDoc(Doc): classes: Mapping[str, str] = ..., methods: Mapping[str, str] = ..., cl: type | None = ..., - *ignored: Any, - ) -> str: ... - def docproperty( - self, object: object, name: str | None = ..., mod: str | None = ..., cl: Any | None = ..., *ignored: Any ) -> str: ... + def docproperty(self, object: object, name: str | None = ..., mod: str | None = ..., cl: Any | None = ...) -> str: ... # type: ignore[override] def docother(self, object: object, name: str | None = ..., mod: Any | None = ..., *ignored: Any) -> str: ... - def docdata( - self, object: object, name: str | None = ..., mod: Any | None = ..., cl: Any | None = ..., *ignored: Any - ) -> str: ... + def docdata(self, object: object, name: str | None = ..., mod: Any | None = ..., cl: Any | None = ...) -> str: ... # type: ignore[override] def index(self, dir: str, shadowed: MutableMapping[str, bool] | None = ...) -> str: ... def filelink(self, url: str, path: str) -> str: ... @@ -148,21 +143,15 @@ class TextDoc(Doc): def indent(self, text: str, prefix: str = ...) -> str: ... def section(self, title: str, contents: str) -> str: ... def formattree( - self, tree: list[tuple[type, Tuple[type, ...]] | list[Any]], modname: str, parent: type | None = ..., prefix: str = ... + self, tree: list[tuple[type, tuple[type, ...]] | list[Any]], modname: str, parent: type | None = ..., prefix: str = ... ) -> str: ... - def docmodule(self, object: object, name: str | None = ..., mod: Any | None = ..., *ignored: Any) -> str: ... + def docmodule(self, object: object, name: str | None = ..., mod: Any | None = ...) -> str: ... # type: ignore[override] def docclass(self, object: object, name: str | None = ..., mod: str | None = ..., *ignored: Any) -> str: ... def formatvalue(self, object: object) -> str: ... - def docroutine( - self, object: object, name: str | None = ..., mod: str | None = ..., cl: Any | None = ..., *ignored: Any - ) -> str: ... - def docproperty( - self, object: object, name: str | None = ..., mod: Any | None = ..., cl: Any | None = ..., *ignored: Any - ) -> str: ... - def docdata( - self, object: object, name: str | None = ..., mod: str | None = ..., cl: Any | None = ..., *ignored: Any - ) -> str: ... - def docother( + def docroutine(self, object: object, name: str | None = ..., mod: str | None = ..., cl: Any | None = ...) -> str: ... # type: ignore[override] + def docproperty(self, object: object, name: str | None = ..., mod: Any | None = ..., cl: Any | None = ...) -> str: ... # type: ignore[override] + def docdata(self, object: object, name: str | None = ..., mod: str | None = ..., cl: Any | None = ...) -> str: ... # type: ignore[override] + def docother( # type: ignore[override] self, object: object, name: str | None = ..., @@ -170,7 +159,6 @@ class TextDoc(Doc): parent: str | None = ..., maxlen: int | None = ..., doc: Any | None = ..., - *ignored: Any, ) -> str: ... def pager(text: str) -> None: ... @@ -199,7 +187,7 @@ _list = list # "list" conflicts with method name class Helper: keywords: dict[str, str | tuple[str, str]] symbols: dict[str, str] - topics: dict[str, str | Tuple[str, ...]] + topics: dict[str, str | tuple[str, ...]] def __init__(self, input: IO[str] | None = ..., output: IO[str] | None = ...) -> None: ... input: IO[str] output: IO[str] diff --git a/mypy/typeshed/stdlib/pyexpat/__init__.pyi b/mypy/typeshed/stdlib/pyexpat/__init__.pyi index 6a3d6cd567914..5aca55c2b813d 100644 --- a/mypy/typeshed/stdlib/pyexpat/__init__.pyi +++ b/mypy/typeshed/stdlib/pyexpat/__init__.pyi @@ -1,7 +1,7 @@ import pyexpat.errors as errors import pyexpat.model as model from _typeshed import SupportsRead -from typing import Any, Callable, Optional, Tuple +from typing import Any, Callable, Optional from typing_extensions import final EXPAT_VERSION: str # undocumented @@ -20,10 +20,10 @@ XML_PARAM_ENTITY_PARSING_NEVER: int XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE: int XML_PARAM_ENTITY_PARSING_ALWAYS: int -_Model = Tuple[int, int, Optional[str], Tuple[Any, ...]] +_Model = tuple[int, int, Optional[str], tuple[Any, ...]] @final -class XMLParserType(object): +class XMLParserType: def Parse(self, __data: str | bytes, __isfinal: bool = ...) -> int: ... def ParseFile(self, __file: SupportsRead[bytes]) -> int: ... def SetBase(self, __base: str) -> None: ... diff --git a/mypy/typeshed/stdlib/random.pyi b/mypy/typeshed/stdlib/random.pyi index 73c29d2f78c3c..ffa866ef9aa05 100644 --- a/mypy/typeshed/stdlib/random.pyi +++ b/mypy/typeshed/stdlib/random.pyi @@ -1,25 +1,27 @@ import _random import sys +from _typeshed import SupportsLenAndGetItem from collections.abc import Callable, Iterable, MutableSequence, Sequence, Set as AbstractSet from fractions import Fraction -from typing import Any, NoReturn, Tuple, TypeVar +from typing import Any, ClassVar, NoReturn, TypeVar _T = TypeVar("_T") class Random(_random.Random): + VERSION: ClassVar[int] def __init__(self, x: Any = ...) -> None: ... def seed(self, a: Any = ..., version: int = ...) -> None: ... - def getstate(self) -> Tuple[Any, ...]: ... - def setstate(self, state: Tuple[Any, ...]) -> None: ... + def getstate(self) -> tuple[Any, ...]: ... + def setstate(self, state: tuple[Any, ...]) -> None: ... def getrandbits(self, __k: int) -> int: ... def randrange(self, start: int, stop: int | None = ..., step: int = ...) -> int: ... def randint(self, a: int, b: int) -> int: ... if sys.version_info >= (3, 9): def randbytes(self, n: int) -> bytes: ... - def choice(self, seq: Sequence[_T]) -> _T: ... + def choice(self, seq: SupportsLenAndGetItem[_T]) -> _T: ... def choices( self, - population: Sequence[_T], + population: SupportsLenAndGetItem[_T], weights: Sequence[float | Fraction] | None = ..., *, cum_weights: Sequence[float | Fraction] | None = ..., @@ -27,7 +29,9 @@ class Random(_random.Random): ) -> list[_T]: ... def shuffle(self, x: MutableSequence[Any], random: Callable[[], float] | None = ...) -> None: ... if sys.version_info >= (3, 9): - def sample(self, population: Sequence[_T] | AbstractSet[_T], k: int, *, counts: Iterable[_T] | None = ...) -> list[_T]: ... + def sample( + self, population: Sequence[_T] | AbstractSet[_T], k: int, *, counts: Iterable[_T] | None = ... + ) -> list[_T]: ... else: def sample(self, population: Sequence[_T] | AbstractSet[_T], k: int) -> list[_T]: ... def random(self) -> float: ... @@ -45,6 +49,7 @@ class Random(_random.Random): # SystemRandom is not implemented for all OS's; good on Windows & Linux class SystemRandom(Random): + def getrandbits(self, k: int) -> int: ... # k can be passed by keyword def getstate(self, *args: Any, **kwds: Any) -> NoReturn: ... def setstate(self, *args: Any, **kwds: Any) -> NoReturn: ... @@ -59,9 +64,13 @@ def randint(a: int, b: int) -> int: ... if sys.version_info >= (3, 9): def randbytes(n: int) -> bytes: ... -def choice(seq: Sequence[_T]) -> _T: ... +def choice(seq: SupportsLenAndGetItem[_T]) -> _T: ... def choices( - population: Sequence[_T], weights: Sequence[float] | None = ..., *, cum_weights: Sequence[float] | None = ..., k: int = ... + population: SupportsLenAndGetItem[_T], + weights: Sequence[float] | None = ..., + *, + cum_weights: Sequence[float] | None = ..., + k: int = ..., ) -> list[_T]: ... def shuffle(x: MutableSequence[Any], random: Callable[[], float] | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/readline.pyi b/mypy/typeshed/stdlib/readline.pyi index 2de749b2c216b..fd3a4b1dcc654 100644 --- a/mypy/typeshed/stdlib/readline.pyi +++ b/mypy/typeshed/stdlib/readline.pyi @@ -1,33 +1,34 @@ +import sys from _typeshed import StrOrBytesPath from typing import Callable, Optional, Sequence -_CompleterT = Optional[Callable[[str, int], Optional[str]]] -_CompDispT = Optional[Callable[[str, Sequence[str], int], None]] - -def parse_and_bind(__string: str) -> None: ... -def read_init_file(__filename: StrOrBytesPath | None = ...) -> None: ... -def get_line_buffer() -> str: ... -def insert_text(__string: str) -> None: ... -def redisplay() -> None: ... -def read_history_file(__filename: StrOrBytesPath | None = ...) -> None: ... -def write_history_file(__filename: StrOrBytesPath | None = ...) -> None: ... -def append_history_file(__nelements: int, __filename: StrOrBytesPath | None = ...) -> None: ... -def get_history_length() -> int: ... -def set_history_length(__length: int) -> None: ... -def clear_history() -> None: ... -def get_current_history_length() -> int: ... -def get_history_item(__index: int) -> str: ... -def remove_history_item(__pos: int) -> None: ... -def replace_history_item(__pos: int, __line: str) -> None: ... -def add_history(__string: str) -> None: ... -def set_auto_history(__enabled: bool) -> None: ... -def set_startup_hook(__function: Callable[[], None] | None = ...) -> None: ... -def set_pre_input_hook(__function: Callable[[], None] | None = ...) -> None: ... -def set_completer(__function: _CompleterT = ...) -> None: ... -def get_completer() -> _CompleterT: ... -def get_completion_type() -> int: ... -def get_begidx() -> int: ... -def get_endidx() -> int: ... -def set_completer_delims(__string: str) -> None: ... -def get_completer_delims() -> str: ... -def set_completion_display_matches_hook(__function: _CompDispT = ...) -> None: ... +if sys.platform != "win32": + _CompleterT = Optional[Callable[[str, int], Optional[str]]] + _CompDispT = Optional[Callable[[str, Sequence[str], int], None]] + def parse_and_bind(__string: str) -> None: ... + def read_init_file(__filename: StrOrBytesPath | None = ...) -> None: ... + def get_line_buffer() -> str: ... + def insert_text(__string: str) -> None: ... + def redisplay() -> None: ... + def read_history_file(__filename: StrOrBytesPath | None = ...) -> None: ... + def write_history_file(__filename: StrOrBytesPath | None = ...) -> None: ... + def append_history_file(__nelements: int, __filename: StrOrBytesPath | None = ...) -> None: ... + def get_history_length() -> int: ... + def set_history_length(__length: int) -> None: ... + def clear_history() -> None: ... + def get_current_history_length() -> int: ... + def get_history_item(__index: int) -> str: ... + def remove_history_item(__pos: int) -> None: ... + def replace_history_item(__pos: int, __line: str) -> None: ... + def add_history(__string: str) -> None: ... + def set_auto_history(__enabled: bool) -> None: ... + def set_startup_hook(__function: Callable[[], None] | None = ...) -> None: ... + def set_pre_input_hook(__function: Callable[[], None] | None = ...) -> None: ... + def set_completer(__function: _CompleterT = ...) -> None: ... + def get_completer() -> _CompleterT: ... + def get_completion_type() -> int: ... + def get_begidx() -> int: ... + def get_endidx() -> int: ... + def set_completer_delims(__string: str) -> None: ... + def get_completer_delims() -> str: ... + def set_completion_display_matches_hook(__function: _CompDispT = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/reprlib.pyi b/mypy/typeshed/stdlib/reprlib.pyi index 4d400554a4ff1..2095c0af69835 100644 --- a/mypy/typeshed/stdlib/reprlib.pyi +++ b/mypy/typeshed/stdlib/reprlib.pyi @@ -1,6 +1,6 @@ from array import array from collections import deque -from typing import Any, Callable, Tuple +from typing import Any, Callable _ReprFunc = Callable[[Any], str] @@ -21,7 +21,7 @@ class Repr: def __init__(self) -> None: ... def repr(self, x: Any) -> str: ... def repr1(self, x: Any, level: int) -> str: ... - def repr_tuple(self, x: Tuple[Any, ...], level: int) -> str: ... + def repr_tuple(self, x: tuple[Any, ...], level: int) -> str: ... def repr_list(self, x: list[Any], level: int) -> str: ... def repr_array(self, x: array[Any], level: int) -> str: ... def repr_set(self, x: set[Any], level: int) -> str: ... diff --git a/mypy/typeshed/stdlib/resource.pyi b/mypy/typeshed/stdlib/resource.pyi index d7124edcc2fa1..19a6f470b7755 100644 --- a/mypy/typeshed/stdlib/resource.pyi +++ b/mypy/typeshed/stdlib/resource.pyi @@ -1,58 +1,73 @@ import sys -from typing import Any, Tuple, overload +from _typeshed import structseq +from typing import overload +from typing_extensions import final -RLIMIT_AS: int -RLIMIT_CORE: int -RLIMIT_CPU: int -RLIMIT_DATA: int -RLIMIT_FSIZE: int -RLIMIT_MEMLOCK: int -RLIMIT_NOFILE: int -RLIMIT_NPROC: int -RLIMIT_RSS: int -RLIMIT_STACK: int -RLIM_INFINITY: int -RUSAGE_CHILDREN: int -RUSAGE_SELF: int -if sys.platform == "linux": - RLIMIT_MSGQUEUE: int - RLIMIT_NICE: int - RLIMIT_OFILE: int - RLIMIT_RTPRIO: int - RLIMIT_RTTIME: int - RLIMIT_SIGPENDING: int - RUSAGE_THREAD: int - -_Tuple16 = Tuple[float, float, int, int, int, int, int, int, int, int, int, int, int, int, int, int] - -class struct_rusage(_Tuple16): - def __new__(cls, sequence: _Tuple16, dict: dict[str, Any] = ...) -> struct_rusage: ... - ru_utime: float - ru_stime: float - ru_maxrss: int - ru_ixrss: int - ru_idrss: int - ru_isrss: int - ru_minflt: int - ru_majflt: int - ru_nswap: int - ru_inblock: int - ru_oublock: int - ru_msgsnd: int - ru_msgrcv: int - ru_nsignals: int - ru_nvcsw: int - ru_nivcsw: int - -def getpagesize() -> int: ... -def getrlimit(__resource: int) -> tuple[int, int]: ... -def getrusage(__who: int) -> struct_rusage: ... -def setrlimit(__resource: int, __limits: tuple[int, int]) -> None: ... - -if sys.platform == "linux": - @overload - def prlimit(pid: int, resource: int, limits: tuple[int, int]) -> tuple[int, int]: ... - @overload - def prlimit(pid: int, resource: int) -> tuple[int, int]: ... - -error = OSError +if sys.platform != "win32": + RLIMIT_AS: int + RLIMIT_CORE: int + RLIMIT_CPU: int + RLIMIT_DATA: int + RLIMIT_FSIZE: int + RLIMIT_MEMLOCK: int + RLIMIT_NOFILE: int + RLIMIT_NPROC: int + RLIMIT_RSS: int + RLIMIT_STACK: int + RLIM_INFINITY: int + RUSAGE_CHILDREN: int + RUSAGE_SELF: int + if sys.platform == "linux": + RLIMIT_MSGQUEUE: int + RLIMIT_NICE: int + RLIMIT_OFILE: int + RLIMIT_RTPRIO: int + RLIMIT_RTTIME: int + RLIMIT_SIGPENDING: int + RUSAGE_THREAD: int + @final + class struct_rusage( + structseq[float], tuple[float, float, int, int, int, int, int, int, int, int, int, int, int, int, int, int] + ): + @property + def ru_utime(self) -> float: ... + @property + def ru_stime(self) -> float: ... + @property + def ru_maxrss(self) -> int: ... + @property + def ru_ixrss(self) -> int: ... + @property + def ru_idrss(self) -> int: ... + @property + def ru_isrss(self) -> int: ... + @property + def ru_minflt(self) -> int: ... + @property + def ru_majflt(self) -> int: ... + @property + def ru_nswap(self) -> int: ... + @property + def ru_inblock(self) -> int: ... + @property + def ru_oublock(self) -> int: ... + @property + def ru_msgsnd(self) -> int: ... + @property + def ru_msgrcv(self) -> int: ... + @property + def ru_nsignals(self) -> int: ... + @property + def ru_nvcsw(self) -> int: ... + @property + def ru_nivcsw(self) -> int: ... + def getpagesize() -> int: ... + def getrlimit(__resource: int) -> tuple[int, int]: ... + def getrusage(__who: int) -> struct_rusage: ... + def setrlimit(__resource: int, __limits: tuple[int, int]) -> None: ... + if sys.platform == "linux": + @overload + def prlimit(pid: int, resource: int, limits: tuple[int, int]) -> tuple[int, int]: ... + @overload + def prlimit(pid: int, resource: int) -> tuple[int, int]: ... + error = OSError diff --git a/mypy/typeshed/stdlib/sched.pyi b/mypy/typeshed/stdlib/sched.pyi index cb96dc2bbf4ab..71aacc5c26103 100644 --- a/mypy/typeshed/stdlib/sched.pyi +++ b/mypy/typeshed/stdlib/sched.pyi @@ -1,10 +1,10 @@ -from typing import Any, Callable, NamedTuple, Tuple +from typing import Any, Callable, NamedTuple class Event(NamedTuple): time: float priority: Any action: Callable[..., Any] - argument: Tuple[Any, ...] + argument: tuple[Any, ...] kwargs: dict[str, Any] class scheduler: @@ -14,7 +14,7 @@ class scheduler: time: float, priority: Any, action: Callable[..., Any], - argument: Tuple[Any, ...] = ..., + argument: tuple[Any, ...] = ..., kwargs: dict[str, Any] = ..., ) -> Event: ... def enter( @@ -22,7 +22,7 @@ class scheduler: delay: float, priority: Any, action: Callable[..., Any], - argument: Tuple[Any, ...] = ..., + argument: tuple[Any, ...] = ..., kwargs: dict[str, Any] = ..., ) -> Event: ... def run(self, blocking: bool = ...) -> float | None: ... diff --git a/mypy/typeshed/stdlib/secrets.pyi b/mypy/typeshed/stdlib/secrets.pyi index 6752a30f431e6..f57eef8492d7b 100644 --- a/mypy/typeshed/stdlib/secrets.pyi +++ b/mypy/typeshed/stdlib/secrets.pyi @@ -1,12 +1,13 @@ +from _typeshed import SupportsLenAndGetItem from hmac import compare_digest as compare_digest from random import SystemRandom as SystemRandom -from typing import Sequence, TypeVar +from typing import TypeVar _T = TypeVar("_T") def randbelow(exclusive_upper_bound: int) -> int: ... def randbits(k: int) -> int: ... -def choice(seq: Sequence[_T]) -> _T: ... +def choice(seq: SupportsLenAndGetItem[_T]) -> _T: ... def token_bytes(nbytes: int | None = ...) -> bytes: ... def token_hex(nbytes: int | None = ...) -> str: ... def token_urlsafe(nbytes: int | None = ...) -> str: ... diff --git a/mypy/typeshed/stdlib/select.pyi b/mypy/typeshed/stdlib/select.pyi index 0329dbaa2c117..e57504b5b447e 100644 --- a/mypy/typeshed/stdlib/select.pyi +++ b/mypy/typeshed/stdlib/select.pyi @@ -13,6 +13,7 @@ if sys.platform != "win32": POLLOUT: int POLLPRI: int POLLRDBAND: int + POLLRDHUP: int POLLRDNORM: int POLLWRBAND: int POLLWRNORM: int @@ -32,7 +33,7 @@ error = OSError if sys.platform != "linux" and sys.platform != "win32": # BSD only - class kevent(object): + class kevent: data: Any fflags: int filter: int @@ -49,7 +50,7 @@ if sys.platform != "linux" and sys.platform != "win32": udata: Any = ..., ) -> None: ... # BSD only - class kqueue(object): + class kqueue: closed: bool def __init__(self) -> None: ... def close(self) -> None: ... @@ -99,7 +100,7 @@ if sys.platform != "linux" and sys.platform != "win32": KQ_NOTE_WRITE: int if sys.platform == "linux": - class epoll(object): + class epoll: def __init__(self, sizehint: int = ..., flags: int = ...) -> None: ... def __enter__(self: Self) -> Self: ... def __exit__( @@ -118,6 +119,7 @@ if sys.platform == "linux": @classmethod def fromfd(cls, __fd: FileDescriptorLike) -> epoll: ... EPOLLERR: int + EPOLLEXCLUSIVE: int EPOLLET: int EPOLLHUP: int EPOLLIN: int @@ -126,10 +128,12 @@ if sys.platform == "linux": EPOLLOUT: int EPOLLPRI: int EPOLLRDBAND: int + EPOLLRDHUP: int EPOLLRDNORM: int EPOLLWRBAND: int EPOLLWRNORM: int EPOLL_RDHUP: int + EPOLL_CLOEXEC: int if sys.platform != "linux" and sys.platform != "darwin" and sys.platform != "win32": # Solaris only diff --git a/mypy/typeshed/stdlib/signal.pyi b/mypy/typeshed/stdlib/signal.pyi index d617e24f227f1..777391662aa36 100644 --- a/mypy/typeshed/stdlib/signal.pyi +++ b/mypy/typeshed/stdlib/signal.pyi @@ -1,56 +1,40 @@ import sys +from _typeshed import structseq from enum import IntEnum from types import FrameType -from typing import Any, Callable, Iterable, Optional, Tuple, Union - -if sys.platform != "win32": - class ItimerError(IOError): ... - ITIMER_PROF: int - ITIMER_REAL: int - ITIMER_VIRTUAL: int +from typing import Any, Callable, Iterable, Optional, Union +from typing_extensions import final NSIG: int class Signals(IntEnum): SIGABRT: int - if sys.platform != "win32": - SIGALRM: int + SIGEMT: int + SIGFPE: int + SIGILL: int + SIGINFO: int + SIGINT: int + SIGSEGV: int + SIGTERM: int + if sys.platform == "win32": SIGBREAK: int - if sys.platform != "win32": + CTRL_C_EVENT: int + CTRL_BREAK_EVENT: int + else: + SIGALRM: int SIGBUS: int SIGCHLD: int - if sys.platform != "darwin" and sys.platform != "win32": - SIGCLD: int - if sys.platform != "win32": SIGCONT: int - SIGEMT: int - SIGFPE: int - if sys.platform != "win32": SIGHUP: int - SIGILL: int - SIGINFO: int - SIGINT: int - if sys.platform != "win32": SIGIO: int SIGIOT: int SIGKILL: int SIGPIPE: int - if sys.platform != "darwin" and sys.platform != "win32": - SIGPOLL: int - SIGPWR: int - if sys.platform != "win32": SIGPROF: int SIGQUIT: int - if sys.platform != "darwin" and sys.platform != "win32": - SIGRTMAX: int - SIGRTMIN: int - SIGSEGV: int - if sys.platform != "win32": SIGSTOP: int SIGSYS: int - SIGTERM: int - if sys.platform != "win32": SIGTRAP: int SIGTSTP: int SIGTTIN: int @@ -62,65 +46,54 @@ class Signals(IntEnum): SIGWINCH: int SIGXCPU: int SIGXFSZ: int + if sys.platform != "darwin": + SIGCLD: int + SIGPOLL: int + SIGPWR: int + SIGRTMAX: int + SIGRTMIN: int class Handlers(IntEnum): SIG_DFL: int SIG_IGN: int -SIG_DFL = Handlers.SIG_DFL -SIG_IGN = Handlers.SIG_IGN - -if sys.platform != "win32": - class Sigmasks(IntEnum): - SIG_BLOCK: int - SIG_UNBLOCK: int - SIG_SETMASK: int - SIG_BLOCK = Sigmasks.SIG_BLOCK - SIG_UNBLOCK = Sigmasks.SIG_UNBLOCK - SIG_SETMASK = Sigmasks.SIG_SETMASK +SIG_DFL: Handlers +SIG_IGN: Handlers _SIGNUM = Union[int, Signals] _HANDLER = Union[Callable[[int, Optional[FrameType]], Any], int, Handlers, None] +def default_int_handler(signum: int, frame: FrameType | None) -> None: ... +def getsignal(__signalnum: _SIGNUM) -> _HANDLER: ... +def signal(__signalnum: _SIGNUM, __handler: _HANDLER) -> _HANDLER: ... + SIGABRT: Signals -if sys.platform != "win32": - SIGALRM: Signals +SIGEMT: Signals +SIGFPE: Signals +SIGILL: Signals +SIGINFO: Signals +SIGINT: Signals +SIGSEGV: Signals +SIGTERM: Signals + if sys.platform == "win32": SIGBREAK: Signals -if sys.platform != "win32": + CTRL_C_EVENT: Signals + CTRL_BREAK_EVENT: Signals +else: + SIGALRM: Signals SIGBUS: Signals SIGCHLD: Signals -if sys.platform != "darwin" and sys.platform != "win32": - SIGCLD: Signals -if sys.platform != "win32": SIGCONT: Signals -SIGEMT: Signals -SIGFPE: Signals -if sys.platform != "win32": SIGHUP: Signals -SIGILL: Signals -SIGINFO: Signals -SIGINT: Signals -if sys.platform != "win32": SIGIO: Signals SIGIOT: Signals SIGKILL: Signals SIGPIPE: Signals -if sys.platform != "darwin" and sys.platform != "win32": - SIGPOLL: Signals - SIGPWR: Signals -if sys.platform != "win32": SIGPROF: Signals SIGQUIT: Signals -if sys.platform != "darwin" and sys.platform != "win32": - SIGRTMAX: Signals - SIGRTMIN: Signals -SIGSEGV: Signals -if sys.platform != "win32": SIGSTOP: Signals SIGSYS: Signals -SIGTERM: Signals -if sys.platform != "win32": SIGTRAP: Signals SIGTSTP: Signals SIGTTIN: Signals @@ -132,64 +105,58 @@ if sys.platform != "win32": SIGWINCH: Signals SIGXCPU: Signals SIGXFSZ: Signals - -if sys.platform == "win32": - CTRL_C_EVENT: int - CTRL_BREAK_EVENT: int - -if sys.platform != "win32" and sys.platform != "darwin": - class struct_siginfo(Tuple[int, int, int, int, int, int, int]): - def __init__(self, sequence: Iterable[int]) -> None: ... - @property - def si_signo(self) -> int: ... - @property - def si_code(self) -> int: ... - @property - def si_errno(self) -> int: ... - @property - def si_pid(self) -> int: ... - @property - def si_uid(self) -> int: ... - @property - def si_status(self) -> int: ... - @property - def si_band(self) -> int: ... - -if sys.platform != "win32": + class ItimerError(IOError): ... + ITIMER_PROF: int + ITIMER_REAL: int + ITIMER_VIRTUAL: int + class Sigmasks(IntEnum): + SIG_BLOCK: int + SIG_UNBLOCK: int + SIG_SETMASK: int + SIG_BLOCK = Sigmasks.SIG_BLOCK + SIG_UNBLOCK = Sigmasks.SIG_UNBLOCK + SIG_SETMASK = Sigmasks.SIG_SETMASK def alarm(__seconds: int) -> int: ... - -def default_int_handler(signum: int, frame: FrameType) -> None: ... - -if sys.platform != "win32": def getitimer(__which: int) -> tuple[float, float]: ... - -def getsignal(__signalnum: _SIGNUM) -> _HANDLER: ... + def pause() -> None: ... + def pthread_kill(__thread_id: int, __signalnum: int) -> None: ... + def pthread_sigmask(__how: int, __mask: Iterable[int]) -> set[_SIGNUM]: ... + def setitimer(__which: int, __seconds: float, __interval: float = ...) -> tuple[float, float]: ... + def siginterrupt(__signalnum: int, __flag: bool) -> None: ... + def sigpending() -> Any: ... + def sigwait(__sigset: Iterable[int]) -> _SIGNUM: ... + if sys.platform != "darwin": + SIGCLD: Signals + SIGPOLL: Signals + SIGPWR: Signals + SIGRTMAX: Signals + SIGRTMIN: Signals + @final + class struct_siginfo(structseq[int], tuple[int, int, int, int, int, int, int]): + @property + def si_signo(self) -> int: ... + @property + def si_code(self) -> int: ... + @property + def si_errno(self) -> int: ... + @property + def si_pid(self) -> int: ... + @property + def si_uid(self) -> int: ... + @property + def si_status(self) -> int: ... + @property + def si_band(self) -> int: ... + def sigtimedwait(sigset: Iterable[int], timeout: float) -> struct_siginfo | None: ... + def sigwaitinfo(sigset: Iterable[int]) -> struct_siginfo: ... if sys.version_info >= (3, 8): def strsignal(__signalnum: _SIGNUM) -> str | None: ... def valid_signals() -> set[Signals]: ... def raise_signal(__signalnum: _SIGNUM) -> None: ... -if sys.platform != "win32": - def pause() -> None: ... - def pthread_kill(__thread_id: int, __signalnum: int) -> None: ... - def pthread_sigmask(__how: int, __mask: Iterable[int]) -> set[_SIGNUM]: ... - if sys.version_info >= (3, 7): def set_wakeup_fd(fd: int, *, warn_on_full_buffer: bool = ...) -> int: ... else: def set_wakeup_fd(fd: int) -> int: ... - -if sys.platform != "win32": - def setitimer(__which: int, __seconds: float, __interval: float = ...) -> tuple[float, float]: ... - def siginterrupt(__signalnum: int, __flag: bool) -> None: ... - -def signal(__signalnum: _SIGNUM, __handler: _HANDLER) -> _HANDLER: ... - -if sys.platform != "win32": - def sigpending() -> Any: ... - def sigwait(__sigset: Iterable[int]) -> _SIGNUM: ... - if sys.platform != "darwin": - def sigtimedwait(sigset: Iterable[int], timeout: float) -> struct_siginfo | None: ... - def sigwaitinfo(sigset: Iterable[int]) -> struct_siginfo: ... diff --git a/mypy/typeshed/stdlib/smtpd.pyi b/mypy/typeshed/stdlib/smtpd.pyi index 2b60205248278..e5401552caaeb 100644 --- a/mypy/typeshed/stdlib/smtpd.pyi +++ b/mypy/typeshed/stdlib/smtpd.pyi @@ -2,9 +2,9 @@ import asynchat import asyncore import socket from collections import defaultdict -from typing import Any, Tuple, Type +from typing import Any, Type -_Address = Tuple[str, int] # (host, port) +_Address = tuple[str, int] # (host, port) class SMTPChannel(asynchat.async_chat): COMMAND: int @@ -40,7 +40,7 @@ class SMTPChannel(asynchat.async_chat): decode_data: bool = ..., ) -> None: ... # base asynchat.async_chat.push() accepts bytes - def push(self, msg: str) -> None: ... # type: ignore + def push(self, msg: str) -> None: ... # type: ignore[override] def collect_incoming_data(self, data: bytes) -> None: ... def found_terminator(self) -> None: ... def smtp_HELO(self, arg: str) -> None: ... @@ -77,11 +77,7 @@ class SMTPServer(asyncore.dispatcher): class DebuggingServer(SMTPServer): ... class PureProxy(SMTPServer): - def process_message( # type: ignore - self, peer: _Address, mailfrom: str, rcpttos: list[str], data: bytes | str - ) -> str | None: ... + def process_message(self, peer: _Address, mailfrom: str, rcpttos: list[str], data: bytes | str) -> str | None: ... # type: ignore[override] class MailmanProxy(PureProxy): - def process_message( # type: ignore - self, peer: _Address, mailfrom: str, rcpttos: list[str], data: bytes | str - ) -> str | None: ... + def process_message(self, peer: _Address, mailfrom: str, rcpttos: list[str], data: bytes | str) -> str | None: ... # type: ignore[override] diff --git a/mypy/typeshed/stdlib/smtplib.pyi b/mypy/typeshed/stdlib/smtplib.pyi index 5dbdf5d44c291..0a57f1f5d2de7 100644 --- a/mypy/typeshed/stdlib/smtplib.pyi +++ b/mypy/typeshed/stdlib/smtplib.pyi @@ -1,14 +1,15 @@ +import sys from _typeshed import Self from email.message import Message as _Message from socket import socket from ssl import SSLContext from types import TracebackType -from typing import Any, Dict, Pattern, Protocol, Sequence, Tuple, Type, Union, overload +from typing import Any, Pattern, Protocol, Sequence, Type, Union, overload -_Reply = Tuple[int, bytes] -_SendErrs = Dict[str, _Reply] +_Reply = tuple[int, bytes] +_SendErrs = dict[str, _Reply] # Should match source_address for socket.create_connection -_SourceAddress = Tuple[Union[bytearray, bytes, str], int] +_SourceAddress = tuple[Union[bytearray, bytes, str], int] SMTP_PORT: int SMTP_SSL_PORT: int @@ -149,6 +150,16 @@ class SMTP_SSL(SMTP): LMTP_PORT: int class LMTP(SMTP): - def __init__( - self, host: str = ..., port: int = ..., local_hostname: str | None = ..., source_address: _SourceAddress | None = ... - ) -> None: ... + if sys.version_info >= (3, 9): + def __init__( + self, + host: str = ..., + port: int = ..., + local_hostname: str | None = ..., + source_address: _SourceAddress | None = ..., + timeout: float = ..., + ) -> None: ... + else: + def __init__( + self, host: str = ..., port: int = ..., local_hostname: str | None = ..., source_address: _SourceAddress | None = ... + ) -> None: ... diff --git a/mypy/typeshed/stdlib/socket.pyi b/mypy/typeshed/stdlib/socket.pyi index 1f5ae6eb76c8e..430fef4ff3449 100644 --- a/mypy/typeshed/stdlib/socket.pyi +++ b/mypy/typeshed/stdlib/socket.pyi @@ -570,9 +570,9 @@ class socket(_socket.socket): ) -> BinaryIO: ... def sendfile(self, file: BinaryIO, offset: int = ..., count: int | None = ...) -> int: ... @property - def family(self) -> AddressFamily: ... # type: ignore + def family(self) -> AddressFamily: ... # type: ignore[override] @property - def type(self) -> SocketKind: ... # type: ignore + def type(self) -> SocketKind: ... # type: ignore[override] def get_inheritable(self) -> bool: ... def set_inheritable(self, inheritable: bool) -> None: ... @@ -593,7 +593,7 @@ if sys.platform == "win32": def socketpair(family: int = ..., type: int = ..., proto: int = ...) -> tuple[socket, socket]: ... else: - def socketpair( # type: ignore + def socketpair( family: int | AddressFamily | None = ..., type: SocketType | int = ..., proto: int = ... ) -> tuple[socket, socket]: ... diff --git a/mypy/typeshed/stdlib/socketserver.pyi b/mypy/typeshed/stdlib/socketserver.pyi index 6f5eeefb84fda..c663e73bef50f 100644 --- a/mypy/typeshed/stdlib/socketserver.pyi +++ b/mypy/typeshed/stdlib/socketserver.pyi @@ -2,11 +2,11 @@ import sys import types from _typeshed import Self from socket import socket as _socket -from typing import Any, BinaryIO, Callable, ClassVar, Tuple, Type, TypeVar, Union +from typing import Any, BinaryIO, Callable, ClassVar, Type, TypeVar, Union _T = TypeVar("_T") -_RequestType = Union[_socket, Tuple[bytes, _socket]] -_AddressType = Union[Tuple[str, int], str] +_RequestType = Union[_socket, tuple[bytes, _socket]] +_AddressType = Union[tuple[str, int], str] class BaseServer: address_family: int @@ -55,6 +55,7 @@ class TCPServer(BaseServer): def close_request(self, request: _RequestType) -> None: ... # undocumented class UDPServer(BaseServer): + max_packet_size: ClassVar[int] def __init__( self, server_address: tuple[str, int], diff --git a/mypy/typeshed/stdlib/spwd.pyi b/mypy/typeshed/stdlib/spwd.pyi index 0f8d36fee945e..7a62d62523f52 100644 --- a/mypy/typeshed/stdlib/spwd.pyi +++ b/mypy/typeshed/stdlib/spwd.pyi @@ -1,15 +1,28 @@ -from typing import NamedTuple +import sys +from _typeshed import structseq +from typing import Any +from typing_extensions import final -class struct_spwd(NamedTuple): - sp_namp: str - sp_pwdp: str - sp_lstchg: int - sp_min: int - sp_max: int - sp_warn: int - sp_inact: int - sp_expire: int - sp_flag: int - -def getspall() -> list[struct_spwd]: ... -def getspnam(__arg: str) -> struct_spwd: ... +if sys.platform != "win32": + @final + class struct_spwd(structseq[Any], tuple[str, str, int, int, int, int, int, int, int]): + @property + def sp_namp(self) -> str: ... + @property + def sp_pwdp(self) -> str: ... + @property + def sp_lstchg(self) -> int: ... + @property + def sp_min(self) -> int: ... + @property + def sp_max(self) -> int: ... + @property + def sp_warn(self) -> int: ... + @property + def sp_inact(self) -> int: ... + @property + def sp_expire(self) -> int: ... + @property + def sp_flag(self) -> int: ... + def getspall() -> list[struct_spwd]: ... + def getspnam(__arg: str) -> struct_spwd: ... diff --git a/mypy/typeshed/stdlib/sqlite3/dbapi2.pyi b/mypy/typeshed/stdlib/sqlite3/dbapi2.pyi index e2e45d538da9d..ea9098940d4b2 100644 --- a/mypy/typeshed/stdlib/sqlite3/dbapi2.pyi +++ b/mypy/typeshed/stdlib/sqlite3/dbapi2.pyi @@ -40,6 +40,8 @@ if sys.version_info >= (3, 7): SQLITE_DELETE: int SQLITE_DENY: int SQLITE_DETACH: int +if sys.version_info >= (3, 7): + SQLITE_DONE: int SQLITE_DROP_INDEX: int SQLITE_DROP_TABLE: int SQLITE_DROP_TEMP_INDEX: int @@ -83,7 +85,7 @@ version: str # TODO: adapt needs to get probed def adapt(obj, protocol, alternate): ... -def complete_statement(sql: str) -> bool: ... +def complete_statement(statement: str) -> bool: ... if sys.version_info >= (3, 7): def connect( @@ -115,7 +117,7 @@ def register_adapter(__type: Type[_T], __caster: Callable[[_T], int | float | st def register_converter(__name: str, __converter: Callable[[bytes], Any]) -> None: ... if sys.version_info < (3, 8): - class Cache(object): + class Cache: def __init__(self, *args, **kwargs) -> None: ... def display(self, *args, **kwargs) -> None: ... def get(self, *args, **kwargs) -> None: ... @@ -124,7 +126,7 @@ class _AggregateProtocol(Protocol): def step(self, value: int) -> None: ... def finalize(self) -> int: ... -class Connection(object): +class Connection: DataError: Any DatabaseError: Any Error: Any @@ -154,16 +156,14 @@ class Connection(object): # TODO: please check in executemany() if seq_of_parameters type is possible like this def executemany(self, __sql: str, __parameters: Iterable[Iterable[Any]]) -> Cursor: ... def executescript(self, __sql_script: bytes | str) -> Cursor: ... - def interrupt(self, *args: Any, **kwargs: Any) -> None: ... - def iterdump(self, *args: Any, **kwargs: Any) -> Generator[str, None, None]: ... - def rollback(self, *args: Any, **kwargs: Any) -> None: ... - # TODO: set_authorizer(authorzer_callback) - # see https://docs.python.org/2/library/sqlite3.html#sqlite3.Connection.set_authorizer - # returns [SQLITE_OK, SQLITE_DENY, SQLITE_IGNORE] so perhaps int - def set_authorizer(self, *args: Any, **kwargs: Any) -> None: ... - # set_progress_handler(handler, n) -> see https://docs.python.org/2/library/sqlite3.html#sqlite3.Connection.set_progress_handler - def set_progress_handler(self, *args: Any, **kwargs: Any) -> None: ... - def set_trace_callback(self, *args: Any, **kwargs: Any) -> None: ... + def interrupt(self) -> None: ... + def iterdump(self) -> Generator[str, None, None]: ... + def rollback(self) -> None: ... + def set_authorizer( + self, authorizer_callback: Callable[[int, str | None, str | None, str | None, str | None], int] | None + ) -> None: ... + def set_progress_handler(self, progress_handler: Callable[[], bool | None] | None, n: int) -> None: ... + def set_trace_callback(self, trace_callback: Callable[[str], object] | None) -> None: ... # enable_load_extension and load_extension is not available on python distributions compiled # without sqlite3 loadable extension support. see footnotes https://docs.python.org/3/library/sqlite3.html#f1 def enable_load_extension(self, enabled: bool) -> None: ... @@ -193,21 +193,26 @@ class Cursor(Iterator[Any]): # required type is sqlite3.Connection (which is imported as _Connection) # however, the name of the __init__ variable is unknown def __init__(self, *args: Any, **kwargs: Any) -> None: ... - def close(self, *args: Any, **kwargs: Any) -> None: ... + def close(self) -> None: ... def execute(self, __sql: str, __parameters: Iterable[Any] = ...) -> Cursor: ... def executemany(self, __sql: str, __seq_of_parameters: Iterable[Iterable[Any]]) -> Cursor: ... def executescript(self, __sql_script: bytes | str) -> Cursor: ... def fetchall(self) -> list[Any]: ... def fetchmany(self, size: int | None = ...) -> list[Any]: ... def fetchone(self) -> Any: ... - def setinputsizes(self, *args: Any, **kwargs: Any) -> None: ... - def setoutputsize(self, *args: Any, **kwargs: Any) -> None: ... + def setinputsizes(self, __sizes: object) -> None: ... # does nothing + def setoutputsize(self, __size: object, __column: object = ...) -> None: ... # does nothing def __iter__(self) -> Cursor: ... def __next__(self) -> Any: ... class DataError(DatabaseError): ... class DatabaseError(Error): ... -class Error(Exception): ... + +class Error(Exception): + if sys.version_info >= (3, 11): + sqlite_errorcode: int + sqlite_errorname: str + class IntegrityError(DatabaseError): ... class InterfaceError(Error): ... class InternalError(DatabaseError): ... @@ -216,14 +221,14 @@ class OperationalError(DatabaseError): ... OptimizedUnicode = str -class PrepareProtocol(object): +class PrepareProtocol: def __init__(self, *args: Any, **kwargs: Any) -> None: ... class ProgrammingError(DatabaseError): ... -class Row(object): +class Row: def __init__(self, *args: Any, **kwargs: Any) -> None: ... - def keys(self, *args: Any, **kwargs: Any): ... + def keys(self): ... def __eq__(self, other): ... def __ge__(self, other): ... def __getitem__(self, index): ... @@ -236,7 +241,7 @@ class Row(object): def __ne__(self, other): ... if sys.version_info < (3, 8): - class Statement(object): + class Statement: def __init__(self, *args, **kwargs): ... class Warning(Exception): ... diff --git a/mypy/typeshed/stdlib/sre_compile.pyi b/mypy/typeshed/stdlib/sre_compile.pyi index aac8c0242764a..98a9f4dad008a 100644 --- a/mypy/typeshed/stdlib/sre_compile.pyi +++ b/mypy/typeshed/stdlib/sre_compile.pyi @@ -1,18 +1,5 @@ -from sre_constants import ( - SRE_FLAG_ASCII as SRE_FLAG_ASCII, - SRE_FLAG_DEBUG as SRE_FLAG_DEBUG, - SRE_FLAG_DOTALL as SRE_FLAG_DOTALL, - SRE_FLAG_IGNORECASE as SRE_FLAG_IGNORECASE, - SRE_FLAG_LOCALE as SRE_FLAG_LOCALE, - SRE_FLAG_MULTILINE as SRE_FLAG_MULTILINE, - SRE_FLAG_TEMPLATE as SRE_FLAG_TEMPLATE, - SRE_FLAG_UNICODE as SRE_FLAG_UNICODE, - SRE_FLAG_VERBOSE as SRE_FLAG_VERBOSE, - SRE_INFO_CHARSET as SRE_INFO_CHARSET, - SRE_INFO_LITERAL as SRE_INFO_LITERAL, - SRE_INFO_PREFIX as SRE_INFO_PREFIX, - _NamedIntConstant, -) +from sre_constants import * +from sre_constants import _NamedIntConstant from sre_parse import SubPattern from typing import Any, Pattern diff --git a/mypy/typeshed/stdlib/sre_constants.pyi b/mypy/typeshed/stdlib/sre_constants.pyi index 4658d0e4b1750..df7e1a28007b8 100644 --- a/mypy/typeshed/stdlib/sre_constants.pyi +++ b/mypy/typeshed/stdlib/sre_constants.pyi @@ -1,6 +1,8 @@ import sys from typing import Any +MAXGROUPS: int + MAGIC: int class error(Exception): @@ -20,6 +22,9 @@ OPCODES: list[_NamedIntConstant] ATCODES: list[_NamedIntConstant] CHCODES: list[_NamedIntConstant] OP_IGNORE: dict[_NamedIntConstant, _NamedIntConstant] +if sys.version_info >= (3, 7): + OP_LOCALE_IGNORE: dict[_NamedIntConstant, _NamedIntConstant] + OP_UNICODE_IGNORE: dict[_NamedIntConstant, _NamedIntConstant] AT_MULTILINE: dict[_NamedIntConstant, _NamedIntConstant] AT_LOCALE: dict[_NamedIntConstant, _NamedIntConstant] AT_UNICODE: dict[_NamedIntConstant, _NamedIntConstant] @@ -75,6 +80,14 @@ SUBPATTERN: _NamedIntConstant MIN_REPEAT_ONE: _NamedIntConstant if sys.version_info >= (3, 7): RANGE_UNI_IGNORE: _NamedIntConstant + GROUPREF_LOC_IGNORE: _NamedIntConstant + GROUPREF_UNI_IGNORE: _NamedIntConstant + IN_LOC_IGNORE: _NamedIntConstant + IN_UNI_IGNORE: _NamedIntConstant + LITERAL_LOC_IGNORE: _NamedIntConstant + LITERAL_UNI_IGNORE: _NamedIntConstant + NOT_LITERAL_LOC_IGNORE: _NamedIntConstant + NOT_LITERAL_UNI_IGNORE: _NamedIntConstant else: RANGE_IGNORE: _NamedIntConstant MIN_REPEAT: _NamedIntConstant diff --git a/mypy/typeshed/stdlib/sre_parse.pyi b/mypy/typeshed/stdlib/sre_parse.pyi index 2d00bedc2c817..c4de55bcbf7ec 100644 --- a/mypy/typeshed/stdlib/sre_parse.pyi +++ b/mypy/typeshed/stdlib/sre_parse.pyi @@ -1,6 +1,7 @@ import sys +from sre_constants import * from sre_constants import _NamedIntConstant as _NIC, error as _Error -from typing import Any, Iterable, List, Match, Optional, Pattern as _Pattern, Tuple, Union, overload +from typing import Any, Iterable, Match, Optional, Pattern as _Pattern, Union, overload SPECIAL_CHARS: str REPEAT_CHARS: str @@ -12,6 +13,8 @@ WHITESPACE: frozenset[str] ESCAPES: dict[str, tuple[_NIC, int]] CATEGORIES: dict[str, tuple[_NIC, _NIC] | tuple[_NIC, list[tuple[_NIC, _NIC]]]] FLAGS: dict[str, int] +if sys.version_info >= (3, 7): + TYPE_FLAGS: int GLOBAL_FLAGS: int class Verbose(Exception): ... @@ -24,7 +27,7 @@ class _State: def __init__(self) -> None: ... @property def groups(self) -> int: ... - def opengroup(self, name: str = ...) -> int: ... + def opengroup(self, name: str | None = ...) -> int: ... def closegroup(self, gid: int, p: SubPattern) -> None: ... def checkgroup(self, gid: int) -> bool: ... def checklookbehindgroup(self, gid: int, source: Tokenizer) -> None: ... @@ -34,12 +37,12 @@ if sys.version_info >= (3, 8): else: Pattern = _State -_OpSubpatternType = Tuple[Optional[int], int, int, SubPattern] -_OpGroupRefExistsType = Tuple[int, SubPattern, SubPattern] -_OpInType = List[Tuple[_NIC, int]] -_OpBranchType = Tuple[None, List[SubPattern]] +_OpSubpatternType = tuple[Optional[int], int, int, SubPattern] +_OpGroupRefExistsType = tuple[int, SubPattern, SubPattern] +_OpInType = list[tuple[_NIC, int]] +_OpBranchType = tuple[None, list[SubPattern]] _AvType = Union[_OpInType, _OpBranchType, Iterable[SubPattern], _OpGroupRefExistsType, _OpSubpatternType] -_CodeType = Tuple[_NIC, _AvType] +_CodeType = tuple[_NIC, _AvType] class SubPattern: data: list[_CodeType] @@ -82,8 +85,8 @@ class Tokenizer: def fix_flags(src: str | bytes, flags: int) -> int: ... -_TemplateType = Tuple[List[Tuple[int, int]], List[Optional[str]]] -_TemplateByteType = Tuple[List[Tuple[int, int]], List[Optional[bytes]]] +_TemplateType = tuple[list[tuple[int, int]], list[Optional[str]]] +_TemplateByteType = tuple[list[tuple[int, int]], list[Optional[bytes]]] if sys.version_info >= (3, 8): def parse(str: str, flags: int = ..., state: State | None = ...) -> SubPattern: ... @overload diff --git a/mypy/typeshed/stdlib/ssl.pyi b/mypy/typeshed/stdlib/ssl.pyi index 689b083d764cf..cdb727285647b 100644 --- a/mypy/typeshed/stdlib/ssl.pyi +++ b/mypy/typeshed/stdlib/ssl.pyi @@ -2,14 +2,14 @@ import enum import socket import sys from _typeshed import ReadableBuffer, Self, StrOrBytesPath, WriteableBuffer -from typing import Any, Callable, ClassVar, Dict, Iterable, List, NamedTuple, Optional, Set, Tuple, Type, Union, overload +from typing import Any, Callable, ClassVar, Iterable, NamedTuple, Optional, Type, Union, overload from typing_extensions import Literal, TypedDict -_PCTRTT = Tuple[Tuple[str, str], ...] -_PCTRTTT = Tuple[_PCTRTT, ...] -_PeerCertRetDictType = Dict[str, Union[str, _PCTRTTT, _PCTRTT]] +_PCTRTT = tuple[tuple[str, str], ...] +_PCTRTTT = tuple[_PCTRTT, ...] +_PeerCertRetDictType = dict[str, Union[str, _PCTRTTT, _PCTRTT]] _PeerCertRetType = Union[_PeerCertRetDictType, bytes, None] -_EnumRetType = List[Tuple[bytes, str, Union[Set[str], bool]]] +_EnumRetType = list[tuple[bytes, str, Union[set[str], bool]]] _PasswordType = Union[Callable[[], Union[str, bytes]], str, bytes] _SrvnmeCbType = Callable[[Union[SSLSocket, SSLObject], Optional[str], SSLSocket], Optional[int]] @@ -102,7 +102,15 @@ def RAND_egd(path: str) -> None: ... def RAND_add(__s: bytes, __entropy: float) -> None: ... def match_hostname(cert: _PeerCertRetType, hostname: str) -> None: ... def cert_time_to_seconds(cert_time: str) -> int: ... -def get_server_certificate(addr: tuple[str, int], ssl_version: int = ..., ca_certs: str | None = ...) -> str: ... + +if sys.version_info >= (3, 10): + def get_server_certificate( + addr: tuple[str, int], ssl_version: int = ..., ca_certs: str | None = ..., timeout: float = ... + ) -> str: ... + +else: + def get_server_certificate(addr: tuple[str, int], ssl_version: int = ..., ca_certs: str | None = ...) -> str: ... + def DER_cert_to_PEM_cert(der_cert_bytes: bytes) -> str: ... def PEM_cert_to_DER_cert(pem_cert_string: str) -> bytes: ... @@ -135,6 +143,9 @@ class VerifyFlags(enum.IntFlag): VERIFY_CRL_CHECK_CHAIN: int VERIFY_X509_STRICT: int VERIFY_X509_TRUSTED_FIRST: int + if sys.version_info >= (3, 10): + VERIFY_ALLOW_PROXY_CERTS: int + VERIFY_X509_PARTIAL_CHAIN: int VERIFY_DEFAULT: VerifyFlags VERIFY_CRL_CHECK_LEAF: VerifyFlags @@ -142,6 +153,10 @@ VERIFY_CRL_CHECK_CHAIN: VerifyFlags VERIFY_X509_STRICT: VerifyFlags VERIFY_X509_TRUSTED_FIRST: VerifyFlags +if sys.version_info >= (3, 10): + VERIFY_ALLOW_PROXY_CERTS: VerifyFlags + VERIFY_X509_PARTIAL_CHAIN: VerifyFlags + class _SSLMethod(enum.IntEnum): PROTOCOL_SSLv23: int PROTOCOL_SSLv2: int @@ -205,7 +220,7 @@ if sys.version_info >= (3, 7): HAS_TLSv1: bool HAS_TLSv1_1: bool HAS_TLSv1_2: bool - HAS_TLSv1_3: bool +HAS_TLSv1_3: bool HAS_ALPN: bool HAS_ECDH: bool HAS_SNI: bool @@ -293,7 +308,9 @@ class SSLSocket(socket.socket): server_hostname: str | None session: SSLSession | None session_reused: bool | None - if sys.version_info < (3, 7): + if sys.version_info >= (3, 7): + def __init__(self, *args: Any, **kwargs: Any) -> None: ... + else: def __init__( self, sock: socket.socket | None = ..., @@ -315,8 +332,6 @@ class SSLSocket(socket.socket): _context: SSLContext | None = ..., _session: Any | None = ..., ) -> None: ... - else: - def __init__(self, *args: Any, **kwargs: Any) -> None: ... def connect(self, addr: socket._Address | bytes) -> None: ... def connect_ex(self, addr: socket._Address | bytes) -> int: ... def recv(self, buflen: int = ..., flags: int = ...) -> bytes: ... diff --git a/mypy/typeshed/stdlib/stat.pyi b/mypy/typeshed/stdlib/stat.pyi index d6450fe77817a..4518acb5a1621 100644 --- a/mypy/typeshed/stdlib/stat.pyi +++ b/mypy/typeshed/stdlib/stat.pyi @@ -1,97 +1 @@ -import sys - -def S_ISDIR(mode: int) -> bool: ... -def S_ISCHR(mode: int) -> bool: ... -def S_ISBLK(mode: int) -> bool: ... -def S_ISREG(mode: int) -> bool: ... -def S_ISFIFO(mode: int) -> bool: ... -def S_ISLNK(mode: int) -> bool: ... -def S_ISSOCK(mode: int) -> bool: ... -def S_IMODE(mode: int) -> int: ... -def S_IFMT(mode: int) -> int: ... -def S_ISDOOR(mode: int) -> int: ... -def S_ISPORT(mode: int) -> int: ... -def S_ISWHT(mode: int) -> int: ... -def filemode(mode: int) -> str: ... - -ST_MODE: int -ST_INO: int -ST_DEV: int -ST_NLINK: int -ST_UID: int -ST_GID: int -ST_SIZE: int -ST_ATIME: int -ST_MTIME: int -ST_CTIME: int - -S_IFSOCK: int -S_IFLNK: int -S_IFREG: int -S_IFBLK: int -S_IFDIR: int -S_IFCHR: int -S_IFIFO: int -S_IFDOOR: int -S_IFPORT: int -S_IFWHT: int -S_ISUID: int -S_ISGID: int -S_ISVTX: int - -S_IRWXU: int -S_IRUSR: int -S_IWUSR: int -S_IXUSR: int - -S_IRWXG: int -S_IRGRP: int -S_IWGRP: int -S_IXGRP: int - -S_IRWXO: int -S_IROTH: int -S_IWOTH: int -S_IXOTH: int - -S_ENFMT: int -S_IREAD: int -S_IWRITE: int -S_IEXEC: int - -UF_NODUMP: int -UF_IMMUTABLE: int -UF_APPEND: int -UF_OPAQUE: int -UF_NOUNLINK: int -if sys.platform == "darwin": - UF_COMPRESSED: int # OS X 10.6+ only - UF_HIDDEN: int # OX X 10.5+ only -SF_ARCHIVED: int -SF_IMMUTABLE: int -SF_APPEND: int -SF_NOUNLINK: int -SF_SNAPSHOT: int - -FILE_ATTRIBUTE_ARCHIVE: int -FILE_ATTRIBUTE_COMPRESSED: int -FILE_ATTRIBUTE_DEVICE: int -FILE_ATTRIBUTE_DIRECTORY: int -FILE_ATTRIBUTE_ENCRYPTED: int -FILE_ATTRIBUTE_HIDDEN: int -FILE_ATTRIBUTE_INTEGRITY_STREAM: int -FILE_ATTRIBUTE_NORMAL: int -FILE_ATTRIBUTE_NOT_CONTENT_INDEXED: int -FILE_ATTRIBUTE_NO_SCRUB_DATA: int -FILE_ATTRIBUTE_OFFLINE: int -FILE_ATTRIBUTE_READONLY: int -FILE_ATTRIBUTE_REPARSE_POINT: int -FILE_ATTRIBUTE_SPARSE_FILE: int -FILE_ATTRIBUTE_SYSTEM: int -FILE_ATTRIBUTE_TEMPORARY: int -FILE_ATTRIBUTE_VIRTUAL: int - -if sys.platform == "win32" and sys.version_info >= (3, 8): - IO_REPARSE_TAG_SYMLINK: int - IO_REPARSE_TAG_MOUNT_POINT: int - IO_REPARSE_TAG_APPEXECLINK: int +from _stat import * diff --git a/mypy/typeshed/stdlib/statistics.pyi b/mypy/typeshed/stdlib/statistics.pyi index ec3574ab12b1b..908d6adaf45df 100644 --- a/mypy/typeshed/stdlib/statistics.pyi +++ b/mypy/typeshed/stdlib/statistics.pyi @@ -1,5 +1,5 @@ import sys -from _typeshed import SupportsLessThanT +from _typeshed import SupportsRichComparisonT from decimal import Decimal from fractions import Fraction from typing import Any, Hashable, Iterable, NamedTuple, Sequence, SupportsFloat, Type, TypeVar, Union @@ -27,8 +27,8 @@ else: def harmonic_mean(data: Iterable[_NumberT]) -> _NumberT: ... def median(data: Iterable[_NumberT]) -> _NumberT: ... -def median_low(data: Iterable[SupportsLessThanT]) -> SupportsLessThanT: ... -def median_high(data: Iterable[SupportsLessThanT]) -> SupportsLessThanT: ... +def median_low(data: Iterable[SupportsRichComparisonT]) -> SupportsRichComparisonT: ... +def median_high(data: Iterable[SupportsRichComparisonT]) -> SupportsRichComparisonT: ... def median_grouped(data: Iterable[_NumberT], interval: _NumberT = ...) -> _NumberT: ... def mode(data: Iterable[_HashableT]) -> _HashableT: ... diff --git a/mypy/typeshed/stdlib/stringprep.pyi b/mypy/typeshed/stdlib/stringprep.pyi index cbc562d460f66..fc28c027ca9b1 100644 --- a/mypy/typeshed/stdlib/stringprep.pyi +++ b/mypy/typeshed/stdlib/stringprep.pyi @@ -1,3 +1,11 @@ +b1_set: set[int] +b3_exceptions: dict[int, str] +c22_specials: set[int] +c6_set: set[int] +c7_set: set[int] +c8_set: set[int] +c9_set: set[int] + def in_table_a1(code: str) -> bool: ... def in_table_b1(code: str) -> bool: ... def map_table_b3(code: str) -> str: ... diff --git a/mypy/typeshed/stdlib/struct.pyi b/mypy/typeshed/stdlib/struct.pyi index d7c9cbef7dce9..47af629732593 100644 --- a/mypy/typeshed/stdlib/struct.pyi +++ b/mypy/typeshed/stdlib/struct.pyi @@ -1,14 +1,14 @@ import sys from _typeshed import ReadableBuffer, WriteableBuffer -from typing import Any, Iterator, Tuple +from typing import Any, Iterator class error(Exception): ... def pack(fmt: str | bytes, *v: Any) -> bytes: ... def pack_into(fmt: str | bytes, buffer: WriteableBuffer, offset: int, *v: Any) -> None: ... -def unpack(__format: str | bytes, __buffer: ReadableBuffer) -> Tuple[Any, ...]: ... -def unpack_from(__format: str | bytes, buffer: ReadableBuffer, offset: int = ...) -> Tuple[Any, ...]: ... -def iter_unpack(__format: str | bytes, __buffer: ReadableBuffer) -> Iterator[Tuple[Any, ...]]: ... +def unpack(__format: str | bytes, __buffer: ReadableBuffer) -> tuple[Any, ...]: ... +def unpack_from(__format: str | bytes, buffer: ReadableBuffer, offset: int = ...) -> tuple[Any, ...]: ... +def iter_unpack(__format: str | bytes, __buffer: ReadableBuffer) -> Iterator[tuple[Any, ...]]: ... def calcsize(__format: str | bytes) -> int: ... class Struct: @@ -20,6 +20,6 @@ class Struct: def __init__(self, format: str | bytes) -> None: ... def pack(self, *v: Any) -> bytes: ... def pack_into(self, buffer: WriteableBuffer, offset: int, *v: Any) -> None: ... - def unpack(self, __buffer: ReadableBuffer) -> Tuple[Any, ...]: ... - def unpack_from(self, buffer: ReadableBuffer, offset: int = ...) -> Tuple[Any, ...]: ... - def iter_unpack(self, __buffer: ReadableBuffer) -> Iterator[Tuple[Any, ...]]: ... + def unpack(self, __buffer: ReadableBuffer) -> tuple[Any, ...]: ... + def unpack_from(self, buffer: ReadableBuffer, offset: int = ...) -> tuple[Any, ...]: ... + def iter_unpack(self, __buffer: ReadableBuffer) -> Iterator[tuple[Any, ...]]: ... diff --git a/mypy/typeshed/stdlib/symbol.pyi b/mypy/typeshed/stdlib/symbol.pyi index 2d3bd83087c7c..234c814b55b5a 100644 --- a/mypy/typeshed/stdlib/symbol.pyi +++ b/mypy/typeshed/stdlib/symbol.pyi @@ -1,3 +1,5 @@ +import sys + single_input: int file_input: int eval_input: int @@ -84,5 +86,13 @@ comp_if: int encoding_decl: int yield_expr: int yield_arg: int +if sys.version_info >= (3, 7): + sync_comp_for: int +if sys.version_info >= (3, 8): + func_body_suite: int + func_type: int + func_type_input: int + namedexpr_test: int + typelist: int sym_name: dict[int, str] diff --git a/mypy/typeshed/stdlib/symtable.pyi b/mypy/typeshed/stdlib/symtable.pyi index 613ac90ef7a96..bc25a4c4639b1 100644 --- a/mypy/typeshed/stdlib/symtable.pyi +++ b/mypy/typeshed/stdlib/symtable.pyi @@ -1,9 +1,9 @@ import sys -from typing import Any, Sequence, Tuple +from typing import Any, Sequence def symtable(code: str, filename: str, compile_type: str) -> SymbolTable: ... -class SymbolTable(object): +class SymbolTable: def __init__(self, raw_table: Any, filename: str) -> None: ... def get_type(self) -> str: ... def get_id(self) -> int: ... @@ -19,19 +19,22 @@ class SymbolTable(object): def get_children(self) -> list[SymbolTable]: ... class Function(SymbolTable): - def get_parameters(self) -> Tuple[str, ...]: ... - def get_locals(self) -> Tuple[str, ...]: ... - def get_globals(self) -> Tuple[str, ...]: ... - def get_frees(self) -> Tuple[str, ...]: ... + def get_parameters(self) -> tuple[str, ...]: ... + def get_locals(self) -> tuple[str, ...]: ... + def get_globals(self) -> tuple[str, ...]: ... + def get_frees(self) -> tuple[str, ...]: ... + if sys.version_info >= (3, 8): + def get_nonlocals(self) -> tuple[str, ...]: ... class Class(SymbolTable): - def get_methods(self) -> Tuple[str, ...]: ... + def get_methods(self) -> tuple[str, ...]: ... -class Symbol(object): +class Symbol: if sys.version_info >= (3, 8): def __init__( self, name: str, flags: int, namespaces: Sequence[SymbolTable] | None = ..., *, module_scope: bool = ... ) -> None: ... + def is_nonlocal(self) -> bool: ... else: def __init__(self, name: str, flags: int, namespaces: Sequence[SymbolTable] | None = ...) -> None: ... def get_name(self) -> str: ... @@ -48,7 +51,7 @@ class Symbol(object): def get_namespaces(self) -> Sequence[SymbolTable]: ... def get_namespace(self) -> SymbolTable: ... -class SymbolTableFactory(object): +class SymbolTableFactory: def __init__(self) -> None: ... def new(self, table: Any, filename: str) -> SymbolTable: ... def __call__(self, table: Any, filename: str) -> SymbolTable: ... diff --git a/mypy/typeshed/stdlib/sys.pyi b/mypy/typeshed/stdlib/sys.pyi index 274e4b90fd6ef..cb1545711d69b 100644 --- a/mypy/typeshed/stdlib/sys.pyi +++ b/mypy/typeshed/stdlib/sys.pyi @@ -1,31 +1,18 @@ import sys +from _typeshed import structseq from builtins import object as _object from importlib.abc import PathEntryFinder from importlib.machinery import ModuleSpec from io import TextIOWrapper from types import FrameType, ModuleType, TracebackType -from typing import ( - Any, - AsyncGenerator, - Callable, - NoReturn, - Optional, - Protocol, - Sequence, - TextIO, - Tuple, - Type, - TypeVar, - Union, - overload, -) -from typing_extensions import Literal +from typing import Any, AsyncGenerator, Callable, NoReturn, Optional, Protocol, Sequence, TextIO, Type, TypeVar, Union, overload +from typing_extensions import Literal, final _T = TypeVar("_T") # The following type alias are stub-only and do not exist during runtime -_ExcInfo = Tuple[Type[BaseException], BaseException, TracebackType] -_OptExcInfo = Union[_ExcInfo, Tuple[None, None, None]] +_ExcInfo = tuple[Type[BaseException], BaseException, TracebackType] +_OptExcInfo = Union[_ExcInfo, tuple[None, None, None]] # Intentionally omits one deprecated and one optional method of `importlib.abc.MetaPathFinder` class _MetaPathFinder(Protocol): @@ -146,12 +133,18 @@ class _int_info: bits_per_digit: int sizeof_digit: int -class _version_info(Tuple[int, int, int, str, int]): - major: int - minor: int - micro: int - releaselevel: str - serial: int +@final +class _version_info(structseq[Any | int], tuple[int, int, int, str, int]): + @property + def major(self) -> int: ... + @property + def minor(self) -> int: ... + @property + def micro(self) -> int: ... + @property + def releaselevel(self) -> str: ... + @property + def serial(self) -> int: ... version_info: _version_info @@ -161,7 +154,7 @@ def _current_frames() -> dict[int, FrameType]: ... def _getframe(__depth: int = ...) -> FrameType: ... def _debugmallocstats() -> None: ... def __displayhook__(value: object) -> None: ... -def __excepthook__(type_: Type[BaseException], value: BaseException, traceback: TracebackType) -> None: ... +def __excepthook__(type_: Type[BaseException], value: BaseException, traceback: TracebackType | None) -> None: ... def exc_info() -> _OptExcInfo: ... # sys.exit() accepts an optional argument of anything printable @@ -192,7 +185,7 @@ _TraceFunc = Callable[[FrameType, str, Any], Optional[Callable[[FrameType, str, def gettrace() -> _TraceFunc | None: ... def settrace(tracefunc: _TraceFunc | None) -> None: ... -class _WinVersion(Tuple[int, int, int, int, str, int, int, int, int, Tuple[int, int, int]]): +class _WinVersion(tuple[int, int, int, int, str, int, int, int, int, tuple[int, int, int]]): major: int minor: int build: int @@ -234,12 +227,12 @@ if sys.version_info >= (3, 8): err_msg: str | None object: _object | None unraisablehook: Callable[[UnraisableHookArgs], Any] - def addaudithook(hook: Callable[[str, Tuple[Any, ...]], Any]) -> None: ... + def addaudithook(hook: Callable[[str, tuple[Any, ...]], Any]) -> None: ... def audit(__event: str, *args: Any) -> None: ... _AsyncgenHook = Optional[Callable[[AsyncGenerator[Any, Any]], None]] -class _asyncgen_hooks(Tuple[_AsyncgenHook, _AsyncgenHook]): +class _asyncgen_hooks(tuple[_AsyncgenHook, _AsyncgenHook]): firstiter: _AsyncgenHook finalizer: _AsyncgenHook diff --git a/mypy/typeshed/stdlib/sysconfig.pyi b/mypy/typeshed/stdlib/sysconfig.pyi index ff828d5199125..17077144f6e98 100644 --- a/mypy/typeshed/stdlib/sysconfig.pyi +++ b/mypy/typeshed/stdlib/sysconfig.pyi @@ -1,12 +1,12 @@ -from typing import IO, Any, Tuple, overload +from typing import IO, Any, overload def get_config_var(name: str) -> str | None: ... @overload def get_config_vars() -> dict[str, Any]: ... @overload def get_config_vars(arg: str, *args: str) -> list[Any]: ... -def get_scheme_names() -> Tuple[str, ...]: ... -def get_path_names() -> Tuple[str, ...]: ... +def get_scheme_names() -> tuple[str, ...]: ... +def get_path_names() -> tuple[str, ...]: ... def get_path(name: str, scheme: str = ..., vars: dict[str, Any] | None = ..., expand: bool = ...) -> str: ... def get_paths(scheme: str = ..., vars: dict[str, Any] | None = ..., expand: bool = ...) -> dict[str, str]: ... def get_python_version() -> str: ... diff --git a/mypy/typeshed/stdlib/syslog.pyi b/mypy/typeshed/stdlib/syslog.pyi index 49169f40db5c4..cfa8df887c1b4 100644 --- a/mypy/typeshed/stdlib/syslog.pyi +++ b/mypy/typeshed/stdlib/syslog.pyi @@ -1,43 +1,47 @@ +import sys from typing import overload +from typing_extensions import Literal -LOG_ALERT: int -LOG_AUTH: int -LOG_CONS: int -LOG_CRIT: int -LOG_CRON: int -LOG_DAEMON: int -LOG_DEBUG: int -LOG_EMERG: int -LOG_ERR: int -LOG_INFO: int -LOG_KERN: int -LOG_LOCAL0: int -LOG_LOCAL1: int -LOG_LOCAL2: int -LOG_LOCAL3: int -LOG_LOCAL4: int -LOG_LOCAL5: int -LOG_LOCAL6: int -LOG_LOCAL7: int -LOG_LPR: int -LOG_MAIL: int -LOG_NDELAY: int -LOG_NEWS: int -LOG_NOTICE: int -LOG_NOWAIT: int -LOG_PERROR: int -LOG_PID: int -LOG_SYSLOG: int -LOG_USER: int -LOG_UUCP: int -LOG_WARNING: int - -def LOG_MASK(a: int) -> int: ... -def LOG_UPTO(a: int) -> int: ... -def closelog() -> None: ... -def openlog(ident: str = ..., logoption: int = ..., facility: int = ...) -> None: ... -def setlogmask(x: int) -> int: ... -@overload -def syslog(priority: int, message: str) -> None: ... -@overload -def syslog(message: str) -> None: ... +if sys.platform != "win32": + LOG_ALERT: Literal[1] + LOG_AUTH: Literal[32] + LOG_AUTHPRIV: Literal[80] + LOG_CONS: Literal[2] + LOG_CRIT: Literal[2] + LOG_CRON: Literal[72] + LOG_DAEMON: Literal[24] + LOG_DEBUG: Literal[7] + LOG_EMERG: Literal[0] + LOG_ERR: Literal[3] + LOG_INFO: Literal[6] + LOG_KERN: Literal[0] + LOG_LOCAL0: Literal[128] + LOG_LOCAL1: Literal[136] + LOG_LOCAL2: Literal[144] + LOG_LOCAL3: Literal[152] + LOG_LOCAL4: Literal[160] + LOG_LOCAL5: Literal[168] + LOG_LOCAL6: Literal[176] + LOG_LOCAL7: Literal[184] + LOG_LPR: Literal[48] + LOG_MAIL: Literal[16] + LOG_NDELAY: Literal[8] + LOG_NEWS: Literal[56] + LOG_NOTICE: Literal[5] + LOG_NOWAIT: Literal[16] + LOG_ODELAY: Literal[4] + LOG_PERROR: Literal[32] + LOG_PID: Literal[1] + LOG_SYSLOG: Literal[40] + LOG_USER: Literal[8] + LOG_UUCP: Literal[64] + LOG_WARNING: Literal[4] + def LOG_MASK(a: int) -> int: ... + def LOG_UPTO(a: int) -> int: ... + def closelog() -> None: ... + def openlog(ident: str = ..., logoption: int = ..., facility: int = ...) -> None: ... + def setlogmask(x: int) -> int: ... + @overload + def syslog(priority: int, message: str) -> None: ... + @overload + def syslog(message: str) -> None: ... diff --git a/mypy/typeshed/stdlib/tarfile.pyi b/mypy/typeshed/stdlib/tarfile.pyi index 0134316d81078..4931a6f0e6795 100644 --- a/mypy/typeshed/stdlib/tarfile.pyi +++ b/mypy/typeshed/stdlib/tarfile.pyi @@ -5,7 +5,7 @@ from _typeshed import Self, StrOrBytesPath, StrPath from collections.abc import Callable, Iterable, Iterator, Mapping from gzip import _ReadableFileobj as _GzipReadableFileobj, _WritableFileobj as _GzipWritableFileobj from types import TracebackType -from typing import IO, Protocol, Tuple, Type, TypeVar, overload +from typing import IO, Protocol, Type, TypeVar, overload from typing_extensions import Literal _TF = TypeVar("_TF", bound=TarFile) @@ -62,10 +62,10 @@ DEFAULT_FORMAT: int # tarfile constants -SUPPORTED_TYPES: Tuple[bytes, ...] -REGULAR_TYPES: Tuple[bytes, ...] -GNU_TYPES: Tuple[bytes, ...] -PAX_FIELDS: Tuple[str, ...] +SUPPORTED_TYPES: tuple[bytes, ...] +REGULAR_TYPES: tuple[bytes, ...] +GNU_TYPES: tuple[bytes, ...] +PAX_FIELDS: tuple[str, ...] PAX_NUMBER_FIELDS: dict[str, type] PAX_NAME_FIELDS: set[str] diff --git a/mypy/typeshed/stdlib/tempfile.pyi b/mypy/typeshed/stdlib/tempfile.pyi index 119c111bc4e13..4aec26175a483 100644 --- a/mypy/typeshed/stdlib/tempfile.pyi +++ b/mypy/typeshed/stdlib/tempfile.pyi @@ -2,7 +2,7 @@ import os import sys from _typeshed import Self from types import TracebackType -from typing import IO, Any, AnyStr, Generic, Iterable, Iterator, Tuple, Type, Union, overload +from typing import IO, Any, AnyStr, Generic, Iterable, Iterator, Type, Union, overload from typing_extensions import Literal if sys.version_info >= (3, 9): @@ -206,7 +206,7 @@ class SpooledTemporaryFile(IO[AnyStr]): @property def encoding(self) -> str: ... # undocumented @property - def newlines(self) -> str | Tuple[str, ...] | None: ... # undocumented + def newlines(self) -> str | tuple[str, ...] | None: ... # undocumented # bytes needs to go first, as default mode is to open as bytes if sys.version_info >= (3, 8): @overload diff --git a/mypy/typeshed/stdlib/termios.pyi b/mypy/typeshed/stdlib/termios.pyi index ed8522dccc514..7142df15715d0 100644 --- a/mypy/typeshed/stdlib/termios.pyi +++ b/mypy/typeshed/stdlib/termios.pyi @@ -1,246 +1,246 @@ +import sys from _typeshed import FileDescriptorLike -from typing import Any, List, Union +from typing import Any, Union -_Attr = List[Union[int, List[Union[bytes, int]]]] +if sys.platform != "win32": + _Attr = list[Union[int, list[Union[bytes, int]]]] -# TODO constants not really documented -B0: int -B1000000: int -B110: int -B115200: int -B1152000: int -B1200: int -B134: int -B150: int -B1500000: int -B1800: int -B19200: int -B200: int -B2000000: int -B230400: int -B2400: int -B2500000: int -B300: int -B3000000: int -B3500000: int -B38400: int -B4000000: int -B460800: int -B4800: int -B50: int -B500000: int -B57600: int -B576000: int -B600: int -B75: int -B921600: int -B9600: int -BRKINT: int -BS0: int -BS1: int -BSDLY: int -CBAUD: int -CBAUDEX: int -CDSUSP: int -CEOF: int -CEOL: int -CEOT: int -CERASE: int -CFLUSH: int -CIBAUD: int -CINTR: int -CKILL: int -CLNEXT: int -CLOCAL: int -CQUIT: int -CR0: int -CR1: int -CR2: int -CR3: int -CRDLY: int -CREAD: int -CRPRNT: int -CRTSCTS: int -CS5: int -CS6: int -CS7: int -CS8: int -CSIZE: int -CSTART: int -CSTOP: int -CSTOPB: int -CSUSP: int -CWERASE: int -ECHO: int -ECHOCTL: int -ECHOE: int -ECHOK: int -ECHOKE: int -ECHONL: int -ECHOPRT: int -EXTA: int -EXTB: int -FF0: int -FF1: int -FFDLY: int -FIOASYNC: int -FIOCLEX: int -FIONBIO: int -FIONCLEX: int -FIONREAD: int -FLUSHO: int -HUPCL: int -ICANON: int -ICRNL: int -IEXTEN: int -IGNBRK: int -IGNCR: int -IGNPAR: int -IMAXBEL: int -INLCR: int -INPCK: int -IOCSIZE_MASK: int -IOCSIZE_SHIFT: int -ISIG: int -ISTRIP: int -IUCLC: int -IXANY: int -IXOFF: int -IXON: int -NCC: int -NCCS: int -NL0: int -NL1: int -NLDLY: int -NOFLSH: int -N_MOUSE: int -N_PPP: int -N_SLIP: int -N_STRIP: int -N_TTY: int -OCRNL: int -OFDEL: int -OFILL: int -OLCUC: int -ONLCR: int -ONLRET: int -ONOCR: int -OPOST: int -PARENB: int -PARMRK: int -PARODD: int -PENDIN: int -TAB0: int -TAB1: int -TAB2: int -TAB3: int -TABDLY: int -TCFLSH: int -TCGETA: int -TCGETS: int -TCIFLUSH: int -TCIOFF: int -TCIOFLUSH: int -TCION: int -TCOFLUSH: int -TCOOFF: int -TCOON: int -TCSADRAIN: int -TCSAFLUSH: int -TCSANOW: int -TCSBRK: int -TCSBRKP: int -TCSETA: int -TCSETAF: int -TCSETAW: int -TCSETS: int -TCSETSF: int -TCSETSW: int -TCXONC: int -TIOCCONS: int -TIOCEXCL: int -TIOCGETD: int -TIOCGICOUNT: int -TIOCGLCKTRMIOS: int -TIOCGPGRP: int -TIOCGSERIAL: int -TIOCGSOFTCAR: int -TIOCGWINSZ: int -TIOCINQ: int -TIOCLINUX: int -TIOCMBIC: int -TIOCMBIS: int -TIOCMGET: int -TIOCMIWAIT: int -TIOCMSET: int -TIOCM_CAR: int -TIOCM_CD: int -TIOCM_CTS: int -TIOCM_DSR: int -TIOCM_DTR: int -TIOCM_LE: int -TIOCM_RI: int -TIOCM_RNG: int -TIOCM_RTS: int -TIOCM_SR: int -TIOCM_ST: int -TIOCNOTTY: int -TIOCNXCL: int -TIOCOUTQ: int -TIOCPKT: int -TIOCPKT_DATA: int -TIOCPKT_DOSTOP: int -TIOCPKT_FLUSHREAD: int -TIOCPKT_FLUSHWRITE: int -TIOCPKT_NOSTOP: int -TIOCPKT_START: int -TIOCPKT_STOP: int -TIOCSCTTY: int -TIOCSERCONFIG: int -TIOCSERGETLSR: int -TIOCSERGETMULTI: int -TIOCSERGSTRUCT: int -TIOCSERGWILD: int -TIOCSERSETMULTI: int -TIOCSERSWILD: int -TIOCSER_TEMT: int -TIOCSETD: int -TIOCSLCKTRMIOS: int -TIOCSPGRP: int -TIOCSSERIAL: int -TIOCSSOFTCAR: int -TIOCSTI: int -TIOCSWINSZ: int -TOSTOP: int -VDISCARD: int -VEOF: int -VEOL: int -VEOL2: int -VERASE: int -VINTR: int -VKILL: int -VLNEXT: int -VMIN: int -VQUIT: int -VREPRINT: int -VSTART: int -VSTOP: int -VSUSP: int -VSWTC: int -VSWTCH: int -VT0: int -VT1: int -VTDLY: int -VTIME: int -VWERASE: int -XCASE: int -XTABS: int - -def tcgetattr(__fd: FileDescriptorLike) -> list[Any]: ... -def tcsetattr(__fd: FileDescriptorLike, __when: int, __attributes: _Attr) -> None: ... -def tcsendbreak(__fd: FileDescriptorLike, __duration: int) -> None: ... -def tcdrain(__fd: FileDescriptorLike) -> None: ... -def tcflush(__fd: FileDescriptorLike, __queue: int) -> None: ... -def tcflow(__fd: FileDescriptorLike, __action: int) -> None: ... - -class error(Exception): ... + # TODO constants not really documented + B0: int + B1000000: int + B110: int + B115200: int + B1152000: int + B1200: int + B134: int + B150: int + B1500000: int + B1800: int + B19200: int + B200: int + B2000000: int + B230400: int + B2400: int + B2500000: int + B300: int + B3000000: int + B3500000: int + B38400: int + B4000000: int + B460800: int + B4800: int + B50: int + B500000: int + B57600: int + B576000: int + B600: int + B75: int + B921600: int + B9600: int + BRKINT: int + BS0: int + BS1: int + BSDLY: int + CBAUD: int + CBAUDEX: int + CDSUSP: int + CEOF: int + CEOL: int + CEOT: int + CERASE: int + CFLUSH: int + CIBAUD: int + CINTR: int + CKILL: int + CLNEXT: int + CLOCAL: int + CQUIT: int + CR0: int + CR1: int + CR2: int + CR3: int + CRDLY: int + CREAD: int + CRPRNT: int + CRTSCTS: int + CS5: int + CS6: int + CS7: int + CS8: int + CSIZE: int + CSTART: int + CSTOP: int + CSTOPB: int + CSUSP: int + CWERASE: int + ECHO: int + ECHOCTL: int + ECHOE: int + ECHOK: int + ECHOKE: int + ECHONL: int + ECHOPRT: int + EXTA: int + EXTB: int + FF0: int + FF1: int + FFDLY: int + FIOASYNC: int + FIOCLEX: int + FIONBIO: int + FIONCLEX: int + FIONREAD: int + FLUSHO: int + HUPCL: int + ICANON: int + ICRNL: int + IEXTEN: int + IGNBRK: int + IGNCR: int + IGNPAR: int + IMAXBEL: int + INLCR: int + INPCK: int + IOCSIZE_MASK: int + IOCSIZE_SHIFT: int + ISIG: int + ISTRIP: int + IUCLC: int + IXANY: int + IXOFF: int + IXON: int + NCC: int + NCCS: int + NL0: int + NL1: int + NLDLY: int + NOFLSH: int + N_MOUSE: int + N_PPP: int + N_SLIP: int + N_STRIP: int + N_TTY: int + OCRNL: int + OFDEL: int + OFILL: int + OLCUC: int + ONLCR: int + ONLRET: int + ONOCR: int + OPOST: int + PARENB: int + PARMRK: int + PARODD: int + PENDIN: int + TAB0: int + TAB1: int + TAB2: int + TAB3: int + TABDLY: int + TCFLSH: int + TCGETA: int + TCGETS: int + TCIFLUSH: int + TCIOFF: int + TCIOFLUSH: int + TCION: int + TCOFLUSH: int + TCOOFF: int + TCOON: int + TCSADRAIN: int + TCSAFLUSH: int + TCSANOW: int + TCSBRK: int + TCSBRKP: int + TCSETA: int + TCSETAF: int + TCSETAW: int + TCSETS: int + TCSETSF: int + TCSETSW: int + TCXONC: int + TIOCCONS: int + TIOCEXCL: int + TIOCGETD: int + TIOCGICOUNT: int + TIOCGLCKTRMIOS: int + TIOCGPGRP: int + TIOCGSERIAL: int + TIOCGSOFTCAR: int + TIOCGWINSZ: int + TIOCINQ: int + TIOCLINUX: int + TIOCMBIC: int + TIOCMBIS: int + TIOCMGET: int + TIOCMIWAIT: int + TIOCMSET: int + TIOCM_CAR: int + TIOCM_CD: int + TIOCM_CTS: int + TIOCM_DSR: int + TIOCM_DTR: int + TIOCM_LE: int + TIOCM_RI: int + TIOCM_RNG: int + TIOCM_RTS: int + TIOCM_SR: int + TIOCM_ST: int + TIOCNOTTY: int + TIOCNXCL: int + TIOCOUTQ: int + TIOCPKT: int + TIOCPKT_DATA: int + TIOCPKT_DOSTOP: int + TIOCPKT_FLUSHREAD: int + TIOCPKT_FLUSHWRITE: int + TIOCPKT_NOSTOP: int + TIOCPKT_START: int + TIOCPKT_STOP: int + TIOCSCTTY: int + TIOCSERCONFIG: int + TIOCSERGETLSR: int + TIOCSERGETMULTI: int + TIOCSERGSTRUCT: int + TIOCSERGWILD: int + TIOCSERSETMULTI: int + TIOCSERSWILD: int + TIOCSER_TEMT: int + TIOCSETD: int + TIOCSLCKTRMIOS: int + TIOCSPGRP: int + TIOCSSERIAL: int + TIOCSSOFTCAR: int + TIOCSTI: int + TIOCSWINSZ: int + TOSTOP: int + VDISCARD: int + VEOF: int + VEOL: int + VEOL2: int + VERASE: int + VINTR: int + VKILL: int + VLNEXT: int + VMIN: int + VQUIT: int + VREPRINT: int + VSTART: int + VSTOP: int + VSUSP: int + VSWTC: int + VSWTCH: int + VT0: int + VT1: int + VTDLY: int + VTIME: int + VWERASE: int + XCASE: int + XTABS: int + def tcgetattr(__fd: FileDescriptorLike) -> list[Any]: ... + def tcsetattr(__fd: FileDescriptorLike, __when: int, __attributes: _Attr) -> None: ... + def tcsendbreak(__fd: FileDescriptorLike, __duration: int) -> None: ... + def tcdrain(__fd: FileDescriptorLike) -> None: ... + def tcflush(__fd: FileDescriptorLike, __queue: int) -> None: ... + def tcflow(__fd: FileDescriptorLike, __action: int) -> None: ... + class error(Exception): ... diff --git a/mypy/typeshed/stdlib/threading.pyi b/mypy/typeshed/stdlib/threading.pyi index 64998d86bf9fa..3e91221baed21 100644 --- a/mypy/typeshed/stdlib/threading.pyi +++ b/mypy/typeshed/stdlib/threading.pyi @@ -11,8 +11,9 @@ _T = TypeVar("_T") __all__: list[str] def active_count() -> int: ... +def activeCount() -> int: ... # deprecated alias for active_count() def current_thread() -> Thread: ... -def currentThread() -> Thread: ... +def currentThread() -> Thread: ... # deprecated alias for current_thread() def get_ident() -> int: ... def enumerate() -> list[Thread]: ... def main_thread() -> Thread: ... @@ -22,13 +23,18 @@ if sys.version_info >= (3, 8): def settrace(func: _TF) -> None: ... def setprofile(func: _PF | None) -> None: ... + +if sys.version_info >= (3, 10): + def gettrace() -> _TF | None: ... + def getprofile() -> _PF | None: ... + def stack_size(size: int = ...) -> int: ... TIMEOUT_MAX: float class ThreadError(Exception): ... -class local(object): +class local: def __getattribute__(self, name: str) -> Any: ... def __setattr__(self, name: str, value: Any) -> None: ... def __delattr__(self, name: str) -> None: ... @@ -50,18 +56,20 @@ class Thread: def start(self) -> None: ... def run(self) -> None: ... def join(self, timeout: float | None = ...) -> None: ... - def getName(self) -> str: ... - def setName(self, name: str) -> None: ... if sys.version_info >= (3, 8): @property def native_id(self) -> int | None: ... # only available on some platforms def is_alive(self) -> bool: ... if sys.version_info < (3, 9): def isAlive(self) -> bool: ... + # the following methods are all deprecated + def getName(self) -> str: ... + def setName(self, name: str) -> None: ... def isDaemon(self) -> bool: ... def setDaemon(self, daemonic: bool) -> None: ... -class _DummyThread(Thread): ... +class _DummyThread(Thread): + def __init__(self) -> None: ... class Lock: def __init__(self) -> None: ... @@ -75,12 +83,12 @@ class Lock: class _RLock: def __init__(self) -> None: ... - def __enter__(self) -> bool: ... + def acquire(self, blocking: bool = ..., timeout: float = ...) -> bool: ... + def release(self) -> None: ... + __enter__ = acquire def __exit__( self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> bool | None: ... - def acquire(self, blocking: bool = ..., timeout: float = ...) -> bool: ... - def release(self) -> None: ... RLock = _RLock @@ -96,7 +104,7 @@ class Condition: def wait_for(self, predicate: Callable[[], _T], timeout: float | None = ...) -> _T: ... def notify(self, n: int = ...) -> None: ... def notify_all(self) -> None: ... - def notifyAll(self) -> None: ... + def notifyAll(self) -> None: ... # deprecated alias for notify_all() class Semaphore: def __init__(self, value: int = ...) -> None: ... @@ -115,6 +123,7 @@ class BoundedSemaphore(Semaphore): ... class Event: def __init__(self) -> None: ... def is_set(self) -> bool: ... + def isSet(self) -> bool: ... # deprecated alias for is_set() def set(self) -> None: ... def clear(self) -> None: ... def wait(self, timeout: float | None = ...) -> bool: ... diff --git a/mypy/typeshed/stdlib/time.pyi b/mypy/typeshed/stdlib/time.pyi index bf370d68e83df..6e23b331d1c85 100644 --- a/mypy/typeshed/stdlib/time.pyi +++ b/mypy/typeshed/stdlib/time.pyi @@ -1,9 +1,10 @@ import sys +from _typeshed import structseq from types import SimpleNamespace -from typing import Any, NamedTuple, Tuple +from typing import Any, Union from typing_extensions import final -_TimeTuple = Tuple[int, int, int, int, int, int, int, int, int] +_TimeTuple = tuple[int, int, int, int, int, int, int, int, int] altzone: int daylight: int @@ -32,39 +33,31 @@ if sys.version_info >= (3, 8) and sys.platform == "darwin": if sys.version_info >= (3, 9) and sys.platform == "linux": CLOCK_TAI: int -class _struct_time(NamedTuple): - tm_year: int - tm_mon: int - tm_mday: int - tm_hour: int - tm_min: int - tm_sec: int - tm_wday: int - tm_yday: int - tm_isdst: int +# Constructor takes an iterable of any type, of length between 9 and 11 elements. +# However, it always *behaves* like a tuple of 9 elements, +# even if an iterable with length >9 is passed. +# https://github.com/python/typeshed/pull/6560#discussion_r767162532 +@final +class struct_time(structseq[Union[Any, int]], _TimeTuple): @property - def n_fields(self) -> int: ... + def tm_year(self) -> int: ... @property - def n_sequence_fields(self) -> int: ... + def tm_mon(self) -> int: ... @property - def n_unnamed_fields(self) -> int: ... - -@final -class struct_time(_struct_time): - def __init__( - self, - o: tuple[int, int, int, int, int, int, int, int, int] - | tuple[int, int, int, int, int, int, int, int, int, str] - | tuple[int, int, int, int, int, int, int, int, int, str, int], - _arg: Any = ..., - ) -> None: ... - def __new__( - cls, - o: tuple[int, int, int, int, int, int, int, int, int] - | tuple[int, int, int, int, int, int, int, int, int, str] - | tuple[int, int, int, int, int, int, int, int, int, str, int], - _arg: Any = ..., - ) -> struct_time: ... + def tm_mday(self) -> int: ... + @property + def tm_hour(self) -> int: ... + @property + def tm_min(self) -> int: ... + @property + def tm_sec(self) -> int: ... + @property + def tm_wday(self) -> int: ... + @property + def tm_yday(self) -> int: ... + @property + def tm_isdst(self) -> int: ... + # These final two properties only exist if a 10- or 11-item sequence was passed to the constructor. @property def tm_zone(self) -> str: ... @property diff --git a/mypy/typeshed/stdlib/tkinter/__init__.pyi b/mypy/typeshed/stdlib/tkinter/__init__.pyi index bda37b406fc3f..50de97f48fdca 100644 --- a/mypy/typeshed/stdlib/tkinter/__init__.pyi +++ b/mypy/typeshed/stdlib/tkinter/__init__.pyi @@ -2,10 +2,10 @@ import _tkinter import sys from _typeshed import StrOrBytesPath from enum import Enum -from tkinter.constants import * # comment this out to find undefined identifier names with flake8 +from tkinter.constants import * from tkinter.font import _FontDescription from types import TracebackType -from typing import Any, Callable, Generic, List, Mapping, Optional, Protocol, Sequence, Tuple, Type, TypeVar, Union, overload +from typing import Any, Callable, Generic, Mapping, Optional, Protocol, Sequence, Type, TypeVar, Union, overload from typing_extensions import Literal, TypedDict # Using anything from tkinter.font in this file means that 'import tkinter' @@ -24,93 +24,46 @@ EXCEPTION = _tkinter.EXCEPTION # - Misc: any widget (don't use BaseWidget because Tk doesn't inherit from BaseWidget) # - Widget: anything that is meant to be put into another widget with e.g. pack or grid # -# Instructions for figuring out the correct type of each widget option: -# - See discussion on #4363. +# Don't trust tkinter's docstrings, because they have been created by copy/pasting from +# Tk's manual pages more than 10 years ago. Use the latest manual pages instead: # -# - Find the option from the manual page of the widget. Usually the manual -# page of a non-ttk widget has the same name as the tkinter class, in the -# 3tk section: +# $ sudo apt install tk-doc tcl-doc +# $ man 3tk label # tkinter.Label +# $ man 3tk ttk_label # tkinter.ttk.Label +# $ man 3tcl after # tkinter.Misc.after # -# $ sudo apt install tk-doc -# $ man 3tk label -# -# Ttk manual pages tend to have ttk_ prefixed names: -# -# $ man 3tk ttk_label -# -# Non-GUI things like the .after() method are often in the 3tcl section: -# -# $ sudo apt install tcl-doc -# $ man 3tcl after -# -# If you don't have man or apt, you can read these manual pages online: -# -# https://www.tcl.tk/doc/ -# -# Every option has '-' in front of its name in the manual page (and in Tcl). -# For example, there's an option named '-text' in the label manual page. -# -# - Tkinter has some options documented in docstrings, but don't rely on them. -# They aren't updated when a new version of Tk comes out, so the latest Tk -# manual pages (see above) are much more likely to actually contain all -# possible options. -# -# Also, reading tkinter's source code typically won't help much because it -# uses a lot of **kwargs and duck typing. Typically every argument goes into -# self.tk.call, which is _tkinter.TkappType.call, and the return value is -# whatever that returns. The type of that depends on how the Tcl interpreter -# represents the return value of the executed Tcl code. -# -# - If you think that int is an appropriate type for something, then you may -# actually want _ScreenUnits instead. -# -# - If you think that Callable[something] is an appropriate type for -# something, then you may actually want Callable[something] | str, -# because it's often possible to specify a string of Tcl code. -# -# - If you think the correct type is Iterable[Foo] or Sequence[Foo], it is -# probably list[Foo] | tuple[Foo, ...], disallowing other sequences such -# as deques: -# -# >>> tkinter.Label(font=('Helvetica', 12, collections.deque(['bold']))) -# Traceback (most recent call last): -# ... -# _tkinter.TclError: unknown font style "deque(['bold'])" -# -# - Some options can be set only in __init__, but all options are available -# when getting their values with configure's return value or cget. -# -# - Asks other tkinter users if you haven't worked much with tkinter. +# You can also read the manual pages online: https://www.tcl.tk/doc/ # Some widgets have an option named -compound that accepts different values # than the _Compound defined here. Many other options have similar things. _Anchor = Literal["nw", "n", "ne", "w", "center", "e", "sw", "s", "se"] # manual page: Tk_GetAnchor _Bitmap = str # manual page: Tk_GetBitmap -_ButtonCommand = Union[str, Callable[[], Any]] # return value is returned from Button.invoke() +_ButtonCommand = Union[str, Callable[[], Any]] # accepts string of tcl code, return value is returned from Button.invoke() _CanvasItemId = int _Color = str # typically '#rrggbb', '#rgb' or color names. _Compound = Literal["top", "left", "center", "right", "bottom", "none"] # -compound in manual page named 'options' -_Cursor = Union[str, Tuple[str], Tuple[str, str], Tuple[str, str, str], Tuple[str, str, str, str]] # manual page: Tk_GetCursor +_Cursor = Union[str, tuple[str], tuple[str, str], tuple[str, str, str], tuple[str, str, str, str]] # manual page: Tk_GetCursor _EntryValidateCommand = Union[ - Callable[[], bool], str, List[str], Tuple[str, ...] + Callable[[], bool], str, list[str], tuple[str, ...] ] # example when it's sequence: entry['invalidcommand'] = [entry.register(print), '%P'] _GridIndex = Union[int, str, Literal["all"]] _ImageSpec = Union[_Image, str] # str can be from e.g. tkinter.image_names() _Padding = Union[ _ScreenUnits, - Tuple[_ScreenUnits], - Tuple[_ScreenUnits, _ScreenUnits], - Tuple[_ScreenUnits, _ScreenUnits, _ScreenUnits], - Tuple[_ScreenUnits, _ScreenUnits, _ScreenUnits, _ScreenUnits], + tuple[_ScreenUnits], + tuple[_ScreenUnits, _ScreenUnits], + tuple[_ScreenUnits, _ScreenUnits, _ScreenUnits], + tuple[_ScreenUnits, _ScreenUnits, _ScreenUnits, _ScreenUnits], ] _Relief = Literal["raised", "sunken", "flat", "ridge", "solid", "groove"] # manual page: Tk_GetRelief -_ScreenUnits = Union[str, float] # manual page: Tk_GetPixels +_ScreenUnits = Union[str, float] # Often the right type instead of int. Manual page: Tk_GetPixels _XYScrollCommand = Union[str, Callable[[float, float], Any]] # -xscrollcommand and -yscrollcommand in 'options' manual page _TakeFocusValue = Union[int, Literal[""], Callable[[str], Optional[bool]]] # -takefocus in manual page named 'options' class EventType(str, Enum): Activate: str ButtonPress: str + Button = ButtonPress ButtonRelease: str Circulate: str CirculateRequest: str @@ -128,6 +81,7 @@ class EventType(str, Enum): GraphicsExpose: str Gravity: str KeyPress: str + Key = KeyPress KeyRelease: str Keymap: str Leave: str @@ -183,7 +137,7 @@ class Variable: def get(self) -> Any: ... def trace_add(self, mode: _TraceMode, callback: Callable[[str, str, str], Any]) -> str: ... def trace_remove(self, mode: _TraceMode, cbname: str) -> None: ... - def trace_info(self) -> list[tuple[Tuple[_TraceMode, ...], str]]: ... + def trace_info(self) -> list[tuple[tuple[_TraceMode, ...], str]]: ... def trace_variable(self, mode, callback): ... # deprecated def trace_vdelete(self, mode, cbname): ... # deprecated def trace_vinfo(self): ... # deprecated @@ -295,7 +249,7 @@ class Misc: def winfo_geometry(self) -> str: ... def winfo_height(self) -> int: ... def winfo_id(self) -> int: ... - def winfo_interps(self, displayof: Literal[0] | Misc | None = ...) -> Tuple[str, ...]: ... + def winfo_interps(self, displayof: Literal[0] | Misc | None = ...) -> tuple[str, ...]: ... def winfo_ismapped(self) -> bool: ... def winfo_manager(self) -> str: ... def winfo_name(self) -> str: ... @@ -466,9 +420,9 @@ class Misc: x: _ScreenUnits = ..., y: _ScreenUnits = ..., ) -> None: ... - def event_info(self, virtual: str | None = ...) -> Tuple[str, ...]: ... - def image_names(self) -> Tuple[str, ...]: ... - def image_types(self) -> Tuple[str, ...]: ... + def event_info(self, virtual: str | None = ...) -> tuple[str, ...]: ... + def image_names(self) -> tuple[str, ...]: ... + def image_types(self) -> tuple[str, ...]: ... # See #4363 and #4891 def __setitem__(self, key: str, value: Any) -> None: ... def __getitem__(self, key: str) -> Any: ... @@ -514,7 +468,7 @@ class Wm: ) -> tuple[int, int, int, int] | None: ... aspect = wm_aspect @overload - def wm_attributes(self) -> Tuple[Any, ...]: ... + def wm_attributes(self) -> tuple[Any, ...]: ... @overload def wm_attributes(self, __option: str) -> Any: ... @overload @@ -525,7 +479,7 @@ class Wm: @overload def wm_colormapwindows(self) -> list[Misc]: ... @overload - def wm_colormapwindows(self, __wlist: list[Misc] | Tuple[Misc, ...]) -> None: ... + def wm_colormapwindows(self, __wlist: list[Misc] | tuple[Misc, ...]) -> None: ... @overload def wm_colormapwindows(self, __first_wlist_item: Misc, *other_wlist_items: Misc) -> None: ... colormapwindows = wm_colormapwindows @@ -589,7 +543,7 @@ class Wm: @overload def wm_protocol(self, name: str, func: None = ...) -> str: ... @overload - def wm_protocol(self, name: None = ..., func: None = ...) -> Tuple[str, ...]: ... + def wm_protocol(self, name: None = ..., func: None = ...) -> tuple[str, ...]: ... protocol = wm_protocol @overload def wm_resizable(self, width: None = ..., height: None = ...) -> tuple[bool, bool]: ... @@ -688,7 +642,8 @@ class Tk(Misc, Wm): quit: Any record: Any setvar: Any - split: Any + if sys.version_info < (3, 11): + split: Any splitlist: Any unsetvar: Any wantobjects: Any @@ -739,14 +694,6 @@ class Pack: pack = pack_configure forget = pack_forget propagate = Misc.pack_propagate - # commented out to avoid mypy getting confused with multiple - # inheritance and how things get overridden with different things - # info = pack_info - # pack_propagate = Misc.pack_propagate - # configure = pack_configure - # config = pack_configure - # slaves = Misc.pack_slaves - # pack_slaves = Misc.pack_slaves class _PlaceInfo(_InMiscNonTotal): # empty dict if widget hasn't been placed anchor: _Anchor @@ -783,13 +730,6 @@ class Place: def place_info(self) -> _PlaceInfo: ... place = place_configure info = place_info - # commented out to avoid mypy getting confused with multiple - # inheritance and how things get overridden with different things - # config = place_configure - # configure = place_configure - # forget = place_forget - # slaves = Misc.place_slaves - # place_slaves = Misc.place_slaves class _GridInfo(_InMiscNonTotal): # empty dict if widget hasn't been gridded column: int @@ -825,24 +765,6 @@ class Grid: grid = grid_configure location = Misc.grid_location size = Misc.grid_size - # commented out to avoid mypy getting confused with multiple - # inheritance and how things get overridden with different things - # bbox = Misc.grid_bbox - # grid_bbox = Misc.grid_bbox - # forget = grid_forget - # info = grid_info - # grid_location = Misc.grid_location - # grid_propagate = Misc.grid_propagate - # grid_size = Misc.grid_size - # rowconfigure = Misc.grid_rowconfigure - # grid_rowconfigure = Misc.grid_rowconfigure - # grid_columnconfigure = Misc.grid_columnconfigure - # columnconfigure = Misc.grid_columnconfigure - # config = grid_configure - # configure = grid_configure - # propagate = Misc.grid_propagate - # slaves = Misc.grid_slaves - # grid_slaves = Misc.grid_slaves class BaseWidget(Misc): master: Misc @@ -1121,21 +1043,19 @@ class Canvas(Widget, XView, YView): def addtag_overlapping(self, newtag: str, x1: _ScreenUnits, y1: _ScreenUnits, x2: _ScreenUnits, y2: _ScreenUnits) -> None: ... def addtag_withtag(self, newtag: str, tagOrId: str | _CanvasItemId) -> None: ... def find(self, *args): ... # internal method - def find_above(self, tagOrId: str | _CanvasItemId) -> Tuple[_CanvasItemId, ...]: ... - def find_all(self) -> Tuple[_CanvasItemId, ...]: ... - def find_below(self, tagOrId: str | _CanvasItemId) -> Tuple[_CanvasItemId, ...]: ... + def find_above(self, tagOrId: str | _CanvasItemId) -> tuple[_CanvasItemId, ...]: ... + def find_all(self) -> tuple[_CanvasItemId, ...]: ... + def find_below(self, tagOrId: str | _CanvasItemId) -> tuple[_CanvasItemId, ...]: ... def find_closest( self, x: _ScreenUnits, y: _ScreenUnits, halo: _ScreenUnits | None = ..., start: str | _CanvasItemId | None = ... - ) -> Tuple[_CanvasItemId, ...]: ... + ) -> tuple[_CanvasItemId, ...]: ... def find_enclosed( self, x1: _ScreenUnits, y1: _ScreenUnits, x2: _ScreenUnits, y2: _ScreenUnits - ) -> Tuple[_CanvasItemId, ...]: ... - def find_overlapping(self, x1: _ScreenUnits, y1: _ScreenUnits, x2: _ScreenUnits, y2: float) -> Tuple[_CanvasItemId, ...]: ... - def find_withtag(self, tagOrId: str | _CanvasItemId) -> Tuple[_CanvasItemId, ...]: ... - # Canvas.bbox() args are `str | _CanvasItemId`, but mypy rejects that - # description because it's incompatible with Misc.bbox(), an alias for - # Misc.grid_bbox(). Yes it is, but there's not much we can do about it. - def bbox(self, *args: str | _CanvasItemId) -> tuple[int, int, int, int]: ... # type: ignore + ) -> tuple[_CanvasItemId, ...]: ... + def find_overlapping(self, x1: _ScreenUnits, y1: _ScreenUnits, x2: _ScreenUnits, y2: float) -> tuple[_CanvasItemId, ...]: ... + def find_withtag(self, tagOrId: str | _CanvasItemId) -> tuple[_CanvasItemId, ...]: ... + # Incompatible with Misc.bbox(), tkinter violates LSP + def bbox(self, *args: str | _CanvasItemId) -> tuple[int, int, int, int]: ... # type: ignore[override] @overload def tag_bind( self, @@ -1156,7 +1076,7 @@ class Canvas(Widget, XView, YView): @overload def coords(self) -> list[float]: ... @overload - def coords(self, __args: list[int] | list[float] | Tuple[float, ...]) -> None: ... + def coords(self, __args: list[int] | list[float] | tuple[float, ...]) -> None: ... @overload def coords(self, __x1: float, __y1: float, *args: float) -> None: ... # create_foo() methods accept coords as a list, a tuple, or as separate arguments. @@ -1172,16 +1092,16 @@ class Canvas(Widget, XView, YView): __x1: float, __y1: float, *, - activedash: str | list[int] | Tuple[int, ...] = ..., + activedash: str | list[int] | tuple[int, ...] = ..., activefill: _Color = ..., activestipple: str = ..., activewidth: _ScreenUnits = ..., arrow: Literal["first", "last", "both"] = ..., arrowshape: tuple[float, float, float] = ..., capstyle: Literal["round", "projecting", "butt"] = ..., - dash: str | list[int] | Tuple[int, ...] = ..., + dash: str | list[int] | tuple[int, ...] = ..., dashoffset: _ScreenUnits = ..., - disableddash: str | list[int] | Tuple[int, ...] = ..., + disableddash: str | list[int] | tuple[int, ...] = ..., disabledfill: _Color = ..., disabledstipple: _Bitmap = ..., disabledwidth: _ScreenUnits = ..., @@ -1192,7 +1112,7 @@ class Canvas(Widget, XView, YView): splinesteps: float = ..., state: Literal["normal", "active", "disabled"] = ..., stipple: _Bitmap = ..., - tags: str | list[str] | Tuple[str, ...] = ..., + tags: str | list[str] | tuple[str, ...] = ..., width: _ScreenUnits = ..., ) -> _CanvasItemId: ... @overload @@ -1200,16 +1120,16 @@ class Canvas(Widget, XView, YView): self, __coords: tuple[float, float, float, float] | list[int] | list[float], *, - activedash: str | list[int] | Tuple[int, ...] = ..., + activedash: str | list[int] | tuple[int, ...] = ..., activefill: _Color = ..., activestipple: str = ..., activewidth: _ScreenUnits = ..., arrow: Literal["first", "last", "both"] = ..., arrowshape: tuple[float, float, float] = ..., capstyle: Literal["round", "projecting", "butt"] = ..., - dash: str | list[int] | Tuple[int, ...] = ..., + dash: str | list[int] | tuple[int, ...] = ..., dashoffset: _ScreenUnits = ..., - disableddash: str | list[int] | Tuple[int, ...] = ..., + disableddash: str | list[int] | tuple[int, ...] = ..., disabledfill: _Color = ..., disabledstipple: _Bitmap = ..., disabledwidth: _ScreenUnits = ..., @@ -1220,7 +1140,7 @@ class Canvas(Widget, XView, YView): splinesteps: float = ..., state: Literal["normal", "active", "disabled"] = ..., stipple: _Bitmap = ..., - tags: str | list[str] | Tuple[str, ...] = ..., + tags: str | list[str] | tuple[str, ...] = ..., width: _ScreenUnits = ..., ) -> _CanvasItemId: ... @overload @@ -1231,15 +1151,15 @@ class Canvas(Widget, XView, YView): __x1: float, __y1: float, *, - activedash: str | list[int] | Tuple[int, ...] = ..., + activedash: str | list[int] | tuple[int, ...] = ..., activefill: _Color = ..., activeoutline: _Color = ..., activeoutlinestipple: _Color = ..., activestipple: str = ..., activewidth: _ScreenUnits = ..., - dash: str | list[int] | Tuple[int, ...] = ..., + dash: str | list[int] | tuple[int, ...] = ..., dashoffset: _ScreenUnits = ..., - disableddash: str | list[int] | Tuple[int, ...] = ..., + disableddash: str | list[int] | tuple[int, ...] = ..., disabledfill: _Color = ..., disabledoutline: _Color = ..., disabledoutlinestipple: _Color = ..., @@ -1252,7 +1172,7 @@ class Canvas(Widget, XView, YView): outlinestipple: _Bitmap = ..., state: Literal["normal", "active", "disabled"] = ..., stipple: _Bitmap = ..., - tags: str | list[str] | Tuple[str, ...] = ..., + tags: str | list[str] | tuple[str, ...] = ..., width: _ScreenUnits = ..., ) -> _CanvasItemId: ... @overload @@ -1260,15 +1180,15 @@ class Canvas(Widget, XView, YView): self, __coords: tuple[float, float, float, float] | list[int] | list[float], *, - activedash: str | list[int] | Tuple[int, ...] = ..., + activedash: str | list[int] | tuple[int, ...] = ..., activefill: _Color = ..., activeoutline: _Color = ..., activeoutlinestipple: _Color = ..., activestipple: str = ..., activewidth: _ScreenUnits = ..., - dash: str | list[int] | Tuple[int, ...] = ..., + dash: str | list[int] | tuple[int, ...] = ..., dashoffset: _ScreenUnits = ..., - disableddash: str | list[int] | Tuple[int, ...] = ..., + disableddash: str | list[int] | tuple[int, ...] = ..., disabledfill: _Color = ..., disabledoutline: _Color = ..., disabledoutlinestipple: _Color = ..., @@ -1281,7 +1201,7 @@ class Canvas(Widget, XView, YView): outlinestipple: _Bitmap = ..., state: Literal["normal", "active", "disabled"] = ..., stipple: _Bitmap = ..., - tags: str | list[str] | Tuple[str, ...] = ..., + tags: str | list[str] | tuple[str, ...] = ..., width: _ScreenUnits = ..., ) -> _CanvasItemId: ... @overload @@ -1292,15 +1212,15 @@ class Canvas(Widget, XView, YView): __x1: float, __y1: float, *xy_pairs: float, - activedash: str | list[int] | Tuple[int, ...] = ..., + activedash: str | list[int] | tuple[int, ...] = ..., activefill: _Color = ..., activeoutline: _Color = ..., activeoutlinestipple: _Color = ..., activestipple: str = ..., activewidth: _ScreenUnits = ..., - dash: str | list[int] | Tuple[int, ...] = ..., + dash: str | list[int] | tuple[int, ...] = ..., dashoffset: _ScreenUnits = ..., - disableddash: str | list[int] | Tuple[int, ...] = ..., + disableddash: str | list[int] | tuple[int, ...] = ..., disabledfill: _Color = ..., disabledoutline: _Color = ..., disabledoutlinestipple: _Color = ..., @@ -1316,23 +1236,23 @@ class Canvas(Widget, XView, YView): splinesteps: float = ..., state: Literal["normal", "active", "disabled"] = ..., stipple: _Bitmap = ..., - tags: str | list[str] | Tuple[str, ...] = ..., + tags: str | list[str] | tuple[str, ...] = ..., width: _ScreenUnits = ..., ) -> _CanvasItemId: ... @overload def create_polygon( self, - __coords: Tuple[float, ...] | list[int] | list[float], + __coords: tuple[float, ...] | list[int] | list[float], *, - activedash: str | list[int] | Tuple[int, ...] = ..., + activedash: str | list[int] | tuple[int, ...] = ..., activefill: _Color = ..., activeoutline: _Color = ..., activeoutlinestipple: _Color = ..., activestipple: str = ..., activewidth: _ScreenUnits = ..., - dash: str | list[int] | Tuple[int, ...] = ..., + dash: str | list[int] | tuple[int, ...] = ..., dashoffset: _ScreenUnits = ..., - disableddash: str | list[int] | Tuple[int, ...] = ..., + disableddash: str | list[int] | tuple[int, ...] = ..., disabledfill: _Color = ..., disabledoutline: _Color = ..., disabledoutlinestipple: _Color = ..., @@ -1348,7 +1268,7 @@ class Canvas(Widget, XView, YView): splinesteps: float = ..., state: Literal["normal", "active", "disabled"] = ..., stipple: _Bitmap = ..., - tags: str | list[str] | Tuple[str, ...] = ..., + tags: str | list[str] | tuple[str, ...] = ..., width: _ScreenUnits = ..., ) -> _CanvasItemId: ... @overload @@ -1359,15 +1279,15 @@ class Canvas(Widget, XView, YView): __x1: float, __y1: float, *, - activedash: str | list[int] | Tuple[int, ...] = ..., + activedash: str | list[int] | tuple[int, ...] = ..., activefill: _Color = ..., activeoutline: _Color = ..., activeoutlinestipple: _Color = ..., activestipple: str = ..., activewidth: _ScreenUnits = ..., - dash: str | list[int] | Tuple[int, ...] = ..., + dash: str | list[int] | tuple[int, ...] = ..., dashoffset: _ScreenUnits = ..., - disableddash: str | list[int] | Tuple[int, ...] = ..., + disableddash: str | list[int] | tuple[int, ...] = ..., disabledfill: _Color = ..., disabledoutline: _Color = ..., disabledoutlinestipple: _Color = ..., @@ -1380,7 +1300,7 @@ class Canvas(Widget, XView, YView): outlinestipple: _Bitmap = ..., state: Literal["normal", "active", "disabled"] = ..., stipple: _Bitmap = ..., - tags: str | list[str] | Tuple[str, ...] = ..., + tags: str | list[str] | tuple[str, ...] = ..., width: _ScreenUnits = ..., ) -> _CanvasItemId: ... @overload @@ -1388,15 +1308,15 @@ class Canvas(Widget, XView, YView): self, __coords: tuple[float, float, float, float] | list[int] | list[float], *, - activedash: str | list[int] | Tuple[int, ...] = ..., + activedash: str | list[int] | tuple[int, ...] = ..., activefill: _Color = ..., activeoutline: _Color = ..., activeoutlinestipple: _Color = ..., activestipple: str = ..., activewidth: _ScreenUnits = ..., - dash: str | list[int] | Tuple[int, ...] = ..., + dash: str | list[int] | tuple[int, ...] = ..., dashoffset: _ScreenUnits = ..., - disableddash: str | list[int] | Tuple[int, ...] = ..., + disableddash: str | list[int] | tuple[int, ...] = ..., disabledfill: _Color = ..., disabledoutline: _Color = ..., disabledoutlinestipple: _Color = ..., @@ -1409,7 +1329,7 @@ class Canvas(Widget, XView, YView): outlinestipple: _Bitmap = ..., state: Literal["normal", "active", "disabled"] = ..., stipple: _Bitmap = ..., - tags: str | list[str] | Tuple[str, ...] = ..., + tags: str | list[str] | tuple[str, ...] = ..., width: _ScreenUnits = ..., ) -> _CanvasItemId: ... @overload @@ -1429,7 +1349,7 @@ class Canvas(Widget, XView, YView): offset: _ScreenUnits = ..., state: Literal["normal", "active", "disabled"] = ..., stipple: _Bitmap = ..., - tags: str | list[str] | Tuple[str, ...] = ..., + tags: str | list[str] | tuple[str, ...] = ..., text: float | str = ..., width: _ScreenUnits = ..., ) -> _CanvasItemId: ... @@ -1449,7 +1369,7 @@ class Canvas(Widget, XView, YView): offset: _ScreenUnits = ..., state: Literal["normal", "active", "disabled"] = ..., stipple: _Bitmap = ..., - tags: str | list[str] | Tuple[str, ...] = ..., + tags: str | list[str] | tuple[str, ...] = ..., text: float | str = ..., width: _ScreenUnits = ..., ) -> _CanvasItemId: ... @@ -1462,7 +1382,7 @@ class Canvas(Widget, XView, YView): anchor: _Anchor = ..., height: _ScreenUnits = ..., state: Literal["normal", "active", "disabled"] = ..., - tags: str | list[str] | Tuple[str, ...] = ..., + tags: str | list[str] | tuple[str, ...] = ..., width: _ScreenUnits = ..., window: Widget = ..., ) -> _CanvasItemId: ... @@ -1474,7 +1394,7 @@ class Canvas(Widget, XView, YView): anchor: _Anchor = ..., height: _ScreenUnits = ..., state: Literal["normal", "active", "disabled"] = ..., - tags: str | list[str] | Tuple[str, ...] = ..., + tags: str | list[str] | tuple[str, ...] = ..., width: _ScreenUnits = ..., window: Widget = ..., ) -> _CanvasItemId: ... @@ -1485,7 +1405,7 @@ class Canvas(Widget, XView, YView): @overload def dtag(self, __id: _CanvasItemId, __tag_to_delete: str) -> None: ... def focus(self, *args): ... - def gettags(self, __tagOrId: str | _CanvasItemId) -> Tuple[str, ...]: ... + def gettags(self, __tagOrId: str | _CanvasItemId) -> tuple[str, ...]: ... def icursor(self, *args): ... def index(self, *args): ... def insert(self, *args): ... @@ -1505,10 +1425,10 @@ class Canvas(Widget, XView, YView): # # But mypy doesn't like aliasing here (maybe because Misc defines the same names) def tag_lower(self, __first: str | _CanvasItemId, __second: str | _CanvasItemId | None = ...) -> None: ... - def lower(self, __first: str | _CanvasItemId, __second: str | _CanvasItemId | None = ...) -> None: ... # type: ignore + def lower(self, __first: str | _CanvasItemId, __second: str | _CanvasItemId | None = ...) -> None: ... # type: ignore[override] def tag_raise(self, __first: str | _CanvasItemId, __second: str | _CanvasItemId | None = ...) -> None: ... - def tkraise(self, __first: str | _CanvasItemId, __second: str | _CanvasItemId | None = ...) -> None: ... # type: ignore - def lift(self, __first: str | _CanvasItemId, __second: str | _CanvasItemId | None = ...) -> None: ... # type: ignore + def tkraise(self, __first: str | _CanvasItemId, __second: str | _CanvasItemId | None = ...) -> None: ... # type: ignore[override] + def lift(self, __first: str | _CanvasItemId, __second: str | _CanvasItemId | None = ...) -> None: ... # type: ignore[override] def scale(self, *args): ... def scan_mark(self, x, y): ... def scan_dragto(self, x, y, gain: int = ...): ... @@ -1737,7 +1657,7 @@ class Entry(Widget, XView): def scan_mark(self, x): ... def scan_dragto(self, x): ... def selection_adjust(self, index: _EntryIndex) -> None: ... - def selection_clear(self) -> None: ... # type: ignore + def selection_clear(self) -> None: ... # type: ignore[override] def selection_from(self, index: _EntryIndex) -> None: ... def selection_present(self) -> bool: ... def selection_range(self, start: _EntryIndex, end: _EntryIndex) -> None: ... @@ -1760,9 +1680,9 @@ class Frame(Widget): bg: _Color = ..., border: _ScreenUnits = ..., borderwidth: _ScreenUnits = ..., - class_: str = ..., - colormap: Literal["new", ""] | Misc = ..., - container: bool = ..., + class_: str = ..., # can't be changed with configure() + colormap: Literal["new", ""] | Misc = ..., # can't be changed with configure() + container: bool = ..., # can't be changed with configure() cursor: _Cursor = ..., height: _ScreenUnits = ..., highlightbackground: _Color = ..., @@ -1773,7 +1693,7 @@ class Frame(Widget): pady: _ScreenUnits = ..., relief: _Relief = ..., takefocus: _TakeFocusValue = ..., - visual: str | tuple[str, int] = ..., + visual: str | tuple[str, int] = ..., # can't be changed with configure() width: _ScreenUnits = ..., ) -> None: ... @overload @@ -1983,7 +1903,7 @@ class Listbox(Widget, XView, YView): def see(self, index): ... def selection_anchor(self, index): ... select_anchor: Any - def selection_clear(self, first, last: Any | None = ...): ... # type: ignore + def selection_clear(self, first, last: Any | None = ...): ... # type: ignore[override] select_clear: Any def selection_includes(self, index): ... select_includes: Any @@ -2730,7 +2650,7 @@ class Text(Widget, XView, YView): startline: int | Literal[""] = ..., state: Literal["normal", "disabled"] = ..., # Literal inside Tuple doesn't actually work - tabs: _ScreenUnits | str | Tuple[_ScreenUnits | str, ...] = ..., + tabs: _ScreenUnits | str | tuple[_ScreenUnits | str, ...] = ..., tabstyle: Literal["tabular", "wordprocessor"] = ..., takefocus: _TakeFocusValue = ..., undo: bool = ..., @@ -2781,7 +2701,7 @@ class Text(Widget, XView, YView): spacing3: _ScreenUnits = ..., startline: int | Literal[""] = ..., state: Literal["normal", "disabled"] = ..., - tabs: _ScreenUnits | str | Tuple[_ScreenUnits | str, ...] = ..., + tabs: _ScreenUnits | str | tuple[_ScreenUnits | str, ...] = ..., tabstyle: Literal["tabular", "wordprocessor"] = ..., takefocus: _TakeFocusValue = ..., undo: bool = ..., @@ -2793,7 +2713,7 @@ class Text(Widget, XView, YView): @overload def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure - def bbox(self, index: _TextIndex) -> tuple[int, int, int, int] | None: ... # type: ignore + def bbox(self, index: _TextIndex) -> tuple[int, int, int, int] | None: ... # type: ignore[override] def compare(self, index1: _TextIndex, op: Literal["<", "<=", "==", ">=", ">", "!="], index2: _TextIndex) -> bool: ... def count(self, index1, index2, *args): ... # TODO @overload @@ -2860,20 +2780,20 @@ class Text(Widget, XView, YView): def image_create(self, index, cnf=..., **kw): ... def image_names(self): ... def index(self, index: _TextIndex) -> str: ... - def insert(self, index: _TextIndex, chars: str, *args: str | list[str] | Tuple[str, ...]) -> None: ... + def insert(self, index: _TextIndex, chars: str, *args: str | list[str] | tuple[str, ...]) -> None: ... @overload def mark_gravity(self, markName: str, direction: None = ...) -> Literal["left", "right"]: ... @overload def mark_gravity(self, markName: str, direction: Literal["left", "right"]) -> None: ... # actually returns empty string - def mark_names(self) -> Tuple[str, ...]: ... + def mark_names(self) -> tuple[str, ...]: ... def mark_set(self, markName: str, index: _TextIndex) -> None: ... def mark_unset(self, *markNames: str) -> None: ... def mark_next(self, index: _TextIndex) -> str | None: ... def mark_previous(self, index: _TextIndex) -> str | None: ... # **kw of peer_create is same as the kwargs of Text.__init__ def peer_create(self, newPathName: str | Text, cnf: dict[str, Any] = ..., **kw: Any) -> None: ... - def peer_names(self) -> Tuple[_tkinter.Tcl_Obj, ...]: ... - def replace(self, index1: _TextIndex, index2: _TextIndex, chars: str, *args: str | list[str] | Tuple[str, ...]) -> None: ... + def peer_names(self) -> tuple[_tkinter.Tcl_Obj, ...]: ... + def replace(self, index1: _TextIndex, index2: _TextIndex, chars: str, *args: str | list[str] | tuple[str, ...]) -> None: ... def scan_mark(self, x: int, y: int) -> None: ... def scan_dragto(self, x: int, y: int) -> None: ... def search( @@ -2945,11 +2865,11 @@ class Text(Widget, XView, YView): tag_config = tag_configure def tag_delete(self, __first_tag_name: str, *tagNames: str) -> None: ... # error if no tag names given def tag_lower(self, tagName: str, belowThis: str | None = ...) -> None: ... - def tag_names(self, index: _TextIndex | None = ...) -> Tuple[str, ...]: ... + def tag_names(self, index: _TextIndex | None = ...) -> tuple[str, ...]: ... def tag_nextrange(self, tagName: str, index1: _TextIndex, index2: _TextIndex | None = ...) -> tuple[str, str] | tuple[()]: ... def tag_prevrange(self, tagName: str, index1: _TextIndex, index2: _TextIndex | None = ...) -> tuple[str, str] | tuple[()]: ... def tag_raise(self, tagName: str, aboveThis: str | None = ...) -> None: ... - def tag_ranges(self, tagName: str) -> Tuple[_tkinter.Tcl_Obj, ...]: ... + def tag_ranges(self, tagName: str) -> tuple[_tkinter.Tcl_Obj, ...]: ... # tag_remove and tag_delete are different def tag_remove(self, tagName: str, index1: _TextIndex, index2: _TextIndex | None = ...) -> None: ... # TODO: window_* methods @@ -3039,10 +2959,10 @@ class PhotoImage(Image): str | list[str] | list[list[_Color]] - | list[Tuple[_Color, ...]] - | Tuple[str, ...] - | Tuple[list[_Color], ...] - | Tuple[Tuple[_Color, ...], ...] + | list[tuple[_Color, ...]] + | tuple[str, ...] + | tuple[list[_Color], ...] + | tuple[tuple[_Color, ...], ...] ), to: tuple[int, int] | None = ..., ) -> None: ... @@ -3066,8 +2986,8 @@ class BitmapImage(Image): maskfile: StrOrBytesPath = ..., ) -> None: ... -def image_names() -> Tuple[str, ...]: ... -def image_types() -> Tuple[str, ...]: ... +def image_names() -> tuple[str, ...]: ... +def image_types() -> tuple[str, ...]: ... class Spinbox(Widget, XView): def __init__( @@ -3086,7 +3006,7 @@ class Spinbox(Widget, XView): buttondownrelief: _Relief = ..., buttonuprelief: _Relief = ..., # percent substitutions don't seem to be supported, it's similar to Entry's validation stuff - command: Callable[[], Any] | str | list[str] | Tuple[str, ...] = ..., + command: Callable[[], Any] | str | list[str] | tuple[str, ...] = ..., cursor: _Cursor = ..., disabledbackground: _Color = ..., disabledforeground: _Color = ..., @@ -3123,7 +3043,7 @@ class Spinbox(Widget, XView): validate: Literal["none", "focus", "focusin", "focusout", "key", "all"] = ..., validatecommand: _EntryValidateCommand = ..., vcmd: _EntryValidateCommand = ..., - values: list[str] | Tuple[str, ...] = ..., + values: list[str] | tuple[str, ...] = ..., width: int = ..., wrap: bool = ..., xscrollcommand: _XYScrollCommand = ..., @@ -3143,7 +3063,7 @@ class Spinbox(Widget, XView): buttoncursor: _Cursor = ..., buttondownrelief: _Relief = ..., buttonuprelief: _Relief = ..., - command: Callable[[], Any] | str | list[str] | Tuple[str, ...] = ..., + command: Callable[[], Any] | str | list[str] | tuple[str, ...] = ..., cursor: _Cursor = ..., disabledbackground: _Color = ..., disabledforeground: _Color = ..., @@ -3179,7 +3099,7 @@ class Spinbox(Widget, XView): validate: Literal["none", "focus", "focusin", "focusout", "key", "all"] = ..., validatecommand: _EntryValidateCommand = ..., vcmd: _EntryValidateCommand = ..., - values: list[str] | Tuple[str, ...] = ..., + values: list[str] | tuple[str, ...] = ..., width: int = ..., wrap: bool = ..., xscrollcommand: _XYScrollCommand = ..., @@ -3199,7 +3119,7 @@ class Spinbox(Widget, XView): def scan(self, *args): ... def scan_mark(self, x): ... def scan_dragto(self, x): ... - def selection(self, *args: Any) -> Tuple[int, ...]: ... + def selection(self, *args: Any) -> tuple[int, ...]: ... def selection_adjust(self, index): ... def selection_clear(self): ... def selection_element(self, element: Any | None = ...): ... @@ -3220,9 +3140,9 @@ class LabelFrame(Widget): bg: _Color = ..., border: _ScreenUnits = ..., borderwidth: _ScreenUnits = ..., - class_: str = ..., - colormap: Literal["new", ""] | Misc = ..., - container: bool = ..., # undocumented + class_: str = ..., # can't be changed with configure() + colormap: Literal["new", ""] | Misc = ..., # can't be changed with configure() + container: bool = ..., # undocumented, can't be changed with configure() cursor: _Cursor = ..., fg: _Color = ..., font: _FontDescription = ..., @@ -3240,7 +3160,7 @@ class LabelFrame(Widget): relief: _Relief = ..., takefocus: _TakeFocusValue = ..., text: float | str = ..., - visual: str | tuple[str, int] = ..., + visual: str | tuple[str, int] = ..., # can't be changed with configure() width: _ScreenUnits = ..., ) -> None: ... @overload diff --git a/mypy/typeshed/stdlib/tkinter/filedialog.pyi b/mypy/typeshed/stdlib/tkinter/filedialog.pyi index 0fc7d6e8a3bc1..b818d5e8253e5 100644 --- a/mypy/typeshed/stdlib/tkinter/filedialog.pyi +++ b/mypy/typeshed/stdlib/tkinter/filedialog.pyi @@ -1,6 +1,6 @@ from _typeshed import StrOrBytesPath from tkinter import Button, Entry, Frame, Listbox, Misc, Scrollbar, StringVar, Toplevel, commondialog -from typing import IO, Any, ClassVar, Iterable, Tuple +from typing import IO, Any, ClassVar, Iterable from typing_extensions import Literal dialogstates: dict[Any, tuple[Any, Any]] @@ -64,7 +64,7 @@ def asksaveasfilename( *, confirmoverwrite: bool | None = ..., defaultextension: str | None = ..., - filetypes: Iterable[tuple[str, str | list[str] | Tuple[str, ...]]] | None = ..., + filetypes: Iterable[tuple[str, str | list[str] | tuple[str, ...]]] | None = ..., initialdir: StrOrBytesPath | None = ..., initialfile: StrOrBytesPath | None = ..., parent: Misc | None = ..., @@ -74,7 +74,7 @@ def asksaveasfilename( def askopenfilename( *, defaultextension: str | None = ..., - filetypes: Iterable[tuple[str, str | list[str] | Tuple[str, ...]]] | None = ..., + filetypes: Iterable[tuple[str, str | list[str] | tuple[str, ...]]] | None = ..., initialdir: StrOrBytesPath | None = ..., initialfile: StrOrBytesPath | None = ..., parent: Misc | None = ..., @@ -84,13 +84,13 @@ def askopenfilename( def askopenfilenames( *, defaultextension: str | None = ..., - filetypes: Iterable[tuple[str, str | list[str] | Tuple[str, ...]]] | None = ..., + filetypes: Iterable[tuple[str, str | list[str] | tuple[str, ...]]] | None = ..., initialdir: StrOrBytesPath | None = ..., initialfile: StrOrBytesPath | None = ..., parent: Misc | None = ..., title: str | None = ..., typevariable: StringVar | str | None = ..., -) -> Literal[""] | Tuple[str, ...]: ... +) -> Literal[""] | tuple[str, ...]: ... def askdirectory( *, initialdir: StrOrBytesPath | None = ..., mustexist: bool | None = ..., parent: Misc | None = ..., title: str | None = ... ) -> str: ... # can be empty string @@ -101,7 +101,7 @@ def asksaveasfile( *, confirmoverwrite: bool | None = ..., defaultextension: str | None = ..., - filetypes: Iterable[tuple[str, str | list[str] | Tuple[str, ...]]] | None = ..., + filetypes: Iterable[tuple[str, str | list[str] | tuple[str, ...]]] | None = ..., initialdir: StrOrBytesPath | None = ..., initialfile: StrOrBytesPath | None = ..., parent: Misc | None = ..., @@ -112,7 +112,7 @@ def askopenfile( mode: str = ..., *, defaultextension: str | None = ..., - filetypes: Iterable[tuple[str, str | list[str] | Tuple[str, ...]]] | None = ..., + filetypes: Iterable[tuple[str, str | list[str] | tuple[str, ...]]] | None = ..., initialdir: StrOrBytesPath | None = ..., initialfile: StrOrBytesPath | None = ..., parent: Misc | None = ..., @@ -123,11 +123,11 @@ def askopenfiles( mode: str = ..., *, defaultextension: str | None = ..., - filetypes: Iterable[tuple[str, str | list[str] | Tuple[str, ...]]] | None = ..., + filetypes: Iterable[tuple[str, str | list[str] | tuple[str, ...]]] | None = ..., initialdir: StrOrBytesPath | None = ..., initialfile: StrOrBytesPath | None = ..., parent: Misc | None = ..., title: str | None = ..., typevariable: StringVar | str | None = ..., -) -> Tuple[IO[Any], ...]: ... # can be empty tuple +) -> tuple[IO[Any], ...]: ... # can be empty tuple def test() -> None: ... diff --git a/mypy/typeshed/stdlib/tkinter/font.pyi b/mypy/typeshed/stdlib/tkinter/font.pyi index fccc0fbf1f0a0..211e8ec9a0beb 100644 --- a/mypy/typeshed/stdlib/tkinter/font.pyi +++ b/mypy/typeshed/stdlib/tkinter/font.pyi @@ -1,7 +1,7 @@ import _tkinter import sys import tkinter -from typing import Any, List, Tuple, Union, overload +from typing import Any, Union, overload from typing_extensions import Literal, TypedDict NORMAL: Literal["normal"] @@ -15,8 +15,8 @@ _FontDescription = Union[ # A font object constructed in Python Font, # ("Helvetica", 12, BOLD) - List[Any], - Tuple[Any, ...], + list[Any], + tuple[Any, ...], # A font object constructed in Tcl _tkinter.Tcl_Obj, ] @@ -102,8 +102,8 @@ class Font: def metrics(self, *, displayof: tkinter.Misc | None = ...) -> _MetricsDict: ... def measure(self, text: str, displayof: tkinter.Misc | None = ...) -> int: ... -def families(root: tkinter.Misc | None = ..., displayof: tkinter.Misc | None = ...) -> Tuple[str, ...]: ... -def names(root: tkinter.Misc | None = ...) -> Tuple[str, ...]: ... +def families(root: tkinter.Misc | None = ..., displayof: tkinter.Misc | None = ...) -> tuple[str, ...]: ... +def names(root: tkinter.Misc | None = ...) -> tuple[str, ...]: ... if sys.version_info >= (3, 10): def nametofont(name: str, root: tkinter.Misc | None = ...) -> Font: ... diff --git a/mypy/typeshed/stdlib/tkinter/tix.pyi b/mypy/typeshed/stdlib/tkinter/tix.pyi index 3037212c0ad1e..6842ab7b1108d 100644 --- a/mypy/typeshed/stdlib/tkinter/tix.pyi +++ b/mypy/typeshed/stdlib/tkinter/tix.pyi @@ -1,5 +1,5 @@ import tkinter -from typing import Any, Tuple +from typing import Any from typing_extensions import Literal WINDOW: Literal["window"] @@ -194,7 +194,7 @@ class HList(TixWidget, tkinter.XView, tkinter.YView): def indicator_size(self, entry: str) -> int: ... def info_anchor(self) -> str: ... def info_bbox(self, entry: str) -> tuple[int, int, int, int]: ... - def info_children(self, entry: str | None = ...) -> Tuple[str, ...]: ... + def info_children(self, entry: str | None = ...) -> tuple[str, ...]: ... def info_data(self, entry: str) -> Any: ... def info_dragsite(self) -> str: ... def info_dropsite(self) -> str: ... @@ -203,7 +203,7 @@ class HList(TixWidget, tkinter.XView, tkinter.YView): def info_next(self, entry: str) -> str: ... def info_parent(self, entry: str) -> str: ... def info_prev(self, entry: str) -> str: ... - def info_selection(self) -> Tuple[str, ...]: ... + def info_selection(self) -> tuple[str, ...]: ... def item_cget(self, entry: str, col: int, opt: Any) -> Any: ... def item_configure(self, entry: str, col: int, cnf: dict[str, Any] = ..., **kw: Any) -> Any | None: ... def item_create(self, entry: str, col: int, cnf: dict[str, Any] = ..., **kw: Any) -> None: ... @@ -224,7 +224,7 @@ class CheckList(TixWidget): def close(self, entrypath: str) -> None: ... def getmode(self, entrypath: str) -> str: ... def open(self, entrypath: str) -> None: ... - def getselection(self, mode: str = ...) -> Tuple[str, ...]: ... + def getselection(self, mode: str = ...) -> tuple[str, ...]: ... def getstatus(self, entrypath: str) -> str: ... def setstatus(self, entrypath: str, mode: str = ...) -> None: ... @@ -253,7 +253,7 @@ class TList(TixWidget, tkinter.XView, tkinter.YView): def info_down(self, index: int) -> int: ... def info_left(self, index: int) -> int: ... def info_right(self, index: int) -> int: ... - def info_selection(self) -> Tuple[int, ...]: ... + def info_selection(self) -> tuple[int, ...]: ... def info_size(self) -> int: ... def info_up(self, index: int) -> int: ... def nearest(self, x: int, y: int) -> int: ... @@ -266,7 +266,7 @@ class PanedWindow(TixWidget): def __init__(self, master: tkinter.Widget | None, cnf: dict[str, Any] = ..., **kw: Any) -> None: ... def add(self, name: str, cnf: dict[str, Any] = ..., **kw: Any) -> None: ... def delete(self, name: str) -> None: ... - def forget(self, name: str) -> None: ... # type: ignore + def forget(self, name: str) -> None: ... # type: ignore[override] def panecget(self, entry: str, opt: Any) -> Any: ... def paneconfigure(self, entry: str, cnf: dict[str, Any] = ..., **kw: Any) -> Any | None: ... def panes(self) -> list[tkinter.Widget]: ... diff --git a/mypy/typeshed/stdlib/tkinter/ttk.pyi b/mypy/typeshed/stdlib/tkinter/ttk.pyi index be0713ec2e4b8..f7319291da6da 100644 --- a/mypy/typeshed/stdlib/tkinter/ttk.pyi +++ b/mypy/typeshed/stdlib/tkinter/ttk.pyi @@ -2,7 +2,7 @@ import _tkinter import sys import tkinter from tkinter.font import _FontDescription -from typing import Any, Callable, Tuple, Union, overload +from typing import Any, Callable, Union, overload from typing_extensions import Literal, TypedDict def tclobjs_to_py(adict): ... @@ -24,7 +24,7 @@ class Style: def element_options(self, elementname): ... def theme_create(self, themename, parent: Any | None = ..., settings: Any | None = ...): ... def theme_settings(self, themename, settings): ... - def theme_names(self) -> Tuple[str, ...]: ... + def theme_names(self) -> tuple[str, ...]: ... @overload def theme_use(self, themename: str) -> None: ... @overload @@ -158,7 +158,7 @@ class Entry(Widget, tkinter.Entry): width: int = ..., xscrollcommand: tkinter._XYScrollCommand = ..., ) -> None: ... - @overload # type: ignore + @overload # type: ignore[override] def configure( self, cnf: dict[str, Any] | None = ..., @@ -183,7 +183,7 @@ class Entry(Widget, tkinter.Entry): @overload def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... # config must be copy/pasted, otherwise ttk.Entry().config is mypy error (don't know why) - @overload # type: ignore + @overload # type: ignore[override] def config( self, cnf: dict[str, Any] | None = ..., @@ -234,11 +234,11 @@ class Combobox(Entry): textvariable: tkinter.Variable = ..., validate: Literal["none", "focus", "focusin", "focusout", "key", "all"] = ..., # undocumented validatecommand: tkinter._EntryValidateCommand = ..., # undocumented - values: list[str] | Tuple[str, ...] = ..., + values: list[str] | tuple[str, ...] = ..., width: int = ..., xscrollcommand: tkinter._XYScrollCommand = ..., # undocumented ) -> None: ... - @overload # type: ignore + @overload # type: ignore[override] def configure( self, cnf: dict[str, Any] | None = ..., @@ -259,14 +259,14 @@ class Combobox(Entry): textvariable: tkinter.Variable = ..., validate: Literal["none", "focus", "focusin", "focusout", "key", "all"] = ..., validatecommand: tkinter._EntryValidateCommand = ..., - values: list[str] | Tuple[str, ...] = ..., + values: list[str] | tuple[str, ...] = ..., width: int = ..., xscrollcommand: tkinter._XYScrollCommand = ..., ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... # config must be copy/pasted, otherwise ttk.Combobox().config is mypy error (don't know why) - @overload # type: ignore + @overload # type: ignore[override] def config( self, cnf: dict[str, Any] | None = ..., @@ -287,7 +287,7 @@ class Combobox(Entry): textvariable: tkinter.Variable = ..., validate: Literal["none", "focus", "focusin", "focusout", "key", "all"] = ..., validatecommand: tkinter._EntryValidateCommand = ..., - values: list[str] | Tuple[str, ...] = ..., + values: list[str] | tuple[str, ...] = ..., width: int = ..., xscrollcommand: tkinter._XYScrollCommand = ..., ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @@ -541,13 +541,13 @@ class Panedwindow(Widget, tkinter.PanedWindow): # width and height for tkinter.ttk.Panedwindow are int but for tkinter.PanedWindow they are screen units height: int = ..., name: str = ..., - orient: Literal["vertical", "horizontal"] = ..., + orient: Literal["vertical", "horizontal"] = ..., # can't be changed with configure() style: str = ..., takefocus: tkinter._TakeFocusValue = ..., width: int = ..., ) -> None: ... def add(self, child: tkinter.Widget, *, weight: int = ..., **kw) -> None: ... - @overload # type: ignore + @overload # type: ignore[override] def configure( self, cnf: dict[str, Any] | None = ..., @@ -561,7 +561,7 @@ class Panedwindow(Widget, tkinter.PanedWindow): @overload def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... # config must be copy/pasted, otherwise ttk.Panedwindow().config is mypy error (don't know why) - @overload # type: ignore + @overload # type: ignore[override] def config( self, cnf: dict[str, Any] | None = ..., @@ -688,7 +688,7 @@ class Scale(Widget, tkinter.Scale): value: float = ..., variable: tkinter.IntVar | tkinter.DoubleVar = ..., ) -> None: ... - @overload # type: ignore + @overload # type: ignore[override] def configure( self, cnf: dict[str, Any] | None = ..., @@ -708,7 +708,7 @@ class Scale(Widget, tkinter.Scale): @overload def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... # config must be copy/pasted, otherwise ttk.Scale().config is mypy error (don't know why) - @overload # type: ignore + @overload # type: ignore[override] def config( self, cnf: dict[str, Any] | None = ..., @@ -742,7 +742,7 @@ class Scrollbar(Widget, tkinter.Scrollbar): style: str = ..., takefocus: tkinter._TakeFocusValue = ..., ) -> None: ... - @overload # type: ignore + @overload # type: ignore[override] def configure( self, cnf: dict[str, Any] | None = ..., @@ -756,7 +756,7 @@ class Scrollbar(Widget, tkinter.Scrollbar): @overload def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... # config must be copy/pasted, otherwise ttk.Scrollbar().config is mypy error (don't know why) - @overload # type: ignore + @overload # type: ignore[override] def config( self, cnf: dict[str, Any] | None = ..., @@ -828,7 +828,7 @@ if sys.version_info >= (3, 7): *, background: tkinter._Color = ..., # undocumented class_: str = ..., - command: Callable[[], Any] | str | list[str] | Tuple[str, ...] = ..., + command: Callable[[], Any] | str | list[str] | tuple[str, ...] = ..., cursor: tkinter._Cursor = ..., exportselection: bool = ..., # undocumented font: _FontDescription = ..., # undocumented @@ -847,18 +847,18 @@ if sys.version_info >= (3, 7): to: float = ..., validate: Literal["none", "focus", "focusin", "focusout", "key", "all"] = ..., validatecommand: tkinter._EntryValidateCommand = ..., - values: list[str] | Tuple[str, ...] = ..., + values: list[str] | tuple[str, ...] = ..., width: int = ..., # undocumented wrap: bool = ..., xscrollcommand: tkinter._XYScrollCommand = ..., ) -> None: ... - @overload # type: ignore + @overload # type: ignore[override] def configure( self, cnf: dict[str, Any] | None = ..., *, background: tkinter._Color = ..., - command: Callable[[], Any] | str | list[str] | Tuple[str, ...] = ..., + command: Callable[[], Any] | str | list[str] | tuple[str, ...] = ..., cursor: tkinter._Cursor = ..., exportselection: bool = ..., font: _FontDescription = ..., @@ -876,14 +876,14 @@ if sys.version_info >= (3, 7): to: float = ..., validate: Literal["none", "focus", "focusin", "focusout", "key", "all"] = ..., validatecommand: tkinter._EntryValidateCommand = ..., - values: list[str] | Tuple[str, ...] = ..., + values: list[str] | tuple[str, ...] = ..., width: int = ..., wrap: bool = ..., xscrollcommand: tkinter._XYScrollCommand = ..., ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... - config = configure # type: ignore + config = configure # type: ignore[assignment] def set(self, value: Any) -> None: ... class _TreeviewItemDict(TypedDict): @@ -922,9 +922,9 @@ class Treeview(Widget, tkinter.XView, tkinter.YView): master: tkinter.Misc | None = ..., *, class_: str = ..., - columns: str | list[str] | Tuple[str, ...] = ..., + columns: str | list[str] | tuple[str, ...] = ..., cursor: tkinter._Cursor = ..., - displaycolumns: str | list[str] | Tuple[str, ...] | list[int] | Tuple[int, ...] | Literal["#all"] = ..., + displaycolumns: str | list[str] | tuple[str, ...] | list[int] | tuple[int, ...] | Literal["#all"] = ..., height: int = ..., name: str = ..., padding: tkinter._Padding = ..., @@ -933,7 +933,7 @@ class Treeview(Widget, tkinter.XView, tkinter.YView): # # 'tree headings' is same as ['tree', 'headings'], and I wouldn't be # surprised if someone is using it. - show: Literal["tree", "headings", "tree headings", ""] | list[str] | Tuple[str, ...] = ..., + show: Literal["tree", "headings", "tree headings", ""] | list[str] | tuple[str, ...] = ..., style: str = ..., takefocus: tkinter._TakeFocusValue = ..., xscrollcommand: tkinter._XYScrollCommand = ..., @@ -944,13 +944,13 @@ class Treeview(Widget, tkinter.XView, tkinter.YView): self, cnf: dict[str, Any] | None = ..., *, - columns: str | list[str] | Tuple[str, ...] = ..., + columns: str | list[str] | tuple[str, ...] = ..., cursor: tkinter._Cursor = ..., - displaycolumns: str | list[str] | Tuple[str, ...] | list[int] | Tuple[int, ...] | Literal["#all"] = ..., + displaycolumns: str | list[str] | tuple[str, ...] | list[int] | tuple[int, ...] | Literal["#all"] = ..., height: int = ..., padding: tkinter._Padding = ..., selectmode: Literal["extended", "browse", "none"] = ..., - show: Literal["tree", "headings", "tree headings", ""] | list[str] | Tuple[str, ...] = ..., + show: Literal["tree", "headings", "tree headings", ""] | list[str] | tuple[str, ...] = ..., style: str = ..., takefocus: tkinter._TakeFocusValue = ..., xscrollcommand: tkinter._XYScrollCommand = ..., @@ -959,8 +959,8 @@ class Treeview(Widget, tkinter.XView, tkinter.YView): @overload def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure - def bbox(self, item, column: _TreeviewColumnId | None = ...) -> tuple[int, int, int, int] | Literal[""]: ... # type: ignore - def get_children(self, item: str | None = ...) -> Tuple[str, ...]: ... + def bbox(self, item, column: _TreeviewColumnId | None = ...) -> tuple[int, int, int, int] | Literal[""]: ... # type: ignore[override] + def get_children(self, item: str | None = ...) -> tuple[str, ...]: ... def set_children(self, item: str, *newchildren: str) -> None: ... @overload def column(self, column: _TreeviewColumnId, option: Literal["width", "minwidth"]) -> int: ... @@ -987,7 +987,7 @@ class Treeview(Widget, tkinter.XView, tkinter.YView): def delete(self, *items: str) -> None: ... def detach(self, *items: str) -> None: ... def exists(self, item: str) -> bool: ... - @overload # type: ignore + @overload # type: ignore[override] def focus(self, item: None = ...) -> str: ... # can return empty string @overload def focus(self, item: str) -> Literal[""]: ... @@ -1027,20 +1027,20 @@ class Treeview(Widget, tkinter.XView, tkinter.YView): id: str = ..., # same as iid text: str = ..., image: tkinter._ImageSpec = ..., - values: list[Any] | Tuple[Any, ...] = ..., + values: list[Any] | tuple[Any, ...] = ..., open: bool = ..., - tags: str | list[str] | Tuple[str, ...] = ..., + tags: str | list[str] | tuple[str, ...] = ..., ) -> str: ... @overload def item(self, item: str, option: Literal["text"]) -> str: ... @overload def item(self, item: str, option: Literal["image"]) -> tuple[str] | Literal[""]: ... @overload - def item(self, item: str, option: Literal["values"]) -> Tuple[Any, ...] | Literal[""]: ... + def item(self, item: str, option: Literal["values"]) -> tuple[Any, ...] | Literal[""]: ... @overload def item(self, item: str, option: Literal["open"]) -> bool: ... # actually 0 or 1 @overload - def item(self, item: str, option: Literal["tags"]) -> Tuple[str, ...] | Literal[""]: ... + def item(self, item: str, option: Literal["tags"]) -> tuple[str, ...] | Literal[""]: ... @overload def item(self, item: str, option: str) -> Any: ... @overload @@ -1051,9 +1051,9 @@ class Treeview(Widget, tkinter.XView, tkinter.YView): *, text: str = ..., image: tkinter._ImageSpec = ..., - values: list[Any] | Tuple[Any, ...] | Literal[""] = ..., + values: list[Any] | tuple[Any, ...] | Literal[""] = ..., open: bool = ..., - tags: str | list[str] | Tuple[str, ...] = ..., + tags: str | list[str] | tuple[str, ...] = ..., ) -> _TreeviewItemDict | None: ... def move(self, item: str, parent: str, index: int) -> None: ... reattach = move @@ -1062,13 +1062,13 @@ class Treeview(Widget, tkinter.XView, tkinter.YView): def prev(self, item: str) -> str: ... # returning empty string means first item def see(self, item: str) -> None: ... if sys.version_info >= (3, 8): - def selection(self) -> Tuple[str, ...]: ... + def selection(self) -> tuple[str, ...]: ... else: - def selection(self, selop: Any | None = ..., items: Any | None = ...) -> Tuple[str, ...]: ... - def selection_set(self, items: str | list[str] | Tuple[str, ...]) -> None: ... - def selection_add(self, items: str | list[str] | Tuple[str, ...]) -> None: ... - def selection_remove(self, items: str | list[str] | Tuple[str, ...]) -> None: ... - def selection_toggle(self, items: str | list[str] | Tuple[str, ...]) -> None: ... + def selection(self, selop: Any | None = ..., items: Any | None = ...) -> tuple[str, ...]: ... + def selection_set(self, items: str | list[str] | tuple[str, ...]) -> None: ... + def selection_add(self, items: str | list[str] | tuple[str, ...]) -> None: ... + def selection_remove(self, items: str | list[str] | tuple[str, ...]) -> None: ... + def selection_toggle(self, items: str | list[str] | tuple[str, ...]) -> None: ... @overload def set(self, item: str, column: None = ..., value: None = ...) -> dict[str, Any]: ... @overload @@ -1104,7 +1104,7 @@ class Treeview(Widget, tkinter.XView, tkinter.YView): image: tkinter._ImageSpec = ..., ) -> _TreeviewTagDict | Any: ... # can be None but annoying to check @overload - def tag_has(self, tagname: str, item: None = ...) -> Tuple[str, ...]: ... + def tag_has(self, tagname: str, item: None = ...) -> tuple[str, ...]: ... @overload def tag_has(self, tagname: str, item: str) -> bool: ... diff --git a/mypy/typeshed/stdlib/token.pyi b/mypy/typeshed/stdlib/token.pyi index 90381833511bb..9451015e9df50 100644 --- a/mypy/typeshed/stdlib/token.pyi +++ b/mypy/typeshed/stdlib/token.pyi @@ -71,6 +71,8 @@ if sys.version_info >= (3, 8): TYPE_IGNORE: int COLONEQUAL: int EXACT_TOKEN_TYPES: dict[str, int] +if sys.version_info >= (3, 10): + SOFT_KEYWORD: int def ISTERMINAL(x: int) -> bool: ... def ISNONTERMINAL(x: int) -> bool: ... diff --git a/mypy/typeshed/stdlib/tokenize.pyi b/mypy/typeshed/stdlib/tokenize.pyi index a8294adb653f1..7614ebfe403e0 100644 --- a/mypy/typeshed/stdlib/tokenize.pyi +++ b/mypy/typeshed/stdlib/tokenize.pyi @@ -2,7 +2,7 @@ import sys from _typeshed import StrOrBytesPath from builtins import open as _builtin_open from token import * # noqa: F403 -from typing import Any, Callable, Generator, Iterable, NamedTuple, Pattern, Sequence, TextIO, Tuple, Union +from typing import Any, Callable, Generator, Iterable, NamedTuple, Pattern, Sequence, TextIO, Union if sys.version_info < (3, 7): COMMENT: int @@ -12,7 +12,7 @@ if sys.version_info < (3, 7): cookie_re: Pattern[str] blank_re: Pattern[bytes] -_Position = Tuple[int, int] +_Position = tuple[int, int] class _TokenInfo(NamedTuple): type: int diff --git a/mypy/typeshed/stdlib/trace.pyi b/mypy/typeshed/stdlib/trace.pyi index bab75c9ada8d7..ee8dffa678208 100644 --- a/mypy/typeshed/stdlib/trace.pyi +++ b/mypy/typeshed/stdlib/trace.pyi @@ -1,13 +1,13 @@ import sys import types from _typeshed import StrPath -from typing import Any, Callable, Mapping, Optional, Sequence, Tuple, TypeVar +from typing import Any, Callable, Mapping, Optional, Sequence, TypeVar from typing_extensions import ParamSpec _T = TypeVar("_T") _P = ParamSpec("_P") _localtrace = Callable[[types.FrameType, str, Any], Callable[..., Any]] -_fileModuleFunction = Tuple[str, Optional[str], str] +_fileModuleFunction = tuple[str, Optional[str], str] class CoverageResults: def __init__( @@ -43,9 +43,9 @@ class Trace: self, cmd: str | types.CodeType, globals: Mapping[str, Any] | None = ..., locals: Mapping[str, Any] | None = ... ) -> None: ... if sys.version_info >= (3, 9): - def runfunc(self, __func: Callable[_P, _T], *args: _P.args, **kw: _P.kwargs) -> _T: ... # type: ignore + def runfunc(self, __func: Callable[_P, _T], *args: _P.args, **kw: _P.kwargs) -> _T: ... else: - def runfunc(self, func: Callable[_P, _T], *args: _P.args, **kw: _P.kwargs) -> _T: ... # type: ignore + def runfunc(self, func: Callable[_P, _T], *args: _P.args, **kw: _P.kwargs) -> _T: ... def file_module_function_of(self, frame: types.FrameType) -> _fileModuleFunction: ... def globaltrace_trackcallers(self, frame: types.FrameType, why: str, arg: Any) -> None: ... def globaltrace_countfuncs(self, frame: types.FrameType, why: str, arg: Any) -> None: ... diff --git a/mypy/typeshed/stdlib/traceback.pyi b/mypy/typeshed/stdlib/traceback.pyi index e685b09a6ae49..4e36490c24e4f 100644 --- a/mypy/typeshed/stdlib/traceback.pyi +++ b/mypy/typeshed/stdlib/traceback.pyi @@ -1,13 +1,14 @@ import sys from _typeshed import SupportsWrite from types import FrameType, TracebackType -from typing import IO, Any, Generator, Iterable, Iterator, List, Mapping, Optional, Tuple, Type +from typing import IO, Any, Generator, Iterable, Iterator, Mapping, Optional, Type, overload -_PT = Tuple[str, int, str, Optional[str]] +_PT = tuple[str, int, str, Optional[str]] def print_tb(tb: TracebackType | None, limit: int | None = ..., file: IO[str] | None = ...) -> None: ... if sys.version_info >= (3, 10): + @overload def print_exception( __exc: Type[BaseException] | None, value: BaseException | None = ..., @@ -16,6 +17,20 @@ if sys.version_info >= (3, 10): file: IO[str] | None = ..., chain: bool = ..., ) -> None: ... + @overload + def print_exception( + __exc: BaseException, *, limit: int | None = ..., file: IO[str] | None = ..., chain: bool = ... + ) -> None: ... + @overload + def format_exception( + __exc: Type[BaseException] | None, + value: BaseException | None = ..., + tb: TracebackType | None = ..., + limit: int | None = ..., + chain: bool = ..., + ) -> list[str]: ... + @overload + def format_exception(__exc: BaseException, *, limit: int | None = ..., chain: bool = ...) -> list[str]: ... else: def print_exception( @@ -26,6 +41,13 @@ else: file: IO[str] | None = ..., chain: bool = ..., ) -> None: ... + def format_exception( + etype: Type[BaseException] | None, + value: BaseException | None, + tb: TracebackType | None, + limit: int | None = ..., + chain: bool = ..., + ) -> list[str]: ... def print_exc(limit: int | None = ..., file: IO[str] | None = ..., chain: bool = ...) -> None: ... def print_last(limit: int | None = ..., file: IO[str] | None = ..., chain: bool = ...) -> None: ... @@ -43,24 +65,6 @@ if sys.version_info >= (3, 10): else: def format_exception_only(etype: Type[BaseException] | None, value: BaseException | None) -> list[str]: ... -if sys.version_info >= (3, 10): - def format_exception( - __exc: Type[BaseException] | None, - value: BaseException | None = ..., - tb: TracebackType | None = ..., - limit: int | None = ..., - chain: bool = ..., - ) -> list[str]: ... - -else: - def format_exception( - etype: Type[BaseException] | None, - value: BaseException | None, - tb: TracebackType | None, - limit: int | None = ..., - chain: bool = ..., - ) -> list[str]: ... - def format_exc(limit: int | None = ..., chain: bool = ...) -> str: ... def format_tb(tb: TracebackType | None, limit: int | None = ...) -> list[str]: ... def format_stack(f: FrameType | None = ..., limit: int | None = ...) -> list[str]: ... @@ -84,7 +88,7 @@ class TracebackException: self, exc_type: Type[BaseException], exc_value: BaseException, - exc_traceback: TracebackType, + exc_traceback: TracebackType | None, *, limit: int | None = ..., lookup_lines: bool = ..., @@ -107,7 +111,7 @@ class TracebackException: self, exc_type: Type[BaseException], exc_value: BaseException, - exc_traceback: TracebackType, + exc_traceback: TracebackType | None, *, limit: int | None = ..., lookup_lines: bool = ..., @@ -142,7 +146,7 @@ class FrameSummary(Iterable[Any]): def __getitem__(self, i: int) -> Any: ... def __iter__(self) -> Iterator[Any]: ... -class StackSummary(List[FrameSummary]): +class StackSummary(list[FrameSummary]): @classmethod def extract( cls, diff --git a/mypy/typeshed/stdlib/tracemalloc.pyi b/mypy/typeshed/stdlib/tracemalloc.pyi index ca4d5901b870f..4d7bbb7994a61 100644 --- a/mypy/typeshed/stdlib/tracemalloc.pyi +++ b/mypy/typeshed/stdlib/tracemalloc.pyi @@ -1,6 +1,7 @@ import sys from _tracemalloc import * -from typing import Optional, Sequence, Tuple, Union, overload +from typing import Optional, Sequence, Union, overload +from typing_extensions import SupportsIndex def get_object_traceback(obj: object) -> Traceback | None: ... def take_snapshot() -> Snapshot: ... @@ -34,7 +35,7 @@ class StatisticDiff: traceback: Traceback def __init__(self, traceback: Traceback, size: int, size_diff: int, count: int, count_diff: int) -> None: ... -_FrameTupleT = Tuple[str, int] +_FrameTupleT = tuple[str, int] class Frame: filename: str @@ -42,9 +43,9 @@ class Frame: def __init__(self, frame: _FrameTupleT) -> None: ... if sys.version_info >= (3, 9): - _TraceTupleT = Union[Tuple[int, int, Sequence[_FrameTupleT], Optional[int]], Tuple[int, int, Sequence[_FrameTupleT]]] + _TraceTupleT = Union[tuple[int, int, Sequence[_FrameTupleT], Optional[int]], tuple[int, int, Sequence[_FrameTupleT]]] else: - _TraceTupleT = Tuple[int, int, Sequence[_FrameTupleT]] + _TraceTupleT = tuple[int, int, Sequence[_FrameTupleT]] class Trace: domain: int @@ -63,7 +64,7 @@ class Traceback(Sequence[Frame]): else: def format(self, limit: int | None = ...) -> list[str]: ... @overload - def __getitem__(self, i: int) -> Frame: ... + def __getitem__(self, i: SupportsIndex) -> Frame: ... @overload def __getitem__(self, s: slice) -> Sequence[Frame]: ... def __len__(self) -> int: ... diff --git a/mypy/typeshed/stdlib/tty.pyi b/mypy/typeshed/stdlib/tty.pyi index c0dc418e9933c..015669a680846 100644 --- a/mypy/typeshed/stdlib/tty.pyi +++ b/mypy/typeshed/stdlib/tty.pyi @@ -1,15 +1,16 @@ +import sys from typing import IO, Union -_FD = Union[int, IO[str]] +if sys.platform != "win32": + _FD = Union[int, IO[str]] -# XXX: Undocumented integer constants -IFLAG: int -OFLAG: int -CFLAG: int -LFLAG: int -ISPEED: int -OSPEED: int -CC: int - -def setraw(fd: _FD, when: int = ...) -> None: ... -def setcbreak(fd: _FD, when: int = ...) -> None: ... + # XXX: Undocumented integer constants + IFLAG: int + OFLAG: int + CFLAG: int + LFLAG: int + ISPEED: int + OSPEED: int + CC: int + def setraw(fd: _FD, when: int = ...) -> None: ... + def setcbreak(fd: _FD, when: int = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/turtle.pyi b/mypy/typeshed/stdlib/turtle.pyi index 9371f2a7a547b..e5efcb4f6ed91 100644 --- a/mypy/typeshed/stdlib/turtle.pyi +++ b/mypy/typeshed/stdlib/turtle.pyi @@ -1,24 +1,26 @@ -from tkinter import Canvas, PhotoImage -from typing import Any, Callable, Dict, Sequence, Tuple, TypeVar, Union, overload +from tkinter import Canvas, Frame, PhotoImage +from typing import Any, Callable, ClassVar, Sequence, TypeVar, Union, overload # Note: '_Color' is the alias we use for arguments and _AnyColor is the # alias we use for return types. Really, these two aliases should be the # same, but as per the "no union returns" typeshed policy, we'll return # Any instead. -_Color = Union[str, Tuple[float, float, float]] +_Color = Union[str, tuple[float, float, float]] _AnyColor = Any # TODO: Replace this with a TypedDict once it becomes standardized. -_PenState = Dict[str, Any] +_PenState = dict[str, Any] _Speed = Union[str, float] -_PolygonCoords = Sequence[Tuple[float, float]] +_PolygonCoords = Sequence[tuple[float, float]] # TODO: Type this more accurately # Vec2D is actually a custom subclass of 'tuple'. -Vec2D = Tuple[float, float] +Vec2D = tuple[float, float] -class TurtleScreenBase(object): +class ScrolledCanvas(Frame): ... + +class TurtleScreenBase: cv: Canvas canvwidth: int canvheight: int @@ -34,7 +36,7 @@ class TurtleScreenBase(object): class Terminator(Exception): ... class TurtleGraphicsError(Exception): ... -class Shape(object): +class Shape: def __init__(self, type_: str, data: _PolygonCoords | PhotoImage | None = ...) -> None: ... def addcomponent(self, poly: _PolygonCoords, fill: _Color, outline: _Color | None = ...) -> None: ... @@ -92,7 +94,7 @@ class TurtleScreen(TurtleScreenBase): def onkeypress(self, fun: Callable[[], Any], key: str | None = ...) -> None: ... onkeyrelease = onkey -class TNavigator(object): +class TNavigator: START_ORIENTATION: dict[str, Vec2D] DEFAULT_MODE: str DEFAULT_ANGLEOFFSET: int @@ -136,7 +138,7 @@ class TNavigator(object): setposition = goto seth = setheading -class TPen(object): +class TPen: def __init__(self, resizemode: str = ...) -> None: ... @overload def resizemode(self, rmode: None = ...) -> str: ... @@ -178,7 +180,7 @@ class TPen(object): def isvisible(self) -> bool: ... # Note: signatures 1 and 2 overlap unsafely when no arguments are provided @overload - def pen(self) -> _PenState: ... # type: ignore + def pen(self) -> _PenState: ... # type: ignore[misc] @overload def pen( self, @@ -206,6 +208,8 @@ class TPen(object): _T = TypeVar("_T") class RawTurtle(TPen, TNavigator): + screen: TurtleScreen + screens: ClassVar[list[TurtleScreen]] def __init__( self, canvas: Canvas | TurtleScreen | None = ..., shape: str = ..., undobuffersize: int = ..., visible: bool = ... ) -> None: ... @@ -220,7 +224,7 @@ class RawTurtle(TPen, TNavigator): def shape(self, name: str) -> None: ... # Unsafely overlaps when no arguments are provided @overload - def shapesize(self) -> tuple[float, float, float]: ... # type: ignore + def shapesize(self) -> tuple[float, float, float]: ... # type: ignore[misc] @overload def shapesize( self, stretch_wid: float | None = ..., stretch_len: float | None = ..., outline: float | None = ... @@ -231,7 +235,7 @@ class RawTurtle(TPen, TNavigator): def shearfactor(self, shear: float) -> None: ... # Unsafely overlaps when no arguments are provided @overload - def shapetransform(self) -> tuple[float, float, float, float]: ... # type: ignore + def shapetransform(self) -> tuple[float, float, float, float]: ... # type: ignore[misc] @overload def shapetransform( self, t11: float | None = ..., t12: float | None = ..., t21: float | None = ..., t22: float | None = ... @@ -247,7 +251,7 @@ class RawTurtle(TPen, TNavigator): # a compound stamp or not. So, as per the "no Union return" policy, # we return Any. def stamp(self) -> Any: ... - def clearstamp(self, stampid: int | Tuple[int, ...]) -> None: ... + def clearstamp(self, stampid: int | tuple[int, ...]) -> None: ... def clearstamps(self, n: int | None = ...) -> None: ... def filling(self) -> bool: ... def begin_fill(self) -> None: ... @@ -449,7 +453,7 @@ def isvisible() -> bool: ... # Note: signatures 1 and 2 overlap unsafely when no arguments are provided @overload -def pen() -> _PenState: ... # type: ignore +def pen() -> _PenState: ... # type: ignore[misc] @overload def pen( pen: _PenState | None = ..., @@ -485,7 +489,7 @@ def shape(name: str) -> None: ... # Unsafely overlaps when no arguments are provided @overload -def shapesize() -> tuple[float, float, float]: ... # type: ignore +def shapesize() -> tuple[float, float, float]: ... # type: ignore[misc] @overload def shapesize(stretch_wid: float | None = ..., stretch_len: float | None = ..., outline: float | None = ...) -> None: ... @overload @@ -495,7 +499,7 @@ def shearfactor(shear: float) -> None: ... # Unsafely overlaps when no arguments are provided @overload -def shapetransform() -> tuple[float, float, float, float]: ... # type: ignore +def shapetransform() -> tuple[float, float, float, float]: ... # type: ignore[misc] @overload def shapetransform( t11: float | None = ..., t12: float | None = ..., t21: float | None = ..., t22: float | None = ... @@ -512,7 +516,7 @@ def tilt(angle: float) -> None: ... # a compound stamp or not. So, as per the "no Union return" policy, # we return Any. def stamp() -> Any: ... -def clearstamp(stampid: int | Tuple[int, ...]) -> None: ... +def clearstamp(stampid: int | tuple[int, ...]) -> None: ... def clearstamps(n: int | None = ...) -> None: ... def filling() -> bool: ... def begin_fill() -> None: ... diff --git a/mypy/typeshed/stdlib/types.pyi b/mypy/typeshed/stdlib/types.pyi index 899024f2dd4db..92f8daa7ebed8 100644 --- a/mypy/typeshed/stdlib/types.pyi +++ b/mypy/typeshed/stdlib/types.pyi @@ -1,4 +1,5 @@ import sys +from _typeshed import SupportsKeysAndGetItem from importlib.abc import _LoaderProtocol from importlib.machinery import ModuleSpec from typing import ( @@ -15,7 +16,6 @@ from typing import ( KeysView, Mapping, MutableSequence, - Tuple, Type, TypeVar, ValuesView, @@ -36,14 +36,15 @@ _V_co = TypeVar("_V_co", covariant=True) @final class _Cell: - __hash__: None # type: ignore + __hash__: None # type: ignore[assignment] cell_contents: Any +# Make sure this class definition stays roughly in line with `builtins.function` @final class FunctionType: - __closure__: Tuple[_Cell, ...] | None + __closure__: tuple[_Cell, ...] | None __code__: CodeType - __defaults__: Tuple[Any, ...] | None + __defaults__: tuple[Any, ...] | None __dict__: dict[str, Any] __globals__: dict[str, Any] __name__: str @@ -55,11 +56,11 @@ class FunctionType: code: CodeType, globals: dict[str, Any], name: str | None = ..., - argdefs: Tuple[object, ...] | None = ..., - closure: Tuple[_Cell, ...] | None = ..., + argdefs: tuple[object, ...] | None = ..., + closure: tuple[_Cell, ...] | None = ..., ) -> None: ... def __call__(self, *args: Any, **kwargs: Any) -> Any: ... - def __get__(self, obj: object | None, type: type | None) -> MethodType: ... + def __get__(self, obj: object | None, type: type | None = ...) -> MethodType: ... LambdaType = FunctionType @@ -75,15 +76,15 @@ class CodeType: co_stacksize: int co_flags: int co_code: bytes - co_consts: Tuple[Any, ...] - co_names: Tuple[str, ...] - co_varnames: Tuple[str, ...] + co_consts: tuple[Any, ...] + co_names: tuple[str, ...] + co_varnames: tuple[str, ...] co_filename: str co_name: str co_firstlineno: int co_lnotab: bytes - co_freevars: Tuple[str, ...] - co_cellvars: Tuple[str, ...] + co_freevars: tuple[str, ...] + co_cellvars: tuple[str, ...] if sys.version_info >= (3, 8): def __init__( self, @@ -94,15 +95,15 @@ class CodeType: stacksize: int, flags: int, codestring: bytes, - constants: Tuple[Any, ...], - names: Tuple[str, ...], - varnames: Tuple[str, ...], + constants: tuple[Any, ...], + names: tuple[str, ...], + varnames: tuple[str, ...], filename: str, name: str, firstlineno: int, lnotab: bytes, - freevars: Tuple[str, ...] = ..., - cellvars: Tuple[str, ...] = ..., + freevars: tuple[str, ...] = ..., + cellvars: tuple[str, ...] = ..., ) -> None: ... else: def __init__( @@ -113,17 +114,40 @@ class CodeType: stacksize: int, flags: int, codestring: bytes, - constants: Tuple[Any, ...], - names: Tuple[str, ...], - varnames: Tuple[str, ...], + constants: tuple[Any, ...], + names: tuple[str, ...], + varnames: tuple[str, ...], filename: str, name: str, firstlineno: int, lnotab: bytes, - freevars: Tuple[str, ...] = ..., - cellvars: Tuple[str, ...] = ..., + freevars: tuple[str, ...] = ..., + cellvars: tuple[str, ...] = ..., ) -> None: ... - if sys.version_info >= (3, 8): + if sys.version_info >= (3, 10): + def replace( + self, + *, + co_argcount: int = ..., + co_posonlyargcount: int = ..., + co_kwonlyargcount: int = ..., + co_nlocals: int = ..., + co_stacksize: int = ..., + co_flags: int = ..., + co_firstlineno: int = ..., + co_code: bytes = ..., + co_consts: tuple[Any, ...] = ..., + co_names: tuple[str, ...] = ..., + co_varnames: tuple[str, ...] = ..., + co_freevars: tuple[str, ...] = ..., + co_cellvars: tuple[str, ...] = ..., + co_filename: str = ..., + co_name: str = ..., + co_linetable: object = ..., + ) -> CodeType: ... + def co_lines(self) -> Iterator[tuple[int, int, int | None]]: ... + co_linetable: object + elif sys.version_info >= (3, 8): def replace( self, *, @@ -135,11 +159,11 @@ class CodeType: co_flags: int = ..., co_firstlineno: int = ..., co_code: bytes = ..., - co_consts: Tuple[Any, ...] = ..., - co_names: Tuple[str, ...] = ..., - co_varnames: Tuple[str, ...] = ..., - co_freevars: Tuple[str, ...] = ..., - co_cellvars: Tuple[str, ...] = ..., + co_consts: tuple[Any, ...] = ..., + co_names: tuple[str, ...] = ..., + co_varnames: tuple[str, ...] = ..., + co_freevars: tuple[str, ...] = ..., + co_cellvars: tuple[str, ...] = ..., co_filename: str = ..., co_name: str = ..., co_lnotab: bytes = ..., @@ -149,8 +173,8 @@ class CodeType: @final class MappingProxyType(Mapping[_KT, _VT_co], Generic[_KT, _VT_co]): - __hash__: None # type: ignore - def __init__(self, mapping: Mapping[_KT, _VT_co]) -> None: ... + __hash__: None # type: ignore[assignment] + def __init__(self, mapping: SupportsKeysAndGetItem[_KT, _VT_co]) -> None: ... def __getitem__(self, k: _KT) -> _VT_co: ... def __iter__(self) -> Iterator[_KT]: ... def __len__(self) -> int: ... @@ -165,7 +189,7 @@ class MappingProxyType(Mapping[_KT, _VT_co], Generic[_KT, _VT_co]): def __ror__(self, __value: Mapping[_T1, _T2]) -> dict[_KT | _T1, _VT_co | _T2]: ... class SimpleNamespace: - __hash__: None # type: ignore + __hash__: None # type: ignore[assignment] def __init__(self, **kwargs: Any) -> None: ... def __getattribute__(self, name: str) -> Any: ... def __setattr__(self, name: str, value: Any) -> None: ... @@ -218,6 +242,8 @@ class AsyncGeneratorType(AsyncGenerator[_T_co, _T_contra]): @overload def athrow(self, __typ: BaseException, __val: None = ..., __tb: TracebackType | None = ...) -> Awaitable[_T_co]: ... def aclose(self) -> Awaitable[None]: ... + if sys.version_info >= (3, 9): + def __class_getitem__(cls, __item: Any) -> GenericAlias: ... @final class CoroutineType(Coroutine[_T_co, _T_contra, _V_co]): @@ -255,8 +281,8 @@ class _StaticFunctionType: @final class MethodType: - __closure__: Tuple[_Cell, ...] | None # inherited from the added function - __defaults__: Tuple[Any, ...] | None # inherited from the added function + __closure__: tuple[_Cell, ...] | None # inherited from the added function + __defaults__: tuple[Any, ...] | None # inherited from the added function __func__: _StaticFunctionType __self__: object __name__: str # inherited from the added function @@ -328,7 +354,7 @@ class FrameType: f_code: CodeType f_globals: dict[str, Any] f_lasti: int - f_lineno: int + f_lineno: int | None f_locals: dict[str, Any] f_trace: Callable[[FrameType, str, Any], Any] | None if sys.version_info >= (3, 7): @@ -359,18 +385,18 @@ if sys.version_info >= (3, 7): kwds: dict[str, Any] | None = ..., exec_body: Callable[[dict[str, Any]], None] | None = ..., ) -> type: ... - def resolve_bases(bases: Iterable[object]) -> Tuple[Any, ...]: ... + def resolve_bases(bases: Iterable[object]) -> tuple[Any, ...]: ... else: def new_class( name: str, - bases: Tuple[type, ...] = ..., + bases: tuple[type, ...] = ..., kwds: dict[str, Any] | None = ..., exec_body: Callable[[dict[str, Any]], None] | None = ..., ) -> type: ... def prepare_class( - name: str, bases: Tuple[type, ...] = ..., kwds: dict[str, Any] | None = ... + name: str, bases: tuple[type, ...] = ..., kwds: dict[str, Any] | None = ... ) -> tuple[type, dict[str, Any], dict[str, Any]]: ... # Actually a different type, but `property` is special and we want that too. @@ -381,10 +407,11 @@ _R = TypeVar("_R") _P = ParamSpec("_P") # it's not really an Awaitable, but can be used in an await expression. Real type: Generator & Awaitable +# The type: ignore is due to overlapping overloads, not the use of ParamSpec @overload -def coroutine(func: Callable[_P, Generator[_R, Any, Any]]) -> Callable[_P, Awaitable[_R]]: ... # type: ignore +def coroutine(func: Callable[_P, Generator[_R, Any, Any]]) -> Callable[_P, Awaitable[_R]]: ... # type: ignore[misc] @overload -def coroutine(func: _Fn) -> _Fn: ... # type: ignore +def coroutine(func: _Fn) -> _Fn: ... if sys.version_info >= (3, 8): CellType = _Cell @@ -392,8 +419,8 @@ if sys.version_info >= (3, 8): if sys.version_info >= (3, 9): class GenericAlias: __origin__: type - __args__: Tuple[Any, ...] - __parameters__: Tuple[Any, ...] + __args__: tuple[Any, ...] + __parameters__: tuple[Any, ...] def __init__(self, origin: type, args: Any) -> None: ... def __getattr__(self, name: str) -> Any: ... # incomplete @@ -407,6 +434,6 @@ if sys.version_info >= (3, 10): NotImplementedType = _NotImplementedType # noqa F811 from builtins @final class UnionType: - __args__: Tuple[Any, ...] + __args__: tuple[Any, ...] def __or__(self, obj: Any) -> UnionType: ... def __ror__(self, obj: Any) -> UnionType: ... diff --git a/mypy/typeshed/stdlib/typing.pyi b/mypy/typeshed/stdlib/typing.pyi index 4656add7ec218..6e461b8aa260b 100644 --- a/mypy/typeshed/stdlib/typing.pyi +++ b/mypy/typeshed/stdlib/typing.pyi @@ -1,5 +1,6 @@ import collections # Needed by aliases like DefaultDict, see mypy issue 2986 import sys +from _typeshed import SupportsKeysAndGetItem from abc import ABCMeta, abstractmethod from types import BuiltinFunctionType, CodeType, FrameType, FunctionType, MethodType, ModuleType, TracebackType from typing_extensions import Literal as _Literal, ParamSpec as _ParamSpec, final as _final @@ -10,9 +11,6 @@ if sys.version_info >= (3, 7): if sys.version_info >= (3, 9): from types import GenericAlias -# Definitions of special type checking related constructs. Their definitions -# are not used, so their value does not matter. - Any = object() class TypeVar: @@ -29,11 +27,18 @@ class TypeVar: covariant: bool = ..., contravariant: bool = ..., ) -> None: ... + if sys.version_info >= (3, 10): + def __or__(self, other: Any) -> _SpecialForm: ... + def __ror__(self, other: Any) -> _SpecialForm: ... +# Used for an undocumented mypy feature. Does not exist at runtime. _promote = object() class _SpecialForm: def __getitem__(self, typeargs: Any) -> object: ... + if sys.version_info >= (3, 10): + def __or__(self, other: Any) -> _SpecialForm: ... + def __ror__(self, other: Any) -> _SpecialForm: ... _F = TypeVar("_F", bound=Callable[..., Any]) _P = _ParamSpec("_P") @@ -80,9 +85,20 @@ if sys.version_info >= (3, 10): def args(self) -> ParamSpecArgs: ... @property def kwargs(self) -> ParamSpecKwargs: ... + def __or__(self, other: Any) -> _SpecialForm: ... + def __ror__(self, other: Any) -> _SpecialForm: ... Concatenate: _SpecialForm = ... TypeAlias: _SpecialForm = ... TypeGuard: _SpecialForm = ... + class NewType: + def __init__(self, name: str, tp: type) -> None: ... + def __call__(self, x: _T) -> _T: ... + def __or__(self, other: Any) -> _SpecialForm: ... + def __ror__(self, other: Any) -> _SpecialForm: ... + __supertype__: type + +else: + def NewType(name: str, tp: Type[_T]) -> Type[_T]: ... # These type variables are used by the container types. _S = TypeVar("_S") @@ -96,7 +112,7 @@ _T_contra = TypeVar("_T_contra", contravariant=True) # Ditto contravariant. _TC = TypeVar("_TC", bound=Type[object]) def no_type_check(arg: _F) -> _F: ... -def no_type_check_decorator(decorator: Callable[_P, _T]) -> Callable[_P, _T]: ... # type: ignore +def no_type_check_decorator(decorator: Callable[_P, _T]) -> Callable[_P, _T]: ... # type: ignore[misc] # Type aliases and type constructors @@ -122,6 +138,14 @@ if sys.version_info >= (3, 9): # Predefined type variables. AnyStr = TypeVar("AnyStr", str, bytes) +if sys.version_info >= (3, 8): + # This class did actually exist in 3.7, but had a different base. + # We'll just pretend it didn't exist though: the main external use case for _ProtocolMeta is + # to inherit from for your own custom protocol metaclasses. If you're using 3.7, at runtime + # you'd use typing_extensions.Protocol, which would be unrelated to typing._ProtocolMeta and + # so you'd run into metaclass conflicts at runtime if you used typing._ProtocolMeta. + class _ProtocolMeta(ABCMeta): ... + # Abstract base classes. def runtime_checkable(cls: _TC) -> _TC: ... @@ -246,7 +270,7 @@ class Coroutine(Awaitable[_V_co], Generic[_T_co, _T_contra, _V_co]): @abstractmethod def close(self) -> None: ... -# NOTE: This type does not exist in typing.py or PEP 484. +# NOTE: This type does not exist in typing.py or PEP 484 but mypy needs it to exist. # The parameters correspond to Generator, but the 4th is the original type. class AwaitableGenerator( Awaitable[_V_co], Generator[_T_co, _T_contra, _V_co], Generic[_T_co, _T_contra, _V_co, _S], metaclass=ABCMeta @@ -465,7 +489,7 @@ class MutableMapping(Mapping[_KT, _VT], Generic[_KT, _VT]): # known to be a Mapping with unknown type parameters, which is closer # to the behavior we want. See mypy issue #1430. @overload - def update(self, __m: Mapping[_KT, _VT], **kwargs: _VT) -> None: ... + def update(self, __m: SupportsKeysAndGetItem[_KT, _VT], **kwargs: _VT) -> None: ... @overload def update(self, __m: Iterable[tuple[_KT, _VT]], **kwargs: _VT) -> None: ... @overload @@ -550,7 +574,7 @@ class Match(Generic[AnyStr]): pos: int endpos: int lastindex: int | None - lastgroup: AnyStr | None + lastgroup: str | None string: AnyStr # The regular expression object whose match() or search() method produced @@ -598,7 +622,7 @@ class Pattern(Generic[AnyStr]): def search(self, string: AnyStr, pos: int = ..., endpos: int = ...) -> Match[AnyStr] | None: ... def match(self, string: AnyStr, pos: int = ..., endpos: int = ...) -> Match[AnyStr] | None: ... def fullmatch(self, string: AnyStr, pos: int = ..., endpos: int = ...) -> Match[AnyStr] | None: ... - def split(self, string: AnyStr, maxsplit: int = ...) -> list[AnyStr]: ... + def split(self, string: AnyStr, maxsplit: int = ...) -> list[AnyStr | Any]: ... def findall(self, string: AnyStr, pos: int = ..., endpos: int = ...) -> list[Any]: ... def finditer(self, string: AnyStr, pos: int = ..., endpos: int = ...) -> Iterator[Match[AnyStr]]: ... @overload @@ -657,9 +681,11 @@ def cast(typ: object, val: Any) -> Any: ... # Type constructors -# NamedTuple is special-cased in the type checker class NamedTuple(Tuple[Any, ...]): - _field_types: collections.OrderedDict[str, Type[Any]] + if sys.version_info < (3, 8): + _field_types: collections.OrderedDict[str, type] + elif sys.version_info < (3, 9): + _field_types: dict[str, type] _field_defaults: dict[str, Any] _fields: Tuple[str, ...] _source: str @@ -691,8 +717,6 @@ class _TypedDict(Mapping[str, object], metaclass=ABCMeta): def __or__(self: _T, __value: _T) -> _T: ... def __ior__(self: _T, __value: _T) -> _T: ... -def NewType(name: str, tp: Type[_T]) -> Type[_T]: ... - # This itself is only available during type checking def type_check_only(func_or_cls: _F) -> _F: ... @@ -704,14 +728,17 @@ if sys.version_info >= (3, 7): __forward_value__: Any | None __forward_is_argument__: bool if sys.version_info >= (3, 9): - # The module argument was added in Python 3.9.7. - def __init__(self, arg: str, is_argument: bool = ..., module: Any | None = ...) -> None: ... + # The module and is_class arguments were added in later Python 3.9 versions. + def __init__(self, arg: str, is_argument: bool = ..., module: Any | None = ..., *, is_class: bool = ...) -> None: ... else: def __init__(self, arg: str, is_argument: bool = ...) -> None: ... def _evaluate(self, globalns: dict[str, Any] | None, localns: dict[str, Any] | None) -> Any | None: ... def __eq__(self, other: Any) -> bool: ... def __hash__(self) -> int: ... def __repr__(self) -> str: ... + if sys.version_info >= (3, 11): + def __or__(self, other: Any) -> _SpecialForm: ... + def __ror__(self, other: Any) -> _SpecialForm: ... if sys.version_info >= (3, 10): - def is_typeddict(tp: Any) -> bool: ... + def is_typeddict(tp: object) -> bool: ... diff --git a/mypy/typeshed/stdlib/typing_extensions.pyi b/mypy/typeshed/stdlib/typing_extensions.pyi index ce407f996022b..e7f288377b83c 100644 --- a/mypy/typeshed/stdlib/typing_extensions.pyi +++ b/mypy/typeshed/stdlib/typing_extensions.pyi @@ -22,7 +22,6 @@ from typing import ( NewType as NewType, NoReturn as NoReturn, Text as Text, - Tuple, Type as Type, TypeVar, ValuesView, @@ -53,6 +52,11 @@ Literal: _SpecialForm = ... def IntVar(name: str) -> Any: ... # returns a new TypeVar +if sys.version_info < (3, 8): + # Technically in 3.6 this inherited from GenericMeta. But let's not reflect that, since + # type checkers tend to assume that Protocols all have the ABCMeta metaclass. + class _ProtocolMeta(abc.ABCMeta): ... + # Internal mypy fallback type for all typed dicts (does not exist at runtime) class _TypedDict(Mapping[str, object], metaclass=abc.ABCMeta): __required_keys__: frozenset[str] @@ -82,7 +86,7 @@ if sys.version_info >= (3, 7): localns: dict[str, Any] | None = ..., include_extras: bool = ..., ) -> dict[str, Any]: ... - def get_args(tp: Any) -> Tuple[Any, ...]: ... + def get_args(tp: Any) -> tuple[Any, ...]: ... def get_origin(tp: Any) -> Any | None: ... Annotated: _SpecialForm = ... diff --git a/mypy/typeshed/stdlib/unicodedata.pyi b/mypy/typeshed/stdlib/unicodedata.pyi index 66c93f7439f74..ead25ba4062c4 100644 --- a/mypy/typeshed/stdlib/unicodedata.pyi +++ b/mypy/typeshed/stdlib/unicodedata.pyi @@ -24,7 +24,7 @@ def name(__chr: str, __default: _T = ...) -> str | _T: ... def normalize(__form: str, __unistr: str) -> str: ... def numeric(__chr: str, __default: _T = ...) -> float | _T: ... -class UCD(object): +class UCD: # The methods below are constructed from the same array in C # (unicodedata_functions) and hence identical to the methods above. unidata_version: str diff --git a/mypy/typeshed/stdlib/unittest/__init__.pyi b/mypy/typeshed/stdlib/unittest/__init__.pyi index 8f0ef896fa0c8..d3b0efaa83ff0 100644 --- a/mypy/typeshed/stdlib/unittest/__init__.pyi +++ b/mypy/typeshed/stdlib/unittest/__init__.pyi @@ -10,15 +10,25 @@ from .case import ( skipIf as skipIf, skipUnless as skipUnless, ) +from .loader import ( + TestLoader as TestLoader, + defaultTestLoader as defaultTestLoader, + findTestCases as findTestCases, + getTestCaseNames as getTestCaseNames, + makeSuite as makeSuite, +) +from .main import TestProgram as TestProgram, main as main +from .result import TestResult as TestResult +from .runner import TextTestResult as TextTestResult, TextTestRunner as TextTestRunner +from .signals import ( + installHandler as installHandler, + registerResult as registerResult, + removeHandler as removeHandler, + removeResult as removeResult, +) +from .suite import BaseTestSuite as BaseTestSuite, TestSuite as TestSuite if sys.version_info >= (3, 8): from .case import addModuleCleanup as addModuleCleanup -from unittest.loader import * -from unittest.main import * -from unittest.result import TestResult as TestResult -from unittest.runner import * -from unittest.signals import * -from unittest.suite import * - def load_tests(loader: TestLoader, tests: TestSuite, pattern: str | None) -> TestSuite: ... diff --git a/mypy/typeshed/stdlib/unittest/_log.pyi b/mypy/typeshed/stdlib/unittest/_log.pyi new file mode 100644 index 0000000000000..f9e406199cd48 --- /dev/null +++ b/mypy/typeshed/stdlib/unittest/_log.pyi @@ -0,0 +1,27 @@ +import logging +import sys +from types import TracebackType +from typing import ClassVar, Generic, NamedTuple, Type, TypeVar +from unittest.case import TestCase + +_L = TypeVar("_L", None, _LoggingWatcher) + +class _LoggingWatcher(NamedTuple): + records: list[logging.LogRecord] + output: list[str] + +class _AssertLogsContext(Generic[_L]): + LOGGING_FORMAT: ClassVar[str] + test_case: TestCase + logger_name: str + level: int + msg: None + if sys.version_info >= (3, 10): + def __init__(self, test_case: TestCase, logger_name: str, level: int, no_logs: bool) -> None: ... + no_logs: bool + else: + def __init__(self, test_case: TestCase, logger_name: str, level: int) -> None: ... + def __enter__(self) -> _L: ... + def __exit__( + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> bool | None: ... diff --git a/mypy/typeshed/stdlib/unittest/case.pyi b/mypy/typeshed/stdlib/unittest/case.pyi index 2ae07144373c2..858bf38e700d3 100644 --- a/mypy/typeshed/stdlib/unittest/case.pyi +++ b/mypy/typeshed/stdlib/unittest/case.pyi @@ -3,13 +3,14 @@ import logging import sys import unittest.result from _typeshed import Self -from collections.abc import Set # equivalent to typing.AbstractSet, not builtins.set +from collections.abc import Set as AbstractSet from contextlib import AbstractContextManager from types import TracebackType from typing import ( Any, AnyStr, Callable, + ClassVar, Container, Generic, Iterable, @@ -18,7 +19,6 @@ from typing import ( NoReturn, Pattern, Sequence, - Tuple, Type, TypeVar, overload, @@ -31,6 +31,33 @@ if sys.version_info >= (3, 9): _E = TypeVar("_E", bound=BaseException) _FT = TypeVar("_FT", bound=Callable[..., Any]) +DIFF_OMITTED: str + +class _BaseTestCaseContext: + def __init__(self, test_case: TestCase) -> None: ... + +if sys.version_info >= (3, 9): + from unittest._log import _AssertLogsContext, _LoggingWatcher +else: + # Unused dummy for _AssertLogsContext. Starting with Python 3.10, + # this is generic over the logging watcher, but in lower versions + # the watcher is hard-coded. + _L = TypeVar("_L") + class _LoggingWatcher(NamedTuple): + records: list[logging.LogRecord] + output: list[str] + class _AssertLogsContext(_BaseTestCaseContext, Generic[_L]): + LOGGING_FORMAT: ClassVar[str] + test_case: TestCase + logger_name: str + level: int + msg: None + def __init__(self, test_case: TestCase, logger_name: str, level: int) -> None: ... + def __enter__(self) -> _LoggingWatcher: ... + def __exit__( + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> bool | None: ... + if sys.version_info >= (3, 8): def addModuleCleanup(__function: Callable[..., Any], *args: Any, **kwargs: Any) -> None: ... def doModuleCleanups() -> None: ... @@ -74,26 +101,26 @@ class TestCase: def assertIsNotNone(self, obj: Any, msg: Any = ...) -> None: ... def assertIn(self, member: Any, container: Iterable[Any] | Container[Any], msg: Any = ...) -> None: ... def assertNotIn(self, member: Any, container: Iterable[Any] | Container[Any], msg: Any = ...) -> None: ... - def assertIsInstance(self, obj: Any, cls: type | Tuple[type, ...], msg: Any = ...) -> None: ... - def assertNotIsInstance(self, obj: Any, cls: type | Tuple[type, ...], msg: Any = ...) -> None: ... + def assertIsInstance(self, obj: Any, cls: type | tuple[type, ...], msg: Any = ...) -> None: ... + def assertNotIsInstance(self, obj: Any, cls: type | tuple[type, ...], msg: Any = ...) -> None: ... def assertGreater(self, a: Any, b: Any, msg: Any = ...) -> None: ... def assertGreaterEqual(self, a: Any, b: Any, msg: Any = ...) -> None: ... def assertLess(self, a: Any, b: Any, msg: Any = ...) -> None: ... def assertLessEqual(self, a: Any, b: Any, msg: Any = ...) -> None: ... @overload - def assertRaises( # type: ignore + def assertRaises( # type: ignore[misc] self, - expected_exception: Type[BaseException] | Tuple[Type[BaseException], ...], + expected_exception: Type[BaseException] | tuple[Type[BaseException], ...], callable: Callable[..., Any], *args: Any, **kwargs: Any, ) -> None: ... @overload - def assertRaises(self, expected_exception: Type[_E] | Tuple[Type[_E], ...], msg: Any = ...) -> _AssertRaisesContext[_E]: ... + def assertRaises(self, expected_exception: Type[_E] | tuple[Type[_E], ...], msg: Any = ...) -> _AssertRaisesContext[_E]: ... @overload - def assertRaisesRegex( # type: ignore + def assertRaisesRegex( # type: ignore[misc] self, - expected_exception: Type[BaseException] | Tuple[Type[BaseException], ...], + expected_exception: Type[BaseException] | tuple[Type[BaseException], ...], expected_regex: str | bytes | Pattern[str] | Pattern[bytes], callable: Callable[..., Any], *args: Any, @@ -102,20 +129,20 @@ class TestCase: @overload def assertRaisesRegex( self, - expected_exception: Type[_E] | Tuple[Type[_E], ...], + expected_exception: Type[_E] | tuple[Type[_E], ...], expected_regex: str | bytes | Pattern[str] | Pattern[bytes], msg: Any = ..., ) -> _AssertRaisesContext[_E]: ... @overload - def assertWarns( # type: ignore - self, expected_warning: Type[Warning] | Tuple[Type[Warning], ...], callable: Callable[..., Any], *args: Any, **kwargs: Any + def assertWarns( # type: ignore[misc] + self, expected_warning: Type[Warning] | tuple[Type[Warning], ...], callable: Callable[..., Any], *args: Any, **kwargs: Any ) -> None: ... @overload - def assertWarns(self, expected_warning: Type[Warning] | Tuple[Type[Warning], ...], msg: Any = ...) -> _AssertWarnsContext: ... + def assertWarns(self, expected_warning: Type[Warning] | tuple[Type[Warning], ...], msg: Any = ...) -> _AssertWarnsContext: ... @overload - def assertWarnsRegex( # type: ignore + def assertWarnsRegex( # type: ignore[misc] self, - expected_warning: Type[Warning] | Tuple[Type[Warning], ...], + expected_warning: Type[Warning] | tuple[Type[Warning], ...], expected_regex: str | bytes | Pattern[str] | Pattern[bytes], callable: Callable[..., Any], *args: Any, @@ -124,11 +151,17 @@ class TestCase: @overload def assertWarnsRegex( self, - expected_warning: Type[Warning] | Tuple[Type[Warning], ...], + expected_warning: Type[Warning] | tuple[Type[Warning], ...], expected_regex: str | bytes | Pattern[str] | Pattern[bytes], msg: Any = ..., ) -> _AssertWarnsContext: ... - def assertLogs(self, logger: str | logging.Logger | None = ..., level: int | str | None = ...) -> _AssertLogsContext: ... + def assertLogs( + self, logger: str | logging.Logger | None = ..., level: int | str | None = ... + ) -> _AssertLogsContext[_LoggingWatcher]: ... + if sys.version_info >= (3, 10): + def assertNoLogs( + self, logger: str | logging.Logger | None = ..., level: int | str | None = ... + ) -> _AssertLogsContext[None]: ... @overload def assertAlmostEqual( self, first: float, second: float, places: int | None = ..., msg: Any = ..., delta: float | None = ... @@ -166,8 +199,8 @@ class TestCase: self, seq1: Sequence[Any], seq2: Sequence[Any], msg: Any = ..., seq_type: Type[Sequence[Any]] | None = ... ) -> None: ... def assertListEqual(self, list1: list[Any], list2: list[Any], msg: Any = ...) -> None: ... - def assertTupleEqual(self, tuple1: Tuple[Any, ...], tuple2: Tuple[Any, ...], msg: Any = ...) -> None: ... - def assertSetEqual(self, set1: Set[object], set2: Set[object], msg: Any = ...) -> None: ... + def assertTupleEqual(self, tuple1: tuple[Any, ...], tuple2: tuple[Any, ...], msg: Any = ...) -> None: ... + def assertSetEqual(self, set1: AbstractSet[object], set2: AbstractSet[object], msg: Any = ...) -> None: ... def assertDictEqual(self, d1: Mapping[Any, object], d2: Mapping[Any, object], msg: Any = ...) -> None: ... def fail(self, msg: Any = ...) -> NoReturn: ... def countTestCases(self) -> int: ... @@ -186,49 +219,53 @@ class TestCase: def doClassCleanups(cls) -> None: ... def _formatMessage(self, msg: str | None, standardMsg: str) -> str: ... # undocumented def _getAssertEqualityFunc(self, first: Any, second: Any) -> Callable[..., None]: ... # undocumented - # below is deprecated - def failUnlessEqual(self, first: Any, second: Any, msg: Any = ...) -> None: ... - def assertEquals(self, first: Any, second: Any, msg: Any = ...) -> None: ... - def failIfEqual(self, first: Any, second: Any, msg: Any = ...) -> None: ... - def assertNotEquals(self, first: Any, second: Any, msg: Any = ...) -> None: ... - def failUnless(self, expr: bool, msg: Any = ...) -> None: ... - def assert_(self, expr: bool, msg: Any = ...) -> None: ... - def failIf(self, expr: bool, msg: Any = ...) -> None: ... - @overload - def failUnlessRaises( # type: ignore - self, - exception: Type[BaseException] | Tuple[Type[BaseException], ...], - callable: Callable[..., Any] = ..., - *args: Any, - **kwargs: Any, - ) -> None: ... - @overload - def failUnlessRaises(self, exception: Type[_E] | Tuple[Type[_E], ...], msg: Any = ...) -> _AssertRaisesContext[_E]: ... - def failUnlessAlmostEqual(self, first: float, second: float, places: int = ..., msg: Any = ...) -> None: ... - def assertAlmostEquals(self, first: float, second: float, places: int = ..., msg: Any = ..., delta: float = ...) -> None: ... - def failIfAlmostEqual(self, first: float, second: float, places: int = ..., msg: Any = ...) -> None: ... - def assertNotAlmostEquals( - self, first: float, second: float, places: int = ..., msg: Any = ..., delta: float = ... - ) -> None: ... - def assertRegexpMatches(self, text: AnyStr, regex: AnyStr | Pattern[AnyStr], msg: Any = ...) -> None: ... - def assertNotRegexpMatches(self, text: AnyStr, regex: AnyStr | Pattern[AnyStr], msg: Any = ...) -> None: ... - @overload - def assertRaisesRegexp( # type: ignore - self, - exception: Type[BaseException] | Tuple[Type[BaseException], ...], - expected_regex: str | bytes | Pattern[str] | Pattern[bytes], - callable: Callable[..., Any], - *args: Any, - **kwargs: Any, - ) -> None: ... - @overload - def assertRaisesRegexp( - self, - exception: Type[_E] | Tuple[Type[_E], ...], - expected_regex: str | bytes | Pattern[str] | Pattern[bytes], - msg: Any = ..., - ) -> _AssertRaisesContext[_E]: ... - def assertDictContainsSubset(self, subset: Mapping[Any, Any], dictionary: Mapping[Any, Any], msg: object = ...) -> None: ... + if sys.version_info < (3, 11): + def failUnlessEqual(self, first: Any, second: Any, msg: Any = ...) -> None: ... + def assertEquals(self, first: Any, second: Any, msg: Any = ...) -> None: ... + def failIfEqual(self, first: Any, second: Any, msg: Any = ...) -> None: ... + def assertNotEquals(self, first: Any, second: Any, msg: Any = ...) -> None: ... + def failUnless(self, expr: bool, msg: Any = ...) -> None: ... + def assert_(self, expr: bool, msg: Any = ...) -> None: ... + def failIf(self, expr: bool, msg: Any = ...) -> None: ... + @overload + def failUnlessRaises( # type: ignore[misc] + self, + exception: Type[BaseException] | tuple[Type[BaseException], ...], + callable: Callable[..., Any] = ..., + *args: Any, + **kwargs: Any, + ) -> None: ... + @overload + def failUnlessRaises(self, exception: Type[_E] | tuple[Type[_E], ...], msg: Any = ...) -> _AssertRaisesContext[_E]: ... + def failUnlessAlmostEqual(self, first: float, second: float, places: int = ..., msg: Any = ...) -> None: ... + def assertAlmostEquals( + self, first: float, second: float, places: int = ..., msg: Any = ..., delta: float = ... + ) -> None: ... + def failIfAlmostEqual(self, first: float, second: float, places: int = ..., msg: Any = ...) -> None: ... + def assertNotAlmostEquals( + self, first: float, second: float, places: int = ..., msg: Any = ..., delta: float = ... + ) -> None: ... + def assertRegexpMatches(self, text: AnyStr, regex: AnyStr | Pattern[AnyStr], msg: Any = ...) -> None: ... + def assertNotRegexpMatches(self, text: AnyStr, regex: AnyStr | Pattern[AnyStr], msg: Any = ...) -> None: ... + @overload + def assertRaisesRegexp( # type: ignore[misc] + self, + exception: Type[BaseException] | tuple[Type[BaseException], ...], + expected_regex: str | bytes | Pattern[str] | Pattern[bytes], + callable: Callable[..., Any], + *args: Any, + **kwargs: Any, + ) -> None: ... + @overload + def assertRaisesRegexp( + self, + exception: Type[_E] | tuple[Type[_E], ...], + expected_regex: str | bytes | Pattern[str] | Pattern[bytes], + msg: Any = ..., + ) -> _AssertRaisesContext[_E]: ... + def assertDictContainsSubset( + self, subset: Mapping[Any, Any], dictionary: Mapping[Any, Any], msg: object = ... + ) -> None: ... class FunctionTestCase(TestCase): def __init__( @@ -240,10 +277,6 @@ class FunctionTestCase(TestCase): ) -> None: ... def runTest(self) -> None: ... -class _LoggingWatcher(NamedTuple): - records: list[logging.LogRecord] - output: list[str] - class _AssertRaisesContext(Generic[_E]): exception: _E def __enter__(self: Self) -> Self: ... @@ -262,16 +295,3 @@ class _AssertWarnsContext: def __exit__( self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> None: ... - -class _AssertLogsContext: - LOGGING_FORMAT: str - records: list[logging.LogRecord] - output: list[str] - def __init__(self, test_case: TestCase, logger_name: str, level: int) -> None: ... - if sys.version_info >= (3, 10): - def __enter__(self) -> _LoggingWatcher | None: ... - else: - def __enter__(self) -> _LoggingWatcher: ... - def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None - ) -> bool | None: ... diff --git a/mypy/typeshed/stdlib/unittest/loader.pyi b/mypy/typeshed/stdlib/unittest/loader.pyi index d3cb4cef733bf..aca7e4f9554f6 100644 --- a/mypy/typeshed/stdlib/unittest/loader.pyi +++ b/mypy/typeshed/stdlib/unittest/loader.pyi @@ -3,10 +3,12 @@ import unittest.case import unittest.result import unittest.suite from types import ModuleType -from typing import Any, Callable, List, Sequence, Type +from typing import Any, Callable, Pattern, Sequence, Type _SortComparisonMethod = Callable[[str, str], int] -_SuiteClass = Callable[[List[unittest.case.TestCase]], unittest.suite.TestSuite] +_SuiteClass = Callable[[list[unittest.case.TestCase]], unittest.suite.TestSuite] + +VALID_MODULE_NAME: Pattern[str] class TestLoader: errors: list[Type[BaseException]] diff --git a/mypy/typeshed/stdlib/unittest/main.pyi b/mypy/typeshed/stdlib/unittest/main.pyi index cd887cec27d06..6d1117ecaf79a 100644 --- a/mypy/typeshed/stdlib/unittest/main.pyi +++ b/mypy/typeshed/stdlib/unittest/main.pyi @@ -6,6 +6,9 @@ import unittest.suite from types import ModuleType from typing import Any, Iterable, Protocol, Type +MAIN_EXAMPLES: str +MODULE_EXAMPLES: str + class _TestRunner(Protocol): def run(self, test: unittest.suite.TestSuite | unittest.case.TestCase) -> unittest.result.TestResult: ... diff --git a/mypy/typeshed/stdlib/unittest/mock.pyi b/mypy/typeshed/stdlib/unittest/mock.pyi index 567ce346f464d..72d0bab95c2e4 100644 --- a/mypy/typeshed/stdlib/unittest/mock.pyi +++ b/mypy/typeshed/stdlib/unittest/mock.pyi @@ -1,27 +1,61 @@ import sys -from typing import Any, Callable, Generic, Iterable, List, Mapping, Sequence, Tuple, Type, TypeVar, overload +from typing import Any, Awaitable, Callable, Generic, Iterable, Mapping, Sequence, Type, TypeVar, overload _T = TypeVar("_T") _TT = TypeVar("_TT", bound=Type[Any]) _R = TypeVar("_R") -__all__ = [ - "Mock", - "MagicMock", - "patch", - "sentinel", - "DEFAULT", - "ANY", - "call", - "create_autospec", - "AsyncMock", - "FILTER_DIR", - "NonCallableMock", - "NonCallableMagicMock", - "mock_open", - "PropertyMock", - "seal", -] +if sys.version_info >= (3, 8): + __all__ = ( + "Mock", + "MagicMock", + "patch", + "sentinel", + "DEFAULT", + "ANY", + "call", + "create_autospec", + "AsyncMock", + "FILTER_DIR", + "NonCallableMock", + "NonCallableMagicMock", + "mock_open", + "PropertyMock", + "seal", + ) +elif sys.version_info >= (3, 7): + __all__ = ( + "Mock", + "MagicMock", + "patch", + "sentinel", + "DEFAULT", + "ANY", + "call", + "create_autospec", + "FILTER_DIR", + "NonCallableMock", + "NonCallableMagicMock", + "mock_open", + "PropertyMock", + "seal", + ) +else: + __all__ = ( + "Mock", + "MagicMock", + "patch", + "sentinel", + "DEFAULT", + "ANY", + "call", + "create_autospec", + "FILTER_DIR", + "NonCallableMock", + "NonCallableMagicMock", + "mock_open", + "PropertyMock", + ) __version__: str FILTER_DIR: Any @@ -39,7 +73,7 @@ class _Sentinel: sentinel: Any DEFAULT: Any -class _Call(Tuple[Any, ...]): +class _Call(tuple[Any, ...]): def __new__( cls, value: Any = ..., name: Any | None = ..., parent: Any | None = ..., two: bool = ..., from_kall: bool = ... ) -> Any: ... @@ -53,25 +87,22 @@ class _Call(Tuple[Any, ...]): __ne__: Any def __call__(self, *args: Any, **kwargs: Any) -> _Call: ... def __getattr__(self, attr: Any) -> Any: ... - def count(self, *args: Any, **kwargs: Any) -> Any: ... - def index(self, *args: Any, **kwargs: Any) -> Any: ... + if sys.version_info >= (3, 8): + @property + def args(self): ... + @property + def kwargs(self): ... def call_list(self) -> Any: ... call: _Call -class _CallList(List[_Call]): +class _CallList(list[_Call]): def __contains__(self, value: Any) -> bool: ... -class _MockIter: - obj: Any - def __init__(self, obj: Any) -> None: ... - def __iter__(self) -> Any: ... - def __next__(self) -> Any: ... - class Base: def __init__(self, *args: Any, **kwargs: Any) -> None: ... -class NonCallableMock(Base, Any): # type: ignore +class NonCallableMock(Base, Any): def __new__(__cls, *args: Any, **kw: Any) -> NonCallableMock: ... def __init__( self, @@ -124,7 +155,7 @@ class NonCallableMock(Base, Any): # type: ignore call_args_list: _CallList mock_calls: _CallList def _format_mock_call_signature(self, args: Any, kwargs: Any) -> str: ... - def _call_matcher(self, _call: Tuple[_Call, ...]) -> _Call: ... + def _call_matcher(self, _call: tuple[_Call, ...]) -> _Call: ... def _get_child_mock(self, **kw: Any) -> NonCallableMock: ... class CallableMixin(Base): @@ -143,7 +174,10 @@ class CallableMixin(Base): _new_parent: Any | None = ..., **kwargs: Any, ) -> None: ... - def __call__(_mock_self, *args: Any, **kwargs: Any) -> Any: ... + if sys.version_info >= (3, 8): + def __call__(self, *args: Any, **kwargs: Any) -> Any: ... + else: + def __call__(_mock_self, *args: Any, **kwargs: Any) -> Any: ... class Mock(CallableMixin, NonCallableMock): ... @@ -162,25 +196,45 @@ class _patch(Generic[_T]): additional_patchers: Any # If new==DEFAULT, self is _patch[Any]. Ideally we'd be able to add an overload for it so that self is _patch[MagicMock], # but that's impossible with the current type system. - def __init__( - self: _patch[_T], - getter: Callable[[], Any], - attribute: str, - new: _T, - spec: Any | None, - create: bool, - spec_set: Any | None, - autospec: Any | None, - new_callable: Any | None, - kwargs: Mapping[str, Any], - ) -> None: ... + if sys.version_info >= (3, 10): + def __init__( + self: _patch[_T], + getter: Callable[[], Any], + attribute: str, + new: _T, + spec: Any | None, + create: bool, + spec_set: Any | None, + autospec: Any | None, + new_callable: Any | None, + kwargs: Mapping[str, Any], + *, + unsafe: bool = ..., + ) -> None: ... + else: + def __init__( + self: _patch[_T], + getter: Callable[[], Any], + attribute: str, + new: _T, + spec: Any | None, + create: bool, + spec_set: Any | None, + autospec: Any | None, + new_callable: Any | None, + kwargs: Mapping[str, Any], + ) -> None: ... def copy(self) -> _patch[_T]: ... @overload def __call__(self, func: _TT) -> _TT: ... @overload def __call__(self, func: Callable[..., _R]) -> Callable[..., _R]: ... + if sys.version_info >= (3, 8): + def decoration_helper(self, patched, args, keywargs): ... def decorate_class(self, klass: _TT) -> _TT: ... def decorate_callable(self, func: Callable[..., _R]) -> Callable[..., _R]: ... + if sys.version_info >= (3, 8): + def decorate_async_callable(self, func: Callable[..., Awaitable[_R]]) -> Callable[..., Awaitable[_R]]: ... def get_original(self) -> tuple[Any, bool]: ... target: Any temp_original: Any @@ -210,7 +264,7 @@ class _patcher: # Ideally we'd be able to add an overload for it so that the return type is _patch[MagicMock], # but that's impossible with the current type system. @overload - def __call__( # type: ignore + def __call__( # type: ignore[misc] self, target: Any, new: _T, @@ -222,7 +276,7 @@ class _patcher: **kwargs: Any, ) -> _patch[_T]: ... @overload - def __call__( # type: ignore + def __call__( self, target: Any, *, @@ -235,7 +289,7 @@ class _patcher: ) -> _patch[MagicMock | AsyncMock]: ... else: @overload - def __call__( # type: ignore + def __call__( # type: ignore[misc] self, target: Any, new: _T, @@ -247,7 +301,7 @@ class _patcher: **kwargs: Any, ) -> _patch[_T]: ... @overload - def __call__( # type: ignore + def __call__( self, target: Any, *, @@ -260,7 +314,7 @@ class _patcher: ) -> _patch[MagicMock]: ... if sys.version_info >= (3, 8): @overload - def object( # type: ignore + def object( # type: ignore[misc] self, target: Any, attribute: str, @@ -273,7 +327,7 @@ class _patcher: **kwargs: Any, ) -> _patch[_T]: ... @overload - def object( # type: ignore + def object( self, target: Any, attribute: str, @@ -287,7 +341,7 @@ class _patcher: ) -> _patch[MagicMock | AsyncMock]: ... else: @overload - def object( # type: ignore + def object( # type: ignore[misc] self, target: Any, attribute: str, @@ -300,7 +354,7 @@ class _patcher: **kwargs: Any, ) -> _patch[_T]: ... @overload - def object( # type: ignore + def object( self, target: Any, attribute: str, @@ -357,10 +411,11 @@ if sys.version_info >= (3, 8): class MagicProxy: name: Any parent: Any - def __init__(self, name: Any, parent: Any) -> None: ... - def __call__(self, *args: Any, **kwargs: Any) -> Any: ... - def create_mock(self) -> Any: ... - def __get__(self, obj: Any, _type: Any | None = ...) -> Any: ... + def __init__(self, name, parent) -> None: ... + if sys.version_info < (3, 8): + def __call__(self, *args: Any, **kwargs: Any) -> Any: ... + def create_mock(self): ... + def __get__(self, obj, _type: Any | None = ...): ... class _ANY: def __eq__(self, other: Any) -> bool: ... diff --git a/mypy/typeshed/stdlib/unittest/result.pyi b/mypy/typeshed/stdlib/unittest/result.pyi index 20c43cf38aa45..9a19aef77d21c 100644 --- a/mypy/typeshed/stdlib/unittest/result.pyi +++ b/mypy/typeshed/stdlib/unittest/result.pyi @@ -1,11 +1,14 @@ import unittest.case from types import TracebackType -from typing import Any, Callable, TextIO, Tuple, Type, TypeVar, Union +from typing import Any, Callable, TextIO, Type, TypeVar, Union -_SysExcInfoType = Union[Tuple[Type[BaseException], BaseException, TracebackType], Tuple[None, None, None]] +_SysExcInfoType = Union[tuple[Type[BaseException], BaseException, TracebackType], tuple[None, None, None]] _F = TypeVar("_F", bound=Callable[..., Any]) +STDOUT_LINE: str +STDERR_LINE: str + # undocumented def failfast(method: _F) -> _F: ... diff --git a/mypy/typeshed/stdlib/unittest/runner.pyi b/mypy/typeshed/stdlib/unittest/runner.pyi index bf8f3c05c1cda..85481880ab173 100644 --- a/mypy/typeshed/stdlib/unittest/runner.pyi +++ b/mypy/typeshed/stdlib/unittest/runner.pyi @@ -17,7 +17,7 @@ class TextTestResult(unittest.result.TestResult): def printErrors(self) -> None: ... def printErrorList(self, flavour: str, errors: tuple[unittest.case.TestCase, str]) -> None: ... -class TextTestRunner(object): +class TextTestRunner: resultclass: _ResultClassType def __init__( self, diff --git a/mypy/typeshed/stdlib/unittest/signals.pyi b/mypy/typeshed/stdlib/unittest/signals.pyi index 375b7d736a352..e6f5f95e1eb1b 100644 --- a/mypy/typeshed/stdlib/unittest/signals.pyi +++ b/mypy/typeshed/stdlib/unittest/signals.pyi @@ -11,4 +11,4 @@ def removeResult(result: unittest.result.TestResult) -> bool: ... @overload def removeHandler(method: None = ...) -> None: ... @overload -def removeHandler(method: Callable[_P, _T]) -> Callable[_P, _T]: ... # type: ignore +def removeHandler(method: Callable[_P, _T]) -> Callable[_P, _T]: ... diff --git a/mypy/typeshed/stdlib/unittest/util.pyi b/mypy/typeshed/stdlib/unittest/util.pyi index ab6ed053a6ffd..680ca24b7c335 100644 --- a/mypy/typeshed/stdlib/unittest/util.pyi +++ b/mypy/typeshed/stdlib/unittest/util.pyi @@ -1,7 +1,7 @@ -from typing import Any, Sequence, Tuple, TypeVar +from typing import Any, Sequence, TypeVar _T = TypeVar("_T") -_Mismatch = Tuple[_T, _T, int] +_Mismatch = tuple[_T, _T, int] _MAX_LENGTH: int _PLACEHOLDER_LEN: int diff --git a/mypy/typeshed/stdlib/urllib/parse.pyi b/mypy/typeshed/stdlib/urllib/parse.pyi index a2467e96c43c5..7404b53820143 100644 --- a/mypy/typeshed/stdlib/urllib/parse.pyi +++ b/mypy/typeshed/stdlib/urllib/parse.pyi @@ -1,5 +1,5 @@ import sys -from typing import Any, AnyStr, Callable, Generic, Mapping, NamedTuple, Sequence, Tuple, Union, overload +from typing import Any, AnyStr, Callable, Generic, Mapping, NamedTuple, Sequence, Union, overload if sys.version_info >= (3, 9): from types import GenericAlias @@ -35,7 +35,7 @@ class _NetlocResultMixinBase(Generic[AnyStr]): class _NetlocResultMixinStr(_NetlocResultMixinBase[str], _ResultMixinStr): ... class _NetlocResultMixinBytes(_NetlocResultMixinBase[bytes], _ResultMixinBytes): ... -class _DefragResultBase(Tuple[Any, ...], Generic[AnyStr]): +class _DefragResultBase(tuple[Any, ...], Generic[AnyStr]): url: AnyStr fragment: AnyStr @@ -116,10 +116,10 @@ def urldefrag(url: bytes | None) -> DefragResultBytes: ... def urlencode( query: Mapping[Any, Any] | Mapping[Any, Sequence[Any]] | Sequence[tuple[Any, Any]] | Sequence[tuple[Any, Sequence[Any]]], doseq: bool = ..., - safe: AnyStr = ..., + safe: _Str = ..., encoding: str = ..., errors: str = ..., - quote_via: Callable[[str, AnyStr, str, str], str] = ..., + quote_via: Callable[[AnyStr, _Str, str, str], str] = ..., ) -> str: ... def urljoin(base: AnyStr, url: AnyStr | None, allow_fragments: bool = ...) -> AnyStr: ... @overload diff --git a/mypy/typeshed/stdlib/urllib/request.pyi b/mypy/typeshed/stdlib/urllib/request.pyi index 3c8a6facde6fb..3749d7a390ead 100644 --- a/mypy/typeshed/stdlib/urllib/request.pyi +++ b/mypy/typeshed/stdlib/urllib/request.pyi @@ -4,7 +4,7 @@ from _typeshed import StrOrBytesPath from email.message import Message from http.client import HTTPMessage, HTTPResponse, _HTTPConnectionProtocol from http.cookiejar import CookieJar -from typing import IO, Any, Callable, ClassVar, Mapping, NoReturn, Pattern, Sequence, Tuple, TypeVar, overload +from typing import IO, Any, Callable, ClassVar, Mapping, NoReturn, Pattern, Sequence, TypeVar, overload from urllib.error import HTTPError from urllib.response import addclosehook, addinfourl @@ -196,9 +196,9 @@ class HTTPSHandler(AbstractHTTPHandler): def https_request(self, request: Request) -> Request: ... # undocumented class FileHandler(BaseHandler): - names: ClassVar[Tuple[str, ...] | None] # undocumented + names: ClassVar[tuple[str, ...] | None] # undocumented def file_open(self, req: Request) -> addinfourl: ... - def get_names(self) -> Tuple[str, ...]: ... # undocumented + def get_names(self) -> tuple[str, ...]: ... # undocumented def open_local_file(self, req: Request) -> addinfourl: ... # undocumented class DataHandler(BaseHandler): diff --git a/mypy/typeshed/stdlib/urllib/response.pyi b/mypy/typeshed/stdlib/urllib/response.pyi index 647ebf8744320..18b498b407448 100644 --- a/mypy/typeshed/stdlib/urllib/response.pyi +++ b/mypy/typeshed/stdlib/urllib/response.pyi @@ -2,7 +2,7 @@ import sys from _typeshed import Self from email.message import Message from types import TracebackType -from typing import IO, Any, BinaryIO, Callable, Iterable, Tuple, Type, TypeVar +from typing import IO, Any, BinaryIO, Callable, Iterable, Type, TypeVar _AIUT = TypeVar("_AIUT", bound=addbase) @@ -37,7 +37,7 @@ class addbase(BinaryIO): class addclosehook(addbase): closehook: Callable[..., object] - hookargs: Tuple[Any, ...] + hookargs: tuple[Any, ...] def __init__(self, fp: IO[bytes], closehook: Callable[..., object], *hookargs: Any) -> None: ... class addinfo(addbase): diff --git a/mypy/typeshed/stdlib/uuid.pyi b/mypy/typeshed/stdlib/uuid.pyi index da13d819fbdf5..782c0491ffb2e 100644 --- a/mypy/typeshed/stdlib/uuid.pyi +++ b/mypy/typeshed/stdlib/uuid.pyi @@ -1,10 +1,10 @@ import sys -from typing import Any, Tuple +from typing import Any # Because UUID has properties called int and bytes we need to rename these temporarily. _Int = int _Bytes = bytes -_FieldsType = Tuple[int, int, int, int, int, int] +_FieldsType = tuple[int, int, int, int, int, int] if sys.version_info >= (3, 7): from enum import Enum diff --git a/mypy/typeshed/stdlib/venv/__init__.pyi b/mypy/typeshed/stdlib/venv/__init__.pyi index 25cf615a32431..7650e87d98b40 100644 --- a/mypy/typeshed/stdlib/venv/__init__.pyi +++ b/mypy/typeshed/stdlib/venv/__init__.pyi @@ -3,6 +3,9 @@ from _typeshed import StrOrBytesPath from types import SimpleNamespace from typing import Sequence +if sys.version_info >= (3, 9): + CORE_VENV_DEPS: tuple[str, ...] + class EnvBuilder: system_site_packages: bool clear: bool diff --git a/mypy/typeshed/stdlib/weakref.pyi b/mypy/typeshed/stdlib/weakref.pyi index dbb6b49f2f2e3..fd1cad7fe8407 100644 --- a/mypy/typeshed/stdlib/weakref.pyi +++ b/mypy/typeshed/stdlib/weakref.pyi @@ -1,5 +1,5 @@ from _weakrefset import WeakSet as WeakSet -from typing import Any, Callable, Generic, Iterable, Iterator, Mapping, MutableMapping, Tuple, Type, TypeVar, overload +from typing import Any, Callable, Generic, Iterable, Iterator, Mapping, MutableMapping, Type, TypeVar, overload from _weakref import ( CallableProxyType as CallableProxyType, @@ -17,7 +17,7 @@ _KT = TypeVar("_KT") _VT = TypeVar("_VT") _CallableT = TypeVar("_CallableT", bound=Callable[..., Any]) -ProxyTypes: Tuple[Type[Any], ...] +ProxyTypes: tuple[Type[Any], ...] class WeakMethod(ref[_CallableT], Generic[_CallableT]): def __new__(cls, meth: _CallableT, callback: Callable[[_CallableT], object] | None = ...) -> WeakMethod[_CallableT]: ... @@ -37,9 +37,9 @@ class WeakValueDictionary(MutableMapping[_KT, _VT]): def __str__(self) -> str: ... def copy(self) -> WeakValueDictionary[_KT, _VT]: ... # These are incompatible with Mapping - def keys(self) -> Iterator[_KT]: ... # type: ignore - def values(self) -> Iterator[_VT]: ... # type: ignore - def items(self) -> Iterator[tuple[_KT, _VT]]: ... # type: ignore + def keys(self) -> Iterator[_KT]: ... # type: ignore[override] + def values(self) -> Iterator[_VT]: ... # type: ignore[override] + def items(self) -> Iterator[tuple[_KT, _VT]]: ... # type: ignore[override] def itervaluerefs(self) -> Iterator[KeyedRef[_KT, _VT]]: ... def valuerefs(self) -> list[KeyedRef[_KT, _VT]]: ... def setdefault(self, key: _KT, default: _VT = ...) -> _VT: ... @@ -68,9 +68,9 @@ class WeakKeyDictionary(MutableMapping[_KT, _VT]): def __str__(self) -> str: ... def copy(self) -> WeakKeyDictionary[_KT, _VT]: ... # These are incompatible with Mapping - def keys(self) -> Iterator[_KT]: ... # type: ignore - def values(self) -> Iterator[_VT]: ... # type: ignore - def items(self) -> Iterator[tuple[_KT, _VT]]: ... # type: ignore + def keys(self) -> Iterator[_KT]: ... # type: ignore[override] + def values(self) -> Iterator[_VT]: ... # type: ignore[override] + def items(self) -> Iterator[tuple[_KT, _VT]]: ... # type: ignore[override] def keyrefs(self) -> list[ref[_KT]]: ... def setdefault(self, key: _KT, default: _VT = ...) -> _VT: ... @overload @@ -81,7 +81,7 @@ class WeakKeyDictionary(MutableMapping[_KT, _VT]): class finalize: def __init__(self, __obj: object, __func: Callable[..., Any], *args: Any, **kwargs: Any) -> None: ... def __call__(self, _: Any = ...) -> Any | None: ... - def detach(self) -> tuple[Any, Any, Tuple[Any, ...], dict[str, Any]] | None: ... - def peek(self) -> tuple[Any, Any, Tuple[Any, ...], dict[str, Any]] | None: ... + def detach(self) -> tuple[Any, Any, tuple[Any, ...], dict[str, Any]] | None: ... + def peek(self) -> tuple[Any, Any, tuple[Any, ...], dict[str, Any]] | None: ... alive: bool atexit: bool diff --git a/mypy/typeshed/stdlib/webbrowser.pyi b/mypy/typeshed/stdlib/webbrowser.pyi index c85288cc562f0..459d886ac9306 100644 --- a/mypy/typeshed/stdlib/webbrowser.pyi +++ b/mypy/typeshed/stdlib/webbrowser.pyi @@ -28,14 +28,9 @@ class BaseBrowser: def open_new_tab(self, url: str) -> bool: ... class GenericBrowser(BaseBrowser): - args: list[str] - name: str - basename: str def __init__(self, name: str | Sequence[str]) -> None: ... - def open(self, url: str, new: int = ..., autoraise: bool = ...) -> bool: ... -class BackgroundBrowser(GenericBrowser): - def open(self, url: str, new: int = ..., autoraise: bool = ...) -> bool: ... +class BackgroundBrowser(GenericBrowser): ... class UnixBrowser(BaseBrowser): raise_opts: list[str] | None @@ -45,59 +40,21 @@ class UnixBrowser(BaseBrowser): remote_action: str remote_action_newwin: str remote_action_newtab: str - def open(self, url: str, new: int = ..., autoraise: bool = ...) -> bool: ... -class Mozilla(UnixBrowser): - remote_args: list[str] - remote_action: str - remote_action_newwin: str - remote_action_newtab: str - background: bool +class Mozilla(UnixBrowser): ... class Galeon(UnixBrowser): raise_opts: list[str] - remote_args: list[str] - remote_action: str - remote_action_newwin: str - background: bool -class Chrome(UnixBrowser): - remote_args: list[str] - remote_action: str - remote_action_newwin: str - remote_action_newtab: str - background: bool - -class Opera(UnixBrowser): - remote_args: list[str] - remote_action: str - remote_action_newwin: str - remote_action_newtab: str - background: bool - -class Elinks(UnixBrowser): - remote_args: list[str] - remote_action: str - remote_action_newwin: str - remote_action_newtab: str - background: bool - redirect_stdout: bool - -class Konqueror(BaseBrowser): - def open(self, url: str, new: int = ..., autoraise: bool = ...) -> bool: ... - -class Grail(BaseBrowser): - def open(self, url: str, new: int = ..., autoraise: bool = ...) -> bool: ... +class Chrome(UnixBrowser): ... +class Opera(UnixBrowser): ... +class Elinks(UnixBrowser): ... +class Konqueror(BaseBrowser): ... +class Grail(BaseBrowser): ... if sys.platform == "win32": - class WindowsDefault(BaseBrowser): - def open(self, url: str, new: int = ..., autoraise: bool = ...) -> bool: ... + class WindowsDefault(BaseBrowser): ... if sys.platform == "darwin": - class MacOSX(BaseBrowser): - name: str - def __init__(self, name: str) -> None: ... - def open(self, url: str, new: int = ..., autoraise: bool = ...) -> bool: ... - class MacOSXOSAScript(BaseBrowser): - def __init__(self, name: str) -> None: ... - def open(self, url: str, new: int = ..., autoraise: bool = ...) -> bool: ... + class MacOSX(BaseBrowser): ... + class MacOSXOSAScript(BaseBrowser): ... # In runtime this class does not have `name` and `basename` diff --git a/mypy/typeshed/stdlib/winreg.pyi b/mypy/typeshed/stdlib/winreg.pyi index 5fff1104e2462..57f0c4b3ddba5 100644 --- a/mypy/typeshed/stdlib/winreg.pyi +++ b/mypy/typeshed/stdlib/winreg.pyi @@ -1,101 +1,101 @@ +import sys from _typeshed import Self from types import TracebackType from typing import Any, Type, Union -from typing_extensions import final +from typing_extensions import Literal, final -_KeyType = Union[HKEYType, int] +if sys.platform == "win32": + _KeyType = Union[HKEYType, int] + def CloseKey(__hkey: _KeyType) -> None: ... + def ConnectRegistry(__computer_name: str | None, __key: _KeyType) -> HKEYType: ... + def CreateKey(__key: _KeyType, __sub_key: str | None) -> HKEYType: ... + def CreateKeyEx(key: _KeyType, sub_key: str | None, reserved: int = ..., access: int = ...) -> HKEYType: ... + def DeleteKey(__key: _KeyType, __sub_key: str) -> None: ... + def DeleteKeyEx(key: _KeyType, sub_key: str, access: int = ..., reserved: int = ...) -> None: ... + def DeleteValue(__key: _KeyType, __value: str) -> None: ... + def EnumKey(__key: _KeyType, __index: int) -> str: ... + def EnumValue(__key: _KeyType, __index: int) -> tuple[str, Any, int]: ... + def ExpandEnvironmentStrings(__str: str) -> str: ... + def FlushKey(__key: _KeyType) -> None: ... + def LoadKey(__key: _KeyType, __sub_key: str, __file_name: str) -> None: ... + def OpenKey(key: _KeyType, sub_key: str, reserved: int = ..., access: int = ...) -> HKEYType: ... + def OpenKeyEx(key: _KeyType, sub_key: str, reserved: int = ..., access: int = ...) -> HKEYType: ... + def QueryInfoKey(__key: _KeyType) -> tuple[int, int, int]: ... + def QueryValue(__key: _KeyType, __sub_key: str | None) -> str: ... + def QueryValueEx(__key: _KeyType, __name: str) -> tuple[Any, int]: ... + def SaveKey(__key: _KeyType, __file_name: str) -> None: ... + def SetValue(__key: _KeyType, __sub_key: str, __type: int, __value: str) -> None: ... + def SetValueEx( + __key: _KeyType, __value_name: str | None, __reserved: Any, __type: int, __value: str | int + ) -> None: ... # reserved is ignored + def DisableReflectionKey(__key: _KeyType) -> None: ... + def EnableReflectionKey(__key: _KeyType) -> None: ... + def QueryReflectionKey(__key: _KeyType) -> bool: ... + HKEY_CLASSES_ROOT: int + HKEY_CURRENT_USER: int + HKEY_LOCAL_MACHINE: int + HKEY_USERS: int + HKEY_PERFORMANCE_DATA: int + HKEY_CURRENT_CONFIG: int + HKEY_DYN_DATA: int -def CloseKey(__hkey: _KeyType) -> None: ... -def ConnectRegistry(__computer_name: str | None, __key: _KeyType) -> HKEYType: ... -def CreateKey(__key: _KeyType, __sub_key: str | None) -> HKEYType: ... -def CreateKeyEx(key: _KeyType, sub_key: str | None, reserved: int = ..., access: int = ...) -> HKEYType: ... -def DeleteKey(__key: _KeyType, __sub_key: str) -> None: ... -def DeleteKeyEx(key: _KeyType, sub_key: str, access: int = ..., reserved: int = ...) -> None: ... -def DeleteValue(__key: _KeyType, __value: str) -> None: ... -def EnumKey(__key: _KeyType, __index: int) -> str: ... -def EnumValue(__key: _KeyType, __index: int) -> tuple[str, Any, int]: ... -def ExpandEnvironmentStrings(__str: str) -> str: ... -def FlushKey(__key: _KeyType) -> None: ... -def LoadKey(__key: _KeyType, __sub_key: str, __file_name: str) -> None: ... -def OpenKey(key: _KeyType, sub_key: str, reserved: int = ..., access: int = ...) -> HKEYType: ... -def OpenKeyEx(key: _KeyType, sub_key: str, reserved: int = ..., access: int = ...) -> HKEYType: ... -def QueryInfoKey(__key: _KeyType) -> tuple[int, int, int]: ... -def QueryValue(__key: _KeyType, __sub_key: str | None) -> str: ... -def QueryValueEx(__key: _KeyType, __name: str) -> tuple[Any, int]: ... -def SaveKey(__key: _KeyType, __file_name: str) -> None: ... -def SetValue(__key: _KeyType, __sub_key: str, __type: int, __value: str) -> None: ... -def SetValueEx( - __key: _KeyType, __value_name: str | None, __reserved: Any, __type: int, __value: str | int -) -> None: ... # reserved is ignored -def DisableReflectionKey(__key: _KeyType) -> None: ... -def EnableReflectionKey(__key: _KeyType) -> None: ... -def QueryReflectionKey(__key: _KeyType) -> bool: ... + KEY_ALL_ACCESS: Literal[983103] + KEY_WRITE: Literal[131078] + KEY_READ: Literal[131097] + KEY_EXECUTE: Literal[131097] + KEY_QUERY_VALUE: Literal[1] + KEY_SET_VALUE: Literal[2] + KEY_CREATE_SUB_KEY: Literal[4] + KEY_ENUMERATE_SUB_KEYS: Literal[8] + KEY_NOTIFY: Literal[16] + KEY_CREATE_LINK: Literal[32] -HKEY_CLASSES_ROOT: int -HKEY_CURRENT_USER: int -HKEY_LOCAL_MACHINE: int -HKEY_USERS: int -HKEY_PERFORMANCE_DATA: int -HKEY_CURRENT_CONFIG: int -HKEY_DYN_DATA: int + KEY_WOW64_64KEY: Literal[256] + KEY_WOW64_32KEY: Literal[512] -KEY_ALL_ACCESS: int -KEY_WRITE: int -KEY_READ: int -KEY_EXECUTE: int -KEY_QUERY_VALUE: int -KEY_SET_VALUE: int -KEY_CREATE_SUB_KEY: int -KEY_ENUMERATE_SUB_KEYS: int -KEY_NOTIFY: int -KEY_CREATE_LINK: int + REG_BINARY: Literal[3] + REG_DWORD: Literal[4] + REG_DWORD_LITTLE_ENDIAN: Literal[4] + REG_DWORD_BIG_ENDIAN: Literal[5] + REG_EXPAND_SZ: Literal[2] + REG_LINK: Literal[6] + REG_MULTI_SZ: Literal[7] + REG_NONE: Literal[0] + REG_QWORD: Literal[11] + REG_QWORD_LITTLE_ENDIAN: Literal[11] + REG_RESOURCE_LIST: Literal[8] + REG_FULL_RESOURCE_DESCRIPTOR: Literal[9] + REG_RESOURCE_REQUIREMENTS_LIST: Literal[10] + REG_SZ: Literal[1] -KEY_WOW64_64KEY: int -KEY_WOW64_32KEY: int + REG_CREATED_NEW_KEY: int # undocumented + REG_LEGAL_CHANGE_FILTER: int # undocumented + REG_LEGAL_OPTION: int # undocumented + REG_NOTIFY_CHANGE_ATTRIBUTES: int # undocumented + REG_NOTIFY_CHANGE_LAST_SET: int # undocumented + REG_NOTIFY_CHANGE_NAME: int # undocumented + REG_NOTIFY_CHANGE_SECURITY: int # undocumented + REG_NO_LAZY_FLUSH: int # undocumented + REG_OPENED_EXISTING_KEY: int # undocumented + REG_OPTION_BACKUP_RESTORE: int # undocumented + REG_OPTION_CREATE_LINK: int # undocumented + REG_OPTION_NON_VOLATILE: int # undocumented + REG_OPTION_OPEN_LINK: int # undocumented + REG_OPTION_RESERVED: int # undocumented + REG_OPTION_VOLATILE: int # undocumented + REG_REFRESH_HIVE: int # undocumented + REG_WHOLE_HIVE_VOLATILE: int # undocumented -REG_BINARY: int -REG_DWORD: int -REG_DWORD_LITTLE_ENDIAN: int -REG_DWORD_BIG_ENDIAN: int -REG_EXPAND_SZ: int -REG_LINK: int -REG_MULTI_SZ: int -REG_NONE: int -REG_QWORD: int -REG_QWORD_LITTLE_ENDIAN: int -REG_RESOURCE_LIST: int -REG_FULL_RESOURCE_DESCRIPTOR: int -REG_RESOURCE_REQUIREMENTS_LIST: int -REG_SZ: int + error = OSError -REG_CREATED_NEW_KEY: int # undocumented -REG_LEGAL_CHANGE_FILTER: int # undocumented -REG_LEGAL_OPTION: int # undocumented -REG_NOTIFY_CHANGE_ATTRIBUTES: int # undocumented -REG_NOTIFY_CHANGE_LAST_SET: int # undocumented -REG_NOTIFY_CHANGE_NAME: int # undocumented -REG_NOTIFY_CHANGE_SECURITY: int # undocumented -REG_NO_LAZY_FLUSH: int # undocumented -REG_OPENED_EXISTING_KEY: int # undocumented -REG_OPTION_BACKUP_RESTORE: int # undocumented -REG_OPTION_CREATE_LINK: int # undocumented -REG_OPTION_NON_VOLATILE: int # undocumented -REG_OPTION_OPEN_LINK: int # undocumented -REG_OPTION_RESERVED: int # undocumented -REG_OPTION_VOLATILE: int # undocumented -REG_REFRESH_HIVE: int # undocumented -REG_WHOLE_HIVE_VOLATILE: int # undocumented - -error = OSError - -# Though this class has a __name__ of PyHKEY, it's exposed as HKEYType for some reason -@final -class HKEYType: - def __bool__(self) -> bool: ... - def __int__(self) -> int: ... - def __enter__(self: Self) -> Self: ... - def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None - ) -> bool | None: ... - def Close(self) -> None: ... - def Detach(self) -> int: ... + # Though this class has a __name__ of PyHKEY, it's exposed as HKEYType for some reason + @final + class HKEYType: + def __bool__(self) -> bool: ... + def __int__(self) -> int: ... + def __enter__(self: Self) -> Self: ... + def __exit__( + self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> bool | None: ... + def Close(self) -> None: ... + def Detach(self) -> int: ... diff --git a/mypy/typeshed/stdlib/wsgiref/handlers.pyi b/mypy/typeshed/stdlib/wsgiref/handlers.pyi index ac1e56b7664eb..eccc0d1647678 100644 --- a/mypy/typeshed/stdlib/wsgiref/handlers.pyi +++ b/mypy/typeshed/stdlib/wsgiref/handlers.pyi @@ -1,12 +1,12 @@ from abc import abstractmethod from types import TracebackType -from typing import IO, Callable, MutableMapping, Optional, Tuple, Type +from typing import IO, Callable, MutableMapping, Optional, Type from .headers import Headers from .types import ErrorStream, InputStream, StartResponse, WSGIApplication, WSGIEnvironment from .util import FileWrapper -_exc_info = Tuple[Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType]] +_exc_info = tuple[Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType]] def format_date_time(timestamp: float | None) -> str: ... # undocumented def read_environ() -> dict[str, str]: ... diff --git a/mypy/typeshed/stdlib/wsgiref/headers.pyi b/mypy/typeshed/stdlib/wsgiref/headers.pyi index 531a521d38241..b62124a2a9368 100644 --- a/mypy/typeshed/stdlib/wsgiref/headers.pyi +++ b/mypy/typeshed/stdlib/wsgiref/headers.pyi @@ -1,6 +1,6 @@ -from typing import List, Pattern, Tuple, overload +from typing import Pattern, overload -_HeaderList = List[Tuple[str, str]] +_HeaderList = list[tuple[str, str]] tspecials: Pattern[str] # undocumented diff --git a/mypy/typeshed/stdlib/wsgiref/util.pyi b/mypy/typeshed/stdlib/wsgiref/util.pyi index a7f710e8012c1..c769c77d36e9e 100644 --- a/mypy/typeshed/stdlib/wsgiref/util.pyi +++ b/mypy/typeshed/stdlib/wsgiref/util.pyi @@ -1,3 +1,4 @@ +import sys from typing import IO, Any, Callable from .types import WSGIEnvironment @@ -7,7 +8,8 @@ class FileWrapper: blksize: int close: Callable[[], None] # only exists if filelike.close exists def __init__(self, filelike: IO[bytes], blksize: int = ...) -> None: ... - def __getitem__(self, key: Any) -> bytes: ... + if sys.version_info < (3, 11): + def __getitem__(self, key: Any) -> bytes: ... def __iter__(self) -> FileWrapper: ... def __next__(self) -> bytes: ... diff --git a/mypy/typeshed/stdlib/xml/dom/__init__.pyi b/mypy/typeshed/stdlib/xml/dom/__init__.pyi index c5766c326c3ea..e5b91bf2a7950 100644 --- a/mypy/typeshed/stdlib/xml/dom/__init__.pyi +++ b/mypy/typeshed/stdlib/xml/dom/__init__.pyi @@ -43,6 +43,7 @@ class IndexSizeErr(DOMException): ... class DomstringSizeErr(DOMException): ... class HierarchyRequestErr(DOMException): ... class WrongDocumentErr(DOMException): ... +class InvalidCharacterErr(DOMException): ... class NoDataAllowedErr(DOMException): ... class NoModificationAllowedErr(DOMException): ... class NotFoundErr(DOMException): ... diff --git a/mypy/typeshed/stdlib/xml/dom/expatbuilder.pyi b/mypy/typeshed/stdlib/xml/dom/expatbuilder.pyi index 964e6fa3f4269..58914e8fabf13 100644 --- a/mypy/typeshed/stdlib/xml/dom/expatbuilder.pyi +++ b/mypy/typeshed/stdlib/xml/dom/expatbuilder.pyi @@ -1,3 +1,99 @@ -from typing import Any +from typing import Any, NoReturn +from xml.dom.minidom import Document, DOMImplementation, Node, TypeInfo +from xml.dom.xmlbuilder import DOMBuilderFilter, Options -def __getattr__(name: str) -> Any: ... # incomplete +TEXT_NODE = Node.TEXT_NODE +CDATA_SECTION_NODE = Node.CDATA_SECTION_NODE +DOCUMENT_NODE = Node.DOCUMENT_NODE +FILTER_ACCEPT = DOMBuilderFilter.FILTER_ACCEPT +FILTER_REJECT = DOMBuilderFilter.FILTER_REJECT +FILTER_SKIP = DOMBuilderFilter.FILTER_SKIP +FILTER_INTERRUPT = DOMBuilderFilter.FILTER_INTERRUPT +theDOMImplementation: DOMImplementation | None + +class ElementInfo: + tagName: Any + def __init__(self, tagName, model: Any | None = ...) -> None: ... + def getAttributeType(self, aname) -> TypeInfo: ... + def getAttributeTypeNS(self, namespaceURI, localName) -> TypeInfo: ... + def isElementContent(self) -> bool: ... + def isEmpty(self) -> bool: ... + def isId(self, aname) -> bool: ... + def isIdNS(self, euri, ename, auri, aname) -> bool: ... + +class ExpatBuilder: + document: Document # Created in self.reset() + curNode: Any # Created in self.reset() + def __init__(self, options: Options | None = ...) -> None: ... + def createParser(self): ... + def getParser(self): ... + def reset(self) -> None: ... + def install(self, parser) -> None: ... + def parseFile(self, file) -> Document: ... + def parseString(self, string: str) -> Document: ... + def start_doctype_decl_handler(self, doctypeName, systemId, publicId, has_internal_subset) -> None: ... + def end_doctype_decl_handler(self) -> None: ... + def pi_handler(self, target, data) -> None: ... + def character_data_handler_cdata(self, data) -> None: ... + def character_data_handler(self, data) -> None: ... + def start_cdata_section_handler(self) -> None: ... + def end_cdata_section_handler(self) -> None: ... + def entity_decl_handler(self, entityName, is_parameter_entity, value, base, systemId, publicId, notationName) -> None: ... + def notation_decl_handler(self, notationName, base, systemId, publicId) -> None: ... + def comment_handler(self, data) -> None: ... + def external_entity_ref_handler(self, context, base, systemId, publicId) -> int: ... + def first_element_handler(self, name, attributes) -> None: ... + def start_element_handler(self, name, attributes) -> None: ... + def end_element_handler(self, name) -> None: ... + def element_decl_handler(self, name, model) -> None: ... + def attlist_decl_handler(self, elem, name, type, default, required) -> None: ... + def xml_decl_handler(self, version, encoding, standalone) -> None: ... + +class FilterVisibilityController: + filter: DOMBuilderFilter + def __init__(self, filter: DOMBuilderFilter) -> None: ... + def startContainer(self, node: Node) -> int: ... + def acceptNode(self, node: Node) -> int: ... + +class FilterCrutch: + def __init__(self, builder) -> None: ... + +class Rejecter(FilterCrutch): + def start_element_handler(self, *args: Any) -> None: ... + def end_element_handler(self, *args: Any) -> None: ... + +class Skipper(FilterCrutch): + def start_element_handler(self, *args: Any) -> None: ... + def end_element_handler(self, *args: Any) -> None: ... + +class FragmentBuilder(ExpatBuilder): + fragment: Any | None + originalDocument: Any + context: Any + def __init__(self, context, options: Options | None = ...) -> None: ... + +class Namespaces: + def createParser(self): ... + def install(self, parser) -> None: ... + def start_namespace_decl_handler(self, prefix, uri) -> None: ... + def start_element_handler(self, name, attributes) -> None: ... + def end_element_handler(self, name) -> None: ... + +class ExpatBuilderNS(Namespaces, ExpatBuilder): ... +class FragmentBuilderNS(Namespaces, FragmentBuilder): ... +class ParseEscape(Exception): ... + +class InternalSubsetExtractor(ExpatBuilder): + subset: Any | None + def getSubset(self) -> Any | None: ... + def parseFile(self, file) -> None: ... # type: ignore[override] + def parseString(self, string: str) -> None: ... # type: ignore[override] + def start_doctype_decl_handler(self, name, publicId, systemId, has_internal_subset) -> None: ... # type: ignore[override] + def end_doctype_decl_handler(self) -> NoReturn: ... + def start_element_handler(self, name, attrs) -> NoReturn: ... + +def parse(file, namespaces: bool = ...): ... +def parseString(string: str, namespaces: bool = ...): ... +def parseFragment(file, context, namespaces: bool = ...): ... +def parseFragmentString(string: str, context, namespaces: bool = ...): ... +def makeBuilder(options: Options) -> ExpatBuilderNS | ExpatBuilder: ... diff --git a/mypy/typeshed/stdlib/xml/dom/minicompat.pyi b/mypy/typeshed/stdlib/xml/dom/minicompat.pyi index 4bc60f7ab9650..38e6d05e4743e 100644 --- a/mypy/typeshed/stdlib/xml/dom/minicompat.pyi +++ b/mypy/typeshed/stdlib/xml/dom/minicompat.pyi @@ -1,17 +1,17 @@ -from typing import Any, Iterable, List, Tuple, Type, TypeVar +from typing import Any, Iterable, Type, TypeVar _T = TypeVar("_T") StringTypes: tuple[Type[str]] -class NodeList(List[_T]): +class NodeList(list[_T]): length: int def item(self, index: int) -> _T | None: ... -class EmptyNodeList(Tuple[Any, ...]): +class EmptyNodeList(tuple[Any, ...]): length: int def item(self, index: int) -> None: ... - def __add__(self, other: Iterable[_T]) -> NodeList[_T]: ... # type: ignore + def __add__(self, other: Iterable[_T]) -> NodeList[_T]: ... # type: ignore[override] def __radd__(self, other: Iterable[_T]) -> NodeList[_T]: ... def defproperty(klass: Type[Any], name: str, doc: str) -> None: ... diff --git a/mypy/typeshed/stdlib/xml/dom/minidom.pyi b/mypy/typeshed/stdlib/xml/dom/minidom.pyi index 4d1d7a9d0faff..e9a26e30d7219 100644 --- a/mypy/typeshed/stdlib/xml/dom/minidom.pyi +++ b/mypy/typeshed/stdlib/xml/dom/minidom.pyi @@ -70,6 +70,10 @@ class Attr(Node): self, qName: str, namespaceURI: str | None = ..., localName: Any | None = ..., prefix: Any | None = ... ) -> None: ... def unlink(self) -> None: ... + @property + def isId(self) -> bool: ... + @property + def schemaType(self) -> Any: ... class NamedNodeMap: def __init__(self, attrs, attrsNS, ownerElement) -> None: ... @@ -96,6 +100,8 @@ class NamedNodeMap: def setNamedItem(self, node): ... def setNamedItemNS(self, node): ... def __delitem__(self, attname_or_tuple) -> None: ... + @property + def length(self) -> int: ... AttributeList = NamedNodeMap @@ -110,6 +116,7 @@ class Element(Node): schemaType: Any parentNode: Any tagName: str + nodeName: str prefix: Any namespaceURI: str | None childNodes: Any @@ -139,6 +146,8 @@ class Element(Node): def setIdAttribute(self, name) -> None: ... def setIdAttributeNS(self, namespaceURI: str, localName) -> None: ... def setIdAttributeNode(self, idAttr) -> None: ... + @property + def attributes(self) -> NamedNodeMap: ... class Childless: attributes: Any @@ -173,6 +182,8 @@ class CharacterData(Childless, Node): def insertData(self, offset: int, arg: str) -> None: ... def deleteData(self, offset: int, count: int) -> None: ... def replaceData(self, offset: int, count: int, arg: str) -> None: ... + @property + def length(self) -> int: ... class Text(CharacterData): nodeType: Any @@ -182,6 +193,10 @@ class Text(CharacterData): def splitText(self, offset): ... def writexml(self, writer, indent: str = ..., addindent: str = ..., newl: str = ...) -> None: ... def replaceWholeText(self, content): ... + @property + def isWhitespaceInElementContent(self) -> bool: ... + @property + def wholeText(self) -> str: ... class Comment(CharacterData): nodeType: Any @@ -205,15 +220,17 @@ class ReadOnlySequentialNamedNodeMap: def removeNamedItemNS(self, namespaceURI: str, localName) -> None: ... def setNamedItem(self, node) -> None: ... def setNamedItemNS(self, node) -> None: ... + @property + def length(self) -> int: ... -class Identified: ... +class Identified: + publicId: Any + systemId: Any class DocumentType(Identified, Childless, Node): nodeType: Any nodeValue: Any name: Any - publicId: Any - systemId: Any internalSubset: Any entities: Any notations: Any diff --git a/mypy/typeshed/stdlib/xml/dom/pulldom.pyi b/mypy/typeshed/stdlib/xml/dom/pulldom.pyi index ce8816b4a98a0..c2b7aa0772fa1 100644 --- a/mypy/typeshed/stdlib/xml/dom/pulldom.pyi +++ b/mypy/typeshed/stdlib/xml/dom/pulldom.pyi @@ -1,4 +1,5 @@ -from typing import IO, Any, Sequence, Tuple, Union +import sys +from typing import IO, Any, Sequence, Union from typing_extensions import Literal from xml.dom.minidom import Document, DOMImplementation, Element, Text from xml.sax.handler import ContentHandler @@ -16,7 +17,7 @@ CHARACTERS: Literal["CHARACTERS"] _DocumentFactory = Union[DOMImplementation, None] _Node = Union[Document, Element, Text] -_Event = Tuple[ +_Event = tuple[ Literal[ Literal["START_ELEMENT"], Literal["END_ELEMENT"], @@ -66,7 +67,8 @@ class DOMEventStream: bufsize: int def __init__(self, stream: IO[bytes], parser: XMLReader, bufsize: int) -> None: ... pulldom: Any - def __getitem__(self, pos): ... + if sys.version_info < (3, 11): + def __getitem__(self, pos): ... def __next__(self): ... def __iter__(self): ... def getEvent(self) -> _Event: ... diff --git a/mypy/typeshed/stdlib/xml/dom/xmlbuilder.pyi b/mypy/typeshed/stdlib/xml/dom/xmlbuilder.pyi index d8936bdc2ab4e..2738d735e73f5 100644 --- a/mypy/typeshed/stdlib/xml/dom/xmlbuilder.pyi +++ b/mypy/typeshed/stdlib/xml/dom/xmlbuilder.pyi @@ -1,6 +1,107 @@ -from typing import Any +from typing import Any, NoReturn, Optional +from typing_extensions import Literal +from urllib.request import OpenerDirector +from xml.dom.expatbuilder import ExpatBuilder, ExpatBuilderNS +from xml.dom.minidom import Node -def __getattr__(name: str) -> Any: ... # incomplete +# UNKNOWN TYPES: +# - `Options.errorHandler`. +# The same as `_DOMBuilderErrorHandlerType`? +# Maybe `xml.sax.handler.ErrorHandler`? +# - Return type of DOMBuilder.getFeature(). +# We could get rid of the `Any` if we knew more +# about `Options.errorHandler`. -class DocumentLS(Any): ... # type: ignore -class DOMImplementationLS(Any): ... # type: ignore +# ALIASES REPRESENTING MORE UNKNOWN TYPES: + +# probably the same as `Options.errorHandler`? +# Maybe `xml.sax.handler.ErrorHandler`? +_DOMBuilderErrorHandlerType = Optional[Any] +# probably some kind of IO... +_DOMInputSourceCharacterStreamType = Optional[Any] +# probably a string?? +_DOMInputSourceStringDataType = Optional[Any] +# probably a string?? +_DOMInputSourceEncodingType = Optional[Any] + +class Options: + namespaces: int + namespace_declarations: bool + validation: bool + external_parameter_entities: bool + external_general_entities: bool + external_dtd_subset: bool + validate_if_schema: bool + validate: bool + datatype_normalization: bool + create_entity_ref_nodes: bool + entities: bool + whitespace_in_element_content: bool + cdata_sections: bool + comments: bool + charset_overrides_xml_encoding: bool + infoset: bool + supported_mediatypes_only: bool + errorHandler: Any | None + filter: DOMBuilderFilter | None # a guess, but seems likely + +class DOMBuilder: + entityResolver: DOMEntityResolver | None # a guess, but seems likely + errorHandler: _DOMBuilderErrorHandlerType + filter: DOMBuilderFilter | None # a guess, but seems likely + ACTION_REPLACE: Literal[1] + ACTION_APPEND_AS_CHILDREN: Literal[2] + ACTION_INSERT_AFTER: Literal[3] + ACTION_INSERT_BEFORE: Literal[4] + def __init__(self) -> None: ... + def setFeature(self, name: str, state: int) -> None: ... + def supportsFeature(self, name: str) -> bool: ... + def canSetFeature(self, name: str, state: int) -> bool: ... + # getFeature could return any attribute from an instance of `Options` + def getFeature(self, name: str) -> Any: ... + def parseURI(self, uri: str) -> ExpatBuilder | ExpatBuilderNS: ... + def parse(self, input: DOMInputSource) -> ExpatBuilder | ExpatBuilderNS: ... + # `input` and `cnode` argtypes for `parseWithContext` are unknowable + # as the function does nothing with them, and always raises an exception. + # But `input` is *probably* `DOMInputSource`? + def parseWithContext(self, input: object, cnode: object, action: Literal[1, 2, 3, 4]) -> NoReturn: ... + +class DOMEntityResolver: + def resolveEntity(self, publicId: str | None, systemId: str) -> DOMInputSource: ... + +class DOMInputSource: + byteStream: OpenerDirector | None + characterStream: _DOMInputSourceCharacterStreamType + stringData: _DOMInputSourceStringDataType + encoding: _DOMInputSourceEncodingType + publicId: str | None + systemId: str | None + baseURI: str | None + +class DOMBuilderFilter: + FILTER_ACCEPT: Literal[1] + FILTER_REJECT: Literal[2] + FILTER_SKIP: Literal[3] + FILTER_INTERRUPT: Literal[4] + whatToShow: int + # The argtypes for acceptNode and startContainer appear to be irrelevant. + def acceptNode(self, element: object) -> Literal[1]: ... + def startContainer(self, element: object) -> Literal[1]: ... + +class DocumentLS: + async_: bool + def abort(self) -> NoReturn: ... + # `load()` and `loadXML()` always raise exceptions + # so the argtypes of `uri` and `source` are unknowable. + # `source` is *probably* `DOMInputSource`? + # `uri` is *probably* a str? (see DOMBuilder.parseURI()) + def load(self, uri: object) -> NoReturn: ... + def loadXML(self, source: object) -> NoReturn: ... + def saveXML(self, snode: Node | None) -> str: ... + +class DOMImplementationLS: + MODE_SYNCHRONOUS: Literal[1] + MODE_ASYNCHRONOUS: Literal[2] + def createDOMBuilder(self, mode: Literal[1], schemaType: None) -> DOMBuilder: ... + def createDOMWriter(self) -> NoReturn: ... + def createDOMInputSource(self) -> DOMInputSource: ... diff --git a/mypy/typeshed/stdlib/xml/etree/ElementInclude.pyi b/mypy/typeshed/stdlib/xml/etree/ElementInclude.pyi index 0ccccce4f3d05..b355bef1208c3 100644 --- a/mypy/typeshed/stdlib/xml/etree/ElementInclude.pyi +++ b/mypy/typeshed/stdlib/xml/etree/ElementInclude.pyi @@ -6,6 +6,9 @@ XINCLUDE: str XINCLUDE_INCLUDE: str XINCLUDE_FALLBACK: str +if sys.version_info >= (3, 9): + DEFAULT_MAX_INCLUSION_DEPTH: int + class FatalIncludeError(SyntaxError): ... def default_loader(href: str | bytes | int, parse: str, encoding: str | None = ...) -> str | Element: ... @@ -17,6 +20,7 @@ if sys.version_info >= (3, 9): def include( elem: Element, loader: Callable[..., str | Element] | None = ..., base_url: str | None = ..., max_depth: int | None = ... ) -> None: ... + class LimitedRecursiveIncludeError(FatalIncludeError): ... else: def include(elem: Element, loader: Callable[..., str | Element] | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/xml/etree/ElementPath.pyi b/mypy/typeshed/stdlib/xml/etree/ElementPath.pyi index db4bd6a4e9585..5a2dd69c1beea 100644 --- a/mypy/typeshed/stdlib/xml/etree/ElementPath.pyi +++ b/mypy/typeshed/stdlib/xml/etree/ElementPath.pyi @@ -1,11 +1,11 @@ -from typing import Callable, Generator, List, Pattern, Tuple, TypeVar +from typing import Callable, Generator, Pattern, TypeVar from xml.etree.ElementTree import Element xpath_tokenizer_re: Pattern[str] -_token = Tuple[str, str] +_token = tuple[str, str] _next = Callable[[], _token] -_callback = Callable[[_SelectorContext, List[Element]], Generator[Element, None, None]] +_callback = Callable[[_SelectorContext, list[Element]], Generator[Element, None, None]] def xpath_tokenizer(pattern: str, namespaces: dict[str, str] | None = ...) -> Generator[_token, None, None]: ... def get_parent_map(context: _SelectorContext) -> dict[Element, Element]: ... diff --git a/mypy/typeshed/stdlib/xml/etree/ElementTree.pyi b/mypy/typeshed/stdlib/xml/etree/ElementTree.pyi index 03a20dcad4cba..c4236cf292bb6 100644 --- a/mypy/typeshed/stdlib/xml/etree/ElementTree.pyi +++ b/mypy/typeshed/stdlib/xml/etree/ElementTree.pyi @@ -4,19 +4,19 @@ from typing import ( IO, Any, Callable, - Dict, Generator, ItemsView, Iterable, Iterator, KeysView, + Mapping, MutableSequence, Sequence, TypeVar, Union, overload, ) -from typing_extensions import Literal +from typing_extensions import Literal, SupportsIndex _T = TypeVar("_T") _File = Union[StrOrBytesPath, FileDescriptor, IO[Any]] @@ -87,14 +87,14 @@ class Element(MutableSequence[Element]): def makeelement(self, __tag: str, __attrib: dict[str, str]) -> Element: ... def remove(self, __subelement: Element) -> None: ... def set(self, __key: str, __value: str) -> None: ... - def __delitem__(self, i: int | slice) -> None: ... + def __delitem__(self, i: SupportsIndex | slice) -> None: ... @overload - def __getitem__(self, i: int) -> Element: ... + def __getitem__(self, i: SupportsIndex) -> Element: ... @overload def __getitem__(self, s: slice) -> MutableSequence[Element]: ... def __len__(self) -> int: ... @overload - def __setitem__(self, i: int, o: Element) -> None: ... + def __setitem__(self, i: SupportsIndex, o: Element) -> None: ... @overload def __setitem__(self, s: slice, o: Iterable[Element]) -> None: ... if sys.version_info < (3, 9): @@ -256,14 +256,32 @@ def fromstringlist(sequence: Sequence[str | bytes], parser: XMLParser | None = . # TreeBuilder is called by client code (they could pass strs, bytes or whatever); # but we don't want to use a too-broad type, or it would be too hard to write # elementfactories. -_ElementFactory = Callable[[Any, Dict[Any, Any]], Element] +_ElementFactory = Callable[[Any, dict[Any, Any]], Element] class TreeBuilder: - def __init__(self, element_factory: _ElementFactory | None = ...) -> None: ... + if sys.version_info >= (3, 8): + # comment_factory can take None because passing None to Comment is not an error + def __init__( + self, + element_factory: _ElementFactory | None = ..., + *, + comment_factory: Callable[[str | None], Element] | None = ..., + pi_factory: Callable[[str, str | None], Element] | None = ..., + insert_comments: bool = ..., + insert_pis: bool = ..., + ) -> None: ... + insert_comments: bool + insert_pis: bool + else: + def __init__(self, element_factory: _ElementFactory | None = ...) -> None: ... def close(self) -> Element: ... def data(self, __data: str | bytes) -> None: ... def start(self, __tag: str | bytes, __attrs: dict[str | bytes, str | bytes]) -> Element: ... def end(self, __tag: str | bytes) -> Element: ... + if sys.version_info >= (3, 8): + # These two methods have pos-only parameters in the C implementation + def comment(self, __text: str | None) -> Element: ... + def pi(self, __target: str, __text: str | None = ...) -> Element: ... if sys.version_info >= (3, 8): class C14NWriterTarget: @@ -279,6 +297,12 @@ if sys.version_info >= (3, 8): exclude_attrs: Iterable[str] | None = ..., exclude_tags: Iterable[str] | None = ..., ) -> None: ... + def data(self, data: str) -> None: ... + def start_ns(self, prefix: str, uri: str) -> None: ... + def start(self, tag: str, attrs: Mapping[str, str]) -> None: ... + def end(self, tag: str) -> None: ... + def comment(self, text: str) -> None: ... + def pi(self, target: str, data: str) -> None: ... class XMLParser: parser: Any diff --git a/mypy/typeshed/stdlib/xmlrpc/client.pyi b/mypy/typeshed/stdlib/xmlrpc/client.pyi index 061df849eff20..e9f9e03ae56db 100644 --- a/mypy/typeshed/stdlib/xmlrpc/client.pyi +++ b/mypy/typeshed/stdlib/xmlrpc/client.pyi @@ -6,16 +6,16 @@ from _typeshed import Self, SupportsRead, SupportsWrite from datetime import datetime from io import BytesIO from types import TracebackType -from typing import Any, Callable, Dict, Iterable, List, Mapping, Protocol, Tuple, Type, Union, overload +from typing import Any, Callable, Iterable, Mapping, Protocol, Type, Union, overload from typing_extensions import Literal class _SupportsTimeTuple(Protocol): def timetuple(self) -> time.struct_time: ... _DateTimeComparable = Union[DateTime, datetime, str, _SupportsTimeTuple] -_Marshallable = Union[None, bool, int, float, str, bytes, Tuple[Any, ...], List[Any], Dict[Any, Any], datetime, DateTime, Binary] -_XMLDate = Union[int, datetime, Tuple[int, ...], time.struct_time] -_HostType = Union[Tuple[str, Dict[str, str]], str] +_Marshallable = Union[None, bool, int, float, str, bytes, tuple[Any, ...], list[Any], dict[Any, Any], datetime, DateTime, Binary] +_XMLDate = Union[int, datetime, tuple[int, ...], time.struct_time] +_HostType = Union[tuple[str, dict[str, str]], str] def escape(s: str) -> str: ... # undocumented @@ -63,12 +63,12 @@ def _strftime(value: _XMLDate) -> str: ... # undocumented class DateTime: value: str # undocumented - def __init__(self, value: int | str | datetime | time.struct_time | Tuple[int, ...] = ...) -> None: ... + def __init__(self, value: int | str | datetime | time.struct_time | tuple[int, ...] = ...) -> None: ... def __lt__(self, other: _DateTimeComparable) -> bool: ... def __le__(self, other: _DateTimeComparable) -> bool: ... def __gt__(self, other: _DateTimeComparable) -> bool: ... def __ge__(self, other: _DateTimeComparable) -> bool: ... - def __eq__(self, other: _DateTimeComparable) -> bool: ... # type: ignore + def __eq__(self, other: _DateTimeComparable) -> bool: ... # type: ignore[override] def make_comparable(self, other: _DateTimeComparable) -> tuple[str, str]: ... # undocumented def timetuple(self) -> time.struct_time: ... # undocumented def decode(self, data: Any) -> None: ... @@ -135,7 +135,7 @@ class Unmarshaller: _use_datetime: bool _use_builtin_types: bool def __init__(self, use_datetime: bool = ..., use_builtin_types: bool = ...) -> None: ... - def close(self) -> Tuple[_Marshallable, ...]: ... + def close(self) -> tuple[_Marshallable, ...]: ... def getmethodname(self) -> str | None: ... def xml(self, encoding: str, standalone: Any) -> None: ... # Standalone is ignored def start(self, tag: str, attrs: dict[str, str]) -> None: ... @@ -159,7 +159,7 @@ class Unmarshaller: class _MultiCallMethod: # undocumented - __call_list: list[tuple[str, Tuple[_Marshallable, ...]]] + __call_list: list[tuple[str, tuple[_Marshallable, ...]]] __name: str def __init__(self, call_list: list[tuple[str, _Marshallable]], name: str) -> None: ... def __getattr__(self, name: str) -> _MultiCallMethod: ... @@ -174,7 +174,7 @@ class MultiCallIterator: # undocumented class MultiCall: __server: ServerProxy - __call_list: list[tuple[str, Tuple[_Marshallable, ...]]] + __call_list: list[tuple[str, tuple[_Marshallable, ...]]] def __init__(self, server: ServerProxy) -> None: ... def __getattr__(self, item: str) -> _MultiCallMethod: ... def __call__(self) -> MultiCallIterator: ... @@ -186,13 +186,13 @@ FastUnmarshaller: Unmarshaller | None def getparser(use_datetime: bool = ..., use_builtin_types: bool = ...) -> tuple[ExpatParser, Unmarshaller]: ... def dumps( - params: Fault | Tuple[_Marshallable, ...], + params: Fault | tuple[_Marshallable, ...], methodname: str | None = ..., methodresponse: bool | None = ..., encoding: str | None = ..., allow_none: bool = ..., ) -> str: ... -def loads(data: str, use_datetime: bool = ..., use_builtin_types: bool = ...) -> tuple[Tuple[_Marshallable, ...], str | None]: ... +def loads(data: str, use_datetime: bool = ..., use_builtin_types: bool = ...) -> tuple[tuple[_Marshallable, ...], str | None]: ... def gzip_encode(data: bytes) -> bytes: ... # undocumented def gzip_decode(data: bytes, max_decode: int = ...) -> bytes: ... # undocumented @@ -204,9 +204,9 @@ class GzipDecodedResponse(gzip.GzipFile): # undocumented class _Method: # undocumented - __send: Callable[[str, Tuple[_Marshallable, ...]], _Marshallable] + __send: Callable[[str, tuple[_Marshallable, ...]], _Marshallable] __name: str - def __init__(self, send: Callable[[str, Tuple[_Marshallable, ...]], _Marshallable], name: str) -> None: ... + def __init__(self, send: Callable[[str, tuple[_Marshallable, ...]], _Marshallable], name: str) -> None: ... def __getattr__(self, name: str) -> _Method: ... def __call__(self, *args: _Marshallable) -> _Marshallable: ... @@ -228,10 +228,10 @@ class Transport: ) -> None: ... else: def __init__(self, use_datetime: bool = ..., use_builtin_types: bool = ...) -> None: ... - def request(self, host: _HostType, handler: str, request_body: bytes, verbose: bool = ...) -> Tuple[_Marshallable, ...]: ... + def request(self, host: _HostType, handler: str, request_body: bytes, verbose: bool = ...) -> tuple[_Marshallable, ...]: ... def single_request( self, host: _HostType, handler: str, request_body: bytes, verbose: bool = ... - ) -> Tuple[_Marshallable, ...]: ... + ) -> tuple[_Marshallable, ...]: ... def getparser(self) -> tuple[ExpatParser, Unmarshaller]: ... def get_host_info(self, host: _HostType) -> tuple[str, list[tuple[str, str]], dict[str, str]]: ... def make_connection(self, host: _HostType) -> http.client.HTTPConnection: ... @@ -239,7 +239,7 @@ class Transport: def send_request(self, host: _HostType, handler: str, request_body: bytes, debug: bool) -> http.client.HTTPConnection: ... def send_headers(self, connection: http.client.HTTPConnection, headers: list[tuple[str, str]]) -> None: ... def send_content(self, connection: http.client.HTTPConnection, request_body: bytes) -> None: ... - def parse_response(self, response: http.client.HTTPResponse) -> Tuple[_Marshallable, ...]: ... + def parse_response(self, response: http.client.HTTPResponse) -> tuple[_Marshallable, ...]: ... class SafeTransport(Transport): @@ -304,6 +304,6 @@ class ServerProxy: self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> None: ... def __close(self) -> None: ... # undocumented - def __request(self, methodname: str, params: Tuple[_Marshallable, ...]) -> Tuple[_Marshallable, ...]: ... # undocumented + def __request(self, methodname: str, params: tuple[_Marshallable, ...]) -> tuple[_Marshallable, ...]: ... # undocumented Server = ServerProxy diff --git a/mypy/typeshed/stdlib/xmlrpc/server.pyi b/mypy/typeshed/stdlib/xmlrpc/server.pyi index bf5611fbaa96b..48105d1461f02 100644 --- a/mypy/typeshed/stdlib/xmlrpc/server.pyi +++ b/mypy/typeshed/stdlib/xmlrpc/server.pyi @@ -3,11 +3,11 @@ import pydoc import socketserver import sys from datetime import datetime -from typing import Any, Callable, Dict, Iterable, List, Mapping, Pattern, Protocol, Tuple, Type, Union +from typing import Any, Callable, Iterable, Mapping, Pattern, Protocol, Type, Union from xmlrpc.client import Fault # TODO: Recursive type on tuple, list, dict -_Marshallable = Union[None, bool, int, float, str, bytes, Tuple[Any, ...], List[Any], Dict[Any, Any], datetime] +_Marshallable = Union[None, bool, int, float, str, bytes, tuple[Any, ...], list[Any], dict[Any, Any], datetime] # The dispatch accepts anywhere from 0 to N arguments, no easy way to allow this in mypy class _DispatchArity0(Protocol): @@ -53,7 +53,7 @@ class SimpleXMLRPCDispatcher: # undocumented def _marshaled_dispatch( self, data: str, - dispatch_method: Callable[[str | None, Tuple[_Marshallable, ...]], Fault | Tuple[_Marshallable, ...]] | None = ..., + dispatch_method: Callable[[str | None, tuple[_Marshallable, ...]], Fault | tuple[_Marshallable, ...]] | None = ..., path: Any | None = ..., ) -> str: ... # undocumented def system_listMethods(self) -> list[str]: ... # undocumented @@ -109,7 +109,7 @@ class MultiPathXMLRPCServer(SimpleXMLRPCServer): # undocumented def _marshaled_dispatch( self, data: str, - dispatch_method: Callable[[str | None, Tuple[_Marshallable, ...]], Fault | Tuple[_Marshallable, ...]] | None = ..., + dispatch_method: Callable[[str | None, tuple[_Marshallable, ...]], Fault | tuple[_Marshallable, ...]] | None = ..., path: Any | None = ..., ) -> str: ... @@ -120,7 +120,16 @@ class CGIXMLRPCRequestHandler(SimpleXMLRPCDispatcher): def handle_request(self, request_text: str | None = ...) -> None: ... class ServerHTMLDoc(pydoc.HTMLDoc): # undocumented - def docroutine(self, object: object, name: str, mod: str | None = ..., funcs: Mapping[str, str] = ..., classes: Mapping[str, str] = ..., methods: Mapping[str, str] = ..., cl: type | None = ...) -> str: ... # type: ignore + def docroutine( # type: ignore[override] + self, + object: object, + name: str, + mod: str | None = ..., + funcs: Mapping[str, str] = ..., + classes: Mapping[str, str] = ..., + methods: Mapping[str, str] = ..., + cl: type | None = ..., + ) -> str: ... def docserver(self, server_name: str, package_documentation: str, methods: dict[str, str]) -> str: ... class XMLRPCDocGenerator: # undocumented diff --git a/mypy/typeshed/stdlib/zipfile.pyi b/mypy/typeshed/stdlib/zipfile.pyi index 2335428549dc1..c64690ba8ca9a 100644 --- a/mypy/typeshed/stdlib/zipfile.pyi +++ b/mypy/typeshed/stdlib/zipfile.pyi @@ -3,10 +3,10 @@ import sys from _typeshed import Self, StrPath from os import PathLike from types import TracebackType -from typing import IO, Any, Callable, Iterable, Iterator, Protocol, Sequence, Tuple, Type, overload +from typing import IO, Any, Callable, Iterable, Iterator, Protocol, Sequence, Type, overload from typing_extensions import Literal -_DateTuple = Tuple[int, int, int, int, int, int] +_DateTuple = tuple[int, int, int, int, int, int] _ReadWriteMode = Literal["r", "w"] _ReadWriteBinaryMode = Literal["r", "w", "rb", "wb"] _ZipFileMode = Literal["r", "w", "x", "a"] @@ -97,10 +97,10 @@ class ZipExtFile(io.BufferedIOBase): close_fileobj: Literal[False] = ..., ) -> None: ... def read(self, n: int | None = ...) -> bytes: ... - def readline(self, limit: int = ...) -> bytes: ... # type: ignore + def readline(self, limit: int = ...) -> bytes: ... # type: ignore[override] def __repr__(self) -> str: ... def peek(self, n: int = ...) -> bytes: ... - def read1(self, n: int | None) -> bytes: ... # type: ignore + def read1(self, n: int | None) -> bytes: ... # type: ignore[override] if sys.version_info >= (3, 7): def seek(self, offset: int, whence: int = ...) -> int: ... diff --git a/mypy/typeshed/stdlib/zipimport.pyi b/mypy/typeshed/stdlib/zipimport.pyi index 155b9742aa578..3435092a47220 100644 --- a/mypy/typeshed/stdlib/zipimport.pyi +++ b/mypy/typeshed/stdlib/zipimport.pyi @@ -1,5 +1,6 @@ import os import sys +from importlib.machinery import ModuleSpec from types import CodeType, ModuleType from typing import Any @@ -8,7 +9,7 @@ if sys.version_info >= (3, 7): class ZipImportError(ImportError): ... -class zipimporter(object): +class zipimporter: archive: str prefix: str def __init__(self, path: str | bytes | os.PathLike[Any]) -> None: ... @@ -22,3 +23,6 @@ class zipimporter(object): def get_source(self, fullname: str) -> str | None: ... def is_package(self, fullname: str) -> bool: ... def load_module(self, fullname: str) -> ModuleType: ... + if sys.version_info >= (3, 10): + def find_spec(self, fullname: str, target: ModuleType | None = ...) -> ModuleSpec | None: ... + def invalidate_caches(self) -> None: ... diff --git a/mypy/typeshed/stdlib/zlib.pyi b/mypy/typeshed/stdlib/zlib.pyi index 5acc4190f1fea..646c96bd2bef2 100644 --- a/mypy/typeshed/stdlib/zlib.pyi +++ b/mypy/typeshed/stdlib/zlib.pyi @@ -1,12 +1,16 @@ from array import array from typing import Any +from typing_extensions import Literal DEFLATED: int DEF_MEM_LEVEL: int MAX_WBITS: int ZLIB_VERSION: str +Z_NO_COMPRESSION: Literal[0] +Z_PARTIAL_FLUSH: Literal[1] Z_BEST_COMPRESSION: int Z_BEST_SPEED: int +Z_BLOCK: Literal[5] Z_DEFAULT_COMPRESSION: int Z_DEFAULT_STRATEGY: int Z_FILTERED: int @@ -17,6 +21,7 @@ Z_HUFFMAN_ONLY: int Z_NO_FLUSH: int Z_RLE: int Z_SYNC_FLUSH: int +Z_TREES: Literal[6] DEF_BUF_SIZE: int ZLIB_RUNTIME_VERSION: str diff --git a/mypy/typeshed/stubs/mypy-extensions/mypy_extensions.pyi b/mypy/typeshed/stubs/mypy-extensions/mypy_extensions.pyi index fc6de37d07d1a..dd182c485177b 100644 --- a/mypy/typeshed/stubs/mypy-extensions/mypy_extensions.pyi +++ b/mypy/typeshed/stubs/mypy-extensions/mypy_extensions.pyi @@ -1,6 +1,6 @@ import abc import sys -from typing import Any, Callable, Generic, ItemsView, KeysView, Mapping, Type, TypeVar, Union, ValuesView +from typing import Any, Callable, Generic, ItemsView, KeysView, Mapping, Type, TypeVar, ValuesView _T = TypeVar("_T") _U = TypeVar("_U") @@ -34,9 +34,8 @@ def VarArg(type: _T = ...) -> _T: ... def KwArg(type: _T = ...) -> _T: ... # Return type that indicates a function does not return. -# This type is equivalent to the None type, but the no-op Union is necessary to -# distinguish the None type from the None value. -NoReturn = Union[None] # Deprecated: Use typing.NoReturn instead. +# Deprecated: Use typing.NoReturn instead. +class NoReturn: ... # This is intended as a class decorator, but mypy rejects abstract classes # when a Type[_T] is expected, so we can't give it the type we want diff --git a/test-data/unit/pythoneval.test b/test-data/unit/pythoneval.test index ab1593dac7541..993af4ced61e1 100644 --- a/test-data/unit/pythoneval.test +++ b/test-data/unit/pythoneval.test @@ -1112,7 +1112,7 @@ c2 = Cell2() reveal_type(c2.pop('value')) [out] _testTypedDictMappingMethods.py:5: note: Revealed type is "builtins.str*" -_testTypedDictMappingMethods.py:6: note: Revealed type is "typing.Iterator[builtins.str*]" +_testTypedDictMappingMethods.py:6: note: Revealed type is "typing.Iterator*[builtins.str*]" _testTypedDictMappingMethods.py:7: note: Revealed type is "builtins.int" _testTypedDictMappingMethods.py:8: note: Revealed type is "builtins.bool" _testTypedDictMappingMethods.py:9: note: Revealed type is "typing.KeysView[builtins.str]" @@ -1152,7 +1152,8 @@ _testCanConvertTypedDictToAnySuperclassOfMapping.py:11: note: def __iter _testCanConvertTypedDictToAnySuperclassOfMapping.py:11: note: Got: _testCanConvertTypedDictToAnySuperclassOfMapping.py:11: note: def __iter__(self) -> Iterator[str] -[case testAsyncioGatherPreciseType] +[case testAsyncioGatherPreciseType-xfail] +# Mysteriously regressed in #11905 import asyncio from typing import Tuple @@ -1328,7 +1329,7 @@ def f() -> Dict[int, str]: def d() -> Dict[int, int]: return {} [out] -_testDictWithStarStarSpecialCase.py:4: error: Argument 1 to "update" of "dict" has incompatible type "Dict[int, int]"; expected "Mapping[int, str]" +_testDictWithStarStarSpecialCase.py:4: error: Argument 1 to "update" of "MutableMapping" has incompatible type "Dict[int, int]"; expected "SupportsKeysAndGetItem[int, str]" [case testLoadsOfOverloads] from typing import overload, Any, TypeVar, Iterable, List, Dict, Callable, Union From 7af46ceaf479a458d6409884fceae9a9ee51b582 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Fri, 28 Jan 2022 11:53:41 +0300 Subject: [PATCH 083/377] Forbid extra `ParamSpec` arguments (#12024) * Forbid extra `ParamSpec` arguments * Change error message --- mypy/semanal.py | 9 +++++++++ test-data/unit/check-parameter-specification.test | 10 ++++++++++ 2 files changed, 19 insertions(+) diff --git a/mypy/semanal.py b/mypy/semanal.py index 2a24c129b133a..340db6c0c2524 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -3292,6 +3292,15 @@ def process_paramspec_declaration(self, s: AssignmentStmt) -> bool: if not self.check_typevarlike_name(call, name, s): return False + # ParamSpec is different from a regular TypeVar: + # arguments are not semantically valid. But, allowed in runtime. + # So, we need to warn users about possible invalid usage. + if len(call.args) > 1: + self.fail( + "Only the first argument to ParamSpec has defined semantics", + s, + ) + # PEP 612 reserves the right to define bound, covariant and contravariant arguments to # ParamSpec in a later PEP. If and when that happens, we should do something # on the lines of process_typevar_parameters diff --git a/test-data/unit/check-parameter-specification.test b/test-data/unit/check-parameter-specification.test index f6123915aadad..f2281babb193e 100644 --- a/test-data/unit/check-parameter-specification.test +++ b/test-data/unit/check-parameter-specification.test @@ -3,6 +3,16 @@ from typing_extensions import ParamSpec P = ParamSpec('P') [builtins fixtures/tuple.pyi] +[case testInvalidParamSpecDefinitions] +from typing import ParamSpec + +P1 = ParamSpec("P1", covariant=True) # E: Only the first argument to ParamSpec has defined semantics +P2 = ParamSpec("P2", contravariant=True) # E: Only the first argument to ParamSpec has defined semantics +P3 = ParamSpec("P3", bound=int) # E: Only the first argument to ParamSpec has defined semantics +P4 = ParamSpec("P4", int, str) # E: Only the first argument to ParamSpec has defined semantics +P5 = ParamSpec("P5", covariant=True, bound=int) # E: Only the first argument to ParamSpec has defined semantics +[builtins fixtures/tuple.pyi] + [case testParamSpecLocations] from typing import Callable, List from typing_extensions import ParamSpec, Concatenate From ace9f25afecbf625be3fba1ebeba189e1149cf62 Mon Sep 17 00:00:00 2001 From: Akuli Date: Fri, 28 Jan 2022 18:52:44 +0200 Subject: [PATCH 084/377] Delete workarounds for fixed typeshed bugs (#12093) --- mypy/checkexpr.py | 5 ++--- mypy/ipc.py | 3 --- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 9bf3ec3a4456c..36f92898edb79 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -4,7 +4,7 @@ from contextlib import contextmanager import itertools from typing import ( - Any, cast, Dict, Set, List, Tuple, Callable, Union, Optional, Sequence, Iterator + cast, Dict, Set, List, Tuple, Callable, Union, Optional, Sequence, Iterator ) from typing_extensions import ClassVar, Final, overload, TypeAlias as _TypeAlias @@ -1607,8 +1607,7 @@ def check_overload_call(self, # Record if we succeeded. Next we need to see if maybe normal procedure # gives a narrower type. if unioned_return: - # TODO: fix signature of zip() in typeshed. - returns, inferred_types = cast(Any, zip)(*unioned_return) + returns, inferred_types = zip(*unioned_return) # Note that we use `combine_function_signatures` instead of just returning # a union of inferred callables because for example a call # Union[int -> int, str -> str](Union[int, str]) is invalid and diff --git a/mypy/ipc.py b/mypy/ipc.py index 8a6a310d7ff85..f48ac18075d80 100644 --- a/mypy/ipc.py +++ b/mypy/ipc.py @@ -54,9 +54,6 @@ def read(self, size: int = 100000) -> bytes: if sys.platform == 'win32': while True: ov, err = _winapi.ReadFile(self.connection, size, overlapped=True) - # TODO: remove once typeshed supports Literal types - assert isinstance(ov, _winapi.Overlapped) - assert isinstance(err, int) try: if err == _winapi.ERROR_IO_PENDING: timeout = int(self.timeout * 1000) if self.timeout else _winapi.INFINITE From 8f9ebf04cd1cd04dc0a7ec6e66024776b3987f17 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Fri, 28 Jan 2022 20:33:28 +0000 Subject: [PATCH 085/377] Run self-check on Windows as part of CI (#11909) As discussed in #11895, mypy's test suite currently does not pass a mypy self-check when run on Windows. This should hopefully be fixed by https://github.com/python/typeshed/pull/6812, but running a self-check on Windows as part of the CI tests should help avoid this issue in the future. --- .github/workflows/test.yml | 7 ++++++- mypy/util.py | 4 +++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7b3740bc4b15e..2551fb0444826 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -75,11 +75,16 @@ jobs: toxenv: py36 tox_extra_args: "-n 2 mypyc/test/test_run.py mypyc/test/test_external.py" debug_build: true - - name: Type check our own code + - name: Type check our own code (py37-ubuntu) python: '3.7' arch: x64 os: ubuntu-latest toxenv: type + - name: Type check our own code (py37-windows-64) + python: '3.7' + arch: x64 + os: windows-latest + toxenv: type - name: Code style with flake8 python: '3.7' arch: x64 diff --git a/mypy/util.py b/mypy/util.py index cd1e15afb4cf1..2d6888dd0a2e6 100644 --- a/mypy/util.py +++ b/mypy/util.py @@ -517,6 +517,8 @@ def hash_digest(data: bytes) -> str: def parse_gray_color(cup: bytes) -> str: """Reproduce a gray color in ANSI escape sequence""" + if sys.platform == "win32": + assert False, "curses is not available on Windows" set_color = ''.join([cup[:-1].decode(), 'm']) gray = curses.tparm(set_color.encode('utf-8'), 1, 89).decode() return gray @@ -580,7 +582,7 @@ def initialize_win_colors(self) -> bool: def initialize_unix_colors(self) -> bool: """Return True if initialization was successful and we can use colors, False otherwise""" - if not CURSES_ENABLED: + if sys.platform == "win32" or not CURSES_ENABLED: return False try: # setupterm wants a fd to potentially write an "initialization sequence". From 080bb0e04e9d5c4d2513621d1fb62f1d61a573e9 Mon Sep 17 00:00:00 2001 From: Akuli Date: Sun, 30 Jan 2022 08:55:18 +0200 Subject: [PATCH 086/377] stubtest: error if a class should be decorated with @final (#12091) --- mypy/stubtest.py | 18 ++++++++++++++++++ mypy/test/teststubtest.py | 31 +++++++++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/mypy/stubtest.py b/mypy/stubtest.py index 4ca088d8aa3ee..df36935a801fc 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -254,6 +254,24 @@ def verify_typeinfo( yield Error(object_path, "is not a type", stub, runtime, stub_desc=repr(stub)) return + try: + class SubClass(runtime): # type: ignore + pass + except TypeError: + # Enum classes are implicitly @final + if not stub.is_final and not issubclass(runtime, enum.Enum): + yield Error( + object_path, + "cannot be subclassed at runtime, but isn't marked with @final in the stub", + stub, + runtime, + stub_desc=repr(stub), + ) + except Exception: + # The class probably wants its subclasses to do something special. + # Examples: ctypes.Array, ctypes._SimpleCData + pass + # Check everything already defined in the stub to_check = set(stub.names) # There's a reasonable case to be made that we should always check all dunders, but it's diff --git a/mypy/test/teststubtest.py b/mypy/test/teststubtest.py index 30ed953d73900..2852299548ed5 100644 --- a/mypy/test/teststubtest.py +++ b/mypy/test/teststubtest.py @@ -691,8 +691,13 @@ def test_special_dunders(self) -> Iterator[Case]: ) if sys.version_info >= (3, 6): yield Case( - stub="class C:\n def __init_subclass__(cls, e: int, **kwargs: int) -> None: ...", - runtime="class C:\n def __init_subclass__(cls, e, **kwargs): pass", + stub=( + "class C:\n" + " def __init_subclass__(\n" + " cls, e: int = ..., **kwargs: int\n" + " ) -> None: ...\n" + ), + runtime="class C:\n def __init_subclass__(cls, e=1, **kwargs): pass", error=None, ) if sys.version_info >= (3, 9): @@ -702,6 +707,28 @@ def test_special_dunders(self) -> Iterator[Case]: error=None, ) + def test_not_subclassable(self) -> None: + output = run_stubtest( + stub=( + "class CanBeSubclassed: ...\n" + "class CanNotBeSubclassed:\n" + " def __init_subclass__(cls) -> None: ...\n" + ), + runtime=( + "class CanNotBeSubclassed:\n" + " def __init_subclass__(cls): raise TypeError('nope')\n" + # ctypes.Array can be subclassed, but subclasses must define a few + # special attributes, e.g. _length_ + "from ctypes import Array as CanBeSubclassed\n" + ), + options=[], + ) + assert ( + "CanNotBeSubclassed cannot be subclassed at runtime," + " but isn't marked with @final in the stub" + ) in output + assert "CanBeSubclassed cannot be subclassed" not in output + @collect_cases def test_name_mangling(self) -> Iterator[Case]: yield Case( From 3b331b30049bb085485b8aa7c1fe34064cab927e Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Sun, 30 Jan 2022 23:32:33 +0000 Subject: [PATCH 087/377] Fix "Implicit type aliases not recognised with PEP 604 + import cycles" (but only for stubs) (#11915) --- mypy/semanal.py | 13 ++++++----- test-data/unit/check-union-or-syntax.test | 27 +++++++++++++++++++++++ 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 340db6c0c2524..2d7c4c7e3d4ca 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -2177,11 +2177,14 @@ def can_be_type_alias(self, rv: Expression, allow_none: bool = False) -> bool: return True if allow_none and isinstance(rv, NameExpr) and rv.fullname == 'builtins.None': return True - if (isinstance(rv, OpExpr) - and rv.op == '|' - and self.can_be_type_alias(rv.left, allow_none=True) - and self.can_be_type_alias(rv.right, allow_none=True)): - return True + if isinstance(rv, OpExpr) and rv.op == '|': + if self.is_stub_file: + return True + if ( + self.can_be_type_alias(rv.left, allow_none=True) + and self.can_be_type_alias(rv.right, allow_none=True) + ): + return True return False def is_type_ref(self, rv: Expression, bare: bool = False) -> bool: diff --git a/test-data/unit/check-union-or-syntax.test b/test-data/unit/check-union-or-syntax.test index 3e5a19b8fe61f..58526cfd06233 100644 --- a/test-data/unit/check-union-or-syntax.test +++ b/test-data/unit/check-union-or-syntax.test @@ -196,3 +196,30 @@ def f(x: Union[int, str, None]) -> None: else: reveal_type(x) # N: Revealed type is "None" [builtins fixtures/isinstance.pyi] + +[case testImplicit604TypeAliasWithCyclicImportInStub] +# flags: --python-version 3.10 +from was_builtins import foo +reveal_type(foo) # N: Revealed type is "Union[builtins.str, was_mmap.mmap]" +[file was_builtins.pyi] +import was_mmap +WriteableBuffer = was_mmap.mmap +ReadableBuffer = str | WriteableBuffer +foo: ReadableBuffer +[file was_mmap.pyi] +from was_builtins import * +class mmap: ... + +# TODO: Get this test to pass +[case testImplicit604TypeAliasWithCyclicImportNotInStub-xfail] +# flags: --python-version 3.10 +from was_builtins import foo +reveal_type(foo) # N: Revealed type is "Union[builtins.str, was_mmap.mmap]" +[file was_builtins.py] +import was_mmap +WriteableBuffer = was_mmap.mmap +ReadableBuffer = str | WriteableBuffer +foo: ReadableBuffer +[file was_mmap.py] +from was_builtins import * +class mmap: ... From c0e49abcf27ff59e761f3ec06a24ee94e700464d Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Tue, 1 Feb 2022 00:23:19 +0000 Subject: [PATCH 088/377] Read pyproject.toml with correct encoding on Windows (#12105) --- mypy/build.py | 2 +- test-data/unit/cmdline.pyproject.test | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/mypy/build.py b/mypy/build.py index f3df5f18f54dd..e636b606ed8f1 100644 --- a/mypy/build.py +++ b/mypy/build.py @@ -511,7 +511,7 @@ def find_config_file_line_number(path: str, section: str, setting_name: str) -> in_desired_section = False try: results = [] - with open(path) as f: + with open(path, encoding="UTF-8") as f: for i, line in enumerate(f): line = line.strip() if line.startswith('[') and line.endswith(']'): diff --git a/test-data/unit/cmdline.pyproject.test b/test-data/unit/cmdline.pyproject.test index ea561ed164e75..831bce2eb63d1 100644 --- a/test-data/unit/cmdline.pyproject.test +++ b/test-data/unit/cmdline.pyproject.test @@ -125,3 +125,11 @@ i: int = 0 This isn't even syntatically valid! [file x/please_skipme_.py] Neither is this! + +[case testPyprojectTOMLUnicode] +# cmd: mypy x.py +[file pyproject.toml] +\[project] +description = "Factory ⸻ A code generator 🏭" +\[tool.mypy] +[file x.py] From 84b977876aa76bfebf5fe49d11ebd202e4a60a33 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Thu, 3 Feb 2022 07:33:44 -0800 Subject: [PATCH 089/377] add support for typing.reveal_type (#12117) --- mypy/semanal.py | 4 ++-- mypy/types.py | 6 ++++++ test-data/unit/check-expressions.test | 16 ++++++++++++++++ test-data/unit/lib-stub/typing.pyi | 2 ++ test-data/unit/lib-stub/typing_extensions.pyi | 2 ++ 5 files changed, 28 insertions(+), 2 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 2d7c4c7e3d4ca..876866963e6bd 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -98,7 +98,7 @@ CallableType, Overloaded, Instance, Type, AnyType, LiteralType, LiteralValue, TypeTranslator, TypeOfAny, TypeType, NoneType, PlaceholderType, TPDICT_NAMES, ProperType, get_proper_type, get_proper_types, TypeAliasType, TypeVarLikeType, - PROTOCOL_NAMES, TYPE_ALIAS_NAMES, FINAL_TYPE_NAMES, FINAL_DECORATOR_NAMES, + PROTOCOL_NAMES, TYPE_ALIAS_NAMES, FINAL_TYPE_NAMES, FINAL_DECORATOR_NAMES, REVEAL_TYPE_NAMES, is_named_instance, ) from mypy.typeops import function_type, get_type_vars @@ -3877,7 +3877,7 @@ def visit_call_expr(self, expr: CallExpr) -> None: expr.analyzed.line = expr.line expr.analyzed.column = expr.column expr.analyzed.accept(self) - elif refers_to_fullname(expr.callee, 'builtins.reveal_type'): + elif refers_to_fullname(expr.callee, REVEAL_TYPE_NAMES): if not self.check_fixed_args(expr, 1, 'reveal_type'): return expr.analyzed = RevealExpr(kind=REVEAL_TYPE, expr=expr.args[0]) diff --git a/mypy/types.py b/mypy/types.py index 1d7ab669a2d4e..5aecb8194f9ec 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -126,6 +126,12 @@ 'typing.Reversible', ) +REVEAL_TYPE_NAMES: Final = ( + 'builtins.reveal_type', + 'typing.reveal_type', + 'typing_extensions.reveal_type', +) + # A placeholder used for Bogus[...] parameters _dummy: Final[Any] = object() diff --git a/test-data/unit/check-expressions.test b/test-data/unit/check-expressions.test index a275de94c9be6..543502e651154 100644 --- a/test-data/unit/check-expressions.test +++ b/test-data/unit/check-expressions.test @@ -1688,6 +1688,22 @@ main:1: note: Revealed type is "Any" def reveal_type(x: int) -> None: pass reveal_type("foo") # E: Argument 1 to "reveal_type" has incompatible type "str"; expected "int" +[case testTypingRevealType] +from typing import reveal_type +from typing import reveal_type as show_me_the_type + +reveal_type(1) # N: Revealed type is "Literal[1]?" +show_me_the_type(1) # N: Revealed type is "Literal[1]?" + +[case testTypingExtensionsRevealType] +from typing_extensions import reveal_type +from typing_extensions import reveal_type as show_me_the_type + +reveal_type(1) # N: Revealed type is "Literal[1]?" +show_me_the_type(1) # N: Revealed type is "Literal[1]?" + +[builtins fixtures/tuple.pyi] + [case testRevealTypeVar] reveal_type = 1 1 + "foo" # E: Unsupported operand types for + ("int" and "str") diff --git a/test-data/unit/lib-stub/typing.pyi b/test-data/unit/lib-stub/typing.pyi index b9f1752aee1bd..7283b47a96e76 100644 --- a/test-data/unit/lib-stub/typing.pyi +++ b/test-data/unit/lib-stub/typing.pyi @@ -47,3 +47,5 @@ class Sequence(Iterable[T_co]): class Mapping(Iterable[T], Generic[T, T_co]): pass def final(meth: T) -> T: pass + +def reveal_type(__obj: T) -> T: pass diff --git a/test-data/unit/lib-stub/typing_extensions.pyi b/test-data/unit/lib-stub/typing_extensions.pyi index 5b32449e71cf2..7c6e14e404cd1 100644 --- a/test-data/unit/lib-stub/typing_extensions.pyi +++ b/test-data/unit/lib-stub/typing_extensions.pyi @@ -44,3 +44,5 @@ class _TypedDict(Mapping[str, object]): def __delitem__(self, k: NoReturn) -> None: ... def TypedDict(typename: str, fields: Dict[str, Type[_T]], *, total: Any = ...) -> Type[dict]: ... + +def reveal_type(__obj: T) -> T: pass From 04cac4b5d911c4f9529e6ce86a27b44f28846f5d Mon Sep 17 00:00:00 2001 From: Joshua Cannon Date: Fri, 4 Feb 2022 07:42:03 +0000 Subject: [PATCH 090/377] [mypyc] Add helpful message to assert (#12119) --- mypyc/irbuild/prepare.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypyc/irbuild/prepare.py b/mypyc/irbuild/prepare.py index 3f028d9009437..2cb3deac97002 100644 --- a/mypyc/irbuild/prepare.py +++ b/mypyc/irbuild/prepare.py @@ -142,7 +142,7 @@ def prepare_method_def(ir: ClassIR, module_name: str, cdef: ClassDef, mapper: Ma ir.method_decls[PROPSET_PREFIX + node.name] = decl if node.func.is_property: - assert node.func.type + assert node.func.type, f"Expected return type annotation for property '{node.name}'" decl.is_prop_getter = True ir.property_types[node.name] = decl.sig.ret_type From 26fdd456b7e665c3c0f161234ee48b9e6144940d Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Sat, 5 Feb 2022 15:08:42 +0300 Subject: [PATCH 091/377] Update mypy_primer_comment.yml --- .github/workflows/mypy_primer_comment.yml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/.github/workflows/mypy_primer_comment.yml b/.github/workflows/mypy_primer_comment.yml index edc91b190e29b..8c61f365606cd 100644 --- a/.github/workflows/mypy_primer_comment.yml +++ b/.github/workflows/mypy_primer_comment.yml @@ -38,6 +38,9 @@ jobs: fs.writeFileSync("diff.zip", Buffer.from(download.data)); - run: unzip diff.zip + # 30000 bytes is about 300 lines, posting comment fails if too long + - run: | + cat diff_*.txt | head -c 30000 | tee fulldiff.txt # Based on https://github.com/kanga333/comment-hider - name: Hide old comments @@ -77,13 +80,7 @@ jobs: github-token: ${{secrets.GITHUB_TOKEN}} script: | const fs = require('fs') - // Keep in sync with shards produced by mypy_primer workflow - const data = ( - ['diff_0.txt', 'diff_1.txt', 'diff_2.txt'] - .map(fileName => fs.readFileSync(fileName, { encoding: 'utf8' })) - .join('') - .substr(0, 30000) // About 300 lines - ) + const data = fs.readFileSync('fulldiff.txt', { encoding: 'utf8' }) console.log("Diff from mypy_primer:") console.log(data) From 48dc990427d3619c107f193757a3ce735e9ca409 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Sun, 6 Feb 2022 10:44:36 +0300 Subject: [PATCH 092/377] Sync `mypy_primer_comment` with `typeshed` (#12125) --- .github/workflows/mypy_primer_comment.yml | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/.github/workflows/mypy_primer_comment.yml b/.github/workflows/mypy_primer_comment.yml index 8c61f365606cd..05e0e7d3815b6 100644 --- a/.github/workflows/mypy_primer_comment.yml +++ b/.github/workflows/mypy_primer_comment.yml @@ -85,12 +85,17 @@ jobs: console.log("Diff from mypy_primer:") console.log(data) + let body if (data.trim()) { - const body = 'Diff from [mypy_primer](https://github.com/hauntsaninja/mypy_primer), showing the effect of this PR on open source code:\n```diff\n' + data + '```' - await github.issues.createComment({ - issue_number: fs.readFileSync("pr_number.txt", { encoding: "utf8" }), - owner: context.repo.owner, - repo: context.repo.repo, - body - }) + body = 'Diff from [mypy_primer](https://github.com/hauntsaninja/mypy_primer), showing the effect of this PR on open source code:\n```diff\n' + data + '```' + } else { + body = 'According to [mypy_primer](https://github.com/hauntsaninja/mypy_primer), this change has no effect on the checked open source code. 🤖🎉' } + const prNumber = parseInt(fs.readFileSync("pr_number.txt", { encoding: "utf8" })) + await github.issues.createComment({ + issue_number: prNumber, + owner: context.repo.owner, + repo: context.repo.repo, + body + }) + return prNumber From 1ccefbdff922b502637009a77632a2be10256297 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Sun, 6 Feb 2022 19:22:38 +0300 Subject: [PATCH 093/377] Improve `.editorconfig` to include `.test` files (#12133) --- .editorconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.editorconfig b/.editorconfig index 461d93d21a34b..07f00de06ee44 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,11 +1,11 @@ root = true -[*.{py,c,cpp,h,rst,md,yml,json}] +[*.{py,c,cpp,h,rst,md,yml,json,test}] trim_trailing_whitespace = true insert_final_newline = true indent_style = space -[*.{py,c,h,json}] +[*.{py,c,h,json,test}] indent_size = 4 [*.yml] From 872c03da11b7e8a11c724e337577b2233573b3b3 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Mon, 7 Feb 2022 10:33:42 +0300 Subject: [PATCH 094/377] Sync `mypy_primer_comment` with `typeshed` (#12136) --- .github/workflows/mypy_primer_comment.yml | 43 ++++++----------------- 1 file changed, 10 insertions(+), 33 deletions(-) diff --git a/.github/workflows/mypy_primer_comment.yml b/.github/workflows/mypy_primer_comment.yml index 05e0e7d3815b6..9aa5b7a7131ec 100644 --- a/.github/workflows/mypy_primer_comment.yml +++ b/.github/workflows/mypy_primer_comment.yml @@ -42,42 +42,11 @@ jobs: - run: | cat diff_*.txt | head -c 30000 | tee fulldiff.txt - # Based on https://github.com/kanga333/comment-hider - - name: Hide old comments - uses: actions/github-script@v3 - with: - github-token: ${{secrets.GITHUB_TOKEN}} - script: | - const fs = require('fs') - - const response = await github.issues.listComments({ - issue_number: fs.readFileSync("pr_number.txt", { encoding: "utf8" }), - owner: context.repo.owner, - repo: context.repo.repo, - }) - const botCommentIds = response.data - .filter(comment => comment.user.login === 'github-actions[bot]') - .map(comment => comment.node_id) - - for (const id of botCommentIds) { - const resp = await github.graphql(` - mutation { - minimizeComment(input: {classifier: OUTDATED, subjectId: "${id}"}) { - minimizedComment { - isMinimized - } - } - } - `) - if (resp.errors) { - throw new Error(resp.errors) - } - } - - name: Post comment + id: post-comment uses: actions/github-script@v3 with: - github-token: ${{secrets.GITHUB_TOKEN}} + github-token: ${{ secrets.GITHUB_TOKEN }} script: | const fs = require('fs') const data = fs.readFileSync('fulldiff.txt', { encoding: 'utf8' }) @@ -99,3 +68,11 @@ jobs: body }) return prNumber + + - name: Hide old comments + # v0.3.0 + uses: kanga333/comment-hider@bbdf5b562fbec24e6f60572d8f712017428b92e0 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + leave_visible: 1 + issue_number: ${{ steps.post-comment.outputs.result }} From 06475709ded9480220004c2bdfcb86287f7f3d34 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Tue, 8 Feb 2022 22:30:13 -0800 Subject: [PATCH 095/377] Delete `open` plugin (#9275) Improvements to typeshed types using literals should have rendered this unnecessary. --- mypy/plugins/default.py | 61 ++-------------------------------- mypy/report.py | 4 +-- mypyc/build.py | 4 +-- test-data/unit/pythoneval.test | 30 ++++++++--------- 4 files changed, 21 insertions(+), 78 deletions(-) diff --git a/mypy/plugins/default.py b/mypy/plugins/default.py index c57c5f9a18d9b..acbb0460ae07a 100644 --- a/mypy/plugins/default.py +++ b/mypy/plugins/default.py @@ -2,10 +2,9 @@ from typing import Callable, Optional, List from mypy import message_registry -from mypy.nodes import Expression, StrExpr, IntExpr, DictExpr, UnaryExpr +from mypy.nodes import StrExpr, IntExpr, DictExpr, UnaryExpr from mypy.plugin import ( - Plugin, FunctionContext, MethodContext, MethodSigContext, AttributeContext, ClassDefContext, - CheckerPluginInterface, + Plugin, FunctionContext, MethodContext, MethodSigContext, AttributeContext, ClassDefContext ) from mypy.plugins.common import try_getting_str_literals from mypy.types import ( @@ -26,8 +25,6 @@ def get_function_hook(self, fullname: str if fullname in ('contextlib.contextmanager', 'contextlib.asynccontextmanager'): return contextmanager_callback - elif fullname == 'builtins.open' and self.python_version[0] == 3: - return open_callback elif fullname == 'ctypes.Array': return ctypes.array_constructor_callback elif fullname == 'functools.singledispatch': @@ -74,8 +71,6 @@ def get_method_hook(self, fullname: str return ctypes.array_getitem_callback elif fullname == 'ctypes.Array.__iter__': return ctypes.array_iter_callback - elif fullname == 'pathlib.Path.open': - return path_open_callback elif fullname == singledispatch.SINGLEDISPATCH_REGISTER_METHOD: return singledispatch.singledispatch_register_callback elif fullname == singledispatch.REGISTER_CALLABLE_CALL_METHOD: @@ -129,58 +124,6 @@ def get_class_decorator_hook(self, fullname: str return None -def open_callback(ctx: FunctionContext) -> Type: - """Infer a better return type for 'open'.""" - return _analyze_open_signature( - arg_types=ctx.arg_types, - args=ctx.args, - mode_arg_index=1, - default_return_type=ctx.default_return_type, - api=ctx.api, - ) - - -def path_open_callback(ctx: MethodContext) -> Type: - """Infer a better return type for 'pathlib.Path.open'.""" - return _analyze_open_signature( - arg_types=ctx.arg_types, - args=ctx.args, - mode_arg_index=0, - default_return_type=ctx.default_return_type, - api=ctx.api, - ) - - -def _analyze_open_signature(arg_types: List[List[Type]], - args: List[List[Expression]], - mode_arg_index: int, - default_return_type: Type, - api: CheckerPluginInterface, - ) -> Type: - """A helper for analyzing any function that has approximately - the same signature as the builtin 'open(...)' function. - - Currently, the only thing the caller can customize is the index - of the 'mode' argument. If the mode argument is omitted or is a - string literal, we refine the return type to either 'TextIO' or - 'BinaryIO' as appropriate. - """ - mode = None - if not arg_types or len(arg_types[mode_arg_index]) != 1: - mode = 'r' - else: - mode_expr = args[mode_arg_index][0] - if isinstance(mode_expr, StrExpr): - mode = mode_expr.value - if mode is not None: - assert isinstance(default_return_type, Instance) # type: ignore - if 'b' in mode: - return api.named_generic_type('typing.BinaryIO', []) - else: - return api.named_generic_type('typing.TextIO', []) - return default_return_type - - def contextmanager_callback(ctx: FunctionContext) -> Type: """Infer a better return type for 'contextlib.contextmanager'.""" # Be defensive, just in case. diff --git a/mypy/report.py b/mypy/report.py index 380a8c6b64417..23b5c78ef9298 100644 --- a/mypy/report.py +++ b/mypy/report.py @@ -245,10 +245,10 @@ def _write_out_report(self, f.write(separator + '\n') for row_values in rows: r = ("{:>{}}" * len(widths)).format(*itertools.chain(*zip(row_values, widths))) - f.writelines(r + '\n') + f.write(r + '\n') f.write(separator + '\n') footer_str = ("{:>{}}" * len(widths)).format(*itertools.chain(*zip(footer, widths))) - f.writelines(footer_str + '\n') + f.write(footer_str + '\n') def _report_any_exprs(self) -> None: total_any = sum(num_any for num_any, _ in self.counts.values()) diff --git a/mypyc/build.py b/mypyc/build.py index 571fb0dd2f5a0..8528aa088ac05 100644 --- a/mypyc/build.py +++ b/mypyc/build.py @@ -308,8 +308,8 @@ def write_file(path: str, contents: str) -> None: old_contents = None if old_contents != encoded_contents: os.makedirs(os.path.dirname(path), exist_ok=True) - with open(path, 'wb') as f: - f.write(encoded_contents) + with open(path, 'wb') as g: + g.write(encoded_contents) # Fudge the mtime forward because otherwise when two builds happen close # together (like in a test) setuptools might not realize the source is newer diff --git a/test-data/unit/pythoneval.test b/test-data/unit/pythoneval.test index 993af4ced61e1..de15055927aeb 100644 --- a/test-data/unit/pythoneval.test +++ b/test-data/unit/pythoneval.test @@ -271,8 +271,8 @@ f.write('x') f.write(b'x') f.foobar() [out] -_program.py:3: error: Argument 1 to "write" of "IO" has incompatible type "bytes"; expected "str" -_program.py:4: error: "TextIO" has no attribute "foobar" +_program.py:3: error: Argument 1 to "write" of "TextIOBase" has incompatible type "bytes"; expected "str" +_program.py:4: error: "TextIOWrapper" has no attribute "foobar" [case testOpenReturnTypeInference] reveal_type(open('x')) @@ -281,9 +281,9 @@ reveal_type(open('x', 'rb')) mode = 'rb' reveal_type(open('x', mode)) [out] -_program.py:1: note: Revealed type is "typing.TextIO" -_program.py:2: note: Revealed type is "typing.TextIO" -_program.py:3: note: Revealed type is "typing.BinaryIO" +_program.py:1: note: Revealed type is "io.TextIOWrapper" +_program.py:2: note: Revealed type is "io.TextIOWrapper" +_program.py:3: note: Revealed type is "io.BufferedReader" _program.py:5: note: Revealed type is "typing.IO[Any]" [case testOpenReturnTypeInferenceSpecialCases] @@ -292,8 +292,8 @@ reveal_type(open(file='x', mode='rb')) mode = 'rb' reveal_type(open(mode=mode, file='r')) [out] -_testOpenReturnTypeInferenceSpecialCases.py:1: note: Revealed type is "typing.BinaryIO" -_testOpenReturnTypeInferenceSpecialCases.py:2: note: Revealed type is "typing.BinaryIO" +_testOpenReturnTypeInferenceSpecialCases.py:1: note: Revealed type is "io.BufferedReader" +_testOpenReturnTypeInferenceSpecialCases.py:2: note: Revealed type is "io.BufferedReader" _testOpenReturnTypeInferenceSpecialCases.py:4: note: Revealed type is "typing.IO[Any]" [case testPathOpenReturnTypeInference] @@ -305,21 +305,21 @@ reveal_type(p.open('rb')) mode = 'rb' reveal_type(p.open(mode)) [out] -_program.py:3: note: Revealed type is "typing.TextIO" -_program.py:4: note: Revealed type is "typing.TextIO" -_program.py:5: note: Revealed type is "typing.BinaryIO" +_program.py:3: note: Revealed type is "io.TextIOWrapper" +_program.py:4: note: Revealed type is "io.TextIOWrapper" +_program.py:5: note: Revealed type is "io.BufferedReader" _program.py:7: note: Revealed type is "typing.IO[Any]" [case testPathOpenReturnTypeInferenceSpecialCases] from pathlib import Path p = Path("x") -reveal_type(p.open(mode='rb', errors='replace')) -reveal_type(p.open(errors='replace', mode='rb')) -mode = 'rb' +reveal_type(p.open(mode='r', errors='replace')) +reveal_type(p.open(errors='replace', mode='r')) +mode = 'r' reveal_type(p.open(mode=mode, errors='replace')) [out] -_program.py:3: note: Revealed type is "typing.BinaryIO" -_program.py:4: note: Revealed type is "typing.BinaryIO" +_program.py:3: note: Revealed type is "io.TextIOWrapper" +_program.py:4: note: Revealed type is "io.TextIOWrapper" _program.py:6: note: Revealed type is "typing.IO[Any]" [case testGenericPatterns] From 37d58c310a0bf79f7635cf4fc2f6a491c7ee9683 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Wed, 9 Feb 2022 09:38:14 +0300 Subject: [PATCH 096/377] Add `StrEnum` support for Python 3.11 (#12035) --- mypy/semanal_enum.py | 2 +- test-data/unit/check-enum.test | 14 ++++++++++++++ test-data/unit/lib-stub/enum.pyi | 5 +++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/mypy/semanal_enum.py b/mypy/semanal_enum.py index bb88b4df47165..a10a879c7ea17 100644 --- a/mypy/semanal_enum.py +++ b/mypy/semanal_enum.py @@ -18,7 +18,7 @@ # Note: 'enum.EnumMeta' is deliberately excluded from this list. Classes that directly use # enum.EnumMeta do not necessarily automatically have the 'name' and 'value' attributes. ENUM_BASES: Final = frozenset(( - 'enum.Enum', 'enum.IntEnum', 'enum.Flag', 'enum.IntFlag', + 'enum.Enum', 'enum.IntEnum', 'enum.Flag', 'enum.IntFlag', 'enum.StrEnum', )) ENUM_SPECIAL_PROPS: Final = frozenset(( 'name', 'value', '_name_', '_value_', '_order_', '__order__', diff --git a/test-data/unit/check-enum.test b/test-data/unit/check-enum.test index 3d7c3fc3a392d..4d80d6908cd5a 100644 --- a/test-data/unit/check-enum.test +++ b/test-data/unit/check-enum.test @@ -232,6 +232,20 @@ an_enum = SomeIntEnum.x an_enum = returns_some_int_enum() [out] +[case testStrEnumCreation] +# flags: --python-version 3.11 +from enum import StrEnum + +class MyStrEnum(StrEnum): + x = 'x' + y = 'y' + +reveal_type(MyStrEnum.x) # N: Revealed type is "Literal[__main__.MyStrEnum.x]?" +reveal_type(MyStrEnum.x.value) # N: Revealed type is "Literal['x']?" +reveal_type(MyStrEnum.y) # N: Revealed type is "Literal[__main__.MyStrEnum.y]?" +reveal_type(MyStrEnum.y.value) # N: Revealed type is "Literal['y']?" +[out] + [case testEnumMethods] from enum import Enum diff --git a/test-data/unit/lib-stub/enum.pyi b/test-data/unit/lib-stub/enum.pyi index 2c1b03532a5bc..11adfc5979552 100644 --- a/test-data/unit/lib-stub/enum.pyi +++ b/test-data/unit/lib-stub/enum.pyi @@ -43,3 +43,8 @@ class IntFlag(int, Flag): class auto(IntFlag): value: Any + + +# It is python-3.11+ only: +class StrEnum(str, Enum): + def __new__(cls: Type[_T], value: str | _T) -> _T: ... From 234344b4879361694ca191a8d06f0847191b9508 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Wed, 9 Feb 2022 12:35:48 -0800 Subject: [PATCH 097/377] Mention common resolutions for build errors (#12154) Might help with breaking changes that result from #9636 Co-authored-by: hauntsaninja <> --- mypy/build.py | 17 +++++++++++++++-- test-data/unit/cmdline.test | 7 +++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/mypy/build.py b/mypy/build.py index e636b606ed8f1..76dded73b2bf9 100644 --- a/mypy/build.py +++ b/mypy/build.py @@ -2830,8 +2830,15 @@ def load_graph(sources: List[BuildSource], manager: BuildManager, ) manager.errors.report( -1, -1, - "Are you missing an __init__.py? Alternatively, consider using --exclude to " - "avoid checking one of them.", + "See https://mypy.readthedocs.io/en/stable/running_mypy.html#mapping-file-paths-to-modules " # noqa: E501 + "for more info", + severity='note', + ) + manager.errors.report( + -1, -1, + "Common resolutions include: a) using `--exclude` to avoid checking one of them, " + "b) adding `__init__.py` somewhere, c) using `--explicit-package-bases` or " + "adjusting MYPYPATH", severity='note' ) @@ -2905,6 +2912,12 @@ def load_graph(sources: List[BuildSource], manager: BuildManager, "for more info", severity='note', ) + manager.errors.report( + -1, 0, + "Common resolutions include: a) adding `__init__.py` somewhere, " + "b) using `--explicit-package-bases` or adjusting MYPYPATH", + severity='note', + ) manager.errors.raise_error() seen_files[newst_path] = newst diff --git a/test-data/unit/cmdline.test b/test-data/unit/cmdline.test index 690b0cc067098..f29c183f20ba8 100644 --- a/test-data/unit/cmdline.test +++ b/test-data/unit/cmdline.test @@ -59,7 +59,8 @@ undef undef [out] dir/a.py: error: Duplicate module named "a" (also at "dir/subdir/a.py") -dir/a.py: note: Are you missing an __init__.py? Alternatively, consider using --exclude to avoid checking one of them. +dir/a.py: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#mapping-file-paths-to-modules for more info +dir/a.py: note: Common resolutions include: a) using `--exclude` to avoid checking one of them, b) adding `__init__.py` somewhere, c) using `--explicit-package-bases` or adjusting MYPYPATH == Return code: 2 [case testCmdlineNonPackageSlash] @@ -125,7 +126,8 @@ mypy: can't decode file 'a.py': unknown encoding: uft-8 # type: ignore [out] two/mod/__init__.py: error: Duplicate module named "mod" (also at "one/mod/__init__.py") -two/mod/__init__.py: note: Are you missing an __init__.py? Alternatively, consider using --exclude to avoid checking one of them. +two/mod/__init__.py: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#mapping-file-paths-to-modules for more info +two/mod/__init__.py: note: Common resolutions include: a) using `--exclude` to avoid checking one of them, b) adding `__init__.py` somewhere, c) using `--explicit-package-bases` or adjusting MYPYPATH == Return code: 2 [case testFlagsFile] @@ -1144,6 +1146,7 @@ import foo.bar [out] src/foo/bar.py: error: Source file found twice under different module names: "src.foo.bar" and "foo.bar" src/foo/bar.py: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#mapping-file-paths-to-modules for more info +src/foo/bar.py: note: Common resolutions include: a) adding `__init__.py` somewhere, b) using `--explicit-package-bases` or adjusting MYPYPATH == Return code: 2 [case testEnableInvalidErrorCode] From 6ff8091dff1493aed1ae951934384d9e977bbc5f Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Wed, 9 Feb 2022 12:36:23 -0800 Subject: [PATCH 098/377] Add support for Never (#12153) --- mypy/semanal.py | 8 ++------ mypy/typeanal.py | 4 ++-- mypy/types.py | 8 ++++++++ test-data/unit/check-unreachable-code.test | 20 +++++++++++++++++++ test-data/unit/lib-stub/typing.pyi | 1 + test-data/unit/lib-stub/typing_extensions.pyi | 3 ++- 6 files changed, 35 insertions(+), 9 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 876866963e6bd..2786411936bf4 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -94,7 +94,7 @@ from mypy.errorcodes import ErrorCode from mypy import message_registry, errorcodes as codes from mypy.types import ( - FunctionLike, UnboundType, TypeVarType, TupleType, UnionType, StarType, + NEVER_NAMES, FunctionLike, UnboundType, TypeVarType, TupleType, UnionType, StarType, CallableType, Overloaded, Instance, Type, AnyType, LiteralType, LiteralValue, TypeTranslator, TypeOfAny, TypeType, NoneType, PlaceholderType, TPDICT_NAMES, ProperType, get_proper_type, get_proper_types, TypeAliasType, TypeVarLikeType, @@ -2227,11 +2227,7 @@ def is_type_ref(self, rv: Expression, bare: bool = False) -> bool: # Assignment color = Color['RED'] defines a variable, not an alias. return not rv.node.is_enum if isinstance(rv.node, Var): - return rv.node.fullname in ( - 'typing.NoReturn', - 'typing_extensions.NoReturn', - 'mypy_extensions.NoReturn', - ) + return rv.node.fullname in NEVER_NAMES if isinstance(rv, NameExpr): n = self.lookup(rv.name, rv) diff --git a/mypy/typeanal.py b/mypy/typeanal.py index 2a14162cf5585..a35f48337d938 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -12,7 +12,7 @@ from mypy.messages import MessageBuilder, quote_type_string, format_type_bare from mypy.options import Options from mypy.types import ( - Type, UnboundType, TupleType, TypedDictType, UnionType, Instance, AnyType, + NEVER_NAMES, Type, UnboundType, TupleType, TypedDictType, UnionType, Instance, AnyType, CallableType, NoneType, ErasedType, DeletedType, TypeList, TypeVarType, SyntheticTypeVisitor, StarType, PartialType, EllipsisType, UninhabitedType, TypeType, CallableArgument, TypeQuery, union_items, TypeOfAny, LiteralType, RawExpressionType, @@ -348,7 +348,7 @@ def try_analyze_special_unbound_type(self, t: UnboundType, fullname: str) -> Opt self.fail('ClassVar[...] must have at most one type argument', t) return AnyType(TypeOfAny.from_error) return self.anal_type(t.args[0]) - elif fullname in ('mypy_extensions.NoReturn', 'typing.NoReturn'): + elif fullname in NEVER_NAMES: return UninhabitedType(is_noreturn=True) elif fullname in LITERAL_TYPE_NAMES: return self.analyze_literal_type(t) diff --git a/mypy/types.py b/mypy/types.py index 5aecb8194f9ec..21f560ed4e232 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -132,6 +132,14 @@ 'typing_extensions.reveal_type', ) +NEVER_NAMES: Final = ( + 'typing.NoReturn', + 'typing_extensions.NoReturn', + 'mypy_extensions.NoReturn', + 'typing.Never', + 'typing_extensions.Never', +) + # A placeholder used for Bogus[...] parameters _dummy: Final[Any] = object() diff --git a/test-data/unit/check-unreachable-code.test b/test-data/unit/check-unreachable-code.test index de85f5188bb81..ad604b474ad4e 100644 --- a/test-data/unit/check-unreachable-code.test +++ b/test-data/unit/check-unreachable-code.test @@ -936,6 +936,26 @@ if False: reveal_type(x) [builtins fixtures/exception.pyi] +[case testNeverVariants] +from typing import Never +from typing_extensions import Never as TENever +from typing import NoReturn +from typing_extensions import NoReturn as TENoReturn +from mypy_extensions import NoReturn as MENoReturn + +bottom1: Never +reveal_type(bottom1) # N: Revealed type is "" +bottom2: TENever +reveal_type(bottom2) # N: Revealed type is "" +bottom3: NoReturn +reveal_type(bottom3) # N: Revealed type is "" +bottom4: TENoReturn +reveal_type(bottom4) # N: Revealed type is "" +bottom5: MENoReturn +reveal_type(bottom5) # N: Revealed type is "" + +[builtins fixtures/tuple.pyi] + [case testUnreachableFlagExpressions] # flags: --warn-unreachable def foo() -> bool: ... diff --git a/test-data/unit/lib-stub/typing.pyi b/test-data/unit/lib-stub/typing.pyi index 7283b47a96e76..1a6c5d36a3672 100644 --- a/test-data/unit/lib-stub/typing.pyi +++ b/test-data/unit/lib-stub/typing.pyi @@ -23,6 +23,7 @@ Type = 0 ClassVar = 0 Final = 0 NoReturn = 0 +Never = 0 NewType = 0 ParamSpec = 0 diff --git a/test-data/unit/lib-stub/typing_extensions.pyi b/test-data/unit/lib-stub/typing_extensions.pyi index 7c6e14e404cd1..38ff331f45d86 100644 --- a/test-data/unit/lib-stub/typing_extensions.pyi +++ b/test-data/unit/lib-stub/typing_extensions.pyi @@ -1,4 +1,4 @@ -from typing import TypeVar, Any, Mapping, Iterator, NoReturn, Dict, Type +from typing import TypeVar, Any, Mapping, Iterator, NoReturn as NoReturn, Dict, Type from typing import TYPE_CHECKING as TYPE_CHECKING from typing import NewType as NewType @@ -27,6 +27,7 @@ Concatenate: _SpecialForm TypeAlias: _SpecialForm TypeGuard: _SpecialForm +Never: _SpecialForm # Fallback type for all typed dicts (does not exist at runtime). class _TypedDict(Mapping[str, object]): From 84696ceeec978e569ca702f4868bb54ba47b97f3 Mon Sep 17 00:00:00 2001 From: Peter Law Date: Wed, 9 Feb 2022 23:44:24 +0000 Subject: [PATCH 099/377] Add an option to require ignore comments have error codes (#11633) Fixes #11509 --- docs/source/error_code_list2.rst | 31 ++++++++++++++++++++++++ mypy/build.py | 8 +++++++ mypy/errorcodes.py | 11 +++++++++ mypy/errors.py | 35 ++++++++++++++++++++++++++++ mypy/fastparse.py | 2 +- mypy/fastparse2.py | 2 +- test-data/unit/check-errorcodes.test | 19 +++++++++++++++ 7 files changed, 106 insertions(+), 2 deletions(-) diff --git a/docs/source/error_code_list2.rst b/docs/source/error_code_list2.rst index 1e035fcf7f692..ba5b67a5aeb78 100644 --- a/docs/source/error_code_list2.rst +++ b/docs/source/error_code_list2.rst @@ -255,3 +255,34 @@ no error in practice. In such case, it might be prudent to annotate ``items: Seq This is similar in concept to ensuring that an expression's type implements an expected interface (e.g. ``Sized``), except that attempting to invoke an undefined method (e.g. ``__len__``) results in an error, while attempting to evaluate an object in boolean context without a concrete implementation results in a truthy value. + + +Check that ``# type: ignore`` include an error code [ignore-without-code] +------------------------------------------------------------------------- + +Warn when a ``# type: ignore`` comment does not specify any error codes. +This clarifies the intent of the ignore and ensures that only the +expected errors are silenced. + +Example: + +.. code-block:: python + + # mypy: enable-error-code ignore-without-code + + class Foo: + def __init__(self, name: str) -> None: + self.name = name + + f = Foo('foo') + + # This line has a typo that mypy can't help with as both: + # - the expected error 'assignment', and + # - the unexpected error 'attr-defined' + # are silenced. + # Error: "type: ignore" comment without error code (currently ignored: [attr-defined]) + f.nme = 42 # type: ignore + + # This line warns correctly about the typo in the attribute name + # Error: "Foo" has no attribute "nme"; maybe "name"? + f.nme = 42 # type: ignore[assignment] diff --git a/mypy/build.py b/mypy/build.py index 76dded73b2bf9..24cef0b83bd3a 100644 --- a/mypy/build.py +++ b/mypy/build.py @@ -2369,6 +2369,13 @@ def generate_unused_ignore_notes(self) -> None: self.verify_dependencies(suppressed_only=True) self.manager.errors.generate_unused_ignore_errors(self.xpath) + def generate_ignore_without_code_notes(self) -> None: + if self.manager.errors.is_error_code_enabled(codes.IGNORE_WITHOUT_CODE): + self.manager.errors.generate_ignore_without_code_errors( + self.xpath, + self.options.warn_unused_ignores, + ) + # Module import and diagnostic glue @@ -3168,6 +3175,7 @@ def process_stale_scc(graph: Graph, scc: List[str], manager: BuildManager) -> No graph[id].finish_passes() for id in stale: graph[id].generate_unused_ignore_notes() + graph[id].generate_ignore_without_code_notes() if any(manager.errors.is_errors_for_file(graph[id].xpath) for id in stale): for id in stale: graph[id].transitive_error = True diff --git a/mypy/errorcodes.py b/mypy/errorcodes.py index ba716608ae569..4407df47d596c 100644 --- a/mypy/errorcodes.py +++ b/mypy/errorcodes.py @@ -141,10 +141,21 @@ def __str__(self) -> str: "Check that overloaded functions outside stub files have an implementation", "General", ) +IGNORE_WITHOUT_CODE: Final = ErrorCode( + "ignore-without-code", + "Warn about '# type: ignore' comments which do not have error codes", + "General", + default_enabled=False, +) # Syntax errors are often blocking. SYNTAX: Final = ErrorCode("syntax", "Report syntax errors", "General") +# This is an internal marker code for a whole-file ignore. It is not intended to +# be user-visible. +FILE: Final = ErrorCode("file", "Internal marker for a whole file being ignored", "General") +del error_codes[FILE.code] + # This is a catch-all for remaining uncategorized errors. MISC: Final = ErrorCode("misc", "Miscellaneous other checks", "General") diff --git a/mypy/errors.py b/mypy/errors.py index ec49541a15a51..9744f134ac166 100644 --- a/mypy/errors.py +++ b/mypy/errors.py @@ -508,6 +508,41 @@ def generate_unused_ignore_errors(self, file: str) -> None: None, False, False, False) self._add_error_info(file, info) + def generate_ignore_without_code_errors(self, + file: str, + is_warning_unused_ignores: bool) -> None: + if is_typeshed_file(file) or file in self.ignored_files: + return + + used_ignored_lines = self.used_ignored_lines[file] + + # If the whole file is ignored, ignore it. + if used_ignored_lines: + _, used_codes = min(used_ignored_lines.items()) + if codes.FILE.code in used_codes: + return + + for line, ignored_codes in self.ignored_lines[file].items(): + if ignored_codes: + continue + + # If the ignore is itself unused and that would be warned about, let + # that error stand alone + if is_warning_unused_ignores and not used_ignored_lines[line]: + continue + + codes_hint = '' + ignored_codes = used_ignored_lines[line] + if ignored_codes: + codes_hint = f' (currently ignored: [{", ".join(ignored_codes)}])' + + message = f'"type: ignore" comment without error code{codes_hint}' + # 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, 'error', message, codes.IGNORE_WITHOUT_CODE, + False, False, False) + self._add_error_info(file, info) + def num_messages(self) -> int: """Return the number of generated messages.""" return sum(len(x) for x in self.error_info_map.values()) diff --git a/mypy/fastparse.py b/mypy/fastparse.py index 5f9ec87e544fb..6de1196fcd812 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -389,7 +389,7 @@ def translate_stmt_list(self, if (ismodule and stmts and self.type_ignores and min(self.type_ignores) < self.get_lineno(stmts[0])): self.errors.used_ignored_lines[self.errors.file][min(self.type_ignores)].append( - codes.MISC.code) + codes.FILE.code) block = Block(self.fix_function_overloads(self.translate_stmt_list(stmts))) mark_block_unreachable(block) return [block] diff --git a/mypy/fastparse2.py b/mypy/fastparse2.py index bf3c09453ec0a..5162fbb5df450 100644 --- a/mypy/fastparse2.py +++ b/mypy/fastparse2.py @@ -217,7 +217,7 @@ def translate_stmt_list(self, if (module and stmts and self.type_ignores and min(self.type_ignores) < self.get_lineno(stmts[0])): self.errors.used_ignored_lines[self.errors.file][min(self.type_ignores)].append( - codes.MISC.code) + codes.FILE.code) block = Block(self.fix_function_overloads(self.translate_stmt_list(stmts))) mark_block_unreachable(block) return [block] diff --git a/test-data/unit/check-errorcodes.test b/test-data/unit/check-errorcodes.test index 177612959354f..642828085b536 100644 --- a/test-data/unit/check-errorcodes.test +++ b/test-data/unit/check-errorcodes.test @@ -145,6 +145,25 @@ x # type: ignore[name-defined, attr-defined] # E: Unused "type: ignore[attr-defi # flags: --warn-unused-ignores "x" # type: ignore[name-defined] # E: Unused "type: ignore" comment +[case testErrorCodeMissingWhenRequired] +# flags: --enable-error-code ignore-without-code +"x" # type: ignore # E: "type: ignore" comment without error code [ignore-without-code] +y # type: ignore # E: "type: ignore" comment without error code (currently ignored: [name-defined]) [ignore-without-code] +z # type: ignore[name-defined] +"a" # type: ignore[ignore-without-code] + +[case testErrorCodeMissingDoesntTrampleUnusedIgnoresWarning] +# flags: --enable-error-code ignore-without-code --warn-unused-ignores +"x" # type: ignore # E: Unused "type: ignore" comment +"y" # type: ignore[ignore-without-code] # E: Unused "type: ignore" comment +z # type: ignore[ignore-without-code] # E: Unused "type: ignore" comment # E: Name "z" is not defined [name-defined] # N: Error code "name-defined" not covered by "type: ignore" comment + +[case testErrorCodeMissingWholeFileIgnores] +# flags: --enable-error-code ignore-without-code +# type: ignore # whole file ignore +x +y # type: ignore # ignore the lack of error code since we're ignore the whole file + [case testErrorCodeIgnoreWithExtraSpace] x # type: ignore [name-defined] x2 # type: ignore [ name-defined ] From 129dba468c235fbdc01f608736554061368bcff3 Mon Sep 17 00:00:00 2001 From: 97littleleaf11 <97littleleaf11@users.noreply.github.com> Date: Thu, 10 Feb 2022 08:09:45 +0800 Subject: [PATCH 100/377] Update CREDITS (#12018) --- CREDITS | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CREDITS b/CREDITS index d0e53de5ee01e..fb2fe155a9b89 100644 --- a/CREDITS +++ b/CREDITS @@ -11,15 +11,18 @@ Dropbox core team: Jukka Lehtosalo Ivan Levkivskyi + Jared Hance Non-Dropbox core team members: Ethan Smith Guido van Rossum - Jelle Zijlstra + Jelle Zijlstra Michael J. Sullivan Shantanu Jain - Xuanda Yang + Xuanda Yang + Jingchen Ye <97littleleaf11@gmail.com> + Nikita Sobolev Past Dropbox core team members: From 5b9318dcf069e08a1e240cc1ae1b40baca6ad577 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Sat, 12 Feb 2022 22:40:39 +0300 Subject: [PATCH 101/377] Add `match_args` support to `attr.s()` (#12111) * Add `match_args` support to `attr.s()` * Improve wording * Serialize `__match_args__` * More tests * Addresses review * Address review --- mypy/plugins/attrs.py | 35 ++++++++++- mypy/plugins/common.py | 8 ++- test-data/unit/check-attr.test | 74 +++++++++++++++++++++++ test-data/unit/lib-stub/attr/__init__.pyi | 2 + 4 files changed, 116 insertions(+), 3 deletions(-) diff --git a/mypy/plugins/attrs.py b/mypy/plugins/attrs.py index b777bf482e8fd..a82b7d9bdfeed 100644 --- a/mypy/plugins/attrs.py +++ b/mypy/plugins/attrs.py @@ -18,18 +18,19 @@ from mypy.plugin import SemanticAnalyzerPluginInterface from mypy.plugins.common import ( _get_argument, _get_bool_argument, _get_decorator_bool_argument, add_method, - deserialize_and_fixup_type + deserialize_and_fixup_type, add_attribute_to_class, ) from mypy.types import ( TupleType, Type, AnyType, TypeOfAny, CallableType, NoneType, TypeVarType, Overloaded, UnionType, FunctionLike, Instance, get_proper_type, + LiteralType, ) from mypy.typeops import make_simplified_union, map_type_from_supertype from mypy.typevars import fill_typevars from mypy.util import unmangle from mypy.server.trigger import make_wildcard_trigger -KW_ONLY_PYTHON_2_UNSUPPORTED = "kw_only is not supported in Python 2" +KW_ONLY_PYTHON_2_UNSUPPORTED: Final = "kw_only is not supported in Python 2" # The names of the different functions that create classes or arguments. attr_class_makers: Final = { @@ -278,6 +279,7 @@ def attr_class_maker_callback(ctx: 'mypy.plugin.ClassDefContext', auto_attribs = _get_decorator_optional_bool_argument(ctx, 'auto_attribs', auto_attribs_default) kw_only = _get_decorator_bool_argument(ctx, 'kw_only', False) + match_args = _get_decorator_bool_argument(ctx, 'match_args', True) if ctx.api.options.python_version[0] < 3: if auto_attribs: @@ -307,6 +309,10 @@ def attr_class_maker_callback(ctx: 'mypy.plugin.ClassDefContext', _add_attrs_magic_attribute(ctx, [(attr.name, info[attr.name].type) for attr in attributes]) if slots: _add_slots(ctx, attributes) + if match_args and ctx.api.options.python_version[:2] >= (3, 10): + # `.__match_args__` is only added for python3.10+, but the argument + # exists for earlier versions as well. + _add_match_args(ctx, attributes) # Save the attributes so that subclasses can reuse them. ctx.cls.info.metadata['attrs'] = { @@ -733,6 +739,7 @@ def _add_attrs_magic_attribute(ctx: 'mypy.plugin.ClassDefContext', ti.names[name] = SymbolTableNode(MDEF, var, plugin_generated=True) attributes_type = Instance(ti, []) + # TODO: refactor using `add_attribute_to_class` var = Var(name=MAGIC_ATTR_NAME, type=TupleType(attributes_types, fallback=attributes_type)) var.info = ctx.cls.info var.is_classvar = True @@ -751,6 +758,30 @@ def _add_slots(ctx: 'mypy.plugin.ClassDefContext', ctx.cls.info.slots = {attr.name for attr in attributes} +def _add_match_args(ctx: 'mypy.plugin.ClassDefContext', + attributes: List[Attribute]) -> None: + if ('__match_args__' not in ctx.cls.info.names + or ctx.cls.info.names['__match_args__'].plugin_generated): + str_type = ctx.api.named_type('builtins.str') + match_args = TupleType( + [ + str_type.copy_modified( + last_known_value=LiteralType(attr.name, fallback=str_type), + ) + for attr in attributes + if not attr.kw_only and attr.init + ], + fallback=ctx.api.named_type('builtins.tuple'), + ) + add_attribute_to_class( + api=ctx.api, + cls=ctx.cls, + name='__match_args__', + typ=match_args, + final=True, + ) + + class MethodAdder: """Helper to add methods to a TypeInfo. diff --git a/mypy/plugins/common.py b/mypy/plugins/common.py index 95f4618da4a14..40ac03e30a504 100644 --- a/mypy/plugins/common.py +++ b/mypy/plugins/common.py @@ -162,6 +162,7 @@ def add_attribute_to_class( name: str, typ: Type, final: bool = False, + no_serialize: bool = False, ) -> None: """ Adds a new attribute to a class definition. @@ -180,7 +181,12 @@ def add_attribute_to_class( node.info = info node.is_final = final node._fullname = info.fullname + '.' + name - info.names[name] = SymbolTableNode(MDEF, node, plugin_generated=True) + info.names[name] = SymbolTableNode( + MDEF, + node, + plugin_generated=True, + no_serialize=no_serialize, + ) def deserialize_and_fixup_type( diff --git a/test-data/unit/check-attr.test b/test-data/unit/check-attr.test index 083feb0152e5c..1fc811d93dc9e 100644 --- a/test-data/unit/check-attr.test +++ b/test-data/unit/check-attr.test @@ -1465,3 +1465,77 @@ class C: self.b = 1 # E: Trying to assign name "b" that is not in "__slots__" of type "__main__.C" self.c = 2 # E: Trying to assign name "c" that is not in "__slots__" of type "__main__.C" [builtins fixtures/attr.pyi] + +[case testAttrsWithMatchArgs] +# flags: --python-version 3.10 +import attr + +@attr.s(match_args=True, auto_attribs=True) +class ToMatch: + x: int + y: int + # Not included: + z: int = attr.field(kw_only=True) + i: int = attr.field(init=False) + +reveal_type(ToMatch(x=1, y=2, z=3).__match_args__) # N: Revealed type is "Tuple[Literal['x']?, Literal['y']?]" +reveal_type(ToMatch(1, 2, z=3).__match_args__) # N: Revealed type is "Tuple[Literal['x']?, Literal['y']?]" +[builtins fixtures/attr.pyi] + +[case testAttrsWithMatchArgsDefaultCase] +# flags: --python-version 3.10 +import attr + +@attr.s(auto_attribs=True) +class ToMatch1: + x: int + y: int + +t1: ToMatch1 +reveal_type(t1.__match_args__) # N: Revealed type is "Tuple[Literal['x']?, Literal['y']?]" + +@attr.define +class ToMatch2: + x: int + y: int + +t2: ToMatch2 +reveal_type(t2.__match_args__) # N: Revealed type is "Tuple[Literal['x']?, Literal['y']?]" +[builtins fixtures/attr.pyi] + +[case testAttrsWithMatchArgsOverrideExisting] +# flags: --python-version 3.10 +import attr +from typing import Final + +@attr.s(match_args=True, auto_attribs=True) +class ToMatch: + __match_args__: Final = ('a', 'b') + x: int + y: int + +# It works the same way runtime does: +reveal_type(ToMatch(x=1, y=2).__match_args__) # N: Revealed type is "Tuple[Literal['a']?, Literal['b']?]" + +@attr.s(auto_attribs=True) +class WithoutMatch: + __match_args__: Final = ('a', 'b') + x: int + y: int + +reveal_type(WithoutMatch(x=1, y=2).__match_args__) # N: Revealed type is "Tuple[Literal['a']?, Literal['b']?]" +[builtins fixtures/attr.pyi] + +[case testAttrsWithMatchArgsOldVersion] +# flags: --python-version 3.9 +import attr + +@attr.s(match_args=True) +class NoMatchArgs: + ... + +n: NoMatchArgs + +reveal_type(n.__match_args__) # E: "NoMatchArgs" has no attribute "__match_args__" \ + # N: Revealed type is "Any" +[builtins fixtures/attr.pyi] diff --git a/test-data/unit/lib-stub/attr/__init__.pyi b/test-data/unit/lib-stub/attr/__init__.pyi index 6ce4b3a64ed55..795e5d3f4f697 100644 --- a/test-data/unit/lib-stub/attr/__init__.pyi +++ b/test-data/unit/lib-stub/attr/__init__.pyi @@ -94,6 +94,7 @@ def attrs(maybe_cls: _C, cache_hash: bool = ..., eq: Optional[bool] = ..., order: Optional[bool] = ..., + match_args: bool = ..., ) -> _C: ... @overload def attrs(maybe_cls: None = ..., @@ -112,6 +113,7 @@ def attrs(maybe_cls: None = ..., cache_hash: bool = ..., eq: Optional[bool] = ..., order: Optional[bool] = ..., + match_args: bool = ..., ) -> Callable[[_C], _C]: ... From 595fec99b36e2d18a57f11a355f161d69b0e5679 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Tue, 15 Feb 2022 02:00:35 -0800 Subject: [PATCH 102/377] Fix CI (#12181) Co-authored-by: hauntsaninja <> --- .github/workflows/docs.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index d44f9143bdc75..228bdb3bd4ad9 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -23,7 +23,7 @@ jobs: with: python-version: '3.7' - name: Install tox - run: pip install --upgrade 'setuptools!=50' 'virtualenv<16.7.11' tox==3.20.1 + run: pip install --upgrade 'setuptools!=50' 'virtualenv>=20.6.0' tox==3.24.5 - name: Setup tox environment run: tox -e ${{ env.TOXENV }} --notest - name: Test diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2551fb0444826..7402a97d73213 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -107,7 +107,7 @@ jobs: ./misc/build-debug-python.sh $PYTHONVERSION $PYTHONDIR $VENV source $VENV/bin/activate - name: Install tox - run: pip install --upgrade 'setuptools!=50' 'virtualenv>=20.6.0' tox==3.20.1 + run: pip install --upgrade 'setuptools!=50' 'virtualenv>=20.6.0' tox==3.24.5 - name: Compiled with mypyc if: ${{ matrix.test_mypyc }} run: | From cd3dfbd0e387f23127998df2c71231d0fee5e692 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Tue, 15 Feb 2022 05:55:36 -0800 Subject: [PATCH 103/377] Fix use of TypeAlias from aliased imports (#12180) Fixes #12179 --- mypy/semanal.py | 2 +- test-data/unit/check-type-aliases.test | 26 ++++++++++++++++++++++- test-data/unit/fixtures/typing-medium.pyi | 1 + 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 2786411936bf4..eb1ed622720ed 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -2643,7 +2643,7 @@ def check_and_set_up_type_alias(self, s: AssignmentStmt) -> bool: pep_613 = False if s.unanalyzed_type is not None and isinstance(s.unanalyzed_type, UnboundType): - lookup = self.lookup(s.unanalyzed_type.name, s, suppress_errors=True) + lookup = self.lookup_qualified(s.unanalyzed_type.name, s, suppress_errors=True) if lookup and lookup.fullname in TYPE_ALIAS_NAMES: pep_613 = True if not pep_613 and s.unanalyzed_type is not None: diff --git a/test-data/unit/check-type-aliases.test b/test-data/unit/check-type-aliases.test index cb023fc0ad3ff..4c5dacee1b3f6 100644 --- a/test-data/unit/check-type-aliases.test +++ b/test-data/unit/check-type-aliases.test @@ -57,7 +57,7 @@ Never = NoReturn a: Never # Used to be an error here def f(a: Never): ... -f(5) # E: Argument 1 to "f" has incompatible type "int"; expected "NoReturn" +f(5) # E: Argument 1 to "f" has incompatible type "int"; expected "NoReturn" [case testImportUnionAlias] import typing from _m import U @@ -702,6 +702,30 @@ x: TypeAlias = list(int) # E: Invalid type alias: expression is not a valid typ a: x [builtins fixtures/tuple.pyi] +[case testAliasedImportPep613] +import typing as tpp +import typing_extensions as tpx +from typing import TypeAlias as TPA +from typing_extensions import TypeAlias as TXA +import typing +import typing_extensions + +Int1: tpp.TypeAlias = int +Int2: tpx.TypeAlias = int +Int3: TPA = int +Int4: TXA = int +Int5: typing.TypeAlias = int +Int6: typing_extensions.TypeAlias = int + +x1: Int1 = "str" # E: Incompatible types in assignment (expression has type "str", variable has type "int") +x2: Int2 = "str" # E: Incompatible types in assignment (expression has type "str", variable has type "int") +x3: Int3 = "str" # E: Incompatible types in assignment (expression has type "str", variable has type "int") +x4: Int4 = "str" # E: Incompatible types in assignment (expression has type "str", variable has type "int") +x5: Int5 = "str" # E: Incompatible types in assignment (expression has type "str", variable has type "int") +x6: Int6 = "str" # E: Incompatible types in assignment (expression has type "str", variable has type "int") +[builtins fixtures/tuple.pyi] +[typing fixtures/typing-medium.pyi] + [case testFunctionScopePep613] from typing_extensions import TypeAlias diff --git a/test-data/unit/fixtures/typing-medium.pyi b/test-data/unit/fixtures/typing-medium.pyi index 7717a6bf17497..923ede2f0c008 100644 --- a/test-data/unit/fixtures/typing-medium.pyi +++ b/test-data/unit/fixtures/typing-medium.pyi @@ -26,6 +26,7 @@ Literal = 0 TypedDict = 0 NoReturn = 0 NewType = 0 +TypeAlias = 0 T = TypeVar('T') T_co = TypeVar('T_co', covariant=True) From 777885f2c26cce195f6d23c80fefae1e66dfaac2 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Tue, 15 Feb 2022 21:25:15 +0000 Subject: [PATCH 104/377] stubtest: enable checking pos-only differences in dunders (#12184) --- mypy/stubtest.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mypy/stubtest.py b/mypy/stubtest.py index df36935a801fc..e67992ace5f8a 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -594,7 +594,6 @@ def _verify_signature( runtime_arg.kind == inspect.Parameter.POSITIONAL_ONLY and not stub_arg.variable.name.startswith("__") and not stub_arg.variable.name.strip("_") == "self" - and not is_dunder(function_name, exclude_special=True) # noisy for dunder methods ): yield ( 'stub argument "{}" should be positional-only ' From 554606bf2b54e6487d0f5d622ed4eb6281fd50de Mon Sep 17 00:00:00 2001 From: Tuomas Siipola Date: Wed, 16 Feb 2022 20:48:02 +0200 Subject: [PATCH 105/377] Suggest `typing.Any` when using `any` as type (#12185) --- mypy/typeanal.py | 5 ++++- test-data/unit/check-functions.test | 5 +++++ test-data/unit/fixtures/any.pyi | 8 ++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 test-data/unit/fixtures/any.pyi diff --git a/mypy/typeanal.py b/mypy/typeanal.py index a35f48337d938..6f75ff7e44d8b 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -492,7 +492,10 @@ def analyze_unbound_type_without_type_info(self, t: UnboundType, sym: SymbolTabl message = 'Variable "{}" is not valid as a type' elif isinstance(sym.node, (SYMBOL_FUNCBASE_TYPES, Decorator)): message = 'Function "{}" is not valid as a type' - notes.append('Perhaps you need "Callable[...]" or a callback protocol?') + if name == 'builtins.any': + notes.append('Perhaps you meant "typing.Any" instead of "any"?') + else: + notes.append('Perhaps you need "Callable[...]" or a callback protocol?') elif isinstance(sym.node, MypyFile): # TODO: suggest a protocol when supported. message = 'Module "{}" is not valid as a type' diff --git a/test-data/unit/check-functions.test b/test-data/unit/check-functions.test index bdf75b2dc58c9..4b6c7253d6472 100644 --- a/test-data/unit/check-functions.test +++ b/test-data/unit/check-functions.test @@ -2605,3 +2605,8 @@ def foo() -> None: pass reveal_type(foo()) # N: Revealed type is "None" + +[case testAnyArgument] +def a(b: any): pass # E: Function "builtins.any" is not valid as a type \ + # N: Perhaps you meant "typing.Any" instead of "any"? +[builtins fixtures/any.pyi] diff --git a/test-data/unit/fixtures/any.pyi b/test-data/unit/fixtures/any.pyi new file mode 100644 index 0000000000000..d6d90b7b3e985 --- /dev/null +++ b/test-data/unit/fixtures/any.pyi @@ -0,0 +1,8 @@ +from typing import TypeVar, Iterable + +T = TypeVar('T') + +class int: pass +class str: pass + +def any(i: Iterable[T]) -> bool: pass From eef316d65bf583b081f0101cdafbef3ecc353acc Mon Sep 17 00:00:00 2001 From: Kenny Stauffer Date: Wed, 16 Feb 2022 16:23:28 -0500 Subject: [PATCH 106/377] Understand the self-destructing nature of Enum._ignore_ (#12128) --- mypy/checkmember.py | 7 ++++--- mypy/semanal_enum.py | 4 ++-- mypy/typeops.py | 7 ++++--- mypy/types.py | 8 ++++++++ mypyc/irbuild/classdef.py | 6 +++--- test-data/unit/check-enum.test | 9 +++++++++ 6 files changed, 30 insertions(+), 11 deletions(-) diff --git a/mypy/checkmember.py b/mypy/checkmember.py index 1c66320bb562f..e7af3978867f4 100644 --- a/mypy/checkmember.py +++ b/mypy/checkmember.py @@ -6,7 +6,8 @@ from mypy.types import ( Type, Instance, AnyType, TupleType, TypedDictType, CallableType, FunctionLike, TypeVarLikeType, Overloaded, TypeVarType, UnionType, PartialType, TypeOfAny, LiteralType, - DeletedType, NoneType, TypeType, has_type_vars, get_proper_type, ProperType, ParamSpecType + DeletedType, NoneType, TypeType, has_type_vars, get_proper_type, ProperType, ParamSpecType, + ENUM_REMOVED_PROPS ) from mypy.nodes import ( TypeInfo, FuncBase, Var, FuncDef, SymbolNode, SymbolTable, Context, @@ -831,8 +832,8 @@ def analyze_enum_class_attribute_access(itype: Instance, name: str, mx: MemberContext, ) -> Optional[Type]: - # Skip "_order_" and "__order__", since Enum will remove it - if name in ("_order_", "__order__"): + # Skip these since Enum will remove it + if name in ENUM_REMOVED_PROPS: return mx.msg.has_no_attr( mx.original_type, itype, name, mx.context, mx.module_symbol_table ) diff --git a/mypy/semanal_enum.py b/mypy/semanal_enum.py index a10a879c7ea17..8b5ecf1b1df41 100644 --- a/mypy/semanal_enum.py +++ b/mypy/semanal_enum.py @@ -13,7 +13,7 @@ ) from mypy.semanal_shared import SemanticAnalyzerInterface from mypy.options import Options -from mypy.types import get_proper_type, LiteralType +from mypy.types import get_proper_type, LiteralType, ENUM_REMOVED_PROPS # Note: 'enum.EnumMeta' is deliberately excluded from this list. Classes that directly use # enum.EnumMeta do not necessarily automatically have the 'name' and 'value' attributes. @@ -21,7 +21,7 @@ 'enum.Enum', 'enum.IntEnum', 'enum.Flag', 'enum.IntFlag', 'enum.StrEnum', )) ENUM_SPECIAL_PROPS: Final = frozenset(( - 'name', 'value', '_name_', '_value_', '_order_', '__order__', + 'name', 'value', '_name_', '_value_', *ENUM_REMOVED_PROPS, # Also attributes from `object`: '__module__', '__annotations__', '__doc__', '__slots__', '__dict__', )) diff --git a/mypy/typeops.py b/mypy/typeops.py index 88d4bc744bdf8..22812a699ae41 100644 --- a/mypy/typeops.py +++ b/mypy/typeops.py @@ -14,7 +14,8 @@ TupleType, Instance, FunctionLike, Type, CallableType, TypeVarLikeType, Overloaded, TypeVarType, UninhabitedType, FormalArgument, UnionType, NoneType, AnyType, TypeOfAny, TypeType, ProperType, LiteralType, get_proper_type, get_proper_types, - copy_type, TypeAliasType, TypeQuery, ParamSpecType + copy_type, TypeAliasType, TypeQuery, ParamSpecType, + ENUM_REMOVED_PROPS ) from mypy.nodes import ( FuncBase, FuncItem, FuncDef, OverloadedFuncDef, TypeInfo, ARG_STAR, ARG_STAR2, ARG_POS, @@ -715,8 +716,8 @@ class Status(Enum): for name, symbol in typ.type.names.items(): if not isinstance(symbol.node, Var): continue - # Skip "_order_" and "__order__", since Enum will remove it - if name in ("_order_", "__order__"): + # Skip these since Enum will remove it + if name in ENUM_REMOVED_PROPS: continue new_items.append(LiteralType(name, typ)) # SymbolTables are really just dicts, and dicts are guaranteed to preserve diff --git a/mypy/types.py b/mypy/types.py index 21f560ed4e232..dadbb84fe1c83 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -132,6 +132,14 @@ 'typing_extensions.reveal_type', ) +# Attributes that can optionally be defined in the body of a subclass of +# enum.Enum but are removed from the class __dict__ by EnumMeta. +ENUM_REMOVED_PROPS: Final = ( + '_ignore_', + '_order_', + '__order__', +) + NEVER_NAMES: Final = ( 'typing.NoReturn', 'typing_extensions.NoReturn', diff --git a/mypyc/irbuild/classdef.py b/mypyc/irbuild/classdef.py index 6c2958c5b8de8..80ec331cd5502 100644 --- a/mypyc/irbuild/classdef.py +++ b/mypyc/irbuild/classdef.py @@ -8,7 +8,7 @@ ClassDef, FuncDef, OverloadedFuncDef, PassStmt, AssignmentStmt, CallExpr, NameExpr, StrExpr, ExpressionStmt, TempNode, Decorator, Lvalue, MemberExpr, RefExpr, TypeInfo, is_class_var ) -from mypy.types import Instance, get_proper_type +from mypy.types import Instance, get_proper_type, ENUM_REMOVED_PROPS from mypyc.ir.ops import ( Value, Register, Call, LoadErrorValue, LoadStatic, InitStatic, TupleSet, SetAttr, Return, BasicBlock, Branch, MethodCall, NAMESPACE_TYPE, LoadAddress @@ -517,8 +517,8 @@ def add_non_ext_class_attr(builder: IRBuilder, if ( cdef.info.bases and cdef.info.bases[0].type.fullname == 'enum.Enum' - # Skip "_order_" and "__order__", since Enum will remove it - and lvalue.name not in ('_order_', '__order__') + # Skip these since Enum will remove it + and lvalue.name not in ENUM_REMOVED_PROPS ): # Enum values are always boxed, so use object_rprimitive. attr_to_cache.append((lvalue, object_rprimitive)) diff --git a/test-data/unit/check-enum.test b/test-data/unit/check-enum.test index 4d80d6908cd5a..a6eb6374da374 100644 --- a/test-data/unit/check-enum.test +++ b/test-data/unit/check-enum.test @@ -1902,3 +1902,12 @@ def f2(c: C, a: Any) -> None: y = {'y': a, 'x': c.value} reveal_type(y) # N: Revealed type is "builtins.dict[builtins.str*, Any]" [builtins fixtures/dict.pyi] + +[case testEnumIgnoreIsDeleted] +from enum import Enum + +class C(Enum): + _ignore_ = 'X' + +C._ignore_ # E: "Type[C]" has no attribute "_ignore_" +[typing fixtures/typing-medium.pyi] From 84aaef5caea0bd0fdb0e9d0ac5c1e850611b22fd Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Wed, 16 Feb 2022 15:43:00 -0800 Subject: [PATCH 107/377] CONTRIBUTING.md: more words for first-time contributors (#12193) mypy attracts a lot of (usually student) first-time contributors who tend to comment on issues with things like "May I work on this issue? Can anyone provide me guidance?" and often end up not getting a response. The goal of this PR is to have a section we can just link to as a reply in such situations. --- CONTRIBUTING.md | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9e5bdeb90a69c..eafefe346d01b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -54,6 +54,12 @@ You can also use `tox` to run tests, for instance: tox -e py ``` +The easiest way to run a single test is: +``` +pytest -n0 -k 'test_name' +``` +There's more useful information on writing and running tests [here](test-data/unit/README.md) + ## First time contributors If you're looking for things to help with, browse our [issue tracker](https://github.com/python/mypy/issues)! @@ -63,21 +69,24 @@ In particular, look for: - [good second issues](https://github.com/python/mypy/labels/good-second-issue) - [documentation issues](https://github.com/python/mypy/labels/documentation) -It's also extremely easy to get started contributing to our sister project -[typeshed](https://github.com/python/typeshed/issues) that provides type stubs -for libraries. This is a great way to become familiar with type syntax. - -If you need help getting started, don't hesitate to ask on -[gitter](https://gitter.im/python/typing). +You do not need to ask for permission to work on any of these issues. +Just fix the issue yourself, [try to add a unit test](#running-tests) and +[open a pull request](#submitting-changes). To get help fixing a specific issue, it's often best to comment on the issue -itself. The more details you provide about what you've tried and where you've -looked, the easier it will be for you to get help. +itself. You're much more likely to get help if you provide details about what +you've tried and where you've looked (maintainers tend to help those who help +themselves). [gitter](https://gitter.im/python/typing) can also be a good place +to ask for help. Interactive debuggers like `pdb` and `ipdb` are really useful for getting started with the mypy codebase. This is a [useful tutorial](https://realpython.com/python-debugging-pdb/). +It's also extremely easy to get started contributing to our sister project +[typeshed](https://github.com/python/typeshed/issues) that provides type stubs +for libraries. This is a great way to become familiar with type syntax. + ## Submitting changes Even more excellent than a good bug report is a fix for a bug, or the From 1de5e55fff22b023d54aa700d630befd162db20e Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Wed, 16 Feb 2022 19:11:18 -0800 Subject: [PATCH 108/377] Fix crashes in class scoped imports (#12023) Fixes #11045, fixes https://github.com/huggingface/transformers/issues/13390 Fixes #10488 Fixes #7045 Fixes #7806 Fixes #11641 Fixes #11351 Fixes #10488 Co-authored-by: @A5rocks --- mypy/semanal.py | 38 +++++++++- test-data/unit/check-classes.test | 109 +++++++++++++++++++++++++++ test-data/unit/check-modules.test | 4 +- test-data/unit/check-newsemanal.test | 4 +- test-data/unit/semanal-modules.test | 2 +- 5 files changed, 149 insertions(+), 8 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index eb1ed622720ed..0f9f3996892ad 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -48,10 +48,11 @@ reduce memory use). """ +import copy from contextlib import contextmanager from typing import ( - List, Dict, Set, Tuple, cast, TypeVar, Union, Optional, Callable, Iterator, Iterable + Any, List, Dict, Set, Tuple, cast, TypeVar, Union, Optional, Callable, Iterator, Iterable ) from typing_extensions import Final, TypeAlias as _TypeAlias @@ -78,7 +79,7 @@ typing_extensions_aliases, EnumCallExpr, RUNTIME_PROTOCOL_DECOS, FakeExpression, Statement, AssignmentExpr, ParamSpecExpr, EllipsisExpr, TypeVarLikeExpr, implicit_module_attrs, - MatchStmt, + MatchStmt, FuncBase ) from mypy.patterns import ( AsPattern, OrPattern, ValuePattern, SequencePattern, @@ -4798,7 +4799,38 @@ def add_imported_symbol(self, module_hidden: bool) -> None: """Add an alias to an existing symbol through import.""" assert not module_hidden or not module_public - symbol = SymbolTableNode(node.kind, node.node, + + symbol_node: Optional[SymbolNode] = node.node + + if self.is_class_scope(): + # I promise this type checks; I'm just making mypyc issues go away. + # mypyc is absolutely convinced that `symbol_node` narrows to a Var in the following, + # when it can also be a FuncBase. Once fixed, `f` in the following can be removed. + # See also https://github.com/mypyc/mypyc/issues/892 + f = cast(Any, lambda x: x) + if isinstance(f(symbol_node), (FuncBase, Var)): + # For imports in class scope, we construct a new node to represent the symbol and + # set its `info` attribute to `self.type`. + existing = self.current_symbol_table().get(name) + if ( + # The redefinition checks in `add_symbol_table_node` don't work for our + # constructed Var / FuncBase, so check for possible redefinitions here. + existing is not None + and isinstance(f(existing.node), (FuncBase, Var)) + and f(existing.type) == f(symbol_node).type + ): + symbol_node = existing.node + else: + # Construct the new node + constructed_node = copy.copy(f(symbol_node)) + assert self.type is not None # guaranteed by is_class_scope + constructed_node.line = context.line + constructed_node.column = context.column + constructed_node.info = self.type + constructed_node._fullname = self.qualified_name(name) + symbol_node = constructed_node + + symbol = SymbolTableNode(node.kind, symbol_node, module_public=module_public, module_hidden=module_hidden) self.add_symbol_table_node(name, symbol, context) diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index a2bcdade3287c..8f3a2c3087863 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -7134,3 +7134,112 @@ class B(A): # E: Final class __main__.B has abstract attributes "foo" [case testUndefinedBaseclassInNestedClass] class C: class C1(XX): pass # E: Name "XX" is not defined + +[case testClassScopeImportFunction] +class Foo: + from mod import foo + +reveal_type(Foo.foo) # N: Revealed type is "def (x: builtins.int, y: builtins.int) -> builtins.int" +reveal_type(Foo().foo) # E: Invalid self argument "Foo" to attribute function "foo" with type "Callable[[int, int], int]" \ + # N: Revealed type is "def (y: builtins.int) -> builtins.int" +[file mod.py] +def foo(x: int, y: int) -> int: ... + +[case testClassScopeImportVariable] +class Foo: + from mod import foo + +reveal_type(Foo.foo) # N: Revealed type is "builtins.int" +reveal_type(Foo().foo) # N: Revealed type is "builtins.int" +[file mod.py] +foo: int + +[case testClassScopeImportModule] +class Foo: + import mod + +reveal_type(Foo.mod) # N: Revealed type is "builtins.object" +reveal_type(Foo.mod.foo) # N: Revealed type is "builtins.int" +[file mod.py] +foo: int + +[case testClassScopeImportFunctionAlias] +class Foo: + from mod import foo + bar = foo + + from mod import const_foo + const_bar = const_foo + +reveal_type(Foo.foo) # N: Revealed type is "def (x: builtins.int, y: builtins.int) -> builtins.int" +reveal_type(Foo.bar) # N: Revealed type is "def (x: builtins.int, y: builtins.int) -> builtins.int" +reveal_type(Foo.const_foo) # N: Revealed type is "builtins.int" +reveal_type(Foo.const_bar) # N: Revealed type is "builtins.int" +[file mod.py] +def foo(x: int, y: int) -> int: ... +const_foo: int + +[case testClassScopeImportModuleStar] +class Foo: + from mod import * + +reveal_type(Foo.foo) # N: Revealed type is "builtins.int" +reveal_type(Foo.bar) # N: Revealed type is "def (x: builtins.int) -> builtins.int" +reveal_type(Foo.baz) # E: "Type[Foo]" has no attribute "baz" \ + # N: Revealed type is "Any" +[file mod.py] +foo: int +def bar(x: int) -> int: ... + +[case testClassScopeImportFunctionNested] +class Foo: + class Bar: + from mod import baz + +reveal_type(Foo.Bar.baz) # N: Revealed type is "def (x: builtins.int) -> builtins.int" +reveal_type(Foo.Bar().baz) # E: Invalid self argument "Bar" to attribute function "baz" with type "Callable[[int], int]" \ + # N: Revealed type is "def () -> builtins.int" +[file mod.py] +def baz(x: int) -> int: ... + +[case testClassScopeImportUndefined] +class Foo: + from unknown import foo # E: Cannot find implementation or library stub for module named "unknown" \ + # N: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports + +reveal_type(Foo.foo) # N: Revealed type is "Any" +reveal_type(Foo().foo) # N: Revealed type is "Any" + +[case testClassScopeImportWithFollowImports] +# flags: --follow-imports=skip +class Foo: + from mod import foo + +reveal_type(Foo().foo) # N: Revealed type is "Any" +[file mod.py] +def foo(x: int, y: int) -> int: ... + +[case testClassScopeImportVarious] +class Foo: + from mod1 import foo + from mod2 import foo # E: Name "foo" already defined on line 2 + + from mod1 import meth1 + def meth1(self, a: str) -> str: ... # E: Name "meth1" already defined on line 5 + + def meth2(self, a: str) -> str: ... + from mod1 import meth2 # E: Name "meth2" already defined on line 8 + +class Bar: + from mod1 import foo + +import mod1 +reveal_type(Foo.foo) # N: Revealed type is "def (x: builtins.int, y: builtins.int) -> builtins.int" +reveal_type(Bar.foo) # N: Revealed type is "def (x: builtins.int, y: builtins.int) -> builtins.int" +reveal_type(mod1.foo) # N: Revealed type is "def (x: builtins.int, y: builtins.int) -> builtins.int" +[file mod1.py] +def foo(x: int, y: int) -> int: ... +def meth1(x: int) -> int: ... +def meth2(x: int) -> int: ... +[file mod2.py] +def foo(z: str) -> int: ... diff --git a/test-data/unit/check-modules.test b/test-data/unit/check-modules.test index 4f0aa83912ea7..e708ee5204972 100644 --- a/test-data/unit/check-modules.test +++ b/test-data/unit/check-modules.test @@ -131,9 +131,9 @@ def f() -> None: pass [case testImportWithinClassBody2] import typing class C: - from m import f + from m import f # E: Method must have at least one argument f() - f(C) # E: Too many arguments for "f" + f(C) # E: Too many arguments for "f" of "C" [file m.py] def f() -> None: pass [out] diff --git a/test-data/unit/check-newsemanal.test b/test-data/unit/check-newsemanal.test index 8a039ad278f37..276f634df9e46 100644 --- a/test-data/unit/check-newsemanal.test +++ b/test-data/unit/check-newsemanal.test @@ -2722,7 +2722,7 @@ import m [file m.py] class C: - from mm import f + from mm import f # E: Method must have at least one argument @dec(f) def m(self): pass @@ -2742,7 +2742,7 @@ import m [file m/__init__.py] class C: - from m.m import f + from m.m import f # E: Method must have at least one argument @dec(f) def m(self): pass diff --git a/test-data/unit/semanal-modules.test b/test-data/unit/semanal-modules.test index 86bb82d7bd694..16b9a9b182502 100644 --- a/test-data/unit/semanal-modules.test +++ b/test-data/unit/semanal-modules.test @@ -568,7 +568,7 @@ MypyFile:1( ImportFrom:2(_x, [y]) AssignmentStmt:3( NameExpr(z* [m]) - NameExpr(y [_x.y])))) + NameExpr(y [__main__.A.y])))) [case testImportInClassBody2] class A: From 5b4ffa99499177430470a08ab27c48d9ca04bac4 Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Thu, 17 Feb 2022 09:49:43 +0100 Subject: [PATCH 109/377] Deduplicate error codes for `ignore-without-code` (#12194) --- docs/source/error_code_list2.rst | 4 +++- docs/source/error_codes.rst | 4 ++++ mypy/errors.py | 4 ++-- test-data/unit/check-errorcodes.test | 14 +++++++++++++- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/docs/source/error_code_list2.rst b/docs/source/error_code_list2.rst index ba5b67a5aeb78..f9c9a64071d17 100644 --- a/docs/source/error_code_list2.rst +++ b/docs/source/error_code_list2.rst @@ -257,6 +257,8 @@ except that attempting to invoke an undefined method (e.g. ``__len__``) results while attempting to evaluate an object in boolean context without a concrete implementation results in a truthy value. +.. _ignore-without-code: + Check that ``# type: ignore`` include an error code [ignore-without-code] ------------------------------------------------------------------------- @@ -280,7 +282,7 @@ Example: # - the expected error 'assignment', and # - the unexpected error 'attr-defined' # are silenced. - # Error: "type: ignore" comment without error code (currently ignored: [attr-defined]) + # Error: "type: ignore" comment without error code (use "type: ignore[attr-defined]" instead) f.nme = 42 # type: ignore # This line warns correctly about the typo in the attribute name diff --git a/docs/source/error_codes.rst b/docs/source/error_codes.rst index 5255a6984b7b9..08d56c59fba20 100644 --- a/docs/source/error_codes.rst +++ b/docs/source/error_codes.rst @@ -31,6 +31,10 @@ or config `show_error_codes = True` to display error codes. Error codes are show $ mypy --show-error-codes prog.py prog.py:1: error: "str" has no attribute "trim" [attr-defined] +It's also possible to require error codes for ``type: ignore`` comments. +See :ref:`ignore-without-code` for more information. + + .. _silence-error-codes: Silencing errors based on error codes diff --git a/mypy/errors.py b/mypy/errors.py index 9744f134ac166..62e82048e964b 100644 --- a/mypy/errors.py +++ b/mypy/errors.py @@ -532,9 +532,9 @@ def generate_ignore_without_code_errors(self, continue codes_hint = '' - ignored_codes = used_ignored_lines[line] + ignored_codes = sorted(set(used_ignored_lines[line])) if ignored_codes: - codes_hint = f' (currently ignored: [{", ".join(ignored_codes)}])' + codes_hint = f' (use "type: ignore[{", ".join(ignored_codes)}]" instead)' message = f'"type: ignore" comment without error code{codes_hint}' # Don't use report since add_error_info will ignore the error! diff --git a/test-data/unit/check-errorcodes.test b/test-data/unit/check-errorcodes.test index 642828085b536..3c85ae48bb29a 100644 --- a/test-data/unit/check-errorcodes.test +++ b/test-data/unit/check-errorcodes.test @@ -148,7 +148,7 @@ x # type: ignore[name-defined, attr-defined] # E: Unused "type: ignore[attr-defi [case testErrorCodeMissingWhenRequired] # flags: --enable-error-code ignore-without-code "x" # type: ignore # E: "type: ignore" comment without error code [ignore-without-code] -y # type: ignore # E: "type: ignore" comment without error code (currently ignored: [name-defined]) [ignore-without-code] +y # type: ignore # E: "type: ignore" comment without error code (use "type: ignore[name-defined]" instead) [ignore-without-code] z # type: ignore[name-defined] "a" # type: ignore[ignore-without-code] @@ -164,6 +164,18 @@ z # type: ignore[ignore-without-code] # E: Unused "type: ignore" comment # E: Na x y # type: ignore # ignore the lack of error code since we're ignore the whole file +[case testErrorCodeMissingMultiple] +# flags: --enable-error-code ignore-without-code --python-version 3.7 +from __future__ import annotations +class A: + attr: int + def func(self, var: int) -> A | None: ... + +a: A | None +# 'union-attr' should only be listed once (instead of twice) and list should be sorted +a.func("invalid string").attr # type: ignore # E: "type: ignore" comment without error code (use "type: ignore[arg-type, union-attr]" instead) [ignore-without-code] +[builtins fixtures/tuple.pyi] + [case testErrorCodeIgnoreWithExtraSpace] x # type: ignore [name-defined] x2 # type: ignore [ name-defined ] From 31586774b7f801cb185c866f35e954c4ef6ffd55 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Thu, 17 Feb 2022 06:51:47 -0800 Subject: [PATCH 110/377] Fix more crashes in class scoped imports (#12199) Fixes #12197 This essentially walks back changes in #12023 that apply to function-like things that are imported in class-scope. We just issue a (non-blocking) error and mark the type as Any. Inference for variables still works fine; I'm yet to think of any problems that could cause. A full fix seems quite difficult, but this is better than both a crash and a blocking error. --- mypy/semanal.py | 70 ++++++++------ test-data/unit/check-classes.test | 115 +++++++++++++++-------- test-data/unit/check-modules.test | 5 +- test-data/unit/check-newsemanal.test | 4 +- test-data/unit/fine-grained-modules.test | 5 +- 5 files changed, 129 insertions(+), 70 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 0f9f3996892ad..c83bc01908ad3 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -48,7 +48,6 @@ reduce memory use). """ -import copy from contextlib import contextmanager from typing import ( @@ -4791,6 +4790,48 @@ def add_module_symbol(self, module_hidden=module_hidden ) + def _get_node_for_class_scoped_import( + self, name: str, symbol_node: Optional[SymbolNode], context: Context + ) -> Optional[SymbolNode]: + if symbol_node is None: + return None + # I promise this type checks; I'm just making mypyc issues go away. + # mypyc is absolutely convinced that `symbol_node` narrows to a Var in the following, + # when it can also be a FuncBase. Once fixed, `f` in the following can be removed. + # See also https://github.com/mypyc/mypyc/issues/892 + f = cast(Any, lambda x: x) + if isinstance(f(symbol_node), (FuncBase, Var)): + # For imports in class scope, we construct a new node to represent the symbol and + # set its `info` attribute to `self.type`. + existing = self.current_symbol_table().get(name) + if ( + # The redefinition checks in `add_symbol_table_node` don't work for our + # constructed Var / FuncBase, so check for possible redefinitions here. + existing is not None + and isinstance(f(existing.node), (FuncBase, Var)) + and ( + isinstance(f(existing.type), f(AnyType)) + or f(existing.type) == f(symbol_node).type + ) + ): + return existing.node + + # Construct the new node + if isinstance(f(symbol_node), FuncBase): + # In theory we could construct a new node here as well, but in practice + # it doesn't work well, see #12197 + typ: Optional[Type] = AnyType(TypeOfAny.from_error) + self.fail('Unsupported class scoped import', context) + else: + typ = f(symbol_node).type + symbol_node = Var(name, typ) + symbol_node._fullname = self.qualified_name(name) + assert self.type is not None # guaranteed by is_class_scope + symbol_node.info = self.type + symbol_node.line = context.line + symbol_node.column = context.column + return symbol_node + def add_imported_symbol(self, name: str, node: SymbolTableNode, @@ -4803,32 +4844,7 @@ def add_imported_symbol(self, symbol_node: Optional[SymbolNode] = node.node if self.is_class_scope(): - # I promise this type checks; I'm just making mypyc issues go away. - # mypyc is absolutely convinced that `symbol_node` narrows to a Var in the following, - # when it can also be a FuncBase. Once fixed, `f` in the following can be removed. - # See also https://github.com/mypyc/mypyc/issues/892 - f = cast(Any, lambda x: x) - if isinstance(f(symbol_node), (FuncBase, Var)): - # For imports in class scope, we construct a new node to represent the symbol and - # set its `info` attribute to `self.type`. - existing = self.current_symbol_table().get(name) - if ( - # The redefinition checks in `add_symbol_table_node` don't work for our - # constructed Var / FuncBase, so check for possible redefinitions here. - existing is not None - and isinstance(f(existing.node), (FuncBase, Var)) - and f(existing.type) == f(symbol_node).type - ): - symbol_node = existing.node - else: - # Construct the new node - constructed_node = copy.copy(f(symbol_node)) - assert self.type is not None # guaranteed by is_class_scope - constructed_node.line = context.line - constructed_node.column = context.column - constructed_node.info = self.type - constructed_node._fullname = self.qualified_name(name) - symbol_node = constructed_node + symbol_node = self._get_node_for_class_scoped_import(name, symbol_node, context) symbol = SymbolTableNode(node.kind, symbol_node, module_public=module_public, diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index 8f3a2c3087863..65b0e8d69cb57 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -7135,24 +7135,20 @@ class B(A): # E: Final class __main__.B has abstract attributes "foo" class C: class C1(XX): pass # E: Name "XX" is not defined -[case testClassScopeImportFunction] +[case testClassScopeImports] class Foo: - from mod import foo + from mod import plain_function # E: Unsupported class scoped import + from mod import plain_var -reveal_type(Foo.foo) # N: Revealed type is "def (x: builtins.int, y: builtins.int) -> builtins.int" -reveal_type(Foo().foo) # E: Invalid self argument "Foo" to attribute function "foo" with type "Callable[[int, int], int]" \ - # N: Revealed type is "def (y: builtins.int) -> builtins.int" -[file mod.py] -def foo(x: int, y: int) -> int: ... +reveal_type(Foo.plain_function) # N: Revealed type is "Any" +reveal_type(Foo().plain_function) # N: Revealed type is "Any" -[case testClassScopeImportVariable] -class Foo: - from mod import foo +reveal_type(Foo.plain_var) # N: Revealed type is "builtins.int" +reveal_type(Foo().plain_var) # N: Revealed type is "builtins.int" -reveal_type(Foo.foo) # N: Revealed type is "builtins.int" -reveal_type(Foo().foo) # N: Revealed type is "builtins.int" [file mod.py] -foo: int +def plain_function(x: int, y: int) -> int: ... +plain_var: int [case testClassScopeImportModule] class Foo: @@ -7163,30 +7159,52 @@ reveal_type(Foo.mod.foo) # N: Revealed type is "builtins.int" [file mod.py] foo: int -[case testClassScopeImportFunctionAlias] +[case testClassScopeImportAlias] class Foo: - from mod import foo - bar = foo + from mod import function # E: Unsupported class scoped import + foo = function - from mod import const_foo - const_bar = const_foo + from mod import var1 + bar = var1 + + from mod import var2 + baz = var2 + + from mod import var3 + qux = var3 + +reveal_type(Foo.foo) # N: Revealed type is "Any" +reveal_type(Foo.function) # N: Revealed type is "Any" + +reveal_type(Foo.bar) # N: Revealed type is "builtins.int" +reveal_type(Foo.var1) # N: Revealed type is "builtins.int" + +reveal_type(Foo.baz) # N: Revealed type is "mod.C" +reveal_type(Foo.var2) # N: Revealed type is "mod.C" + +reveal_type(Foo.qux) # N: Revealed type is "builtins.int" +reveal_type(Foo.var3) # N: Revealed type is "builtins.int" -reveal_type(Foo.foo) # N: Revealed type is "def (x: builtins.int, y: builtins.int) -> builtins.int" -reveal_type(Foo.bar) # N: Revealed type is "def (x: builtins.int, y: builtins.int) -> builtins.int" -reveal_type(Foo.const_foo) # N: Revealed type is "builtins.int" -reveal_type(Foo.const_bar) # N: Revealed type is "builtins.int" [file mod.py] -def foo(x: int, y: int) -> int: ... -const_foo: int +def function(x: int, y: int) -> int: ... +var1: int + +class C: ... +var2: C + +A = int +var3: A + [case testClassScopeImportModuleStar] class Foo: - from mod import * + from mod import * # E: Unsupported class scoped import reveal_type(Foo.foo) # N: Revealed type is "builtins.int" -reveal_type(Foo.bar) # N: Revealed type is "def (x: builtins.int) -> builtins.int" +reveal_type(Foo.bar) # N: Revealed type is "Any" reveal_type(Foo.baz) # E: "Type[Foo]" has no attribute "baz" \ # N: Revealed type is "Any" + [file mod.py] foo: int def bar(x: int) -> int: ... @@ -7194,11 +7212,11 @@ def bar(x: int) -> int: ... [case testClassScopeImportFunctionNested] class Foo: class Bar: - from mod import baz + from mod import baz # E: Unsupported class scoped import + +reveal_type(Foo.Bar.baz) # N: Revealed type is "Any" +reveal_type(Foo.Bar().baz) # N: Revealed type is "Any" -reveal_type(Foo.Bar.baz) # N: Revealed type is "def (x: builtins.int) -> builtins.int" -reveal_type(Foo.Bar().baz) # E: Invalid self argument "Bar" to attribute function "baz" with type "Callable[[int], int]" \ - # N: Revealed type is "def () -> builtins.int" [file mod.py] def baz(x: int) -> int: ... @@ -7221,25 +7239,48 @@ def foo(x: int, y: int) -> int: ... [case testClassScopeImportVarious] class Foo: - from mod1 import foo - from mod2 import foo # E: Name "foo" already defined on line 2 + from mod1 import foo # E: Unsupported class scoped import + from mod2 import foo - from mod1 import meth1 + from mod1 import meth1 # E: Unsupported class scoped import def meth1(self, a: str) -> str: ... # E: Name "meth1" already defined on line 5 def meth2(self, a: str) -> str: ... - from mod1 import meth2 # E: Name "meth2" already defined on line 8 + from mod1 import meth2 # E: Unsupported class scoped import \ + # E: Name "meth2" already defined on line 8 class Bar: - from mod1 import foo + from mod1 import foo # E: Unsupported class scoped import import mod1 -reveal_type(Foo.foo) # N: Revealed type is "def (x: builtins.int, y: builtins.int) -> builtins.int" -reveal_type(Bar.foo) # N: Revealed type is "def (x: builtins.int, y: builtins.int) -> builtins.int" +reveal_type(Foo.foo) # N: Revealed type is "Any" +reveal_type(Bar.foo) # N: Revealed type is "Any" reveal_type(mod1.foo) # N: Revealed type is "def (x: builtins.int, y: builtins.int) -> builtins.int" + [file mod1.py] def foo(x: int, y: int) -> int: ... def meth1(x: int) -> int: ... def meth2(x: int) -> int: ... [file mod2.py] def foo(z: str) -> int: ... + + +[case testClassScopeImportWithError] +class Foo: + from mod import meth1 # E: Unsupported class scoped import + from mod import meth2 # E: Unsupported class scoped import + from mod import T + +reveal_type(Foo.T) # E: Type variable "Foo.T" cannot be used as an expression \ + # N: Revealed type is "Any" + +[file mod.pyi] +from typing import Any, TypeVar, overload + +@overload +def meth1(self: Any, y: int) -> int: ... +@overload +def meth1(self: Any, y: str) -> str: ... + +T = TypeVar("T") +def meth2(self: Any, y: T) -> T: ... diff --git a/test-data/unit/check-modules.test b/test-data/unit/check-modules.test index e708ee5204972..6c32c088255d1 100644 --- a/test-data/unit/check-modules.test +++ b/test-data/unit/check-modules.test @@ -131,9 +131,10 @@ def f() -> None: pass [case testImportWithinClassBody2] import typing class C: - from m import f # E: Method must have at least one argument + from m import f # E: Unsupported class scoped import f() - f(C) # E: Too many arguments for "f" of "C" + # ideally, the following should error: + f(C) [file m.py] def f() -> None: pass [out] diff --git a/test-data/unit/check-newsemanal.test b/test-data/unit/check-newsemanal.test index 276f634df9e46..3b4b0303691a8 100644 --- a/test-data/unit/check-newsemanal.test +++ b/test-data/unit/check-newsemanal.test @@ -2722,7 +2722,7 @@ import m [file m.py] class C: - from mm import f # E: Method must have at least one argument + from mm import f # E: Unsupported class scoped import @dec(f) def m(self): pass @@ -2742,7 +2742,7 @@ import m [file m/__init__.py] class C: - from m.m import f # E: Method must have at least one argument + from m.m import f # E: Unsupported class scoped import @dec(f) def m(self): pass diff --git a/test-data/unit/fine-grained-modules.test b/test-data/unit/fine-grained-modules.test index 856eaaad083c4..80a2883ee756d 100644 --- a/test-data/unit/fine-grained-modules.test +++ b/test-data/unit/fine-grained-modules.test @@ -1509,11 +1509,12 @@ class C: pass main:3: error: Name "f" is not defined main:4: error: Name "C" is not defined == -main:3: error: Missing positional argument "x" in call to "f" +main:2: error: Unsupported class scoped import main:4: error: Name "C" is not defined == -main:3: error: Missing positional argument "x" in call to "f" +main:2: error: Unsupported class scoped import == +main:2: error: Unsupported class scoped import [case testImportStarAddMissingDependencyInsidePackage1] from p.b import f From d02db50c3f187871545b1a560a2d93fffcb53e7e Mon Sep 17 00:00:00 2001 From: Tuomas Siipola Date: Thu, 17 Feb 2022 22:50:05 +0200 Subject: [PATCH 111/377] Suggest `typing.Callable` when using `callable` as type (#12204) --- mypy/typeanal.py | 2 ++ test-data/unit/check-functions.test | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/mypy/typeanal.py b/mypy/typeanal.py index 6f75ff7e44d8b..766e413545536 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -494,6 +494,8 @@ def analyze_unbound_type_without_type_info(self, t: UnboundType, sym: SymbolTabl message = 'Function "{}" is not valid as a type' if name == 'builtins.any': notes.append('Perhaps you meant "typing.Any" instead of "any"?') + elif name == 'builtins.callable': + notes.append('Perhaps you meant "typing.Callable" instead of "callable"?') else: notes.append('Perhaps you need "Callable[...]" or a callback protocol?') elif isinstance(sym.node, MypyFile): diff --git a/test-data/unit/check-functions.test b/test-data/unit/check-functions.test index 4b6c7253d6472..30150ca436e84 100644 --- a/test-data/unit/check-functions.test +++ b/test-data/unit/check-functions.test @@ -2610,3 +2610,8 @@ reveal_type(foo()) # N: Revealed type is "None" def a(b: any): pass # E: Function "builtins.any" is not valid as a type \ # N: Perhaps you meant "typing.Any" instead of "any"? [builtins fixtures/any.pyi] + +[case testCallableArgument] +def a(b: callable): pass # E: Function "builtins.callable" is not valid as a type \ + # N: Perhaps you meant "typing.Callable" instead of "callable"? +[builtins fixtures/callable.pyi] From c7365efceb24587c9b71066c360e167bcdce536a Mon Sep 17 00:00:00 2001 From: jhance Date: Fri, 18 Feb 2022 05:33:43 -0800 Subject: [PATCH 112/377] [mypyc] Implement additional ircheck checks (#12191) * Implement more checks in ircheck Check op/register validity and check type coercions for return and assign. * Add checks for call operations, control ops, and literal loads * Add check for duplicate ops In particular, this will catch the case where builder.add() is called twice, which causes very weird bogus IR. --- mypyc/analysis/ircheck.py | 226 ++++++++++++++++++++++++++--- mypyc/ir/ops.py | 18 ++- mypyc/test-data/irbuild-basic.test | 7 +- mypyc/test-data/irbuild-dict.test | 1 - mypyc/test/test_ircheck.py | 155 +++++++++++++++++--- 5 files changed, 360 insertions(+), 47 deletions(-) diff --git a/mypyc/analysis/ircheck.py b/mypyc/analysis/ircheck.py index f15beceff8cec..6450766f404c3 100644 --- a/mypyc/analysis/ircheck.py +++ b/mypyc/analysis/ircheck.py @@ -1,14 +1,20 @@ """Utilities for checking that internal ir is valid and consistent.""" -from typing import List, Union +from typing import List, Union, Set, Tuple from mypyc.ir.pprint import format_func from mypyc.ir.ops import ( OpVisitor, BasicBlock, Op, ControlOp, Goto, Branch, Return, Unreachable, Assign, AssignMulti, LoadErrorValue, LoadLiteral, GetAttr, SetAttr, LoadStatic, InitStatic, TupleGet, TupleSet, IncRef, DecRef, Call, MethodCall, Cast, Box, Unbox, RaiseStandardError, CallC, Truncate, LoadGlobal, IntOp, ComparisonOp, - LoadMem, SetMem, GetElementPtr, LoadAddress, KeepAlive + LoadMem, SetMem, GetElementPtr, LoadAddress, KeepAlive, Register, Integer, + BaseAssign ) -from mypyc.ir.func_ir import FuncIR +from mypyc.ir.rtypes import ( + RType, RPrimitive, RUnion, is_object_rprimitive, RInstance, RArray, + int_rprimitive, list_rprimitive, dict_rprimitive, set_rprimitive, + range_rprimitive, str_rprimitive, bytes_rprimitive, tuple_rprimitive +) +from mypyc.ir.func_ir import FuncIR, FUNC_STATICMETHOD class FnError(object): @@ -17,8 +23,11 @@ def __init__(self, source: Union[Op, BasicBlock], desc: str) -> None: self.desc = desc def __eq__(self, other: object) -> bool: - return isinstance(other, FnError) and self.source == other.source and \ - self.desc == other.desc + return ( + isinstance(other, FnError) + and self.source == other.source + and self.desc == other.desc + ) def __repr__(self) -> str: return f"FnError(source={self.source}, desc={self.desc})" @@ -28,19 +37,44 @@ def check_func_ir(fn: FuncIR) -> List[FnError]: """Applies validations to a given function ir and returns a list of errors found.""" errors = [] + op_set = set() + for block in fn.blocks: if not block.terminated: - errors.append(FnError( - source=block.ops[-1] if block.ops else block, - desc="Block not terminated", - )) + errors.append( + FnError( + source=block.ops[-1] if block.ops else block, + desc="Block not terminated", + ) + ) + for op in block.ops[:-1]: + if isinstance(op, ControlOp): + errors.append( + FnError( + source=op, + desc="Block has operations after control op", + ) + ) + + if op in op_set: + errors.append( + FnError( + source=op, + desc="Func has a duplicate op", + ) + ) + op_set.add(op) + + errors.extend(check_op_sources_valid(fn)) + if errors: + return errors op_checker = OpChecker(fn) for block in fn.blocks: for op in block.ops: op.accept(op_checker) - return errors + op_checker.errors + return op_checker.errors class IrCheckException(Exception): @@ -50,11 +84,90 @@ class IrCheckException(Exception): def assert_func_ir_valid(fn: FuncIR) -> None: errors = check_func_ir(fn) if errors: - raise IrCheckException("Internal error: Generated invalid IR: \n" + "\n".join( - format_func(fn, [(e.source, e.desc) for e in errors])), + raise IrCheckException( + "Internal error: Generated invalid IR: \n" + + "\n".join(format_func(fn, [(e.source, e.desc) for e in errors])), ) +def check_op_sources_valid(fn: FuncIR) -> List[FnError]: + errors = [] + valid_ops: Set[Op] = set() + valid_registers: Set[Register] = set() + + for block in fn.blocks: + valid_ops.update(block.ops) + + valid_registers.update( + [op.dest for op in block.ops if isinstance(op, BaseAssign)] + ) + + valid_registers.update(fn.arg_regs) + + for block in fn.blocks: + for op in block.ops: + for source in op.sources(): + if isinstance(source, Integer): + pass + elif isinstance(source, Op): + if source not in valid_ops: + errors.append( + FnError( + source=op, + desc=f"Invalid op reference to op of type {type(source).__name__}", + ) + ) + elif isinstance(source, Register): + if source not in valid_registers: + errors.append( + FnError( + source=op, + desc=f"Invalid op reference to register {source.name}", + ) + ) + + return errors + + +disjoint_types = set( + [ + int_rprimitive.name, + bytes_rprimitive.name, + str_rprimitive.name, + dict_rprimitive.name, + list_rprimitive.name, + set_rprimitive.name, + tuple_rprimitive.name, + range_rprimitive.name, + ] +) + + +def can_coerce_to(src: RType, dest: RType) -> bool: + """Check if src can be assigned to dest_rtype. + + Currently okay to have false positives. + """ + if isinstance(dest, RUnion): + return any(can_coerce_to(src, d) for d in dest.items) + + if isinstance(dest, RPrimitive): + if isinstance(src, RPrimitive): + # If either src or dest is a disjoint type, then they must both be. + if src.name in disjoint_types and dest.name in disjoint_types: + return src.name == dest.name + return src.size == dest.size + if isinstance(src, RInstance): + return is_object_rprimitive(dest) + if isinstance(src, RUnion): + # IR doesn't have the ability to narrow unions based on + # control flow, so cannot be a strict all() here. + return any(can_coerce_to(s, dest) for s in src.items) + return False + + return True + + class OpChecker(OpVisitor[None]): def __init__(self, parent_fn: FuncIR) -> None: self.parent_fn = parent_fn @@ -66,7 +179,16 @@ def fail(self, source: Op, desc: str) -> None: def check_control_op_targets(self, op: ControlOp) -> None: for target in op.targets(): if target not in self.parent_fn.blocks: - self.fail(source=op, desc=f"Invalid control operation target: {target.label}") + self.fail( + source=op, desc=f"Invalid control operation target: {target.label}" + ) + + def check_type_coercion(self, op: Op, src: RType, dest: RType) -> None: + if not can_coerce_to(src, dest): + self.fail( + source=op, + desc=f"Cannot coerce source type {src.name} to dest type {dest.name}", + ) def visit_goto(self, op: Goto) -> None: self.check_control_op_targets(op) @@ -75,29 +197,76 @@ def visit_branch(self, op: Branch) -> None: self.check_control_op_targets(op) def visit_return(self, op: Return) -> None: - pass + self.check_type_coercion(op, op.value.type, self.parent_fn.decl.sig.ret_type) def visit_unreachable(self, op: Unreachable) -> None: + # Unreachables are checked at a higher level since validation + # requires access to the entire basic block. pass def visit_assign(self, op: Assign) -> None: - pass + self.check_type_coercion(op, op.src.type, op.dest.type) def visit_assign_multi(self, op: AssignMulti) -> None: - pass + for src in op.src: + assert isinstance(op.dest.type, RArray) + self.check_type_coercion(op, src.type, op.dest.type.item_type) def visit_load_error_value(self, op: LoadErrorValue) -> None: + # Currently it is assumed that all types have an error value. + # Once this is fixed we can validate that the rtype here actually + # has an error value. pass + def check_tuple_items_valid_literals( + self, op: LoadLiteral, t: Tuple[object, ...] + ) -> None: + for x in t: + if x is not None and not isinstance( + x, (str, bytes, bool, int, float, complex, tuple) + ): + self.fail(op, f"Invalid type for item of tuple literal: {type(x)})") + if isinstance(x, tuple): + self.check_tuple_items_valid_literals(op, x) + def visit_load_literal(self, op: LoadLiteral) -> None: - pass + expected_type = None + if op.value is None: + expected_type = "builtins.object" + elif isinstance(op.value, int): + expected_type = "builtins.int" + elif isinstance(op.value, str): + expected_type = "builtins.str" + elif isinstance(op.value, bytes): + expected_type = "builtins.bytes" + elif isinstance(op.value, bool): + expected_type = "builtins.object" + elif isinstance(op.value, float): + expected_type = "builtins.float" + elif isinstance(op.value, complex): + expected_type = "builtins.object" + elif isinstance(op.value, tuple): + expected_type = "builtins.tuple" + self.check_tuple_items_valid_literals(op, op.value) + + assert expected_type is not None, "Missed a case for LoadLiteral check" + + if op.type.name not in [expected_type, "builtins.object"]: + self.fail( + op, + f"Invalid literal value for type: value has " + f"type {expected_type}, but op has type {op.type.name}", + ) def visit_get_attr(self, op: GetAttr) -> None: + # Nothing to do. pass def visit_set_attr(self, op: SetAttr) -> None: + # Nothing to do. pass + # Static operations cannot be checked at the function level. def visit_load_static(self, op: LoadStatic) -> None: pass @@ -105,22 +274,41 @@ def visit_init_static(self, op: InitStatic) -> None: pass def visit_tuple_get(self, op: TupleGet) -> None: + # Nothing to do. pass def visit_tuple_set(self, op: TupleSet) -> None: + # Nothing to do. pass def visit_inc_ref(self, op: IncRef) -> None: + # Nothing to do. pass def visit_dec_ref(self, op: DecRef) -> None: + # Nothing to do. pass def visit_call(self, op: Call) -> None: - pass + # Length is checked in constructor, and return type is set + # in a way that can't be incorrect + for arg_value, arg_runtime in zip(op.args, op.fn.sig.args): + self.check_type_coercion(op, arg_value.type, arg_runtime.type) def visit_method_call(self, op: MethodCall) -> None: - pass + # Similar to above, but we must look up method first. + method_decl = op.receiver_type.class_ir.method_decl(op.method) + if method_decl.kind == FUNC_STATICMETHOD: + decl_index = 0 + else: + decl_index = 1 + + if len(op.args) + decl_index != len(method_decl.sig.args): + self.fail(op, "Incorrect number of args for method call.") + + # Skip the receiver argument (self) + for arg_value, arg_runtime in zip(op.args, method_decl.sig.args[decl_index:]): + self.check_type_coercion(op, arg_value.type, arg_runtime.type) def visit_cast(self, op: Cast) -> None: pass diff --git a/mypyc/ir/ops.py b/mypyc/ir/ops.py index 22dead2f79764..65480ebcc7c38 100644 --- a/mypyc/ir/ops.py +++ b/mypyc/ir/ops.py @@ -214,15 +214,21 @@ def accept(self, visitor: 'OpVisitor[T]') -> T: pass -class Assign(Op): +class BaseAssign(Op): + """Base class for ops that assign to a register.""" + def __init__(self, dest: Register, line: int = -1) -> None: + super().__init__(line) + self.dest = dest + + +class Assign(BaseAssign): """Assign a value to a Register (dest = src).""" error_kind = ERR_NEVER def __init__(self, dest: Register, src: Value, line: int = -1) -> None: - super().__init__(line) + super().__init__(dest, line) self.src = src - self.dest = dest def sources(self) -> List[Value]: return [self.src] @@ -234,7 +240,7 @@ def accept(self, visitor: 'OpVisitor[T]') -> T: return visitor.visit_assign(self) -class AssignMulti(Op): +class AssignMulti(BaseAssign): """Assign multiple values to a Register (dest = src1, src2, ...). This is used to initialize RArray values. It's provided to avoid @@ -248,12 +254,11 @@ class AssignMulti(Op): error_kind = ERR_NEVER def __init__(self, dest: Register, src: List[Value], line: int = -1) -> None: - super().__init__(line) + super().__init__(dest, line) assert src assert isinstance(dest.type, RArray) assert dest.type.length == len(src) self.src = src - self.dest = dest def sources(self) -> List[Value]: return self.src[:] @@ -490,6 +495,7 @@ def __init__(self, fn: 'FuncDecl', args: Sequence[Value], line: int) -> None: super().__init__(line) self.fn = fn self.args = list(args) + assert len(self.args) == len(fn.sig.args) self.type = fn.sig.ret_type def sources(self) -> List[Value]: diff --git a/mypyc/test-data/irbuild-basic.test b/mypyc/test-data/irbuild-basic.test index 2032ea034e71a..5aa5e25487c4b 100644 --- a/mypyc/test-data/irbuild-basic.test +++ b/mypyc/test-data/irbuild-basic.test @@ -909,20 +909,19 @@ L0: [case testDownCastSpecialCases] from typing import cast, Optional, Tuple class A: pass -def f(o: Optional[A], n: int, t: Tuple[int, ...]) -> None: +def f(o: Optional[A], n: int, t: Tuple[int, ...], tt: Tuple[int, int]) -> None: a = cast(A, o) m = cast(bool, n) - tt: Tuple[int, int] t = tt [out] -def f(o, n, t): +def f(o, n, t, tt): o :: union[__main__.A, None] n :: int t :: tuple + tt :: tuple[int, int] r0, a :: __main__.A r1 :: object r2, m :: bool - tt :: tuple[int, int] r3 :: object L0: r0 = cast(__main__.A, o) diff --git a/mypyc/test-data/irbuild-dict.test b/mypyc/test-data/irbuild-dict.test index 69dd42f01dd36..089a9a02b0b04 100644 --- a/mypyc/test-data/irbuild-dict.test +++ b/mypyc/test-data/irbuild-dict.test @@ -458,4 +458,3 @@ L2: L3: r7 = box(None, 1) return r7 - diff --git a/mypyc/test/test_ircheck.py b/mypyc/test/test_ircheck.py index 28d3c8e8c25d0..3c56ddac3e858 100644 --- a/mypyc/test/test_ircheck.py +++ b/mypyc/test/test_ircheck.py @@ -1,9 +1,15 @@ import unittest -from typing import List - -from mypyc.analysis.ircheck import check_func_ir, FnError -from mypyc.ir.rtypes import none_rprimitive -from mypyc.ir.ops import BasicBlock, Op, Return, Integer, Goto +from typing import List, Optional + +from mypyc.analysis.ircheck import check_func_ir, FnError, can_coerce_to +from mypyc.ir.class_ir import ClassIR +from mypyc.ir.rtypes import ( + none_rprimitive, str_rprimitive, int32_rprimitive, int64_rprimitive, + RType, RUnion, bytes_rprimitive, RInstance, object_rprimitive +) +from mypyc.ir.ops import ( + BasicBlock, Op, Return, Integer, Goto, Register, LoadLiteral, Assign +) from mypyc.ir.func_ir import FuncIR, FuncDecl, FuncSignature from mypyc.ir.pprint import format_func @@ -30,19 +36,33 @@ def basic_block(self, ops: List[Op]) -> BasicBlock: block.ops = ops return block - def func_decl(self, name: str) -> FuncDecl: - return FuncDecl(name=name, class_name=None, module_name="module", sig=FuncSignature( - args=[], ret_type=none_rprimitive, - )) + def func_decl(self, name: str, ret_type: Optional[RType] = None) -> FuncDecl: + if ret_type is None: + ret_type = none_rprimitive + return FuncDecl( + name=name, + class_name=None, + module_name="module", + sig=FuncSignature( + args=[], + ret_type=ret_type, + ), + ) def test_valid_fn(self) -> None: - assert_no_errors(FuncIR( - decl=self.func_decl(name="func_1"), - arg_regs=[], - blocks=[self.basic_block(ops=[ - Return(value=NONE_VALUE), - ])], - )) + assert_no_errors( + FuncIR( + decl=self.func_decl(name="func_1"), + arg_regs=[], + blocks=[ + self.basic_block( + ops=[ + Return(value=NONE_VALUE), + ] + ) + ], + ) + ) def test_block_not_terminated_empty_block(self) -> None: block = self.basic_block([]) @@ -73,7 +93,108 @@ def test_invalid_goto(self) -> None: # block_1 omitted blocks=[block_2], ) - assert_has_error(fn, FnError(source=goto, desc="Invalid control operation target: 1")) + assert_has_error( + fn, FnError(source=goto, desc="Invalid control operation target: 1") + ) + + def test_invalid_register_source(self) -> None: + ret = Return( + value=Register( + type=none_rprimitive, + name="r1", + ) + ) + block = self.basic_block([ret]) + fn = FuncIR( + decl=self.func_decl(name="func_1"), + arg_regs=[], + blocks=[block], + ) + assert_has_error( + fn, FnError(source=ret, desc="Invalid op reference to register r1") + ) + + def test_invalid_op_source(self) -> None: + ret = Return( + value=LoadLiteral( + value="foo", + rtype=str_rprimitive, + ) + ) + block = self.basic_block([ret]) + fn = FuncIR( + decl=self.func_decl(name="func_1"), + arg_regs=[], + blocks=[block], + ) + assert_has_error( + fn, + FnError(source=ret, desc="Invalid op reference to op of type LoadLiteral"), + ) + + def test_invalid_return_type(self) -> None: + ret = Return(value=Integer(value=5, rtype=int32_rprimitive)) + fn = FuncIR( + decl=self.func_decl(name="func_1", ret_type=int64_rprimitive), + arg_regs=[], + blocks=[self.basic_block([ret])], + ) + assert_has_error( + fn, + FnError( + source=ret, desc="Cannot coerce source type int32 to dest type int64" + ), + ) + + def test_invalid_assign(self) -> None: + arg_reg = Register(type=int64_rprimitive, name="r1") + assign = Assign(dest=arg_reg, src=Integer(value=5, rtype=int32_rprimitive)) + ret = Return(value=NONE_VALUE) + fn = FuncIR( + decl=self.func_decl(name="func_1"), + arg_regs=[arg_reg], + blocks=[self.basic_block([assign, ret])], + ) + assert_has_error( + fn, + FnError( + source=assign, desc="Cannot coerce source type int32 to dest type int64" + ), + ) + + def test_can_coerce_to(self) -> None: + cls = ClassIR(name="Cls", module_name="cls") + valid_cases = [ + (int64_rprimitive, int64_rprimitive), + (str_rprimitive, str_rprimitive), + (str_rprimitive, object_rprimitive), + (object_rprimitive, str_rprimitive), + (RUnion([bytes_rprimitive, str_rprimitive]), str_rprimitive), + (str_rprimitive, RUnion([bytes_rprimitive, str_rprimitive])), + (RInstance(cls), object_rprimitive), + ] + + invalid_cases = [ + (int64_rprimitive, int32_rprimitive), + (RInstance(cls), str_rprimitive), + (str_rprimitive, bytes_rprimitive), + ] + + for src, dest in valid_cases: + assert can_coerce_to(src, dest) + for src, dest in invalid_cases: + assert not can_coerce_to(src, dest) + + def test_duplicate_op(self) -> None: + arg_reg = Register(type=int32_rprimitive, name="r1") + assign = Assign(dest=arg_reg, src=Integer(value=5, rtype=int32_rprimitive)) + block = self.basic_block([assign, assign, Return(value=NONE_VALUE)]) + fn = FuncIR( + decl=self.func_decl(name="func_1"), + arg_regs=[], + blocks=[block], + ) + assert_has_error(fn, FnError(source=assign, desc="Func has a duplicate op")) def test_pprint(self) -> None: block_1 = self.basic_block([Return(value=NONE_VALUE)]) From 85fc99c99e7e2afc5896de1842d52e6e6cd55197 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Sat, 19 Feb 2022 07:47:17 +0000 Subject: [PATCH 113/377] stubtest: error if a function is async at runtime but not in the stub (and vice versa) (#12212) --- mypy/stubtest.py | 41 +++++++++++++++++++++++++++--- mypy/test/teststubtest.py | 53 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 4 deletions(-) diff --git a/mypy/stubtest.py b/mypy/stubtest.py index e67992ace5f8a..546ea96dd9a0b 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -676,6 +676,18 @@ def _verify_signature( yield 'runtime does not have **kwargs argument "{}"'.format(stub.varkw.variable.name) +def _verify_coroutine( + stub: nodes.FuncItem, runtime: Any, *, runtime_is_coroutine: bool +) -> Optional[str]: + if stub.is_coroutine: + if not runtime_is_coroutine: + return 'is an "async def" function in the stub, but not at runtime' + else: + if runtime_is_coroutine: + return 'is an "async def" function at runtime, but not in the stub' + return None + + @verify.register(nodes.FuncItem) def verify_funcitem( stub: nodes.FuncItem, runtime: MaybeMissing[Any], object_path: List[str] @@ -693,19 +705,40 @@ def verify_funcitem( yield Error(object_path, "is inconsistent, " + message, stub, runtime) signature = safe_inspect_signature(runtime) + runtime_is_coroutine = inspect.iscoroutinefunction(runtime) + + if signature: + stub_sig = Signature.from_funcitem(stub) + runtime_sig = Signature.from_inspect_signature(signature) + runtime_sig_desc = f'{"async " if runtime_is_coroutine else ""}def {signature}' + else: + runtime_sig_desc = None + + coroutine_mismatch_error = _verify_coroutine( + stub, + runtime, + runtime_is_coroutine=runtime_is_coroutine + ) + + if coroutine_mismatch_error is not None: + yield Error( + object_path, + coroutine_mismatch_error, + stub, + runtime, + runtime_desc=runtime_sig_desc + ) + if not signature: return - stub_sig = Signature.from_funcitem(stub) - runtime_sig = Signature.from_inspect_signature(signature) - for message in _verify_signature(stub_sig, runtime_sig, function_name=stub.name): yield Error( object_path, "is inconsistent, " + message, stub, runtime, - runtime_desc="def " + str(signature), + runtime_desc=runtime_sig_desc, ) diff --git a/mypy/test/teststubtest.py b/mypy/test/teststubtest.py index 2852299548ed5..78ae82b058cd1 100644 --- a/mypy/test/teststubtest.py +++ b/mypy/test/teststubtest.py @@ -28,6 +28,34 @@ def use_tmp_dir() -> Iterator[None]: TEST_MODULE_NAME = "test_module" + +stubtest_typing_stub = """ +Any = object() + +class _SpecialForm: + def __getitem__(self, typeargs: Any) -> object: ... + +Callable: _SpecialForm = ... +Generic: _SpecialForm = ... + +class TypeVar: + def __init__(self, name, covariant: bool = ..., contravariant: bool = ...) -> None: ... + +_T = TypeVar("_T") +_T_co = TypeVar("_T_co", covariant=True) +_K = TypeVar("_K") +_V = TypeVar("_V") +_S = TypeVar("_S", contravariant=True) +_R = TypeVar("_R", covariant=True) + +class Coroutine(Generic[_T_co, _S, _R]): ... +class Iterable(Generic[_T_co]): ... +class Mapping(Generic[_K, _V]): ... +class Sequence(Iterable[_T_co]): ... +class Tuple(Sequence[_T_co]): ... +def overload(func: _T) -> _T: ... +""" + stubtest_builtins_stub = """ from typing import Generic, Mapping, Sequence, TypeVar, overload @@ -66,6 +94,8 @@ def run_stubtest( with use_tmp_dir(): with open("builtins.pyi", "w") as f: f.write(stubtest_builtins_stub) + with open("typing.pyi", "w") as f: + f.write(stubtest_typing_stub) with open("{}.pyi".format(TEST_MODULE_NAME), "w") as f: f.write(stub) with open("{}.py".format(TEST_MODULE_NAME), "w") as f: @@ -172,6 +202,29 @@ class X: error="X.mistyped_var", ) + @collect_cases + def test_coroutines(self) -> Iterator[Case]: + yield Case( + stub="async def foo() -> int: ...", + runtime="def foo(): return 5", + error="foo", + ) + yield Case( + stub="def bar() -> int: ...", + runtime="async def bar(): return 5", + error="bar", + ) + yield Case( + stub="def baz() -> int: ...", + runtime="def baz(): return 5", + error=None, + ) + yield Case( + stub="async def bingo() -> int: ...", + runtime="async def bingo(): return 5", + error=None, + ) + @collect_cases def test_arg_name(self) -> Iterator[Case]: yield Case( From 36d50d68ba350ebd167a604a2bb3906ac720911f Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Sun, 20 Feb 2022 00:15:07 +0100 Subject: [PATCH 114/377] Tweak ignore-without-code error message (#12216) --- docs/source/error_code_list2.rst | 2 +- mypy/errors.py | 2 +- test-data/unit/check-errorcodes.test | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/error_code_list2.rst b/docs/source/error_code_list2.rst index f9c9a64071d17..c55643ad6181e 100644 --- a/docs/source/error_code_list2.rst +++ b/docs/source/error_code_list2.rst @@ -282,7 +282,7 @@ Example: # - the expected error 'assignment', and # - the unexpected error 'attr-defined' # are silenced. - # Error: "type: ignore" comment without error code (use "type: ignore[attr-defined]" instead) + # Error: "type: ignore" comment without error code (consider "type: ignore[attr-defined]" instead) f.nme = 42 # type: ignore # This line warns correctly about the typo in the attribute name diff --git a/mypy/errors.py b/mypy/errors.py index 62e82048e964b..60abb739ba847 100644 --- a/mypy/errors.py +++ b/mypy/errors.py @@ -534,7 +534,7 @@ def generate_ignore_without_code_errors(self, codes_hint = '' ignored_codes = sorted(set(used_ignored_lines[line])) if ignored_codes: - codes_hint = f' (use "type: ignore[{", ".join(ignored_codes)}]" instead)' + codes_hint = f' (consider "type: ignore[{", ".join(ignored_codes)}]" instead)' message = f'"type: ignore" comment without error code{codes_hint}' # Don't use report since add_error_info will ignore the error! diff --git a/test-data/unit/check-errorcodes.test b/test-data/unit/check-errorcodes.test index 3c85ae48bb29a..a74771108ca20 100644 --- a/test-data/unit/check-errorcodes.test +++ b/test-data/unit/check-errorcodes.test @@ -148,7 +148,7 @@ x # type: ignore[name-defined, attr-defined] # E: Unused "type: ignore[attr-defi [case testErrorCodeMissingWhenRequired] # flags: --enable-error-code ignore-without-code "x" # type: ignore # E: "type: ignore" comment without error code [ignore-without-code] -y # type: ignore # E: "type: ignore" comment without error code (use "type: ignore[name-defined]" instead) [ignore-without-code] +y # type: ignore # E: "type: ignore" comment without error code (consider "type: ignore[name-defined]" instead) [ignore-without-code] z # type: ignore[name-defined] "a" # type: ignore[ignore-without-code] @@ -173,7 +173,7 @@ class A: a: A | None # 'union-attr' should only be listed once (instead of twice) and list should be sorted -a.func("invalid string").attr # type: ignore # E: "type: ignore" comment without error code (use "type: ignore[arg-type, union-attr]" instead) [ignore-without-code] +a.func("invalid string").attr # type: ignore # E: "type: ignore" comment without error code (consider "type: ignore[arg-type, union-attr]" instead) [ignore-without-code] [builtins fixtures/tuple.pyi] [case testErrorCodeIgnoreWithExtraSpace] From 9af578d796564617fc5d110b66e84087e23c41ea Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Sat, 19 Feb 2022 23:51:52 +0000 Subject: [PATCH 115/377] stubtest: error if a dunder method is missing from a stub (#12203) --- mypy/stubtest.py | 72 +++++++++++++++++++++++++++++++++++---- mypy/test/teststubtest.py | 13 ++++++- 2 files changed, 78 insertions(+), 7 deletions(-) diff --git a/mypy/stubtest.py b/mypy/stubtest.py index 546ea96dd9a0b..dacd31dbcf84c 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -25,7 +25,7 @@ from mypy import nodes from mypy.config_parser import parse_config_file from mypy.options import Options -from mypy.util import FancyFormatter, bytes_to_human_readable_repr, is_dunder, SPECIAL_DUNDERS +from mypy.util import FancyFormatter, bytes_to_human_readable_repr, is_dunder class Missing: @@ -243,6 +243,60 @@ def _belongs_to_runtime(r: types.ModuleType, attr: str) -> bool: ) +IGNORED_DUNDERS = frozenset({ + # Very special attributes + "__weakref__", + "__slots__", + "__dict__", + "__text_signature__", + # Pickle methods + "__setstate__", + "__getstate__", + "__getnewargs__", + "__getinitargs__", + "__reduce_ex__", + "__reduce__", + # typing implementation details + "__parameters__", + "__origin__", + "__args__", + "__orig_bases__", + "__final__", + # isinstance/issubclass hooks that type-checkers don't usually care about + "__instancecheck__", + "__subclasshook__", + "__subclasscheck__", + # Dataclasses implementation details + "__dataclass_fields__", + "__dataclass_params__", + # ctypes weirdness + "__ctype_be__", + "__ctype_le__", + "__ctypes_from_outparam__", + # These two are basically useless for type checkers + "__hash__", + "__getattr__", + # For some reason, mypy doesn't infer classes with metaclass=ABCMeta inherit this attribute + "__abstractmethods__", + # Ideally we'd include __match_args__ in stubs, + # but this currently has issues + "__match_args__", + "__doc__", # Can only ever be str | None, who cares? + "__del__", # Only ever called when an object is being deleted, who cares? + "__new_member__", # If an enum defines __new__, the method is renamed as __new_member__ +}) + + +if sys.version_info >= (3, 7): + _WrapperDescriptorType = types.WrapperDescriptorType +else: + _WrapperDescriptorType = type(object.__init__) + + +def is_private(name: str) -> bool: + return name.startswith("_") and not is_dunder(name) + + @verify.register(nodes.TypeInfo) def verify_typeinfo( stub: nodes.TypeInfo, runtime: MaybeMissing[Type[Any]], object_path: List[str] @@ -274,11 +328,9 @@ class SubClass(runtime): # type: ignore # Check everything already defined in the stub to_check = set(stub.names) - # There's a reasonable case to be made that we should always check all dunders, but it's - # currently quite noisy. We could turn this into a denylist instead of an allowlist. to_check.update( # cast to workaround mypyc complaints - m for m in cast(Any, vars)(runtime) if not m.startswith("_") or m in SPECIAL_DUNDERS + m for m in cast(Any, vars)(runtime) if not is_private(m) and m not in IGNORED_DUNDERS ) for entry in sorted(to_check): @@ -292,8 +344,16 @@ class SubClass(runtime): # type: ignore except Exception: # Catch all exceptions in case the runtime raises an unexpected exception # from __getattr__ or similar. - pass - else: + continue + # Do not error for an object missing from the stub + # If the runtime object is a types.WrapperDescriptorType object + # and has a non-special dunder name. + # The vast majority of these are false positives. + if not ( + isinstance(stub_to_verify, Missing) + and isinstance(runtime_attr, _WrapperDescriptorType) + and is_dunder(mangled_entry, exclude_special=True) + ): yield from verify(stub_to_verify, runtime_attr, object_path + [entry]) diff --git a/mypy/test/teststubtest.py b/mypy/test/teststubtest.py index 78ae82b058cd1..4f5659e97889b 100644 --- a/mypy/test/teststubtest.py +++ b/mypy/test/teststubtest.py @@ -65,6 +65,7 @@ def overload(func: _T) -> _T: ... VT = TypeVar('VT') class object: + __module__: str def __init__(self) -> None: pass class type: ... @@ -710,6 +711,16 @@ def h(x: str): ... yield Case( stub="from mystery import A, B as B, C as D # type: ignore", runtime="", error="B" ) + yield Case( + stub="class Y: ...", + runtime="__all__ += ['Y']\nclass Y:\n def __or__(self, other): return self|other", + error="Y.__or__" + ) + yield Case( + stub="class Z: ...", + runtime="__all__ += ['Z']\nclass Z:\n def __reduce__(self): return (Z,)", + error=None + ) @collect_cases def test_missing_no_runtime_all(self) -> Iterator[Case]: @@ -731,7 +742,7 @@ def test_non_public_2(self) -> Iterator[Case]: yield Case(stub="g: int", runtime="def g(): ...", error="g") @collect_cases - def test_special_dunders(self) -> Iterator[Case]: + def test_dunders(self) -> Iterator[Case]: yield Case( stub="class A:\n def __init__(self, a: int, b: int) -> None: ...", runtime="class A:\n def __init__(self, a, bx): pass", From f98881cbdf516484fbee30c38ace8d7acdd5ffaf Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sat, 19 Feb 2022 17:26:02 -0800 Subject: [PATCH 116/377] stubtest: ignore __main__ module (#12218) Co-authored-by: hauntsaninja <> --- mypy/stubtest.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mypy/stubtest.py b/mypy/stubtest.py index dacd31dbcf84c..4577d7265d841 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -1287,7 +1287,8 @@ def test_stubs(args: argparse.Namespace, use_builtins_fixtures: bool = False) -> if args.check_typeshed: assert not args.modules, "Cannot pass both --check-typeshed and a list of modules" modules = get_typeshed_stdlib_modules(args.custom_typeshed_dir) - annoying_modules = {"antigravity", "this"} + # typeshed added a stub for __main__, but that causes stubtest to check itself + annoying_modules = {"antigravity", "this", "__main__"} modules = [m for m in modules if m not in annoying_modules] assert modules, "No modules to check" From 58514a9cf2643da8b74bc5bce4be6d2c201b40e5 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sat, 19 Feb 2022 18:08:24 -0800 Subject: [PATCH 117/377] stubtest: error if module level dunder is missing, housekeeping (#12217) Basically a follow up to #12203 New errors in typeshed from this: ``` _decimal.__libmpdec_version__ is not present in stub _heapq.__about__ is not present in stub builtins.__build_class__ is not present in stub cgitb.__UNDEF__ is not present in stub decimal.__libmpdec_version__ is not present in stub sys.__unraisablehook__ is not present in stub ``` Some general housekeeping, moving things around, renaming things, adding some comments. --- mypy/stubtest.py | 140 ++++++++++++++++++++++++-------------- mypy/test/teststubtest.py | 10 ++- 2 files changed, 96 insertions(+), 54 deletions(-) diff --git a/mypy/stubtest.py b/mypy/stubtest.py index 4577d7265d841..0a1ffd67960c1 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -144,6 +144,11 @@ def get_description(self, concise: bool = False) -> str: return "".join(output) +# ==================== +# Core logic +# ==================== + + def test_module(module_name: str) -> Iterator[Error]: """Tests a given module's stub against introspecting it at runtime. @@ -204,7 +209,7 @@ def verify_mypyfile( to_check = set( m for m, o in stub.names.items() - if not o.module_hidden and (not m.startswith("_") or hasattr(runtime, m)) + if not o.module_hidden and (not is_probably_private(m) or hasattr(runtime, m)) ) def _belongs_to_runtime(r: types.ModuleType, attr: str) -> bool: @@ -220,7 +225,7 @@ def _belongs_to_runtime(r: types.ModuleType, attr: str) -> bool: else [ m for m in dir(runtime) - if not m.startswith("_") + if not is_probably_private(m) # Ensure that the object's module is `runtime`, since in the absence of __all__ we # don't have a good way to detect re-exports at runtime. and _belongs_to_runtime(runtime, m) @@ -228,7 +233,7 @@ def _belongs_to_runtime(r: types.ModuleType, attr: str) -> bool: ) # Check all things declared in module's __all__, falling back to our best guess to_check.update(runtime_public_contents) - to_check.difference_update({"__file__", "__doc__", "__name__", "__builtins__", "__package__"}) + to_check.difference_update(IGNORED_MODULE_DUNDERS) for entry in sorted(to_check): stub_entry = stub.names[entry].node if entry in stub.names else MISSING @@ -243,60 +248,12 @@ def _belongs_to_runtime(r: types.ModuleType, attr: str) -> bool: ) -IGNORED_DUNDERS = frozenset({ - # Very special attributes - "__weakref__", - "__slots__", - "__dict__", - "__text_signature__", - # Pickle methods - "__setstate__", - "__getstate__", - "__getnewargs__", - "__getinitargs__", - "__reduce_ex__", - "__reduce__", - # typing implementation details - "__parameters__", - "__origin__", - "__args__", - "__orig_bases__", - "__final__", - # isinstance/issubclass hooks that type-checkers don't usually care about - "__instancecheck__", - "__subclasshook__", - "__subclasscheck__", - # Dataclasses implementation details - "__dataclass_fields__", - "__dataclass_params__", - # ctypes weirdness - "__ctype_be__", - "__ctype_le__", - "__ctypes_from_outparam__", - # These two are basically useless for type checkers - "__hash__", - "__getattr__", - # For some reason, mypy doesn't infer classes with metaclass=ABCMeta inherit this attribute - "__abstractmethods__", - # Ideally we'd include __match_args__ in stubs, - # but this currently has issues - "__match_args__", - "__doc__", # Can only ever be str | None, who cares? - "__del__", # Only ever called when an object is being deleted, who cares? - "__new_member__", # If an enum defines __new__, the method is renamed as __new_member__ -}) - - if sys.version_info >= (3, 7): _WrapperDescriptorType = types.WrapperDescriptorType else: _WrapperDescriptorType = type(object.__init__) -def is_private(name: str) -> bool: - return name.startswith("_") and not is_dunder(name) - - @verify.register(nodes.TypeInfo) def verify_typeinfo( stub: nodes.TypeInfo, runtime: MaybeMissing[Type[Any]], object_path: List[str] @@ -330,7 +287,9 @@ class SubClass(runtime): # type: ignore to_check = set(stub.names) to_check.update( # cast to workaround mypyc complaints - m for m in cast(Any, vars)(runtime) if not is_private(m) and m not in IGNORED_DUNDERS + m + for m in cast(Any, vars)(runtime) + if not is_probably_private(m) and m not in ALLOW_MISSING_CLASS_DUNDERS ) for entry in sorted(to_check): @@ -1009,6 +968,78 @@ def verify_typealias( ) +# ==================== +# Helpers +# ==================== + + +IGNORED_MODULE_DUNDERS = frozenset( + { + "__file__", + "__doc__", + "__name__", + "__builtins__", + "__package__", + "__cached__", + "__loader__", + "__spec__", + "__path__", # mypy adds __path__ to packages, but C packages don't have it + "__getattr__", # resulting behaviour might be typed explicitly + # TODO: remove the following from this list + "__author__", + "__version__", + "__copyright__", + } +) + +ALLOW_MISSING_CLASS_DUNDERS = frozenset( + { + # Special attributes + "__dict__", + "__text_signature__", + "__weakref__", + "__del__", # Only ever called when an object is being deleted, who cares? + # These two are basically useless for type checkers + "__hash__", + "__getattr__", # resulting behaviour might be typed explicitly + # isinstance/issubclass hooks that type-checkers don't usually care about + "__instancecheck__", + "__subclasshook__", + "__subclasscheck__", + # Pickle methods + "__setstate__", + "__getstate__", + "__getnewargs__", + "__getinitargs__", + "__reduce_ex__", + "__reduce__", + # ctypes weirdness + "__ctype_be__", + "__ctype_le__", + "__ctypes_from_outparam__", + # mypy limitations + "__abstractmethods__", # Classes with metaclass=ABCMeta inherit this attribute + "__new_member__", # If an enum defines __new__, the method is renamed as __new_member__ + "__dataclass_fields__", # Generated by dataclasses + "__dataclass_params__", # Generated by dataclasses + "__doc__", # mypy's semanal for namedtuples assumes this is str, not Optional[str] + # typing implementation details, consider removing some of these: + "__parameters__", + "__origin__", + "__args__", + "__orig_bases__", + "__final__", + # Consider removing these: + "__match_args__", + "__slots__", + } +) + + +def is_probably_private(name: str) -> bool: + return name.startswith("_") and not is_dunder(name) + + def is_probably_a_function(runtime: Any) -> bool: return ( isinstance(runtime, (types.FunctionType, types.BuiltinFunctionType)) @@ -1151,6 +1182,11 @@ def anytype() -> mypy.types.AnyType: return mypy.types.LiteralType(value=value, fallback=fallback) +# ==================== +# Build and entrypoint +# ==================== + + _all_stubs: Dict[str, nodes.MypyFile] = {} diff --git a/mypy/test/teststubtest.py b/mypy/test/teststubtest.py index 4f5659e97889b..9cdb12afdf072 100644 --- a/mypy/test/teststubtest.py +++ b/mypy/test/teststubtest.py @@ -143,7 +143,11 @@ def test(*args: Any, **kwargs: Any) -> None: for c in cases: if c.error is None: continue - expected_error = "{}.{}".format(TEST_MODULE_NAME, c.error) + expected_error = c.error + if expected_error == "": + expected_error = TEST_MODULE_NAME + elif not expected_error.startswith(f"{TEST_MODULE_NAME}."): + expected_error = f"{TEST_MODULE_NAME}.{expected_error}" assert expected_error not in expected_errors, ( "collect_cases merges cases into a single stubtest invocation; we already " "expect an error for {}".format(expected_error) @@ -730,7 +734,9 @@ def test_missing_no_runtime_all(self) -> Iterator[Case]: @collect_cases def test_non_public_1(self) -> Iterator[Case]: - yield Case(stub="__all__: list[str]", runtime="", error=None) # dummy case + yield Case( + stub="__all__: list[str]", runtime="", error="test_module.__all__" + ) # dummy case yield Case(stub="_f: int", runtime="def _f(): ...", error="_f") @collect_cases From 608f2749b8b4c5bf361ccd657b492c343a9f9851 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sat, 19 Feb 2022 18:28:36 -0800 Subject: [PATCH 118/377] stubtest: catch more getattr errors (#12219) Fixes for https://github.com/python/typeshed/issues/7307 Amusingly, the evil runtime module that is causing havoc is... mypy, which sqlalchemy has some extension for. Co-authored-by: hauntsaninja <> --- mypy/stubtest.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/mypy/stubtest.py b/mypy/stubtest.py index 0a1ffd67960c1..e15a5503ab118 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -214,7 +214,10 @@ def verify_mypyfile( def _belongs_to_runtime(r: types.ModuleType, attr: str) -> bool: obj = getattr(r, attr) - obj_mod = getattr(obj, "__module__", None) + try: + obj_mod = getattr(obj, "__module__", None) + except Exception: + return False if obj_mod is not None: return obj_mod == r.__name__ return not isinstance(obj, types.ModuleType) @@ -241,11 +244,13 @@ def _belongs_to_runtime(r: types.ModuleType, attr: str) -> bool: # Don't recursively check exported modules, since that leads to infinite recursion continue assert stub_entry is not None - yield from verify( - stub_entry, - getattr(runtime, entry, MISSING), - object_path + [entry], - ) + try: + runtime_entry = getattr(runtime, entry, MISSING) + except Exception: + # Catch all exceptions in case the runtime raises an unexpected exception + # from __getattr__ or similar. + continue + yield from verify(stub_entry, runtime_entry, object_path + [entry]) if sys.version_info >= (3, 7): From a72689265348a00216b90de966cd5a54f1d97093 Mon Sep 17 00:00:00 2001 From: 97littleleaf11 <11172084+97littleleaf11@users.noreply.github.com> Date: Sun, 20 Feb 2022 12:54:43 +0800 Subject: [PATCH 119/377] [mypyc] Refactor: Use WrapperGenerator for generate_wrapper_core (#12209) The WrapperGenerator is an abstract class for wrapper generation, originally from generate_wrapper_core. The latter one is fully covered by the WrapperGenerator. --- mypyc/codegen/emitwrapper.py | 65 +++++++++--------------------------- 1 file changed, 16 insertions(+), 49 deletions(-) diff --git a/mypyc/codegen/emitwrapper.py b/mypyc/codegen/emitwrapper.py index bbee8fea0d919..dd08bdb40bf3c 100644 --- a/mypyc/codegen/emitwrapper.py +++ b/mypyc/codegen/emitwrapper.py @@ -286,21 +286,20 @@ def generate_bin_op_wrapper(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> str: gen.emit_header() if fn.name not in reverse_op_methods and fn.name in reverse_op_method_names: # There's only a reverse operator method. - generate_bin_op_reverse_only_wrapper(cl, fn, emitter, gen) + generate_bin_op_reverse_only_wrapper(emitter, gen) else: rmethod = reverse_op_methods[fn.name] fn_rev = cl.get_method(rmethod) if fn_rev is None: # There's only a forward operator method. - generate_bin_op_forward_only_wrapper(cl, fn, emitter, gen) + generate_bin_op_forward_only_wrapper(fn, emitter, gen) else: # There's both a forward and a reverse operator method. generate_bin_op_both_wrappers(cl, fn, fn_rev, emitter, gen) return wrapper_name -def generate_bin_op_forward_only_wrapper(cl: ClassIR, - fn: FuncIR, +def generate_bin_op_forward_only_wrapper(fn: FuncIR, emitter: Emitter, gen: 'WrapperGenerator') -> None: gen.emit_arg_processing(error=GotoHandler('typefail'), raise_exception=False) @@ -331,9 +330,7 @@ def generate_bin_op_forward_only_wrapper(cl: ClassIR, gen.finish() -def generate_bin_op_reverse_only_wrapper(cl: ClassIR, - fn_rev: FuncIR, - emitter: Emitter, +def generate_bin_op_reverse_only_wrapper(emitter: Emitter, gen: 'WrapperGenerator') -> None: gen.arg_names = ['right', 'left'] gen.emit_arg_processing(error=GotoHandler('typefail'), raise_exception=False) @@ -650,47 +647,17 @@ def generate_wrapper_core(fn: FuncIR, It converts the PyObject *s to the necessary types, checking and unboxing if necessary, makes the call, then boxes the result if necessary and returns it. """ + gen = WrapperGenerator(None, emitter) + gen.set_target(fn) + gen.arg_names = arg_names or [arg.name for arg in fn.args] + gen.cleanups = cleanups or [] + gen.optional_args = optional_args or [] + gen.traceback_code = traceback_code or '' - optional_args = optional_args or [] - cleanups = cleanups or [] - use_goto = bool(cleanups or traceback_code) - error = ReturnHandler('NULL') if not use_goto else GotoHandler('fail') - - arg_names = arg_names or [arg.name for arg in fn.args] - for arg_name, arg in zip(arg_names, fn.args): - # Suppress the argument check for *args/**kwargs, since we know it must be right. - typ = arg.type if arg.kind not in (ARG_STAR, ARG_STAR2) else object_rprimitive - generate_arg_check(arg_name, - typ, - emitter, - error, - optional=arg in optional_args) - native_args = ', '.join('arg_{}'.format(arg) for arg in arg_names) - if fn.ret_type.is_unboxed or use_goto: - # TODO: The Py_RETURN macros return the correct PyObject * with reference count handling. - # Are they relevant? - emitter.emit_line('{}retval = {}{}({});'.format(emitter.ctype_spaced(fn.ret_type), - NATIVE_PREFIX, - fn.cname(emitter.names), - native_args)) - emitter.emit_lines(*cleanups) - if fn.ret_type.is_unboxed: - emitter.emit_error_check('retval', fn.ret_type, 'return NULL;') - emitter.emit_box('retval', 'retbox', fn.ret_type, declare_dest=True) - - emitter.emit_line('return {};'.format('retbox' if fn.ret_type.is_unboxed else 'retval')) - else: - emitter.emit_line('return {}{}({});'.format(NATIVE_PREFIX, - fn.cname(emitter.names), - native_args)) - # TODO: Tracebacks? - - if use_goto: - emitter.emit_label('fail') - emitter.emit_lines(*cleanups) - if traceback_code: - emitter.emit_lines(traceback_code) - emitter.emit_lines('return NULL;') + error = ReturnHandler('NULL') if not gen.use_goto() else GotoHandler('fail') + gen.emit_arg_processing(error=error) + gen.emit_call() + gen.emit_error_handling() def generate_arg_check(name: str, @@ -741,7 +708,7 @@ class WrapperGenerator: # TODO: Use this for more wrappers - def __init__(self, cl: ClassIR, emitter: Emitter) -> None: + def __init__(self, cl: Optional[ClassIR], emitter: Emitter) -> None: self.cl = cl self.emitter = emitter self.cleanups: List[str] = [] @@ -764,7 +731,7 @@ def wrapper_name(self) -> str: """Return the name of the wrapper function.""" return '{}{}{}'.format(DUNDER_PREFIX, self.target_name, - self.cl.name_prefix(self.emitter.names)) + self.cl.name_prefix(self.emitter.names) if self.cl else '') def use_goto(self) -> bool: """Do we use a goto for error handling (instead of straight return)?""" From 68b208d0a8a7e24bfa2c7ed816625381ce9e6fde Mon Sep 17 00:00:00 2001 From: Marti Raudsepp Date: Sun, 20 Feb 2022 09:04:47 +0200 Subject: [PATCH 120/377] Coalesce Literals when printing Unions (#12205) Instead of printing `Union[Literal[X], Literal[Y]]`, these are now printed as `Literal[X, Y]`. --- mypy/messages.py | 67 ++++++++++++++++----------- mypy/typeops.py | 15 ++++++ test-data/unit/check-enum.test | 6 +-- test-data/unit/check-expressions.test | 4 +- test-data/unit/check-isinstance.test | 4 +- test-data/unit/check-literal.test | 52 ++++++++++----------- test-data/unit/check-narrowing.test | 2 +- 7 files changed, 89 insertions(+), 61 deletions(-) diff --git a/mypy/messages.py b/mypy/messages.py index 406237783cf14..96cb2f3ae3714 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -39,6 +39,7 @@ IS_SETTABLE, IS_CLASSVAR, IS_CLASS_OR_STATIC, ) from mypy.sametypes import is_same_type +from mypy.typeops import separate_union_literals from mypy.util import unmangle from mypy.errorcodes import ErrorCode from mypy import message_registry, errorcodes as codes @@ -1664,6 +1665,16 @@ def format_type_inner(typ: Type, def format(typ: Type) -> str: return format_type_inner(typ, verbosity, fullnames) + def format_list(types: Sequence[Type]) -> str: + return ', '.join(format(typ) for typ in types) + + def format_literal_value(typ: LiteralType) -> str: + if typ.is_enum_literal(): + underlying_type = format(typ.fallback) + return '{}.{}'.format(underlying_type, typ.value) + else: + return typ.value_repr() + # TODO: show type alias names in errors. typ = get_proper_type(typ) @@ -1686,15 +1697,10 @@ def format(typ: Type) -> str: elif itype.type.fullname in reverse_builtin_aliases: alias = reverse_builtin_aliases[itype.type.fullname] alias = alias.split('.')[-1] - items = [format(arg) for arg in itype.args] - return '{}[{}]'.format(alias, ', '.join(items)) + return '{}[{}]'.format(alias, format_list(itype.args)) else: # There are type arguments. Convert the arguments to strings. - a: List[str] = [] - for arg in itype.args: - a.append(format(arg)) - s = ', '.join(a) - return '{}[{}]'.format(base_str, s) + return '{}[{}]'.format(base_str, format_list(itype.args)) elif isinstance(typ, TypeVarType): # This is similar to non-generic instance types. return typ.name @@ -1704,10 +1710,7 @@ def format(typ: Type) -> str: # Prefer the name of the fallback class (if not tuple), as it's more informative. if typ.partial_fallback.type.fullname != 'builtins.tuple': return format(typ.partial_fallback) - items = [] - for t in typ.items: - items.append(format(t)) - s = 'Tuple[{}]'.format(', '.join(items)) + s = 'Tuple[{}]'.format(format_list(typ.items)) return s elif isinstance(typ, TypedDictType): # If the TypedDictType is named, return the name @@ -1722,24 +1725,34 @@ def format(typ: Type) -> str: s = 'TypedDict({{{}}})'.format(', '.join(items)) return s elif isinstance(typ, LiteralType): - if typ.is_enum_literal(): - underlying_type = format(typ.fallback) - return 'Literal[{}.{}]'.format(underlying_type, typ.value) - else: - return str(typ) + return 'Literal[{}]'.format(format_literal_value(typ)) elif isinstance(typ, UnionType): - # Only print Unions as Optionals if the Optional wouldn't have to contain another Union - print_as_optional = (len(typ.items) - - sum(isinstance(get_proper_type(t), NoneType) - for t in typ.items) == 1) - if print_as_optional: - rest = [t for t in typ.items if not isinstance(get_proper_type(t), NoneType)] - return 'Optional[{}]'.format(format(rest[0])) + literal_items, union_items = separate_union_literals(typ) + + # Coalesce multiple Literal[] members. This also changes output order. + # If there's just one Literal item, retain the original ordering. + if len(literal_items) > 1: + literal_str = 'Literal[{}]'.format( + ', '.join(format_literal_value(t) for t in literal_items) + ) + + if len(union_items) == 1 and isinstance(get_proper_type(union_items[0]), NoneType): + return 'Optional[{}]'.format(literal_str) + elif union_items: + return 'Union[{}, {}]'.format(format_list(union_items), literal_str) + else: + return literal_str else: - items = [] - for t in typ.items: - items.append(format(t)) - s = 'Union[{}]'.format(', '.join(items)) + # Only print Union as Optional if the Optional wouldn't have to contain another Union + print_as_optional = (len(typ.items) - + sum(isinstance(get_proper_type(t), NoneType) + for t in typ.items) == 1) + if print_as_optional: + rest = [t for t in typ.items if not isinstance(get_proper_type(t), NoneType)] + return 'Optional[{}]'.format(format(rest[0])) + else: + s = 'Union[{}]'.format(format_list(typ.items)) + return s elif isinstance(typ, NoneType): return 'None' diff --git a/mypy/typeops.py b/mypy/typeops.py index 22812a699ae41..57fdfeadad9a1 100644 --- a/mypy/typeops.py +++ b/mypy/typeops.py @@ -846,3 +846,18 @@ def is_redundant_literal_instance(general: ProperType, specific: ProperType) -> return True return False + + +def separate_union_literals(t: UnionType) -> Tuple[Sequence[LiteralType], Sequence[Type]]: + """Separate literals from other members in a union type.""" + literal_items = [] + union_items = [] + + for item in t.items: + proper = get_proper_type(item) + if isinstance(proper, LiteralType): + literal_items.append(proper) + else: + union_items.append(item) + + return literal_items, union_items diff --git a/test-data/unit/check-enum.test b/test-data/unit/check-enum.test index a6eb6374da374..572c8f3929e1f 100644 --- a/test-data/unit/check-enum.test +++ b/test-data/unit/check-enum.test @@ -1405,9 +1405,9 @@ class E(Enum): e: E a: Literal[E.A, E.B, E.C] = e -b: Literal[E.A, E.B] = e # E: Incompatible types in assignment (expression has type "E", variable has type "Union[Literal[E.A], Literal[E.B]]") -c: Literal[E.A, E.C] = e # E: Incompatible types in assignment (expression has type "E", variable has type "Union[Literal[E.A], Literal[E.C]]") -b = a # E: Incompatible types in assignment (expression has type "Union[Literal[E.A], Literal[E.B], Literal[E.C]]", variable has type "Union[Literal[E.A], Literal[E.B]]") +b: Literal[E.A, E.B] = e # E: Incompatible types in assignment (expression has type "E", variable has type "Literal[E.A, E.B]") +c: Literal[E.A, E.C] = e # E: Incompatible types in assignment (expression has type "E", variable has type "Literal[E.A, E.C]") +b = a # E: Incompatible types in assignment (expression has type "Literal[E.A, E.B, E.C]", variable has type "Literal[E.A, E.B]") [builtins fixtures/bool.pyi] [case testIntEnumWithNewTypeValue] diff --git a/test-data/unit/check-expressions.test b/test-data/unit/check-expressions.test index 543502e651154..6c6a5d473f011 100644 --- a/test-data/unit/check-expressions.test +++ b/test-data/unit/check-expressions.test @@ -2153,9 +2153,9 @@ def returns_1_or_2() -> Literal[1, 2]: ... THREE: Final = 3 -if returns_a_or_b() == 'c': # E: Non-overlapping equality check (left operand type: "Union[Literal['a'], Literal['b']]", right operand type: "Literal['c']") +if returns_a_or_b() == 'c': # E: Non-overlapping equality check (left operand type: "Literal['a', 'b']", right operand type: "Literal['c']") ... -if returns_1_or_2() is THREE: # E: Non-overlapping identity check (left operand type: "Union[Literal[1], Literal[2]]", right operand type: "Literal[3]") +if returns_1_or_2() is THREE: # E: Non-overlapping identity check (left operand type: "Literal[1, 2]", right operand type: "Literal[3]") ... [builtins fixtures/bool.pyi] diff --git a/test-data/unit/check-isinstance.test b/test-data/unit/check-isinstance.test index f531947d1faf9..64c1a2aad3cbf 100644 --- a/test-data/unit/check-isinstance.test +++ b/test-data/unit/check-isinstance.test @@ -2390,8 +2390,8 @@ class B: def t3(self) -> None: if isinstance(self, (A1, A2)): reveal_type(self) # N: Revealed type is "Union[__main__.2, __main__.]" - x0: Literal[0] = self.f() # E: Incompatible types in assignment (expression has type "Union[Literal[1], Literal[2]]", variable has type "Literal[0]") - x1: Literal[1] = self.f() # E: Incompatible types in assignment (expression has type "Union[Literal[1], Literal[2]]", variable has type "Literal[1]") + x0: Literal[0] = self.f() # E: Incompatible types in assignment (expression has type "Literal[1, 2]", variable has type "Literal[0]") + x1: Literal[1] = self.f() # E: Incompatible types in assignment (expression has type "Literal[1, 2]", variable has type "Literal[1]") [builtins fixtures/isinstance.pyi] diff --git a/test-data/unit/check-literal.test b/test-data/unit/check-literal.test index 37ae12419151f..3886d3c39eddc 100644 --- a/test-data/unit/check-literal.test +++ b/test-data/unit/check-literal.test @@ -846,7 +846,7 @@ def func(x: Literal['foo', 'bar', ' foo ']) -> None: ... func('foo') func('bar') func(' foo ') -func('baz') # E: Argument 1 to "func" has incompatible type "Literal['baz']"; expected "Union[Literal['foo'], Literal['bar'], Literal[' foo ']]" +func('baz') # E: Argument 1 to "func" has incompatible type "Literal['baz']"; expected "Literal['foo', 'bar', ' foo ']" a: Literal['foo'] b: Literal['bar'] @@ -860,7 +860,7 @@ func(b) func(c) func(d) func(e) -func(f) # E: Argument 1 to "func" has incompatible type "Union[Literal['foo'], Literal['bar'], Literal['baz']]"; expected "Union[Literal['foo'], Literal['bar'], Literal[' foo ']]" +func(f) # E: Argument 1 to "func" has incompatible type "Literal['foo', 'bar', 'baz']"; expected "Literal['foo', 'bar', ' foo ']" [builtins fixtures/tuple.pyi] [out] @@ -1129,8 +1129,8 @@ d: int foo(a) foo(b) -foo(c) # E: Argument 1 to "foo" has incompatible type "Union[Literal[4], Literal[5]]"; expected "Union[Literal[1], Literal[2], Literal[3]]" -foo(d) # E: Argument 1 to "foo" has incompatible type "int"; expected "Union[Literal[1], Literal[2], Literal[3]]" +foo(c) # E: Argument 1 to "foo" has incompatible type "Literal[4, 5]"; expected "Literal[1, 2, 3]" +foo(d) # E: Argument 1 to "foo" has incompatible type "int"; expected "Literal[1, 2, 3]" [builtins fixtures/tuple.pyi] [out] @@ -1144,7 +1144,7 @@ c: Literal[4, 'foo'] foo(a) foo(b) -foo(c) # E: Argument 1 to "foo" has incompatible type "Union[Literal[4], Literal['foo']]"; expected "int" +foo(c) # E: Argument 1 to "foo" has incompatible type "Literal[4, 'foo']"; expected "int" [builtins fixtures/tuple.pyi] [out] @@ -1248,19 +1248,19 @@ class Contravariant(Generic[T_contra]): pass a1: Invariant[Literal[1]] a2: Invariant[Literal[1, 2]] a3: Invariant[Literal[1, 2, 3]] -a2 = a1 # E: Incompatible types in assignment (expression has type "Invariant[Literal[1]]", variable has type "Invariant[Union[Literal[1], Literal[2]]]") -a2 = a3 # E: Incompatible types in assignment (expression has type "Invariant[Union[Literal[1], Literal[2], Literal[3]]]", variable has type "Invariant[Union[Literal[1], Literal[2]]]") +a2 = a1 # E: Incompatible types in assignment (expression has type "Invariant[Literal[1]]", variable has type "Invariant[Literal[1, 2]]") +a2 = a3 # E: Incompatible types in assignment (expression has type "Invariant[Literal[1, 2, 3]]", variable has type "Invariant[Literal[1, 2]]") b1: Covariant[Literal[1]] b2: Covariant[Literal[1, 2]] b3: Covariant[Literal[1, 2, 3]] b2 = b1 -b2 = b3 # E: Incompatible types in assignment (expression has type "Covariant[Union[Literal[1], Literal[2], Literal[3]]]", variable has type "Covariant[Union[Literal[1], Literal[2]]]") +b2 = b3 # E: Incompatible types in assignment (expression has type "Covariant[Literal[1, 2, 3]]", variable has type "Covariant[Literal[1, 2]]") c1: Contravariant[Literal[1]] c2: Contravariant[Literal[1, 2]] c3: Contravariant[Literal[1, 2, 3]] -c2 = c1 # E: Incompatible types in assignment (expression has type "Contravariant[Literal[1]]", variable has type "Contravariant[Union[Literal[1], Literal[2]]]") +c2 = c1 # E: Incompatible types in assignment (expression has type "Contravariant[Literal[1]]", variable has type "Contravariant[Literal[1, 2]]") c2 = c3 [builtins fixtures/tuple.pyi] [out] @@ -1275,12 +1275,12 @@ def bar(x: Sequence[Literal[1, 2]]) -> None: pass a: List[Literal[1]] b: List[Literal[1, 2, 3]] -foo(a) # E: Argument 1 to "foo" has incompatible type "List[Literal[1]]"; expected "List[Union[Literal[1], Literal[2]]]" \ +foo(a) # E: Argument 1 to "foo" has incompatible type "List[Literal[1]]"; expected "List[Literal[1, 2]]" \ # N: "List" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance \ # N: Consider using "Sequence" instead, which is covariant -foo(b) # E: Argument 1 to "foo" has incompatible type "List[Union[Literal[1], Literal[2], Literal[3]]]"; expected "List[Union[Literal[1], Literal[2]]]" +foo(b) # E: Argument 1 to "foo" has incompatible type "List[Literal[1, 2, 3]]"; expected "List[Literal[1, 2]]" bar(a) -bar(b) # E: Argument 1 to "bar" has incompatible type "List[Union[Literal[1], Literal[2], Literal[3]]]"; expected "Sequence[Union[Literal[1], Literal[2]]]" +bar(b) # E: Argument 1 to "bar" has incompatible type "List[Literal[1, 2, 3]]"; expected "Sequence[Literal[1, 2]]" [builtins fixtures/list.pyi] [out] @@ -1363,9 +1363,9 @@ x = b # E: Incompatible types in assignment (expression has type "str", variabl y = c # E: Incompatible types in assignment (expression has type "bool", variable has type "Literal[True]") z = d # This is ok: Literal[None] and None are equivalent. -combined = a # E: Incompatible types in assignment (expression has type "int", variable has type "Union[Literal[1], Literal['foo'], Literal[True], None]") -combined = b # E: Incompatible types in assignment (expression has type "str", variable has type "Union[Literal[1], Literal['foo'], Literal[True], None]") -combined = c # E: Incompatible types in assignment (expression has type "bool", variable has type "Union[Literal[1], Literal['foo'], Literal[True], None]") +combined = a # E: Incompatible types in assignment (expression has type "int", variable has type "Optional[Literal[1, 'foo', True]]") +combined = b # E: Incompatible types in assignment (expression has type "str", variable has type "Optional[Literal[1, 'foo', True]]") +combined = c # E: Incompatible types in assignment (expression has type "bool", variable has type "Optional[Literal[1, 'foo', True]]") combined = d # Also ok, for similar reasons. e: Literal[1] = 1 @@ -1392,9 +1392,9 @@ a: Literal[1] = 2 # E: Incompatible types in assignment (expression ha b: Literal["foo"] = "bar" # E: Incompatible types in assignment (expression has type "Literal['bar']", variable has type "Literal['foo']") c: Literal[True] = False # E: Incompatible types in assignment (expression has type "Literal[False]", variable has type "Literal[True]") -d: Literal[1, 2] = 3 # E: Incompatible types in assignment (expression has type "Literal[3]", variable has type "Union[Literal[1], Literal[2]]") -e: Literal["foo", "bar"] = "baz" # E: Incompatible types in assignment (expression has type "Literal['baz']", variable has type "Union[Literal['foo'], Literal['bar']]") -f: Literal[True, 4] = False # E: Incompatible types in assignment (expression has type "Literal[False]", variable has type "Union[Literal[True], Literal[4]]") +d: Literal[1, 2] = 3 # E: Incompatible types in assignment (expression has type "Literal[3]", variable has type "Literal[1, 2]") +e: Literal["foo", "bar"] = "baz" # E: Incompatible types in assignment (expression has type "Literal['baz']", variable has type "Literal['foo', 'bar']") +f: Literal[True, 4] = False # E: Incompatible types in assignment (expression has type "Literal[False]", variable has type "Literal[True, 4]") [builtins fixtures/primitives.pyi] [out] @@ -1504,7 +1504,7 @@ reveal_type(arr3) # N: Revealed type is "builtins.list[builtins.int*]" reveal_type(arr4) # N: Revealed type is "builtins.list[builtins.object*]" reveal_type(arr5) # N: Revealed type is "builtins.list[builtins.object*]" -bad: List[Literal[1, 2]] = [1, 2, 3] # E: List item 2 has incompatible type "Literal[3]"; expected "Union[Literal[1], Literal[2]]" +bad: List[Literal[1, 2]] = [1, 2, 3] # E: List item 2 has incompatible type "Literal[3]"; expected "Literal[1, 2]" [builtins fixtures/list.pyi] [out] @@ -1619,19 +1619,19 @@ reveal_type(func(a)) # N: Revealed type is "Union[__main__.A, __main__.C]" reveal_type(func(b)) # N: Revealed type is "__main__.B" reveal_type(func(c)) # N: Revealed type is "Union[__main__.B, __main__.A]" reveal_type(func(d)) # N: Revealed type is "__main__.B" \ - # E: Argument 1 to "func" has incompatible type "Union[Literal[6], Literal[7]]"; expected "Union[Literal[3], Literal[4], Literal[5], Literal[6]]" + # E: Argument 1 to "func" has incompatible type "Literal[6, 7]"; expected "Literal[3, 4, 5, 6]" reveal_type(func(e)) # E: No overload variant of "func" matches argument type "int" \ # N: Possible overload variants: \ # N: def func(x: Literal[-40]) -> A \ - # N: def func(x: Union[Literal[3], Literal[4], Literal[5], Literal[6]]) -> B \ + # N: def func(x: Literal[3, 4, 5, 6]) -> B \ # N: def func(x: Literal['foo']) -> C \ # N: Revealed type is "Any" -reveal_type(func(f)) # E: No overload variant of "func" matches argument type "Union[Literal[7], Literal['bar']]" \ +reveal_type(func(f)) # E: No overload variant of "func" matches argument type "Literal[7, 'bar']" \ # N: Possible overload variants: \ # N: def func(x: Literal[-40]) -> A \ - # N: def func(x: Union[Literal[3], Literal[4], Literal[5], Literal[6]]) -> B \ + # N: def func(x: Literal[3, 4, 5, 6]) -> B \ # N: def func(x: Literal['foo']) -> C \ # N: Revealed type is "Any" [builtins fixtures/tuple.pyi] @@ -1657,7 +1657,7 @@ reveal_type(f(1)) # N: Revealed type is "builtins.int" reveal_type(f(2)) # N: Revealed type is "builtins.int" reveal_type(f(y)) # N: Revealed type is "builtins.object" reveal_type(f(z)) # N: Revealed type is "builtins.int" \ - # E: Argument 1 to "f" has incompatible type "Union[Literal[1], Literal[2], Literal['three']]"; expected "Union[Literal[1], Literal[2]]" + # E: Argument 1 to "f" has incompatible type "Literal[1, 2, 'three']"; expected "Literal[1, 2]" [builtins fixtures/tuple.pyi] [out] @@ -1726,8 +1726,8 @@ def f(x): x: Literal['a', 'b'] y: Literal['a', 'b'] -f(x, y) # E: Argument 1 to "f" has incompatible type "Union[Literal['a'], Literal['b']]"; expected "Literal['a']" \ - # E: Argument 2 to "f" has incompatible type "Union[Literal['a'], Literal['b']]"; expected "Literal['a']" \ +f(x, y) # E: Argument 1 to "f" has incompatible type "Literal['a', 'b']"; expected "Literal['a']" \ + # E: Argument 2 to "f" has incompatible type "Literal['a', 'b']"; expected "Literal['a']" \ [builtins fixtures/tuple.pyi] [out] diff --git a/test-data/unit/check-narrowing.test b/test-data/unit/check-narrowing.test index 16cdc69ec1b7a..23715b24d43e2 100644 --- a/test-data/unit/check-narrowing.test +++ b/test-data/unit/check-narrowing.test @@ -894,7 +894,7 @@ else: reveal_type(y) # N: Revealed type is "__main__.Custom" # No contamination here -if 1 == x == z: # E: Non-overlapping equality check (left operand type: "Union[Literal[1], Literal[2], None]", right operand type: "Default") +if 1 == x == z: # E: Non-overlapping equality check (left operand type: "Optional[Literal[1, 2]]", right operand type: "Default") reveal_type(x) # E: Statement is unreachable reveal_type(z) else: From 66982637944451401a88edc95be1fed6f3a87baa Mon Sep 17 00:00:00 2001 From: 97littleleaf11 <11172084+97littleleaf11@users.noreply.github.com> Date: Sun, 20 Feb 2022 23:54:53 +0800 Subject: [PATCH 121/377] Update dev-intro.md Add a link to Python doc about Python C API, which is a friendly tutorial for beginners. --- mypyc/doc/dev-intro.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypyc/doc/dev-intro.md b/mypyc/doc/dev-intro.md index bf0c1a8368743..d11df7068e91c 100644 --- a/mypyc/doc/dev-intro.md +++ b/mypyc/doc/dev-intro.md @@ -149,7 +149,7 @@ know for mypyc contributors: ([The C Programming Language](https://en.wikipedia.org/wiki/The_C_Programming_Language) is a classic book about C) * Basic familiarity with the Python C API (see - [Python C API documentation](https://docs.python.org/3/c-api/intro.html)) + [Python C API documentation](https://docs.python.org/3/c-api/intro.html)). [Extending and Embedding the Python Interpreter](https://docs.python.org/3/extending/index.html) is a good tutorial for beginners. * Basics of compilers (see the [mypy wiki](https://github.com/python/mypy/wiki/Learning-Resources) for some ideas) From b22c4e4a2e9f56480724a45e159552c922af47dc Mon Sep 17 00:00:00 2001 From: Bas van Beek <43369155+BvB93@users.noreply.github.com> Date: Sun, 20 Feb 2022 22:18:03 +0100 Subject: [PATCH 122/377] BUG: Fix an `issubclass` failure for protocols with overloaded methods (#9904) Co-authored-by: Shantanu <12621235+hauntsaninja@users.noreply.github.com> --- mypy/subtypes.py | 2 +- test-data/unit/check-protocols.test | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/mypy/subtypes.py b/mypy/subtypes.py index 51a9dfbb8bc1e..a261e3712328b 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -763,7 +763,7 @@ def non_method_protocol_members(tp: TypeInfo) -> List[str]: for member in tp.protocol_members: typ = get_proper_type(find_member(member, instance, instance)) - if not isinstance(typ, CallableType): + if not isinstance(typ, (Overloaded, CallableType)): result.append(member) return result diff --git a/test-data/unit/check-protocols.test b/test-data/unit/check-protocols.test index 6768263e9832e..a5962bde5333e 100644 --- a/test-data/unit/check-protocols.test +++ b/test-data/unit/check-protocols.test @@ -2382,7 +2382,7 @@ y: PBad = None # E: Incompatible types in assignment (expression has type "None [out] [case testOnlyMethodProtocolUsableWithIsSubclass] -from typing import Protocol, runtime_checkable, Union, Type +from typing import Protocol, runtime_checkable, Union, Type, Sequence, overload @runtime_checkable class P(Protocol): def meth(self) -> int: @@ -2404,6 +2404,17 @@ if issubclass(cls, P): reveal_type(cls) # N: Revealed type is "Type[__main__.C]" else: reveal_type(cls) # N: Revealed type is "Type[__main__.E]" + +@runtime_checkable +class POverload(Protocol): + @overload + def meth(self, a: int) -> float: ... + @overload + def meth(self, a: str) -> Sequence[float]: ... + def meth(self, a): + pass + +reveal_type(issubclass(int, POverload)) # N: Revealed type is "builtins.bool" [builtins fixtures/isinstance.pyi] [typing fixtures/typing-full.pyi] [out] From 2d30dbaa34eab9d7519e440480f360fc9a1e65c3 Mon Sep 17 00:00:00 2001 From: 97littleleaf11 <11172084+97littleleaf11@users.noreply.github.com> Date: Tue, 22 Feb 2022 01:12:36 +0800 Subject: [PATCH 123/377] Fix one invalid reference inside visit_class_pattern (#12229) --- mypy/checkpattern.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/checkpattern.py b/mypy/checkpattern.py index 2c40e856be885..fbbb4c319ccb6 100644 --- a/mypy/checkpattern.py +++ b/mypy/checkpattern.py @@ -567,7 +567,7 @@ def visit_class_pattern(self, o: ClassPattern) -> PatternType: if local_errors.is_errors() or key_type is None: key_type = AnyType(TypeOfAny.from_error) self.msg.fail(message_registry.CLASS_PATTERN_UNKNOWN_KEYWORD.format(typ, keyword), - value) + pattern) inner_type, inner_rest_type, inner_captures = self.accept(pattern, key_type) if is_uninhabited(inner_type): From 2c9a8e731785fac1d1ef342863b70854de16423a Mon Sep 17 00:00:00 2001 From: 97littleleaf11 <11172084+97littleleaf11@users.noreply.github.com> Date: Tue, 22 Feb 2022 13:40:22 +0800 Subject: [PATCH 124/377] Sync pythoncapi_compat (#12188) --- mypyc/lib-rt/pythoncapi_compat.h | 138 +++++++++++++++++-------------- 1 file changed, 76 insertions(+), 62 deletions(-) diff --git a/mypyc/lib-rt/pythoncapi_compat.h b/mypyc/lib-rt/pythoncapi_compat.h index b4011d20a19a2..c9191a1d7a579 100644 --- a/mypyc/lib-rt/pythoncapi_compat.h +++ b/mypyc/lib-rt/pythoncapi_compat.h @@ -1,7 +1,6 @@ -// Header file providing new functions of the Python C API to old Python -// versions. +// Header file providing new C API functions to old Python versions. // -// File distributed under the MIT license. +// File distributed under the Zero Clause BSD (0BSD) license. // Copyright Contributors to the pythoncapi_compat project. // // Homepage: @@ -10,7 +9,7 @@ // Latest version: // https://raw.githubusercontent.com/pythoncapi/pythoncapi_compat/master/pythoncapi_compat.h // -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: 0BSD #ifndef PYTHONCAPI_COMPAT #define PYTHONCAPI_COMPAT @@ -27,24 +26,34 @@ extern "C" { // the inline keyword in C (only in C++): use __inline instead. #if (defined(_MSC_VER) && _MSC_VER < 1900 \ && !defined(__cplusplus) && !defined(inline)) -# define inline __inline -# define PYTHONCAPI_COMPAT_MSC_INLINE - // These two macros are undefined at the end of this file +# define PYCAPI_COMPAT_INLINE(TYPE static __inline TYPE +#else +# define PYCAPI_COMPAT_STATIC_INLINE(TYPE) static inline TYPE #endif +// C++ compatibility +#ifdef __cplusplus +# define PYCAPI_COMPAT_CAST(TYPE, EXPR) reinterpret_cast(EXPR) +# define PYCAPI_COMPAT_NULL nullptr +#else +# define PYCAPI_COMPAT_CAST(TYPE, EXPR) (TYPE)(EXPR) +# define PYCAPI_COMPAT_NULL NULL +#endif + // Cast argument to PyObject* type. #ifndef _PyObject_CAST -# define _PyObject_CAST(op) ((PyObject*)(op)) +# define _PyObject_CAST(op) PYCAPI_COMPAT_CAST(PyObject*, op) #endif #ifndef _PyObject_CAST_CONST -# define _PyObject_CAST_CONST(op) ((const PyObject*)(op)) +# define _PyObject_CAST_CONST(op) PYCAPI_COMPAT_CAST(const PyObject*, op) #endif // bpo-42262 added Py_NewRef() to Python 3.10.0a3 #if PY_VERSION_HEX < 0x030A00A3 && !defined(Py_NewRef) -static inline PyObject* _Py_NewRef(PyObject *obj) +PYCAPI_COMPAT_STATIC_INLINE(PyObject*) +_Py_NewRef(PyObject *obj) { Py_INCREF(obj); return obj; @@ -55,7 +64,8 @@ static inline PyObject* _Py_NewRef(PyObject *obj) // bpo-42262 added Py_XNewRef() to Python 3.10.0a3 #if PY_VERSION_HEX < 0x030A00A3 && !defined(Py_XNewRef) -static inline PyObject* _Py_XNewRef(PyObject *obj) +PYCAPI_COMPAT_STATIC_INLINE(PyObject*) +_Py_XNewRef(PyObject *obj) { Py_XINCREF(obj); return obj; @@ -66,7 +76,8 @@ static inline PyObject* _Py_XNewRef(PyObject *obj) // See https://bugs.python.org/issue42522 #if !defined(_Py_StealRef) -static inline PyObject* __Py_StealRef(PyObject *obj) +PYCAPI_COMPAT_STATIC_INLINE(PyObject*) +__Py_StealRef(PyObject *obj) { Py_DECREF(obj); return obj; @@ -77,7 +88,8 @@ static inline PyObject* __Py_StealRef(PyObject *obj) // See https://bugs.python.org/issue42522 #if !defined(_Py_XStealRef) -static inline PyObject* __Py_XStealRef(PyObject *obj) +PYCAPI_COMPAT_STATIC_INLINE(PyObject*) +__Py_XStealRef(PyObject *obj) { Py_XDECREF(obj); return obj; @@ -88,7 +100,8 @@ static inline PyObject* __Py_XStealRef(PyObject *obj) // bpo-39573 added Py_SET_REFCNT() to Python 3.9.0a4 #if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_REFCNT) -static inline void _Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) +PYCAPI_COMPAT_STATIC_INLINE(void) +_Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) { ob->ob_refcnt = refcnt; } @@ -133,7 +146,7 @@ static inline void _Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) // bpo-39573 added Py_SET_TYPE() to Python 3.9.0a4 #if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_TYPE) -static inline void +PYCAPI_COMPAT_STATIC_INLINE(void) _Py_SET_TYPE(PyObject *ob, PyTypeObject *type) { ob->ob_type = type; @@ -144,7 +157,7 @@ _Py_SET_TYPE(PyObject *ob, PyTypeObject *type) // bpo-39573 added Py_SET_SIZE() to Python 3.9.0a4 #if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_SIZE) -static inline void +PYCAPI_COMPAT_STATIC_INLINE(void) _Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size) { ob->ob_size = size; @@ -155,47 +168,49 @@ _Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size) // bpo-40421 added PyFrame_GetCode() to Python 3.9.0b1 #if PY_VERSION_HEX < 0x030900B1 -static inline PyCodeObject* +PYCAPI_COMPAT_STATIC_INLINE(PyCodeObject*) PyFrame_GetCode(PyFrameObject *frame) { - assert(frame != NULL); - assert(frame->f_code != NULL); - return (PyCodeObject*)Py_NewRef(frame->f_code); + assert(frame != PYCAPI_COMPAT_NULL); + assert(frame->f_code != PYCAPI_COMPAT_NULL); + return PYCAPI_COMPAT_CAST(PyCodeObject*, Py_NewRef(frame->f_code)); } #endif -static inline PyCodeObject* +PYCAPI_COMPAT_STATIC_INLINE(PyCodeObject*) _PyFrame_GetCodeBorrow(PyFrameObject *frame) { - return (PyCodeObject *)_Py_StealRef(PyFrame_GetCode(frame)); + return PYCAPI_COMPAT_CAST(PyCodeObject *, + _Py_StealRef(PyFrame_GetCode(frame))); } // bpo-40421 added PyFrame_GetCode() to Python 3.9.0b1 #if PY_VERSION_HEX < 0x030900B1 && !defined(PYPY_VERSION) -static inline PyFrameObject* +PYCAPI_COMPAT_STATIC_INLINE(PyFrameObject*) PyFrame_GetBack(PyFrameObject *frame) { - assert(frame != NULL); - return (PyFrameObject*)Py_XNewRef(frame->f_back); + assert(frame != PYCAPI_COMPAT_NULL); + return PYCAPI_COMPAT_CAST(PyFrameObject*, Py_XNewRef(frame->f_back)); } #endif #if !defined(PYPY_VERSION) -static inline PyFrameObject* +PYCAPI_COMPAT_STATIC_INLINE(PyFrameObject*) _PyFrame_GetBackBorrow(PyFrameObject *frame) { - return (PyFrameObject *)_Py_XStealRef(PyFrame_GetBack(frame)); + return PYCAPI_COMPAT_CAST(PyFrameObject *, + _Py_XStealRef(PyFrame_GetBack(frame))); } #endif // bpo-39947 added PyThreadState_GetInterpreter() to Python 3.9.0a5 #if PY_VERSION_HEX < 0x030900A5 -static inline PyInterpreterState * +PYCAPI_COMPAT_STATIC_INLINE(PyInterpreterState *) PyThreadState_GetInterpreter(PyThreadState *tstate) { - assert(tstate != NULL); + assert(tstate != PYCAPI_COMPAT_NULL); return tstate->interp; } #endif @@ -203,37 +218,38 @@ PyThreadState_GetInterpreter(PyThreadState *tstate) // bpo-40429 added PyThreadState_GetFrame() to Python 3.9.0b1 #if PY_VERSION_HEX < 0x030900B1 && !defined(PYPY_VERSION) -static inline PyFrameObject* +PYCAPI_COMPAT_STATIC_INLINE(PyFrameObject*) PyThreadState_GetFrame(PyThreadState *tstate) { - assert(tstate != NULL); - return (PyFrameObject *)Py_XNewRef(tstate->frame); + assert(tstate != PYCAPI_COMPAT_NULL); + return PYCAPI_COMPAT_CAST(PyFrameObject *, Py_XNewRef(tstate->frame)); } #endif #if !defined(PYPY_VERSION) -static inline PyFrameObject* +PYCAPI_COMPAT_STATIC_INLINE(PyFrameObject*) _PyThreadState_GetFrameBorrow(PyThreadState *tstate) { - return (PyFrameObject *)_Py_XStealRef(PyThreadState_GetFrame(tstate)); + return PYCAPI_COMPAT_CAST(PyFrameObject*, + _Py_XStealRef(PyThreadState_GetFrame(tstate))); } #endif // bpo-39947 added PyInterpreterState_Get() to Python 3.9.0a5 #if PY_VERSION_HEX < 0x030900A5 -static inline PyInterpreterState * +PYCAPI_COMPAT_STATIC_INLINE(PyInterpreterState*) PyInterpreterState_Get(void) { PyThreadState *tstate; PyInterpreterState *interp; tstate = PyThreadState_GET(); - if (tstate == NULL) { + if (tstate == PYCAPI_COMPAT_NULL) { Py_FatalError("GIL released (tstate is NULL)"); } interp = tstate->interp; - if (interp == NULL) { + if (interp == PYCAPI_COMPAT_NULL) { Py_FatalError("no current interpreter"); } return interp; @@ -243,17 +259,18 @@ PyInterpreterState_Get(void) // bpo-39947 added PyInterpreterState_Get() to Python 3.9.0a6 #if 0x030700A1 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030900A6 && !defined(PYPY_VERSION) -static inline uint64_t +PYCAPI_COMPAT_STATIC_INLINE(uint64_t) PyThreadState_GetID(PyThreadState *tstate) { - assert(tstate != NULL); + assert(tstate != PYCAPI_COMPAT_NULL); return tstate->id; } #endif // bpo-43760 added PyThreadState_EnterTracing() to Python 3.11.0a2 #if PY_VERSION_HEX < 0x030B00A2 && !defined(PYPY_VERSION) -static inline void PyThreadState_EnterTracing(PyThreadState *tstate) +PYCAPI_COMPAT_STATIC_INLINE(void) +PyThreadState_EnterTracing(PyThreadState *tstate) { tstate->tracing++; #if PY_VERSION_HEX >= 0x030A00A1 @@ -266,11 +283,12 @@ static inline void PyThreadState_EnterTracing(PyThreadState *tstate) // bpo-43760 added PyThreadState_LeaveTracing() to Python 3.11.0a2 #if PY_VERSION_HEX < 0x030B00A2 && !defined(PYPY_VERSION) -static inline void PyThreadState_LeaveTracing(PyThreadState *tstate) +PYCAPI_COMPAT_STATIC_INLINE(void) +PyThreadState_LeaveTracing(PyThreadState *tstate) { + int use_tracing = (tstate->c_tracefunc != PYCAPI_COMPAT_NULL + || tstate->c_profilefunc != PYCAPI_COMPAT_NULL); tstate->tracing--; - int use_tracing = (tstate->c_tracefunc != NULL - || tstate->c_profilefunc != NULL); #if PY_VERSION_HEX >= 0x030A00A1 tstate->cframe->use_tracing = use_tracing; #else @@ -282,7 +300,7 @@ static inline void PyThreadState_LeaveTracing(PyThreadState *tstate) // bpo-37194 added PyObject_CallNoArgs() to Python 3.9.0a1 #if PY_VERSION_HEX < 0x030900A1 -static inline PyObject* +PYCAPI_COMPAT_STATIC_INLINE(PyObject*) PyObject_CallNoArgs(PyObject *func) { return PyObject_CallFunctionObjArgs(func, NULL); @@ -293,7 +311,7 @@ PyObject_CallNoArgs(PyObject *func) // bpo-39245 made PyObject_CallOneArg() public (previously called // _PyObject_CallOneArg) in Python 3.9.0a4 #if PY_VERSION_HEX < 0x030900A4 -static inline PyObject* +PYCAPI_COMPAT_STATIC_INLINE(PyObject*) PyObject_CallOneArg(PyObject *func, PyObject *arg) { return PyObject_CallFunctionObjArgs(func, arg, NULL); @@ -303,12 +321,12 @@ PyObject_CallOneArg(PyObject *func, PyObject *arg) // bpo-1635741 added PyModule_AddObjectRef() to Python 3.10.0a3 #if PY_VERSION_HEX < 0x030A00A3 -static inline int -PyModule_AddObjectRef(PyObject *module, const char *name, PyObject *value) +PYCAPI_COMPAT_STATIC_INLINE(int) +PyModule_AddObjectRef(PyObject *mod, const char *name, PyObject *value) { int res; Py_XINCREF(value); - res = PyModule_AddObject(module, name, value); + res = PyModule_AddObject(mod, name, value); if (res < 0) { Py_XDECREF(value); } @@ -319,8 +337,8 @@ PyModule_AddObjectRef(PyObject *module, const char *name, PyObject *value) // bpo-40024 added PyModule_AddType() to Python 3.9.0a5 #if PY_VERSION_HEX < 0x030900A5 -static inline int -PyModule_AddType(PyObject *module, PyTypeObject *type) +PYCAPI_COMPAT_STATIC_INLINE(int) +PyModule_AddType(PyObject *mod, PyTypeObject *type) { const char *name, *dot; @@ -330,13 +348,13 @@ PyModule_AddType(PyObject *module, PyTypeObject *type) // inline _PyType_Name() name = type->tp_name; - assert(name != NULL); + assert(name != PYCAPI_COMPAT_NULL); dot = strrchr(name, '.'); - if (dot != NULL) { + if (dot != PYCAPI_COMPAT_NULL) { name = dot + 1; } - return PyModule_AddObjectRef(module, name, (PyObject *)type); + return PyModule_AddObjectRef(mod, name, _PyObject_CAST(type)); } #endif @@ -344,7 +362,7 @@ PyModule_AddType(PyObject *module, PyTypeObject *type) // bpo-40241 added PyObject_GC_IsTracked() to Python 3.9.0a6. // bpo-4688 added _PyObject_GC_IS_TRACKED() to Python 2.7.0a2. #if PY_VERSION_HEX < 0x030900A6 && !defined(PYPY_VERSION) -static inline int +PYCAPI_COMPAT_STATIC_INLINE(int) PyObject_GC_IsTracked(PyObject* obj) { return (PyObject_IS_GC(obj) && _PyObject_GC_IS_TRACKED(obj)); @@ -354,17 +372,18 @@ PyObject_GC_IsTracked(PyObject* obj) // bpo-40241 added PyObject_GC_IsFinalized() to Python 3.9.0a6. // bpo-18112 added _PyGCHead_FINALIZED() to Python 3.4.0 final. #if PY_VERSION_HEX < 0x030900A6 && PY_VERSION_HEX >= 0x030400F0 && !defined(PYPY_VERSION) -static inline int +PYCAPI_COMPAT_STATIC_INLINE(int) PyObject_GC_IsFinalized(PyObject *obj) { - return (PyObject_IS_GC(obj) && _PyGCHead_FINALIZED((PyGC_Head *)(obj)-1)); + PyGC_Head *gc = PYCAPI_COMPAT_CAST(PyGC_Head *, obj) - 1; + return (PyObject_IS_GC(obj) && _PyGCHead_FINALIZED(gc)); } #endif // bpo-39573 added Py_IS_TYPE() to Python 3.9.0a4 #if PY_VERSION_HEX < 0x030900A4 && !defined(Py_IS_TYPE) -static inline int +PYCAPI_COMPAT_STATIC_INLINE(int) _Py_IS_TYPE(const PyObject *ob, const PyTypeObject *type) { return ob->ob_type == type; } @@ -382,11 +401,6 @@ _Py_IS_TYPE(const PyObject *ob, const PyTypeObject *type) { #endif -#ifdef PYTHONCAPI_COMPAT_MSC_INLINE -# undef inline -# undef PYTHONCAPI_COMPAT_MSC_INLINE -#endif - #ifdef __cplusplus } #endif From a8b6d6f74cef7a2435f69fc8cdb33cf43fc4a8ac Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Tue, 22 Feb 2022 13:56:27 +0000 Subject: [PATCH 125/377] Fix inference of protocol against overloaded function (#12227) We used to infer a callable in a protocol against all overload items. This could result in incorrect results, if only one of the overload items would actually match the protocol. Fix the issue by only considering the first matching overload item. This seems to help with protocols involving `__getitem__`. In particular, this fixes regressions related to `SupportsLenAndGetItem`, which is used for `random.choice`. --- mypy/constraints.py | 25 ++++++++- test-data/unit/check-protocols.test | 83 +++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 1 deletion(-) diff --git a/mypy/constraints.py b/mypy/constraints.py index 9bc233054e917..ebf48f1dfec8c 100644 --- a/mypy/constraints.py +++ b/mypy/constraints.py @@ -658,8 +658,12 @@ def infer_against_any(self, types: Iterable[Type], any_type: AnyType) -> List[Co return res def visit_overloaded(self, template: Overloaded) -> List[Constraint]: + if isinstance(self.actual, CallableType): + items = find_matching_overload_items(template, self.actual) + else: + items = template.items res: List[Constraint] = [] - for t in template.items: + for t in items: res.extend(infer_constraints(t, self.actual, self.direction)) return res @@ -701,3 +705,22 @@ def find_matching_overload_item(overloaded: Overloaded, template: CallableType) # Fall back to the first item if we can't find a match. This is totally arbitrary -- # maybe we should just bail out at this point. return items[0] + + +def find_matching_overload_items(overloaded: Overloaded, + template: CallableType) -> List[CallableType]: + """Like find_matching_overload_item, but return all matches, not just the first.""" + items = overloaded.items + res = [] + for item in items: + # Return type may be indeterminate in the template, so ignore it when performing a + # subtype check. + if mypy.subtypes.is_callable_compatible(item, template, + is_compat=mypy.subtypes.is_subtype, + ignore_return=True): + res.append(item) + if not res: + # Falling back to all items if we can't find a match is pretty arbitrary, but + # it maintains backward compatibility. + res = items[:] + return res diff --git a/test-data/unit/check-protocols.test b/test-data/unit/check-protocols.test index a5962bde5333e..d04ba28ccb031 100644 --- a/test-data/unit/check-protocols.test +++ b/test-data/unit/check-protocols.test @@ -2806,3 +2806,86 @@ class MyClass: assert isinstance(self, MyProtocol) [builtins fixtures/isinstance.pyi] [typing fixtures/typing-full.pyi] + +[case testMatchProtocolAgainstOverloadWithAmbiguity] +from typing import TypeVar, Protocol, Union, Generic, overload + +T = TypeVar("T", covariant=True) + +class slice: pass + +class GetItem(Protocol[T]): + def __getitem__(self, k: int) -> T: ... + +class Str: # Resembles 'str' + def __getitem__(self, k: Union[int, slice]) -> Str: ... + +class Lst(Generic[T]): # Resembles 'list' + def __init__(self, x: T): ... + @overload + def __getitem__(self, k: int) -> T: ... + @overload + def __getitem__(self, k: slice) -> Lst[T]: ... + def __getitem__(self, k): pass + +def f(x: GetItem[GetItem[Str]]) -> None: ... + +a: Lst[Str] +f(Lst(a)) + +class Lst2(Generic[T]): + def __init__(self, x: T): ... + # The overload items are tweaked but still compatible + @overload + def __getitem__(self, k: Str) -> None: ... + @overload + def __getitem__(self, k: slice) -> Lst2[T]: ... + @overload + def __getitem__(self, k: Union[int, str]) -> T: ... + def __getitem__(self, k): pass + +b: Lst2[Str] +f(Lst2(b)) + +class Lst3(Generic[T]): # Resembles 'list' + def __init__(self, x: T): ... + # The overload items are no longer compatible (too narrow argument type) + @overload + def __getitem__(self, k: slice) -> Lst3[T]: ... + @overload + def __getitem__(self, k: bool) -> T: ... + def __getitem__(self, k): pass + +c: Lst3[Str] +f(Lst3(c)) # E: Argument 1 to "f" has incompatible type "Lst3[Lst3[Str]]"; expected "GetItem[GetItem[Str]]" \ +# N: Following member(s) of "Lst3[Lst3[Str]]" have conflicts: \ +# N: Expected: \ +# N: def __getitem__(self, int) -> GetItem[Str] \ +# N: Got: \ +# N: @overload \ +# N: def __getitem__(self, slice) -> Lst3[Lst3[Str]] \ +# N: @overload \ +# N: def __getitem__(self, bool) -> Lst3[Str] + +[builtins fixtures/list.pyi] +[typing fixtures/typing-full.pyi] + +[case testMatchProtocolAgainstOverloadWithMultipleMatchingItems] +from typing import Protocol, overload, TypeVar, Any + +_T_co = TypeVar("_T_co", covariant=True) +_T = TypeVar("_T") + +class SupportsRound(Protocol[_T_co]): + @overload + def __round__(self) -> int: ... + @overload + def __round__(self, __ndigits: int) -> _T_co: ... + +class C: + # This matches both overload items of SupportsRound + def __round__(self, __ndigits: int = ...) -> int: ... + +def round(number: SupportsRound[_T], ndigits: int) -> _T: ... + +round(C(), 1) From 1321e9e78dda815e14d16338f01903b449379bdd Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Tue, 22 Feb 2022 17:19:50 +0300 Subject: [PATCH 126/377] Check `Enum` definition for invalid base classes (#12026) Closes #11948 --- mypy/checker.py | 33 +++++++++++++++++ test-data/unit/check-enum.test | 65 ++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/mypy/checker.py b/mypy/checker.py index 2f99b9b4fece7..610ede794b91d 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -1837,6 +1837,7 @@ def visit_class_def(self, defn: ClassDef) -> None: for base in defn.info.mro[1:-1]: # we don't need self and `object` if base.is_enum and base.fullname not in ENUM_BASES: self.check_final_enum(defn, base) + self.check_enum_bases(defn) def check_final_deletable(self, typ: TypeInfo) -> None: # These checks are only for mypyc. Only perform some checks that are easier @@ -1931,6 +1932,38 @@ def is_final_enum_value(self, sym: SymbolTableNode) -> bool: return True return False + def check_enum_bases(self, defn: ClassDef) -> None: + enum_base: Optional[Instance] = None + data_base: Optional[Instance] = None + for base in defn.info.bases: + if enum_base is None and base.type.fullname in ENUM_BASES: + enum_base = base + continue + elif enum_base is not None: + self.fail( + 'No base classes are allowed after "{}"'.format(enum_base), + defn, + ) + break + + # This might not be 100% correct, because runtime `__new__` + # and `__new__` from `typeshed` are sometimes different, + # but it is good enough. + new_method = base.type.get('__new__') + if (data_base is None + and enum_base is None # data type is always before `Enum` + and new_method + and new_method.node + and new_method.node.fullname != 'builtins.object.__new__'): + data_base = base + continue + elif data_base is not None: + self.fail( + 'Only a single data type mixin is allowed for Enum subtypes, ' + 'found extra "{}"'.format(base), + defn, + ) + def check_protocol_variance(self, defn: ClassDef) -> None: """Check that protocol definition is compatible with declared variances of type variables. diff --git a/test-data/unit/check-enum.test b/test-data/unit/check-enum.test index 572c8f3929e1f..e1dec9aec86fc 100644 --- a/test-data/unit/check-enum.test +++ b/test-data/unit/check-enum.test @@ -1883,6 +1883,71 @@ class SubWithOverload(WithOverload): # Should pass pass [builtins fixtures/tuple.pyi] +[case testEnumBaseClassesOrder] +import enum + +# Base types: + +class First: + def __new__(cls, val): + pass + +class Second: + def __new__(cls, val): + pass + +class Third: + def __new__(cls, val): + pass + +class Mixin: + pass + +# Correct Enums: + +class Correct1(Mixin, First, enum.Enum): + pass + +class Correct2(First, enum.Enum): + pass + +class Correct3(Mixin, enum.Enum): + pass + +class RegularClass(Mixin, First, Second): + pass + +# Wrong Enums: + +class MixinAfterEnum1(enum.Enum, Mixin): # E: No base classes are allowed after "enum.Enum" + pass + +class MixinAfterEnum2(First, enum.Enum, Mixin): # E: No base classes are allowed after "enum.Enum" + pass + +class TwoDataTypes(First, Second, enum.Enum): # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second" + pass + +class TwoDataTypesAndIntEnumMixin(First, Second, enum.IntEnum, Mixin): # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second" \ + # E: No base classes are allowed after "enum.IntEnum" + pass + +class ThreeDataTypes(First, Second, Third, enum.Enum): # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second" \ + # E: # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Third" + pass + +class ThreeDataTypesAndMixin(First, Second, Third, enum.Enum, Mixin): # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second" \ + # E: # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Third" \ + # E: No base classes are allowed after "enum.Enum" + pass + +class FromEnumAndOther1(Correct2, Second, enum.Enum): # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second" + pass + +class FromEnumAndOther2(Correct2, Second): # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second" + pass +[builtins fixtures/tuple.pyi] + [case testEnumtValueUnionSimplification] from enum import IntEnum from typing import Any From 8157a6f65bf7fec004b5cc7b3ea01f8cf2b420e8 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Tue, 22 Feb 2022 14:34:32 +0000 Subject: [PATCH 127/377] Typeshed cherry-pick: Improve signature of overlaps in ipaddress (#7260) (#12236) This fixes a minor regression. --- mypy/typeshed/stdlib/ipaddress.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/typeshed/stdlib/ipaddress.pyi b/mypy/typeshed/stdlib/ipaddress.pyi index 6af3ebc3a2bd4..1cfd9a7c93784 100644 --- a/mypy/typeshed/stdlib/ipaddress.pyi +++ b/mypy/typeshed/stdlib/ipaddress.pyi @@ -84,7 +84,7 @@ class _BaseNetwork(_IPAddressBase, Container[_A], Iterable[_A], Generic[_A]): def max_prefixlen(self) -> int: ... @property def num_addresses(self) -> int: ... - def overlaps(self, other: _BaseNetwork[_A]) -> bool: ... + def overlaps(self, other: _BaseNetwork[IPv4Address] | _BaseNetwork[IPv6Address]) -> bool: ... @property def prefixlen(self) -> int: ... if sys.version_info >= (3, 7): From 7143424750280a476e9cdcaaa1bb6050c84bd534 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Tue, 22 Feb 2022 17:47:24 +0300 Subject: [PATCH 128/377] Handle `raise Exception(), None` on Python2.7 (#11786) Closes #11742 Related #11743 Related #11289 Related #11700 --- mypy/checker.py | 94 +++++++++++++++++++++++++++---- mypy/fastparse2.py | 4 ++ mypy/nodes.py | 5 +- test-data/unit/check-python2.test | 83 +++++++++++++++++++++++++-- 4 files changed, 167 insertions(+), 19 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 610ede794b91d..db229e274ab72 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -3581,7 +3581,7 @@ def visit_raise_stmt(self, s: RaiseStmt) -> None: if s.expr: self.type_check_raise(s.expr, s) if s.from_expr: - self.type_check_raise(s.from_expr, s, True) + self.type_check_raise(s.from_expr, s, optional=True) self.binder.unreachable() def type_check_raise(self, e: Expression, s: RaiseStmt, @@ -3590,24 +3590,94 @@ def type_check_raise(self, e: Expression, s: RaiseStmt, if isinstance(typ, DeletedType): self.msg.deleted_as_rvalue(typ, e) return + + if self.options.python_version[0] == 2: + # Since `raise` has very different rule on python2, we use a different helper. + # https://github.com/python/mypy/pull/11289 + self._type_check_raise_python2(e, s, typ) + return + + # Python3 case: exc_type = self.named_type('builtins.BaseException') - expected_type = UnionType([exc_type, TypeType(exc_type)]) + expected_type_items = [exc_type, TypeType(exc_type)] if optional: - expected_type.items.append(NoneType()) - if self.options.python_version[0] == 2: - # allow `raise type, value, traceback` - # https://docs.python.org/2/reference/simple_stmts.html#the-raise-statement - # TODO: Also check tuple item types. - any_type = AnyType(TypeOfAny.implementation_artifact) - tuple_type = self.named_type('builtins.tuple') - expected_type.items.append(TupleType([any_type, any_type], tuple_type)) - expected_type.items.append(TupleType([any_type, any_type, any_type], tuple_type)) - self.check_subtype(typ, expected_type, s, message_registry.INVALID_EXCEPTION) + # This is used for `x` part in a case like `raise e from x`, + # where we allow `raise e from None`. + expected_type_items.append(NoneType()) + + self.check_subtype( + typ, UnionType.make_union(expected_type_items), s, + message_registry.INVALID_EXCEPTION, + ) if isinstance(typ, FunctionLike): # https://github.com/python/mypy/issues/11089 self.expr_checker.check_call(typ, [], [], e) + def _type_check_raise_python2(self, e: Expression, s: RaiseStmt, typ: ProperType) -> None: + # Python2 has two possible major cases: + # 1. `raise expr`, where `expr` is some expression, it can be: + # - Exception typ + # - Exception instance + # - Old style class (not supported) + # - Tuple, where 0th item is exception type or instance + # 2. `raise exc, msg, traceback`, where: + # - `exc` is exception type (not instance!) + # - `traceback` is `types.TracebackType | None` + # Important note: `raise exc, msg` is not the same as `raise (exc, msg)` + # We call `raise exc, msg, traceback` - legacy mode. + exc_type = self.named_type('builtins.BaseException') + exc_inst_or_type = UnionType([exc_type, TypeType(exc_type)]) + + if (not s.legacy_mode and (isinstance(typ, TupleType) and typ.items + or (isinstance(typ, Instance) and typ.args + and typ.type.fullname == 'builtins.tuple'))): + # `raise (exc, ...)` case: + item = typ.items[0] if isinstance(typ, TupleType) else typ.args[0] + self.check_subtype( + item, exc_inst_or_type, s, + 'When raising a tuple, first element must by derived from BaseException', + ) + return + elif s.legacy_mode: + # `raise Exception, msg` case + # `raise Exception, msg, traceback` case + # https://docs.python.org/2/reference/simple_stmts.html#the-raise-statement + assert isinstance(typ, TupleType) # Is set in fastparse2.py + if (len(typ.items) >= 2 + and isinstance(get_proper_type(typ.items[1]), NoneType)): + expected_type: Type = exc_inst_or_type + else: + expected_type = TypeType(exc_type) + self.check_subtype( + typ.items[0], expected_type, s, + 'Argument 1 must be "{}" subtype'.format(expected_type), + ) + + # Typecheck `traceback` part: + if len(typ.items) == 3: + # Now, we typecheck `traceback` argument if it is present. + # We do this after the main check for better error message + # and better ordering: first about `BaseException` subtype, + # then about `traceback` type. + traceback_type = UnionType.make_union([ + self.named_type('types.TracebackType'), + NoneType(), + ]) + self.check_subtype( + typ.items[2], traceback_type, s, + 'Argument 3 must be "{}" subtype'.format(traceback_type), + ) + else: + expected_type_items = [ + # `raise Exception` and `raise Exception()` cases: + exc_type, TypeType(exc_type), + ] + self.check_subtype( + typ, UnionType.make_union(expected_type_items), + s, message_registry.INVALID_EXCEPTION, + ) + def visit_try_stmt(self, s: TryStmt) -> None: """Type check a try statement.""" # Our enclosing frame will get the result if the try/except falls through. diff --git a/mypy/fastparse2.py b/mypy/fastparse2.py index 5162fbb5df450..0e8faa957d67c 100644 --- a/mypy/fastparse2.py +++ b/mypy/fastparse2.py @@ -665,19 +665,23 @@ def visit_With(self, n: ast27.With) -> WithStmt: typ) return self.set_line(stmt, n) + # 'raise' [test [',' test [',' test]]] def visit_Raise(self, n: ast27.Raise) -> RaiseStmt: + legacy_mode = False if n.type is None: e = None else: if n.inst is None: e = self.visit(n.type) else: + legacy_mode = True if n.tback is None: e = TupleExpr([self.visit(n.type), self.visit(n.inst)]) else: e = TupleExpr([self.visit(n.type), self.visit(n.inst), self.visit(n.tback)]) stmt = RaiseStmt(e, None) + stmt.legacy_mode = legacy_mode return self.set_line(stmt, n) # TryExcept(stmt* body, excepthandler* handlers, stmt* orelse) diff --git a/mypy/nodes.py b/mypy/nodes.py index 5f0d58aecb569..49edd16a3085a 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -1302,16 +1302,19 @@ def accept(self, visitor: StatementVisitor[T]) -> T: class RaiseStmt(Statement): - __slots__ = ('expr', 'from_expr') + __slots__ = ('expr', 'from_expr', 'legacy_mode') # Plain 'raise' is a valid statement. expr: Optional[Expression] from_expr: Optional[Expression] + # Is set when python2 has `raise exc, msg, traceback`. + legacy_mode: bool def __init__(self, expr: Optional[Expression], from_expr: Optional[Expression]) -> None: super().__init__() self.expr = expr self.from_expr = from_expr + self.legacy_mode = False def accept(self, visitor: StatementVisitor[T]) -> T: return visitor.visit_raise_stmt(self) diff --git a/test-data/unit/check-python2.test b/test-data/unit/check-python2.test index d658fe013401f..0481767abd63a 100644 --- a/test-data/unit/check-python2.test +++ b/test-data/unit/check-python2.test @@ -68,18 +68,89 @@ A.f(1) A.f('') # E: Argument 1 to "f" of "A" has incompatible type "str"; expected "int" [builtins_py2 fixtures/staticmethod.pyi] -[case testRaiseTuple] -import typing -raise BaseException, "a" -raise BaseException, "a", None -[builtins_py2 fixtures/exception.pyi] - [case testRaiseTupleTypeFail] import typing x = None # type: typing.Type[typing.Tuple[typing.Any, typing.Any, typing.Any]] raise x # E: Exception must be derived from BaseException [builtins_py2 fixtures/exception.pyi] +[case testRaiseTupleOfThreeOnPython2] +from types import TracebackType +from typing import Optional, Tuple, Type + +e = None # type: Optional[TracebackType] + +# Correct raising several items: + +raise BaseException +raise BaseException(1) +raise (BaseException,) +raise (BaseException(1),) +raise BaseException, 1 +raise BaseException, 1, e +raise BaseException, 1, None + +raise Exception +raise Exception(1) +raise Exception() +raise Exception(1), None +raise Exception(), None +raise Exception(1), None, None +raise Exception(1), None, e +raise (Exception,) +raise (Exception(1),) +raise Exception, 1 +raise Exception, 1, e +raise Exception, 1, None + +# Errors: + +raise int, 1 # E: Argument 1 must be "Type[builtins.BaseException]" subtype +raise int, None # E: Argument 1 must be "Union[builtins.BaseException, Type[builtins.BaseException]]" subtype +raise Exception(1), 1 # E: Argument 1 must be "Type[builtins.BaseException]" subtype +raise Exception(1), 1, None # E: Argument 1 must be "Type[builtins.BaseException]" subtype +raise Exception, 1, 1 # E: Argument 3 must be "Union[types.TracebackType, None]" subtype +raise int, 1, 1 # E: Argument 1 must be "Type[builtins.BaseException]" subtype \ + # E: Argument 3 must be "Union[types.TracebackType, None]" subtype + +# Correct raising tuple: + +t1 = (BaseException,) +t2 = (Exception(1), 2, 3, 4) # type: Tuple[Exception, int, int, int] +t3 = (Exception,) # type: Tuple[Type[Exception], ...] +t4 = (Exception(1),) # type: Tuple[Exception, ...] + +raise t1 +raise t2 +raise t3 +raise t4 + +# Errors: + +raise t1, 1, None # E: Argument 1 must be "Type[builtins.BaseException]" subtype +raise t2, 1 # E: Argument 1 must be "Type[builtins.BaseException]" subtype +raise t3, 1, e # E: Argument 1 must be "Type[builtins.BaseException]" subtype +raise t4, 1, 1 # E: Argument 1 must be "Type[builtins.BaseException]" subtype \ + # E: Argument 3 must be "Union[types.TracebackType, None]" subtype + +w1 = () +w2 = (1, Exception) +w3 = (1,) # type: Tuple[int, ...] + +raise w1 # E: Exception must be derived from BaseException +raise w2 # E: When raising a tuple, first element must by derived from BaseException +raise w3 # E: When raising a tuple, first element must by derived from BaseException + +# Bare raise: + +try: + pass +except Exception: + raise # ok +[builtins_py2 fixtures/exception.pyi] +[file types.pyi] +class TracebackType: pass + [case testTryExceptWithTuple] try: None From bd37ab895f15b5ad04586d14155ebb14aceeb1eb Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Tue, 22 Feb 2022 18:24:30 +0300 Subject: [PATCH 129/377] Adds docs about `Enum` type (#11805) * Adds docs about `Enum` type * Better structure --- docs/source/literal_types.rst | 120 +++++++++++++++++++++++++++++++++- 1 file changed, 119 insertions(+), 1 deletion(-) diff --git a/docs/source/literal_types.rst b/docs/source/literal_types.rst index da62b31526c96..d5271b256bb21 100644 --- a/docs/source/literal_types.rst +++ b/docs/source/literal_types.rst @@ -1,7 +1,10 @@ +Literal types and Enums +======================= + .. _literal_types: Literal types -============= +------------- Literal types let you indicate that an expression is equal to some specific primitive value. For example, if we annotate a variable with type ``Literal["foo"]``, @@ -369,3 +372,118 @@ whatever type the parameter has. For example, ``Literal[3]`` is treated as a subtype of ``int`` and so will inherit all of ``int``'s methods directly. This means that ``Literal[3].__add__`` accepts the same arguments and has the same return type as ``int.__add__``. + + +Enums +----- + +Mypy has special support for :py:class:`enum.Enum` and its subclasses: +:py:class:`enum.IntEnum`, :py:class:`enum.Flag`, and :py:class:`enum.IntFlag`. + +.. code-block:: python + + from enum import Enum + + class Direction(Enum): + up = 'up' + down = 'down' + + reveal_type(Direction.up) # Revealed type is "Literal[Direction.up]?" + reveal_type(Direction.down) # Revealed type is "Literal[Direction.down]?" + +You can use enums to annotate types as you would expect: + +.. code-block:: python + + class Movement: + def __init__(self, direction: Direction, speed: float) -> None: + self.direction = direction + self.speed = speed + + Movement(Direction.up, 5.0) # ok + Movement('up', 5.0) # E: Argument 1 to "Movemement" has incompatible type "str"; expected "Direction" + +Exhaustive checks +***************** + +Similiar to ``Literal`` types ``Enum`` supports exhaustive checks. +Let's start with a definition: + +.. code-block:: python + + from enum import Enum + from typing import NoReturn + + def assert_never(value: NoReturn) -> NoReturn: + # This also works in runtime as well: + assert False, 'This code should never be reached, got: {0}'.format(value) + + class Direction(Enum): + up = 'up' + down = 'down' + +Now, let's define an exhaustive check: + +.. code-block:: python + + def choose_direction(direction: Direction) -> None: + if direction is Direction.up: + reveal_type(direction) # N: Revealed type is "Literal[ex.Direction.up]" + print('Going up!') + return + elif direction is Direction.down: + print('Down') + return + assert_never(direction) + +And then test that it raises an error when some cases are not covered: + +.. code-block:: python + + def choose_direction(direction: Direction) -> None: + if direction == Direction.up: + print('Going up!') + return + assert_never(direction) # E: Argument 1 to "assert_never" has incompatible type "Direction"; expected "NoReturn" + +Extra Enum checks +***************** + +Mypy also tries to support special features of ``Enum`` +the same way Python's runtime does. + +Extra checks: + +- Any ``Enum`` class with values is implicitly :ref:`final `. + This is what happens in CPython: + + .. code-block:: python + + >>> class AllDirection(Direction): + ... left = 'left' + ... right = 'right' + Traceback (most recent call last): + ... + TypeError: Other: cannot extend enumeration 'Some' + + We do the same thing: + + .. code-block:: python + + class AllDirection(Direction): # E: Cannot inherit from final class "Some" + left = 'left' + right = 'right' + +- All ``Enum`` fields are implictly ``final`` as well. + + .. code-block:: python + + Direction.up = '^' # E: Cannot assign to final attribute "up" + +- All field names are checked to be unique. + + .. code-block:: python + + class Some(Enum): + x = 1 + x = 2 # E: Attempted to reuse member name "x" in Enum definition "Some" From 784b67ec0b1daa42c128396f247987bb0c80a3d3 Mon Sep 17 00:00:00 2001 From: 97littleleaf11 <11172084+97littleleaf11@users.noreply.github.com> Date: Wed, 23 Feb 2022 00:02:04 +0800 Subject: [PATCH 130/377] [mypyc] Use Py_TYPE and Py_IsNone (#12233) --- mypyc/lib-rt/dict_ops.c | 4 ++-- mypyc/lib-rt/exc_ops.c | 2 +- mypyc/lib-rt/generic_ops.c | 2 +- mypyc/lib-rt/misc_ops.c | 7 +++---- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/mypyc/lib-rt/dict_ops.c b/mypyc/lib-rt/dict_ops.c index 21a9035021ea2..b013a8a5f0b93 100644 --- a/mypyc/lib-rt/dict_ops.c +++ b/mypyc/lib-rt/dict_ops.c @@ -139,8 +139,8 @@ int CPyDict_UpdateInDisplay(PyObject *dict, PyObject *stuff) { if (ret < 0) { if (PyErr_ExceptionMatches(PyExc_AttributeError)) { PyErr_Format(PyExc_TypeError, - "'%.200s' object is not a mapping", - stuff->ob_type->tp_name); + "'%.200s' object is not a mapping", + Py_TYPE(stuff)->tp_name); } } return ret; diff --git a/mypyc/lib-rt/exc_ops.c b/mypyc/lib-rt/exc_ops.c index b87d5471a411d..7ef46479d2e8e 100644 --- a/mypyc/lib-rt/exc_ops.c +++ b/mypyc/lib-rt/exc_ops.c @@ -140,7 +140,7 @@ static PyObject *CPy_GetTypeName(PyObject *type) { // Get the type of a value as a string, expanding tuples to include // all the element types. static PyObject *CPy_FormatTypeName(PyObject *value) { - if (value == Py_None) { + if (Py_IsNone(value)) { return PyUnicode_FromString("None"); } diff --git a/mypyc/lib-rt/generic_ops.c b/mypyc/lib-rt/generic_ops.c index 1dff949dcfcf6..2f4a7941a6dab 100644 --- a/mypyc/lib-rt/generic_ops.c +++ b/mypyc/lib-rt/generic_ops.c @@ -33,7 +33,7 @@ PyObject *CPyObject_GetAttr3(PyObject *v, PyObject *name, PyObject *defl) PyObject *CPyIter_Next(PyObject *iter) { - return (*iter->ob_type->tp_iternext)(iter); + return (*Py_TYPE(iter)->tp_iternext)(iter); } PyObject *CPyNumber_Power(PyObject *base, PyObject *index) diff --git a/mypyc/lib-rt/misc_ops.c b/mypyc/lib-rt/misc_ops.c index 6b5685ab1f1a6..cebd1cf997f83 100644 --- a/mypyc/lib-rt/misc_ops.c +++ b/mypyc/lib-rt/misc_ops.c @@ -3,14 +3,13 @@ // These are registered in mypyc.primitives.misc_ops. #include -#include "pythoncapi_compat.h" #include "CPy.h" PyObject *CPy_GetCoro(PyObject *obj) { // If the type has an __await__ method, call it, // otherwise, fallback to calling __iter__. - PyAsyncMethods* async_struct = obj->ob_type->tp_as_async; + PyAsyncMethods* async_struct = Py_TYPE(obj)->tp_as_async; if (async_struct != NULL && async_struct->am_await != NULL) { return (async_struct->am_await)(obj); } else { @@ -25,7 +24,7 @@ PyObject *CPyIter_Send(PyObject *iter, PyObject *val) // Do a send, or a next if second arg is None. // (This behavior is to match the PEP 380 spec for yield from.) _Py_IDENTIFIER(send); - if (val == Py_None) { + if (Py_IsNone(val)) { return CPyIter_Next(iter); } else { return _PyObject_CallMethodIdOneArg(iter, &PyId_send, val); @@ -640,7 +639,7 @@ CPy_Super(PyObject *builtins, PyObject *self) { if (!super_type) return NULL; PyObject *result = PyObject_CallFunctionObjArgs( - super_type, (PyObject*)self->ob_type, self, NULL); + super_type, (PyObject*)Py_TYPE(self), self, NULL); Py_DECREF(super_type); return result; } From bb1fda39eb4a9cf370086987760e4dc113b8b859 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Tue, 22 Feb 2022 17:07:38 +0000 Subject: [PATCH 131/377] Typeshed cherry-pick: Replace some literal types in logging with int (#7354) (#12239) Fixes some regressions. Context: python/typeshed#7258 --- mypy/typeshed/stdlib/logging/__init__.pyi | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/mypy/typeshed/stdlib/logging/__init__.pyi b/mypy/typeshed/stdlib/logging/__init__.pyi index d0d50041a0cf7..442e79a9c6f32 100644 --- a/mypy/typeshed/stdlib/logging/__init__.pyi +++ b/mypy/typeshed/stdlib/logging/__init__.pyi @@ -244,14 +244,14 @@ class Logger(Filterer): def hasHandlers(self) -> bool: ... def callHandlers(self, record: LogRecord) -> None: ... # undocumented -CRITICAL: Literal[50] -FATAL: Literal[50] -ERROR: Literal[40] -WARNING: Literal[30] -WARN: Literal[30] -INFO: Literal[20] -DEBUG: Literal[10] -NOTSET: Literal[0] +CRITICAL: int +FATAL: int +ERROR: int +WARNING: int +WARN: int +INFO: int +DEBUG: int +NOTSET: int class Handler(Filterer): level: int # undocumented From eca4c300111a8c12e402acbada35badbd3c705f8 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Tue, 22 Feb 2022 17:08:01 +0000 Subject: [PATCH 132/377] Typeshed cherry-pick: Use `int | Any` for `types.FrameType.f_lineno` (#6935) (#12240) This fixes some regressions. --- mypy/typeshed/stdlib/types.pyi | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mypy/typeshed/stdlib/types.pyi b/mypy/typeshed/stdlib/types.pyi index 92f8daa7ebed8..caf745b99554e 100644 --- a/mypy/typeshed/stdlib/types.pyi +++ b/mypy/typeshed/stdlib/types.pyi @@ -354,7 +354,10 @@ class FrameType: f_code: CodeType f_globals: dict[str, Any] f_lasti: int - f_lineno: int | None + # see discussion in #6769: f_lineno *can* sometimes be None, + # but you should probably file a bug report with CPython if you encounter it being None in the wild. + # An `int | None` annotation here causes too many false-positive errors. + f_lineno: int | Any f_locals: dict[str, Any] f_trace: Callable[[FrameType, str, Any], Any] | None if sys.version_info >= (3, 7): From 65ac27050149126469e006954a6ae5a0c5359ea8 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Tue, 22 Feb 2022 19:51:47 +0000 Subject: [PATCH 133/377] Use type variable bound to infer constraints (#12230) This fixes a regression where `iter(x)` could generate a false positive if `x` has a type variable type. --- mypy/constraints.py | 4 ++++ test-data/unit/check-protocols.test | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/mypy/constraints.py b/mypy/constraints.py index ebf48f1dfec8c..040bcff8c99d3 100644 --- a/mypy/constraints.py +++ b/mypy/constraints.py @@ -513,6 +513,10 @@ def visit_instance(self, template: Instance) -> List[Constraint]: return infer_constraints(template, mypy.typeops.tuple_fallback(actual), self.direction) + elif isinstance(actual, TypeVarType): + if not actual.values: + return infer_constraints(template, actual.upper_bound, self.direction) + return [] else: return [] diff --git a/test-data/unit/check-protocols.test b/test-data/unit/check-protocols.test index d04ba28ccb031..65fb30a3547f9 100644 --- a/test-data/unit/check-protocols.test +++ b/test-data/unit/check-protocols.test @@ -2807,6 +2807,27 @@ class MyClass: [builtins fixtures/isinstance.pyi] [typing fixtures/typing-full.pyi] +[case testProtocolAndTypeVariableSpecialCase] +from typing import TypeVar, Iterable, Optional, Callable, Protocol + +T_co = TypeVar('T_co', covariant=True) + +class SupportsNext(Protocol[T_co]): + def __next__(self) -> T_co: ... + +N = TypeVar("N", bound=SupportsNext, covariant=True) + +class SupportsIter(Protocol[T_co]): + def __iter__(self) -> T_co: ... + +def f(i: SupportsIter[N]) -> N: ... + +I = TypeVar('I', bound=Iterable) + +def g(x: I, y: Iterable) -> None: + f(x) + f(y) + [case testMatchProtocolAgainstOverloadWithAmbiguity] from typing import TypeVar, Protocol, Union, Generic, overload From fa3adbd462eb1be64c4417d75319c632324e821c Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Wed, 23 Feb 2022 04:55:16 +0300 Subject: [PATCH 134/377] Update `Enum` docs (#12238) After merging https://github.com/python/mypy/pull/11805 I found out that we are missing several new `Enum` features. This PR adds them to the docs. Refs https://github.com/python/mypy/pull/12026 Refs https://github.com/python/mypy/pull/12035 --- docs/source/literal_types.rst | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/source/literal_types.rst b/docs/source/literal_types.rst index d5271b256bb21..c5df354ce6782 100644 --- a/docs/source/literal_types.rst +++ b/docs/source/literal_types.rst @@ -378,7 +378,8 @@ Enums ----- Mypy has special support for :py:class:`enum.Enum` and its subclasses: -:py:class:`enum.IntEnum`, :py:class:`enum.Flag`, and :py:class:`enum.IntFlag`. +:py:class:`enum.IntEnum`, :py:class:`enum.Flag`, :py:class:`enum.IntFlag`, +and :py:class:`enum.StrEnum`. .. code-block:: python @@ -487,3 +488,14 @@ Extra checks: class Some(Enum): x = 1 x = 2 # E: Attempted to reuse member name "x" in Enum definition "Some" + +- Base classes have no conflicts and mixin types are correct. + + .. code-block:: python + + class WrongEnum(str, int, enum.Enum): + # E: Only a single data type mixin is allowed for Enum subtypes, found extra "int" + ... + + class MixinAfterEnum(enum.Enum, Mixin): # E: No base classes are allowed after "enum.Enum" + ... From a3fc35a10dbf8158e1e989787202ab6c7b1766d1 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Tue, 22 Feb 2022 19:44:27 -0800 Subject: [PATCH 135/377] Make pyinfo compatible with Python 2 (#12244) I'm not adding a test because it's Python 2, but I did test locally. Co-authored-by: hauntsaninja <> --- mypy/pyinfo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/pyinfo.py b/mypy/pyinfo.py index 3834c04e218e9..ab2d3286bd5cf 100644 --- a/mypy/pyinfo.py +++ b/mypy/pyinfo.py @@ -19,7 +19,7 @@ def getprefixes(): # type: () -> Tuple[str, str] - return sys.base_prefix, sys.prefix + return getattr(sys, "base_prefix", sys.prefix), sys.prefix def getsitepackages(): From 115ac31fd42c5dcbb0ea4b0e9713e7a33c1418cc Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Wed, 23 Feb 2022 12:54:37 +0000 Subject: [PATCH 136/377] [mypyc] Improve comments and docstrings in tests (#12223) Tests for multi-file and separate compilation modes are a bit special, and it seems useful to have more documentation. Co-authored-by: Jelle Zijlstra --- mypyc/test-data/run-multimodule.test | 12 +++++++++++- mypyc/test/test_run.py | 23 ++++++++++++++++++++--- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/mypyc/test-data/run-multimodule.test b/mypyc/test-data/run-multimodule.test index 1444254b7595b..20c9002cdf1d9 100644 --- a/mypyc/test-data/run-multimodule.test +++ b/mypyc/test-data/run-multimodule.test @@ -1,4 +1,14 @@ --- These test cases compile two modules at a time (native and other.py) +-- These test cases compile two or more modules at a time. +-- Any file prefixed with "other" is compiled. +-- +-- Note that these are run in three compilation modes: regular, +-- multi-file and separate. See the docstrings of +-- mypyc.test.test_run.TestRunMultiFile and +-- mypyc.test.test_run.TestRunSeparate for more information. +-- +-- Some of these files perform multiple incremental runs. See +-- test-data/unit/check-incremental.test for more information +-- about how this is specified (e.g. .2 file name suffixes). [case testMultiModulePackage] from p.other import g diff --git a/mypyc/test/test_run.py b/mypyc/test/test_run.py index 306c151ef319c..a5e356ea56a6e 100644 --- a/mypyc/test/test_run.py +++ b/mypyc/test/test_run.py @@ -127,7 +127,7 @@ class TestRun(MypycDataSuite): base_path = test_temp_dir optional_out = True multi_file = False - separate = False + separate = False # If True, using separate (incremental) compilation def run_case(self, testcase: DataDrivenTestCase) -> None: # setup.py wants to be run from the root directory of the package, which we accommodate @@ -347,7 +347,11 @@ def get_separate(self, program_text: str, class TestRunMultiFile(TestRun): - """Run the main multi-module tests in multi-file compilation mode.""" + """Run the main multi-module tests in multi-file compilation mode. + + In multi-file mode each module gets compiled into a separate C file, + but all modules (C files) are compiled together. + """ multi_file = True test_name_suffix = '_multi' @@ -358,7 +362,20 @@ class TestRunMultiFile(TestRun): class TestRunSeparate(TestRun): - """Run the main multi-module tests in separate compilation mode.""" + """Run the main multi-module tests in separate compilation mode. + + In this mode there are multiple compilation groups, which are compiled + incrementally. Each group is compiled to a separate C file, and these C + files are compiled separately. + + Each compiled module is placed into a separate compilation group, unless + overridden by a special comment. Consider this example: + + # separate: [(["other.py", "other_b.py"], "stuff")] + + This puts other.py and other_b.py into a compilation group named "stuff". + Any files not mentioned in the comment will get single-file groups. + """ separate = True test_name_suffix = '_separate' From 14de8c6f1f24648299528881561ddcd52172701d Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Wed, 23 Feb 2022 21:16:02 +0300 Subject: [PATCH 137/377] Use `__truediv__` for python2 with `__future__` import, refs #11740 (#11787) Now `__future__` imports do not leak in semanal.py. Closes #11740 Refs #11741 Refs #11276 Refs #11700 --- mypy/build.py | 6 ++- mypy/checkexpr.py | 7 ++- mypy/nodes.py | 11 ++++- mypy/semanal.py | 9 ++-- test-data/unit/check-expressions.test | 64 +++++++++++++++++++++++++++ 5 files changed, 87 insertions(+), 10 deletions(-) diff --git a/mypy/build.py b/mypy/build.py index 24cef0b83bd3a..3ddbe40f1a90e 100644 --- a/mypy/build.py +++ b/mypy/build.py @@ -2186,8 +2186,10 @@ def type_checker(self) -> TypeChecker: if not self._type_checker: assert self.tree is not None, "Internal error: must be called on parsed file only" manager = self.manager - self._type_checker = TypeChecker(manager.errors, manager.modules, self.options, - self.tree, self.xpath, manager.plugin) + self._type_checker = TypeChecker( + manager.errors, manager.modules, self.options, + self.tree, self.xpath, manager.plugin, + ) return self._type_checker def type_map(self) -> Dict[Expression, Type]: diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 36f92898edb79..4ece9ac4c94bf 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -2416,8 +2416,11 @@ def dangerous_comparison(self, left: Type, right: Type, def get_operator_method(self, op: str) -> str: if op == '/' and self.chk.options.python_version[0] == 2: - # TODO also check for "from __future__ import division" - return '__div__' + return ( + '__truediv__' + if self.chk.tree.is_future_flag_set('division') + else '__div__' + ) else: return operators.op_methods[op] diff --git a/mypy/nodes.py b/mypy/nodes.py index 49edd16a3085a..f520280dce2df 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -258,7 +258,8 @@ class MypyFile(SymbolNode): __slots__ = ('_fullname', 'path', 'defs', 'alias_deps', 'is_bom', 'names', 'imports', 'ignored_lines', 'is_stub', - 'is_cache_skeleton', 'is_partial_stub_package', 'plugin_deps') + 'is_cache_skeleton', 'is_partial_stub_package', 'plugin_deps', + 'future_import_flags') # Fully qualified module name _fullname: Bogus[str] @@ -287,6 +288,8 @@ class MypyFile(SymbolNode): is_partial_stub_package: bool # Plugin-created dependencies plugin_deps: Dict[str, Set[str]] + # Future imports defined in this file. Populated during semantic analysis. + future_import_flags: Set[str] def __init__(self, defs: List[Statement], @@ -309,6 +312,7 @@ def __init__(self, self.is_stub = False self.is_cache_skeleton = False self.is_partial_stub_package = False + self.future_import_flags = set() def local_definitions(self) -> Iterator[Definition]: """Return all definitions within the module (including nested). @@ -331,6 +335,9 @@ def accept(self, visitor: NodeVisitor[T]) -> T: def is_package_init_file(self) -> bool: return len(self.path) != 0 and os.path.basename(self.path).startswith('__init__.') + def is_future_flag_set(self, flag: str) -> bool: + return flag in self.future_import_flags + def serialize(self) -> JsonDict: return {'.class': 'MypyFile', '_fullname': self._fullname, @@ -338,6 +345,7 @@ def serialize(self) -> JsonDict: 'is_stub': self.is_stub, 'path': self.path, 'is_partial_stub_package': self.is_partial_stub_package, + 'future_import_flags': list(self.future_import_flags), } @classmethod @@ -350,6 +358,7 @@ def deserialize(cls, data: JsonDict) -> 'MypyFile': tree.path = data['path'] tree.is_partial_stub_package = data['is_partial_stub_package'] tree.is_cache_skeleton = True + tree.future_import_flags = set(data['future_import_flags']) return tree diff --git a/mypy/semanal.py b/mypy/semanal.py index c83bc01908ad3..02ce361ab5d35 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -226,7 +226,6 @@ class SemanticAnalyzer(NodeVisitor[None], errors: Errors # Keeps track of generated errors plugin: Plugin # Mypy plugin for special casing of library features statement: Optional[Statement] = None # Statement/definition being analyzed - future_import_flags: Set[str] # Mapping from 'async def' function definitions to their return type wrapped as a # 'Coroutine[Any, Any, T]'. Used to keep track of whether a function definition's @@ -291,8 +290,6 @@ def __init__(self, # current SCC or top-level function. self.deferral_debug_context: List[Tuple[str, int]] = [] - self.future_import_flags: Set[str] = set() - # mypyc doesn't properly handle implementing an abstractproperty # with a regular attribute so we make them properties @property @@ -5374,10 +5371,12 @@ def parse_bool(self, expr: Expression) -> Optional[bool]: def set_future_import_flags(self, module_name: str) -> None: if module_name in FUTURE_IMPORTS: - self.future_import_flags.add(FUTURE_IMPORTS[module_name]) + self.modules[self.cur_mod_id].future_import_flags.add( + FUTURE_IMPORTS[module_name], + ) def is_future_flag_set(self, flag: str) -> bool: - return flag in self.future_import_flags + return self.modules[self.cur_mod_id].is_future_flag_set(flag) class HasPlaceholders(TypeQuery[bool]): diff --git a/test-data/unit/check-expressions.test b/test-data/unit/check-expressions.test index 6c6a5d473f011..46f0cf02a125b 100644 --- a/test-data/unit/check-expressions.test +++ b/test-data/unit/check-expressions.test @@ -202,6 +202,70 @@ class C: pass [builtins fixtures/tuple.pyi] +[case testDivPython2] +# flags: --python-version 2.7 +class A(object): + def __div__(self, other): + # type: (A, str) -> str + return 'a' + +a = A() +reveal_type(a / 'b') # N: Revealed type is "builtins.str" +a / 1 # E: Unsupported operand types for / ("A" and "int") +[builtins fixtures/bool.pyi] + +[case testDivPython2FutureImport] +# flags: --python-version 2.7 +from __future__ import division + +class A(object): + def __truediv__(self, other): + # type: (A, str) -> str + return 'a' + +a = A() +reveal_type(a / 'b') # N: Revealed type is "builtins.str" +a / 1 # E: Unsupported operand types for / ("A" and "int") +[builtins fixtures/bool.pyi] + +[case testDivPython2FutureImportNotLeaking] +# flags: --python-version 2.7 +import m1 + +[file m1.py] +import m2 + +class A(object): + def __div__(self, other): + # type: (A, str) -> str + return 'a' + +a = A() +reveal_type(a / 'b') # N: Revealed type is "builtins.str" +a / 1 # E: Unsupported operand types for / ("A" and "int") +[file m2.py] +from __future__ import division +[builtins fixtures/bool.pyi] + +[case testDivPython2FutureImportNotLeaking2] +# flags: --python-version 2.7 +import m1 + +[file m1.py] +import m2 + +class A(object): + def __div__(self, other): + # type: (A, str) -> str + return 'a' + +a = A() +reveal_type(a / 'b') # N: Revealed type is "builtins.str" +a / 1 # E: Unsupported operand types for / ("A" and "int") +[file m2.py] +# empty +[builtins fixtures/bool.pyi] + [case testIntDiv] a, b, c = None, None, None # type: (A, B, C) if int(): From ea933268427737976ef819ea3fff0599264e3d5b Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 25 Feb 2022 19:19:08 +0000 Subject: [PATCH 138/377] Give "as" variables in with statements separate scopes (#12254) Use renaming to allow two with statements to define the same variable using incompatible types. The implementation is pretty simple-minded and doesn't work in cases where there is even a hint of potential ambiguity about which variant of a variable a reference targets, typically due to functions. This could be generalized to for statements in the future. Fixes #12246. --- mypy/build.py | 11 +- mypy/renaming.py | 171 +++++++++++- test-data/unit/check-python310.test | 41 +++ test-data/unit/check-statements.test | 365 ++++++++++++++++++++++++- test-data/unit/semanal-statements.test | 56 ++++ 5 files changed, 630 insertions(+), 14 deletions(-) diff --git a/mypy/build.py b/mypy/build.py index 3ddbe40f1a90e..6513414dd298e 100644 --- a/mypy/build.py +++ b/mypy/build.py @@ -56,7 +56,7 @@ from mypy.fscache import FileSystemCache from mypy.metastore import MetadataStore, FilesystemMetadataStore, SqliteMetadataStore from mypy.typestate import TypeState, reset_global_state -from mypy.renaming import VariableRenameVisitor +from mypy.renaming import VariableRenameVisitor, LimitedVariableRenameVisitor from mypy.config_parser import parse_mypy_comments from mypy.freetree import free_tree from mypy.stubinfo import legacy_bundled_packages, is_legacy_bundled_package @@ -2119,9 +2119,12 @@ def semantic_analysis_pass1(self) -> None: analyzer.visit_file(self.tree, self.xpath, self.id, options) # TODO: Do this while constructing the AST? self.tree.names = SymbolTable() - if options.allow_redefinition: - # Perform renaming across the AST to allow variable redefinitions - self.tree.accept(VariableRenameVisitor()) + if not self.tree.is_stub: + # Always perform some low-key variable renaming + self.tree.accept(LimitedVariableRenameVisitor()) + if options.allow_redefinition: + # Perform more renaming across the AST to allow variable redefinitions + self.tree.accept(VariableRenameVisitor()) def add_dependency(self, dep: str) -> None: if dep not in self.dependencies_set: diff --git a/mypy/renaming.py b/mypy/renaming.py index c200e94d58e78..aa16d6dc8dd20 100644 --- a/mypy/renaming.py +++ b/mypy/renaming.py @@ -1,11 +1,11 @@ from contextlib import contextmanager -from typing import Dict, Iterator, List +from typing import Dict, Iterator, List, Set from typing_extensions import Final from mypy.nodes import ( Block, AssignmentStmt, NameExpr, MypyFile, FuncDef, Lvalue, ListExpr, TupleExpr, WhileStmt, ForStmt, BreakStmt, ContinueStmt, TryStmt, WithStmt, MatchStmt, StarExpr, - ImportFrom, MemberExpr, IndexExpr, Import, ClassDef + ImportFrom, MemberExpr, IndexExpr, Import, ImportAll, ClassDef ) from mypy.patterns import AsPattern from mypy.traverser import TraverserVisitor @@ -262,15 +262,9 @@ def flush_refs(self) -> None: # as it will be publicly visible outside the module. to_rename = refs[:-1] for i, item in enumerate(to_rename): - self.rename_refs(item, i) + rename_refs(item, i) self.refs.pop() - def rename_refs(self, names: List[NameExpr], index: int) -> None: - name = names[0].name - new_name = name + "'" * (index + 1) - for expr in names: - expr.name = new_name - # Helpers for determining which assignments define new variables def clear(self) -> None: @@ -392,3 +386,162 @@ def record_assignment(self, name: str, can_be_redefined: bool) -> bool: else: # Assigns to an existing variable. return False + + +class LimitedVariableRenameVisitor(TraverserVisitor): + """Perform some limited variable renaming in with statements. + + This allows reusing a variable in multiple with statements with + different types. For example, the two instances of 'x' can have + incompatible types: + + with C() as x: + f(x) + with D() as x: + g(x) + + The above code gets renamed conceptually into this (not valid Python!): + + with C() as x': + f(x') + with D() as x: + g(x) + + If there's a reference to a variable defined in 'with' outside the + statement, or if there's any trickiness around variable visibility + (e.g. function definitions), we give up and won't perform renaming. + + The main use case is to allow binding both readable and writable + binary files into the same variable. These have different types: + + with open(fnam, 'rb') as f: ... + with open(fnam, 'wb') as f: ... + """ + + def __init__(self) -> None: + # Short names of variables bound in with statements using "as" + # in a surrounding scope + self.bound_vars: List[str] = [] + # Names that can't be safely renamed, per scope ('*' means that + # no names can be renamed) + self.skipped: List[Set[str]] = [] + # References to variables that we may need to rename. List of + # scopes; each scope is a mapping from name to list of collections + # of names that refer to the same logical variable. + self.refs: List[Dict[str, List[List[NameExpr]]]] = [] + + def visit_mypy_file(self, file_node: MypyFile) -> None: + """Rename variables within a file. + + This is the main entry point to this class. + """ + with self.enter_scope(): + for d in file_node.defs: + d.accept(self) + + def visit_func_def(self, fdef: FuncDef) -> None: + self.reject_redefinition_of_vars_in_scope() + with self.enter_scope(): + for arg in fdef.arguments: + self.record_skipped(arg.variable.name) + super().visit_func_def(fdef) + + def visit_class_def(self, cdef: ClassDef) -> None: + self.reject_redefinition_of_vars_in_scope() + with self.enter_scope(): + super().visit_class_def(cdef) + + def visit_with_stmt(self, stmt: WithStmt) -> None: + for expr in stmt.expr: + expr.accept(self) + old_len = len(self.bound_vars) + for target in stmt.target: + if target is not None: + self.analyze_lvalue(target) + for target in stmt.target: + if target: + target.accept(self) + stmt.body.accept(self) + + while len(self.bound_vars) > old_len: + self.bound_vars.pop() + + def analyze_lvalue(self, lvalue: Lvalue) -> None: + if isinstance(lvalue, NameExpr): + name = lvalue.name + if name in self.bound_vars: + # Name bound in a surrounding with statement, so it can be renamed + self.visit_name_expr(lvalue) + else: + var_info = self.refs[-1] + if name not in var_info: + var_info[name] = [] + var_info[name].append([]) + self.bound_vars.append(name) + elif isinstance(lvalue, (ListExpr, TupleExpr)): + for item in lvalue.items: + self.analyze_lvalue(item) + elif isinstance(lvalue, MemberExpr): + lvalue.expr.accept(self) + elif isinstance(lvalue, IndexExpr): + lvalue.base.accept(self) + lvalue.index.accept(self) + elif isinstance(lvalue, StarExpr): + self.analyze_lvalue(lvalue.expr) + + def visit_import(self, imp: Import) -> None: + # We don't support renaming imports + for id, as_id in imp.ids: + self.record_skipped(as_id or id) + + def visit_import_from(self, imp: ImportFrom) -> None: + # We don't support renaming imports + for id, as_id in imp.names: + self.record_skipped(as_id or id) + + def visit_import_all(self, imp: ImportAll) -> None: + # Give up, since we don't know all imported names yet + self.reject_redefinition_of_vars_in_scope() + + def visit_name_expr(self, expr: NameExpr) -> None: + name = expr.name + if name in self.bound_vars: + # Record reference so that it can be renamed later + for scope in reversed(self.refs): + if name in scope: + scope[name][-1].append(expr) + else: + self.record_skipped(name) + + @contextmanager + def enter_scope(self) -> Iterator[None]: + self.skipped.append(set()) + self.refs.append({}) + yield None + self.flush_refs() + + def reject_redefinition_of_vars_in_scope(self) -> None: + self.record_skipped('*') + + def record_skipped(self, name: str) -> None: + self.skipped[-1].add(name) + + def flush_refs(self) -> None: + ref_dict = self.refs.pop() + skipped = self.skipped.pop() + if '*' not in skipped: + for name, refs in ref_dict.items(): + if len(refs) <= 1 or name in skipped: + continue + # At module top level we must not rename the final definition, + # as it may be publicly visible + to_rename = refs[:-1] + for i, item in enumerate(to_rename): + rename_refs(item, i) + + +def rename_refs(names: List[NameExpr], index: int) -> None: + name = names[0].name + new_name = name + "'" * (index + 1) + for expr in names: + expr.name = new_name diff --git a/test-data/unit/check-python310.test b/test-data/unit/check-python310.test index 4c0324b9bec76..0d4f46d539243 100644 --- a/test-data/unit/check-python310.test +++ b/test-data/unit/check-python310.test @@ -1175,3 +1175,44 @@ def foo(value) -> int: # E: Missing return statement return 1 case 2: return 2 + +[case testWithStatementScopeAndMatchStatement] +from m import A, B + +with A() as x: + pass +with B() as x: \ + # E: Incompatible types in assignment (expression has type "B", variable has type "A") + pass + +with A() as y: + pass +with B() as y: \ + # E: Incompatible types in assignment (expression has type "B", variable has type "A") + pass + +with A() as z: + pass +with B() as z: \ + # E: Incompatible types in assignment (expression has type "B", variable has type "A") + pass + +with A() as zz: + pass +with B() as zz: \ + # E: Incompatible types in assignment (expression has type "B", variable has type "A") + pass + +match x: + case str(y) as z: + zz = y + +[file m.pyi] +from typing import Any + +class A: + def __enter__(self) -> A: ... + def __exit__(self, x, y, z) -> None: ... +class B: + def __enter__(self) -> B: ... + def __exit__(self, x, y, z) -> None: ... diff --git a/test-data/unit/check-statements.test b/test-data/unit/check-statements.test index 62d82f94a6c11..5819ace83603e 100644 --- a/test-data/unit/check-statements.test +++ b/test-data/unit/check-statements.test @@ -1555,7 +1555,6 @@ class LiteralReturn: return False [builtins fixtures/bool.pyi] - [case testWithStmtBoolExitReturnInStub] import stub @@ -1572,6 +1571,370 @@ class C3: def __exit__(self, x, y, z) -> Optional[bool]: pass [builtins fixtures/bool.pyi] +[case testWithStmtScopeBasics] +from m import A, B + +def f1() -> None: + with A() as x: + reveal_type(x) # N: Revealed type is "m.A" + with B() as x: + reveal_type(x) # N: Revealed type is "m.B" + +def f2() -> None: + with A() as x: + reveal_type(x) # N: Revealed type is "m.A" + y = x # Use outside with makes the scope function-level + with B() as x: \ + # E: Incompatible types in assignment (expression has type "B", variable has type "A") + reveal_type(x) # N: Revealed type is "m.A" + +[file m.pyi] +class A: + def __enter__(self) -> A: ... + def __exit__(self, x, y, z) -> None: ... +class B: + def __enter__(self) -> B: ... + def __exit__(self, x, y, z) -> None: ... + +[case testWithStmtScopeAndFuncDef] +from m import A, B + +with A() as x: + reveal_type(x) # N: Revealed type is "m.A" + +def f() -> None: + pass # Don't support function definition in the middle + +with B() as x: \ + # E: Incompatible types in assignment (expression has type "B", variable has type "A") + reveal_type(x) # N: Revealed type is "m.A" + +[file m.pyi] +class A: + def __enter__(self) -> A: ... + def __exit__(self, x, y, z) -> None: ... +class B: + def __enter__(self) -> B: ... + def __exit__(self, x, y, z) -> None: ... + +[case testWithStmtScopeAndFuncDef2] +from m import A, B + +def f() -> None: + pass # function before with is unsupported + +with A() as x: + reveal_type(x) # N: Revealed type is "m.A" + +with B() as x: \ + # E: Incompatible types in assignment (expression has type "B", variable has type "A") + reveal_type(x) # N: Revealed type is "m.A" + +[file m.pyi] +class A: + def __enter__(self) -> A: ... + def __exit__(self, x, y, z) -> None: ... +class B: + def __enter__(self) -> B: ... + def __exit__(self, x, y, z) -> None: ... + +[case testWithStmtScopeAndFuncDef3] +from m import A, B + +with A() as x: + reveal_type(x) # N: Revealed type is "m.A" + +with B() as x: \ + # E: Incompatible types in assignment (expression has type "B", variable has type "A") + reveal_type(x) # N: Revealed type is "m.A" + +def f() -> None: + pass # function after with is unsupported + +[file m.pyi] +class A: + def __enter__(self) -> A: ... + def __exit__(self, x, y, z) -> None: ... +class B: + def __enter__(self) -> B: ... + def __exit__(self, x, y, z) -> None: ... + +[case testWithStmtScopeAndFuncDef4] +from m import A, B + +with A() as x: + def f() -> None: + pass # Function within with is unsupported + + reveal_type(x) # N: Revealed type is "m.A" + +with B() as x: \ + # E: Incompatible types in assignment (expression has type "B", variable has type "A") + reveal_type(x) # N: Revealed type is "m.A" + +[file m.pyi] +class A: + def __enter__(self) -> A: ... + def __exit__(self, x, y, z) -> None: ... +class B: + def __enter__(self) -> B: ... + def __exit__(self, x, y, z) -> None: ... + +[case testWithStmtScopeAndImport1] +from m import A, B, x + +with A() as x: \ + # E: Incompatible types in assignment (expression has type "A", variable has type "B") + reveal_type(x) # N: Revealed type is "m.B" + +with B() as x: + reveal_type(x) # N: Revealed type is "m.B" + +[file m.pyi] +x: B + +class A: + def __enter__(self) -> A: ... + def __exit__(self, x, y, z) -> None: ... +class B: + def __enter__(self) -> B: ... + def __exit__(self, x, y, z) -> None: ... + +[case testWithStmtScopeAndImport2] +from m import A, B +import m as x + +with A() as x: \ + # E: Incompatible types in assignment (expression has type "A", variable has type Module) + pass + +with B() as x: \ + # E: Incompatible types in assignment (expression has type "B", variable has type Module) + pass + +[file m.pyi] +class A: + def __enter__(self) -> A: ... + def __exit__(self, x, y, z) -> None: ... +class B: + def __enter__(self) -> B: ... + def __exit__(self, x, y, z) -> None: ... +[builtins fixtures/module.pyi] + +[case testWithStmtScopeAndImportStar] +from m import A, B +from m import * + +with A() as x: + pass + +with B() as x: \ + # E: Incompatible types in assignment (expression has type "B", variable has type "A") + pass + +[file m.pyi] +class A: + def __enter__(self) -> A: ... + def __exit__(self, x, y, z) -> None: ... +class B: + def __enter__(self) -> B: ... + def __exit__(self, x, y, z) -> None: ... + +[case testWithStmtScopeNestedWith1] +from m import A, B + +with A() as x: + with B() as x: \ + # E: Incompatible types in assignment (expression has type "B", variable has type "A") + reveal_type(x) # N: Revealed type is "m.A" + +with B() as x: + with A() as x: \ + # E: Incompatible types in assignment (expression has type "A", variable has type "B") + reveal_type(x) # N: Revealed type is "m.B" + +[file m.pyi] +class A: + def __enter__(self) -> A: ... + def __exit__(self, x, y, z) -> None: ... +class B: + def __enter__(self) -> B: ... + def __exit__(self, x, y, z) -> None: ... + +[case testWithStmtScopeNestedWith2] +from m import A, B + +with A() as x: + with A() as y: + reveal_type(y) # N: Revealed type is "m.A" + with B() as y: + reveal_type(y) # N: Revealed type is "m.B" + +[file m.pyi] +class A: + def __enter__(self) -> A: ... + def __exit__(self, x, y, z) -> None: ... +class B: + def __enter__(self) -> B: ... + def __exit__(self, x, y, z) -> None: ... + +[case testWithStmtScopeInnerAndOuterScopes] +from m import A, B + +x = A() # Outer scope should have no impact + +with A() as x: + pass + +def f() -> None: + with A() as x: + reveal_type(x) # N: Revealed type is "m.A" + with B() as x: + reveal_type(x) # N: Revealed type is "m.B" + +y = x + +with A() as x: + pass + +[file m.pyi] +class A: + def __enter__(self) -> A: ... + def __exit__(self, x, y, z) -> None: ... +class B: + def __enter__(self) -> B: ... + def __exit__(self, x, y, z) -> None: ... + +[case testWithStmtScopeMultipleContextManagers] +from m import A, B + +with A() as x, B() as y: + reveal_type(x) # N: Revealed type is "m.A" + reveal_type(y) # N: Revealed type is "m.B" +with B() as x, A() as y: + reveal_type(x) # N: Revealed type is "m.B" + reveal_type(y) # N: Revealed type is "m.A" + +[file m.pyi] +class A: + def __enter__(self) -> A: ... + def __exit__(self, x, y, z) -> None: ... +class B: + def __enter__(self) -> B: ... + def __exit__(self, x, y, z) -> None: ... + +[case testWithStmtScopeMultipleAssignment] +from m import A, B + +with A() as (x, y): + reveal_type(x) # N: Revealed type is "m.A" + reveal_type(y) # N: Revealed type is "builtins.int" +with B() as [x, y]: + reveal_type(x) # N: Revealed type is "m.B" + reveal_type(y) # N: Revealed type is "builtins.str" + +[file m.pyi] +from typing import Tuple + +class A: + def __enter__(self) -> Tuple[A, int]: ... + def __exit__(self, x, y, z) -> None: ... +class B: + def __enter__(self) -> Tuple[B, str]: ... + def __exit__(self, x, y, z) -> None: ... +[builtins fixtures/tuple.pyi] + +[case testWithStmtScopeComplexAssignments] +from m import A, B, f + +with A() as x: + pass +with B() as x: \ + # E: Incompatible types in assignment (expression has type "B", variable has type "A") + pass +with B() as f(x).x: + pass + +with A() as y: + pass +with B() as y: \ + # E: Incompatible types in assignment (expression has type "B", variable has type "A") + pass +with B() as f(y)[0]: + pass + +[file m.pyi] +def f(x): ... + +class A: + def __enter__(self) -> A: ... + def __exit__(self, x, y, z) -> None: ... +class B: + def __enter__(self) -> B: ... + def __exit__(self, x, y, z) -> None: ... + +[case testWithStmtScopeAndClass] +from m import A, B + +with A() as x: + pass + +class C: + with A() as y: + pass + with B() as y: + pass + +with B() as x: \ + # E: Incompatible types in assignment (expression has type "B", variable has type "A") + pass + +[file m.pyi] +class A: + def __enter__(self) -> A: ... + def __exit__(self, x, y, z) -> None: ... +class B: + def __enter__(self) -> B: ... + def __exit__(self, x, y, z) -> None: ... + +[case testWithStmtScopeInnerScopeReference] +from m import A, B + +with A() as x: + def f() -> A: + return x + f() + +with B() as x: \ + # E: Incompatible types in assignment (expression has type "B", variable has type "A") + pass +[file m.pyi] +class A: + def __enter__(self) -> A: ... + def __exit__(self, x, y, z) -> None: ... +class B: + def __enter__(self) -> B: ... + def __exit__(self, x, y, z) -> None: ... + +[case testWithStmtScopeAndLambda] +from m import A, B + +# This is technically not correct, since the lambda can outlive the with +# statement, but this behavior seems more intuitive. + +with A() as x: + lambda: reveal_type(x) # N: Revealed type is "m.A" + +with B() as x: + pass +[file m.pyi] +class A: + def __enter__(self) -> A: ... + def __exit__(self, x, y, z) -> None: ... +class B: + def __enter__(self) -> B: ... + def __exit__(self, x, y, z) -> None: ... + -- Chained assignment -- ------------------ diff --git a/test-data/unit/semanal-statements.test b/test-data/unit/semanal-statements.test index 97dd5f048834d..fdc5ca2bbbdd9 100644 --- a/test-data/unit/semanal-statements.test +++ b/test-data/unit/semanal-statements.test @@ -1058,3 +1058,59 @@ MypyFile:1( AssignmentStmt:6( NameExpr(x [__main__.x]) StrExpr())) + +[case testSimpleWithRenaming] +with 0 as y: + z = y +with 1 as y: + y = 1 +[out] +MypyFile:1( + WithStmt:1( + Expr( + IntExpr(0)) + Target( + NameExpr(y'* [__main__.y'])) + Block:1( + AssignmentStmt:2( + NameExpr(z* [__main__.z]) + NameExpr(y' [__main__.y'])))) + WithStmt:3( + Expr( + IntExpr(1)) + Target( + NameExpr(y* [__main__.y])) + Block:3( + AssignmentStmt:4( + NameExpr(y [__main__.y]) + IntExpr(1))))) + +[case testSimpleWithRenamingFailure] +with 0 as y: + z = y +zz = y +with 1 as y: + y = 1 +[out] +MypyFile:1( + WithStmt:1( + Expr( + IntExpr(0)) + Target( + NameExpr(y* [__main__.y])) + Block:1( + AssignmentStmt:2( + NameExpr(z* [__main__.z]) + NameExpr(y [__main__.y])))) + AssignmentStmt:3( + NameExpr(zz* [__main__.zz]) + NameExpr(y [__main__.y])) + WithStmt:4( + Expr( + IntExpr(1)) + Target( + NameExpr(y [__main__.y])) + Block:4( + AssignmentStmt:5( + NameExpr(y [__main__.y]) + IntExpr(1))))) From feca706d5f2540003ae8b24009d56dac7c067eba Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 25 Feb 2022 23:18:10 +0000 Subject: [PATCH 139/377] renaming: minor comment tweaks (#12255) --- mypy/renaming.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mypy/renaming.py b/mypy/renaming.py index aa16d6dc8dd20..ae21631f0f0ae 100644 --- a/mypy/renaming.py +++ b/mypy/renaming.py @@ -422,10 +422,10 @@ def __init__(self) -> None: # Short names of variables bound in with statements using "as" # in a surrounding scope self.bound_vars: List[str] = [] - # Names that can't be safely renamed, per scope ('*' means that + # Stack of names that can't be safely renamed, per scope ('*' means that # no names can be renamed) self.skipped: List[Set[str]] = [] - # References to variables that we may need to rename. List of + # References to variables that we may need to rename. Stack of # scopes; each scope is a mapping from name to list of collections # of names that refer to the same logical variable. self.refs: List[Dict[str, List[List[NameExpr]]]] = [] From e7846480501d816f938f82932f937683621247b9 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Sun, 27 Feb 2022 22:33:50 +0000 Subject: [PATCH 140/377] stubtest: do not error if a stub is async, but runtime is not (#12234) --- mypy/stubtest.py | 29 ++++++++--------------------- mypy/test/teststubtest.py | 11 ++++++----- 2 files changed, 14 insertions(+), 26 deletions(-) diff --git a/mypy/stubtest.py b/mypy/stubtest.py index e15a5503ab118..a08b0aac10979 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -700,18 +700,6 @@ def _verify_signature( yield 'runtime does not have **kwargs argument "{}"'.format(stub.varkw.variable.name) -def _verify_coroutine( - stub: nodes.FuncItem, runtime: Any, *, runtime_is_coroutine: bool -) -> Optional[str]: - if stub.is_coroutine: - if not runtime_is_coroutine: - return 'is an "async def" function in the stub, but not at runtime' - else: - if runtime_is_coroutine: - return 'is an "async def" function at runtime, but not in the stub' - return None - - @verify.register(nodes.FuncItem) def verify_funcitem( stub: nodes.FuncItem, runtime: MaybeMissing[Any], object_path: List[str] @@ -735,21 +723,20 @@ def verify_funcitem( stub_sig = Signature.from_funcitem(stub) runtime_sig = Signature.from_inspect_signature(signature) runtime_sig_desc = f'{"async " if runtime_is_coroutine else ""}def {signature}' + stub_desc = f'def {stub_sig!r}' else: - runtime_sig_desc = None - - coroutine_mismatch_error = _verify_coroutine( - stub, - runtime, - runtime_is_coroutine=runtime_is_coroutine - ) + runtime_sig_desc, stub_desc = None, None - if coroutine_mismatch_error is not None: + # Don't raise an error if the stub is a coroutine, but the runtime isn't. + # That results in false positives. + # See https://github.com/python/typeshed/issues/7344 + if runtime_is_coroutine and not stub.is_coroutine: yield Error( object_path, - coroutine_mismatch_error, + 'is an "async def" function at runtime, but not in the stub', stub, runtime, + stub_desc=stub_desc, runtime_desc=runtime_sig_desc ) diff --git a/mypy/test/teststubtest.py b/mypy/test/teststubtest.py index 9cdb12afdf072..fa7505e371918 100644 --- a/mypy/test/teststubtest.py +++ b/mypy/test/teststubtest.py @@ -209,16 +209,17 @@ class X: @collect_cases def test_coroutines(self) -> Iterator[Case]: - yield Case( - stub="async def foo() -> int: ...", - runtime="def foo(): return 5", - error="foo", - ) yield Case( stub="def bar() -> int: ...", runtime="async def bar(): return 5", error="bar", ) + # Don't error for this one -- we get false positives otherwise + yield Case( + stub="async def foo() -> int: ...", + runtime="def foo(): return 5", + error=None, + ) yield Case( stub="def baz() -> int: ...", runtime="def baz(): return 5", From feab20938d8e0ac66c4d3b270c26f9e9545eb63f Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Mon, 28 Feb 2022 15:09:52 +0300 Subject: [PATCH 141/377] Fix enum regression #12258 (#12260) Closes #12258 Closes #12262 --- mypy/checker.py | 41 +++++++++++++------- test-data/unit/check-enum.test | 71 +++++++++++++++++++++++++++++----- 2 files changed, 89 insertions(+), 23 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index db229e274ab72..851f23185f4fa 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -1838,6 +1838,7 @@ def visit_class_def(self, defn: ClassDef) -> None: if base.is_enum and base.fullname not in ENUM_BASES: self.check_final_enum(defn, base) self.check_enum_bases(defn) + self.check_enum_new(defn) def check_final_deletable(self, typ: TypeInfo) -> None: # These checks are only for mypyc. Only perform some checks that are easier @@ -1934,9 +1935,8 @@ def is_final_enum_value(self, sym: SymbolTableNode) -> bool: def check_enum_bases(self, defn: ClassDef) -> None: enum_base: Optional[Instance] = None - data_base: Optional[Instance] = None for base in defn.info.bases: - if enum_base is None and base.type.fullname in ENUM_BASES: + if enum_base is None and base.type.is_enum: enum_base = base continue elif enum_base is not None: @@ -1946,23 +1946,36 @@ def check_enum_bases(self, defn: ClassDef) -> None: ) break - # This might not be 100% correct, because runtime `__new__` - # and `__new__` from `typeshed` are sometimes different, - # but it is good enough. - new_method = base.type.get('__new__') - if (data_base is None - and enum_base is None # data type is always before `Enum` - and new_method - and new_method.node - and new_method.node.fullname != 'builtins.object.__new__'): - data_base = base - continue - elif data_base is not None: + def check_enum_new(self, defn: ClassDef) -> None: + def has_new_method(info: TypeInfo) -> bool: + new_method = info.get('__new__') + return bool( + new_method + and new_method.node + and new_method.node.fullname != 'builtins.object.__new__' + ) + + has_new = False + for base in defn.info.bases: + candidate = False + + if base.type.is_enum: + # If we have an `Enum`, then we need to check all its bases. + candidate = any( + not b.is_enum and has_new_method(b) + for b in base.type.mro[1:-1] + ) + else: + candidate = has_new_method(base.type) + + if candidate and has_new: self.fail( 'Only a single data type mixin is allowed for Enum subtypes, ' 'found extra "{}"'.format(base), defn, ) + elif candidate: + has_new = True def check_protocol_variance(self, defn: ClassDef) -> None: """Check that protocol definition is compatible with declared diff --git a/test-data/unit/check-enum.test b/test-data/unit/check-enum.test index e1dec9aec86fc..78460909cd6a7 100644 --- a/test-data/unit/check-enum.test +++ b/test-data/unit/check-enum.test @@ -1905,6 +1905,9 @@ class Mixin: # Correct Enums: +class Correct0(enum.Enum): + pass + class Correct1(Mixin, First, enum.Enum): pass @@ -1917,8 +1920,29 @@ class Correct3(Mixin, enum.Enum): class RegularClass(Mixin, First, Second): pass +# Correct inheritance: + +class _InheritingDataAndMixin(Correct1): + pass + +class _CorrectWithData(First, Correct0): + pass + +class _CorrectWithDataAndMixin(Mixin, First, Correct0): + pass + +class _CorrectWithMixin(Mixin, Correct2): + pass + # Wrong Enums: +class TwoDataTypesViaInheritance(Second, Correct2): # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Correct2" + pass + +class TwoDataTypesViaInheritanceAndMixin(Second, Correct2, Mixin): # E: No base classes are allowed after "__main__.Correct2" \ + # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Correct2" + pass + class MixinAfterEnum1(enum.Enum, Mixin): # E: No base classes are allowed after "enum.Enum" pass @@ -1928,27 +1952,56 @@ class MixinAfterEnum2(First, enum.Enum, Mixin): # E: No base classes are allowe class TwoDataTypes(First, Second, enum.Enum): # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second" pass -class TwoDataTypesAndIntEnumMixin(First, Second, enum.IntEnum, Mixin): # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second" \ - # E: No base classes are allowed after "enum.IntEnum" +class TwoDataTypesAndIntEnumMixin(First, Second, enum.IntEnum, Mixin): # E: No base classes are allowed after "enum.IntEnum" \ + # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second" pass class ThreeDataTypes(First, Second, Third, enum.Enum): # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second" \ - # E: # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Third" + # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Third" pass -class ThreeDataTypesAndMixin(First, Second, Third, enum.Enum, Mixin): # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second" \ - # E: # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Third" \ - # E: No base classes are allowed after "enum.Enum" +class ThreeDataTypesAndMixin(First, Second, Third, enum.Enum, Mixin): # E: No base classes are allowed after "enum.Enum" \ + # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second" \ + # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Third" pass -class FromEnumAndOther1(Correct2, Second, enum.Enum): # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second" +class FromEnumAndOther1(Correct2, Second, enum.Enum): # E: No base classes are allowed after "__main__.Correct2" \ + # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second" pass -class FromEnumAndOther2(Correct2, Second): # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second" +class FromEnumAndOther2(Correct2, Second): # E: No base classes are allowed after "__main__.Correct2" \ + # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second" pass [builtins fixtures/tuple.pyi] -[case testEnumtValueUnionSimplification] +[case testRegression12258] +from enum import Enum + +class MyEnum(Enum): ... + +class BytesEnum(bytes, MyEnum): ... # Should be ok +[builtins fixtures/tuple.pyi] + +[case testEnumWithNewHierarchy] +import enum + +class A: + def __new__(cls, val): ... +class B(A): + def __new__(cls, val): ... +class C: + def __new__(cls, val): ... + +class E1(A, enum.Enum): ... +class E2(B, enum.Enum): ... + +# Errors: + +class W1(C, E1): ... # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.E1" +class W2(C, E2): ... # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.E2" +[builtins fixtures/tuple.pyi] + +[case testEnumValueUnionSimplification] from enum import IntEnum from typing import Any From 187f39461df068766a3129fa99ac376fc5a7143b Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Tue, 1 Mar 2022 02:31:09 -0800 Subject: [PATCH 142/377] Remove orjson stubs from default list (#12264) See https://github.com/python/typeshed/issues/5863 Co-authored-by: hauntsaninja <> --- mypy/stubinfo.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mypy/stubinfo.py b/mypy/stubinfo.py index 9945a12c121f8..d1bcb4a6c157f 100644 --- a/mypy/stubinfo.py +++ b/mypy/stubinfo.py @@ -59,7 +59,6 @@ def is_legacy_bundled_package(prefix: str, py_version: int) -> bool: 'maxminddb': StubInfo('types-maxminddb'), 'mock': StubInfo('types-mock'), 'OpenSSL': StubInfo('types-pyOpenSSL'), - 'orjson': StubInfo('types-orjson', py_version=3), 'paramiko': StubInfo('types-paramiko'), 'pathlib2': StubInfo('types-pathlib2', py_version=2), 'pkg_resources': StubInfo('types-setuptools', py_version=3), From 26bfc631c1cd25a874cce21c0b08df5e7d939edb Mon Sep 17 00:00:00 2001 From: Purna Chandra Mansingh <42216008+purna135@users.noreply.github.com> Date: Wed, 2 Mar 2022 07:42:56 +0530 Subject: [PATCH 143/377] Improve the "Argument must be a mapping" error message (#12222) Fixes #12070 --- mypy/messages.py | 5 +---- test-data/unit/check-kwargs.test | 7 +++++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mypy/messages.py b/mypy/messages.py index 96cb2f3ae3714..bb69771901056 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -954,11 +954,8 @@ def invalid_keyword_var_arg(self, typ: Type, is_mapping: bool, context: Context) if isinstance(typ, Instance) and is_mapping: self.fail('Keywords must be strings', context) else: - suffix = '' - if isinstance(typ, Instance): - suffix = ', not {}'.format(format_type(typ)) self.fail( - 'Argument after ** must be a mapping{}'.format(suffix), + 'Argument after ** must be a mapping, not {}'.format(format_type(typ)), context, code=codes.ARG_TYPE) def undefined_in_superclass(self, member: str, context: Context) -> None: diff --git a/test-data/unit/check-kwargs.test b/test-data/unit/check-kwargs.test index 7f0b8af3ba0ed..9f8de1265ee7c 100644 --- a/test-data/unit/check-kwargs.test +++ b/test-data/unit/check-kwargs.test @@ -350,12 +350,15 @@ class A: pass [builtins fixtures/dict.pyi] [case testInvalidTypeForKeywordVarArg] -from typing import Dict +# flags: --strict-optional +from typing import Dict, Any, Optional def f(**kwargs: 'A') -> None: pass -d = None # type: Dict[A, A] +d = {} # type: Dict[A, A] f(**d) # E: Keywords must be strings f(**A()) # E: Argument after ** must be a mapping, not "A" class A: pass +kwargs: Optional[Any] +f(**kwargs) # E: Argument after ** must be a mapping, not "Optional[Any]" [builtins fixtures/dict.pyi] [case testPassingKeywordVarArgsToNonVarArgsFunction] From 7b4d72596fadb9da28a932f044834fa07e885668 Mon Sep 17 00:00:00 2001 From: 97littleleaf11 <11172084+97littleleaf11@users.noreply.github.com> Date: Wed, 2 Mar 2022 18:07:39 +0800 Subject: [PATCH 144/377] Remove test case for TypedDict with kwargs (#12273) --- test-data/unit/semanal-typeddict.test | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/test-data/unit/semanal-typeddict.test b/test-data/unit/semanal-typeddict.test index 4a74dc6e1cf3d..b9eb6e0c2b138 100644 --- a/test-data/unit/semanal-typeddict.test +++ b/test-data/unit/semanal-typeddict.test @@ -1,17 +1,5 @@ -- Create Type --- TODO: Implement support for this syntax. ---[case testCanCreateTypedDictTypeWithKeywordArguments] ---from mypy_extensions import TypedDict ---Point = TypedDict('Point', x=int, y=int) ---[builtins fixtures/dict.pyi] ---[out] ---MypyFile:1( --- ImportFrom:1(mypy_extensions, [TypedDict]) --- AssignmentStmt:2( --- NameExpr(Point* [__main__.Point]) --- TypedDictExpr:2(Point))) - -- TODO: Implement support for this syntax. --[case testCanCreateTypedDictTypeWithDictCall] --from mypy_extensions import TypedDict From 68b3b27c2fc47cc01f16d98e7e7d944ad5c0c6be Mon Sep 17 00:00:00 2001 From: 97littleleaf11 <11172084+97littleleaf11@users.noreply.github.com> Date: Thu, 3 Mar 2022 00:07:07 +0800 Subject: [PATCH 145/377] Support universal2 (#10651) --- misc/build_wheel.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/misc/build_wheel.py b/misc/build_wheel.py index 188660e2eefc3..9d34242ead412 100644 --- a/misc/build_wheel.py +++ b/misc/build_wheel.py @@ -44,8 +44,8 @@ def create_environ(python_version: str) -> Dict[str, str]: # When cross-compiling on Intel, it is not possible to test arm64 and # the arm64 part of a universal2 wheel. Warnings will be silenced with # following CIBW_TEST_SKIP - env['CIBW_ARCHS_MACOS'] = "x86_64 arm64" - env['CIBW_TEST_SKIP'] = "*-macosx_arm64" + env['CIBW_ARCHS_MACOS'] = "x86_64 arm64 universal2" + env['CIBW_TEST_SKIP'] = "*-macosx_arm64 *_universal2:arm64" env['CIBW_BUILD_VERBOSITY'] = '1' From 0777c1006c2307f4a3d1cc87462b13cbd2a85435 Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Thu, 3 Mar 2022 07:11:28 +0100 Subject: [PATCH 146/377] Add support for conditionally defined overloads (#10712) ### Description This PR allows users to define overloads conditionally, e.g., based on the Python version. At the moment this is only possible if all overloads are contained in the same block which requires duplications. ```py from typing import overload, Any import sys class A: ... class B: ... if sys.version_info >= (3, 9): class C: ... @overload def func(g: int) -> A: ... @overload def func(g: bytes) -> B: ... if sys.version_info >= (3, 9): @overload def func(g: str) -> C: ... def func(g: Any) -> Any: ... ``` Closes #9744 ## Test Plan Unit tests have been added. ## Limitations Only `if` is supported. Support for `elif` and `else` might be added in the future. However, I believe that the single if as shown in the example is also the most common use case. The change itself is fully backwards compatible, i.e. the current workaround (see below) will continue to function as expected. ~~**Update**: Seems like support for `elif` and `else` is required for the tests to pass.~~ **Update**: Added support for `elif` and `else`. ## Current workaround ```py from typing import overload, Any import sys class A: ... class B: ... if sys.version_info >= (3, 9): class C: ... if sys.version_info >= (3, 9): @overload def func(g: int) -> A: ... @overload def func(g: bytes) -> B: ... @overload def func(g: str) -> C: ... def func(g: Any) -> Any: ... else: @overload def func(g: int) -> A: ... @overload def func(g: bytes) -> B: ... def func(g: Any) -> Any: ... ``` --- docs/source/more_types.rst | 108 ++++ mypy/fastparse.py | 199 +++++- test-data/unit/check-overloading.test | 881 ++++++++++++++++++++++++++ 3 files changed, 1185 insertions(+), 3 deletions(-) diff --git a/docs/source/more_types.rst b/docs/source/more_types.rst index 82a6568afcb29..11c5643705ad5 100644 --- a/docs/source/more_types.rst +++ b/docs/source/more_types.rst @@ -581,6 +581,114 @@ with ``Union[int, slice]`` and ``Union[T, Sequence]``. to returning ``Any`` only if the input arguments also contain ``Any``. +Conditional overloads +--------------------- + +Sometimes it is useful to define overloads conditionally. +Common use cases include types that are unavailable at runtime or that +only exist in a certain Python version. All existing overload rules still apply. +For example, there must be at least two overloads. + +.. note:: + + Mypy can only infer a limited number of conditions. + Supported ones currently include :py:data:`~typing.TYPE_CHECKING`, ``MYPY``, + :ref:`version_and_platform_checks`, and :option:`--always-true ` + and :option:`--always-false ` values. + +.. code-block:: python + + from typing import TYPE_CHECKING, Any, overload + + if TYPE_CHECKING: + class A: ... + class B: ... + + + if TYPE_CHECKING: + @overload + def func(var: A) -> A: ... + + @overload + def func(var: B) -> B: ... + + def func(var: Any) -> Any: + return var + + + reveal_type(func(A())) # Revealed type is "A" + +.. code-block:: python + + # flags: --python-version 3.10 + import sys + from typing import Any, overload + + class A: ... + class B: ... + class C: ... + class D: ... + + + if sys.version_info < (3, 7): + @overload + def func(var: A) -> A: ... + + elif sys.version_info >= (3, 10): + @overload + def func(var: B) -> B: ... + + else: + @overload + def func(var: C) -> C: ... + + @overload + def func(var: D) -> D: ... + + def func(var: Any) -> Any: + return var + + + reveal_type(func(B())) # Revealed type is "B" + reveal_type(func(C())) # No overload variant of "func" matches argument type "C" + # Possible overload variants: + # def func(var: B) -> B + # def func(var: D) -> D + # Revealed type is "Any" + + +.. note:: + + In the last example, mypy is executed with + :option:`--python-version 3.10 `. + Therefore, the condition ``sys.version_info >= (3, 10)`` will match and + the overload for ``B`` will be added. + The overloads for ``A`` and ``C`` are ignored! + The overload for ``D`` is not defined conditionally and thus is also added. + +When mypy cannot infer a condition to be always True or always False, an error is emitted. + +.. code-block:: python + + from typing import Any, overload + + class A: ... + class B: ... + + + def g(bool_var: bool) -> None: + if bool_var: # Condition can't be inferred, unable to merge overloads + @overload + def func(var: A) -> A: ... + + @overload + def func(var: B) -> B: ... + + def func(var: Any) -> Any: ... + + reveal_type(func(A())) # Revealed type is "Any" + + .. _advanced_self: Advanced uses of self-types diff --git a/mypy/fastparse.py b/mypy/fastparse.py index 6de1196fcd812..483e5eb4bc42f 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -44,7 +44,7 @@ from mypy import message_registry, errorcodes as codes from mypy.errors import Errors from mypy.options import Options -from mypy.reachability import mark_block_unreachable +from mypy.reachability import infer_reachability_of_if_statement, mark_block_unreachable from mypy.util import bytes_to_human_readable_repr try: @@ -344,9 +344,19 @@ def fail(self, msg: str, line: int, column: int, - blocker: bool = True) -> None: + blocker: bool = True, + code: codes.ErrorCode = codes.SYNTAX) -> None: if blocker or not self.options.ignore_errors: - self.errors.report(line, column, msg, blocker=blocker, code=codes.SYNTAX) + self.errors.report(line, column, msg, blocker=blocker, code=code) + + def fail_merge_overload(self, node: IfStmt) -> None: + self.fail( + "Condition can't be inferred, unable to merge overloads", + line=node.line, + column=node.column, + blocker=False, + code=codes.MISC, + ) def visit(self, node: Optional[AST]) -> Any: if node is None: @@ -476,12 +486,93 @@ def fix_function_overloads(self, stmts: List[Statement]) -> List[Statement]: ret: List[Statement] = [] current_overload: List[OverloadPart] = [] current_overload_name: Optional[str] = None + last_if_stmt: Optional[IfStmt] = None + last_if_overload: Optional[Union[Decorator, FuncDef, OverloadedFuncDef]] = None + last_if_stmt_overload_name: Optional[str] = None + last_if_unknown_truth_value: Optional[IfStmt] = None + skipped_if_stmts: List[IfStmt] = [] for stmt in stmts: + if_overload_name: Optional[str] = None + if_block_with_overload: Optional[Block] = None + if_unknown_truth_value: Optional[IfStmt] = None + if ( + isinstance(stmt, IfStmt) + and len(stmt.body[0].body) == 1 + and ( + isinstance(stmt.body[0].body[0], (Decorator, OverloadedFuncDef)) + or current_overload_name is not None + and isinstance(stmt.body[0].body[0], FuncDef) + ) + ): + # Check IfStmt block to determine if function overloads can be merged + if_overload_name = self._check_ifstmt_for_overloads(stmt) + if if_overload_name is not None: + if_block_with_overload, if_unknown_truth_value = \ + self._get_executable_if_block_with_overloads(stmt) + if (current_overload_name is not None and isinstance(stmt, (Decorator, FuncDef)) and stmt.name == current_overload_name): + if last_if_stmt is not None: + skipped_if_stmts.append(last_if_stmt) + if last_if_overload is not None: + # Last stmt was an IfStmt with same overload name + # Add overloads to current_overload + if isinstance(last_if_overload, OverloadedFuncDef): + current_overload.extend(last_if_overload.items) + else: + current_overload.append(last_if_overload) + last_if_stmt, last_if_overload = None, None + if last_if_unknown_truth_value: + self.fail_merge_overload(last_if_unknown_truth_value) + last_if_unknown_truth_value = None current_overload.append(stmt) + elif ( + current_overload_name is not None + and isinstance(stmt, IfStmt) + and if_overload_name == current_overload_name + ): + # IfStmt only contains stmts relevant to current_overload. + # Check if stmts are reachable and add them to current_overload, + # otherwise skip IfStmt to allow subsequent overload + # or function definitions. + skipped_if_stmts.append(stmt) + if if_block_with_overload is None: + if if_unknown_truth_value is not None: + self.fail_merge_overload(if_unknown_truth_value) + continue + if last_if_overload is not None: + # Last stmt was an IfStmt with same overload name + # Add overloads to current_overload + if isinstance(last_if_overload, OverloadedFuncDef): + current_overload.extend(last_if_overload.items) + else: + current_overload.append(last_if_overload) + last_if_stmt, last_if_overload = None, None + if isinstance(if_block_with_overload.body[0], OverloadedFuncDef): + current_overload.extend(if_block_with_overload.body[0].items) + else: + current_overload.append( + cast(Union[Decorator, FuncDef], if_block_with_overload.body[0]) + ) else: + if last_if_stmt is not None: + ret.append(last_if_stmt) + last_if_stmt_overload_name = current_overload_name + last_if_stmt, last_if_overload = None, None + last_if_unknown_truth_value = None + + if current_overload and current_overload_name == last_if_stmt_overload_name: + # Remove last stmt (IfStmt) from ret if the overload names matched + # Only happens if no executable block had been found in IfStmt + skipped_if_stmts.append(cast(IfStmt, ret.pop())) + if current_overload and skipped_if_stmts: + # Add bare IfStmt (without overloads) to ret + # Required for mypy to be able to still check conditions + for if_stmt in skipped_if_stmts: + self._strip_contents_from_if_stmt(if_stmt) + ret.append(if_stmt) + skipped_if_stmts = [] if len(current_overload) == 1: ret.append(current_overload[0]) elif len(current_overload) > 1: @@ -495,17 +586,119 @@ def fix_function_overloads(self, stmts: List[Statement]) -> List[Statement]: if isinstance(stmt, Decorator) and not unnamed_function(stmt.name): current_overload = [stmt] current_overload_name = stmt.name + elif ( + isinstance(stmt, IfStmt) + and if_overload_name is not None + ): + current_overload = [] + current_overload_name = if_overload_name + last_if_stmt = stmt + last_if_stmt_overload_name = None + if if_block_with_overload is not None: + last_if_overload = cast( + Union[Decorator, FuncDef, OverloadedFuncDef], + if_block_with_overload.body[0] + ) + last_if_unknown_truth_value = if_unknown_truth_value else: current_overload = [] current_overload_name = None ret.append(stmt) + if current_overload and skipped_if_stmts: + # Add bare IfStmt (without overloads) to ret + # Required for mypy to be able to still check conditions + for if_stmt in skipped_if_stmts: + self._strip_contents_from_if_stmt(if_stmt) + ret.append(if_stmt) if len(current_overload) == 1: ret.append(current_overload[0]) elif len(current_overload) > 1: ret.append(OverloadedFuncDef(current_overload)) + elif last_if_stmt is not None: + ret.append(last_if_stmt) return ret + def _check_ifstmt_for_overloads(self, stmt: IfStmt) -> Optional[str]: + """Check if IfStmt contains only overloads with the same name. + Return overload_name if found, None otherwise. + """ + # Check that block only contains a single Decorator, FuncDef, or OverloadedFuncDef. + # Multiple overloads have already been merged as OverloadedFuncDef. + if not ( + len(stmt.body[0].body) == 1 + and isinstance(stmt.body[0].body[0], (Decorator, FuncDef, OverloadedFuncDef)) + ): + return None + + overload_name = stmt.body[0].body[0].name + if stmt.else_body is None: + return overload_name + + if isinstance(stmt.else_body, Block) and len(stmt.else_body.body) == 1: + # For elif: else_body contains an IfStmt itself -> do a recursive check. + if ( + isinstance(stmt.else_body.body[0], (Decorator, FuncDef, OverloadedFuncDef)) + and stmt.else_body.body[0].name == overload_name + ): + return overload_name + if ( + isinstance(stmt.else_body.body[0], IfStmt) + and self._check_ifstmt_for_overloads(stmt.else_body.body[0]) == overload_name + ): + return overload_name + + return None + + def _get_executable_if_block_with_overloads( + self, stmt: IfStmt + ) -> Tuple[Optional[Block], Optional[IfStmt]]: + """Return block from IfStmt that will get executed. + + Return + 0 -> A block if sure that alternative blocks are unreachable. + 1 -> An IfStmt if the reachability of it can't be inferred, + i.e. the truth value is unknown. + """ + infer_reachability_of_if_statement(stmt, self.options) + if ( + stmt.else_body is None + and stmt.body[0].is_unreachable is True + ): + # always False condition with no else + return None, None + if ( + stmt.else_body is None + or stmt.body[0].is_unreachable is False + and stmt.else_body.is_unreachable is False + ): + # The truth value is unknown, thus not conclusive + return None, stmt + if stmt.else_body.is_unreachable is True: + # else_body will be set unreachable if condition is always True + return stmt.body[0], None + if stmt.body[0].is_unreachable is True: + # body will be set unreachable if condition is always False + # else_body can contain an IfStmt itself (for elif) -> do a recursive check + if isinstance(stmt.else_body.body[0], IfStmt): + return self._get_executable_if_block_with_overloads(stmt.else_body.body[0]) + return stmt.else_body, None + return None, stmt + + def _strip_contents_from_if_stmt(self, stmt: IfStmt) -> None: + """Remove contents from IfStmt. + + Needed to still be able to check the conditions after the contents + have been merged with the surrounding function overloads. + """ + if len(stmt.body) == 1: + stmt.body[0].body = [] + if stmt.else_body and len(stmt.else_body.body) == 1: + if isinstance(stmt.else_body.body[0], IfStmt): + self._strip_contents_from_if_stmt(stmt.else_body.body[0]) + else: + stmt.else_body.body = [] + def in_method_scope(self) -> bool: return self.class_and_function_stack[-2:] == ['C', 'F'] diff --git a/test-data/unit/check-overloading.test b/test-data/unit/check-overloading.test index d13b5fc4b3e64..376ce0e304945 100644 --- a/test-data/unit/check-overloading.test +++ b/test-data/unit/check-overloading.test @@ -5421,3 +5421,884 @@ def f_f(arg: str) -> None: ... @Bad2() # E: "Bad2" not callable def f_f(arg): ... [builtins fixtures/dict.pyi] + + +[case testOverloadIfBasic] +# flags: --always-true True --always-false False +from typing import overload + +class A: ... +class B: ... +class C: ... +class D: ... + +# ----- +# Test basic overload merging +# ----- + +@overload +def f1(g: A) -> A: ... +if True: + @overload + def f1(g: B) -> B: ... +def f1(g): ... +reveal_type(f1(A())) # N: Revealed type is "__main__.A" +reveal_type(f1(B())) # N: Revealed type is "__main__.B" + +@overload +def f2(g: A) -> A: ... +@overload +def f2(g: B) -> B: ... +if False: + @overload + def f2(g: C) -> C: ... +def f2(g): ... +reveal_type(f2(A())) # N: Revealed type is "__main__.A" +reveal_type(f2(C())) # E: No overload variant of "f2" matches argument type "C" \ + # N: Possible overload variants: \ + # N: def f2(g: A) -> A \ + # N: def f2(g: B) -> B \ + # N: Revealed type is "Any" + +@overload +def f3(g: A) -> A: ... +@overload +def f3(g: B) -> B: ... +if maybe_true: # E: Condition cannot be inferred, unable to merge overloads \ + # E: Name "maybe_true" is not defined + @overload + def f3(g: C) -> C: ... +def f3(g): ... +reveal_type(f3(A())) # N: Revealed type is "__main__.A" +reveal_type(f3(C())) # E: No overload variant of "f3" matches argument type "C" \ + # N: Possible overload variants: \ + # N: def f3(g: A) -> A \ + # N: def f3(g: B) -> B \ + # N: Revealed type is "Any" + +if True: + @overload + def f4(g: A) -> A: ... +if True: + @overload + def f4(g: B) -> B: ... +@overload +def f4(g: C) -> C: ... +def f4(g): ... +reveal_type(f4(A())) # N: Revealed type is "__main__.A" +reveal_type(f4(B())) # N: Revealed type is "__main__.B" +reveal_type(f4(C())) # N: Revealed type is "__main__.C" + +if True: + @overload + def f5(g: A) -> A: ... +@overload +def f5(g: B) -> B: ... +if True: + @overload + def f5(g: C) -> C: ... +@overload +def f5(g: D) -> D: ... +def f5(g): ... +reveal_type(f5(A())) # N: Revealed type is "__main__.A" +reveal_type(f5(B())) # N: Revealed type is "__main__.B" +reveal_type(f5(C())) # N: Revealed type is "__main__.C" +reveal_type(f5(D())) # N: Revealed type is "__main__.D" + +[case testOverloadIfSysVersion] +# flags: --python-version 3.9 +from typing import overload +import sys + +class A: ... +class B: ... +class C: ... + +# ----- +# "Real" world example +# Test overload merging for sys.version_info +# ----- + +@overload +def f1(g: A) -> A: ... +if sys.version_info >= (3, 9): + @overload + def f1(g: B) -> B: ... +def f1(g): ... +reveal_type(f1(A())) # N: Revealed type is "__main__.A" +reveal_type(f1(B())) # N: Revealed type is "__main__.B" + +@overload +def f2(g: A) -> A: ... +@overload +def f2(g: B) -> B: ... +if sys.version_info >= (3, 10): + @overload + def f2(g: C) -> C: ... +def f2(g): ... +reveal_type(f2(A())) # N: Revealed type is "__main__.A" +reveal_type(f2(C())) # E: No overload variant of "f2" matches argument type "C" \ + # N: Possible overload variants: \ + # N: def f2(g: A) -> A \ + # N: def f2(g: B) -> B \ + # N: Revealed type is "Any" +[builtins fixtures/ops.pyi] + +[case testOverloadIfMerging] +# flags: --always-true True +from typing import overload + +class A: ... +class B: ... +class C: ... + +# ----- +# Test overload merging +# ----- + +@overload +def f1(g: A) -> A: ... +if True: + # Some comment + @overload + def f1(g: B) -> B: ... +def f1(g): ... +reveal_type(f1(A())) # N: Revealed type is "__main__.A" +reveal_type(f1(B())) # N: Revealed type is "__main__.B" + +@overload +def f2(g: A) -> A: ... +if True: + @overload + def f2(g: bytes) -> B: ... + @overload + def f2(g: B) -> C: ... +def f2(g): ... +reveal_type(f2(A())) # N: Revealed type is "__main__.A" +reveal_type(f2(B())) # N: Revealed type is "__main__.C" + +@overload +def f3(g: A) -> A: ... +@overload +def f3(g: B) -> B: ... +if True: + def f3(g): ... +reveal_type(f3(A())) # N: Revealed type is "__main__.A" +reveal_type(f3(B())) # N: Revealed type is "__main__.B" + +if True: + @overload + def f4(g: A) -> A: ... +@overload +def f4(g: B) -> B: ... +def f4(g): ... +reveal_type(f4(A())) # N: Revealed type is "__main__.A" +reveal_type(f4(B())) # N: Revealed type is "__main__.B" + +if True: + # Some comment + @overload + def f5(g: A) -> A: ... + @overload + def f5(g: B) -> B: ... +def f5(g): ... +reveal_type(f5(A())) # N: Revealed type is "__main__.A" +reveal_type(f5(B())) # N: Revealed type is "__main__.B" + +[case testOverloadIfNotMerging] +# flags: --always-true True +from typing import overload + +class A: ... +class B: ... +class C: ... + +# ----- +# Don't merge if IfStmt contains nodes other than overloads +# ----- + +@overload # E: An overloaded function outside a stub file must have an implementation +def f1(g: A) -> A: ... +@overload +def f1(g: B) -> B: ... +if True: + @overload # E: Name "f1" already defined on line 12 \ + # E: Single overload definition, multiple required + def f1(g: C) -> C: ... + pass # Some other action +def f1(g): ... # E: Name "f1" already defined on line 12 +reveal_type(f1(A())) # N: Revealed type is "__main__.A" +reveal_type(f1(C())) # E: No overload variant of "f1" matches argument type "C" \ + # N: Possible overload variants: \ + # N: def f1(g: A) -> A \ + # N: def f1(g: B) -> B \ + # N: Revealed type is "Any" + +if True: + pass # Some other action + @overload # E: Single overload definition, multiple required + def f2(g: A) -> A: ... +@overload # E: Name "f2" already defined on line 26 +def f2(g: B) -> B: ... +@overload +def f2(g: C) -> C: ... +def f2(g): ... +reveal_type(f2(A())) # N: Revealed type is "__main__.A" +reveal_type(f2(C())) # N: Revealed type is "__main__.A" \ + # E: Argument 1 to "f2" has incompatible type "C"; expected "A" + +[case testOverloadIfOldStyle] +# flags: --always-false var_false --always-true var_true +from typing import overload + +class A: ... +class B: ... + +# ----- +# Test old style to make sure it still works +# ----- + +var_true = True +var_false = False + +if var_false: + @overload + def f1(g: A) -> A: ... + @overload + def f1(g: B) -> B: ... + def f1(g): ... +elif var_true: + @overload + def f1(g: A) -> A: ... + @overload + def f1(g: B) -> B: ... + def f1(g): ... +else: + @overload + def f1(g: A) -> A: ... + @overload + def f1(g: B) -> B: ... + def f1(g): ... +reveal_type(f1(A())) # N: Revealed type is "__main__.A" +reveal_type(f1(B())) # N: Revealed type is "__main__.B" + +[case testOverloadIfElse] +# flags: --always-true True --always-false False +from typing import overload + +class A: ... +class B: ... +class C: ... +class D: ... + +# ----- +# Match the first always-true block +# ----- + +@overload +def f1(x: A) -> A: ... +if True: + @overload + def f1(x: B) -> B: ... +elif False: + @overload + def f1(x: C) -> C: ... +else: + @overload + def f1(x: D) -> D: ... +def f1(x): ... +reveal_type(f1(A())) # N: Revealed type is "__main__.A" +reveal_type(f1(B())) # N: Revealed type is "__main__.B" +reveal_type(f1(C())) # E: No overload variant of "f1" matches argument type "C" \ + # N: Possible overload variants: \ + # N: def f1(x: A) -> A \ + # N: def f1(x: B) -> B \ + # N: Revealed type is "Any" + +@overload +def f2(x: A) -> A: ... +if False: + @overload + def f2(x: B) -> B: ... +elif True: + @overload + def f2(x: C) -> C: ... +else: + @overload + def f2(x: D) -> D: ... +def f2(x): ... +reveal_type(f2(A())) # N: Revealed type is "__main__.A" +reveal_type(f2(B())) # E: No overload variant of "f2" matches argument type "B" \ + # N: Possible overload variants: \ + # N: def f2(x: A) -> A \ + # N: def f2(x: C) -> C \ + # N: Revealed type is "Any" +reveal_type(f2(C())) # N: Revealed type is "__main__.C" + +@overload +def f3(x: A) -> A: ... +if False: + @overload + def f3(x: B) -> B: ... +elif False: + @overload + def f3(x: C) -> C: ... +else: + @overload + def f3(x: D) -> D: ... +def f3(x): ... +reveal_type(f3(A())) # N: Revealed type is "__main__.A" +reveal_type(f3(C())) # E: No overload variant of "f3" matches argument type "C" \ + # N: Possible overload variants: \ + # N: def f3(x: A) -> A \ + # N: def f3(x: D) -> D \ + # N: Revealed type is "Any" +reveal_type(f3(D())) # N: Revealed type is "__main__.D" + +[case testOverloadIfElse2] +# flags: --always-true True +from typing import overload + +class A: ... +class B: ... +class C: ... +class D: ... + +# ----- +# Match the first always-true block +# Don't merge overloads if can't be certain about execution of block +# ----- + +@overload +def f1(x: A) -> A: ... +if True: + @overload + def f1(x: B) -> B: ... +else: + @overload + def f1(x: D) -> D: ... +def f1(x): ... +reveal_type(f1(A())) # N: Revealed type is "__main__.A" +reveal_type(f1(B())) # N: Revealed type is "__main__.B" +reveal_type(f1(D())) # E: No overload variant of "f1" matches argument type "D" \ + # N: Possible overload variants: \ + # N: def f1(x: A) -> A \ + # N: def f1(x: B) -> B \ + # N: Revealed type is "Any" + +@overload +def f2(x: A) -> A: ... +if True: + @overload + def f2(x: B) -> B: ... +elif maybe_true: + @overload + def f2(x: C) -> C: ... +else: + @overload + def f2(x: D) -> D: ... +def f2(x): ... +reveal_type(f2(A())) # N: Revealed type is "__main__.A" +reveal_type(f2(B())) # N: Revealed type is "__main__.B" +reveal_type(f2(C())) # E: No overload variant of "f2" matches argument type "C" \ + # N: Possible overload variants: \ + # N: def f2(x: A) -> A \ + # N: def f2(x: B) -> B \ + # N: Revealed type is "Any" + +@overload # E: Single overload definition, multiple required +def f3(x: A) -> A: ... +if maybe_true: # E: Condition cannot be inferred, unable to merge overloads \ + # E: Name "maybe_true" is not defined + @overload + def f3(x: B) -> B: ... +elif True: + @overload + def f3(x: C) -> C: ... +else: + @overload + def f3(x: D) -> D: ... +def f3(x): ... +reveal_type(f3(A())) # N: Revealed type is "__main__.A" +reveal_type(f3(B())) # E: No overload variant of "f3" matches argument type "B" \ + # N: Possible overload variant: \ + # N: def f3(x: A) -> A \ + # N: Revealed type is "Any" + +@overload # E: Single overload definition, multiple required +def f4(x: A) -> A: ... +if maybe_true: # E: Condition cannot be inferred, unable to merge overloads \ + # E: Name "maybe_true" is not defined + @overload + def f4(x: B) -> B: ... +else: + @overload + def f4(x: D) -> D: ... +def f4(x): ... +reveal_type(f4(A())) # N: Revealed type is "__main__.A" +reveal_type(f4(B())) # E: No overload variant of "f4" matches argument type "B" \ + # N: Possible overload variant: \ + # N: def f4(x: A) -> A \ + # N: Revealed type is "Any" + +[case testOverloadIfElse3] +# flags: --always-false False +from typing import overload + +class A: ... +class B: ... +class C: ... +class D: ... +class E: ... + +# ----- +# Match the first always-true block +# Don't merge overloads if can't be certain about execution of block +# ----- + +@overload +def f1(x: A) -> A: ... +if False: + @overload + def f1(x: B) -> B: ... +else: + @overload + def f1(x: D) -> D: ... +def f1(x): ... +reveal_type(f1(A())) # N: Revealed type is "__main__.A" +reveal_type(f1(B())) # E: No overload variant of "f1" matches argument type "B" \ + # N: Possible overload variants: \ + # N: def f1(x: A) -> A \ + # N: def f1(x: D) -> D \ + # N: Revealed type is "Any" +reveal_type(f1(D())) # N: Revealed type is "__main__.D" + +@overload # E: Single overload definition, multiple required +def f2(x: A) -> A: ... +if False: + @overload + def f2(x: B) -> B: ... +elif maybe_true: # E: Condition cannot be inferred, unable to merge overloads \ + # E: Name "maybe_true" is not defined + @overload + def f2(x: C) -> C: ... +else: + @overload + def f2(x: D) -> D: ... +def f2(x): ... +reveal_type(f2(A())) # N: Revealed type is "__main__.A" +reveal_type(f2(C())) # E: No overload variant of "f2" matches argument type "C" \ + # N: Possible overload variant: \ + # N: def f2(x: A) -> A \ + # N: Revealed type is "Any" + +@overload # E: Single overload definition, multiple required +def f3(x: A) -> A: ... +if maybe_true: # E: Condition cannot be inferred, unable to merge overloads \ + # E: Name "maybe_true" is not defined + @overload + def f3(x: B) -> B: ... +elif False: + @overload + def f3(x: C) -> C: ... +else: + @overload + def f3(x: D) -> D: ... +def f3(x): ... +reveal_type(f3(A())) # N: Revealed type is "__main__.A" +reveal_type(f3(B())) # E: No overload variant of "f3" matches argument type "B" \ + # N: Possible overload variant: \ + # N: def f3(x: A) -> A \ + # N: Revealed type is "Any" + +def g(bool_var: bool) -> None: + @overload + def f4(x: A) -> A: ... + if bool_var: # E: Condition cannot be inferred, unable to merge overloads + @overload + def f4(x: B) -> B: ... + elif maybe_true: # E: Name "maybe_true" is not defined + # No 'Condition cannot be inferred' error here since it's already + # emitted on the first condition, 'bool_var', above. + @overload + def f4(x: C) -> C: ... + else: + @overload + def f4(x: D) -> D: ... + @overload + def f4(x: E) -> E: ... + def f4(x): ... + reveal_type(f4(E())) # N: Revealed type is "__main__.E" + reveal_type(f4(B())) # E: No overload variant of "f4" matches argument type "B" \ + # N: Possible overload variants: \ + # N: def f4(x: A) -> A \ + # N: def f4(x: E) -> E \ + # N: Revealed type is "Any" + +[case testOverloadIfSkipUnknownExecution] +# flags: --always-true True +from typing import overload + +class A: ... +class B: ... +class C: ... +class D: ... + +# ----- +# If blocks should be skipped if execution can't be certain +# Overload name must match outer name +# ----- + +@overload # E: Single overload definition, multiple required +def f1(x: A) -> A: ... +if maybe_true: # E: Condition cannot be inferred, unable to merge overloads \ + # E: Name "maybe_true" is not defined + @overload + def f1(x: B) -> B: ... +def f1(x): ... +reveal_type(f1(A())) # N: Revealed type is "__main__.A" + +if maybe_true: # E: Condition cannot be inferred, unable to merge overloads \ + # E: Name "maybe_true" is not defined + @overload + def f2(x: A) -> A: ... +@overload +def f2(x: B) -> B: ... +@overload +def f2(x: C) -> C: ... +def f2(x): ... +reveal_type(f2(A())) # E: No overload variant of "f2" matches argument type "A" \ + # N: Possible overload variants: \ + # N: def f2(x: B) -> B \ + # N: def f2(x: C) -> C \ + # N: Revealed type is "Any" + +if True: + @overload # E: Single overload definition, multiple required + def f3(x: A) -> A: ... + if maybe_true: # E: Condition cannot be inferred, unable to merge overloads \ + # E: Name "maybe_true" is not defined + @overload + def f3(x: B) -> B: ... + def f3(x): ... +reveal_type(f3(A())) # N: Revealed type is "__main__.A" + +if True: + if maybe_true: # E: Condition cannot be inferred, unable to merge overloads \ + # E: Name "maybe_true" is not defined + @overload + def f4(x: A) -> A: ... + @overload + def f4(x: B) -> B: ... + @overload + def f4(x: C) -> C: ... + def f4(x): ... +reveal_type(f4(A())) # E: No overload variant of "f4" matches argument type "A" \ + # N: Possible overload variants: \ + # N: def f4(x: B) -> B \ + # N: def f4(x: C) -> C \ + # N: Revealed type is "Any" + +[case testOverloadIfDontSkipUnrelatedOverload] +# flags: --always-true True +from typing import overload + +class A: ... +class B: ... +class C: ... +class D: ... + +# ----- +# Don't skip if block if overload name doesn't match outer name +# ----- + +@overload # E: Single overload definition, multiple required +def f1(x: A) -> A: ... +if maybe_true: # E: Name "maybe_true" is not defined + @overload # E: Single overload definition, multiple required + def g1(x: B) -> B: ... +def f1(x): ... # E: Name "f1" already defined on line 13 +reveal_type(f1(A())) # N: Revealed type is "__main__.A" + +if maybe_true: # E: Name "maybe_true" is not defined + @overload # E: Single overload definition, multiple required + def g2(x: A) -> A: ... +@overload +def f2(x: B) -> B: ... +@overload +def f2(x: C) -> C: ... +def f2(x): ... +reveal_type(f2(A())) # E: No overload variant of "f2" matches argument type "A" \ + # N: Possible overload variants: \ + # N: def f2(x: B) -> B \ + # N: def f2(x: C) -> C \ + # N: Revealed type is "Any" + +if True: + @overload # E: Single overload definition, multiple required + def f3(x: A) -> A: ... + if maybe_true: # E: Name "maybe_true" is not defined + @overload # E: Single overload definition, multiple required + def g3(x: B) -> B: ... + def f3(x): ... +reveal_type(f3(A())) # N: Revealed type is "__main__.A" + +if True: + if maybe_true: # E: Name "maybe_true" is not defined + @overload # E: Single overload definition, multiple required + def g4(x: A) -> A: ... + @overload + def f4(x: B) -> B: ... + @overload + def f4(x: C) -> C: ... + def f4(x): ... +reveal_type(f4(A())) # E: No overload variant of "f4" matches argument type "A" \ + # N: Possible overload variants: \ + # N: def f4(x: B) -> B \ + # N: def f4(x: C) -> C \ + # N: Revealed type is "Any" + +[case testOverloadIfNotMergingDifferentNames] +# flags: --always-true True +from typing import overload + +class A: ... +class B: ... +class C: ... +class D: ... + +# ----- +# Don't merge overloads if IfStmts contains overload with different name +# ----- + +@overload # E: An overloaded function outside a stub file must have an implementation +def f1(x: A) -> A: ... +@overload +def f1(x: B) -> B: ... +if True: + @overload # E: Single overload definition, multiple required + def g1(x: C) -> C: ... +def f1(x): ... # E: Name "f1" already defined on line 13 +reveal_type(f1(A())) # N: Revealed type is "__main__.A" +reveal_type(f1(C())) # E: No overload variant of "f1" matches argument type "C" \ + # N: Possible overload variants: \ + # N: def f1(x: A) -> A \ + # N: def f1(x: B) -> B \ + # N: Revealed type is "Any" + +if True: + @overload # E: Single overload definition, multiple required + def g2(x: A) -> A: ... +@overload +def f2(x: B) -> B: ... +@overload +def f2(x: C) -> C: ... +def f2(x): ... +reveal_type(f2(A())) # E: No overload variant of "f2" matches argument type "A" \ + # N: Possible overload variants: \ + # N: def f2(x: B) -> B \ + # N: def f2(x: C) -> C \ + # N: Revealed type is "Any" +reveal_type(f2(B())) # N: Revealed type is "__main__.B" + +if True: + if True: + @overload # E: Single overload definition, multiple required + def g3(x: A) -> A: ... + @overload + def f3(x: B) -> B: ... + @overload + def f3(x: C) -> C: ... + def f3(x): ... +reveal_type(f3(A())) # E: No overload variant of "f3" matches argument type "A" \ + # N: Possible overload variants: \ + # N: def f3(x: B) -> B \ + # N: def f3(x: C) -> C \ + # N: Revealed type is "Any" +reveal_type(f3(B())) # N: Revealed type is "__main__.B" + +[case testOverloadIfSplitFunctionDef] +# flags: --always-true True --always-false False +from typing import overload + +class A: ... +class B: ... +class C: ... +class D: ... + +# ----- +# Test split FuncDefs +# ----- + +@overload +def f1(x: A) -> A: ... +@overload +def f1(x: B) -> B: ... +if True: + def f1(x): ... +reveal_type(f1(A())) # N: Revealed type is "__main__.A" + +@overload +def f2(x: A) -> A: ... +@overload +def f2(x: B) -> B: ... +if False: + def f2(x): ... +else: + def f2(x): ... +reveal_type(f2(A())) # N: Revealed type is "__main__.A" + +@overload # E: An overloaded function outside a stub file must have an implementation +def f3(x: A) -> A: ... +@overload +def f3(x: B) -> B: ... +if True: + def f3(x): ... # E: Name "f3" already defined on line 31 +else: + pass # some other node + def f3(x): ... +reveal_type(f3(A())) # N: Revealed type is "__main__.A" + +[case testOverloadIfMixed] +# flags: --always-true True --always-false False +from typing import overload, TYPE_CHECKING + +class A: ... +class B: ... +class C: ... +class D: ... + +if maybe_var: # E: Name "maybe_var" is not defined + pass +if True: + @overload + def f1(x: A) -> A: ... +@overload +def f1(x: B) -> B: ... +def f1(x): ... +reveal_type(f1(A())) # N: Revealed type is "__main__.A" +reveal_type(f1(B())) # N: Revealed type is "__main__.B" + +if True: + @overload + def f2(x: A) -> A: ... + @overload + def f2(x: B) -> B: ... +def f2(x): ... +reveal_type(f2(A())) # N: Revealed type is "__main__.A" +reveal_type(f2(B())) # N: Revealed type is "__main__.B" + +if True: + @overload + def f3(x: A) -> A: ... + @overload + def f3(x: B) -> B: ... + def f3(x): ... +reveal_type(f3(A())) # N: Revealed type is "__main__.A" +reveal_type(f3(B())) # N: Revealed type is "__main__.B" + +# Don't crash with AssignmentStmt if elif +@overload # E: Single overload definition, multiple required +def f4(x: A) -> A: ... +if False: + @overload + def f4(x: B) -> B: ... +elif True: + var = 1 +def f4(x): ... # E: Name "f4" already defined on line 39 + +if TYPE_CHECKING: + @overload + def f5(x: A) -> A: ... + @overload + def f5(x: B) -> B: ... +def f5(x): ... +reveal_type(f5(A())) # N: Revealed type is "__main__.A" +reveal_type(f5(B())) # N: Revealed type is "__main__.B" + +# Test from check-functions - testUnconditionalRedefinitionOfConditionalFunction +# Don't merge If blocks if they appear before any overloads +# and don't contain any overloads themselves. +if maybe_true: # E: Name "maybe_true" is not defined + def f6(x): ... +def f6(x): ... # E: Name "f6" already defined on line 61 + +if maybe_true: # E: Name "maybe_true" is not defined + pass # Some other node + def f7(x): ... +def f7(x): ... # E: Name "f7" already defined on line 66 + +@overload +def f8(x: A) -> A: ... +@overload +def f8(x: B) -> B: ... +if False: + def f8(x: C) -> C: ... +def f8(x): ... +reveal_type(f8(A())) # N: Revealed type is "__main__.A" +reveal_type(f8(C())) # E: No overload variant of "f8" matches argument type "C" \ + # N: Possible overload variants: \ + # N: def f8(x: A) -> A \ + # N: def f8(x: B) -> B \ + # N: Revealed type is "Any" + +if maybe_true: # E: Condition cannot be inferred, unable to merge overloads \ + # E: Name "maybe_true" is not defined + @overload + def f9(x: A) -> A: ... +if another_maybe_true: # E: Condition cannot be inferred, unable to merge overloads \ + # E: Name "another_maybe_true" is not defined + @overload + def f9(x: B) -> B: ... +@overload +def f9(x: C) -> C: ... +@overload +def f9(x: D) -> D: ... +def f9(x): ... +reveal_type(f9(A())) # E: No overload variant of "f9" matches argument type "A" \ + # N: Possible overload variants: \ + # N: def f9(x: C) -> C \ + # N: def f9(x: D) -> D \ + # N: Revealed type is "Any" +reveal_type(f9(C())) # N: Revealed type is "__main__.C" + +if True: + if maybe_true: # E: Condition cannot be inferred, unable to merge overloads \ + # E: Name "maybe_true" is not defined + @overload + def f10(x: A) -> A: ... + if another_maybe_true: # E: Condition cannot be inferred, unable to merge overloads \ + # E: Name "another_maybe_true" is not defined + @overload + def f10(x: B) -> B: ... + @overload + def f10(x: C) -> C: ... + @overload + def f10(x: D) -> D: ... + def f10(x): ... +reveal_type(f10(A())) # E: No overload variant of "f10" matches argument type "A" \ + # N: Possible overload variants: \ + # N: def f10(x: C) -> C \ + # N: def f10(x: D) -> D \ + # N: Revealed type is "Any" +reveal_type(f10(C())) # N: Revealed type is "__main__.C" + +if some_var: # E: Name "some_var" is not defined + pass +@overload +def f11(x: A) -> A: ... +@overload +def f11(x: B) -> B: ... +def f11(x): ... +reveal_type(f11(A())) # N: Revealed type is "__main__.A" + +if True: + if some_var: # E: Name "some_var" is not defined + pass + @overload + def f12(x: A) -> A: ... + @overload + def f12(x: B) -> B: ... + def f12(x): ... +reveal_type(f12(A())) # N: Revealed type is "__main__.A" +[typing fixtures/typing-medium.pyi] From 73a5b3c2d0224d7d3bfe094309552f6c5c60c6cb Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Thu, 3 Mar 2022 18:57:12 +0100 Subject: [PATCH 147/377] Small doc improvements for conditional overloads (#12283) --- docs/source/more_types.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/source/more_types.rst b/docs/source/more_types.rst index 11c5643705ad5..2203022ad73f1 100644 --- a/docs/source/more_types.rst +++ b/docs/source/more_types.rst @@ -593,7 +593,7 @@ For example, there must be at least two overloads. Mypy can only infer a limited number of conditions. Supported ones currently include :py:data:`~typing.TYPE_CHECKING`, ``MYPY``, - :ref:`version_and_platform_checks`, and :option:`--always-true ` + :ref:`version_and_platform_checks`, :option:`--always-true `, and :option:`--always-false ` values. .. code-block:: python @@ -666,7 +666,8 @@ For example, there must be at least two overloads. The overloads for ``A`` and ``C`` are ignored! The overload for ``D`` is not defined conditionally and thus is also added. -When mypy cannot infer a condition to be always True or always False, an error is emitted. +When mypy cannot infer a condition to be always ``True`` or always ``False``, +an error is emitted. .. code-block:: python From a562f0aac287b1069a8267b3812fb6813eaefec3 Mon Sep 17 00:00:00 2001 From: Stanislav Levin Date: Fri, 4 Mar 2022 11:28:01 +0300 Subject: [PATCH 148/377] stubtest: Fix wrong assumption about relative path (#12282) Fixes https://github.com/python/mypy/issues/11019 `run_stubtest` creates temp directory and prepend `sys.path` with relative path (dot `.`) wrongly assuming that the dot will be resolved to absolute path on *every* import attempt. But in Python dot(`.`) in sys.path is actually resolved by PathFinder and cached in `sys.path_importer_cache` like: ``` sys.path_importer_cache['.'] FileFinder('/somepath/.') ``` later calls for `find_module` return None and import of `test_module` fails. This resulted in only the first test in stubtest's suite passed in non-pytest-xdist environments. This issue was hidden with bug or feature in pytest-xdist < 2.3.0: https://github.com/pytest-dev/pytest-xdist/issues/421 It was fixed in pytest-xdist 2.3.0: https://github.com/pytest-dev/pytest-xdist/pull/667/ - sys.path for pytest-xdist < 2.3.0 `'.', 'project_path', ''` - sys.path for pytest-xdist >= 2.3.0 or without xdist `'.', 'project_path'` In Python for denoting cwd the empty path `''` can be used as a special case, but for readability `sys.path` is prepended with resolved absolute path of temp directory. Also it's essential to restore back `sys.path` after a test to not break subsequent tests. Signed-off-by: Stanislav Levin --- mypy/test/teststubtest.py | 16 +++++++++------- test-requirements.txt | 4 ++-- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/mypy/test/teststubtest.py b/mypy/test/teststubtest.py index fa7505e371918..5de888739be98 100644 --- a/mypy/test/teststubtest.py +++ b/mypy/test/teststubtest.py @@ -16,13 +16,20 @@ @contextlib.contextmanager -def use_tmp_dir() -> Iterator[None]: +def use_tmp_dir(mod_name: str) -> Iterator[None]: current = os.getcwd() + current_syspath = sys.path[:] with tempfile.TemporaryDirectory() as tmp: try: os.chdir(tmp) + if sys.path[0] != tmp: + sys.path.insert(0, tmp) yield finally: + sys.path = current_syspath[:] + if mod_name in sys.modules: + del sys.modules[mod_name] + os.chdir(current) @@ -92,7 +99,7 @@ def staticmethod(f: T) -> T: ... def run_stubtest( stub: str, runtime: str, options: List[str], config_file: Optional[str] = None, ) -> str: - with use_tmp_dir(): + with use_tmp_dir(TEST_MODULE_NAME): with open("builtins.pyi", "w") as f: f.write(stubtest_builtins_stub) with open("typing.pyi", "w") as f: @@ -105,11 +112,6 @@ def run_stubtest( with open("{}_config.ini".format(TEST_MODULE_NAME), "w") as f: f.write(config_file) options = options + ["--mypy-config-file", "{}_config.ini".format(TEST_MODULE_NAME)] - if sys.path[0] != ".": - sys.path.insert(0, ".") - if TEST_MODULE_NAME in sys.modules: - del sys.modules[TEST_MODULE_NAME] - output = io.StringIO() with contextlib.redirect_stdout(output): test_stubs( diff --git a/test-requirements.txt b/test-requirements.txt index d4e21592721b2..f1c0fa68e34f8 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -7,8 +7,8 @@ flake8-pyi>=20.5 lxml>=4.4.0; python_version<'3.11' psutil>=4.0 # pytest 6.2.3 does not support Python 3.10 -pytest>=6.2.4,<7.0.0 -pytest-xdist>=1.34.0,<2.0.0 +pytest>=6.2.4 +pytest-xdist>=1.34.0 pytest-forked>=1.3.0,<2.0.0 pytest-cov>=2.10.0,<3.0.0 py>=1.5.2 From 4d99f7c6ee5bcae4eedb041106943cf29b58ceb3 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Fri, 4 Mar 2022 12:55:24 -0800 Subject: [PATCH 149/377] teststubtest: further fix tests (#12287) Basically a follow up to #12282 Co-authored-by: hauntsaninja <> --- mypy/test/teststubtest.py | 44 ++++++++++++++------------------------- 1 file changed, 16 insertions(+), 28 deletions(-) diff --git a/mypy/test/teststubtest.py b/mypy/test/teststubtest.py index 5de888739be98..759942c57ce73 100644 --- a/mypy/test/teststubtest.py +++ b/mypy/test/teststubtest.py @@ -7,7 +7,6 @@ import tempfile import textwrap import unittest -from pathlib import Path from typing import Any, Callable, Iterator, List, Optional import mypy.stubtest @@ -16,7 +15,7 @@ @contextlib.contextmanager -def use_tmp_dir(mod_name: str) -> Iterator[None]: +def use_tmp_dir(mod_name: str) -> Iterator[str]: current = os.getcwd() current_syspath = sys.path[:] with tempfile.TemporaryDirectory() as tmp: @@ -24,7 +23,7 @@ def use_tmp_dir(mod_name: str) -> Iterator[None]: os.chdir(tmp) if sys.path[0] != tmp: sys.path.insert(0, tmp) - yield + yield tmp finally: sys.path = current_syspath[:] if mod_name in sys.modules: @@ -99,7 +98,7 @@ def staticmethod(f: T) -> T: ... def run_stubtest( stub: str, runtime: str, options: List[str], config_file: Optional[str] = None, ) -> str: - with use_tmp_dir(TEST_MODULE_NAME): + with use_tmp_dir(TEST_MODULE_NAME) as tmp_dir: with open("builtins.pyi", "w") as f: f.write(stubtest_builtins_stub) with open("typing.pyi", "w") as f: @@ -118,10 +117,8 @@ def run_stubtest( parse_options([TEST_MODULE_NAME] + options), use_builtins_fixtures=True ) - - module_path = Path(os.getcwd()) / TEST_MODULE_NAME # remove cwd as it's not available from outside - return output.getvalue().replace(str(module_path), TEST_MODULE_NAME) + return output.getvalue().replace(tmp_dir + os.sep, "") class Case: @@ -780,27 +777,18 @@ def test_dunders(self) -> Iterator[Case]: error=None, ) - def test_not_subclassable(self) -> None: - output = run_stubtest( - stub=( - "class CanBeSubclassed: ...\n" - "class CanNotBeSubclassed:\n" - " def __init_subclass__(cls) -> None: ...\n" - ), - runtime=( - "class CanNotBeSubclassed:\n" - " def __init_subclass__(cls): raise TypeError('nope')\n" - # ctypes.Array can be subclassed, but subclasses must define a few - # special attributes, e.g. _length_ - "from ctypes import Array as CanBeSubclassed\n" - ), - options=[], + @collect_cases + def test_not_subclassable(self) -> Iterator[Case]: + yield Case( + stub="class CanBeSubclassed: ...", + runtime="class CanBeSubclassed: ...", + error=None, + ) + yield Case( + stub="class CannotBeSubclassed:\n def __init_subclass__(cls) -> None: ...", + runtime="class CannotBeSubclassed:\n def __init_subclass__(cls): raise TypeError", + error="CannotBeSubclassed", ) - assert ( - "CanNotBeSubclassed cannot be subclassed at runtime," - " but isn't marked with @final in the stub" - ) in output - assert "CanBeSubclassed cannot be subclassed" not in output @collect_cases def test_name_mangling(self) -> Iterator[Case]: @@ -1114,7 +1102,7 @@ def test_config_file(self) -> None: "plugins={}/test-data/unit/plugins/decimal_to_int.py\n".format(root_dir) ) output = run_stubtest(stub=stub, runtime=runtime, options=[]) - assert output == ( + assert remove_color_code(output) == ( "error: test_module.temp variable differs from runtime type Literal[5]\n" "Stub: at line 2\ndecimal.Decimal\nRuntime:\n5\n\n" ) From b3752a60af3f8e6a1b17c4ebc90ed554cb934288 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Fri, 4 Mar 2022 17:50:44 -0800 Subject: [PATCH 150/377] Revert "stubtest pos-only differences in dunders (#12184)" (#12293) This reverts commit 777885f2c26cce195f6d23c80fefae1e66dfaac2. To help with https://github.com/python/typeshed/issues/7441 and reduce risk of stubtest issues interfering with a mypy release. The extra type correctness here is really minimal. Co-authored-by: hauntsaninja <> --- mypy/stubtest.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mypy/stubtest.py b/mypy/stubtest.py index a08b0aac10979..3320f23707354 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -618,6 +618,7 @@ def _verify_signature( runtime_arg.kind == inspect.Parameter.POSITIONAL_ONLY and not stub_arg.variable.name.startswith("__") and not stub_arg.variable.name.strip("_") == "self" + and not is_dunder(function_name, exclude_special=True) # noisy for dunder methods ): yield ( 'stub argument "{}" should be positional-only ' From c7a81620bef7585cca6905861bb7ef34ec12da2f Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Fri, 4 Mar 2022 22:13:30 -0800 Subject: [PATCH 151/377] stubtest: ignore more dunder positional-only errors (#12294) This isn't actually a reversion. This logic was asymmetrical for reasons lost to time. Although I suspect it was this way because the delta only a few errors on typeshed. What changed was that as a result of #12203 we actually started checking a lot more dunder methods. Previously, we only checked dunders if either: a) it was a special dunder, like `__init__` or `__call__`, or b) the dunder was defined on the actual stub class itself In particular, we started checking every dunder redefined at runtime that the stub just inherited from object. A possible intermediate option would be to not check positional-only arguments in the case where a stub inherits the definition. I'll experiment with that once typeshed CI is green. Co-authored-by: hauntsaninja <> --- mypy/stubtest.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/mypy/stubtest.py b/mypy/stubtest.py index 3320f23707354..b568017cfa5f3 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -288,13 +288,14 @@ class SubClass(runtime): # type: ignore # Examples: ctypes.Array, ctypes._SimpleCData pass - # Check everything already defined in the stub + # Check everything already defined on the stub class itself (i.e. not inherited) to_check = set(stub.names) + # Check all public things on the runtime class to_check.update( # cast to workaround mypyc complaints m for m in cast(Any, vars)(runtime) - if not is_probably_private(m) and m not in ALLOW_MISSING_CLASS_DUNDERS + if not is_probably_private(m) and m not in IGNORABLE_CLASS_DUNDERS ) for entry in sorted(to_check): @@ -629,6 +630,7 @@ def _verify_signature( if ( runtime_arg.kind != inspect.Parameter.POSITIONAL_ONLY and stub_arg.variable.name.startswith("__") + and not is_dunder(function_name, exclude_special=True) # noisy for dunder methods ): yield ( 'stub argument "{}" should be positional or keyword ' @@ -985,16 +987,16 @@ def verify_typealias( } ) -ALLOW_MISSING_CLASS_DUNDERS = frozenset( +IGNORABLE_CLASS_DUNDERS = frozenset( { # Special attributes "__dict__", "__text_signature__", "__weakref__", "__del__", # Only ever called when an object is being deleted, who cares? - # These two are basically useless for type checkers "__hash__", "__getattr__", # resulting behaviour might be typed explicitly + "__setattr__", # defining this on a class can cause worse type checking # isinstance/issubclass hooks that type-checkers don't usually care about "__instancecheck__", "__subclasshook__", From fce1b548be74f7c65f8e3645f2a2b46aeff0c5a8 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Sat, 5 Mar 2022 11:10:47 +0000 Subject: [PATCH 152/377] CI: Do not run mypy_primer on stubtest/stubgen PRs (#12295) PRs that only affect stubtest or stubgen are never going to have any effect on mypy_primer's output, so we can safely skip the CI check for those PRs. The same goes for PRs that only alter files in the tests directory. --- .github/workflows/mypy_primer.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/mypy_primer.yml b/.github/workflows/mypy_primer.yml index 88500b698707b..e65d918228b4e 100644 --- a/.github/workflows/mypy_primer.yml +++ b/.github/workflows/mypy_primer.yml @@ -8,6 +8,10 @@ on: - '**/*.rst' - '**/*.md' - 'mypyc/**' + - 'mypy/stubtest.py' + - 'mypy/stubgen.py' + - 'mypy/stubgenc.py' + - 'mypy/test/**' jobs: mypy_primer: From 226661f62f365102f5fd913b39b32ed3f12e208b Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Mon, 7 Mar 2022 15:11:13 +0000 Subject: [PATCH 153/377] Exhaustiveness checking for match statements (#12267) Closes #12010. Mypy can now detect if a match statement covers all the possible values. Example: ``` def f(x: int | str) -> int: match x: case str(): return 0 case int(): return 1 # Mypy knows that we can't reach here ``` Most of the work was done by @freundTech. I did various minor updates and changes to tests. This doesn't handle some cases properly, including these: 1. We don't recognize that `match [*args]` fully covers a list type 2. Fake intersections don't work quite right (some tests are skipped) 3. We assume enums don't have custom `__eq__` methods Co-authored-by: Adrian Freund --- mypy/checker.py | 85 +++-- mypy/checkpattern.py | 38 +- mypy/patterns.py | 5 + test-data/unit/check-python310.test | 534 ++++++++++++++++++++++------ 4 files changed, 520 insertions(+), 142 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 851f23185f4fa..31dcf985200be 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -4089,36 +4089,57 @@ def visit_match_stmt(self, s: MatchStmt) -> None: if isinstance(subject_type, DeletedType): self.msg.deleted_as_rvalue(subject_type, s) + # We infer types of patterns twice. The first pass is used + # to infer the types of capture variables. The type of a + # capture variable may depend on multiple patterns (it + # will be a union of all capture types). This pass ignores + # guard expressions. pattern_types = [self.pattern_checker.accept(p, subject_type) for p in s.patterns] - type_maps: List[TypeMap] = [t.captures for t in pattern_types] - self.infer_variable_types_from_type_maps(type_maps) + inferred_types = self.infer_variable_types_from_type_maps(type_maps) - for pattern_type, g, b in zip(pattern_types, s.guards, s.bodies): + # The second pass narrows down the types and type checks bodies. + for p, g, b in zip(s.patterns, s.guards, s.bodies): + current_subject_type = self.expr_checker.narrow_type_from_binder(s.subject, + subject_type) + pattern_type = self.pattern_checker.accept(p, current_subject_type) with self.binder.frame_context(can_skip=True, fall_through=2): if b.is_unreachable or isinstance(get_proper_type(pattern_type.type), UninhabitedType): self.push_type_map(None) + else_map: TypeMap = {} else: - self.binder.put(s.subject, pattern_type.type) + pattern_map, else_map = conditional_types_to_typemaps( + s.subject, + pattern_type.type, + pattern_type.rest_type + ) + self.remove_capture_conflicts(pattern_type.captures, + inferred_types) + self.push_type_map(pattern_map) self.push_type_map(pattern_type.captures) if g is not None: - gt = get_proper_type(self.expr_checker.accept(g)) + with self.binder.frame_context(can_skip=True, fall_through=3): + gt = get_proper_type(self.expr_checker.accept(g)) - if isinstance(gt, DeletedType): - self.msg.deleted_as_rvalue(gt, s) + if isinstance(gt, DeletedType): + self.msg.deleted_as_rvalue(gt, s) - if_map, _ = self.find_isinstance_check(g) + guard_map, guard_else_map = self.find_isinstance_check(g) + else_map = or_conditional_maps(else_map, guard_else_map) - self.push_type_map(if_map) - self.accept(b) + self.push_type_map(guard_map) + self.accept(b) + else: + self.accept(b) + self.push_type_map(else_map) # This is needed due to a quirk in frame_context. Without it types will stay narrowed # after the match. with self.binder.frame_context(can_skip=False, fall_through=2): pass - def infer_variable_types_from_type_maps(self, type_maps: List[TypeMap]) -> None: + def infer_variable_types_from_type_maps(self, type_maps: List[TypeMap]) -> Dict[Var, Type]: all_captures: Dict[Var, List[Tuple[NameExpr, Type]]] = defaultdict(list) for tm in type_maps: if tm is not None: @@ -4128,28 +4149,38 @@ def infer_variable_types_from_type_maps(self, type_maps: List[TypeMap]) -> None: assert isinstance(node, Var) all_captures[node].append((expr, typ)) + inferred_types: Dict[Var, Type] = {} for var, captures in all_captures.items(): - conflict = False + already_exists = False types: List[Type] = [] for expr, typ in captures: types.append(typ) - previous_type, _, inferred = self.check_lvalue(expr) + previous_type, _, _ = self.check_lvalue(expr) if previous_type is not None: - conflict = True - self.check_subtype(typ, previous_type, expr, - msg=message_registry.INCOMPATIBLE_TYPES_IN_CAPTURE, - subtype_label="pattern captures type", - supertype_label="variable has type") - for type_map in type_maps: - if type_map is not None and expr in type_map: - del type_map[expr] - - if not conflict: + already_exists = True + if self.check_subtype(typ, previous_type, expr, + msg=message_registry.INCOMPATIBLE_TYPES_IN_CAPTURE, + subtype_label="pattern captures type", + supertype_label="variable has type"): + inferred_types[var] = previous_type + + if not already_exists: new_type = UnionType.make_union(types) # Infer the union type at the first occurrence first_occurrence, _ = captures[0] + inferred_types[var] = new_type self.infer_variable_type(var, first_occurrence, new_type, first_occurrence) + return inferred_types + + def remove_capture_conflicts(self, type_map: TypeMap, inferred_types: Dict[Var, Type]) -> None: + if type_map: + for expr, typ in list(type_map.items()): + if isinstance(expr, NameExpr): + node = expr.node + assert isinstance(node, Var) + if node not in inferred_types or not is_subtype(typ, inferred_types[node]): + del type_map[expr] def make_fake_typeinfo(self, curr_module_fullname: str, @@ -5637,6 +5668,14 @@ def conditional_types(current_type: Type, None means no new information can be inferred. If default is set it is returned instead.""" if proposed_type_ranges: + if len(proposed_type_ranges) == 1: + target = proposed_type_ranges[0].item + target = get_proper_type(target) + if isinstance(target, LiteralType) and (target.is_enum_literal() + or isinstance(target.value, bool)): + enum_name = target.fallback.type.fullname + current_type = try_expanding_sum_type_to_union(current_type, + enum_name) proposed_items = [type_range.item for type_range in proposed_type_ranges] proposed_type = make_simplified_union(proposed_items) if isinstance(proposed_type, AnyType): diff --git a/mypy/checkpattern.py b/mypy/checkpattern.py index fbbb4c319ccb6..9c6e67db03e11 100644 --- a/mypy/checkpattern.py +++ b/mypy/checkpattern.py @@ -1,4 +1,5 @@ """Pattern checker. This file is conceptually part of TypeChecker.""" + from collections import defaultdict from typing import List, Optional, Tuple, Dict, NamedTuple, Set, Union from typing_extensions import Final @@ -19,7 +20,8 @@ ) from mypy.plugin import Plugin from mypy.subtypes import is_subtype -from mypy.typeops import try_getting_str_literals_from_type, make_simplified_union +from mypy.typeops import try_getting_str_literals_from_type, make_simplified_union, \ + coerce_to_literal from mypy.types import ( ProperType, AnyType, TypeOfAny, Instance, Type, UninhabitedType, get_proper_type, TypedDictType, TupleType, NoneType, UnionType @@ -55,7 +57,7 @@ 'PatternType', [ ('type', Type), # The type the match subject can be narrowed to - ('rest_type', Type), # For exhaustiveness checking. Not used yet + ('rest_type', Type), # The remaining type if the pattern didn't match ('captures', Dict[Expression, Type]), # The variables captured by the pattern ]) @@ -177,6 +179,7 @@ def visit_or_pattern(self, o: OrPattern) -> PatternType: def visit_value_pattern(self, o: ValuePattern) -> PatternType: current_type = self.type_context[-1] typ = self.chk.expr_checker.accept(o.expr) + typ = coerce_to_literal(typ) narrowed_type, rest_type = self.chk.conditional_types_with_intersection( current_type, [get_type_range(typ)], @@ -259,6 +262,9 @@ def visit_sequence_pattern(self, o: SequencePattern) -> PatternType: new_inner_types = self.expand_starred_pattern_types(contracted_new_inner_types, star_position, len(inner_types)) + rest_inner_types = self.expand_starred_pattern_types(contracted_rest_inner_types, + star_position, + len(inner_types)) # # Calculate new type @@ -287,15 +293,20 @@ def visit_sequence_pattern(self, o: SequencePattern) -> PatternType: if all(is_uninhabited(typ) for typ in inner_rest_types): # All subpatterns always match, so we can apply negative narrowing - new_type, rest_type = self.chk.conditional_types_with_intersection( - current_type, [get_type_range(new_type)], o, default=current_type - ) + rest_type = TupleType(rest_inner_types, current_type.partial_fallback) else: new_inner_type = UninhabitedType() for typ in new_inner_types: new_inner_type = join_types(new_inner_type, typ) new_type = self.construct_sequence_child(current_type, new_inner_type) - if not is_subtype(new_type, current_type): + if is_subtype(new_type, current_type): + new_type, _ = self.chk.conditional_types_with_intersection( + current_type, + [get_type_range(new_type)], + o, + default=current_type + ) + else: new_type = current_type return PatternType(new_type, rest_type, captures) @@ -344,8 +355,7 @@ def expand_starred_pattern_types(self, star_pos: Optional[int], num_types: int ) -> List[Type]: - """ - Undoes the contraction done by contract_starred_pattern_types. + """Undoes the contraction done by contract_starred_pattern_types. For example if the sequence pattern is [a, *b, c] and types [bool, int, str] are extended to lenght 4 the result is [bool, int, int, str]. @@ -639,6 +649,13 @@ def construct_sequence_child(self, outer_type: Type, inner_type: Type) -> Type: For example: construct_sequence_child(List[int], str) = List[str] """ + proper_type = get_proper_type(outer_type) + if isinstance(proper_type, UnionType): + types = [ + self.construct_sequence_child(item, inner_type) for item in proper_type.items + if self.can_match_sequence(get_proper_type(item)) + ] + return make_simplified_union(types) sequence = self.chk.named_generic_type("typing.Sequence", [inner_type]) if is_subtype(outer_type, self.chk.named_type("typing.Sequence")): proper_type = get_proper_type(outer_type) @@ -676,6 +693,11 @@ def get_var(expr: Expression) -> Var: def get_type_range(typ: Type) -> 'mypy.checker.TypeRange': + typ = get_proper_type(typ) + if (isinstance(typ, Instance) + and typ.last_known_value + and isinstance(typ.last_known_value.value, bool)): + typ = typ.last_known_value return mypy.checker.TypeRange(typ, is_upper_bound=False) diff --git a/mypy/patterns.py b/mypy/patterns.py index 8557fac6daf61..f7f5f56d0ed5e 100644 --- a/mypy/patterns.py +++ b/mypy/patterns.py @@ -21,6 +21,7 @@ def accept(self, visitor: PatternVisitor[T]) -> T: class AsPattern(Pattern): + """The pattern as """ # The python ast, and therefore also our ast merges capture, wildcard and as patterns into one # for easier handling. # If pattern is None this is a capture pattern. If name and pattern are both none this is a @@ -39,6 +40,7 @@ def accept(self, visitor: PatternVisitor[T]) -> T: class OrPattern(Pattern): + """The pattern | | ...""" patterns: List[Pattern] def __init__(self, patterns: List[Pattern]) -> None: @@ -50,6 +52,7 @@ def accept(self, visitor: PatternVisitor[T]) -> T: class ValuePattern(Pattern): + """The pattern x.y (or x.y.z, ...)""" expr: Expression def __init__(self, expr: Expression): @@ -73,6 +76,7 @@ def accept(self, visitor: PatternVisitor[T]) -> T: class SequencePattern(Pattern): + """The pattern [, ...]""" patterns: List[Pattern] def __init__(self, patterns: List[Pattern]): @@ -114,6 +118,7 @@ def accept(self, visitor: PatternVisitor[T]) -> T: class ClassPattern(Pattern): + """The pattern Cls(...)""" class_ref: RefExpr positionals: List[Pattern] keyword_keys: List[str] diff --git a/test-data/unit/check-python310.test b/test-data/unit/check-python310.test index 0d4f46d539243..9d56aeb468f74 100644 --- a/test-data/unit/check-python310.test +++ b/test-data/unit/check-python310.test @@ -1,5 +1,6 @@ -- Capture Pattern -- -[case testCapturePatternType] + +[case testMatchCapturePatternType] class A: ... m: A @@ -7,23 +8,24 @@ match m: case a: reveal_type(a) # N: Revealed type is "__main__.A" - -- Literal Pattern -- -[case testLiteralPatternNarrows] + +[case testMatchLiteralPatternNarrows] m: object match m: case 1: - reveal_type(m) # N: Revealed type is "Literal[1]?" + reveal_type(m) # N: Revealed type is "Literal[1]" -[case testLiteralPatternAlreadyNarrower] +[case testMatchLiteralPatternAlreadyNarrower-skip] m: bool match m: case 1: - reveal_type(m) # N: Revealed type is "builtins.bool" + reveal_type(m) # This should probably be unreachable, but isn't detected as such. +[builtins fixtures/primitives.pyi] -[case testLiteralPatternUnreachable] +[case testMatchLiteralPatternUnreachable] # primitives are needed because otherwise mypy doesn't see that int and str are incompatible m: int @@ -32,9 +34,9 @@ match m: reveal_type(m) [builtins fixtures/primitives.pyi] - -- Value Pattern -- -[case testValuePatternNarrows] + +[case testMatchValuePatternNarrows] import b m: object @@ -44,7 +46,7 @@ match m: [file b.py] b: int -[case testValuePatternAlreadyNarrower] +[case testMatchValuePatternAlreadyNarrower] import b m: bool @@ -54,7 +56,7 @@ match m: [file b.py] b: int -[case testValuePatternIntersect] +[case testMatchValuePatternIntersect] import b class A: ... @@ -62,12 +64,12 @@ m: A match m: case b.b: - reveal_type(m) # N: Revealed type is "__main__." + reveal_type(m) # N: Revealed type is "__main__.1" [file b.py] class B: ... b: B -[case testValuePatternUnreachable] +[case testMatchValuePatternUnreachable] # primitives are needed because otherwise mypy doesn't see that int and str are incompatible import b @@ -80,9 +82,9 @@ match m: b: str [builtins fixtures/primitives.pyi] - -- Sequence Pattern -- -[case testSequencePatternCaptures] + +[case testMatchSequencePatternCaptures] from typing import List m: List[int] @@ -91,7 +93,7 @@ match m: reveal_type(a) # N: Revealed type is "builtins.int*" [builtins fixtures/list.pyi] -[case testSequencePatternCapturesStarred] +[case testMatchSequencePatternCapturesStarred] from typing import Sequence m: Sequence[int] @@ -101,7 +103,7 @@ match m: reveal_type(b) # N: Revealed type is "builtins.list[builtins.int*]" [builtins fixtures/list.pyi] -[case testSequencePatternNarrowsInner] +[case testMatchSequencePatternNarrowsInner] from typing import Sequence m: Sequence[object] @@ -109,7 +111,7 @@ match m: case [1, True]: reveal_type(m) # N: Revealed type is "typing.Sequence[builtins.int]" -[case testSequencePatternNarrowsOuter] +[case testMatchSequencePatternNarrowsOuter] from typing import Sequence m: object @@ -117,7 +119,7 @@ match m: case [1, True]: reveal_type(m) # N: Revealed type is "typing.Sequence[builtins.int]" -[case testSequencePatternAlreadyNarrowerInner] +[case testMatchSequencePatternAlreadyNarrowerInner] from typing import Sequence m: Sequence[bool] @@ -125,7 +127,7 @@ match m: case [1, True]: reveal_type(m) # N: Revealed type is "typing.Sequence[builtins.bool]" -[case testSequencePatternAlreadyNarrowerOuter] +[case testMatchSequencePatternAlreadyNarrowerOuter] from typing import Sequence m: Sequence[object] @@ -133,7 +135,7 @@ match m: case [1, True]: reveal_type(m) # N: Revealed type is "typing.Sequence[builtins.int]" -[case testSequencePatternAlreadyNarrowerBoth] +[case testMatchSequencePatternAlreadyNarrowerBoth] from typing import Sequence m: Sequence[bool] @@ -141,7 +143,7 @@ match m: case [1, True]: reveal_type(m) # N: Revealed type is "typing.Sequence[builtins.bool]" -[case testNestedSequencePatternNarrowsInner] +[case testMatchNestedSequencePatternNarrowsInner] from typing import Sequence m: Sequence[Sequence[object]] @@ -149,7 +151,7 @@ match m: case [[1], [True]]: reveal_type(m) # N: Revealed type is "typing.Sequence[typing.Sequence[builtins.int]]" -[case testNestedSequencePatternNarrowsOuter] +[case testMatchNestedSequencePatternNarrowsOuter] from typing import Sequence m: object @@ -157,7 +159,7 @@ match m: case [[1], [True]]: reveal_type(m) # N: Revealed type is "typing.Sequence[typing.Sequence[builtins.int]]" -[case testSequencePatternDoesntNarrowInvariant] +[case testMatchSequencePatternDoesntNarrowInvariant] from typing import List m: List[object] @@ -166,7 +168,7 @@ match m: reveal_type(m) # N: Revealed type is "builtins.list[builtins.object]" [builtins fixtures/list.pyi] -[case testSequencePatternMatches] +[case testMatchSequencePatternMatches] import array, collections from typing import Sequence, Iterable @@ -229,8 +231,7 @@ match m11: [builtins fixtures/primitives.pyi] [typing fixtures/typing-full.pyi] - -[case testSequencePatternCapturesTuple] +[case testMatchSequencePatternCapturesTuple] from typing import Tuple m: Tuple[int, str, bool] @@ -242,7 +243,7 @@ match m: reveal_type(m) # N: Revealed type is "Tuple[builtins.int, builtins.str, builtins.bool]" [builtins fixtures/list.pyi] -[case testSequencePatternTupleTooLong] +[case testMatchSequencePatternTupleTooLong] from typing import Tuple m: Tuple[int, str] @@ -253,7 +254,7 @@ match m: reveal_type(c) [builtins fixtures/list.pyi] -[case testSequencePatternTupleTooShort] +[case testMatchSequencePatternTupleTooShort] from typing import Tuple m: Tuple[int, str, bool] @@ -263,16 +264,16 @@ match m: reveal_type(b) [builtins fixtures/list.pyi] -[case testSequencePatternTupleNarrows] +[case testMatchSequencePatternTupleNarrows] from typing import Tuple m: Tuple[object, object] match m: case [1, "str"]: - reveal_type(m) # N: Revealed type is "Tuple[Literal[1]?, Literal['str']?]" + reveal_type(m) # N: Revealed type is "Tuple[Literal[1], Literal['str']]" [builtins fixtures/list.pyi] -[case testSequencePatternTupleStarred] +[case testMatchSequencePatternTupleStarred] from typing import Tuple m: Tuple[int, str, bool] @@ -284,7 +285,7 @@ match m: reveal_type(m) # N: Revealed type is "Tuple[builtins.int, builtins.str, builtins.bool]" [builtins fixtures/list.pyi] -[case testSequencePatternTupleStarredUnion] +[case testMatchSequencePatternTupleStarredUnion] from typing import Tuple m: Tuple[int, str, float, bool] @@ -296,8 +297,7 @@ match m: reveal_type(m) # N: Revealed type is "Tuple[builtins.int, builtins.str, builtins.float, builtins.bool]" [builtins fixtures/list.pyi] - -[case testSequencePatternTupleStarredTooShort] +[case testMatchSequencePatternTupleStarredTooShort] from typing import Tuple m: Tuple[int] reveal_type(m) # N: Revealed type is "Tuple[builtins.int]" @@ -309,7 +309,7 @@ match m: reveal_type(c) [builtins fixtures/list.pyi] -[case testNonMatchingSequencePattern] +[case testMatchNonMatchingSequencePattern] from typing import List x: List[int] @@ -317,7 +317,7 @@ match x: case [str()]: pass -[case testSequenceUnion-skip] +[case testMatchSequenceUnion-skip] from typing import List, Union m: Union[List[List[str]], str] @@ -327,7 +327,8 @@ match m: [builtins fixtures/list.pyi] -- Mapping Pattern -- -[case testMappingPatternCaptures] + +[case testMatchMappingPatternCaptures] from typing import Dict import b m: Dict[str, int] @@ -341,7 +342,7 @@ match m: b: str [builtins fixtures/dict.pyi] -[case testMappingPatternCapturesWrongKeyType] +[case testMatchMappingPatternCapturesWrongKeyType] # This is not actually unreachable, as a subclass of dict could accept keys with different types from typing import Dict import b @@ -356,7 +357,7 @@ match m: b: int [builtins fixtures/dict.pyi] -[case testMappingPatternCapturesTypedDict] +[case testMatchMappingPatternCapturesTypedDict] from typing import TypedDict class A(TypedDict): @@ -377,7 +378,7 @@ match m: reveal_type(v5) # N: Revealed type is "builtins.object*" [typing fixtures/typing-typeddict.pyi] -[case testMappingPatternCapturesTypedDictWithLiteral] +[case testMatchMappingPatternCapturesTypedDictWithLiteral] from typing import TypedDict import b @@ -404,7 +405,7 @@ b: Literal["b"] = "b" o: Final[str] = "o" [typing fixtures/typing-typeddict.pyi] -[case testMappingPatternCapturesTypedDictWithNonLiteral] +[case testMatchMappingPatternCapturesTypedDictWithNonLiteral] from typing import TypedDict import b @@ -422,7 +423,7 @@ from typing import Final, Literal a: str [typing fixtures/typing-typeddict.pyi] -[case testMappingPatternCapturesTypedDictUnreachable] +[case testMatchMappingPatternCapturesTypedDictUnreachable] # TypedDict keys are always str, so this is actually unreachable from typing import TypedDict import b @@ -442,7 +443,7 @@ match m: b: int [typing fixtures/typing-typeddict.pyi] -[case testMappingPatternCaptureRest] +[case testMatchMappingPatternCaptureRest] m: object match m: @@ -450,7 +451,7 @@ match m: reveal_type(r) # N: Revealed type is "builtins.dict[builtins.object, builtins.object]" [builtins fixtures/dict.pyi] -[case testMappingPatternCaptureRestFromMapping] +[case testMatchMappingPatternCaptureRestFromMapping] from typing import Mapping m: Mapping[str, int] @@ -460,10 +461,11 @@ match m: reveal_type(r) # N: Revealed type is "builtins.dict[builtins.str*, builtins.int*]" [builtins fixtures/dict.pyi] --- Mapping patterns currently don't narrow -- +-- Mapping patterns currently do not narrow -- -- Class Pattern -- -[case testClassPatternCapturePositional] + +[case testMatchClassPatternCapturePositional] from typing import Final class A: @@ -479,7 +481,7 @@ match m: reveal_type(j) # N: Revealed type is "builtins.int" [builtins fixtures/tuple.pyi] -[case testClassPatternMemberClassCapturePositional] +[case testMatchClassPatternMemberClassCapturePositional] import b m: b.A @@ -497,7 +499,7 @@ class A: b: int [builtins fixtures/tuple.pyi] -[case testClassPatternCaptureKeyword] +[case testMatchClassPatternCaptureKeyword] class A: a: str b: int @@ -509,7 +511,7 @@ match m: reveal_type(i) # N: Revealed type is "builtins.str" reveal_type(j) # N: Revealed type is "builtins.int" -[case testClassPatternCaptureSelf] +[case testMatchClassPatternCaptureSelf] m: object match m: @@ -537,7 +539,7 @@ match m: reveal_type(k) # N: Revealed type is "builtins.tuple[Any, ...]" [builtins fixtures/primitives.pyi] -[case testClassPatternNarrowSelfCapture] +[case testMatchClassPatternNarrowSelfCapture] m: object match m: @@ -565,7 +567,7 @@ match m: reveal_type(m) # N: Revealed type is "builtins.tuple[Any, ...]" [builtins fixtures/primitives.pyi] -[case testClassPatternCaptureDataclass] +[case testMatchClassPatternCaptureDataclass] from dataclasses import dataclass @dataclass @@ -581,7 +583,7 @@ match m: reveal_type(j) # N: Revealed type is "builtins.int" [builtins fixtures/dataclasses.pyi] -[case testClassPatternCaptureDataclassNoMatchArgs] +[case testMatchClassPatternCaptureDataclassNoMatchArgs] from dataclasses import dataclass @dataclass(match_args=False) @@ -596,7 +598,7 @@ match m: pass [builtins fixtures/dataclasses.pyi] -[case testClassPatternCaptureDataclassPartialMatchArgs] +[case testMatchClassPatternCaptureDataclassPartialMatchArgs] from dataclasses import dataclass, field @dataclass @@ -613,7 +615,7 @@ match m: reveal_type(k) # N: Revealed type is "builtins.str" [builtins fixtures/dataclasses.pyi] -[case testClassPatternCaptureNamedTupleInline] +[case testMatchClassPatternCaptureNamedTupleInline] from collections import namedtuple A = namedtuple("A", ["a", "b"]) @@ -626,7 +628,7 @@ match m: reveal_type(j) # N: Revealed type is "Any" [builtins fixtures/list.pyi] -[case testClassPatternCaptureNamedTupleInlineTyped] +[case testMatchClassPatternCaptureNamedTupleInlineTyped] from typing import NamedTuple A = NamedTuple("A", [("a", str), ("b", int)]) @@ -639,7 +641,7 @@ match m: reveal_type(j) # N: Revealed type is "builtins.int" [builtins fixtures/list.pyi] -[case testClassPatternCaptureNamedTupleClass] +[case testMatchClassPatternCaptureNamedTupleClass] from typing import NamedTuple class A(NamedTuple): @@ -654,7 +656,7 @@ match m: reveal_type(j) # N: Revealed type is "builtins.int" [builtins fixtures/tuple.pyi] -[case testClassPatternCaptureGeneric] +[case testMatchClassPatternCaptureGeneric] from typing import Generic, TypeVar T = TypeVar('T') @@ -669,7 +671,7 @@ match m: reveal_type(m) # N: Revealed type is "__main__.A[Any]" reveal_type(i) # N: Revealed type is "Any" -[case testClassPatternCaptureGenericAlreadyKnown] +[case testMatchClassPatternCaptureGenericAlreadyKnown] from typing import Generic, TypeVar T = TypeVar('T') @@ -684,7 +686,7 @@ match m: reveal_type(m) # N: Revealed type is "__main__.A[builtins.int]" reveal_type(i) # N: Revealed type is "builtins.int*" -[case testClassPatternCaptureFilledGenericTypeAlias] +[case testMatchClassPatternCaptureFilledGenericTypeAlias] from typing import Generic, TypeVar T = TypeVar('T') @@ -700,7 +702,7 @@ match m: case B(a=i): # E: Class pattern class must not be a type alias with type parameters reveal_type(i) -[case testClassPatternCaptureGenericTypeAlias] +[case testMatchClassPatternCaptureGenericTypeAlias] from typing import Generic, TypeVar T = TypeVar('T') @@ -716,7 +718,7 @@ match m: case B(a=i): pass -[case testClassPatternNarrows] +[case testMatchClassPatternNarrows] from typing import Final class A: @@ -733,7 +735,7 @@ match m: reveal_type(m) # N: Revealed type is "__main__.A" [builtins fixtures/tuple.pyi] -[case testClassPatternNarrowsUnion] +[case testMatchClassPatternNarrowsUnion] from typing import Final, Union class A: @@ -769,7 +771,7 @@ match m: reveal_type(l) # N: Revealed type is "builtins.str" [builtins fixtures/tuple.pyi] -[case testClassPatternAlreadyNarrower] +[case testMatchClassPatternAlreadyNarrower] from typing import Final class A: @@ -789,7 +791,7 @@ match m: reveal_type(m) # N: Revealed type is "__main__.B" [builtins fixtures/tuple.pyi] -[case testClassPatternIntersection] +[case testMatchClassPatternIntersection] from typing import Final class A: @@ -802,12 +804,12 @@ m: B match m: case A(): - reveal_type(m) # N: Revealed type is "__main__." + reveal_type(m) # N: Revealed type is "__main__.2" case A(i, j): - reveal_type(m) # N: Revealed type is "__main__.1" + reveal_type(m) # N: Revealed type is "__main__.3" [builtins fixtures/tuple.pyi] -[case testClassPatternNonexistentKeyword] +[case testMatchClassPatternNonexistentKeyword] class A: ... m: object @@ -817,7 +819,7 @@ match m: reveal_type(m) # N: Revealed type is "__main__.A" reveal_type(j) # N: Revealed type is "Any" -[case testClassPatternDuplicateKeyword] +[case testMatchClassPatternDuplicateKeyword] class A: a: str @@ -827,7 +829,7 @@ match m: case A(a=i, a=j): # E: Duplicate keyword pattern "a" pass -[case testClassPatternDuplicateImplicitKeyword] +[case testMatchClassPatternDuplicateImplicitKeyword] from typing import Final class A: @@ -841,7 +843,7 @@ match m: pass [builtins fixtures/tuple.pyi] -[case testClassPatternTooManyPositionals] +[case testMatchClassPatternTooManyPositionals] from typing import Final class A: @@ -856,7 +858,7 @@ match m: pass [builtins fixtures/tuple.pyi] -[case testClassPatternIsNotType] +[case testMatchClassPatternIsNotType] a = 1 m: object @@ -865,7 +867,7 @@ match m: reveal_type(i) reveal_type(j) -[case testClassPatternNestedGenerics] +[case testMatchClassPatternNestedGenerics] # From cpython test_patma.py x = [[{0: 0}]] match x: @@ -877,7 +879,7 @@ reveal_type(y) # N: Revealed type is "builtins.int" reveal_type(z) # N: Revealed type is "builtins.int*" [builtins fixtures/dict.pyi] -[case testNonFinalMatchArgs] +[case testMatchNonFinalMatchArgs] class A: __match_args__ = ("a", "b") # N: __match_args__ must be final for checking of match statements to work a: str @@ -891,7 +893,7 @@ match m: reveal_type(j) # N: Revealed type is "Any" [builtins fixtures/tuple.pyi] -[case testAnyTupleMatchArgs] +[case testMatchAnyTupleMatchArgs] from typing import Tuple, Any class A: @@ -908,7 +910,7 @@ match m: reveal_type(k) # N: Revealed type is "Any" [builtins fixtures/tuple.pyi] -[case testNonLiteralMatchArgs] +[case testMatchNonLiteralMatchArgs] from typing import Final b: str = "b" @@ -927,7 +929,7 @@ match m: reveal_type(j) # N: Revealed type is "Any" [builtins fixtures/tuple.pyi] -[case testExternalMatchArgs] +[case testMatchExternalMatchArgs] from typing import Final, Literal args: Final = ("a", "b") @@ -946,9 +948,9 @@ class B: [builtins fixtures/tuple.pyi] [typing fixtures/typing-medium.pyi] - -- As Pattern -- -[case testAsPattern] + +[case testMatchAsPattern] m: int match m: @@ -956,51 +958,51 @@ match m: reveal_type(x) # N: Revealed type is "builtins.int" reveal_type(l) # N: Revealed type is "builtins.int" -[case testAsPatternNarrows] +[case testMatchAsPatternNarrows] m: object match m: case int() as l: reveal_type(l) # N: Revealed type is "builtins.int" -[case testAsPatternCapturesOr] +[case testMatchAsPatternCapturesOr] m: object match m: case 1 | 2 as n: - reveal_type(n) # N: Revealed type is "Union[Literal[1]?, Literal[2]?]" + reveal_type(n) # N: Revealed type is "Union[Literal[1], Literal[2]]" -[case testAsPatternAlreadyNarrower] +[case testMatchAsPatternAlreadyNarrower] m: bool match m: case int() as l: reveal_type(l) # N: Revealed type is "builtins.bool" - -- Or Pattern -- -[case testOrPatternNarrows] + +[case testMatchOrPatternNarrows] m: object match m: case 1 | 2: - reveal_type(m) # N: Revealed type is "Union[Literal[1]?, Literal[2]?]" + reveal_type(m) # N: Revealed type is "Union[Literal[1], Literal[2]]" -[case testOrPatternNarrowsStr] +[case testMatchOrPatternNarrowsStr] m: object match m: case "foo" | "bar": - reveal_type(m) # N: Revealed type is "Union[Literal['foo']?, Literal['bar']?]" + reveal_type(m) # N: Revealed type is "Union[Literal['foo'], Literal['bar']]" -[case testOrPatternNarrowsUnion] +[case testMatchOrPatternNarrowsUnion] m: object match m: case 1 | "foo": - reveal_type(m) # N: Revealed type is "Union[Literal[1]?, Literal['foo']?]" + reveal_type(m) # N: Revealed type is "Union[Literal[1], Literal['foo']]" -[case testOrPatterCapturesMissing] +[case testMatchOrPatterCapturesMissing] from typing import List m: List[int] @@ -1010,7 +1012,7 @@ match m: reveal_type(y) # N: Revealed type is "builtins.int*" [builtins fixtures/list.pyi] -[case testOrPatternCapturesJoin] +[case testMatchOrPatternCapturesJoin] m: object match m: @@ -1018,9 +1020,9 @@ match m: reveal_type(x) # N: Revealed type is "typing.Iterable[Any]" [builtins fixtures/dict.pyi] - -- Interactions -- -[case testCapturePatternMultipleCases] + +[case testMatchCapturePatternMultipleCases] m: object match m: @@ -1031,7 +1033,7 @@ match m: reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]" -[case testCapturePatternMultipleCaptures] +[case testMatchCapturePatternMultipleCaptures] from typing import Iterable m: Iterable[int] @@ -1041,7 +1043,7 @@ match m: reveal_type(x) # N: Revealed type is "builtins.int" [builtins fixtures/list.pyi] -[case testCapturePatternPreexistingSame] +[case testMatchCapturePatternPreexistingSame] a: int m: int @@ -1049,7 +1051,19 @@ match m: case a: reveal_type(a) # N: Revealed type is "builtins.int" -[case testCapturePatternPreexistingIncompatible] +[case testMatchCapturePatternPreexistingNarrows] +a: int +m: bool + +match m: + case a: + reveal_type(a) # N: Revealed type is "builtins.bool" + +reveal_type(a) # N: Revealed type is "builtins.bool" +a = 3 +reveal_type(a) # N: Revealed type is "builtins.int" + +[case testMatchCapturePatternPreexistingIncompatible] a: str m: int @@ -1057,7 +1071,9 @@ match m: case a: # E: Incompatible types in capture pattern (pattern captures type "int", variable has type "str") reveal_type(a) # N: Revealed type is "builtins.str" -[case testCapturePatternPreexistingIncompatibleLater] +reveal_type(a) # N: Revealed type is "builtins.str" + +[case testMatchCapturePatternPreexistingIncompatibleLater] a: str m: object @@ -1067,9 +1083,11 @@ match m: case int(a): # E: Incompatible types in capture pattern (pattern captures type "int", variable has type "str") reveal_type(a) # N: Revealed type is "builtins.str" +reveal_type(a) # N: Revealed type is "builtins.str" -- Guards -- -[case testSimplePatternGuard] + +[case testMatchSimplePatternGuard] m: str def guard() -> bool: ... @@ -1078,21 +1096,21 @@ match m: case a if guard(): reveal_type(a) # N: Revealed type is "builtins.str" -[case testAlwaysTruePatternGuard] +[case testMatchAlwaysTruePatternGuard] m: str match m: case a if True: reveal_type(a) # N: Revealed type is "builtins.str" -[case testAlwaysFalsePatternGuard] +[case testMatchAlwaysFalsePatternGuard] m: str match m: case a if False: reveal_type(a) -[case testRedefiningPatternGuard] +[case testMatchRedefiningPatternGuard] # flags: --strict-optional m: str @@ -1100,14 +1118,14 @@ match m: case a if a := 1: # E: Incompatible types in assignment (expression has type "int", variable has type "str") reveal_type(a) # N: Revealed type is "" -[case testAssigningPatternGuard] +[case testMatchAssigningPatternGuard] m: str match m: case a if a := "test": reveal_type(a) # N: Revealed type is "builtins.str" -[case testNarrowingPatternGuard] +[case testMatchNarrowingPatternGuard] m: object match m: @@ -1115,7 +1133,7 @@ match m: reveal_type(a) # N: Revealed type is "builtins.str" [builtins fixtures/isinstancelist.pyi] -[case testIncompatiblePatternGuard] +[case testMatchIncompatiblePatternGuard] class A: ... class B: ... @@ -1126,7 +1144,7 @@ match m: reveal_type(a) # N: Revealed type is "__main__." [builtins fixtures/isinstancelist.pyi] -[case testUnreachablePatternGuard] +[case testMatchUnreachablePatternGuard] m: str match m: @@ -1135,7 +1153,8 @@ match m: [builtins fixtures/isinstancelist.pyi] -- Exhaustiveness -- -[case testUnionNegativeNarrowing-skip] + +[case testMatchUnionNegativeNarrowing] from typing import Union m: Union[str, int] @@ -1148,7 +1167,7 @@ match m: reveal_type(b) # N: Revealed type is "builtins.int" reveal_type(m) # N: Revealed type is "builtins.int" -[case testOrPatternNegativeNarrowing-skip] +[case testMatchOrPatternNegativeNarrowing] from typing import Union m: Union[str, bytes, int] @@ -1160,7 +1179,7 @@ match m: case b: reveal_type(b) # N: Revealed type is "builtins.int" -[case testExhaustiveReturn-skip] +[case testMatchExhaustiveReturn] def foo(value) -> int: match value: case "bar": @@ -1168,7 +1187,7 @@ def foo(value) -> int: case _: return 2 -[case testNoneExhaustiveReturn-skip] +[case testMatchNonExhaustiveReturn] def foo(value) -> int: # E: Missing return statement match value: case "bar": @@ -1176,7 +1195,300 @@ def foo(value) -> int: # E: Missing return statement case 2: return 2 -[case testWithStatementScopeAndMatchStatement] +[case testMatchMoreExhaustiveReturnCases] +def g(value: int | None) -> int: + match value: + case int(): + return 0 + case None: + return 1 + +def b(value: bool) -> int: + match value: + case True: + return 2 + case False: + return 3 + +[case testMatchMiscNonExhaustiveReturn] +class C: + a: int | str + +def f1(value: int | str | None) -> int: # E: Missing return statement + match value: + case int(): + return 0 + case None: + return 1 + +def f2(c: C) -> int: # E: Missing return statement + match c: + case C(a=int()): + return 0 + case C(a=str()): + return 1 + +def f3(x: list[str]) -> int: # E: Missing return statement + match x: + case [a]: + return 0 + case [a, b]: + return 1 + +def f4(x: dict[str, int]) -> int: # E: Missing return statement + match x: + case {'x': a}: + return 0 + +def f5(x: bool) -> int: # E: Missing return statement + match x: + case True: + return 0 +[builtins fixtures/dict.pyi] + +[case testMatchNonExhaustiveError] +from typing import NoReturn +def assert_never(x: NoReturn) -> None: ... + +def f(value: int) -> int: # E: Missing return statement + match value: + case 1: + return 0 + case 2: + return 1 + case o: + assert_never(o) # E: Argument 1 to "assert_never" has incompatible type "int"; expected "NoReturn" + +[case testMatchExhaustiveNoError] +from typing import NoReturn, Union, Literal +def assert_never(x: NoReturn) -> None: ... + +def f(value: Literal[1] | Literal[2]) -> int: + match value: + case 1: + return 0 + case 2: + return 1 + case o: + assert_never(o) +[typing fixtures/typing-medium.pyi] + +[case testMatchSequencePatternNegativeNarrowing] +from typing import Union, Sequence, Tuple + +m1: Sequence[int | str] + +match m1: + case [int()]: + reveal_type(m1) # N: Revealed type is "typing.Sequence[builtins.int]" + case r: + reveal_type(m1) # N: Revealed type is "typing.Sequence[Union[builtins.int, builtins.str]]" + +m2: Tuple[int | str] + +match m2: + case (int(),): + reveal_type(m2) # N: Revealed type is "Tuple[builtins.int]" + case r2: + reveal_type(m2) # N: Revealed type is "Tuple[builtins.str]" + +m3: Tuple[Union[int, str]] + +match m3: + case (1,): + reveal_type(m3) # N: Revealed type is "Tuple[Literal[1]]" + case r2: + reveal_type(m3) # N: Revealed type is "Tuple[Union[builtins.int, builtins.str]]" +[builtins fixtures/tuple.pyi] + +[case testMatchLiteralPatternEnumNegativeNarrowing] +from enum import Enum +class Medal(Enum): + gold = 1 + silver = 2 + bronze = 3 + +def f(m: Medal) -> int: + match m: + case Medal.gold: + reveal_type(m) # N: Revealed type is "Literal[__main__.Medal.gold]" + return 0 + case _: + reveal_type(m) # N: Revealed type is "Union[Literal[__main__.Medal.silver], Literal[__main__.Medal.bronze]]" + return 1 + +def g(m: Medal) -> int: + match m: + case Medal.gold: + return 0 + case Medal.silver: + return 1 + case Medal.bronze: + return 2 + +[case testMatchLiteralPatternEnumCustomEquals-skip] +from enum import Enum +class Medal(Enum): + gold = 1 + silver = 2 + bronze = 3 + + def __eq__(self, other) -> bool: ... + +m: Medal + +match m: + case Medal.gold: + reveal_type(m) # N: Revealed type is "Literal[__main__.Medal.gold]" + case _: + reveal_type(m) # N: Revealed type is "__main__.Medal" + +[case testMatchNarrowUsingPatternGuardSpecialCase] +def f(x: int | str) -> int: # E: Missing return statement + match x: + case x if isinstance(x, str): + return 0 + case int(): + return 1 +[builtins fixtures/isinstance.pyi] + +[case testMatchNarrowDownUnionPartially] +# flags: --strict-optional + +def f(x: int | str) -> None: + match x: + case int(): + return + reveal_type(x) # N: Revealed type is "builtins.str" + +def g(x: int | str | None) -> None: + match x: + case int() | None: + return + reveal_type(x) # N: Revealed type is "builtins.str" + +def h(x: int | str | None) -> None: + match x: + case int() | str(): + return + reveal_type(x) # N: Revealed type is "None" + +[case testMatchNarrowDownUsingLiteralMatch] +from enum import Enum +class Medal(Enum): + gold = 1 + silver = 2 + +def b1(x: bool) -> None: + match x: + case True: + return + reveal_type(x) # N: Revealed type is "Literal[False]" + +def b2(x: bool) -> None: + match x: + case False: + return + reveal_type(x) # N: Revealed type is "Literal[True]" + +def e1(x: Medal) -> None: + match x: + case Medal.gold: + return + reveal_type(x) # N: Revealed type is "Literal[__main__.Medal.silver]" + +def e2(x: Medal) -> None: + match x: + case Medal.silver: + return + reveal_type(x) # N: Revealed type is "Literal[__main__.Medal.gold]" + +def i(x: int) -> None: + match x: + case 1: + return + reveal_type(x) # N: Revealed type is "builtins.int" + +def s(x: str) -> None: + match x: + case 'x': + return + reveal_type(x) # N: Revealed type is "builtins.str" + +def union(x: str | bool) -> None: + match x: + case True: + return + reveal_type(x) # N: Revealed type is "Union[builtins.str, Literal[False]]" + +[case testMatchAssertFalseToSilenceFalsePositives] +class C: + a: int | str + +def f(c: C) -> int: + match c: + case C(a=int()): + return 0 + case C(a=str()): + return 1 + case _: + assert False + +def g(c: C) -> int: + match c: + case C(a=int()): + return 0 + case C(a=str()): + return 1 + assert False + +[case testMatchAsPatternExhaustiveness] +def f(x: int | str) -> int: + match x: + case int() as n: + return n + case str() as s: + return 1 + +[case testMatchAsPatternIntersection-skip] +class A: pass +class B: pass +class C: pass + +def f(x: A) -> None: + match x: + case B() as y: + reveal_type(y) # N: Revealed type is "__main__." + case C() as y: + reveal_type(y) # N: Revealed type is "__main__." + reveal_type(y) # N: Revealed type is "Union[__main__., __main__.]" + +[case testMatchWithBreakAndContinue] +# flags: --strict-optional +def f(x: int | str | None) -> None: + i = int() + while i: + match x: + case int(): + continue + case str(): + break + reveal_type(x) # N: Revealed type is "None" + reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str, None]" + +[case testMatchNarrowDownWithStarred-skip] +from typing import List +def f(x: List[int] | int) -> None: + match x: + case [*y]: + reveal_type(y) # N: Revealed type is "builtins.list[builtins.int*]" + return + reveal_type(x) # N: Revealed type is "builtins.int" +[builtins fixtures/list.pyi] + +-- Misc + +[case testMatchAndWithStatementScope] from m import A, B with A() as x: From 8650f5c2eedc26f11b6f5c35cf0c0d752aaf51fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0t=C4=9Bp=C3=A1n=20Hor=C3=A1=C4=8Dek?= <4643182+shoracek@users.noreply.github.com> Date: Tue, 8 Mar 2022 04:30:01 +0100 Subject: [PATCH 154/377] stubgen: fix non default keyword-only argument positioning (#12303) Fixes #11082 --- mypy/stubgen.py | 6 ++++-- test-data/unit/stubgen.test | 5 +++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/mypy/stubgen.py b/mypy/stubgen.py index b0a2c4e645876..dafb446a835a1 100755 --- a/mypy/stubgen.py +++ b/mypy/stubgen.py @@ -649,9 +649,11 @@ def visit_func_def(self, o: FuncDef, is_abstract: bool = False, # type "UnboundType" and will not match. if not isinstance(get_proper_type(annotated_type), AnyType): annotation = ": {}".format(self.print_annotation(annotated_type)) + + if kind.is_named() and not any(arg.startswith('*') for arg in args): + args.append('*') + if arg_.initializer: - if kind.is_named() and not any(arg.startswith('*') for arg in args): - args.append('*') if not annotation: typename = self.get_str_type_of_node(arg_.initializer, True, False) if typename == '': diff --git a/test-data/unit/stubgen.test b/test-data/unit/stubgen.test index e20073027db20..6592791f9aa39 100644 --- a/test-data/unit/stubgen.test +++ b/test-data/unit/stubgen.test @@ -2580,3 +2580,8 @@ class A: def f(x: int, y: int) -> int: ... @t.overload def f(x: t.Tuple[int, int]) -> int: ... + +[case testNonDefaultKeywordOnlyArgAfterAsterisk] +def func(*, non_default_kwarg: bool, default_kwarg: bool = True): ... +[out] +def func(*, non_default_kwarg: bool, default_kwarg: bool = ...): ... From 5d82d5b98098ba639c517dd9dfc7273704b1e761 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Tue, 8 Mar 2022 07:19:08 -0800 Subject: [PATCH 155/377] Use tomllib on Python 3.11 (#12305) --- mypy-requirements.txt | 2 +- mypy/config_parser.py | 12 ++++++++---- mypy/modulefinder.py | 11 +++++++---- setup.py | 2 +- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index 61e0a9f28e01a..1c372294383d3 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ typing_extensions>=3.10 mypy_extensions>=0.4.3 typed_ast>=1.4.0,<2; python_version<'3.8' -tomli>=1.1.0 +tomli>=1.1.0; python_version<'3.11' diff --git a/mypy/config_parser.py b/mypy/config_parser.py index fa57caee14a4c..36358f9df79a1 100644 --- a/mypy/config_parser.py +++ b/mypy/config_parser.py @@ -6,7 +6,11 @@ import re import sys -import tomli +if sys.version_info >= (3, 11): + import tomllib +else: + import tomli as tomllib + from typing import (Any, Callable, Dict, List, Mapping, MutableMapping, Optional, Sequence, TextIO, Tuple, Union) from typing_extensions import Final, TypeAlias as _TypeAlias @@ -178,8 +182,8 @@ def parse_config_file(options: Options, set_strict_flags: Callable[[], None], continue try: if is_toml(config_file): - with open(config_file, encoding="utf-8") as f: - toml_data = tomli.loads(f.read()) + with open(config_file, "rb") as f: + toml_data = tomllib.load(f) # Filter down to just mypy relevant toml keys toml_data = toml_data.get('tool', {}) if 'mypy' not in toml_data: @@ -191,7 +195,7 @@ def parse_config_file(options: Options, set_strict_flags: Callable[[], None], config_parser.read(config_file) parser = config_parser config_types = ini_config_types - except (tomli.TOMLDecodeError, configparser.Error, ConfigTOMLValueError) as err: + except (tomllib.TOMLDecodeError, configparser.Error, ConfigTOMLValueError) as err: print("%s: %s" % (config_file, err), file=stderr) else: if config_file in defaults.SHARED_CONFIG_FILES and 'mypy' not in parser: diff --git a/mypy/modulefinder.py b/mypy/modulefinder.py index 8dcaee6f99d6c..94d2dd34c16e7 100644 --- a/mypy/modulefinder.py +++ b/mypy/modulefinder.py @@ -12,6 +12,11 @@ import sys from enum import Enum, unique +if sys.version_info >= (3, 11): + import tomllib +else: + import tomli as tomllib + from typing import Dict, Iterator, List, NamedTuple, Optional, Set, Tuple, Union from typing_extensions import Final, TypeAlias as _TypeAlias @@ -449,10 +454,8 @@ def _is_compatible_stub_package(self, stub_dir: str) -> bool: """ metadata_fnam = os.path.join(stub_dir, 'METADATA.toml') if os.path.isfile(metadata_fnam): - # Delay import for a possible minor performance win. - import tomli - with open(metadata_fnam, encoding="utf-8") as f: - metadata = tomli.loads(f.read()) + with open(metadata_fnam, "rb") as f: + metadata = tomllib.load(f) if self.python_major_ver == 2: return bool(metadata.get('python2', False)) else: diff --git a/setup.py b/setup.py index 233ad30294c64..c2e46675a26b0 100644 --- a/setup.py +++ b/setup.py @@ -198,7 +198,7 @@ def run(self): install_requires=["typed_ast >= 1.4.0, < 2; python_version<'3.8'", 'typing_extensions>=3.10', 'mypy_extensions >= 0.4.3', - 'tomli>=1.1.0', + "tomli>=1.1.0; python_version<'3.11'", ], # Same here. extras_require={ From 18c32da8459632c746be597cd03f891d566f85d1 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Tue, 8 Mar 2022 15:37:33 +0000 Subject: [PATCH 156/377] Update version to 0.950+dev (#12309) --- mypy/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/version.py b/mypy/version.py index 8877d01e5bb82..b59c826eab6b3 100644 --- a/mypy/version.py +++ b/mypy/version.py @@ -5,7 +5,7 @@ # - Release versions have the form "0.NNN". # - Dev versions have the form "0.NNN+dev" (PLUS sign to conform to PEP 440). # - For 1.0 we'll switch back to 1.2.3 form. -__version__ = '0.940+dev' +__version__ = '0.950+dev' base_version = __version__ mypy_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) From 47e2ca8f54a0f72596e429c820cd9674a215f827 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Wed, 9 Mar 2022 05:18:32 -0800 Subject: [PATCH 157/377] Fix proper_plugin for typeshed tuple change (#12319) This will be broken by https://github.com/python/typeshed/pull/7454 Co-authored-by: hauntsaninja <> --- misc/proper_plugin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/misc/proper_plugin.py b/misc/proper_plugin.py index 249ad983266b7..acd77500cd5db 100644 --- a/misc/proper_plugin.py +++ b/misc/proper_plugin.py @@ -1,6 +1,6 @@ from mypy.plugin import Plugin, FunctionContext from mypy.types import ( - Type, Instance, CallableType, UnionType, get_proper_type, ProperType, + FunctionLike, Type, Instance, CallableType, UnionType, get_proper_type, ProperType, get_proper_types, TupleType, NoneTyp, AnyType ) from mypy.nodes import TypeInfo @@ -52,7 +52,7 @@ def isinstance_proper_hook(ctx: FunctionContext) -> Type: def is_special_target(right: ProperType) -> bool: """Whitelist some special cases for use in isinstance() with improper types.""" - if isinstance(right, CallableType) and right.is_type_obj(): + if isinstance(right, FunctionLike) and right.is_type_obj(): if right.type_object().fullname == 'builtins.tuple': # Used with Union[Type, Tuple[Type, ...]]. return True From 4a744b35e28277e2193feb78de90d3b3cbb3169b Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Wed, 9 Mar 2022 05:20:01 -0800 Subject: [PATCH 158/377] Print compilation status with --version (#12318) Resolves #12317 Co-authored-by: hauntsaninja <> --- mypy/main.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mypy/main.py b/mypy/main.py index d765781838cf8..d6e16eaf5a625 100644 --- a/mypy/main.py +++ b/mypy/main.py @@ -492,9 +492,11 @@ def add_invertible_flag(flag: str, general_group.add_argument( '-v', '--verbose', action='count', dest='verbosity', help="More verbose messages") + + compilation_status = "no" if __file__.endswith(".py") else "yes" general_group.add_argument( '-V', '--version', action=CapturableVersionAction, - version='%(prog)s ' + __version__, + version='%(prog)s ' + __version__ + f" (compiled: {compilation_status})", help="Show program's version number and exit", stdout=stdout) From 504779b8511b36880df13476b4fbb35a6625743f Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Wed, 9 Mar 2022 13:48:01 -0800 Subject: [PATCH 159/377] Fixes for typeshed changes (#12323) Co-authored-by: hauntsaninja <> --- mypy/semanal.py | 2 +- test-data/unit/fixtures/args.pyi | 1 + test-data/unit/lib-stub/typing.pyi | 5 +++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 02ce361ab5d35..db255a7dedc80 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4546,7 +4546,7 @@ def create_getattr_var(self, getattr_defn: SymbolTableNode, def lookup_fully_qualified(self, fullname: str) -> SymbolTableNode: ret = self.lookup_fully_qualified_or_none(fullname) - assert ret is not None + assert ret is not None, fullname return ret def lookup_fully_qualified_or_none(self, fullname: str) -> Optional[SymbolTableNode]: diff --git a/test-data/unit/fixtures/args.pyi b/test-data/unit/fixtures/args.pyi index ffe54375f68e9..8d0ecc00f4b6d 100644 --- a/test-data/unit/fixtures/args.pyi +++ b/test-data/unit/fixtures/args.pyi @@ -27,6 +27,7 @@ class list(Sequence[T], Generic[T]): pass class int: def __eq__(self, o: object) -> bool: pass class str: pass +class bytes: pass class bool: pass class function: pass class ellipsis: pass diff --git a/test-data/unit/lib-stub/typing.pyi b/test-data/unit/lib-stub/typing.pyi index 1a6c5d36a3672..57563fc9d2f60 100644 --- a/test-data/unit/lib-stub/typing.pyi +++ b/test-data/unit/lib-stub/typing.pyi @@ -47,6 +47,11 @@ class Sequence(Iterable[T_co]): # Mapping type is oversimplified intentionally. class Mapping(Iterable[T], Generic[T, T_co]): pass +class Awaitable(Protocol[T]): + def __await__(self) -> Generator[Any, Any, T]: pass + +class Coroutine(Awaitable[V], Generic[T, U, V]): pass + def final(meth: T) -> T: pass def reveal_type(__obj: T) -> T: pass From 3024b3291d4317576f6d689e262d5e1eb1be17f7 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 10 Mar 2022 17:44:52 +0000 Subject: [PATCH 160/377] Update copyright in LICENSE (#12330) --- LICENSE | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 549ff65756112..991496cb4878e 100644 --- a/LICENSE +++ b/LICENSE @@ -4,7 +4,8 @@ Mypy (and mypyc) are licensed under the terms of the MIT license, reproduced bel The MIT License -Copyright (c) 2015-2021 Jukka Lehtosalo and contributors +Copyright (c) 2012-2022 Jukka Lehtosalo and contributors +Copyright (c) 2015-2022 Dropbox, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), From 0d38613d8bd156a793a2f9f0f8f331499ad31531 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 10 Mar 2022 17:45:41 +0000 Subject: [PATCH 161/377] Minor documentation updates (#12329) * Some minor documentation updates * Add more discussion of exhaustiveness checking * Update docs/source/literal_types.rst * Simplify docs for legacy async Co-authored-by: Jelle Zijlstra --- docs/source/config_file.rst | 4 +- docs/source/literal_types.rst | 54 ++++++++++++++++----- docs/source/more_types.rst | 90 +++++++++-------------------------- 3 files changed, 67 insertions(+), 81 deletions(-) diff --git a/docs/source/config_file.rst b/docs/source/config_file.rst index 0b53f1ca53703..6373a5094b3df 100644 --- a/docs/source/config_file.rst +++ b/docs/source/config_file.rst @@ -201,7 +201,7 @@ section of the command line docs. A regular expression that matches file names, directory names and paths which mypy should ignore while recursively discovering files to check. - Use forward slashes on all platforms. + Use forward slashes (``/``) as directory separators on all platforms. .. code-block:: ini @@ -237,7 +237,7 @@ section of the command line docs. [tool.mypy] exclude = [ - "^one\.py$", # TOML's double-quoted strings require escaping backslashes + "^one\\.py$", # TOML's double-quoted strings require escaping backslashes 'two\.pyi$', # but TOML's single-quoted strings do not '^three\.', ] diff --git a/docs/source/literal_types.rst b/docs/source/literal_types.rst index c5df354ce6782..2bca6db71ac79 100644 --- a/docs/source/literal_types.rst +++ b/docs/source/literal_types.rst @@ -292,8 +292,8 @@ using ``isinstance()``: This feature is sometimes called "sum types" or "discriminated union types" in other programming languages. -Exhaustiveness checks -********************* +Exhaustiveness checking +*********************** You may want to check that some code covers all possible ``Literal`` or ``Enum`` cases. Example: @@ -359,6 +359,35 @@ mypy will spot the error: # expected "NoReturn" assert_never(x) +If runtime checking against unexpected values is not needed, you can +leave out the ``assert_never`` call in the above example, and mypy +will still generate an error about function ``validate`` returning +without a value: + +.. code-block:: python + + PossibleValues = Literal['one', 'two', 'three'] + + # Error: Missing return statement + def validate(x: PossibleValues) -> bool: + if x == 'one': + return True + elif x == 'two': + return False + +Exhaustiveness checking is also supported for match statements (Python 3.10 and later): + +.. code-block:: python + + def validate(x: PossibleValues) -> bool: + match x: + case 'one': + return True + case 'two': + return False + assert_never(x) + + Limitations *********** @@ -404,10 +433,10 @@ You can use enums to annotate types as you would expect: Movement(Direction.up, 5.0) # ok Movement('up', 5.0) # E: Argument 1 to "Movemement" has incompatible type "str"; expected "Direction" -Exhaustive checks -***************** +Exhaustiveness checking +*********************** -Similiar to ``Literal`` types ``Enum`` supports exhaustive checks. +Similar to ``Literal`` types, ``Enum`` supports exhaustiveness checking. Let's start with a definition: .. code-block:: python @@ -423,21 +452,22 @@ Let's start with a definition: up = 'up' down = 'down' -Now, let's define an exhaustive check: +Now, let's use an exhaustiveness check: .. code-block:: python def choose_direction(direction: Direction) -> None: if direction is Direction.up: - reveal_type(direction) # N: Revealed type is "Literal[ex.Direction.up]" + reveal_type(direction) # N: Revealed type is "Literal[Direction.up]" print('Going up!') return elif direction is Direction.down: print('Down') return + # This line is never reached assert_never(direction) -And then test that it raises an error when some cases are not covered: +If we forget to handle one of the cases, mypy will generate an error: .. code-block:: python @@ -447,13 +477,13 @@ And then test that it raises an error when some cases are not covered: return assert_never(direction) # E: Argument 1 to "assert_never" has incompatible type "Direction"; expected "NoReturn" +Exhaustiveness checking is also supported for match statements (Python 3.10 and later). + Extra Enum checks ***************** Mypy also tries to support special features of ``Enum`` -the same way Python's runtime does. - -Extra checks: +the same way Python's runtime does: - Any ``Enum`` class with values is implicitly :ref:`final `. This is what happens in CPython: @@ -467,7 +497,7 @@ Extra checks: ... TypeError: Other: cannot extend enumeration 'Some' - We do the same thing: + Mypy also catches this error: .. code-block:: python diff --git a/docs/source/more_types.rst b/docs/source/more_types.rst index 2203022ad73f1..dd688cab7e17b 100644 --- a/docs/source/more_types.rst +++ b/docs/source/more_types.rst @@ -874,68 +874,6 @@ value of type :py:class:`Coroutine[Any, Any, T] `, which is a :ref:`reveal_type() ` displays the inferred static type of an expression. -If you want to use coroutines in Python 3.4, which does not support -the ``async def`` syntax, you can instead use the :py:func:`@asyncio.coroutine ` -decorator to convert a generator into a coroutine. - -Note that we set the ``YieldType`` of the generator to be ``Any`` in the -following example. This is because the exact yield type is an implementation -detail of the coroutine runner (e.g. the :py:mod:`asyncio` event loop) and your -coroutine shouldn't have to know or care about what precisely that type is. - -.. code-block:: python - - from typing import Any, Generator - import asyncio - - @asyncio.coroutine - def countdown_2(tag: str, count: int) -> Generator[Any, None, str]: - while count > 0: - print('T-minus {} ({})'.format(count, tag)) - yield from asyncio.sleep(0.1) - count -= 1 - return "Blastoff!" - - loop = asyncio.get_event_loop() - loop.run_until_complete(countdown_2("USS Enterprise", 5)) - loop.close() - -As before, the result of calling a generator decorated with :py:func:`@asyncio.coroutine ` -will be a value of type :py:class:`Awaitable[T] `. - -.. note:: - - At runtime, you are allowed to add the :py:func:`@asyncio.coroutine ` decorator to - both functions and generators. This is useful when you want to mark a - work-in-progress function as a coroutine, but have not yet added ``yield`` or - ``yield from`` statements: - - .. code-block:: python - - import asyncio - - @asyncio.coroutine - def serialize(obj: object) -> str: - # todo: add yield/yield from to turn this into a generator - return "placeholder" - - However, mypy currently does not support converting functions into - coroutines. Support for this feature will be added in a future version, but - for now, you can manually force the function to be a generator by doing - something like this: - - .. code-block:: python - - from typing import Generator - import asyncio - - @asyncio.coroutine - def serialize(obj: object) -> Generator[None, None, str]: - # todo: add yield/yield from to turn this into a generator - if False: - yield - return "placeholder" - You may also choose to create a subclass of :py:class:`~typing.Awaitable` instead: .. code-block:: python @@ -995,11 +933,29 @@ To create an iterable coroutine, subclass :py:class:`~typing.AsyncIterator`: loop.run_until_complete(countdown_4("Serenity", 5)) loop.close() -For a more concrete example, the mypy repo has a toy webcrawler that -demonstrates how to work with coroutines. One version -`uses async/await `_ -and one -`uses yield from `_. +If you use coroutines in legacy code that was originally written for +Python 3.4, which did not support the ``async def`` syntax, you would +instead use the :py:func:`@asyncio.coroutine ` +decorator to convert a generator into a coroutine, and use a +generator type as the return type: + +.. code-block:: python + + from typing import Any, Generator + import asyncio + + @asyncio.coroutine + def countdown_2(tag: str, count: int) -> Generator[Any, None, str]: + while count > 0: + print('T-minus {} ({})'.format(count, tag)) + yield from asyncio.sleep(0.1) + count -= 1 + return "Blastoff!" + + loop = asyncio.get_event_loop() + loop.run_until_complete(countdown_2("USS Enterprise", 5)) + loop.close() + .. _typeddict: From 3a5b2a996af8e0333e5eebbdbadc9eec3d1f310e Mon Sep 17 00:00:00 2001 From: Jared Hance Date: Mon, 7 Mar 2022 14:50:43 -0800 Subject: [PATCH 162/377] Support MYPY_VERSION for overriding version --- mypy/version.py | 26 ++++++++++++++++++-------- setup.py | 4 +++- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/mypy/version.py b/mypy/version.py index b59c826eab6b3..eb9ec1a76265d 100644 --- a/mypy/version.py +++ b/mypy/version.py @@ -5,12 +5,22 @@ # - Release versions have the form "0.NNN". # - Dev versions have the form "0.NNN+dev" (PLUS sign to conform to PEP 440). # - For 1.0 we'll switch back to 1.2.3 form. -__version__ = '0.950+dev' -base_version = __version__ +base_version = '0.950+dev' +# Overridden by setup.py +__version__ = base_version -mypy_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) -if __version__.endswith('+dev') and git.is_git_repo(mypy_dir) and git.have_git(): - __version__ += '.' + git.git_revision(mypy_dir).decode('utf-8') - if git.is_dirty(mypy_dir): - __version__ += '.dirty' -del mypy_dir + +def setup_compute_version() -> str: + # We allow an environment variable to override version, but we should probably + # enforce that it is consistent with the existing version minus additional information. + if "MYPY_VERSION" in os.environ: + assert os.environ["MYPY_VERSION"].startswith(base_version) + return os.environ["MYPY_VERSION"] + + mypy_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) + if base_version.endswith('+dev') and git.is_git_repo(mypy_dir) and git.have_git(): + version = base_version + '.' + git.git_revision(mypy_dir).decode('utf-8') + if git.is_dirty(mypy_dir): + return version + ".dirty" + return version + return base_version diff --git a/setup.py b/setup.py index c2e46675a26b0..b6247a3a19406 100644 --- a/setup.py +++ b/setup.py @@ -17,7 +17,7 @@ # alternative forms of installing, as suggested by README.md). from setuptools import setup, find_packages from setuptools.command.build_py import build_py -from mypy.version import __version__ as version +from mypy.version import setup_compute_version description = 'Optional static typing for Python' long_description = ''' @@ -32,6 +32,8 @@ types. '''.lstrip() +version = setup_compute_version() + def find_package_data(base, globs, root='mypy'): """Find all interesting data files, for setup(package_data=) From 536bac07a52fc57fcd76ddbde210347b36e88d1e Mon Sep 17 00:00:00 2001 From: jhance Date: Thu, 10 Mar 2022 20:20:23 -0800 Subject: [PATCH 163/377] Error on unused awaitable expressions (#12279) Generates an error when an expression has a type which has a defined __await__ in its MRO but is not used. This includes all builtin awaitable objects (e.g. futures, coroutines, and tasks) but also anything a user might define which is also awaitable. A hint is attached to suggest awaiting. This can be extended in the future to other types of values that may lead to a resource leak if needed, or even exposed as a plugin. We test simple and complex cases (coroutines and user defined classes). We also test that __getattr__ does not create false positives for awaitables. Some tests require fixes, either because they were deliberately not awaiting an awaitable to verify some other logic in mypy, or because reveal_type returns the object, so it was generating an error we would rather simply silence, --- mypy/checker.py | 28 ++++++++++++++++++++-- mypy/errorcodes.py | 9 +++++++ mypy/message_registry.py | 1 + test-data/unit/check-async-await.test | 28 +++++++++++++++++++++- test-data/unit/check-class-namedtuple.test | 2 +- test-data/unit/check-flags.test | 3 ++- 6 files changed, 66 insertions(+), 5 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 31dcf985200be..e0f2398b67fce 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -85,7 +85,7 @@ from mypy.scope import Scope from mypy import state, errorcodes as codes from mypy.traverser import has_return_statement, all_return_statements -from mypy.errorcodes import ErrorCode +from mypy.errorcodes import ErrorCode, UNUSED_AWAITABLE, UNUSED_COROUTINE from mypy.util import is_typeshed_file, is_dunder, is_sunder T = TypeVar('T') @@ -3432,8 +3432,32 @@ def try_infer_partial_type_from_indexed_assignment( [key_type, value_type]) del partial_types[var] + def type_requires_usage(self, typ: Type) -> Optional[Tuple[str, ErrorCode]]: + """Some types require usage in all cases. The classic example is + an unused coroutine. + + In the case that it does require usage, returns a note to attach + to the error message. + """ + proper_type = get_proper_type(typ) + if isinstance(proper_type, Instance): + # We use different error codes for generic awaitable vs coroutine. + # Coroutines are on by default, whereas generic awaitables are not. + if proper_type.type.fullname == "typing.Coroutine": + return ("Are you missing an await?", UNUSED_COROUTINE) + if proper_type.type.get("__await__") is not None: + return ("Are you missing an await?", UNUSED_AWAITABLE) + return None + def visit_expression_stmt(self, s: ExpressionStmt) -> None: - self.expr_checker.accept(s.expr, allow_none_return=True, always_allow_any=True) + expr_type = self.expr_checker.accept(s.expr, allow_none_return=True, always_allow_any=True) + error_note_and_code = self.type_requires_usage(expr_type) + if error_note_and_code: + error_note, code = error_note_and_code + self.fail( + message_registry.TYPE_MUST_BE_USED.format(format_type(expr_type)), s, code=code + ) + self.note(error_note, s, code=code) def visit_return_stmt(self, s: ReturnStmt) -> None: """Type check a return statement.""" diff --git a/mypy/errorcodes.py b/mypy/errorcodes.py index 4407df47d596c..31f1a2fb73eae 100644 --- a/mypy/errorcodes.py +++ b/mypy/errorcodes.py @@ -97,6 +97,9 @@ def __str__(self) -> str: LITERAL_REQ: Final = ErrorCode( "literal-required", "Check that value is a literal", 'General' ) +UNUSED_COROUTINE: Final = ErrorCode( + "unused-coroutine", "Ensure that all coroutines are used", "General" +) # These error codes aren't enabled by default. NO_UNTYPED_DEF: Final[ErrorCode] = ErrorCode( @@ -147,6 +150,12 @@ def __str__(self) -> str: "General", default_enabled=False, ) +UNUSED_AWAITABLE: Final = ErrorCode( + "unused-awaitable", + "Ensure that all awaitable values are used", + "General", + default_enabled=False, +) # Syntax errors are often blocking. diff --git a/mypy/message_registry.py b/mypy/message_registry.py index 1477cc4da575b..68e739b243582 100644 --- a/mypy/message_registry.py +++ b/mypy/message_registry.py @@ -141,6 +141,7 @@ def format(self, *args: object, **kwargs: object) -> "ErrorMessage": PYTHON2_PRINT_FILE_TYPE: Final = ( 'Argument "file" to "print" has incompatible type "{}"; expected "{}"' ) +TYPE_MUST_BE_USED: Final = 'Value of type {} must be used' # Generic GENERIC_INSTANCE_VAR_CLASS_ACCESS: Final = ( diff --git a/test-data/unit/check-async-await.test b/test-data/unit/check-async-await.test index f4bf7c7cfa941..382d788ee904d 100644 --- a/test-data/unit/check-async-await.test +++ b/test-data/unit/check-async-await.test @@ -12,7 +12,7 @@ async def f() -> int: async def f() -> int: return 0 -reveal_type(f()) # N: Revealed type is "typing.Coroutine[Any, Any, builtins.int]" +_ = reveal_type(f()) # N: Revealed type is "typing.Coroutine[Any, Any, builtins.int]" [builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] @@ -799,3 +799,29 @@ async def precise2(futures: Iterable[Awaitable[int]]) -> None: [builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] + +[case testUnusedAwaitable] +# flags: --show-error-codes --enable-error-code unused-awaitable +from typing import Iterable + +async def foo() -> None: + pass + +class A: + def __await__(self) -> Iterable[int]: + yield 5 + +# Things with __getattr__ should not simply be considered awaitable. +class B: + def __getattr__(self, attr) -> object: + return 0 + +def bar() -> None: + A() # E: Value of type "A" must be used [unused-awaitable] \ + # N: Are you missing an await? + foo() # E: Value of type "Coroutine[Any, Any, None]" must be used [unused-coroutine] \ + # N: Are you missing an await? + B() + +[builtins fixtures/async_await.pyi] +[typing fixtures/typing-async.pyi] diff --git a/test-data/unit/check-class-namedtuple.test b/test-data/unit/check-class-namedtuple.test index cf3af49ab3a43..4a1a84ca0301d 100644 --- a/test-data/unit/check-class-namedtuple.test +++ b/test-data/unit/check-class-namedtuple.test @@ -538,7 +538,7 @@ class XRepr(NamedTuple): return 0 reveal_type(XMeth(1).double()) # N: Revealed type is "builtins.int" -reveal_type(XMeth(1).asyncdouble()) # N: Revealed type is "typing.Coroutine[Any, Any, builtins.int]" +_ = reveal_type(XMeth(1).asyncdouble()) # N: Revealed type is "typing.Coroutine[Any, Any, builtins.int]" reveal_type(XMeth(42).x) # N: Revealed type is "builtins.int" reveal_type(XRepr(42).__str__()) # N: Revealed type is "builtins.str" reveal_type(XRepr(1, 2).__sub__(XRepr(3))) # N: Revealed type is "builtins.int" diff --git a/test-data/unit/check-flags.test b/test-data/unit/check-flags.test index 8f72a82b0760d..8ee0adce3c8e8 100644 --- a/test-data/unit/check-flags.test +++ b/test-data/unit/check-flags.test @@ -405,7 +405,8 @@ async def g() -> NoReturn: await f() async def h() -> NoReturn: # E: Implicit return in function which does not return - f() + # Purposely not evaluating coroutine + _ = f() [builtins fixtures/dict.pyi] [typing fixtures/typing-async.pyi] From 1a0a49ae23e4e496ff996b8ab791d82d9334f06b Mon Sep 17 00:00:00 2001 From: Ekin Dursun Date: Fri, 11 Mar 2022 08:24:41 +0300 Subject: [PATCH 164/377] mypyc: Fix overflow in id function (CPyTagged_Id) (#12332) In CPython, the id of an object is its address. It's computed by converting the pointer to an unsigned integer (PyLong_FromVoidPtr). A similar logic is present here, pointer is converted to a Py_ssize_t and CPyTagged_FromSsize_t is called with that integer. There is a problem with that approach: Py_ssize_t cannot hold every pointer value. Sometimes overflow happens and CPyTagged_FromSsize_t is called with a negative integer. With the new approach, the number is checked: If it fits in a Py_ssize_t, CPyTagged_FromSsize_t is called. If not, it is directly converted to a PyObject using PyLong_FromVoidPtr. --- mypyc/lib-rt/CPy.h | 1 + mypyc/lib-rt/int_ops.c | 9 +++++++++ mypyc/lib-rt/misc_ops.c | 2 +- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/mypyc/lib-rt/CPy.h b/mypyc/lib-rt/CPy.h index 987819154abf7..9f5ae52d4e40f 100644 --- a/mypyc/lib-rt/CPy.h +++ b/mypyc/lib-rt/CPy.h @@ -121,6 +121,7 @@ static inline size_t CPy_FindAttrOffset(PyTypeObject *trait, CPyVTableItem *vtab CPyTagged CPyTagged_FromSsize_t(Py_ssize_t value); +CPyTagged CPyTagged_FromVoidPtr(void *ptr); CPyTagged CPyTagged_FromObject(PyObject *object); CPyTagged CPyTagged_StealFromObject(PyObject *object); CPyTagged CPyTagged_BorrowFromObject(PyObject *object); diff --git a/mypyc/lib-rt/int_ops.c b/mypyc/lib-rt/int_ops.c index 1275f2c105776..edf0631416198 100644 --- a/mypyc/lib-rt/int_ops.c +++ b/mypyc/lib-rt/int_ops.c @@ -26,6 +26,15 @@ CPyTagged CPyTagged_FromSsize_t(Py_ssize_t value) { } } +CPyTagged CPyTagged_FromVoidPtr(void *ptr) { + if ((uintptr_t)ptr > PY_SSIZE_T_MAX) { + PyObject *object = PyLong_FromVoidPtr(ptr); + return ((CPyTagged)object) | CPY_INT_TAG; + } else { + return CPyTagged_FromSsize_t((Py_ssize_t)ptr); + } +} + CPyTagged CPyTagged_FromObject(PyObject *object) { int overflow; // The overflow check knows about CPyTagged's width diff --git a/mypyc/lib-rt/misc_ops.c b/mypyc/lib-rt/misc_ops.c index cebd1cf997f83..dcce89d907201 100644 --- a/mypyc/lib-rt/misc_ops.c +++ b/mypyc/lib-rt/misc_ops.c @@ -437,7 +437,7 @@ CPyPickle_GetState(PyObject *obj) } CPyTagged CPyTagged_Id(PyObject *o) { - return CPyTagged_FromSsize_t((Py_ssize_t)o); + return CPyTagged_FromVoidPtr(o); } #define MAX_INT_CHARS 22 From 7ee84c71e851ce373d1824ecc09332caa373148c Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 11 Mar 2022 09:13:25 +0000 Subject: [PATCH 165/377] Revert "Support MYPY_VERSION for overriding version" (#12333) This reverts commit 3a5b2a996af8e0333e5eebbdbadc9eec3d1f310e. --- mypy/version.py | 26 ++++++++------------------ setup.py | 4 +--- 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/mypy/version.py b/mypy/version.py index eb9ec1a76265d..b59c826eab6b3 100644 --- a/mypy/version.py +++ b/mypy/version.py @@ -5,22 +5,12 @@ # - Release versions have the form "0.NNN". # - Dev versions have the form "0.NNN+dev" (PLUS sign to conform to PEP 440). # - For 1.0 we'll switch back to 1.2.3 form. -base_version = '0.950+dev' -# Overridden by setup.py -__version__ = base_version +__version__ = '0.950+dev' +base_version = __version__ - -def setup_compute_version() -> str: - # We allow an environment variable to override version, but we should probably - # enforce that it is consistent with the existing version minus additional information. - if "MYPY_VERSION" in os.environ: - assert os.environ["MYPY_VERSION"].startswith(base_version) - return os.environ["MYPY_VERSION"] - - mypy_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) - if base_version.endswith('+dev') and git.is_git_repo(mypy_dir) and git.have_git(): - version = base_version + '.' + git.git_revision(mypy_dir).decode('utf-8') - if git.is_dirty(mypy_dir): - return version + ".dirty" - return version - return base_version +mypy_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) +if __version__.endswith('+dev') and git.is_git_repo(mypy_dir) and git.have_git(): + __version__ += '.' + git.git_revision(mypy_dir).decode('utf-8') + if git.is_dirty(mypy_dir): + __version__ += '.dirty' +del mypy_dir diff --git a/setup.py b/setup.py index b6247a3a19406..c2e46675a26b0 100644 --- a/setup.py +++ b/setup.py @@ -17,7 +17,7 @@ # alternative forms of installing, as suggested by README.md). from setuptools import setup, find_packages from setuptools.command.build_py import build_py -from mypy.version import setup_compute_version +from mypy.version import __version__ as version description = 'Optional static typing for Python' long_description = ''' @@ -32,8 +32,6 @@ types. '''.lstrip() -version = setup_compute_version() - def find_package_data(base, globs, root='mypy'): """Find all interesting data files, for setup(package_data=) From 0fecec8c72605ec7bae343b28d545c477c726e81 Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Sat, 12 Mar 2022 02:13:48 +0100 Subject: [PATCH 166/377] Fix small conditional overload regression (#12336) Don't merge conditional FuncDef after an unconditional one. --- mypy/fastparse.py | 5 +++++ test-data/unit/check-overloading.test | 26 ++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/mypy/fastparse.py b/mypy/fastparse.py index 483e5eb4bc42f..077d287655fbe 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -486,6 +486,7 @@ def fix_function_overloads(self, stmts: List[Statement]) -> List[Statement]: ret: List[Statement] = [] current_overload: List[OverloadPart] = [] current_overload_name: Optional[str] = None + seen_unconditional_func_def = False last_if_stmt: Optional[IfStmt] = None last_if_overload: Optional[Union[Decorator, FuncDef, OverloadedFuncDef]] = None last_if_stmt_overload_name: Optional[str] = None @@ -498,6 +499,7 @@ def fix_function_overloads(self, stmts: List[Statement]) -> List[Statement]: if ( isinstance(stmt, IfStmt) and len(stmt.body[0].body) == 1 + and seen_unconditional_func_def is False and ( isinstance(stmt.body[0].body[0], (Decorator, OverloadedFuncDef)) or current_overload_name is not None @@ -527,6 +529,8 @@ def fix_function_overloads(self, stmts: List[Statement]) -> List[Statement]: self.fail_merge_overload(last_if_unknown_truth_value) last_if_unknown_truth_value = None current_overload.append(stmt) + if isinstance(stmt, FuncDef): + seen_unconditional_func_def = True elif ( current_overload_name is not None and isinstance(stmt, IfStmt) @@ -583,6 +587,7 @@ def fix_function_overloads(self, stmts: List[Statement]) -> List[Statement]: # most of mypy/mypyc assumes that all the functions in an OverloadedFuncDef are # related, but multiple underscore functions next to each other aren't necessarily # related + seen_unconditional_func_def = False if isinstance(stmt, Decorator) and not unnamed_function(stmt.name): current_overload = [stmt] current_overload_name = stmt.name diff --git a/test-data/unit/check-overloading.test b/test-data/unit/check-overloading.test index 376ce0e304945..0d04074406e65 100644 --- a/test-data/unit/check-overloading.test +++ b/test-data/unit/check-overloading.test @@ -6302,3 +6302,29 @@ if True: def f12(x): ... reveal_type(f12(A())) # N: Revealed type is "__main__.A" [typing fixtures/typing-medium.pyi] + +[case testOverloadIfUnconditionalFuncDef] +# flags: --always-true True --always-false False +from typing import overload + +class A: ... +class B: ... + +# ----- +# Don't merge conditional FuncDef after unconditional one +# ----- + +@overload +def f1(x: A) -> A: ... +@overload +def f1(x: B) -> B: ... +def f1(x): ... + +@overload +def f2(x: A) -> A: ... +if True: + @overload + def f2(x: B) -> B: ... +def f2(x): ... +if True: + def f2(x): ... # E: Name "f2" already defined on line 17 From 61b621b0b00d1943ebd6cf81d8ca32d4ba1a3fd0 Mon Sep 17 00:00:00 2001 From: Mathieu Kniewallner Date: Mon, 14 Mar 2022 04:33:24 +0100 Subject: [PATCH 167/377] Add missing `enable_error_code` to config doc (#12346) This PR adds enable_error_code to the configuration documentation, with a description similar to disable_error_code. It also adds a similar note as the one found for --enable-error-code flag documentation. --- docs/source/config_file.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/source/config_file.rst b/docs/source/config_file.rst index 6373a5094b3df..5cfc5f86e37f1 100644 --- a/docs/source/config_file.rst +++ b/docs/source/config_file.rst @@ -648,6 +648,14 @@ section of the command line docs. Allows disabling one or multiple error codes globally. +.. confval:: enable_error_code + + :type: comma-separated list of strings + + Allows enabling one or multiple error codes globally. + + Note: This option will override disabled error codes from the disable_error_code option. + .. confval:: implicit_reexport :type: boolean From f9dadb13daca61bdf7972c95c36071956e7d3b43 Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Mon, 14 Mar 2022 09:55:13 +0100 Subject: [PATCH 168/377] Fix `__annotations__` being undefined (#10969) --- mypy/nodes.py | 3 ++- mypy/semanal.py | 7 +++++++ mypy/stubtest.py | 1 + test-data/unit/check-basic.test | 28 ++++++---------------------- 4 files changed, 16 insertions(+), 23 deletions(-) diff --git a/mypy/nodes.py b/mypy/nodes.py index f520280dce2df..7680641e659f5 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -106,7 +106,8 @@ def get_column(self) -> int: '__doc__': None, # depends on Python version, see semanal.py '__path__': None, # depends on if the module is a package '__file__': '__builtins__.str', - '__package__': '__builtins__.str' + '__package__': '__builtins__.str', + '__annotations__': None, # dict[str, Any] bounded in add_implicit_module_attrs() } diff --git a/mypy/semanal.py b/mypy/semanal.py index db255a7dedc80..60127961b60e4 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -447,6 +447,13 @@ def add_implicit_module_attrs(self, file_node: MypyFile) -> None: node = sym.node assert isinstance(node, TypeInfo) typ = Instance(node, [self.str_type()]) + elif name == '__annotations__': + sym = self.lookup_qualified("__builtins__.dict", Context(), suppress_errors=True) + if not sym: + continue + node = sym.node + assert isinstance(node, TypeInfo) + typ = Instance(node, [self.str_type(), AnyType(TypeOfAny.special_form)]) else: assert t is not None, 'type should be specified for {}'.format(name) typ = UnboundType(t) diff --git a/mypy/stubtest.py b/mypy/stubtest.py index b568017cfa5f3..ccaf28022d4e1 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -978,6 +978,7 @@ def verify_typealias( "__cached__", "__loader__", "__spec__", + "__annotations__", "__path__", # mypy adds __path__ to packages, but C packages don't have it "__getattr__", # resulting behaviour might be typed explicitly # TODO: remove the following from this list diff --git a/test-data/unit/check-basic.test b/test-data/unit/check-basic.test index 03dee485c8482..238aab3944fff 100644 --- a/test-data/unit/check-basic.test +++ b/test-data/unit/check-basic.test @@ -236,32 +236,16 @@ from typing import Any def f() -> Any: yield -[case testModule__name__] +[case testModuleImplicitAttributes] import typing -x = __name__ # type: str -a = __name__ # type: A # E: Incompatible types in assignment (expression has type "str", variable has type "A") class A: pass +reveal_type(__name__) # N: Revealed type is "builtins.str" +reveal_type(__doc__) # N: Revealed type is "builtins.str" +reveal_type(__file__) # N: Revealed type is "builtins.str" +reveal_type(__package__) # N: Revealed type is "builtins.str" +reveal_type(__annotations__) # N: Revealed type is "builtins.dict[builtins.str, Any]" [builtins fixtures/primitives.pyi] -[case testModule__doc__] -import typing -x = __doc__ # type: str -a = __doc__ # type: A # E: Incompatible types in assignment (expression has type "str", variable has type "A") -class A: pass -[builtins fixtures/primitives.pyi] - -[case testModule__file__] -import typing -x = __file__ # type: str -a = __file__ # type: A # E: Incompatible types in assignment (expression has type "str", variable has type "A") -class A: pass -[builtins fixtures/primitives.pyi] - -[case test__package__] -import typing -x = __package__ # type: str -a = __file__ # type: int # E: Incompatible types in assignment (expression has type "str", variable has type "int") - -- Scoping and shadowing -- --------------------- From 91357952db51a2d7f1c72dd5cc04f0fcb58c9248 Mon Sep 17 00:00:00 2001 From: Chris Rose Date: Mon, 14 Mar 2022 09:07:27 -0700 Subject: [PATCH 169/377] Typeshed cherry-pick: Use import instead of type alias in `email/message.pyi` (#7022) (#12340) Co-authored-by: Chris Rose --- mypy/typeshed/stdlib/email/message.pyi | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mypy/typeshed/stdlib/email/message.pyi b/mypy/typeshed/stdlib/email/message.pyi index 7d5eb4500d8f9..b89c8f8ec167d 100644 --- a/mypy/typeshed/stdlib/email/message.pyi +++ b/mypy/typeshed/stdlib/email/message.pyi @@ -2,7 +2,9 @@ from email.charset import Charset from email.contentmanager import ContentManager from email.errors import MessageDefect from email.policy import Policy -from typing import Any, Generator, Iterator, Optional, Sequence, TypeVar, Union + +# using a type alias ("_HeaderType = Any") breaks mypy, who knows why +from typing import Any, Any as _HeaderType, Generator, Iterator, Optional, Sequence, TypeVar, Union _T = TypeVar("_T") @@ -10,7 +12,6 @@ _PayloadType = Union[list[Message], str, bytes] _CharsetType = Union[Charset, str, None] _ParamsType = Union[str, None, tuple[str, Optional[str], str]] _ParamType = Union[str, tuple[Optional[str], Optional[str], str]] -_HeaderType = Any class Message: policy: Policy # undocumented From b09683cb33ab28b34011acb367161309a1e9af5d Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Tue, 15 Mar 2022 10:03:38 +0000 Subject: [PATCH 170/377] Correct example in `runtime_troubles.rst` (#12356) `SupportsLessThan` was removed from `_typeshed` in https://github.com/python/typeshed/pull/6583 and replaced with a new `SupportsRichComparison` type, which better reflects the types at runtime. Fixes #12355 --- docs/source/runtime_troubles.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/runtime_troubles.rst b/docs/source/runtime_troubles.rst index e748fb000b71d..1bab66194e474 100644 --- a/docs/source/runtime_troubles.rst +++ b/docs/source/runtime_troubles.rst @@ -254,7 +254,7 @@ sections, these can be dealt with by using :ref:`typing.TYPE_CHECKING from typing import TYPE_CHECKING if TYPE_CHECKING: - from _typeshed import SupportsLessThan + from _typeshed import SupportsRichComparison .. _generic-builtins: From e639cfd7778115084cb437b0d26d66e6cb1bc4f4 Mon Sep 17 00:00:00 2001 From: mixed-source <75610070+mixed-source@users.noreply.github.com> Date: Thu, 17 Mar 2022 10:58:19 +0800 Subject: [PATCH 171/377] Add ``type`` to both lists of generic types (#10985) (#12351) Updates documentation for both builtin generic types and `typing` generic types to include `type` and `Type` respectively. --- docs/source/builtin_types.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/source/builtin_types.rst b/docs/source/builtin_types.rst index 6abd5250fc42c..7ff9bd3c38e9e 100644 --- a/docs/source/builtin_types.rst +++ b/docs/source/builtin_types.rst @@ -53,6 +53,7 @@ Type Description ``Iterable[int]`` iterable object containing ints ``Sequence[bool]`` sequence of booleans (read-only) ``Mapping[str, int]`` mapping from ``str`` keys to ``int`` values (read-only) +``type[C]`` type object of ``C`` (``C`` is a class/type variable/union of types) ====================== =============================== The type ``dict`` is a *generic* class, signified by type arguments within @@ -82,6 +83,7 @@ Type Description ``Iterable[int]`` iterable object containing ints ``Sequence[bool]`` sequence of booleans (read-only) ``Mapping[str, int]`` mapping from ``str`` keys to ``int`` values (read-only) +``Type[C]`` type object of ``C`` (``C`` is a class/type variable/union of types) ====================== =============================== ``List`` is an alias for the built-in type ``list`` that supports From aa0d18638bdde631e0fe542e839a7df2dd04ba79 Mon Sep 17 00:00:00 2001 From: jhance Date: Thu, 17 Mar 2022 05:49:13 -0700 Subject: [PATCH 172/377] Add UnpackType type and basic semanal (#12367) Adds very basic support for Unpack expressions (where Unpack is either from typing or typing_extensions). Many of the visitors implementations are not implemented yet. The only supported feature we have so far is validating that the argument to UnpackType actually makes sense. Currently we don't support unions, though. Since TypeVarTuple isn't yet implemented, we don't support that from UnpackType either. We don't want anyone to start using variadic generics at all until we have real support for it. We also don't want to implement it in one huge PR. So mypy is learning a new flag called --enable-incomplete-features which we can enable by default in any testsuite that needs to use incomplete features, as well as pass on the command line for debugging, but it is undocumented and suppressed from the help output so nobody should find it. --- mypy/constraints.py | 6 ++-- mypy/erasetype.py | 5 ++- mypy/expandtype.py | 5 ++- mypy/fixup.py | 6 +++- mypy/indirection.py | 3 ++ mypy/join.py | 6 +++- mypy/main.py | 2 ++ mypy/meet.py | 5 ++- mypy/message_registry.py | 1 + mypy/options.py | 1 + mypy/sametypes.py | 6 +++- mypy/semanal_typeargs.py | 10 +++++- mypy/server/astdiff.py | 6 +++- mypy/server/astmerge.py | 6 +++- mypy/server/deps.py | 5 ++- mypy/subtypes.py | 8 ++++- mypy/test/testsemanal.py | 1 + mypy/type_visitor.py | 12 ++++++- mypy/typeanal.py | 16 ++++++++-- mypy/types.py | 32 +++++++++++++++++++ mypy/typetraverser.py | 6 +++- test-data/unit/lib-stub/typing_extensions.pyi | 2 ++ test-data/unit/semanal-errors.test | 9 ++++++ 23 files changed, 142 insertions(+), 17 deletions(-) diff --git a/mypy/constraints.py b/mypy/constraints.py index 040bcff8c99d3..8a05b527b6bd2 100644 --- a/mypy/constraints.py +++ b/mypy/constraints.py @@ -8,8 +8,7 @@ TupleType, TypedDictType, UnionType, Overloaded, ErasedType, PartialType, DeletedType, UninhabitedType, TypeType, TypeVarId, TypeQuery, is_named_instance, TypeOfAny, LiteralType, ProperType, ParamSpecType, get_proper_type, TypeAliasType, is_union_with_any, - callable_with_ellipsis, - TUPLE_LIKE_INSTANCE_NAMES, + UnpackType, callable_with_ellipsis, TUPLE_LIKE_INSTANCE_NAMES, ) from mypy.maptype import map_instance_to_supertype import mypy.subtypes @@ -404,6 +403,9 @@ def visit_param_spec(self, template: ParamSpecType) -> List[Constraint]: # Can't infer ParamSpecs from component values (only via Callable[P, T]). return [] + def visit_unpack_type(self, template: UnpackType) -> List[Constraint]: + raise NotImplementedError + # Non-leaf types def visit_instance(self, template: Instance) -> List[Constraint]: diff --git a/mypy/erasetype.py b/mypy/erasetype.py index f33b4f3a95cce..e1a0becc8447b 100644 --- a/mypy/erasetype.py +++ b/mypy/erasetype.py @@ -4,7 +4,7 @@ Type, TypeVisitor, UnboundType, AnyType, NoneType, TypeVarId, Instance, TypeVarType, CallableType, TupleType, TypedDictType, UnionType, Overloaded, ErasedType, PartialType, DeletedType, TypeTranslator, UninhabitedType, TypeType, TypeOfAny, LiteralType, ProperType, - get_proper_type, get_proper_types, TypeAliasType, ParamSpecType + get_proper_type, get_proper_types, TypeAliasType, ParamSpecType, UnpackType ) from mypy.nodes import ARG_STAR, ARG_STAR2 @@ -59,6 +59,9 @@ def visit_type_var(self, t: TypeVarType) -> ProperType: def visit_param_spec(self, t: ParamSpecType) -> ProperType: return AnyType(TypeOfAny.special_form) + def visit_unpack_type(self, t: UnpackType) -> ProperType: + raise NotImplementedError + def visit_callable_type(self, t: CallableType) -> ProperType: # We must preserve the fallback type for overload resolution to work. any_type = AnyType(TypeOfAny.special_form) diff --git a/mypy/expandtype.py b/mypy/expandtype.py index ca1bac71cc523..7e1645b75645e 100644 --- a/mypy/expandtype.py +++ b/mypy/expandtype.py @@ -5,7 +5,7 @@ NoneType, Overloaded, TupleType, TypedDictType, UnionType, ErasedType, PartialType, DeletedType, UninhabitedType, TypeType, TypeVarId, FunctionLike, TypeVarType, LiteralType, get_proper_type, ProperType, - TypeAliasType, ParamSpecType, TypeVarLikeType + TypeAliasType, ParamSpecType, TypeVarLikeType, UnpackType ) @@ -111,6 +111,9 @@ def visit_param_spec(self, t: ParamSpecType) -> Type: else: return repl + def visit_unpack_type(self, t: UnpackType) -> Type: + raise NotImplementedError + def visit_callable_type(self, t: CallableType) -> Type: param_spec = t.param_spec() if param_spec is not None: diff --git a/mypy/fixup.py b/mypy/fixup.py index da54c40e733f0..cd10ae9156116 100644 --- a/mypy/fixup.py +++ b/mypy/fixup.py @@ -10,7 +10,8 @@ from mypy.types import ( CallableType, Instance, Overloaded, TupleType, TypedDictType, TypeVarType, UnboundType, UnionType, TypeVisitor, LiteralType, - TypeType, NOT_READY, TypeAliasType, AnyType, TypeOfAny, ParamSpecType + TypeType, NOT_READY, TypeAliasType, AnyType, TypeOfAny, ParamSpecType, + UnpackType, ) from mypy.visitor import NodeVisitor from mypy.lookup import lookup_fully_qualified @@ -251,6 +252,9 @@ def visit_type_var(self, tvt: TypeVarType) -> None: def visit_param_spec(self, p: ParamSpecType) -> None: p.upper_bound.accept(self) + def visit_unpack_type(self, u: UnpackType) -> None: + u.type.accept(self) + def visit_unbound_type(self, o: UnboundType) -> None: for a in o.args: a.accept(self) diff --git a/mypy/indirection.py b/mypy/indirection.py index 238f46c8830f2..9c9959c5f6566 100644 --- a/mypy/indirection.py +++ b/mypy/indirection.py @@ -67,6 +67,9 @@ def visit_type_var(self, t: types.TypeVarType) -> Set[str]: def visit_param_spec(self, t: types.ParamSpecType) -> Set[str]: return set() + def visit_unpack_type(self, t: types.UnpackType) -> Set[str]: + return t.type.accept(self) + def visit_instance(self, t: types.Instance) -> Set[str]: out = self._visit(t.args) if t.type: diff --git a/mypy/join.py b/mypy/join.py index 161c65ea800cd..e11cccb5fa447 100644 --- a/mypy/join.py +++ b/mypy/join.py @@ -7,7 +7,8 @@ Type, AnyType, NoneType, TypeVisitor, Instance, UnboundType, TypeVarType, CallableType, TupleType, TypedDictType, ErasedType, UnionType, FunctionLike, Overloaded, LiteralType, PartialType, DeletedType, UninhabitedType, TypeType, TypeOfAny, get_proper_type, - ProperType, get_proper_types, TypeAliasType, PlaceholderType, ParamSpecType + ProperType, get_proper_types, TypeAliasType, PlaceholderType, ParamSpecType, + UnpackType ) from mypy.maptype import map_instance_to_supertype from mypy.subtypes import ( @@ -256,6 +257,9 @@ def visit_param_spec(self, t: ParamSpecType) -> ProperType: return t return self.default(self.s) + def visit_unpack_type(self, t: UnpackType) -> UnpackType: + raise NotImplementedError + def visit_instance(self, t: Instance) -> ProperType: if isinstance(self.s, Instance): if self.instance_joiner is None: diff --git a/mypy/main.py b/mypy/main.py index d6e16eaf5a625..638bce0ccd772 100644 --- a/mypy/main.py +++ b/mypy/main.py @@ -862,6 +862,8 @@ def add_invertible_flag(flag: str, # Must be followed by another flag or by '--' (and then only file args may follow). parser.add_argument('--cache-map', nargs='+', dest='special-opts:cache_map', help=argparse.SUPPRESS) + parser.add_argument('--enable-incomplete-features', default=False, + help=argparse.SUPPRESS) # options specifying code to check code_group = parser.add_argument_group( diff --git a/mypy/meet.py b/mypy/meet.py index 0b336aa6f8104..e6b62ff13ad87 100644 --- a/mypy/meet.py +++ b/mypy/meet.py @@ -6,7 +6,7 @@ TupleType, TypedDictType, ErasedType, UnionType, PartialType, DeletedType, UninhabitedType, TypeType, TypeOfAny, Overloaded, FunctionLike, LiteralType, ProperType, get_proper_type, get_proper_types, TypeAliasType, TypeGuardedType, - ParamSpecType + ParamSpecType, UnpackType, ) from mypy.subtypes import is_equivalent, is_subtype, is_callable_compatible, is_proper_subtype from mypy.erasetype import erase_type @@ -506,6 +506,9 @@ def visit_param_spec(self, t: ParamSpecType) -> ProperType: else: return self.default(self.s) + def visit_unpack_type(self, t: UnpackType) -> ProperType: + raise NotImplementedError + def visit_instance(self, t: Instance) -> ProperType: if isinstance(self.s, Instance): if t.type == self.s.type: diff --git a/mypy/message_registry.py b/mypy/message_registry.py index 68e739b243582..93a0258cf07a4 100644 --- a/mypy/message_registry.py +++ b/mypy/message_registry.py @@ -152,6 +152,7 @@ def format(self, *args: object, **kwargs: object) -> "ErrorMessage": IMPLICIT_GENERIC_ANY_BUILTIN: Final = ( 'Implicit generic "Any". Use "{}" and specify generic parameters' ) +INVALID_UNPACK = "{} cannot be unpacked (must be tuple or TypeVarTuple)" # TypeVar INCOMPATIBLE_TYPEVAR_VALUE: Final = 'Value of type variable "{}" of {} cannot be {}' diff --git a/mypy/options.py b/mypy/options.py index 58278b1580e88..b0dead4146b58 100644 --- a/mypy/options.py +++ b/mypy/options.py @@ -258,6 +258,7 @@ def __init__(self) -> None: self.dump_type_stats = False self.dump_inference_stats = False self.dump_build_stats = False + self.enable_incomplete_features = False # -- test options -- # Stop after the semantic analysis phase diff --git a/mypy/sametypes.py b/mypy/sametypes.py index 33cd7f0606cf6..70cd216031797 100644 --- a/mypy/sametypes.py +++ b/mypy/sametypes.py @@ -4,7 +4,7 @@ Type, UnboundType, AnyType, NoneType, TupleType, TypedDictType, UnionType, CallableType, TypeVarType, Instance, TypeVisitor, ErasedType, Overloaded, PartialType, DeletedType, UninhabitedType, TypeType, LiteralType, - ProperType, get_proper_type, TypeAliasType, ParamSpecType + ProperType, get_proper_type, TypeAliasType, ParamSpecType, UnpackType ) from mypy.typeops import tuple_fallback, make_simplified_union @@ -102,6 +102,10 @@ def visit_param_spec(self, left: ParamSpecType) -> bool: return (isinstance(self.right, ParamSpecType) and left.id == self.right.id and left.flavor == self.right.flavor) + def visit_unpack_type(self, left: UnpackType) -> bool: + return (isinstance(self.right, UnpackType) and + is_same_type(left.type, self.right.type)) + def visit_callable_type(self, left: CallableType) -> bool: # FIX generics if isinstance(self.right, CallableType): diff --git a/mypy/semanal_typeargs.py b/mypy/semanal_typeargs.py index 50e01145d60a5..0e885f46a7a51 100644 --- a/mypy/semanal_typeargs.py +++ b/mypy/semanal_typeargs.py @@ -10,7 +10,7 @@ from mypy.nodes import TypeInfo, Context, MypyFile, FuncItem, ClassDef, Block, FakeInfo from mypy.types import ( Type, Instance, TypeVarType, AnyType, get_proper_types, TypeAliasType, ParamSpecType, - get_proper_type + UnpackType, TupleType, get_proper_type ) from mypy.mixedtraverser import MixedTraverserVisitor from mypy.subtypes import is_subtype @@ -95,6 +95,14 @@ def visit_instance(self, t: Instance) -> None: t, code=codes.TYPE_VAR) super().visit_instance(t) + def visit_unpack_type(self, typ: UnpackType) -> None: + proper_type = get_proper_type(typ.type) + if isinstance(proper_type, TupleType): + return + if isinstance(proper_type, Instance) and proper_type.type.fullname == "builtins.tuple": + return + self.fail(message_registry.INVALID_UNPACK.format(proper_type), typ) + def check_type_var_values(self, type: TypeInfo, actuals: List[Type], arg_name: str, valids: List[Type], arg_number: int, context: Context) -> None: for actual in get_proper_types(actuals): diff --git a/mypy/server/astdiff.py b/mypy/server/astdiff.py index 12add8efcb3ab..28d9423420b8f 100644 --- a/mypy/server/astdiff.py +++ b/mypy/server/astdiff.py @@ -59,7 +59,8 @@ class level -- these are handled at attribute level (say, 'mod.Cls.method' from mypy.types import ( Type, TypeVisitor, UnboundType, AnyType, NoneType, UninhabitedType, ErasedType, DeletedType, Instance, TypeVarType, CallableType, TupleType, TypedDictType, - UnionType, Overloaded, PartialType, TypeType, LiteralType, TypeAliasType, ParamSpecType + UnionType, Overloaded, PartialType, TypeType, LiteralType, TypeAliasType, ParamSpecType, + UnpackType, ) from mypy.util import get_prefix @@ -317,6 +318,9 @@ def visit_param_spec(self, typ: ParamSpecType) -> SnapshotItem: typ.flavor, snapshot_type(typ.upper_bound)) + def visit_unpack_type(self, typ: UnpackType) -> SnapshotItem: + return ('UnpackType', snapshot_type(typ.type)) + def visit_callable_type(self, typ: CallableType) -> SnapshotItem: # FIX generics return ('CallableType', diff --git a/mypy/server/astmerge.py b/mypy/server/astmerge.py index 8db2b302b8449..24e771fc868a1 100644 --- a/mypy/server/astmerge.py +++ b/mypy/server/astmerge.py @@ -59,7 +59,8 @@ Type, SyntheticTypeVisitor, Instance, AnyType, NoneType, CallableType, ErasedType, DeletedType, TupleType, TypeType, TypedDictType, UnboundType, UninhabitedType, UnionType, Overloaded, TypeVarType, TypeList, CallableArgument, EllipsisType, StarType, LiteralType, - RawExpressionType, PartialType, PlaceholderType, TypeAliasType, ParamSpecType + RawExpressionType, PartialType, PlaceholderType, TypeAliasType, ParamSpecType, + UnpackType ) from mypy.util import get_prefix, replace_object_state from mypy.typestate import TypeState @@ -411,6 +412,9 @@ def visit_type_var(self, typ: TypeVarType) -> None: def visit_param_spec(self, typ: ParamSpecType) -> None: pass + def visit_unpack_type(self, typ: UnpackType) -> None: + typ.type.accept(self) + def visit_typeddict_type(self, typ: TypedDictType) -> None: for value_type in typ.items.values(): value_type.accept(self) diff --git a/mypy/server/deps.py b/mypy/server/deps.py index cee12c9f8aab3..ebd808de6a6df 100644 --- a/mypy/server/deps.py +++ b/mypy/server/deps.py @@ -99,7 +99,7 @@ class 'mod.Cls'. This can also refer to an attribute inherited from a Type, Instance, AnyType, NoneType, TypeVisitor, CallableType, DeletedType, PartialType, TupleType, TypeType, TypeVarType, TypedDictType, UnboundType, UninhabitedType, UnionType, FunctionLike, Overloaded, TypeOfAny, LiteralType, ErasedType, get_proper_type, ProperType, - TypeAliasType, ParamSpecType + TypeAliasType, ParamSpecType, UnpackType ) from mypy.server.trigger import make_trigger, make_wildcard_trigger from mypy.util import correct_relative_import @@ -961,6 +961,9 @@ def visit_param_spec(self, typ: ParamSpecType) -> List[str]: triggers.extend(self.get_type_triggers(typ.upper_bound)) return triggers + def visit_unpack_type(self, typ: UnpackType) -> List[str]: + return typ.type.accept(self) + def visit_typeddict_type(self, typ: TypedDictType) -> List[str]: triggers = [] for item in typ.items.values(): diff --git a/mypy/subtypes.py b/mypy/subtypes.py index a261e3712328b..17caea9db6f5a 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -8,7 +8,7 @@ Instance, TypeVarType, CallableType, TupleType, TypedDictType, UnionType, Overloaded, ErasedType, PartialType, DeletedType, UninhabitedType, TypeType, is_named_instance, FunctionLike, TypeOfAny, LiteralType, get_proper_type, TypeAliasType, ParamSpecType, - TUPLE_LIKE_INSTANCE_NAMES, + UnpackType, TUPLE_LIKE_INSTANCE_NAMES, ) import mypy.applytype import mypy.constraints @@ -327,6 +327,9 @@ def visit_param_spec(self, left: ParamSpecType) -> bool: return True return self._is_subtype(left.upper_bound, self.right) + def visit_unpack_type(self, left: UnpackType) -> bool: + raise NotImplementedError + def visit_callable_type(self, left: CallableType) -> bool: right = self.right if isinstance(right, CallableType): @@ -1357,6 +1360,9 @@ def visit_param_spec(self, left: ParamSpecType) -> bool: return True return self._is_proper_subtype(left.upper_bound, self.right) + def visit_unpack_type(self, left: UnpackType) -> bool: + raise NotImplementedError + def visit_callable_type(self, left: CallableType) -> bool: right = self.right if isinstance(right, CallableType): diff --git a/mypy/test/testsemanal.py b/mypy/test/testsemanal.py index 441f9ab32dbb3..cbe0fb230d7a0 100644 --- a/mypy/test/testsemanal.py +++ b/mypy/test/testsemanal.py @@ -49,6 +49,7 @@ def get_semanal_options(program_text: str, testcase: DataDrivenTestCase) -> Opti options.semantic_analysis_only = True options.show_traceback = True options.python_version = PYTHON3_VERSION + options.enable_incomplete_features = True return options diff --git a/mypy/type_visitor.py b/mypy/type_visitor.py index 99821fa62640c..2adc73c009387 100644 --- a/mypy/type_visitor.py +++ b/mypy/type_visitor.py @@ -23,7 +23,7 @@ RawExpressionType, Instance, NoneType, TypeType, UnionType, TypeVarType, PartialType, DeletedType, UninhabitedType, TypeVarLikeType, UnboundType, ErasedType, StarType, EllipsisType, TypeList, CallableArgument, - PlaceholderType, TypeAliasType, ParamSpecType, get_proper_type + PlaceholderType, TypeAliasType, ParamSpecType, UnpackType, get_proper_type ) @@ -107,6 +107,10 @@ def visit_type_type(self, t: TypeType) -> T: def visit_type_alias_type(self, t: TypeAliasType) -> T: pass + @abstractmethod + def visit_unpack_type(self, t: UnpackType) -> T: + pass + @trait @mypyc_attr(allow_interpreted_subclasses=True) @@ -189,6 +193,9 @@ def visit_param_spec(self, t: ParamSpecType) -> Type: def visit_partial_type(self, t: PartialType) -> Type: return t + def visit_unpack_type(self, t: UnpackType) -> Type: + return t.type.accept(self) + def visit_callable_type(self, t: CallableType) -> Type: return t.copy_modified(arg_types=self.translate_types(t.arg_types), ret_type=t.ret_type.accept(self), @@ -301,6 +308,9 @@ def visit_type_var(self, t: TypeVarType) -> T: def visit_param_spec(self, t: ParamSpecType) -> T: return self.strategy([]) + def visit_unpack_type(self, t: UnpackType) -> T: + return self.query_types([t.type]) + def visit_partial_type(self, t: PartialType) -> T: return self.strategy([]) diff --git a/mypy/typeanal.py b/mypy/typeanal.py index 766e413545536..b40bec6ca3379 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -17,8 +17,9 @@ StarType, PartialType, EllipsisType, UninhabitedType, TypeType, CallableArgument, TypeQuery, union_items, TypeOfAny, LiteralType, RawExpressionType, PlaceholderType, Overloaded, get_proper_type, TypeAliasType, RequiredType, - TypeVarLikeType, ParamSpecType, ParamSpecFlavor, callable_with_ellipsis, - TYPE_ALIAS_NAMES, FINAL_TYPE_NAMES, LITERAL_TYPE_NAMES, ANNOTATED_TYPE_NAMES, + TypeVarLikeType, ParamSpecType, ParamSpecFlavor, UnpackType, + callable_with_ellipsis, TYPE_ALIAS_NAMES, FINAL_TYPE_NAMES, + LITERAL_TYPE_NAMES, ANNOTATED_TYPE_NAMES, ) from mypy.nodes import ( @@ -377,6 +378,14 @@ def try_analyze_special_unbound_type(self, t: UnboundType, fullname: str) -> Opt elif self.anal_type_guard_arg(t, fullname) is not None: # In most contexts, TypeGuard[...] acts as an alias for bool (ignoring its args) return self.named_type('builtins.bool') + elif fullname in ('typing.Unpack', 'typing_extensions.Unpack'): + # We don't want people to try to use this yet. + if not self.options.enable_incomplete_features: + self.fail('"Unpack" is not supported by mypy yet', t) + return AnyType(TypeOfAny.from_error) + return UnpackType( + self.anal_type(t.args[0]), line=t.line, column=t.column, + ) return None def get_omitted_any(self, typ: Type, fullname: Optional[str] = None) -> AnyType: @@ -558,6 +567,9 @@ def visit_type_var(self, t: TypeVarType) -> Type: def visit_param_spec(self, t: ParamSpecType) -> Type: return t + def visit_unpack_type(self, t: UnpackType) -> Type: + raise NotImplementedError + def visit_callable_type(self, t: CallableType, nested: bool = True) -> Type: # Every Callable can bind its own type variables, if they're not in the outer scope with self.tvar_scope_frame(): diff --git a/mypy/types.py b/mypy/types.py index dadbb84fe1c83..4d56ee9359afc 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -764,6 +764,35 @@ def serialize(self) -> JsonDict: assert False, "Synthetic types don't serialize" +class UnpackType(ProperType): + """Type operator Unpack from PEP646. Can be either with Unpack[] + or unpacking * syntax. + + The inner type should be either a TypeVarTuple, a constant size + tuple, or a variable length tuple, or a union of one of those. + """ + __slots__ = ["type"] + + def __init__(self, typ: Type, line: int = -1, column: int = -1) -> None: + super().__init__(line, column) + self.type = typ + + def accept(self, visitor: 'TypeVisitor[T]') -> T: + return visitor.visit_unpack_type(self) + + def serialize(self) -> JsonDict: + return { + ".class": "UnpackType", + "type": self.type.serialize(), + } + + @classmethod + def deserialize(cls, data: JsonDict) -> "UnpackType": + assert data[".class"] == "UnpackType" + typ = data["type"] + return UnpackType(deserialize_type(typ)) + + class AnyType(ProperType): """The type 'Any'.""" @@ -2474,6 +2503,9 @@ def visit_type_alias_type(self, t: TypeAliasType) -> str: return type_str return '' + def visit_unpack_type(self, t: UnpackType) -> str: + return 'Unpack[{}]'.format(t.type.accept(self)) + def list_str(self, a: Iterable[Type]) -> str: """Convert items of an array to strings (pretty-print types) and join the results with commas. diff --git a/mypy/typetraverser.py b/mypy/typetraverser.py index a03784b0406e6..7bfae5aed1c27 100644 --- a/mypy/typetraverser.py +++ b/mypy/typetraverser.py @@ -6,7 +6,8 @@ Type, SyntheticTypeVisitor, AnyType, UninhabitedType, NoneType, ErasedType, DeletedType, TypeVarType, LiteralType, Instance, CallableType, TupleType, TypedDictType, UnionType, Overloaded, TypeType, CallableArgument, UnboundType, TypeList, StarType, EllipsisType, - PlaceholderType, PartialType, RawExpressionType, TypeAliasType, ParamSpecType + PlaceholderType, PartialType, RawExpressionType, TypeAliasType, ParamSpecType, + UnpackType ) @@ -100,6 +101,9 @@ def visit_raw_expression_type(self, t: RawExpressionType) -> None: def visit_type_alias_type(self, t: TypeAliasType) -> None: self.traverse_types(t.args) + def visit_unpack_type(self, t: UnpackType) -> None: + t.type.accept(self) + # Helpers def traverse_types(self, types: Iterable[Type]) -> None: diff --git a/test-data/unit/lib-stub/typing_extensions.pyi b/test-data/unit/lib-stub/typing_extensions.pyi index 38ff331f45d86..7ad334d6a24eb 100644 --- a/test-data/unit/lib-stub/typing_extensions.pyi +++ b/test-data/unit/lib-stub/typing_extensions.pyi @@ -29,6 +29,8 @@ TypeAlias: _SpecialForm TypeGuard: _SpecialForm Never: _SpecialForm +Unpack: _SpecialForm + # Fallback type for all typed dicts (does not exist at runtime). class _TypedDict(Mapping[str, object]): # Needed to make this class non-abstract. It is explicitly declared abstract in diff --git a/test-data/unit/semanal-errors.test b/test-data/unit/semanal-errors.test index 4b1f4ce00da73..1eea55fca799b 100644 --- a/test-data/unit/semanal-errors.test +++ b/test-data/unit/semanal-errors.test @@ -1442,3 +1442,12 @@ TP2: int = ParamSpec('TP2') # E: Cannot declare the type of a parameter specifi from typing_extensions import Annotated # Next line should not crash: class A(Annotated): pass # E: Annotated[...] must have exactly one type argument and at least one annotation + +[case testInvalidUnpackTypes] +from typing_extensions import Unpack +from typing import Tuple + +heterogenous_tuple: Tuple[Unpack[Tuple[int, str]]] +homogenous_tuple: Tuple[Unpack[Tuple[int, ...]]] +bad: Tuple[Unpack[int]] # E: builtins.int cannot be unpacked (must be tuple or TypeVarTuple) +[builtins fixtures/tuple.pyi] From 21d957afc6241c57eaa364c70920e3927ff94fdd Mon Sep 17 00:00:00 2001 From: citruz <3756270+citruz@users.noreply.github.com> Date: Fri, 18 Mar 2022 02:57:02 +0100 Subject: [PATCH 173/377] stubgen: fix handling of Protocol and add testcase (#12129) ### Description This PR fixes #12072 by correctly handling `Protocol` definitions. Previously, the `Protocol` base class was removed when generating type stubs which causes problems with other packages that want to use type definition (because they see it as a regular class, not as a `Protocol`). ## Test Plan Added a testcase to the stubgen testset. Co-authored-by: 97littleleaf11 <11172084+97littleleaf11@users.noreply.github.com> --- mypy/stubgen.py | 6 ++++++ test-data/unit/stubgen.test | 24 ++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/mypy/stubgen.py b/mypy/stubgen.py index dafb446a835a1..6db5aa75d102f 100755 --- a/mypy/stubgen.py +++ b/mypy/stubgen.py @@ -851,6 +851,12 @@ def visit_class_def(self, o: ClassDef) -> None: base_types.append('metaclass=abc.ABCMeta') self.import_tracker.add_import('abc') self.import_tracker.require_name('abc') + elif self.analyzed and o.info.is_protocol: + type_str = 'Protocol' + if o.info.type_vars: + type_str += f'[{", ".join(o.info.type_vars)}]' + base_types.append(type_str) + self.add_typing_import('Protocol') if base_types: self.add('(%s)' % ', '.join(base_types)) self.add(':\n') diff --git a/test-data/unit/stubgen.test b/test-data/unit/stubgen.test index 6592791f9aa39..62fae21df4f4e 100644 --- a/test-data/unit/stubgen.test +++ b/test-data/unit/stubgen.test @@ -2581,6 +2581,30 @@ def f(x: int, y: int) -> int: ... @t.overload def f(x: t.Tuple[int, int]) -> int: ... +[case testProtocol_semanal] +from typing import Protocol, TypeVar + +class P(Protocol): + def f(self, x: int, y: int) -> str: + ... + +T = TypeVar('T') +T2 = TypeVar('T2') +class PT(Protocol[T, T2]): + def f(self, x: T) -> T2: + ... + +[out] +from typing import Protocol, TypeVar + +class P(Protocol): + def f(self, x: int, y: int) -> str: ... +T = TypeVar('T') +T2 = TypeVar('T2') + +class PT(Protocol[T, T2]): + def f(self, x: T) -> T2: ... + [case testNonDefaultKeywordOnlyArgAfterAsterisk] def func(*, non_default_kwarg: bool, default_kwarg: bool = True): ... [out] From fd905502e8d94ae6a97e5120aeb687b4a59516eb Mon Sep 17 00:00:00 2001 From: 97littleleaf11 <11172084+97littleleaf11@users.noreply.github.com> Date: Fri, 18 Mar 2022 09:59:31 +0800 Subject: [PATCH 174/377] Add success msg for only notes output (#12306) --- mypy/dmypy_server.py | 11 +++++------ mypy/main.py | 18 +++++++++--------- mypy/util.py | 11 ++++++----- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/mypy/dmypy_server.py b/mypy/dmypy_server.py index 2f8fc7f119ba2..f2dbc0361f062 100644 --- a/mypy/dmypy_server.py +++ b/mypy/dmypy_server.py @@ -772,12 +772,11 @@ def pretty_messages(self, messages: List[str], n_sources: int, fixed_terminal_width=terminal_width) if self.options.error_summary: summary: Optional[str] = None - if messages: - n_errors, n_files = count_stats(messages) - if n_errors: - summary = self.formatter.format_error(n_errors, n_files, n_sources, - use_color=use_color) - else: + n_errors, n_notes, n_files = count_stats(messages) + if n_errors: + summary = self.formatter.format_error(n_errors, n_files, n_sources, + use_color=use_color) + elif not messages or n_notes == len(messages): summary = self.formatter.format_success(n_sources, use_color) if summary: # Create new list to avoid appending multiple summaries on successive runs. diff --git a/mypy/main.py b/mypy/main.py index 638bce0ccd772..3d98365872509 100644 --- a/mypy/main.py +++ b/mypy/main.py @@ -113,15 +113,15 @@ def main(script_path: Optional[str], if messages: code = 2 if blockers else 1 if options.error_summary: - if messages: - n_errors, n_files = util.count_stats(messages) - if n_errors: - summary = formatter.format_error( - n_errors, n_files, len(sources), blockers=blockers, - use_color=options.color_output - ) - stdout.write(summary + '\n') - else: + n_errors, n_notes, n_files = util.count_stats(messages) + if n_errors: + summary = formatter.format_error( + n_errors, n_files, len(sources), blockers=blockers, + use_color=options.color_output + ) + stdout.write(summary + '\n') + # Only notes should also output success + elif not messages or n_notes == len(messages): stdout.write(formatter.format_success(len(sources), options.color_output) + '\n') stdout.flush() diff --git a/mypy/util.py b/mypy/util.py index 2d6888dd0a2e6..c02e5dcfc9b4a 100644 --- a/mypy/util.py +++ b/mypy/util.py @@ -435,11 +435,12 @@ def check_python_version(program: str) -> None: "please upgrade to 3.6 or newer".format(name=program)) -def count_stats(errors: List[str]) -> Tuple[int, int]: - """Count total number of errors and files in error list.""" - errors = [e for e in errors if ': error:' in e] - files = {e.split(':')[0] for e in errors} - return len(errors), len(files) +def count_stats(messages: List[str]) -> Tuple[int, int, int]: + """Count total number of errors, notes and error_files in message list.""" + errors = [e for e in messages if ': error:' in e] + error_files = {e.split(':')[0] for e in errors} + notes = [e for e in messages if ': note:' in e] + return len(errors), len(notes), len(error_files) def split_words(msg: str) -> List[str]: From 8c8d169565a0b7cd692997a2cf3a689dbff1ffbe Mon Sep 17 00:00:00 2001 From: KotlinIsland <65446343+KotlinIsland@users.noreply.github.com> Date: Sat, 19 Mar 2022 15:58:40 +1000 Subject: [PATCH 175/377] Remove NBSP from test case (#12380) This fixes a test case, the test case included a NBSP which resulted in the test being completely invalid. Now updated the test case to vent the impostor expect the correct result instead. --- test-data/unit/check-flags.test | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test-data/unit/check-flags.test b/test-data/unit/check-flags.test index 8ee0adce3c8e8..a204135777769 100644 --- a/test-data/unit/check-flags.test +++ b/test-data/unit/check-flags.test @@ -1991,7 +1991,8 @@ x.trim() # E: "str" has no attribute "trim" [attr-defined] [case testEnableDifferentErrorCode] # flags: --disable-error-code attr-defined --enable-error-code name-defined --show-error-code x = 'should not be fine' -x.trim() # E: "str" has no attribute "trim" [attr-defined] +x.trim() +y.trim() # E: Name "y" is not defined [name-defined] [case testEnableMultipleErrorCode] # flags: \ From 8d02b47e179722ef421ed7caa983da7d1f219153 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Sat, 19 Mar 2022 08:56:42 -0700 Subject: [PATCH 176/377] dmypy: warn instead of failing if report generation is configured (#10181) ### Description Log a warning instead of failing when `dmypy run` is called on a project that has report generation configured via setup.cfg Resolves #10118 ## Test Plan 1. Built package locally 2. Installed into my virtualenv 3. Created test project with mypy.ini contents: ```ini [mypy] html_report = build/html ``` 1. Ran `dmypy run .` Result: ``` dmypy run . dmypy: ignoring report generation settings. Start/restart cannot generate reports. Daemon started ``` --- mypy/dmypy_server.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mypy/dmypy_server.py b/mypy/dmypy_server.py index f2dbc0361f062..a8a7dd82f665f 100644 --- a/mypy/dmypy_server.py +++ b/mypy/dmypy_server.py @@ -135,10 +135,11 @@ def process_start_options(flags: List[str], allow_sources: bool) -> Options: ['-i'] + flags, require_targets=False, server_options=True ) if options.report_dirs: - sys.exit("dmypy: start/restart cannot generate reports") + print("dmypy: Ignoring report generation settings. Start/restart cannot generate reports.") if options.junit_xml: - sys.exit("dmypy: start/restart does not support --junit-xml; " - "pass it to check/recheck instead") + print("dmypy: Ignoring report generation settings. " + "Start/restart does not support --junit-xml. Pass it to check/recheck instead") + options.junit_xml = None if not options.incremental: sys.exit("dmypy: start/restart should not disable incremental mode") if options.follow_imports not in ('skip', 'error', 'normal'): From abab1cd84f002894022da513075ab6d4cf82b065 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sun, 20 Mar 2022 18:04:32 -0700 Subject: [PATCH 177/377] Fix caching of PEP 561 namespace packages with missing submodules (#12250) Fixes #12232 Another "fail every 2nd run" bug `if not self.is_module(sub_id):`, the parent can come before another child, and we fail to resolve the parent. Co-authored-by: hauntsaninja <> --- mypy/build.py | 30 +++++++++++++++++----------- test-data/unit/check-errorcodes.test | 6 +++--- test-data/unit/cmdline.test | 4 ++-- test-data/unit/pep561.test | 10 ++++++++++ test-data/unit/semanal-errors.test | 2 +- 5 files changed, 34 insertions(+), 18 deletions(-) diff --git a/mypy/build.py b/mypy/build.py index 6513414dd298e..694261411d800 100644 --- a/mypy/build.py +++ b/mypy/build.py @@ -730,20 +730,19 @@ def correct_rel_imp(imp: Union[ImportFrom, ImportAll]) -> str: return new_id res: List[Tuple[int, str, int]] = [] + delayed_res: List[Tuple[int, str, int]] = [] for imp in file.imports: if not imp.is_unreachable: if isinstance(imp, Import): pri = import_priority(imp, PRI_MED) ancestor_pri = import_priority(imp, PRI_LOW) for id, _ in imp.ids: - # We append the target (e.g. foo.bar.baz) - # before the ancestors (e.g. foo and foo.bar) - # so that, if FindModuleCache finds the target - # module in a package marked with py.typed - # underneath a namespace package installed in - # site-packages, (gasp), that cache's - # knowledge of the ancestors can be primed - # when it is asked to find the target. + # We append the target (e.g. foo.bar.baz) before the ancestors (e.g. foo + # and foo.bar) so that, if FindModuleCache finds the target module in a + # package marked with py.typed underneath a namespace package installed in + # site-packages, (gasp), that cache's knowledge of the ancestors + # (aka FindModuleCache.ns_ancestors) can be primed when it is asked to find + # the parent. res.append((pri, id, imp.line)) ancestor_parts = id.split(".")[:-1] ancestors = [] @@ -752,6 +751,7 @@ def correct_rel_imp(imp: Union[ImportFrom, ImportAll]) -> str: res.append((ancestor_pri, ".".join(ancestors), imp.line)) elif isinstance(imp, ImportFrom): cur_id = correct_rel_imp(imp) + any_are_submodules = False all_are_submodules = True # Also add any imported names that are submodules. pri = import_priority(imp, PRI_MED) @@ -759,6 +759,7 @@ def correct_rel_imp(imp: Union[ImportFrom, ImportAll]) -> str: sub_id = cur_id + '.' + name if self.is_module(sub_id): res.append((pri, sub_id, imp.line)) + any_are_submodules = True else: all_are_submodules = False # Add cur_id as a dependency, even if all of the @@ -768,14 +769,19 @@ def correct_rel_imp(imp: Union[ImportFrom, ImportAll]) -> str: # if all of the imports are submodules, do the import at a lower # priority. pri = import_priority(imp, PRI_HIGH if not all_are_submodules else PRI_LOW) - # The imported module goes in after the - # submodules, for the same namespace related - # reasons discussed in the Import case. - res.append((pri, cur_id, imp.line)) + # The imported module goes in after the submodules, for the same namespace + # related reasons discussed in the Import case. + # There is an additional twist: if none of the submodules exist, + # we delay the import in case other imports of other submodules succeed. + if any_are_submodules: + res.append((pri, cur_id, imp.line)) + else: + delayed_res.append((pri, cur_id, imp.line)) elif isinstance(imp, ImportAll): pri = import_priority(imp, PRI_HIGH) res.append((pri, correct_rel_imp(imp), imp.line)) + res.extend(delayed_res) return res def is_module(self, id: str) -> bool: diff --git a/test-data/unit/check-errorcodes.test b/test-data/unit/check-errorcodes.test index a74771108ca20..9fde5ce0d0cc1 100644 --- a/test-data/unit/check-errorcodes.test +++ b/test-data/unit/check-errorcodes.test @@ -596,10 +596,10 @@ if int() is str(): # E: Non-overlapping identity check (left operand type: "int [builtins fixtures/primitives.pyi] [case testErrorCodeMissingModule] -from defusedxml import xyz # E: Cannot find implementation or library stub for module named "defusedxml" [import] \ - # N: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports +from defusedxml import xyz # E: Cannot find implementation or library stub for module named "defusedxml" [import] from nonexistent import foobar # E: Cannot find implementation or library stub for module named "nonexistent" [import] -import nonexistent2 # E: Cannot find implementation or library stub for module named "nonexistent2" [import] +import nonexistent2 # E: Cannot find implementation or library stub for module named "nonexistent2" [import] \ + # N: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports from nonexistent3 import * # E: Cannot find implementation or library stub for module named "nonexistent3" [import] from pkg import bad # E: Module "pkg" has no attribute "bad" [attr-defined] from pkg.bad2 import bad3 # E: Cannot find implementation or library stub for module named "pkg.bad2" [import] diff --git a/test-data/unit/cmdline.test b/test-data/unit/cmdline.test index f29c183f20ba8..918493b8df48c 100644 --- a/test-data/unit/cmdline.test +++ b/test-data/unit/cmdline.test @@ -415,9 +415,9 @@ follow_imports = error [file a.py] / # No error reported [out] -main.py:1: error: Import of "a" ignored -main.py:1: note: (Using --follow-imports=error, module not passed on command line) main.py:2: note: Revealed type is "Any" +main.py:3: error: Import of "a" ignored +main.py:3: note: (Using --follow-imports=error, module not passed on command line) main.py:4: note: Revealed type is "Any" [case testConfigFollowImportsSelective] diff --git a/test-data/unit/pep561.test b/test-data/unit/pep561.test index 364414b202e1c..290cf73b78291 100644 --- a/test-data/unit/pep561.test +++ b/test-data/unit/pep561.test @@ -222,3 +222,13 @@ b.bf(1) [out] testNamespacePkgWStubsWithNamespacePackagesFlag.py:7: error: Argument 1 to "bf" has incompatible type "int"; expected "bool" testNamespacePkgWStubsWithNamespacePackagesFlag.py:8: error: Argument 1 to "bf" has incompatible type "int"; expected "bool" + + +[case testTypedPkgNamespaceRegFromImportTwiceMissing] +# pkgs: typedpkg_ns_a +from typedpkg_ns import b # type: ignore +from typedpkg_ns import a +-- dummy should trigger a second iteration +[file dummy.py.2] +[out] +[out2] diff --git a/test-data/unit/semanal-errors.test b/test-data/unit/semanal-errors.test index 1eea55fca799b..a0efccef59134 100644 --- a/test-data/unit/semanal-errors.test +++ b/test-data/unit/semanal-errors.test @@ -293,8 +293,8 @@ from m.n import x from a.b import * [out] main:2: error: Cannot find implementation or library stub for module named "m.n" -main:2: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports main:3: error: Cannot find implementation or library stub for module named "a.b" +main:3: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports [case testErrorInImportedModule] import m From 8427df1630d434ea7e8778f876a0af024b696c69 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Mon, 21 Mar 2022 02:55:08 -0700 Subject: [PATCH 178/377] find_sources: fix lint (#12403) flake8-bugbear released a new version with new checks. SourceFinder is small (and we don't have many of them), so this isn't a particularly big deal. --- mypy/find_sources.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/find_sources.py b/mypy/find_sources.py index a44648f261edf..25da5b4aa842f 100644 --- a/mypy/find_sources.py +++ b/mypy/find_sources.py @@ -160,7 +160,7 @@ def crawl_up(self, path: str) -> Tuple[str, str]: def crawl_up_dir(self, dir: str) -> Tuple[str, str]: return self._crawl_up_helper(dir) or ("", dir) - @functools.lru_cache() + @functools.lru_cache() # noqa: B019 def _crawl_up_helper(self, dir: str) -> Optional[Tuple[str, str]]: """Given a directory, maybe returns module and base directory. From 47b9f5e2f65d54d3187cbe0719f9619bf608a126 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Mon, 21 Mar 2022 16:51:39 +0000 Subject: [PATCH 179/377] Remove Python 2 test (#12412) This has been failing locally for me, and since Python 2 is EOL, I don't want to figure out how to fix this. --- test-data/unit/pep561.test | 9 --------- 1 file changed, 9 deletions(-) diff --git a/test-data/unit/pep561.test b/test-data/unit/pep561.test index 290cf73b78291..5fd7b5dce6c6b 100644 --- a/test-data/unit/pep561.test +++ b/test-data/unit/pep561.test @@ -82,15 +82,6 @@ reveal_type(a) testTypedPkgStubs_python2.py:3: error: Module "typedpkg" has no attribute "dne" testTypedPkgStubs_python2.py:5: note: Revealed type is "builtins.list[builtins.str]" -[case testTypedPkgSimple_python2] -# pkgs: typedpkg -from typedpkg.sample import ex -from typedpkg import dne -a = ex(['']) -reveal_type(a) -[out] -testTypedPkgSimple_python2.py:5: note: Revealed type is "builtins.tuple[builtins.str, ...]" - [case testTypedPkgSimpleEgg] # pkgs: typedpkg; no-pip from typedpkg.sample import ex From 27938e7007595584192573f80ab8977a534431f0 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Mon, 21 Mar 2022 21:24:12 +0100 Subject: [PATCH 180/377] stubtest: error for read-only property at runtime, but not in stub (#12291) --- mypy/stubtest.py | 29 ++++++++++++++++-- mypy/test/teststubtest.py | 62 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 86 insertions(+), 5 deletions(-) diff --git a/mypy/stubtest.py b/mypy/stubtest.py index ccaf28022d4e1..ae9c71801dfb9 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -773,6 +773,18 @@ def verify_var( yield Error(object_path, "is not present at runtime", stub, runtime) return + if ( + stub.is_initialized_in_class + and is_read_only_property(runtime) + and (stub.is_settable_property or not stub.is_property) + ): + yield Error( + object_path, + "is read-only at runtime but not in the stub", + stub, + runtime + ) + runtime_type = get_mypy_type_of_runtime_value(runtime) if ( runtime_type is not None @@ -805,7 +817,14 @@ def verify_overloadedfuncdef( return if stub.is_property: - # We get here in cases of overloads from property.setter + # Any property with a setter is represented as an OverloadedFuncDef + if is_read_only_property(runtime): + yield Error( + object_path, + "is read-only at runtime but not in the stub", + stub, + runtime + ) return if not is_probably_a_function(runtime): @@ -848,7 +867,7 @@ def verify_typevarexpr( yield None -def _verify_property(stub: nodes.Decorator, runtime: Any) -> Iterator[str]: +def _verify_readonly_property(stub: nodes.Decorator, runtime: Any) -> Iterator[str]: assert stub.func.is_property if isinstance(runtime, property): return @@ -923,7 +942,7 @@ def verify_decorator( yield Error(object_path, "is not present at runtime", stub, runtime) return if stub.func.is_property: - for message in _verify_property(stub, runtime): + for message in _verify_readonly_property(stub, runtime): yield Error(object_path, message, stub, runtime) return @@ -1044,6 +1063,10 @@ def is_probably_a_function(runtime: Any) -> bool: ) +def is_read_only_property(runtime: object) -> bool: + return isinstance(runtime, property) and runtime.fset is None + + def safe_inspect_signature(runtime: Any) -> Optional[inspect.Signature]: try: return inspect.signature(runtime) diff --git a/mypy/test/teststubtest.py b/mypy/test/teststubtest.py index 759942c57ce73..1cdcd34c666c8 100644 --- a/mypy/test/teststubtest.py +++ b/mypy/test/teststubtest.py @@ -547,12 +547,12 @@ def test_property(self) -> Iterator[Case]: stub=""" class Good: @property - def f(self) -> int: ... + def read_only_attr(self) -> int: ... """, runtime=""" class Good: @property - def f(self) -> int: return 1 + def read_only_attr(self): return 1 """, error=None, ) @@ -592,6 +592,38 @@ class BadReadOnly: """, error="BadReadOnly.f", ) + yield Case( + stub=""" + class Y: + @property + def read_only_attr(self) -> int: ... + @read_only_attr.setter + def read_only_attr(self, val: int) -> None: ... + """, + runtime=""" + class Y: + @property + def read_only_attr(self): return 5 + """, + error="Y.read_only_attr", + ) + yield Case( + stub=""" + class Z: + @property + def read_write_attr(self) -> int: ... + @read_write_attr.setter + def read_write_attr(self, val: int) -> None: ... + """, + runtime=""" + class Z: + @property + def read_write_attr(self): return self._val + @read_write_attr.setter + def read_write_attr(self, val): self._val = val + """, + error=None, + ) @collect_cases def test_var(self) -> Iterator[Case]: @@ -630,6 +662,32 @@ def __init__(self): """, error=None, ) + yield Case( + stub=""" + class Y: + read_only_attr: int + """, + runtime=""" + class Y: + @property + def read_only_attr(self): return 5 + """, + error="Y.read_only_attr", + ) + yield Case( + stub=""" + class Z: + read_write_attr: int + """, + runtime=""" + class Z: + @property + def read_write_attr(self): return self._val + @read_write_attr.setter + def read_write_attr(self, val): self._val = val + """, + error=None, + ) @collect_cases def test_type_alias(self) -> Iterator[Case]: From 4de80616b8dd1392bb8dea04eb7c32b57a93e64d Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Mon, 21 Mar 2022 16:17:28 -0700 Subject: [PATCH 181/377] mypy_primer: mention if output is truncated (#12419) Co-authored-by: hauntsaninja <> --- .github/workflows/mypy_primer_comment.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/mypy_primer_comment.yml b/.github/workflows/mypy_primer_comment.yml index 9aa5b7a7131ec..6942efc78e8c9 100644 --- a/.github/workflows/mypy_primer_comment.yml +++ b/.github/workflows/mypy_primer_comment.yml @@ -38,9 +38,8 @@ jobs: fs.writeFileSync("diff.zip", Buffer.from(download.data)); - run: unzip diff.zip - # 30000 bytes is about 300 lines, posting comment fails if too long - run: | - cat diff_*.txt | head -c 30000 | tee fulldiff.txt + cat diff_*.txt | tee fulldiff.txt - name: Post comment id: post-comment @@ -49,7 +48,11 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} script: | const fs = require('fs') - const data = fs.readFileSync('fulldiff.txt', { encoding: 'utf8' }) + let data = fs.readFileSync('fulldiff.txt', { encoding: 'utf8' }) + // posting comment fails if too long, so truncate + if (data.length > 30000) { + data = data.substring(0, 30000) + `\n\n... (truncated ${diff.length - 30000} chars) ...\n` + } console.log("Diff from mypy_primer:") console.log(data) From aabbf471f929cf1540fbe46828b11a4fe4c764b3 Mon Sep 17 00:00:00 2001 From: KotlinIsland Date: Tue, 22 Mar 2022 11:53:53 +1000 Subject: [PATCH 182/377] readme: add pypi badges --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 16436e208cd3b..6b23ddb8a93a7 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,8 @@ Mypy: Static Typing for Python ======================================= +[![Stable Version](https://img.shields.io/pypi/v/mypy?color=blue)](https://pypi.org/project/mypy/) +[![Downloads](https://img.shields.io/pypi/dm/mypy)](https://pypistats.org/packages/mypy) [![Build Status](https://api.travis-ci.com/python/mypy.svg?branch=master)](https://travis-ci.com/python/mypy) [![Documentation Status](https://readthedocs.org/projects/mypy/badge/?version=latest)](https://mypy.readthedocs.io/en/latest/?badge=latest) [![Chat at https://gitter.im/python/typing](https://badges.gitter.im/python/typing.svg)](https://gitter.im/python/typing?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) From 49825a9057d8c52603e91f6b99e4de94ca3d8a66 Mon Sep 17 00:00:00 2001 From: Cibin Mathew <10793628+cibinmathew@users.noreply.github.com> Date: Tue, 22 Mar 2022 09:40:24 +0530 Subject: [PATCH 183/377] Fix: Empty reveal locals ouput (#12400) Fixes https://github.com/python/mypy/issues/12388 Co-authored-by: Cibin Mathew --- mypy/messages.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/mypy/messages.py b/mypy/messages.py index bb69771901056..f067e7e06bd4b 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -1171,9 +1171,12 @@ def reveal_locals(self, type_map: Dict[str, Optional[Type]], context: Context) - # 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])) - self.note("Revealed local types are:", context) - for line in [' {}: {}'.format(k, v) for k, v in sorted_locals.items()]: - self.note(line, context) + if sorted_locals: + self.note("Revealed local types are:", context) + for k, v in sorted_locals.items(): + self.note(' {}: {}'.format(k, v), context) + else: + self.note("There are no locals to reveal", context) def unsupported_type_type(self, item: Type, context: Context) -> None: self.fail('Cannot instantiate type "Type[{}]"'.format(format_type_bare(item)), context) From 718b50eeb872517467fe244992b0cf93d64a92e0 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Tue, 22 Mar 2022 09:55:48 +0000 Subject: [PATCH 184/377] Allow non-final __match_args__ and overriding (#12415) Allow subclasses to override `__match_args__` freely, and don't require `__match_args__` to be final. This matches runtime behavior. For example, if `B` subclasses `A`, `case A(...)` also matches instances of `B`, using the `__match_args__` from `A`. The issue was brough up by @AlexWaygood in https://github.com/python/mypy/pull/12411#issuecomment-1074078992. --- mypy/checker.py | 17 ++++++------ mypy/message_registry.py | 1 + test-data/unit/check-python310.test | 40 ++++++++++++++++++++++++++--- 3 files changed, 47 insertions(+), 11 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index e0f2398b67fce..de33f62592976 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -1439,12 +1439,7 @@ def check_setattr_method(self, typ: Type, context: Context) -> None: self.msg.invalid_signature_for_special_method(typ, context, '__setattr__') def check_match_args(self, var: Var, typ: Type, context: Context) -> None: - """Check that __match_args__ is final and contains literal strings""" - - if not var.is_final: - self.note("__match_args__ must be final for checking of match statements to work", - context, code=codes.LITERAL_REQ) - + """Check that __match_args__ contains literal strings""" typ = get_proper_type(typ) if not isinstance(typ, TupleType) or \ not all([is_string_literal(item) for item in typ.items]): @@ -2276,11 +2271,16 @@ def check_assignment(self, lvalue: Lvalue, rvalue: Expression, infer_lvalue_type # Defer PartialType's super type checking. if (isinstance(lvalue, RefExpr) and - not (isinstance(lvalue_type, PartialType) and lvalue_type.type is None)): + not (isinstance(lvalue_type, PartialType) and + lvalue_type.type is None) and + not (isinstance(lvalue, NameExpr) and lvalue.name == '__match_args__')): if self.check_compatibility_all_supers(lvalue, lvalue_type, rvalue): # We hit an error on this line; don't check for any others return + if isinstance(lvalue, MemberExpr) and lvalue.name == '__match_args__': + self.fail(message_registry.CANNOT_MODIFY_MATCH_ARGS, lvalue) + if lvalue_type: if isinstance(lvalue_type, PartialType) and lvalue_type.type is None: # Try to infer a proper type for a variable with a partial None type. @@ -2377,7 +2377,8 @@ def check_assignment(self, lvalue: Lvalue, rvalue: Expression, infer_lvalue_type if inferred: rvalue_type = self.expr_checker.accept(rvalue) - if not inferred.is_final: + if not (inferred.is_final or (isinstance(lvalue, NameExpr) and + lvalue.name == '__match_args__')): rvalue_type = remove_instance_last_known_values(rvalue_type) self.infer_variable_type(inferred, lvalue, rvalue_type, rvalue) self.check_assignment_to_slots(lvalue) diff --git a/mypy/message_registry.py b/mypy/message_registry.py index 93a0258cf07a4..4d2569587c2d7 100644 --- a/mypy/message_registry.py +++ b/mypy/message_registry.py @@ -247,3 +247,4 @@ def format(self, *args: object, **kwargs: object) -> "ErrorMessage": CLASS_PATTERN_DUPLICATE_KEYWORD_PATTERN: Final = 'Duplicate keyword pattern "{}"' CLASS_PATTERN_UNKNOWN_KEYWORD: Final = 'Class "{}" has no attribute "{}"' MULTIPLE_ASSIGNMENTS_IN_PATTERN: Final = 'Multiple assignments to name "{}" in pattern' +CANNOT_MODIFY_MATCH_ARGS: Final = 'Cannot assign to "__match_args__"' diff --git a/test-data/unit/check-python310.test b/test-data/unit/check-python310.test index 9d56aeb468f74..10a3e56c63693 100644 --- a/test-data/unit/check-python310.test +++ b/test-data/unit/check-python310.test @@ -881,7 +881,7 @@ reveal_type(z) # N: Revealed type is "builtins.int*" [case testMatchNonFinalMatchArgs] class A: - __match_args__ = ("a", "b") # N: __match_args__ must be final for checking of match statements to work + __match_args__ = ("a", "b") a: str b: int @@ -889,8 +889,8 @@ m: object match m: case A(i, j): - reveal_type(i) # N: Revealed type is "Any" - reveal_type(j) # N: Revealed type is "Any" + reveal_type(i) # N: Revealed type is "builtins.str" + reveal_type(j) # N: Revealed type is "builtins.int" [builtins fixtures/tuple.pyi] [case testMatchAnyTupleMatchArgs] @@ -1528,3 +1528,37 @@ class A: class B: def __enter__(self) -> B: ... def __exit__(self, x, y, z) -> None: ... + +[case testOverrideMatchArgs] +class AST: + __match_args__ = () + +class stmt(AST): ... + +class AnnAssign(stmt): + __match_args__ = ('target', 'annotation', 'value', 'simple') + target: str + annotation: int + value: str + simple: int + +reveal_type(AST.__match_args__) # N: Revealed type is "Tuple[]" +reveal_type(stmt.__match_args__) # N: Revealed type is "Tuple[]" +reveal_type(AnnAssign.__match_args__) # N: Revealed type is "Tuple[Literal['target']?, Literal['annotation']?, Literal['value']?, Literal['simple']?]" + +AnnAssign.__match_args__ = ('a', 'b', 'c', 'd') # E: Cannot assign to "__match_args__" +__match_args__ = 0 + +def f(x: AST) -> None: + match x: + case AST(): + reveal_type(x) # N: Revealed type is "__main__.AST" + match x: + case stmt(): + reveal_type(x) # N: Revealed type is "__main__.stmt" + match x: + case AnnAssign(a, b, c, d): + reveal_type(a) # N: Revealed type is "builtins.str" + reveal_type(b) # N: Revealed type is "builtins.int" + reveal_type(c) # N: Revealed type is "builtins.str" +[builtins fixtures/tuple.pyi] From b814ae15aa1897f22e4d1783439aa39fc8c92f4c Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Tue, 22 Mar 2022 09:56:27 +0000 Subject: [PATCH 185/377] Fix crash in match statement if class name is undefined (#12417) Fixes #12416. --- mypy/checkpattern.py | 3 ++- test-data/unit/check-python310.test | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/mypy/checkpattern.py b/mypy/checkpattern.py index 9c6e67db03e11..a20dfb714025f 100644 --- a/mypy/checkpattern.py +++ b/mypy/checkpattern.py @@ -463,7 +463,8 @@ def visit_class_pattern(self, o: ClassPattern) -> PatternType: # Check class type # type_info = o.class_ref.node - assert type_info is not None + if type_info is None: + return PatternType(AnyType(TypeOfAny.from_error), AnyType(TypeOfAny.from_error), {}) if isinstance(type_info, TypeAlias) and not type_info.no_args: self.msg.fail(message_registry.CLASS_PATTERN_GENERIC_TYPE_ALIAS, o) return self.early_non_match() diff --git a/test-data/unit/check-python310.test b/test-data/unit/check-python310.test index 10a3e56c63693..6046b7ec7333d 100644 --- a/test-data/unit/check-python310.test +++ b/test-data/unit/check-python310.test @@ -567,6 +567,20 @@ match m: reveal_type(m) # N: Revealed type is "builtins.tuple[Any, ...]" [builtins fixtures/primitives.pyi] +[case testMatchInvalidClassPattern] +m: object + +match m: + case xyz(y): # E: Name "xyz" is not defined + reveal_type(m) # N: Revealed type is "Any" + reveal_type(y) # E: Cannot determine type of "y" \ + # N: Revealed type is "Any" + +match m: + case xyz(z=x): # E: Name "xyz" is not defined + reveal_type(x) # E: Cannot determine type of "x" \ + # N: Revealed type is "Any" + [case testMatchClassPatternCaptureDataclass] from dataclasses import dataclass From 9551b93d843ec958b7ce35e957c42d392fc0697e Mon Sep 17 00:00:00 2001 From: Petter Friberg Date: Tue, 22 Mar 2022 16:53:38 +0100 Subject: [PATCH 186/377] Support overriding dunder attributes in Enum subclass (#12138) Allows any dunder (`__name__`) attributes except `__members__` (due to it being read-only) to be overridden in enum subclasses. Fixes #12132. --- mypy/checker.py | 24 ++++++++++++---- mypy/message_registry.py | 5 ++++ mypy/semanal.py | 6 ++-- test-data/unit/check-enum.test | 51 ++++++++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+), 7 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index de33f62592976..1dd2035aeec68 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -1829,11 +1829,7 @@ def visit_class_def(self, defn: ClassDef) -> None: if typ.is_protocol and typ.defn.type_vars: self.check_protocol_variance(defn) if not defn.has_incompatible_baseclass and defn.info.is_enum: - for base in defn.info.mro[1:-1]: # we don't need self and `object` - if base.is_enum and base.fullname not in ENUM_BASES: - self.check_final_enum(defn, base) - self.check_enum_bases(defn) - self.check_enum_new(defn) + self.check_enum(defn) def check_final_deletable(self, typ: TypeInfo) -> None: # These checks are only for mypyc. Only perform some checks that are easier @@ -1891,6 +1887,24 @@ def check_init_subclass(self, defn: ClassDef) -> None: # all other bases have already been checked. break + def check_enum(self, defn: ClassDef) -> None: + assert defn.info.is_enum + if defn.info.fullname not in ENUM_BASES: + for sym in defn.info.names.values(): + if (isinstance(sym.node, Var) and sym.node.has_explicit_value and + sym.node.name == '__members__'): + # `__members__` will always be overwritten by `Enum` and is considered + # read-only so we disallow assigning a value to it + self.fail( + message_registry.ENUM_MEMBERS_ATTR_WILL_BE_OVERRIDEN, sym.node + ) + for base in defn.info.mro[1:-1]: # we don't need self and `object` + if base.is_enum and base.fullname not in ENUM_BASES: + self.check_final_enum(defn, base) + + self.check_enum_bases(defn) + self.check_enum_new(defn) + def check_final_enum(self, defn: ClassDef, base: TypeInfo) -> None: for sym in base.names.values(): if self.is_final_enum_value(sym): diff --git a/mypy/message_registry.py b/mypy/message_registry.py index 4d2569587c2d7..787ad83ce373e 100644 --- a/mypy/message_registry.py +++ b/mypy/message_registry.py @@ -206,6 +206,11 @@ def format(self, *args: object, **kwargs: object) -> "ErrorMessage": ) CANNOT_MAKE_DELETABLE_FINAL: Final = ErrorMessage("Deletable attribute cannot be final") +# Enum +ENUM_MEMBERS_ATTR_WILL_BE_OVERRIDEN: Final = ErrorMessage( + 'Assigned "__members__" will be overriden by "Enum" internally' +) + # ClassVar CANNOT_OVERRIDE_INSTANCE_VAR: Final = ErrorMessage( 'Cannot override instance variable (previously declared on base class "{}") with class ' diff --git a/mypy/semanal.py b/mypy/semanal.py index 60127961b60e4..ef10b62086b38 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -116,6 +116,7 @@ ) from mypy.util import ( correct_relative_import, unmangle, module_prefix, is_typeshed_file, unnamed_function, + is_dunder, ) from mypy.scope import Scope from mypy.semanal_shared import ( @@ -2480,8 +2481,9 @@ def store_final_status(self, s: AssignmentStmt) -> None: cur_node = self.type.names.get(lval.name, None) if (cur_node and isinstance(cur_node.node, Var) and not (isinstance(s.rvalue, TempNode) and s.rvalue.no_rhs)): - cur_node.node.is_final = True - s.is_final_def = True + # Double underscored members are writable on an `Enum`. + # (Except read-only `__members__` but that is handled in type checker) + cur_node.node.is_final = s.is_final_def = not is_dunder(cur_node.node.name) # Special case: deferred initialization of a final attribute in __init__. # In this case we just pretend this is a valid final definition to suppress diff --git a/test-data/unit/check-enum.test b/test-data/unit/check-enum.test index 78460909cd6a7..9e2b38bd9c8df 100644 --- a/test-data/unit/check-enum.test +++ b/test-data/unit/check-enum.test @@ -2029,3 +2029,54 @@ class C(Enum): C._ignore_ # E: "Type[C]" has no attribute "_ignore_" [typing fixtures/typing-medium.pyi] + +[case testCanOverrideDunderAttributes] +import typing +from enum import Enum, Flag + +class BaseEnum(Enum): + __dunder__ = 1 + __labels__: typing.Dict[int, str] + +class Override(BaseEnum): + __dunder__ = 2 + __labels__ = {1: "1"} + +Override.__dunder__ = 3 +BaseEnum.__dunder__ = 3 +Override.__labels__ = {2: "2"} + +class FlagBase(Flag): + __dunder__ = 1 + __labels__: typing.Dict[int, str] + +class FlagOverride(FlagBase): + __dunder__ = 2 + __labels = {1: "1"} + +FlagOverride.__dunder__ = 3 +FlagBase.__dunder__ = 3 +FlagOverride.__labels__ = {2: "2"} +[builtins fixtures/dict.pyi] + +[case testCanNotInitialize__members__] +import typing +from enum import Enum + +class WritingMembers(Enum): + __members__: typing.Dict[Enum, Enum] = {} # E: Assigned "__members__" will be overriden by "Enum" internally + +class OnlyAnnotatedMembers(Enum): + __members__: typing.Dict[Enum, Enum] +[builtins fixtures/dict.pyi] + +[case testCanOverrideDunderOnNonFirstBaseEnum] +import typing +from enum import Enum + +class Some: + __labels__: typing.Dict[int, str] + +class A(Some, Enum): + __labels__ = {1: "1"} +[builtins fixtures/dict.pyi] From e0f16ed027ff7bcd30d9a4dffebe95c101447b8d Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Tue, 22 Mar 2022 16:26:38 +0000 Subject: [PATCH 187/377] Fix inheritance false positives with dataclasses/attrs (#12411) Multiple inheritance from dataclasses and attrs classes works at runtime, so don't complain about `__match_args__` or `__attrs_attrs__` which tend to have incompatible types in subclasses. Fixes #12349. Fixes #12008. Fixes #12065. --- mypy/checker.py | 21 +++++++++------------ mypy/nodes.py | 5 ++++- mypy/plugins/attrs.py | 2 +- mypy/plugins/common.py | 7 ++++++- mypy/plugins/dataclasses.py | 2 +- mypy/semanal.py | 12 +++++++++--- test-data/unit/check-attr.test | 16 ++++++++++++++++ test-data/unit/check-dataclasses.test | 16 ++++++++++++++++ 8 files changed, 62 insertions(+), 19 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 1dd2035aeec68..e6c22a99c5028 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -2112,8 +2112,9 @@ class C(B, A[int]): ... # this is unsafe because... self.msg.cant_override_final(name, base2.name, ctx) if is_final_node(first.node): self.check_if_final_var_override_writable(name, second.node, ctx) - # __slots__ and __deletable__ are special and the type can vary across class hierarchy. - if name in ('__slots__', '__deletable__'): + # Some attributes like __slots__ and __deletable__ are special, and the type can + # vary across class hierarchy. + if isinstance(second.node, Var) and second.node.allow_incompatible_override: ok = True if not ok: self.msg.base_class_definitions_incompatible(name, base1, base2, @@ -2475,16 +2476,12 @@ def check_compatibility_all_supers(self, lvalue: RefExpr, lvalue_type: Optional[ last_immediate_base = direct_bases[-1] if direct_bases else None for base in lvalue_node.info.mro[1:]: - # Only check __slots__ against the 'object' - # If a base class defines a Tuple of 3 elements, a child of - # this class should not be allowed to define it as a Tuple of - # anything other than 3 elements. The exception to this rule - # is __slots__, where it is allowed for any child class to - # redefine it. - if lvalue_node.name == "__slots__" and base.fullname != "builtins.object": - continue - # We don't care about the type of "__deletable__". - if lvalue_node.name == "__deletable__": + # The type of "__slots__" and some other attributes usually doesn't need to + # be compatible with a base class. We'll still check the type of "__slots__" + # against "object" as an exception. + if (isinstance(lvalue_node, Var) and lvalue_node.allow_incompatible_override and + not (lvalue_node.name == "__slots__" and + base.fullname == "builtins.object")): continue if is_private(lvalue_node.name): diff --git a/mypy/nodes.py b/mypy/nodes.py index 7680641e659f5..98402ab9b71b0 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -853,7 +853,7 @@ def deserialize(cls, data: JsonDict) -> 'Decorator': 'is_classmethod', 'is_property', 'is_settable_property', 'is_suppressed_import', 'is_classvar', 'is_abstract_var', 'is_final', 'final_unset_in_class', 'final_set_in_init', 'explicit_self_type', 'is_ready', 'from_module_getattr', - 'has_explicit_value', + 'has_explicit_value', 'allow_incompatible_override', ] @@ -885,6 +885,7 @@ class Var(SymbolNode): 'explicit_self_type', 'from_module_getattr', 'has_explicit_value', + 'allow_incompatible_override', ) def __init__(self, name: str, type: 'Optional[mypy.types.Type]' = None) -> None: @@ -932,6 +933,8 @@ def __init__(self, name: str, type: 'Optional[mypy.types.Type]' = None) -> None: # Var can be created with an explicit value `a = 1` or without one `a: int`, # we need a way to tell which one is which. self.has_explicit_value = False + # If True, subclasses can override this with an incompatible type. + self.allow_incompatible_override = False @property def name(self) -> str: diff --git a/mypy/plugins/attrs.py b/mypy/plugins/attrs.py index a82b7d9bdfeed..9e4b80c905cfb 100644 --- a/mypy/plugins/attrs.py +++ b/mypy/plugins/attrs.py @@ -744,6 +744,7 @@ def _add_attrs_magic_attribute(ctx: 'mypy.plugin.ClassDefContext', var.info = ctx.cls.info var.is_classvar = True var._fullname = f"{ctx.cls.fullname}.{MAGIC_ATTR_CLS_NAME}" + var.allow_incompatible_override = True ctx.cls.info.names[MAGIC_ATTR_NAME] = SymbolTableNode( kind=MDEF, node=var, @@ -778,7 +779,6 @@ def _add_match_args(ctx: 'mypy.plugin.ClassDefContext', cls=ctx.cls, name='__match_args__', typ=match_args, - final=True, ) diff --git a/mypy/plugins/common.py b/mypy/plugins/common.py index 40ac03e30a504..90db614404bd2 100644 --- a/mypy/plugins/common.py +++ b/mypy/plugins/common.py @@ -5,7 +5,7 @@ FuncDef, PassStmt, RefExpr, SymbolTableNode, Var, JsonDict, ) from mypy.plugin import CheckerPluginInterface, ClassDefContext, SemanticAnalyzerPluginInterface -from mypy.semanal import set_callable_name +from mypy.semanal import set_callable_name, ALLOW_INCOMPATIBLE_OVERRIDE from mypy.types import ( CallableType, Overloaded, Type, TypeVarType, deserialize_type, get_proper_type, ) @@ -163,6 +163,7 @@ def add_attribute_to_class( typ: Type, final: bool = False, no_serialize: bool = False, + override_allow_incompatible: bool = False, ) -> None: """ Adds a new attribute to a class definition. @@ -180,6 +181,10 @@ def add_attribute_to_class( node = Var(name, typ) node.info = info node.is_final = final + if name in ALLOW_INCOMPATIBLE_OVERRIDE: + node.allow_incompatible_override = True + else: + node.allow_incompatible_override = override_allow_incompatible node._fullname = info.fullname + '.' + name info.names[name] = SymbolTableNode( MDEF, diff --git a/mypy/plugins/dataclasses.py b/mypy/plugins/dataclasses.py index 091c627f5c1b1..211f0a8dda839 100644 --- a/mypy/plugins/dataclasses.py +++ b/mypy/plugins/dataclasses.py @@ -227,7 +227,7 @@ def transform(self) -> None: literals: List[Type] = [LiteralType(attr.name, str_type) for attr in attributes if attr.is_in_init] match_args_type = TupleType(literals, ctx.api.named_type("builtins.tuple")) - add_attribute_to_class(ctx.api, ctx.cls, "__match_args__", match_args_type, final=True) + add_attribute_to_class(ctx.api, ctx.cls, "__match_args__", match_args_type) self._add_dataclass_fields_magic_attribute() diff --git a/mypy/semanal.py b/mypy/semanal.py index ef10b62086b38..ea5ccb73c05f0 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -153,6 +153,10 @@ # available very early on. CORE_BUILTIN_CLASSES: Final = ["object", "bool", "function"] +# Subclasses can override these Var attributes with incompatible types. This can also be +# set for individual attributes using 'allow_incompatible_override' of Var. +ALLOW_INCOMPATIBLE_OVERRIDE: Final = ('__slots__', '__deletable__', '__match_args__') + # Used for tracking incomplete references Tag: _TypeAlias = int @@ -2917,18 +2921,20 @@ def make_name_lvalue_var( self, lvalue: NameExpr, kind: int, inferred: bool, has_explicit_value: bool, ) -> Var: """Return a Var node for an lvalue that is a name expression.""" - v = Var(lvalue.name) + name = lvalue.name + v = Var(name) v.set_line(lvalue) v.is_inferred = inferred if kind == MDEF: assert self.type is not None v.info = self.type v.is_initialized_in_class = True + v.allow_incompatible_override = name in ALLOW_INCOMPATIBLE_OVERRIDE if kind != LDEF: - v._fullname = self.qualified_name(lvalue.name) + v._fullname = self.qualified_name(name) else: # fullanme should never stay None - v._fullname = lvalue.name + v._fullname = name v.is_ready = False # Type not inferred yet v.has_explicit_value = has_explicit_value return v diff --git a/test-data/unit/check-attr.test b/test-data/unit/check-attr.test index 1fc811d93dc9e..7905f1add6ca7 100644 --- a/test-data/unit/check-attr.test +++ b/test-data/unit/check-attr.test @@ -1539,3 +1539,19 @@ n: NoMatchArgs reveal_type(n.__match_args__) # E: "NoMatchArgs" has no attribute "__match_args__" \ # N: Revealed type is "Any" [builtins fixtures/attr.pyi] + +[case testAttrsMultipleInheritance] +# flags: --python-version 3.10 +import attr + +@attr.s +class A: + x = attr.ib(type=int) + +@attr.s +class B: + y = attr.ib(type=int) + +class AB(A, B): + pass +[builtins fixtures/attr.pyi] diff --git a/test-data/unit/check-dataclasses.test b/test-data/unit/check-dataclasses.test index eed329bb59c7a..1773ac0eac8d7 100644 --- a/test-data/unit/check-dataclasses.test +++ b/test-data/unit/check-dataclasses.test @@ -1536,3 +1536,19 @@ A(a=1, b=2) A(1) A(a="foo") # E: Argument "a" to "A" has incompatible type "str"; expected "int" [builtins fixtures/dataclasses.pyi] + +[case testDataclassesMultipleInheritanceWithNonDataclass] +# flags: --python-version 3.10 +from dataclasses import dataclass + +@dataclass +class A: + prop_a: str + +@dataclass +class B: + prop_b: bool + +class Derived(A, B): + pass +[builtins fixtures/dataclasses.pyi] From efe9a31f65f0204d674ea761b58b640fb7031248 Mon Sep 17 00:00:00 2001 From: Max Shvets Date: Sat, 22 Jan 2022 17:45:12 +0200 Subject: [PATCH 188/377] Implement close method for generators --- mypyc/irbuild/generator.py | 49 +++++++++++++++++++--- mypyc/test-data/fixtures/ir.py | 2 + mypyc/test-data/run-generators.test | 65 +++++++++++++++++++++++++++++ 3 files changed, 111 insertions(+), 5 deletions(-) diff --git a/mypyc/irbuild/generator.py b/mypyc/irbuild/generator.py index 39d30cf74eebe..7655939b44128 100644 --- a/mypyc/irbuild/generator.py +++ b/mypyc/irbuild/generator.py @@ -15,12 +15,16 @@ from mypyc.common import SELF_NAME, NEXT_LABEL_ATTR_NAME, ENV_ATTR_NAME from mypyc.ir.ops import ( BasicBlock, Call, Return, Goto, Integer, SetAttr, Unreachable, RaiseStandardError, - Value, Register + Value, Register, MethodCall, TupleSet, Branch, NO_TRACEBACK_LINE_NO ) from mypyc.ir.rtypes import RInstance, int_rprimitive, object_rprimitive from mypyc.ir.func_ir import FuncIR, FuncDecl, FuncSignature, RuntimeArg from mypyc.ir.class_ir import ClassIR -from mypyc.primitives.exc_ops import raise_exception_with_tb_op +from mypyc.irbuild.nonlocalcontrol import ExceptNonlocalControl +from mypyc.primitives.exc_ops import ( + raise_exception_with_tb_op, error_catch_op, exc_matches_op, reraise_exception_op, + restore_exc_info_op +) from mypyc.irbuild.env_class import ( add_args_to_env, load_outer_env, load_env_registers, finalize_env_class ) @@ -220,11 +224,46 @@ def add_throw_to_generator_class(builder: IRBuilder, def add_close_to_generator_class(builder: IRBuilder, fn_info: FuncInfo) -> None: """Generates the '__close__' method for a generator class.""" - # TODO: Currently this method just triggers a runtime error. - # We should fill this out (https://github.com/mypyc/mypyc/issues/790). with builder.enter_method(fn_info.generator_class.ir, 'close', object_rprimitive, fn_info): + except_block, else_block = BasicBlock(), BasicBlock() + builder.builder.push_error_handler(except_block) + builder.goto_and_activate(BasicBlock()) + generator_exit = builder.load_module_attr_by_fullname('builtins.GeneratorExit', + fn_info.fitem.line) + builder.add(MethodCall( + builder.self(), + 'throw', + [generator_exit, builder.none_object(), builder.none_object()])) + builder.goto(else_block) + builder.builder.pop_error_handler() + + builder.activate_block(except_block) + old_exc = builder.call_c(error_catch_op, [], fn_info.fitem.line) + builder.nonlocal_control.append( + ExceptNonlocalControl(builder.nonlocal_control[-1], old_exc)) + stop_iteration = builder.load_module_attr_by_fullname('builtins.StopIteration', + fn_info.fitem.line) + exceptions = builder.add( + TupleSet([generator_exit, stop_iteration], fn_info.fitem.line)) + matches = builder.call_c( + exc_matches_op, [exceptions], fn_info.fitem.line) + + match_block, non_match_block = BasicBlock(), BasicBlock() + builder.add(Branch(matches, match_block, non_match_block, Branch.BOOL)) + + builder.activate_block(match_block) + builder.call_c(restore_exc_info_op, [builder.read(old_exc)], fn_info.fitem.line) + builder.add(Return(builder.none_object())) + + builder.activate_block(non_match_block) + builder.call_c(reraise_exception_op, [], NO_TRACEBACK_LINE_NO) + builder.add(Unreachable()) + + builder.nonlocal_control.pop() + + builder.activate_block(else_block) builder.add(RaiseStandardError(RaiseStandardError.RUNTIME_ERROR, - 'close method on generator classes unimplemented', + 'generator ignored GeneratorExit', fn_info.fitem.line)) builder.add(Unreachable()) diff --git a/mypyc/test-data/fixtures/ir.py b/mypyc/test-data/fixtures/ir.py index 786f77143e9ee..a661067845ac5 100644 --- a/mypyc/test-data/fixtures/ir.py +++ b/mypyc/test-data/fixtures/ir.py @@ -276,6 +276,8 @@ class ArithmeticError(Exception): pass class ZeroDivisionError(Exception): pass +class GeneratorExit(BaseException): pass + def any(i: Iterable[T]) -> bool: pass def all(i: Iterable[T]) -> bool: pass def sum(i: Iterable[T]) -> int: pass diff --git a/mypyc/test-data/run-generators.test b/mypyc/test-data/run-generators.test index 3f34c732b5227..b2f244b900086 100644 --- a/mypyc/test-data/run-generators.test +++ b/mypyc/test-data/run-generators.test @@ -516,3 +516,68 @@ class E: [file driver.py] # really I only care it builds + +[case testCloseStopIterationRaised] +def g() -> object: + try: + yield 1 + except GeneratorExit: + raise + +[file driver.py] +from native import g + +gen = g() +next(gen) +gen.close() + +[case testCloseGeneratorExitRaised] +def g() -> object: + yield 1 + +[file driver.py] +from native import g + +gen = g() +next(gen) +gen.close() + +[case testCloseGeneratorExitIgnored] +def g() -> object: + try: + yield 1 + except GeneratorExit: + pass + + yield 2 + +[file driver.py] +from native import g + +gen = g() +next(gen) +try: + gen.close() +except RuntimeError as e: + assert str(e) == 'generator ignored GeneratorExit' +else: + assert False + +[case testCloseGeneratorRaisesAnotherException] +def g() -> object: + try: + yield 1 + except GeneratorExit: + raise RuntimeError("error") + +[file driver.py] +from native import g + +gen = g() +next(gen) +try: + gen.close() +except RuntimeError as e: + assert str(e) == 'error' +else: + assert False From fd8a15e1abdd2bb4f75c3a6319ebfba233e1fe8e Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Wed, 23 Mar 2022 13:33:38 +0000 Subject: [PATCH 189/377] Make order of processing the builtins SCC predictable (#12431) Various things can go wrong if the order of modules in the builtins SCC that also includes typing, _typeshed and others is adjusted. Hopefully fixes #12422. May also fix #12421. --- mypy/build.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/mypy/build.py b/mypy/build.py index 694261411d800..f7a9e9e05e1d3 100644 --- a/mypy/build.py +++ b/mypy/build.py @@ -2965,12 +2965,16 @@ def process_graph(graph: Graph, manager: BuildManager) -> None: # Order the SCC's nodes using a heuristic. # Note that ascc is a set, and scc is a list. scc = order_ascc(graph, ascc) - # If builtins is in the list, move it last. (This is a bit of - # a hack, but it's necessary because the builtins module is - # part of a small cycle involving at least {builtins, abc, - # typing}. Of these, builtins must be processed last or else - # some builtin objects will be incompletely processed.) + # Make the order of the SCC that includes 'builtins' and 'typing', + # among other things, predictable. Various things may break if + # the order changes. if 'builtins' in ascc: + scc = sorted(scc, reverse=True) + # If builtins is in the list, move it last. (This is a bit of + # a hack, but it's necessary because the builtins module is + # part of a small cycle involving at least {builtins, abc, + # typing}. Of these, builtins must be processed last or else + # some builtin objects will be incompletely processed.) scc.remove('builtins') scc.append('builtins') if manager.options.verbosity >= 2: From 3751e382dd3474b75fb4cdfc4f255e433aef555d Mon Sep 17 00:00:00 2001 From: jhance Date: Wed, 23 Mar 2022 12:38:23 -0700 Subject: [PATCH 190/377] Pin the version of bugbear (#12436) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index f1c0fa68e34f8..a3d11872fd5ca 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -2,7 +2,7 @@ -r build-requirements.txt attrs>=18.0 flake8==3.9.2 -flake8-bugbear +flake8-bugbear==22.3.20 flake8-pyi>=20.5 lxml>=4.4.0; python_version<'3.11' psutil>=4.0 From fa9921a49dfc5982e221af474b05191160a7f763 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0t=C4=9Bp=C3=A1n=20Hor=C3=A1=C4=8Dek?= <4643182+shoracek@users.noreply.github.com> Date: Wed, 23 Mar 2022 23:47:26 +0100 Subject: [PATCH 191/377] semanal: Check that async for/with is inside an async function (#12418) * semanal: Disallow async for/with in non-async functions * Fix invalid async syntax in test --- mypy/message_registry.py | 3 ++ mypy/semanal.py | 20 ++++++++++++ test-data/unit/check-async-await.test | 39 ++++++++++++++++++++++++ test-data/unit/check-default-plugin.test | 5 +-- 4 files changed, 65 insertions(+), 2 deletions(-) diff --git a/mypy/message_registry.py b/mypy/message_registry.py index 787ad83ce373e..78fe07f70c92b 100644 --- a/mypy/message_registry.py +++ b/mypy/message_registry.py @@ -61,6 +61,9 @@ def format(self, *args: object, **kwargs: object) -> "ErrorMessage": ) INCOMPATIBLE_TYPES_IN_ASYNC_FOR: Final = 'Incompatible types in "async for"' +ASYNC_FOR_OUTSIDE_COROUTINE: Final = '"async for" outside async function' +ASYNC_WITH_OUTSIDE_COROUTINE: Final = '"async with" outside async function' + INCOMPATIBLE_TYPES_IN_YIELD: Final = ErrorMessage('Incompatible types in "yield"') INCOMPATIBLE_TYPES_IN_YIELD_FROM: Final = ErrorMessage('Incompatible types in "yield from"') INCOMPATIBLE_TYPES_IN_STR_INTERPOLATION: Final = "Incompatible types in string interpolation" diff --git a/mypy/semanal.py b/mypy/semanal.py index ea5ccb73c05f0..eded9a5ea913b 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -3621,6 +3621,10 @@ def visit_while_stmt(self, s: WhileStmt) -> None: self.visit_block_maybe(s.else_body) def visit_for_stmt(self, s: ForStmt) -> None: + if s.is_async: + if not self.is_func_scope() or not self.function_stack[-1].is_coroutine: + self.fail(message_registry.ASYNC_FOR_OUTSIDE_COROUTINE, s, code=codes.SYNTAX) + self.statement = s s.expr.accept(self) @@ -3680,6 +3684,10 @@ def visit_with_stmt(self, s: WithStmt) -> None: self.statement = s types: List[Type] = [] + if s.is_async: + if not self.is_func_scope() or not self.function_stack[-1].is_coroutine: + self.fail(message_registry.ASYNC_WITH_OUTSIDE_COROUTINE, s, code=codes.SYNTAX) + if s.unanalyzed_type: assert isinstance(s.unanalyzed_type, ProperType) actual_targets = [t for t in s.target if t is not None] @@ -4175,12 +4183,24 @@ def visit_type_application(self, expr: TypeApplication) -> None: expr.types[i] = analyzed def visit_list_comprehension(self, expr: ListComprehension) -> None: + if any(expr.generator.is_async): + if not self.is_func_scope() or not self.function_stack[-1].is_coroutine: + self.fail(message_registry.ASYNC_FOR_OUTSIDE_COROUTINE, expr, code=codes.SYNTAX) + expr.generator.accept(self) def visit_set_comprehension(self, expr: SetComprehension) -> None: + if any(expr.generator.is_async): + if not self.is_func_scope() or not self.function_stack[-1].is_coroutine: + self.fail(message_registry.ASYNC_FOR_OUTSIDE_COROUTINE, expr, code=codes.SYNTAX) + expr.generator.accept(self) def visit_dictionary_comprehension(self, expr: DictionaryComprehension) -> None: + if any(expr.is_async): + if not self.is_func_scope() or not self.function_stack[-1].is_coroutine: + self.fail(message_registry.ASYNC_FOR_OUTSIDE_COROUTINE, expr, code=codes.SYNTAX) + with self.enter(expr): self.analyze_comp_for(expr) expr.key.accept(self) diff --git a/test-data/unit/check-async-await.test b/test-data/unit/check-async-await.test index 382d788ee904d..efa0209fe1b1d 100644 --- a/test-data/unit/check-async-await.test +++ b/test-data/unit/check-async-await.test @@ -825,3 +825,42 @@ def bar() -> None: [builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] + +[case testAsyncForOutsideCoroutine] +# flags: --python-version 3.7 + +async def g(): + yield 0 + +def f() -> None: + [x async for x in g()] # E: "async for" outside async function + {x async for x in g()} # E: "async for" outside async function + {x: True async for x in g()} # E: "async for" outside async function + (x async for x in g()) + async for x in g(): ... # E: "async for" outside async function + +[x async for x in g()] # E: "async for" outside async function +{x async for x in g()} # E: "async for" outside async function +{x: True async for x in g()} # E: "async for" outside async function +(x async for x in g()) +async for x in g(): ... # E: "async for" outside async function + +[builtins fixtures/async_await.pyi] +[typing fixtures/typing-async.pyi] + +[case testAsyncWithOutsideCoroutine] +# flags: --python-version 3.7 + +class C: + async def __aenter__(self): pass + async def __aexit__(self, x, y, z): pass + +def f() -> None: + async with C() as x: # E: "async with" outside async function + pass + +async with C() as x: # E: "async with" outside async function + pass + +[builtins fixtures/async_await.pyi] +[typing fixtures/typing-async.pyi] diff --git a/test-data/unit/check-default-plugin.test b/test-data/unit/check-default-plugin.test index aef6d6a71497b..cbbfce3ab353a 100644 --- a/test-data/unit/check-default-plugin.test +++ b/test-data/unit/check-default-plugin.test @@ -37,8 +37,9 @@ async def yield_id(item: T) -> AsyncGenerator[T, None]: reveal_type(yield_id) # N: Revealed type is "def [T] (item: T`-1) -> typing.AsyncContextManager[T`-1]" -async with yield_id(1) as x: - reveal_type(x) # N: Revealed type is "builtins.int*" +async def f() -> None: + async with yield_id(1) as x: + reveal_type(x) # N: Revealed type is "builtins.int*" [typing fixtures/typing-async.pyi] [builtins fixtures/tuple.pyi] From a78e60cc13daefda009c56ea10207fd3a75900ea Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Thu, 24 Mar 2022 05:08:14 +0300 Subject: [PATCH 192/377] Recognize `Hashable` as a real protocol (#11802) When this piece of code was checked: ```python from typing import Awaitable, Hashable, Union, Tuple, List obj: Union[Tuple[int], List[int]] if isinstance(obj, Hashable): reveal_type(obj) ``` Mypy revealed that `Hashable` is `() -> object`. It happened, because [`is_subtype(explicit_type, default_ret_type, ignore_type_params=True)`](https://github.com/python/mypy/blob/56684e43a14e3782409c47e99bb47191d631a3de/mypy/typeops.py#L130) was `True`, where `explicit_type=object` and `default_ret_type=Hashable`. It happened because `object` has `__hash__` method. The only thing that popped out of my head is to simply exclude protocols from this condition. I guess that we might double check protocols with `__new__` and `__init__` to be sure. But, I am not able to think of proper test cases for this. Any ideas? Or is my single test good enough? I am adding `pythoneval` test, because of the complexity in how `Hashable` is defined and analyzed in real life. Closes #11799 --- mypy/typeops.py | 4 ++++ test-data/unit/pythoneval.test | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/mypy/typeops.py b/mypy/typeops.py index 57fdfeadad9a1..007a54e17b95e 100644 --- a/mypy/typeops.py +++ b/mypy/typeops.py @@ -107,6 +107,10 @@ def class_callable(init_type: CallableType, info: TypeInfo, type_type: Instance, explicit_type = init_ret_type if is_new else orig_self_type if ( isinstance(explicit_type, (Instance, TupleType)) + # We have to skip protocols, because it can can be a subtype of a return type + # by accident. Like `Hashable` is a subtype of `object`. See #11799 + and isinstance(default_ret_type, Instance) + and not default_ret_type.type.is_protocol # Only use the declared return type from __new__ or declared self in __init__ # if it is actually returning a subtype of what we would return otherwise. and is_subtype(explicit_type, default_ret_type, ignore_type_params=True) diff --git a/test-data/unit/pythoneval.test b/test-data/unit/pythoneval.test index de15055927aeb..f560ac81e6450 100644 --- a/test-data/unit/pythoneval.test +++ b/test-data/unit/pythoneval.test @@ -1575,6 +1575,19 @@ reveal_type(x) # Revealed type is "collections.OrderedDict[builtins.str, builti [out] _testTypingExtensionsOrderedDictAlias.py:3: note: Revealed type is "collections.OrderedDict[builtins.str, builtins.str]" +[case testSpecialTypingProtocols] +# flags: --warn-unreachable +from typing import Awaitable, Hashable, Union, Tuple, List + +obj: Union[Tuple[int], List[int]] +if isinstance(obj, Hashable): + reveal_type(obj) +if isinstance(obj, Awaitable): + reveal_type(obj) +[out] +_testSpecialTypingProtocols.py:6: note: Revealed type is "Tuple[builtins.int]" +_testSpecialTypingProtocols.py:8: error: Statement is unreachable + [case testEnumValueWithPlaceholderNodeType] # https://github.com/python/mypy/issues/11971 from enum import Enum From 1772a4cc3ed5290efa95cde2c8246db183781201 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 24 Mar 2022 09:26:34 +0000 Subject: [PATCH 193/377] Let overload item have a wider return type than implementation (#12435) A wider return type can be useful if a decorator used for the overload implementation gets a more precise return type as part of a typeshed update. Closes #12434. --- mypy/checker.py | 3 ++- test-data/unit/check-overloading.test | 21 +++++++++++++++++++++ test-data/unit/fine-grained.test | 1 + 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/mypy/checker.py b/mypy/checker.py index e6c22a99c5028..a02a877a808fe 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -600,7 +600,8 @@ def check_overlapping_overloads(self, defn: OverloadedFuncDef) -> None: self.msg.overloaded_signatures_arg_specific(i + 1, defn.impl) # Is the overload alternative's return type a subtype of the implementation's? - if not is_subtype_no_promote(sig1.ret_type, impl.ret_type): + if not (is_subtype_no_promote(sig1.ret_type, impl.ret_type) or + is_subtype_no_promote(impl.ret_type, sig1.ret_type)): self.msg.overloaded_signatures_ret_specific(i + 1, defn.impl) # Here's the scoop about generators and coroutines. diff --git a/test-data/unit/check-overloading.test b/test-data/unit/check-overloading.test index 0d04074406e65..591741f3e4e8b 100644 --- a/test-data/unit/check-overloading.test +++ b/test-data/unit/check-overloading.test @@ -6328,3 +6328,24 @@ if True: def f2(x): ... if True: def f2(x): ... # E: Name "f2" already defined on line 17 + +[case testOverloadItemHasMoreGeneralReturnType] +from typing import overload + +@overload +def f() -> object: ... + +@overload +def f(x: int) -> object: ... + +def f(x: int = 0) -> int: + return x + +@overload +def g() -> object: ... + +@overload +def g(x: int) -> str: ... + +def g(x: int = 0) -> int: # E: Overloaded function implementation cannot produce return type of signature 2 + return x diff --git a/test-data/unit/fine-grained.test b/test-data/unit/fine-grained.test index ad67ff19dfd22..86872277c6e31 100644 --- a/test-data/unit/fine-grained.test +++ b/test-data/unit/fine-grained.test @@ -2084,6 +2084,7 @@ a.py:5: error: "list" expects 1 type argument, but 2 given == [case testPreviousErrorInOverloadedFunction] +# flags: --strict-optional import a [file a.py] from typing import overload From fec532028dcb7def7af4356e529fffb38c4afcea Mon Sep 17 00:00:00 2001 From: 97littleleaf11 <11172084+97littleleaf11@users.noreply.github.com> Date: Thu, 24 Mar 2022 22:39:19 +0800 Subject: [PATCH 194/377] Use Furo theme for documentation (#12348) Current readthedoc theme cannot fully utilize the width of browser especially when you are using a wide screen. I am choosing Furo since it's quite popular in python community (pip, black, etc). Other changes: * Use mypy instead of Mypy * Move introduction to index page, which makes better impression for newcomers. Closes #12374 --- .github/workflows/docs.yml | 3 ++- .github/workflows/test.yml | 1 + docs/requirements-docs.txt | 2 +- docs/source/conf.py | 16 +++++--------- docs/source/index.rst | 41 ++++++++++++++++++++++++++++++++++-- docs/source/introduction.rst | 32 ---------------------------- mypyc/doc/conf.py | 10 ++------- mypyc/doc/index.rst | 6 ++++++ 8 files changed, 56 insertions(+), 55 deletions(-) delete mode 100644 docs/source/introduction.rst diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 228bdb3bd4ad9..79560db2d09ba 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -7,6 +7,7 @@ on: pull_request: paths: - 'docs/**' + - 'mypyc/doc/**' - '**/*.rst' - '**/*.md' - CREDITS @@ -21,7 +22,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-python@v2 with: - python-version: '3.7' + python-version: '3.10' - name: Install tox run: pip install --upgrade 'setuptools!=50' 'virtualenv>=20.6.0' tox==3.24.5 - name: Setup tox environment diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7402a97d73213..f62dba8cb9c7a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,6 +7,7 @@ on: pull_request: paths-ignore: - 'docs/**' + - 'mypyc/doc/**' - '**/*.rst' - '**/*.md' - .gitignore diff --git a/docs/requirements-docs.txt b/docs/requirements-docs.txt index 7e3d31ebea988..395964ad9d44c 100644 --- a/docs/requirements-docs.txt +++ b/docs/requirements-docs.txt @@ -1,2 +1,2 @@ sphinx>=4.2.0,<5.0.0 -sphinx-rtd-theme>=1.0.0,<2.0.0 +furo>=2022.3.4 diff --git a/docs/source/conf.py b/docs/source/conf.py index 9f1ab882c5c81..5c3bf94c2f8c0 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -48,8 +48,8 @@ master_doc = 'index' # General information about the project. -project = u'Mypy' -copyright = u'2016, Jukka Lehtosalo' +project = u'mypy' +copyright = u'2012-2022 Jukka Lehtosalo and mypy contributors' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -103,13 +103,7 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -try: - import sphinx_rtd_theme -except: - html_theme = 'default' -else: - html_theme = 'sphinx_rtd_theme' - html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] +html_theme = "furo" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the @@ -128,7 +122,7 @@ # The name of an image file (relative to this directory) to place at the top # of the sidebar. -#html_logo = None +html_logo = "http://mypy-lang.org/static/mypy_light.svg" # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 @@ -187,7 +181,7 @@ #html_file_suffix = None # Output file base name for HTML help builder. -htmlhelp_basename = 'Mypydoc' +htmlhelp_basename = 'mypydoc' # -- Options for LaTeX output --------------------------------------------- diff --git a/docs/source/index.rst b/docs/source/index.rst index 9cd9220c60b9b..7127308a2d1da 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -6,13 +6,43 @@ Welcome to mypy documentation! ============================== -Mypy is a static type checker for Python 3 and Python 2.7. +Mypy is a static type checker for Python 3 and Python 2.7. If you sprinkle +your code with type annotations, mypy can type check your code and find common +bugs. As mypy is a static analyzer, or a lint-like tool, the type +annotations are just hints for mypy and don't interfere when running your program. +You run your program with a standard Python interpreter, and the annotations +are treated effectively as comments. + +Using the Python 3 annotation syntax (using :pep:`484` and :pep:`526` notation) +or a comment-based annotation syntax for Python 2 code, you will be able to +efficiently annotate your code and use mypy to check the code for common errors. +Mypy has a powerful and easy-to-use type system with modern features such as +type inference, generics, callable types, tuple types, union types, and +structural subtyping. + +As a developer, you decide how to use mypy in your workflow. You can always +escape to dynamic typing as mypy's approach to static typing doesn't restrict +what you can do in your programs. Using mypy will make your programs easier to +understand, debug, and maintain. + +This documentation provides a short introduction to mypy. It will help you +get started writing statically typed code. Knowledge of Python and a +statically typed object-oriented language, such as Java, are assumed. + +.. note:: + + Mypy is used in production by many companies and projects, but mypy is + officially beta software. There will be occasional changes + that break backward compatibility. The mypy development team tries to + minimize the impact of changes to user code. + +Contents +-------- .. toctree:: :maxdepth: 2 :caption: First steps - introduction getting_started existing_code @@ -74,6 +104,13 @@ Mypy is a static type checker for Python 3 and Python 2.7. additional_features faq +.. toctree:: + :hidden: + :caption: Project Links + + GitHub + Website + Indices and tables ================== diff --git a/docs/source/introduction.rst b/docs/source/introduction.rst deleted file mode 100644 index 16ed5a392af73..0000000000000 --- a/docs/source/introduction.rst +++ /dev/null @@ -1,32 +0,0 @@ -Introduction -============ - -Mypy is a static type checker for Python 3 and Python 2.7. If you sprinkle -your code with type annotations, mypy can type check your code and find common -bugs. As mypy is a static analyzer, or a lint-like tool, the type -annotations are just hints for mypy and don't interfere when running your program. -You run your program with a standard Python interpreter, and the annotations -are treated effectively as comments. - -Using the Python 3 annotation syntax (using :pep:`484` and :pep:`526` notation) -or a comment-based annotation syntax for Python 2 code, you will be able to -efficiently annotate your code and use mypy to check the code for common errors. -Mypy has a powerful and easy-to-use type system with modern features such as -type inference, generics, callable types, tuple types, union types, and -structural subtyping. - -As a developer, you decide how to use mypy in your workflow. You can always -escape to dynamic typing as mypy's approach to static typing doesn't restrict -what you can do in your programs. Using mypy will make your programs easier to -understand, debug, and maintain. - -This documentation provides a short introduction to mypy. It will help you -get started writing statically typed code. Knowledge of Python and a -statically typed object-oriented language, such as Java, are assumed. - -.. note:: - - Mypy is used in production by many companies and projects, but mypy is - officially beta software. There will be occasional changes - that break backward compatibility. The mypy development team tries to - minimize the impact of changes to user code. diff --git a/mypyc/doc/conf.py b/mypyc/doc/conf.py index d055a3b49087d..fa980bbb1b065 100644 --- a/mypyc/doc/conf.py +++ b/mypyc/doc/conf.py @@ -17,7 +17,7 @@ # -- Project information ----------------------------------------------------- project = 'mypyc' -copyright = '2020, mypyc team' +copyright = '2020-2022, mypyc team' author = 'mypyc team' # The version info for the project you're documenting, acts as replacement for @@ -50,13 +50,7 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -try: - import sphinx_rtd_theme # type: ignore -except: - html_theme = 'default' -else: - html_theme = 'sphinx_rtd_theme' - html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] +html_theme = 'furo' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, diff --git a/mypyc/doc/index.rst b/mypyc/doc/index.rst index 7098c03946d61..5b1cc48fab3d1 100644 --- a/mypyc/doc/index.rst +++ b/mypyc/doc/index.rst @@ -47,6 +47,12 @@ generate fast code. performance_tips_and_tricks +.. toctree:: + :hidden: + :caption: Project Links + + GitHub + Indices and tables ================== From aa7c170b4ad31bada4faea003f9f0cb99bb58b25 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Thu, 24 Mar 2022 13:53:53 -0700 Subject: [PATCH 195/377] mypy_primer: fix comment workflow (#12443) Co-authored-by: hauntsaninja <> --- .github/workflows/mypy_primer_comment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/mypy_primer_comment.yml b/.github/workflows/mypy_primer_comment.yml index 6942efc78e8c9..36977862eebe5 100644 --- a/.github/workflows/mypy_primer_comment.yml +++ b/.github/workflows/mypy_primer_comment.yml @@ -51,7 +51,7 @@ jobs: let data = fs.readFileSync('fulldiff.txt', { encoding: 'utf8' }) // posting comment fails if too long, so truncate if (data.length > 30000) { - data = data.substring(0, 30000) + `\n\n... (truncated ${diff.length - 30000} chars) ...\n` + data = data.substring(0, 30000) + `\n\n... (truncated ${data.length - 30000} chars) ...\n` } console.log("Diff from mypy_primer:") From 6b0e8485ac20a15fb7ad8762e14315c9e9bdc349 Mon Sep 17 00:00:00 2001 From: Stanislav Levin Date: Fri, 25 Mar 2022 18:54:03 +0300 Subject: [PATCH 196/377] testcmdline: Sync assumption about error message for Python 3.10.3 (#12452) Python 3.10.3 is more correct about syntax error for `mypy` test case `testBlocker`. See https://bugs.python.org/issue46240 for details. Closes #12451 Signed-off-by: Stanislav Levin --- test-data/unit/cmdline.test | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test-data/unit/cmdline.test b/test-data/unit/cmdline.test index 918493b8df48c..1a038b9fac092 100644 --- a/test-data/unit/cmdline.test +++ b/test-data/unit/cmdline.test @@ -1249,6 +1249,10 @@ Found 1 error in 1 file (errors prevented further checking) pkg/x.py:1: error: invalid syntax. Perhaps you forgot a comma? Found 1 error in 1 file (errors prevented further checking) == Return code: 2 +[out version>=3.10.3] +pkg/x.py:1: error: invalid syntax +Found 1 error in 1 file (errors prevented further checking) +== Return code: 2 [case testCmdlinePackageAndFile] # cmd: mypy -p pkg file From 82bc8df22dd1b5feea97f91dff7d91aef41dc767 Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Fri, 25 Mar 2022 16:58:37 +0100 Subject: [PATCH 197/377] stubgen: Use _typeshed.Incomplete instead of typing.Any (#12449) Since python/typeshed#7535, typeshed has a new type `_typeshed.Incomplete`, intended to mark fields that are partly annotated, but need more manual investigation. This applies to all types generated by stubgen, except when explicitly annotated with `Any` in the implementation. --- mypy/stubgen.py | 29 +++---- test-data/unit/stubgen.test | 160 +++++++++++++++++++----------------- 2 files changed, 100 insertions(+), 89 deletions(-) diff --git a/mypy/stubgen.py b/mypy/stubgen.py index 6db5aa75d102f..5d8e6a57c2121 100755 --- a/mypy/stubgen.py +++ b/mypy/stubgen.py @@ -566,6 +566,7 @@ def visit_mypy_file(self, o: MypyFile) -> None: self.defined_names = find_defined_names(o) self.referenced_names = find_referenced_names(o) known_imports = { + "_typeshed": ["Incomplete"], "typing": ["Any", "TypeVar"], "collections.abc": ["Generator"], } @@ -689,14 +690,14 @@ def visit_func_def(self, o: FuncDef, is_abstract: bool = False, return_name = 'None' for expr, in_assignment in all_yield_expressions(o): if expr.expr is not None and not self.is_none_expr(expr.expr): - self.add_typing_import('Any') - yield_name = 'Any' + self.add_typing_import('Incomplete') + yield_name = 'Incomplete' if in_assignment: - self.add_typing_import('Any') - send_name = 'Any' + self.add_typing_import('Incomplete') + send_name = 'Incomplete' if has_return_statement(o): - self.add_typing_import('Any') - return_name = 'Any' + self.add_typing_import('Incomplete') + return_name = 'Incomplete' generator_name = self.typing_name('Generator') retname = f'{generator_name}[{yield_name}, {send_name}, {return_name}]' elif not has_return_statement(o) and not is_abstract: @@ -954,18 +955,18 @@ def process_namedtuple(self, lvalue: NameExpr, rvalue: CallExpr) -> None: list_items = cast(List[StrExpr], rvalue.args[1].items) items = [item.value for item in list_items] else: - self.add('%s%s: Any' % (self._indent, lvalue.name)) - self.import_tracker.require_name('Any') + self.add('%s%s: Incomplete' % (self._indent, lvalue.name)) + self.import_tracker.require_name('Incomplete') return self.import_tracker.require_name('NamedTuple') self.add('{}class {}(NamedTuple):'.format(self._indent, lvalue.name)) if len(items) == 0: self.add(' ...\n') else: - self.import_tracker.require_name('Any') + self.import_tracker.require_name('Incomplete') self.add('\n') for item in items: - self.add('{} {}: Any\n'.format(self._indent, item)) + self.add('{} {}: Incomplete\n'.format(self._indent, item)) self._state = CLASS def is_alias_expression(self, expr: Expression, top_level: bool = True) -> bool: @@ -1220,11 +1221,11 @@ def get_str_type_of_node(self, rvalue: Expression, return 'bool' if can_infer_optional and \ isinstance(rvalue, NameExpr) and rvalue.name == 'None': - self.add_typing_import('Any') - return '{} | None'.format(self.typing_name('Any')) + self.add_typing_import('Incomplete') + return '{} | None'.format(self.typing_name('Incomplete')) if can_be_any: - self.add_typing_import('Any') - return self.typing_name('Any') + self.add_typing_import('Incomplete') + return self.typing_name('Incomplete') else: return '' diff --git a/test-data/unit/stubgen.test b/test-data/unit/stubgen.test index 62fae21df4f4e..148b7c0480424 100644 --- a/test-data/unit/stubgen.test +++ b/test-data/unit/stubgen.test @@ -28,9 +28,9 @@ def g(b: int = ..., c: int = ...) -> None: ... [case testDefaultArgNone] def f(x=None): ... [out] -from typing import Any +from _typeshed import Incomplete -def f(x: Any | None = ...) -> None: ... +def f(x: Incomplete | None = ...) -> None: ... [case testDefaultArgBool] def f(x=True, y=False): ... @@ -275,10 +275,10 @@ def foo(x) -> None: ... [case testMultipleAssignment] x, y = 1, 2 [out] -from typing import Any +from _typeshed import Incomplete -x: Any -y: Any +x: Incomplete +y: Incomplete [case testMultipleAssignmentAnnotated] x, y = 1, "2" # type: int, str @@ -289,10 +289,10 @@ y: str [case testMultipleAssignment2] [x, y] = 1, 2 [out] -from typing import Any +from _typeshed import Incomplete -x: Any -y: Any +x: Incomplete +y: Incomplete [case testKeywordOnlyArg] def f(x, *, y=1): ... @@ -588,11 +588,12 @@ class A: import collections, x X = collections.namedtuple('X', ['a', 'b']) [out] -from typing import Any, NamedTuple +from _typeshed import Incomplete +from typing import NamedTuple class X(NamedTuple): - a: Any - b: Any + a: Incomplete + b: Incomplete [case testEmptyNamedtuple] import collections @@ -607,33 +608,36 @@ from collections import namedtuple, xx X = namedtuple('X', 'a b') xx [out] -from typing import Any, NamedTuple +from _typeshed import Incomplete +from typing import NamedTuple class X(NamedTuple): - a: Any - b: Any + a: Incomplete + b: Incomplete [case testNamedtupleAltSyntaxUsingComma] from collections import namedtuple, xx X = namedtuple('X', 'a, b') xx [out] -from typing import Any, NamedTuple +from _typeshed import Incomplete +from typing import NamedTuple class X(NamedTuple): - a: Any - b: Any + a: Incomplete + b: Incomplete [case testNamedtupleAltSyntaxUsingMultipleCommas] from collections import namedtuple, xx X = namedtuple('X', 'a,, b') xx [out] -from typing import Any, NamedTuple +from _typeshed import Incomplete +from typing import NamedTuple class X(NamedTuple): - a: Any - b: Any + a: Incomplete + b: Incomplete [case testNamedtupleWithUnderscore] from collections import namedtuple as _namedtuple @@ -641,13 +645,14 @@ def f(): ... X = _namedtuple('X', 'a b') def g(): ... [out] -from typing import Any, NamedTuple +from _typeshed import Incomplete +from typing import NamedTuple def f() -> None: ... class X(NamedTuple): - a: Any - b: Any + a: Incomplete + b: Incomplete def g() -> None: ... @@ -656,11 +661,12 @@ import collections, x _X = collections.namedtuple('_X', ['a', 'b']) class Y(_X): ... [out] -from typing import Any, NamedTuple +from _typeshed import Incomplete +from typing import NamedTuple class _X(NamedTuple): - a: Any - b: Any + a: Incomplete + b: Incomplete class Y(_X): ... @@ -671,27 +677,28 @@ Y = namedtuple('Y', ('a',)) Z = namedtuple('Z', ('a', 'b', 'c', 'd', 'e')) xx [out] -from typing import Any, NamedTuple +from _typeshed import Incomplete +from typing import NamedTuple class X(NamedTuple): ... class Y(NamedTuple): - a: Any + a: Incomplete class Z(NamedTuple): - a: Any - b: Any - c: Any - d: Any - e: Any + a: Incomplete + b: Incomplete + c: Incomplete + d: Incomplete + e: Incomplete [case testDynamicNamedTuple] from collections import namedtuple N = namedtuple('N', ['x', 'y'] + ['z']) [out] -from typing import Any +from _typeshed import Incomplete -N: Any +N: Incomplete [case testArbitraryBaseClass] import x @@ -809,12 +816,12 @@ class A: def method(self, a=None): self.x = [] [out] -from typing import Any +from _typeshed import Incomplete class A: - x: Any - def __init__(self, a: Any | None = ...) -> None: ... - def method(self, a: Any | None = ...) -> None: ... + x: Incomplete + def __init__(self, a: Incomplete | None = ...) -> None: ... + def method(self, a: Incomplete | None = ...) -> None: ... [case testAnnotationImportsFrom] import foo @@ -945,10 +952,10 @@ class Foo: alias = str [out] -from typing import Any +from _typeshed import Incomplete class Foo: - alias: Any + alias: Incomplete [case testAliasExceptions] noalias1 = None @@ -956,10 +963,10 @@ noalias2 = ... noalias3 = True [out] -from typing import Any +from _typeshed import Incomplete -noalias1: Any -noalias2: Any +noalias1: Incomplete +noalias2: Incomplete noalias3: bool -- More features/fixes: @@ -1000,14 +1007,14 @@ def all(): x = yield 123 return "abc" [out] +from _typeshed import Incomplete from collections.abc import Generator -from typing import Any -def f() -> Generator[Any, None, None]: ... -def g() -> Generator[None, Any, None]: ... +def f() -> Generator[Incomplete, None, None]: ... +def g() -> Generator[None, Incomplete, None]: ... def h1() -> Generator[None, None, None]: ... -def h2() -> Generator[None, None, Any]: ... -def all() -> Generator[Any, Any, Any]: ... +def h2() -> Generator[None, None, Incomplete]: ... +def all() -> Generator[Incomplete, Incomplete, Incomplete]: ... [case testFunctionYieldsNone] def f(): @@ -1028,12 +1035,12 @@ class Generator: def f(): yield 123 [out] +from _typeshed import Incomplete from collections.abc import Generator as _Generator -from typing import Any class Generator: ... -def f() -> _Generator[Any, None, None]: ... +def f() -> _Generator[Incomplete, None, None]: ... [case testCallable] from typing import Callable @@ -1422,9 +1429,9 @@ x = registry[a.f] [file a.py] def f(): ... [out] -from typing import Any +from _typeshed import Incomplete -x: Any +x: Incomplete [case testCrossModuleClass_semanal] import a @@ -1466,12 +1473,12 @@ class _A: ... [file _a.py] def f(): ... [out] -from typing import Any +from _typeshed import Incomplete class C: ... -A: Any -B: Any +A: Incomplete +B: Incomplete [case testPrivateAliasesIncluded_semanal] # flags: --include-private @@ -1503,12 +1510,13 @@ y: Final = x z: Final[object] t: Final [out] -from typing import Any, Final +from _typeshed import Incomplete +from typing import Final x: Final[int] -y: Final[Any] +y: Final[Incomplete] z: Final[object] -t: Final[Any] +t: Final[Incomplete] [case testFinalInvalid_semanal] Final = 'boom' @@ -1525,10 +1533,11 @@ from typing import Dict, Any funcs: Dict[Any, Any] f = funcs[a.f] [out] +from _typeshed import Incomplete from typing import Any, Dict funcs: Dict[Any, Any] -f: Any +f: Incomplete [case testAbstractMethodNameExpr] from abc import ABCMeta, abstractmethod @@ -1796,29 +1805,29 @@ class A(metaclass=abc.ABCMeta): @abc.abstractmethod def x(self): ... -[case testClassWithNameAnyOrOptional] +[case testClassWithNameIncompleteOrOptional] Y = object() def g(x=None): pass x = g() -class Any: +class Incomplete: pass def Optional(): return 0 [out] -from typing import Any as _Any +from _typeshed import Incomplete as _Incomplete -Y: _Any +Y: _Incomplete -def g(x: _Any | None = ...) -> None: ... +def g(x: _Incomplete | None = ...) -> None: ... -x: _Any +x: _Incomplete -class Any: ... +class Incomplete: ... def Optional(): ... @@ -1889,10 +1898,10 @@ class Request2: [out] # main.pyi -from typing import Any +from _typeshed import Incomplete -x: Any -y: Any +x: Incomplete +y: Incomplete # p/sub/requests.pyi class Request2: ... @@ -2280,10 +2289,10 @@ class C: x = attr.ib() [out] -from typing import Any +from _typeshed import Incomplete class C: - x: Any + x: Incomplete def __init__(self, x) -> None: ... def __lt__(self, other): ... def __le__(self, other): ... @@ -2296,12 +2305,13 @@ from collections import namedtuple class C: N = namedtuple('N', ['x', 'y']) [out] -from typing import Any, NamedTuple +from _typeshed import Incomplete +from typing import NamedTuple class C: class N(NamedTuple): - x: Any - y: Any + x: Incomplete + y: Incomplete [case testImports_directImportsWithAlias] import p.a as a From c7559283995ea020afbb82d92cad538f0b174913 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Sat, 26 Mar 2022 16:17:06 +0000 Subject: [PATCH 198/377] [mypyc] Simplify generated code for native attribute get (#11978) The implementation merges consecutive GetAttr and Branch ops. The main benefit is that this makes the generated code smaller and easier to read, making it easier to spot possible improvements in the code. --- mypyc/codegen/emitfunc.py | 73 +++++++++++++++++++++++++++++++------ mypyc/lib-rt/CPy.h | 2 + mypyc/lib-rt/exc_ops.c | 8 ++++ mypyc/test/test_emitfunc.py | 31 ++++++++++++++-- 4 files changed, 99 insertions(+), 15 deletions(-) diff --git a/mypyc/codegen/emitfunc.py b/mypyc/codegen/emitfunc.py index 6215e29b51a17..294f416520f24 100644 --- a/mypyc/codegen/emitfunc.py +++ b/mypyc/codegen/emitfunc.py @@ -1,6 +1,6 @@ """Code generation for native function bodies.""" -from typing import Union, Optional +from typing import List, Union, Optional from typing_extensions import Final from mypyc.common import ( @@ -8,7 +8,7 @@ ) from mypyc.codegen.emit import Emitter from mypyc.ir.ops import ( - OpVisitor, Goto, Branch, Return, Assign, Integer, LoadErrorValue, GetAttr, SetAttr, + Op, OpVisitor, Goto, Branch, Return, Assign, Integer, LoadErrorValue, GetAttr, SetAttr, LoadStatic, InitStatic, TupleGet, TupleSet, Call, IncRef, DecRef, Box, Cast, Unbox, BasicBlock, Value, MethodCall, Unreachable, NAMESPACE_STATIC, NAMESPACE_TYPE, NAMESPACE_MODULE, RaiseStandardError, CallC, LoadGlobal, Truncate, IntOp, LoadMem, GetElementPtr, @@ -88,8 +88,13 @@ def generate_native_function(fn: FuncIR, next_block = blocks[i + 1] body.emit_label(block) visitor.next_block = next_block - for op in block.ops: - op.accept(visitor) + + ops = block.ops + visitor.ops = ops + visitor.op_index = 0 + while visitor.op_index < len(ops): + ops[visitor.op_index].accept(visitor) + visitor.op_index += 1 body.emit_line('}') @@ -110,7 +115,12 @@ def __init__(self, self.module_name = module_name self.literals = emitter.context.literals self.rare = False + # Next basic block to be processed after the current one (if any), set by caller self.next_block: Optional[BasicBlock] = None + # Ops in the basic block currently being processed, set by caller + self.ops: List[Op] = [] + # Current index within ops; visit methods can increment this to skip/merge ops + self.op_index = 0 def temp_name(self) -> str: return self.emitter.temp_name() @@ -293,16 +303,44 @@ def visit_get_attr(self, op: GetAttr) -> None: attr_expr = self.get_attr_expr(obj, op, decl_cl) self.emitter.emit_line('{} = {};'.format(dest, attr_expr)) self.emitter.emit_undefined_attr_check( - attr_rtype, attr_expr, '==', unlikely=True + attr_rtype, dest, '==', unlikely=True ) exc_class = 'PyExc_AttributeError' - self.emitter.emit_line( - 'PyErr_SetString({}, "attribute {} of {} undefined");'.format( - exc_class, repr(op.attr), repr(cl.name))) + merged_branch = None + branch = self.next_branch() + if branch is not None: + if (branch.value is op + and branch.op == Branch.IS_ERROR + and branch.traceback_entry is not None + and not branch.negated): + # Generate code for the following branch here to avoid + # redundant branches in the generate code. + self.emit_attribute_error(branch, cl.name, op.attr) + self.emit_line('goto %s;' % self.label(branch.true)) + merged_branch = branch + self.emitter.emit_line('}') + if not merged_branch: + self.emitter.emit_line( + 'PyErr_SetString({}, "attribute {} of {} undefined");'.format( + exc_class, repr(op.attr), repr(cl.name))) + if attr_rtype.is_refcounted: - self.emitter.emit_line('} else {') - self.emitter.emit_inc_ref(attr_expr, attr_rtype) - self.emitter.emit_line('}') + if not merged_branch: + self.emitter.emit_line('} else {') + self.emitter.emit_inc_ref(dest, attr_rtype) + if merged_branch: + if merged_branch.false is not self.next_block: + self.emit_line('goto %s;' % self.label(merged_branch.false)) + self.op_index += 1 + else: + self.emitter.emit_line('}') + + def next_branch(self) -> Optional[Branch]: + if self.op_index + 1 < len(self.ops): + next_op = self.ops[self.op_index + 1] + if isinstance(next_op, Branch): + return next_op + return None def visit_set_attr(self, op: SetAttr) -> None: dest = self.reg(op) @@ -603,6 +641,19 @@ def emit_traceback(self, op: Branch) -> None: if DEBUG_ERRORS: self.emit_line('assert(PyErr_Occurred() != NULL && "failure w/o err!");') + def emit_attribute_error(self, op: Branch, class_name: str, attr: str) -> None: + assert op.traceback_entry is not None + globals_static = self.emitter.static_name('globals', self.module_name) + self.emit_line('CPy_AttributeError("%s", "%s", "%s", "%s", %d, %s);' % ( + self.source_path.replace("\\", "\\\\"), + op.traceback_entry[0], + class_name, + attr, + op.traceback_entry[1], + globals_static)) + if DEBUG_ERRORS: + self.emit_line('assert(PyErr_Occurred() != NULL && "failure w/o err!");') + def emit_signed_int_cast(self, type: RType) -> str: if is_tagged(type): return '(Py_ssize_t)' diff --git a/mypyc/lib-rt/CPy.h b/mypyc/lib-rt/CPy.h index 9f5ae52d4e40f..4c0f91a5707ec 100644 --- a/mypyc/lib-rt/CPy.h +++ b/mypyc/lib-rt/CPy.h @@ -498,6 +498,8 @@ void _CPy_GetExcInfo(PyObject **p_type, PyObject **p_value, PyObject **p_traceba void CPyError_OutOfMemory(void); void CPy_TypeError(const char *expected, PyObject *value); void CPy_AddTraceback(const char *filename, const char *funcname, int line, PyObject *globals); +void CPy_AttributeError(const char *filename, const char *funcname, const char *classname, + const char *attrname, int line, PyObject *globals); // Misc operations diff --git a/mypyc/lib-rt/exc_ops.c b/mypyc/lib-rt/exc_ops.c index 7ef46479d2e8e..2e1f4fb668637 100644 --- a/mypyc/lib-rt/exc_ops.c +++ b/mypyc/lib-rt/exc_ops.c @@ -225,3 +225,11 @@ void CPy_AddTraceback(const char *filename, const char *funcname, int line, PyOb error: _PyErr_ChainExceptions(exc, val, tb); } + +void CPy_AttributeError(const char *filename, const char *funcname, const char *classname, + const char *attrname, int line, PyObject *globals) { + char buf[500]; + snprintf(buf, sizeof(buf), "attribute '%.200s' of '%.200s' undefined", classname, attrname); + PyErr_SetString(PyExc_AttributeError, buf); + CPy_AddTraceback(filename, funcname, line, globals); +} diff --git a/mypyc/test/test_emitfunc.py b/mypyc/test/test_emitfunc.py index c18cd37b17072..0bb4dc68e8af3 100644 --- a/mypyc/test/test_emitfunc.py +++ b/mypyc/test/test_emitfunc.py @@ -281,10 +281,10 @@ def test_get_attr(self) -> None: self.assert_emit( GetAttr(self.r, 'y', 1), """cpy_r_r0 = ((mod___AObject *)cpy_r_r)->_y; - if (unlikely(((mod___AObject *)cpy_r_r)->_y == CPY_INT_TAG)) { + if (unlikely(cpy_r_r0 == CPY_INT_TAG)) { PyErr_SetString(PyExc_AttributeError, "attribute 'y' of 'A' undefined"); } else { - CPyTagged_INCREF(((mod___AObject *)cpy_r_r)->_y); + CPyTagged_INCREF(cpy_r_r0); } """) @@ -292,11 +292,28 @@ def test_get_attr_non_refcounted(self) -> None: self.assert_emit( GetAttr(self.r, 'x', 1), """cpy_r_r0 = ((mod___AObject *)cpy_r_r)->_x; - if (unlikely(((mod___AObject *)cpy_r_r)->_x == 2)) { + if (unlikely(cpy_r_r0 == 2)) { PyErr_SetString(PyExc_AttributeError, "attribute 'x' of 'A' undefined"); } """) + def test_get_attr_merged(self) -> None: + op = GetAttr(self.r, 'y', 1) + branch = Branch(op, BasicBlock(8), BasicBlock(9), Branch.IS_ERROR) + branch.traceback_entry = ('foobar', 123) + self.assert_emit( + op, + """\ + cpy_r_r0 = ((mod___AObject *)cpy_r_r)->_y; + if (unlikely(cpy_r_r0 == CPY_INT_TAG)) { + CPy_AttributeError("prog.py", "foobar", "A", "y", 123, CPyStatic_prog___globals); + goto CPyL8; + } + CPyTagged_INCREF(cpy_r_r0); + goto CPyL9; + """, + next_branch=branch) + def test_set_attr(self) -> None: self.assert_emit( SetAttr(self.r, 'y', self.m, 1), @@ -428,7 +445,8 @@ def assert_emit(self, expected: str, next_block: Optional[BasicBlock] = None, *, - rare: bool = False) -> None: + rare: bool = False, + next_branch: Optional[Branch] = None) -> None: block = BasicBlock(0) block.ops.append(op) value_names = generate_names_for_ir(self.registers, [block]) @@ -440,6 +458,11 @@ def assert_emit(self, visitor = FunctionEmitterVisitor(emitter, declarations, 'prog.py', 'prog') visitor.next_block = next_block visitor.rare = rare + if next_branch: + visitor.ops = [op, next_branch] + else: + visitor.ops = [op] + visitor.op_index = 0 op.accept(visitor) frags = declarations.fragments + emitter.fragments From 1480344cfc99ed0396c2b9b9f36c14b253f440b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0t=C4=9Bp=C3=A1n=20Hor=C3=A1=C4=8Dek?= <4643182+shoracek@users.noreply.github.com> Date: Sun, 27 Mar 2022 05:34:05 +0200 Subject: [PATCH 199/377] stubgen: Do not consider nested generators (#12463) Since yields in nested functions will not yield outside of the considered function, they can be ignored. --- mypy/traverser.py | 25 +++++++++++++------------ test-data/unit/stubgen.test | 9 +++++++++ 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/mypy/traverser.py b/mypy/traverser.py index 6ab97116a12ea..996f752f4c32a 100644 --- a/mypy/traverser.py +++ b/mypy/traverser.py @@ -368,8 +368,20 @@ def has_return_statement(fdef: FuncBase) -> bool: return seeker.found -class YieldSeeker(TraverserVisitor): +class FuncCollectorBase(TraverserVisitor): + def __init__(self) -> None: + self.inside_func = False + + def visit_func_def(self, defn: FuncDef) -> None: + if not self.inside_func: + self.inside_func = True + super().visit_func_def(defn) + self.inside_func = False + + +class YieldSeeker(FuncCollectorBase): def __init__(self) -> None: + super().__init__() self.found = False def visit_yield_expr(self, o: YieldExpr) -> None: @@ -382,17 +394,6 @@ def has_yield_expression(fdef: FuncBase) -> bool: return seeker.found -class FuncCollectorBase(TraverserVisitor): - def __init__(self) -> None: - self.inside_func = False - - def visit_func_def(self, defn: FuncDef) -> None: - if not self.inside_func: - self.inside_func = True - super().visit_func_def(defn) - self.inside_func = False - - class ReturnCollector(FuncCollectorBase): def __init__(self) -> None: super().__init__() diff --git a/test-data/unit/stubgen.test b/test-data/unit/stubgen.test index 148b7c0480424..cbce46b356059 100644 --- a/test-data/unit/stubgen.test +++ b/test-data/unit/stubgen.test @@ -2619,3 +2619,12 @@ class PT(Protocol[T, T2]): def func(*, non_default_kwarg: bool, default_kwarg: bool = True): ... [out] def func(*, non_default_kwarg: bool, default_kwarg: bool = ...): ... + +[case testNestedGenerator] +def f(): + def g(): + yield 0 + + return 0 +[out] +def f(): ... From ecef427dbd046a0ec7738bb06dd81bd761d104dd Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Sun, 27 Mar 2022 15:37:01 +0100 Subject: [PATCH 200/377] stubtest: enable verification of `__match_args__` attributes (#12465) #12415 (included in release 0.942) unblocked typeshed from adding missing `__match_args__` attributes (see https://github.com/python/typeshed/pull/7556). This means stubtest is now unblocked from checking the correctness of `__match_args__` attributes in the stub! --- mypy/stubtest.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mypy/stubtest.py b/mypy/stubtest.py index ae9c71801dfb9..07727615dfcfe 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -1044,8 +1044,7 @@ def verify_typealias( "__args__", "__orig_bases__", "__final__", - # Consider removing these: - "__match_args__", + # Consider removing __slots__? "__slots__", } ) From 466be215e431ddc7540840f814eed45163a141cc Mon Sep 17 00:00:00 2001 From: KotlinIsland <65446343+KotlinIsland@users.noreply.github.com> Date: Mon, 28 Mar 2022 13:23:52 +1000 Subject: [PATCH 201/377] [mypyc] Use more accurate flags with msvc (#12468) Co-authored-by: KotlinIsland --- mypyc/build.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/mypyc/build.py b/mypyc/build.py index 8528aa088ac05..2c04eed9e64c0 100644 --- a/mypyc/build.py +++ b/mypyc/build.py @@ -523,10 +523,20 @@ def mypycify( # This flag is needed for gcc but does not exist on clang. cflags += ['-Wno-unused-but-set-variable'] elif compiler.compiler_type == 'msvc': - if opt_level == '3': + # msvc doesn't have levels, '/O2' is full and '/Od' is disable + if opt_level == '0': + opt_level = 'd' + elif opt_level in ('1', '2', '3'): opt_level = '2' + if debug_level == '0': + debug_level = "NONE" + elif debug_level == '1': + debug_level = "FASTLINK" + elif debug_level in ('2', '3'): + debug_level = "FULL" cflags += [ '/O{}'.format(opt_level), + f'/DEBUG:{debug_level}', '/wd4102', # unreferenced label '/wd4101', # unreferenced local variable '/wd4146', # negating unsigned int From a66cb498ed6bd8b582ccc9e88c89cef332ef8245 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Mon, 28 Mar 2022 14:31:27 +0100 Subject: [PATCH 202/377] Fix Windows test failures in CI (#12477) Allow extension file names such as `native.pyd` in addition to `native..`. I'm not sure why the file names have changed, but the new file names seem okay as well. Fixes #12460. --- mypyc/test/test_run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypyc/test/test_run.py b/mypyc/test/test_run.py index a5e356ea56a6e..2a2aa8fae0e4b 100644 --- a/mypyc/test/test_run.py +++ b/mypyc/test/test_run.py @@ -263,7 +263,7 @@ def run_case_step(self, testcase: DataDrivenTestCase, incremental_step: int) -> # Assert that an output file got created suffix = 'pyd' if sys.platform == 'win32' else 'so' - assert glob.glob('native.*.{}'.format(suffix)) + assert glob.glob('native.*.{}'.format(suffix)) or glob.glob('native.{}'.format(suffix)) driver_path = 'driver.py' if not os.path.isfile(driver_path): From bd530392cdbe444c63cc21820ad7b9748ea9c816 Mon Sep 17 00:00:00 2001 From: Stanislav K <44553725+stkrizh@users.noreply.github.com> Date: Mon, 28 Mar 2022 22:20:57 +0200 Subject: [PATCH 203/377] Remove the * for inferred types from reveal_type output (#12459) Closes #10076 --- mypy/types.py | 2 - test-data/unit/check-abstract.test | 4 +- test-data/unit/check-async-await.test | 34 ++-- test-data/unit/check-attr.test | 24 +-- test-data/unit/check-callable.test | 2 +- test-data/unit/check-classes.test | 98 +++++------ test-data/unit/check-ctypes.test | 22 +-- test-data/unit/check-custom-plugin.test | 12 +- test-data/unit/check-dataclasses.test | 28 ++-- test-data/unit/check-default-plugin.test | 8 +- test-data/unit/check-enum.test | 14 +- test-data/unit/check-final.test | 4 +- test-data/unit/check-functions.test | 12 +- test-data/unit/check-generic-alias.test | 4 +- test-data/unit/check-generic-subtyping.test | 64 ++++---- test-data/unit/check-generics.test | 154 +++++++++--------- test-data/unit/check-incremental.test | 8 +- test-data/unit/check-inference-context.test | 12 +- test-data/unit/check-inference.test | 52 +++--- test-data/unit/check-isinstance.test | 22 +-- test-data/unit/check-lists.test | 8 +- test-data/unit/check-literal.test | 94 +++++------ test-data/unit/check-modules.test | 12 +- test-data/unit/check-newsemanal.test | 52 +++--- test-data/unit/check-newsyntax.test | 2 +- test-data/unit/check-newtype.test | 4 +- test-data/unit/check-optional.test | 10 +- test-data/unit/check-overloading.test | 60 +++---- .../unit/check-parameter-specification.test | 18 +- test-data/unit/check-protocols.test | 68 ++++---- test-data/unit/check-python310.test | 44 ++--- test-data/unit/check-python38.test | 24 +-- test-data/unit/check-redefine.test | 20 +-- test-data/unit/check-selftype.test | 80 ++++----- test-data/unit/check-serialize.test | 18 +- test-data/unit/check-statements.test | 10 +- test-data/unit/check-tuples.test | 44 ++--- test-data/unit/check-type-aliases.test | 8 +- test-data/unit/check-typeddict.test | 52 +++--- test-data/unit/check-typeguard.test | 12 +- test-data/unit/check-typevar-values.test | 8 +- test-data/unit/check-unions.test | 144 ++++++++-------- test-data/unit/check-unreachable-code.test | 8 +- test-data/unit/check-varargs.test | 2 +- test-data/unit/fine-grained.test | 2 +- test-data/unit/pythoneval.test | 34 ++-- 46 files changed, 708 insertions(+), 710 deletions(-) diff --git a/mypy/types.py b/mypy/types.py index 4d56ee9359afc..9fc0c1831a010 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -2344,8 +2344,6 @@ def visit_instance(self, t: Instance) -> str: else: s = t.type.fullname or t.type.name or '' - if t.erased: - s += '*' if t.args: if t.type.fullname == 'builtins.tuple': assert len(t.args) == 1 diff --git a/test-data/unit/check-abstract.test b/test-data/unit/check-abstract.test index 6f3318a87683c..beb2d9397e43b 100644 --- a/test-data/unit/check-abstract.test +++ b/test-data/unit/check-abstract.test @@ -1004,8 +1004,8 @@ my_abstract_types = { 'B': MyAbstractB, } -reveal_type(my_concrete_types) # N: Revealed type is "builtins.dict[builtins.str*, def () -> __main__.MyAbstractType]" -reveal_type(my_abstract_types) # N: Revealed type is "builtins.dict[builtins.str*, def () -> __main__.MyAbstractType]" +reveal_type(my_concrete_types) # N: Revealed type is "builtins.dict[builtins.str, def () -> __main__.MyAbstractType]" +reveal_type(my_abstract_types) # N: Revealed type is "builtins.dict[builtins.str, def () -> __main__.MyAbstractType]" a = my_concrete_types['A']() a.do() diff --git a/test-data/unit/check-async-await.test b/test-data/unit/check-async-await.test index efa0209fe1b1d..a9c6507bceef3 100644 --- a/test-data/unit/check-async-await.test +++ b/test-data/unit/check-async-await.test @@ -39,7 +39,7 @@ main:4: error: Return value expected async def f() -> int: x = await f() - reveal_type(x) # N: Revealed type is "builtins.int*" + reveal_type(x) # N: Revealed type is "builtins.int" return x [builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] @@ -150,7 +150,7 @@ class C(AsyncIterator[int]): async def __anext__(self) -> int: return 0 async def f() -> None: async for x in C(): - reveal_type(x) # N: Revealed type is "builtins.int*" + reveal_type(x) # N: Revealed type is "builtins.int" [builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] @@ -201,23 +201,23 @@ class asyncify(Generic[T], AsyncIterator[T]): async def listcomp(obj: Iterable[int]): lst = [i async for i in asyncify(obj)] - reveal_type(lst) # N: Revealed type is "builtins.list[builtins.int*]" + reveal_type(lst) # N: Revealed type is "builtins.list[builtins.int]" lst2 = [i async for i in asyncify(obj) for j in obj] - reveal_type(lst2) # N: Revealed type is "builtins.list[builtins.int*]" + reveal_type(lst2) # N: Revealed type is "builtins.list[builtins.int]" async def setcomp(obj: Iterable[int]): lst = {i async for i in asyncify(obj)} - reveal_type(lst) # N: Revealed type is "builtins.set[builtins.int*]" + reveal_type(lst) # N: Revealed type is "builtins.set[builtins.int]" async def dictcomp(obj: Iterable[Tuple[int, str]]): lst = {i: j async for i, j in asyncify(obj)} - reveal_type(lst) # N: Revealed type is "builtins.dict[builtins.int*, builtins.str*]" + reveal_type(lst) # N: Revealed type is "builtins.dict[builtins.int, builtins.str]" async def generatorexp(obj: Iterable[int]): lst = (i async for i in asyncify(obj)) - reveal_type(lst) # N: Revealed type is "typing.AsyncGenerator[builtins.int*, None]" + reveal_type(lst) # N: Revealed type is "typing.AsyncGenerator[builtins.int, None]" lst2 = (i async for i in asyncify(obj) for i in obj) - reveal_type(lst2) # N: Revealed type is "typing.AsyncGenerator[builtins.int*, None]" + reveal_type(lst2) # N: Revealed type is "typing.AsyncGenerator[builtins.int, None]" [builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] @@ -260,7 +260,7 @@ class C: async def __aexit__(self, x, y, z) -> None: pass async def f() -> None: async with C() as x: - reveal_type(x) # N: Revealed type is "builtins.int*" + reveal_type(x) # N: Revealed type is "builtins.int" [builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] @@ -435,7 +435,7 @@ async def f() -> int: async def g() -> AsyncGenerator[int, None]: value = await f() - reveal_type(value) # N: Revealed type is "builtins.int*" + reveal_type(value) # N: Revealed type is "builtins.int" yield value yield 'not an int' # E: Incompatible types in "yield" (actual type "str", expected type "int") @@ -446,7 +446,7 @@ reveal_type(g()) # N: Revealed type is "typing.AsyncGenerator[builtins.int, Non async def h() -> None: async for item in g(): - reveal_type(item) # N: Revealed type is "builtins.int*" + reveal_type(item) # N: Revealed type is "builtins.int" async def wrong_return() -> Generator[int, None, None]: # E: The return type of an async generator function should be "AsyncGenerator" or one of its supertypes yield 3 @@ -465,7 +465,7 @@ async def gen() -> AsyncIterator[int]: async def use_gen() -> None: async for item in gen(): - reveal_type(item) # N: Revealed type is "builtins.int*" + reveal_type(item) # N: Revealed type is "builtins.int" [builtins fixtures/dict.pyi] [typing fixtures/typing-async.pyi] @@ -481,9 +481,9 @@ async def genfunc() -> AsyncGenerator[int, None]: async def user() -> None: gen = genfunc() - reveal_type(gen.__aiter__()) # N: Revealed type is "typing.AsyncGenerator[builtins.int*, None]" + reveal_type(gen.__aiter__()) # N: Revealed type is "typing.AsyncGenerator[builtins.int, None]" - reveal_type(await gen.__anext__()) # N: Revealed type is "builtins.int*" + reveal_type(await gen.__anext__()) # N: Revealed type is "builtins.int" [builtins fixtures/dict.pyi] [typing fixtures/typing-async.pyi] @@ -504,7 +504,7 @@ async def gen() -> AsyncGenerator[int, str]: async def h() -> None: g = gen() await g.asend(()) # E: Argument 1 to "asend" of "AsyncGenerator" has incompatible type "Tuple[]"; expected "str" - reveal_type(await g.asend('hello')) # N: Revealed type is "builtins.int*" + reveal_type(await g.asend('hello')) # N: Revealed type is "builtins.int" [builtins fixtures/dict.pyi] [typing fixtures/typing-async.pyi] @@ -522,8 +522,8 @@ async def gen() -> AsyncGenerator[str, int]: async def h() -> None: g = gen() v = await g.asend(1) - reveal_type(v) # N: Revealed type is "builtins.str*" - reveal_type(await g.athrow(BaseException)) # N: Revealed type is "builtins.str*" + reveal_type(v) # N: Revealed type is "builtins.str" + reveal_type(await g.athrow(BaseException)) # N: Revealed type is "builtins.str" [builtins fixtures/dict.pyi] [typing fixtures/typing-async.pyi] diff --git a/test-data/unit/check-attr.test b/test-data/unit/check-attr.test index 7905f1add6ca7..688366e616171 100644 --- a/test-data/unit/check-attr.test +++ b/test-data/unit/check-attr.test @@ -445,9 +445,9 @@ class A(Generic[T]): return self.x # E: Incompatible return value type (got "List[T]", expected "T") reveal_type(A) # N: Revealed type is "def [T] (x: builtins.list[T`1], y: T`1) -> __main__.A[T`1]" a = A([1], 2) -reveal_type(a) # N: Revealed type is "__main__.A[builtins.int*]" -reveal_type(a.x) # N: Revealed type is "builtins.list[builtins.int*]" -reveal_type(a.y) # N: Revealed type is "builtins.int*" +reveal_type(a) # N: Revealed type is "__main__.A[builtins.int]" +reveal_type(a.x) # N: Revealed type is "builtins.list[builtins.int]" +reveal_type(a.y) # N: Revealed type is "builtins.int" A(['str'], 7) # E: Cannot infer type argument 1 of "A" A([1], '2') # E: Cannot infer type argument 1 of "A" @@ -492,12 +492,12 @@ class Sub(Base[S]): pass sub_int = Sub[int](attr=1) -reveal_type(sub_int) # N: Revealed type is "__main__.Sub[builtins.int*]" -reveal_type(sub_int.attr) # N: Revealed type is "builtins.int*" +reveal_type(sub_int) # N: Revealed type is "__main__.Sub[builtins.int]" +reveal_type(sub_int.attr) # N: Revealed type is "builtins.int" sub_str = Sub[str](attr='ok') -reveal_type(sub_str) # N: Revealed type is "__main__.Sub[builtins.str*]" -reveal_type(sub_str.attr) # N: Revealed type is "builtins.str*" +reveal_type(sub_str) # N: Revealed type is "__main__.Sub[builtins.str]" +reveal_type(sub_str.attr) # N: Revealed type is "builtins.str" [builtins fixtures/bool.pyi] @@ -522,9 +522,9 @@ class Sub(Base[int, str, float]): sub = Sub(one=1, two='ok', three=3.14) reveal_type(sub) # N: Revealed type is "__main__.Sub" -reveal_type(sub.one) # N: Revealed type is "builtins.int*" -reveal_type(sub.two) # N: Revealed type is "builtins.str*" -reveal_type(sub.three) # N: Revealed type is "builtins.float*" +reveal_type(sub.one) # N: Revealed type is "builtins.int" +reveal_type(sub.two) # N: Revealed type is "builtins.str" +reveal_type(sub.three) # N: Revealed type is "builtins.float" [builtins fixtures/bool.pyi] @@ -551,8 +551,8 @@ class Sub(Middle[str]): sub = Sub(base_attr=1, middle_attr='ok') reveal_type(sub) # N: Revealed type is "__main__.Sub" -reveal_type(sub.base_attr) # N: Revealed type is "builtins.int*" -reveal_type(sub.middle_attr) # N: Revealed type is "builtins.str*" +reveal_type(sub.base_attr) # N: Revealed type is "builtins.int" +reveal_type(sub.middle_attr) # N: Revealed type is "builtins.str" [builtins fixtures/bool.pyi] diff --git a/test-data/unit/check-callable.test b/test-data/unit/check-callable.test index 697a323f2365e..7d25eb271f534 100644 --- a/test-data/unit/check-callable.test +++ b/test-data/unit/check-callable.test @@ -310,7 +310,7 @@ def f(t: T) -> None: # N: Revealed type is "builtins.int" \ # N: Revealed type is "builtins.str" else: - reveal_type(t) # N: Revealed type is "builtins.int*" # N: Revealed type is "builtins.str" + reveal_type(t) # N: Revealed type is "builtins.int" # N: Revealed type is "builtins.str" [builtins fixtures/callable.pyi] diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index 65b0e8d69cb57..d74481a55cbbd 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -1543,8 +1543,8 @@ class A: f = D(10) g = D('10') a = A() -reveal_type(a.f) # N: Revealed type is "builtins.int*" -reveal_type(a.g) # N: Revealed type is "builtins.str*" +reveal_type(a.f) # N: Revealed type is "builtins.int" +reveal_type(a.g) # N: Revealed type is "builtins.str" [case testSettingGenericDataDescriptor] from typing import TypeVar, Type, Generic, Any @@ -1568,10 +1568,10 @@ from d import D class A: f = D(10) # type: D[A, int] g = D('10') # type: D[A, str] -reveal_type(A.f) # N: Revealed type is "d.D[__main__.A*, builtins.int*]" -reveal_type(A.g) # N: Revealed type is "d.D[__main__.A*, builtins.str*]" -reveal_type(A().f) # N: Revealed type is "builtins.int*" -reveal_type(A().g) # N: Revealed type is "builtins.str*" +reveal_type(A.f) # N: Revealed type is "d.D[__main__.A, builtins.int]" +reveal_type(A.g) # N: Revealed type is "d.D[__main__.A, builtins.str]" +reveal_type(A().f) # N: Revealed type is "builtins.int" +reveal_type(A().g) # N: Revealed type is "builtins.str" [file d.pyi] from typing import TypeVar, Type, Generic, overload T = TypeVar('T') @@ -1606,8 +1606,8 @@ class D(Generic[T, V]): def __get__(self, inst: T, own: Type[T]) -> V: pass [builtins fixtures/bool.pyi] [out] -main:8: note: Revealed type is "d.D[__main__.A*, builtins.int*]" -main:9: note: Revealed type is "d.D[__main__.A*, builtins.str*]" +main:8: note: Revealed type is "d.D[__main__.A, builtins.int]" +main:9: note: Revealed type is "d.D[__main__.A, builtins.str]" [case testAccessingGenericDescriptorFromClassBadOverload] # flags: --strict-optional @@ -1677,8 +1677,8 @@ class A: f = D(10) g = D('10') a = A() -reveal_type(a.f) # N: Revealed type is "builtins.int*" -reveal_type(a.g) # N: Revealed type is "builtins.str*" +reveal_type(a.f) # N: Revealed type is "builtins.int" +reveal_type(a.g) # N: Revealed type is "builtins.str" [case testSettingGenericDataDescriptorSubclass] from typing import TypeVar, Type, Generic @@ -2299,7 +2299,7 @@ class Fraction(Real): # Note: When doing A + B and if B is a subtype of A, we will always call B.__radd__(A) first # and only try A.__add__(B) second if necessary. -reveal_type(Real() + Fraction()) # N: Revealed type is "__main__.Real*" +reveal_type(Real() + Fraction()) # N: Revealed type is "__main__.Real" # Note: When doing A + A, we only ever call A.__add__(A), never A.__radd__(A). reveal_type(Fraction() + Fraction()) # N: Revealed type is "builtins.str" @@ -2312,7 +2312,7 @@ class Real: class Fraction(Real): def __radd__(self, other: T) -> T: ... # E: Signatures of "__radd__" of "Fraction" and "__add__" of "T" are unsafely overlapping -reveal_type(Real() + Fraction()) # N: Revealed type is "__main__.Real*" +reveal_type(Real() + Fraction()) # N: Revealed type is "__main__.Real" reveal_type(Fraction() + Fraction()) # N: Revealed type is "builtins.str" @@ -2324,7 +2324,7 @@ class Real: class Fraction(Real): def __radd__(self, other: T) -> T: ... # E: Signatures of "__radd__" of "Fraction" and "__add__" of "Real" are unsafely overlapping -reveal_type(Real() + Fraction()) # N: Revealed type is "__main__.Real*" +reveal_type(Real() + Fraction()) # N: Revealed type is "__main__.Real" reveal_type(Fraction() + Fraction()) # N: Revealed type is "builtins.str" [case testReverseOperatorTypeVar3] @@ -2336,8 +2336,8 @@ class Fraction(Real): def __radd__(self, other: T) -> T: ... # E: Signatures of "__radd__" of "Fraction" and "__add__" of "T" are unsafely overlapping class FractionChild(Fraction): pass -reveal_type(Real() + Fraction()) # N: Revealed type is "__main__.Real*" -reveal_type(FractionChild() + Fraction()) # N: Revealed type is "__main__.FractionChild*" +reveal_type(Real() + Fraction()) # N: Revealed type is "__main__.Real" +reveal_type(FractionChild() + Fraction()) # N: Revealed type is "__main__.FractionChild" reveal_type(FractionChild() + FractionChild()) # N: Revealed type is "builtins.str" # Runtime error: we try calling __add__, it doesn't match, and we don't try __radd__ since @@ -2512,7 +2512,7 @@ def sum(x: Iterable[T]) -> Union[T, int]: ... def len(x: Iterable[T]) -> int: ... x = [1.1, 2.2, 3.3] -reveal_type(sum(x)) # N: Revealed type is "builtins.float*" +reveal_type(sum(x)) # N: Revealed type is "builtins.float" reveal_type(sum(x) / len(x)) # N: Revealed type is "builtins.float" [builtins fixtures/floatdict.pyi] @@ -2528,7 +2528,7 @@ def sum(x: Iterable[T], default: S) -> Union[T, S]: ... def sum(*args): pass x = ["a", "b", "c"] -reveal_type(x + sum([x, x, x], [])) # N: Revealed type is "builtins.list[builtins.str*]" +reveal_type(x + sum([x, x, x], [])) # N: Revealed type is "builtins.list[builtins.str]" [builtins fixtures/floatdict.pyi] [case testAbstractReverseOperatorMethod] @@ -3136,7 +3136,7 @@ class A(Generic[T]): class B(Generic[T]): a: Type[A[T]] = A -reveal_type(B[int]().a) # N: Revealed type is "Type[__main__.A[builtins.int*]]" +reveal_type(B[int]().a) # N: Revealed type is "Type[__main__.A[builtins.int]]" B[int]().a('hi') # E: Argument 1 to "A" has incompatible type "str"; expected "int" class C(Generic[T]): @@ -3168,7 +3168,7 @@ class C: def __init__(self) -> None: self.aa = self.a_int() -reveal_type(C().aa) # N: Revealed type is "__main__.A[builtins.int*, builtins.int*]" +reveal_type(C().aa) # N: Revealed type is "__main__.A[builtins.int, builtins.int]" [out] @@ -3217,7 +3217,7 @@ pro_user = new_user(ProUser) reveal_type(pro_user) [out] main:7: note: Revealed type is "U`-1" -main:10: note: Revealed type is "__main__.ProUser*" +main:10: note: Revealed type is "__main__.ProUser" [case testTypeUsingTypeCTypeVarDefaultInit] from typing import Type, TypeVar @@ -3254,7 +3254,7 @@ reveal_type(wiz) def error(u_c: Type[U]) -> P: return new_pro(u_c) # Error here, see below [out] -main:11: note: Revealed type is "__main__.WizUser*" +main:11: note: Revealed type is "__main__.WizUser" main:13: error: Value of type variable "P" of "new_pro" cannot be "U" main:13: error: Incompatible return value type (got "U", expected "P") @@ -3279,7 +3279,7 @@ class C(Generic[T_co]): def meth(self) -> None: reveal_type(self.x) # N: Revealed type is "T_co`1" -reveal_type(C(1).x) # N: Revealed type is "builtins.int*" +reveal_type(C(1).x) # N: Revealed type is "builtins.int" [builtins fixtures/property.pyi] [out] @@ -3524,7 +3524,7 @@ y = None # type: Type[Any] z = None # type: Type[C] lst = [x, y, z] -reveal_type(lst) # N: Revealed type is "builtins.list[builtins.type*]" +reveal_type(lst) # N: Revealed type is "builtins.list[builtins.type]" T1 = TypeVar('T1', bound=type) T2 = TypeVar('T2', bound=Type[Any]) @@ -4423,14 +4423,14 @@ class ImplicitMeta(type): class Implicit(metaclass=ImplicitMeta): pass for _ in Implicit: pass -reveal_type(list(Implicit)) # N: Revealed type is "builtins.list[builtins.int*]" +reveal_type(list(Implicit)) # N: Revealed type is "builtins.list[builtins.int]" class ExplicitMeta(type, Iterable[int]): def __iter__(self) -> Iterator[int]: yield 1 class Explicit(metaclass=ExplicitMeta): pass for _ in Explicit: pass -reveal_type(list(Explicit)) # N: Revealed type is "builtins.list[builtins.int*]" +reveal_type(list(Explicit)) # N: Revealed type is "builtins.list[builtins.int]" [builtins fixtures/list.pyi] @@ -4490,7 +4490,7 @@ class M1(M): def foo(cls: Type[T]) -> T: ... class A(metaclass=M1): pass -reveal_type(A.foo()) # N: Revealed type is "__main__.A*" +reveal_type(A.foo()) # N: Revealed type is "__main__.A" [case testMetaclassAndSkippedImport] # flags: --ignore-missing-imports @@ -4567,7 +4567,7 @@ class A(metaclass=M): def foo(self): pass reveal_type(A.g1) # N: Revealed type is "def () -> __main__.A" -reveal_type(A.g2) # N: Revealed type is "def () -> __main__.A*" +reveal_type(A.g2) # N: Revealed type is "def () -> __main__.A" reveal_type(A.g3) # N: Revealed type is "def () -> def () -> __main__.A" reveal_type(A.g4) # N: Revealed type is "def () -> def () -> __main__.A" @@ -4584,7 +4584,7 @@ reveal_type(B.g4) # N: Revealed type is "def () -> def () -> __main__.B" ta: Type[A] = m # E: Incompatible types in assignment (expression has type "M", variable has type "Type[A]") a: A = ta() reveal_type(ta.g1) # N: Revealed type is "def () -> __main__.A" -reveal_type(ta.g2) # N: Revealed type is "def () -> __main__.A*" +reveal_type(ta.g2) # N: Revealed type is "def () -> __main__.A" reveal_type(ta.g3) # N: Revealed type is "def () -> Type[__main__.A]" reveal_type(ta.g4) # N: Revealed type is "def () -> Type[__main__.A]" @@ -4592,7 +4592,7 @@ x: M = ta x.g1 # E: Invalid self argument "M" to attribute function "g1" with type "Callable[[Type[A]], A]" x.g2 # E: Invalid self argument "M" to attribute function "g2" with type "Callable[[Type[TA]], TA]" x.g3 # E: Invalid self argument "M" to attribute function "g3" with type "Callable[[TTA], TTA]" -reveal_type(x.g4) # N: Revealed type is "def () -> __main__.M*" +reveal_type(x.g4) # N: Revealed type is "def () -> __main__.M" def r(ta: Type[TA], tta: TTA) -> None: x: M = ta @@ -4665,7 +4665,7 @@ class ExampleDict(Generic[K, V]): ... D = TypeVar('D') def mkdict(dict_type: Type[D]) -> D: ... -reveal_type(mkdict(ExampleDict)) # N: Revealed type is "__main__.ExampleDict*[Any, Any]" +reveal_type(mkdict(ExampleDict)) # N: Revealed type is "__main__.ExampleDict[Any, Any]" [case testTupleForwardBase] from m import a @@ -4766,7 +4766,7 @@ def parse_ast(name_dict: NameDict) -> None: if isinstance(name_dict[''], int): pass x = name_dict[''] - reveal_type(x) # N: Revealed type is "__main__.NameInfo*" + reveal_type(x) # N: Revealed type is "__main__.NameInfo" if int(): x = NameInfo(Base()) # OK x = Base() # E: Incompatible types in assignment (expression has type "Base", variable has type "NameInfo") @@ -5136,8 +5136,8 @@ C1().foo() D1().foo() C1().bar() # E: "C1" has no attribute "bar" D1().bar() # E: "D1" has no attribute "bar" -for x in C1: reveal_type(x) # N: Revealed type is "builtins.int*" -for x in C2: reveal_type(x) # N: Revealed type is "builtins.int*" +for x in C1: reveal_type(x) # N: Revealed type is "builtins.int" +for x in C2: reveal_type(x) # N: Revealed type is "builtins.int" C2().foo() D2().foo() C2().bar() @@ -5163,8 +5163,8 @@ class Arc1(Generic[T_co], Destroyable): pass class MyDestr(Destroyable): pass -reveal_type(Arc[MyDestr]()) # N: Revealed type is "__main__.Arc[__main__.MyDestr*]" -reveal_type(Arc1[MyDestr]()) # N: Revealed type is "__main__.Arc1[__main__.MyDestr*]" +reveal_type(Arc[MyDestr]()) # N: Revealed type is "__main__.Arc[__main__.MyDestr]" +reveal_type(Arc1[MyDestr]()) # N: Revealed type is "__main__.Arc1[__main__.MyDestr]" [builtins fixtures/bool.pyi] [typing fixtures/typing-full.pyi] @@ -5276,8 +5276,8 @@ reveal_type(type(C1).x) # N: Revealed type is "builtins.int" reveal_type(type(C2).x) # N: Revealed type is "builtins.int" C1().foo() C1().bar() # E: "C1" has no attribute "bar" -for x in C1: reveal_type(x) # N: Revealed type is "builtins.int*" -for x in C2: reveal_type(x) # N: Revealed type is "builtins.int*" +for x in C1: reveal_type(x) # N: Revealed type is "builtins.int" +for x in C2: reveal_type(x) # N: Revealed type is "builtins.int" C2().foo() C2().bar() C2().baz() # E: "C2" has no attribute "baz" @@ -5297,7 +5297,7 @@ class Arc(future.utils.with_metaclass(ArcMeta, Generic[T_co], Destroyable)): pass class MyDestr(Destroyable): pass -reveal_type(Arc[MyDestr]()) # N: Revealed type is "__main__.Arc[__main__.MyDestr*]" +reveal_type(Arc[MyDestr]()) # N: Revealed type is "__main__.Arc[__main__.MyDestr]" [builtins fixtures/bool.pyi] [typing fixtures/typing-full.pyi] @@ -5405,7 +5405,7 @@ T = TypeVar('T') class C(Any): def bar(self: T) -> Type[T]: pass def foo(self) -> None: - reveal_type(self.bar()) # N: Revealed type is "Type[__main__.C*]" + reveal_type(self.bar()) # N: Revealed type is "Type[__main__.C]" reveal_type(self.bar().__name__) # N: Revealed type is "builtins.str" [builtins fixtures/type.pyi] [out] @@ -5580,7 +5580,7 @@ class D(C[Descr]): d: D reveal_type(d.normal) # N: Revealed type is "builtins.int" -reveal_type(d.dynamic) # N: Revealed type is "__main__.Descr*" +reveal_type(d.dynamic) # N: Revealed type is "__main__.Descr" reveal_type(D.other) # N: Revealed type is "builtins.int" D.dynamic # E: "Type[D]" has no attribute "dynamic" [out] @@ -5645,7 +5645,7 @@ class B(Generic[T]): ... y: A z: A[int] x = [y, z] -reveal_type(x) # N: Revealed type is "builtins.list[__main__.B*[Any]]" +reveal_type(x) # N: Revealed type is "builtins.list[__main__.B[Any]]" A = B [builtins fixtures/list.pyi] @@ -5668,8 +5668,8 @@ class C(dynamic): name = Descr(str) c: C -reveal_type(c.id) # N: Revealed type is "builtins.int*" -reveal_type(C.name) # N: Revealed type is "d.Descr[builtins.str*]" +reveal_type(c.id) # N: Revealed type is "builtins.int" +reveal_type(C.name) # N: Revealed type is "d.Descr[builtins.str]" [file d.pyi] from typing import Any, overload, Generic, TypeVar, Type @@ -5699,8 +5699,8 @@ class C: def foo(cls) -> int: return 42 -reveal_type(C.foo) # N: Revealed type is "builtins.int*" -reveal_type(C().foo) # N: Revealed type is "builtins.int*" +reveal_type(C.foo) # N: Revealed type is "builtins.int" +reveal_type(C().foo) # N: Revealed type is "builtins.int" [out] [case testMultipleInheritanceCycle] @@ -6064,7 +6064,7 @@ class A(b.B): @c.deco def meth(self) -> int: y = super().meth() - reveal_type(y) # N: Revealed type is "Tuple[builtins.int*, builtins.int]" + reveal_type(y) # N: Revealed type is "Tuple[builtins.int, builtins.int]" return 0 [file b.py] from a import A @@ -6123,7 +6123,7 @@ class A(b.B): @c.deco def meth(self) -> int: y = super().meth() - reveal_type(y) # N: Revealed type is "Tuple[builtins.int*, builtins.int]" + reveal_type(y) # N: Revealed type is "Tuple[builtins.int, builtins.int]" reveal_type(other.x) # N: Revealed type is "builtins.int" return 0 @@ -6565,8 +6565,8 @@ class X: pass class Y(X): pass -reveal_type(X(20)) # N: Revealed type is "__main__.X*" -reveal_type(Y(20)) # N: Revealed type is "__main__.Y*" +reveal_type(X(20)) # N: Revealed type is "__main__.X" +reveal_type(Y(20)) # N: Revealed type is "__main__.Y" [case testNewReturnType5] from typing import Any, TypeVar, Generic, overload diff --git a/test-data/unit/check-ctypes.test b/test-data/unit/check-ctypes.test index e309060166b35..17b87904e9c6a 100644 --- a/test-data/unit/check-ctypes.test +++ b/test-data/unit/check-ctypes.test @@ -7,7 +7,7 @@ class MyCInt(ctypes.c_int): intarr4 = ctypes.c_int * 4 a = intarr4(1, ctypes.c_int(2), MyCInt(3), 4) intarr4(1, 2, 3, "invalid") # E: Array constructor argument 4 of type "str" is not convertible to the array element type "c_int" -reveal_type(a) # N: Revealed type is "ctypes.Array[ctypes.c_int*]" +reveal_type(a) # N: Revealed type is "ctypes.Array[ctypes.c_int]" reveal_type(a[0]) # N: Revealed type is "builtins.int" reveal_type(a[1:3]) # N: Revealed type is "builtins.list[builtins.int]" a[0] = 42 @@ -18,7 +18,7 @@ a[3] = b"bytes" # E: No overload variant of "__setitem__" of "Array" matches ar # N: def __setitem__(self, int, Union[c_int, int]) -> None \ # N: def __setitem__(self, slice, List[Union[c_int, int]]) -> None for x in a: - reveal_type(x) # N: Revealed type is "builtins.int*" + reveal_type(x) # N: Revealed type is "builtins.int" [builtins fixtures/floatdict.pyi] [case testCtypesArrayCustomElementType] @@ -32,9 +32,9 @@ myintarr4 = MyCInt * 4 mya = myintarr4(1, 2, MyCInt(3), 4) myintarr4(1, ctypes.c_int(2), MyCInt(3), "invalid") # E: Array constructor argument 2 of type "c_int" is not convertible to the array element type "MyCInt" \ # E: Array constructor argument 4 of type "str" is not convertible to the array element type "MyCInt" -reveal_type(mya) # N: Revealed type is "ctypes.Array[__main__.MyCInt*]" -reveal_type(mya[0]) # N: Revealed type is "__main__.MyCInt*" -reveal_type(mya[1:3]) # N: Revealed type is "builtins.list[__main__.MyCInt*]" +reveal_type(mya) # N: Revealed type is "ctypes.Array[__main__.MyCInt]" +reveal_type(mya[0]) # N: Revealed type is "__main__.MyCInt" +reveal_type(mya[1:3]) # N: Revealed type is "builtins.list[__main__.MyCInt]" mya[0] = 42 mya[1] = ctypes.c_int(42) # E: No overload variant of "__setitem__" of "Array" matches argument types "int", "c_int" \ # N: Possible overload variants: \ @@ -46,11 +46,11 @@ mya[3] = b"bytes" # E: No overload variant of "__setitem__" of "Array" matches # N: def __setitem__(self, int, Union[MyCInt, int]) -> None \ # N: def __setitem__(self, slice, List[Union[MyCInt, int]]) -> None for myx in mya: - reveal_type(myx) # N: Revealed type is "__main__.MyCInt*" + reveal_type(myx) # N: Revealed type is "__main__.MyCInt" myu: Union[ctypes.Array[ctypes.c_int], List[str]] for myi in myu: - reveal_type(myi) # N: Revealed type is "Union[builtins.int*, builtins.str*]" + reveal_type(myi) # N: Revealed type is "Union[builtins.int, builtins.str]" [builtins fixtures/floatdict.pyi] [case testCtypesArrayUnionElementType] @@ -168,10 +168,10 @@ intarr4 = ctypes.c_int * 4 intarr6 = ctypes.c_int * 6 int_values = [1, 2, 3, 4] c_int_values = [ctypes.c_int(1), ctypes.c_int(2), ctypes.c_int(3), ctypes.c_int(4)] -reveal_type(intarr4(*int_values)) # N: Revealed type is "ctypes.Array[ctypes.c_int*]" -reveal_type(intarr4(*c_int_values)) # N: Revealed type is "ctypes.Array[ctypes.c_int*]" -reveal_type(intarr6(1, ctypes.c_int(2), *int_values)) # N: Revealed type is "ctypes.Array[ctypes.c_int*]" -reveal_type(intarr6(1, ctypes.c_int(2), *c_int_values)) # N: Revealed type is "ctypes.Array[ctypes.c_int*]" +reveal_type(intarr4(*int_values)) # N: Revealed type is "ctypes.Array[ctypes.c_int]" +reveal_type(intarr4(*c_int_values)) # N: Revealed type is "ctypes.Array[ctypes.c_int]" +reveal_type(intarr6(1, ctypes.c_int(2), *int_values)) # N: Revealed type is "ctypes.Array[ctypes.c_int]" +reveal_type(intarr6(1, ctypes.c_int(2), *c_int_values)) # N: Revealed type is "ctypes.Array[ctypes.c_int]" float_values = [1.0, 2.0, 3.0, 4.0] intarr4(*float_values) # E: Array constructor argument 1 of type "List[float]" is not convertible to the array element type "Iterable[c_int]" diff --git a/test-data/unit/check-custom-plugin.test b/test-data/unit/check-custom-plugin.test index 2707d886d64ef..b5bf0a67eb915 100644 --- a/test-data/unit/check-custom-plugin.test +++ b/test-data/unit/check-custom-plugin.test @@ -345,8 +345,8 @@ class C: c = C() reveal_type(c.x) # N: Revealed type is "Union[builtins.int, None]" -reveal_type(c.y) # N: Revealed type is "builtins.int*" -reveal_type(c.z) # N: Revealed type is "Union[builtins.int*, None]" +reveal_type(c.y) # N: Revealed type is "builtins.int" +reveal_type(c.z) # N: Revealed type is "Union[builtins.int, None]" [file mod.py] from typing import Generic, TypeVar, Type @@ -558,7 +558,7 @@ reveal_type(foo[3]) # N: Revealed type is "builtins.int" reveal_type(foo(4, 5, 6)) # N: Revealed type is "builtins.int" foo[4] = 5 for x in foo: - reveal_type(x) # N: Revealed type is "builtins.int*" + reveal_type(x) # N: Revealed type is "builtins.int" [file mypy.ini] \[mypy] @@ -649,7 +649,7 @@ from mod import declarative_base Base1 = Base2 = declarative_base() -class C1(Base1): ... +class C1(Base1): ... class C2(Base2): ... [file mod.py] def declarative_base(): ... @@ -762,9 +762,9 @@ T = TypeVar("T") class Class(Generic[T]): def __init__(self, one: T): ... def __call__(self, two: T) -> int: ... -reveal_type(Class("hi")("there")) # N: Revealed type is "builtins.str*" +reveal_type(Class("hi")("there")) # N: Revealed type is "builtins.str" instance = Class(3.14) -reveal_type(instance(2)) # N: Revealed type is "builtins.float*" +reveal_type(instance(2)) # N: Revealed type is "builtins.float" [file mypy.ini] \[mypy] diff --git a/test-data/unit/check-dataclasses.test b/test-data/unit/check-dataclasses.test index 1773ac0eac8d7..869f8397ef067 100644 --- a/test-data/unit/check-dataclasses.test +++ b/test-data/unit/check-dataclasses.test @@ -608,10 +608,10 @@ class A(Generic[T]): reveal_type(A) # N: Revealed type is "def [T] (x: T`1, y: T`1, z: builtins.list[T`1]) -> __main__.A[T`1]" A(1, 2, ["a", "b"]) # E: Cannot infer type argument 1 of "A" a = A(1, 2, [1, 2]) -reveal_type(a) # N: Revealed type is "__main__.A[builtins.int*]" -reveal_type(a.x) # N: Revealed type is "builtins.int*" -reveal_type(a.y) # N: Revealed type is "builtins.int*" -reveal_type(a.z) # N: Revealed type is "builtins.list[builtins.int*]" +reveal_type(a) # N: Revealed type is "__main__.A[builtins.int]" +reveal_type(a.x) # N: Revealed type is "builtins.int" +reveal_type(a.y) # N: Revealed type is "builtins.int" +reveal_type(a.z) # N: Revealed type is "builtins.list[builtins.int]" s: str = a.bar() # E: Incompatible types in assignment (expression has type "int", variable has type "str") [builtins fixtures/dataclasses.pyi] @@ -656,12 +656,12 @@ class Sub(Base[S]): pass sub_int = Sub[int](attr=1) -reveal_type(sub_int) # N: Revealed type is "__main__.Sub[builtins.int*]" -reveal_type(sub_int.attr) # N: Revealed type is "builtins.int*" +reveal_type(sub_int) # N: Revealed type is "__main__.Sub[builtins.int]" +reveal_type(sub_int.attr) # N: Revealed type is "builtins.int" sub_str = Sub[str](attr='ok') -reveal_type(sub_str) # N: Revealed type is "__main__.Sub[builtins.str*]" -reveal_type(sub_str.attr) # N: Revealed type is "builtins.str*" +reveal_type(sub_str) # N: Revealed type is "__main__.Sub[builtins.str]" +reveal_type(sub_str.attr) # N: Revealed type is "builtins.str" [builtins fixtures/dataclasses.pyi] @@ -686,9 +686,9 @@ class Sub(Base[int, str, float]): sub = Sub(one=1, two='ok', three=3.14) reveal_type(sub) # N: Revealed type is "__main__.Sub" -reveal_type(sub.one) # N: Revealed type is "builtins.int*" -reveal_type(sub.two) # N: Revealed type is "builtins.str*" -reveal_type(sub.three) # N: Revealed type is "builtins.float*" +reveal_type(sub.one) # N: Revealed type is "builtins.int" +reveal_type(sub.two) # N: Revealed type is "builtins.str" +reveal_type(sub.three) # N: Revealed type is "builtins.float" [builtins fixtures/dataclasses.pyi] @@ -715,8 +715,8 @@ class Sub(Middle[str]): sub = Sub(base_attr=1, middle_attr='ok') reveal_type(sub) # N: Revealed type is "__main__.Sub" -reveal_type(sub.base_attr) # N: Revealed type is "builtins.int*" -reveal_type(sub.middle_attr) # N: Revealed type is "builtins.str*" +reveal_type(sub.base_attr) # N: Revealed type is "builtins.int" +reveal_type(sub.middle_attr) # N: Revealed type is "builtins.str" [builtins fixtures/dataclasses.pyi] @@ -739,7 +739,7 @@ class A(Generic[T]): @classmethod def other(cls, x: T) -> A[T]: ... -reveal_type(A(0).other) # N: Revealed type is "def (x: builtins.int*) -> __main__.A[builtins.int*]" +reveal_type(A(0).other) # N: Revealed type is "def (x: builtins.int) -> __main__.A[builtins.int]" [builtins fixtures/dataclasses.pyi] [case testDataclassesForwardRefs] diff --git a/test-data/unit/check-default-plugin.test b/test-data/unit/check-default-plugin.test index cbbfce3ab353a..4d8844d254d16 100644 --- a/test-data/unit/check-default-plugin.test +++ b/test-data/unit/check-default-plugin.test @@ -16,7 +16,7 @@ def yield_id(item: T) -> Iterator[T]: reveal_type(yield_id) # N: Revealed type is "def [T] (item: T`-1) -> contextlib.GeneratorContextManager[T`-1]" with yield_id(1) as x: - reveal_type(x) # N: Revealed type is "builtins.int*" + reveal_type(x) # N: Revealed type is "builtins.int" f = yield_id def g(x, y): pass @@ -39,7 +39,7 @@ reveal_type(yield_id) # N: Revealed type is "def [T] (item: T`-1) -> typing.Asyn async def f() -> None: async with yield_id(1) as x: - reveal_type(x) # N: Revealed type is "builtins.int*" + reveal_type(x) # N: Revealed type is "builtins.int" [typing fixtures/typing-async.pyi] [builtins fixtures/tuple.pyi] @@ -69,7 +69,7 @@ def identity(x: int) -> int: return x with _thread_mapper(1) as m: lst = list(m(identity, [2, 3])) - reveal_type(lst) # N: Revealed type is "builtins.list[builtins.int*]" + reveal_type(lst) # N: Revealed type is "builtins.list[builtins.int]" [typing fixtures/typing-medium.pyi] [builtins fixtures/list.pyi] @@ -79,6 +79,6 @@ from typing import Callable, Iterator c: Callable[..., Iterator[int]] reveal_type(c) # N: Revealed type is "def (*Any, **Any) -> typing.Iterator[builtins.int]" -reveal_type(contextmanager(c)) # N: Revealed type is "def (*Any, **Any) -> contextlib.GeneratorContextManager[builtins.int*]" +reveal_type(contextmanager(c)) # N: Revealed type is "def (*Any, **Any) -> contextlib.GeneratorContextManager[builtins.int]" [typing fixtures/typing-medium.pyi] [builtins fixtures/tuple.pyi] diff --git a/test-data/unit/check-enum.test b/test-data/unit/check-enum.test index 9e2b38bd9c8df..2504e8e0e9c30 100644 --- a/test-data/unit/check-enum.test +++ b/test-data/unit/check-enum.test @@ -300,7 +300,7 @@ class E(IntEnum): x = None # type: int reveal_type(E(x)) [out] -main:5: note: Revealed type is "__main__.E*" +main:5: note: Revealed type is "__main__.E" [case testEnumIndex] from enum import IntEnum @@ -345,7 +345,7 @@ class F(Generic[T], Enum): # E: Enum class cannot be generic x: T y: T -reveal_type(F[int].x) # N: Revealed type is "__main__.F[builtins.int*]" +reveal_type(F[int].x) # N: Revealed type is "__main__.F[builtins.int]" [case testEnumFlag] from enum import Flag @@ -542,8 +542,8 @@ from enum import IntEnum Color = IntEnum('Color', 'red green blue') reveal_type(Color['green']) # N: Revealed type is "__main__.Color" for c in Color: - reveal_type(c) # N: Revealed type is "__main__.Color*" -reveal_type(list(Color)) # N: Revealed type is "builtins.list[__main__.Color*]" + reveal_type(c) # N: Revealed type is "__main__.Color" +reveal_type(list(Color)) # N: Revealed type is "builtins.list[__main__.Color]" [builtins fixtures/list.pyi] @@ -2012,13 +2012,13 @@ class C(IntEnum): def f1(c: C) -> None: x = {'x': c.value} - reveal_type(x) # N: Revealed type is "builtins.dict[builtins.str*, builtins.int]" + reveal_type(x) # N: Revealed type is "builtins.dict[builtins.str, builtins.int]" def f2(c: C, a: Any) -> None: x = {'x': c.value, 'y': a} - reveal_type(x) # N: Revealed type is "builtins.dict[builtins.str*, Any]" + reveal_type(x) # N: Revealed type is "builtins.dict[builtins.str, Any]" y = {'y': a, 'x': c.value} - reveal_type(y) # N: Revealed type is "builtins.dict[builtins.str*, Any]" + reveal_type(y) # N: Revealed type is "builtins.dict[builtins.str, Any]" [builtins fixtures/dict.pyi] [case testEnumIgnoreIsDeleted] diff --git a/test-data/unit/check-final.test b/test-data/unit/check-final.test index 063b2b8aba886..a955d021647d7 100644 --- a/test-data/unit/check-final.test +++ b/test-data/unit/check-final.test @@ -250,7 +250,7 @@ class C(Generic[T]): self.x: Final = x self.y: Final = 1 -reveal_type(C((1, 2)).x) # N: Revealed type is "Tuple[builtins.int*, builtins.int*]" +reveal_type(C((1, 2)).x) # N: Revealed type is "Tuple[builtins.int, builtins.int]" C.x # E: Cannot access final instance attribute "x" on class object \ # E: Access to generic instance variables via class is ambiguous C.y # E: Cannot access final instance attribute "y" on class object @@ -1090,4 +1090,4 @@ class A: a: Final[ClassVar[int]] # E: Variable should not be annotated with both ClassVar and Final b: ClassVar[Final[int]] # E: Final can be only used as an outermost qualifier in a variable annotation c: ClassVar[Final] = 1 # E: Final can be only used as an outermost qualifier in a variable annotation -[out] \ No newline at end of file +[out] diff --git a/test-data/unit/check-functions.test b/test-data/unit/check-functions.test index 30150ca436e84..dd0ebb96a25b6 100644 --- a/test-data/unit/check-functions.test +++ b/test-data/unit/check-functions.test @@ -2300,7 +2300,7 @@ def g(__x: T) -> T: pass f = g reveal_type(f) # N: Revealed type is "def [T] (T`-1) -> T`-1" i = f(3) -reveal_type(i) # N: Revealed type is "builtins.int*" +reveal_type(i) # N: Revealed type is "builtins.int" [case testFunctionReturningGenericFunction] from typing import Callable, TypeVar @@ -2311,7 +2311,7 @@ reveal_type(deco) # N: Revealed type is "def () -> def [T] (T`-1) -> T`-1" f = deco() reveal_type(f) # N: Revealed type is "def [T] (T`-1) -> T`-1" i = f(3) -reveal_type(i) # N: Revealed type is "builtins.int*" +reveal_type(i) # N: Revealed type is "builtins.int" [case testFunctionReturningGenericFunctionPartialBinding] from typing import Callable, TypeVar @@ -2322,9 +2322,9 @@ U = TypeVar('U') def deco(x: U) -> Callable[[T, U], T]: pass reveal_type(deco) # N: Revealed type is "def [U] (x: U`-1) -> def [T] (T`-2, U`-1) -> T`-2" f = deco("foo") -reveal_type(f) # N: Revealed type is "def [T] (T`-2, builtins.str*) -> T`-2" +reveal_type(f) # N: Revealed type is "def [T] (T`-2, builtins.str) -> T`-2" i = f(3, "eggs") -reveal_type(i) # N: Revealed type is "builtins.int*" +reveal_type(i) # N: Revealed type is "builtins.int" [case testFunctionReturningGenericFunctionTwoLevelBinding] from typing import Callable, TypeVar @@ -2335,9 +2335,9 @@ def deco() -> Callable[[T], Callable[[T, R], R]]: pass f = deco() reveal_type(f) # N: Revealed type is "def [T] (T`-1) -> def [R] (T`-1, R`-2) -> R`-2" g = f(3) -reveal_type(g) # N: Revealed type is "def [R] (builtins.int*, R`-2) -> R`-2" +reveal_type(g) # N: Revealed type is "def [R] (builtins.int, R`-2) -> R`-2" s = g(4, "foo") -reveal_type(s) # N: Revealed type is "builtins.str*" +reveal_type(s) # N: Revealed type is "builtins.str" [case testGenericFunctionReturnAsDecorator] from typing import Callable, TypeVar diff --git a/test-data/unit/check-generic-alias.test b/test-data/unit/check-generic-alias.test index 73efbd223c6c7..bba3f5f9bd047 100644 --- a/test-data/unit/check-generic-alias.test +++ b/test-data/unit/check-generic-alias.test @@ -252,7 +252,7 @@ B = tuple[int, str] x: B = (1, 'x') y: B = ('x', 1) # E: Incompatible types in assignment (expression has type "Tuple[str, int]", variable has type "Tuple[int, str]") -reveal_type(tuple[int, ...]()) # N: Revealed type is "builtins.tuple[builtins.int*, ...]" +reveal_type(tuple[int, ...]()) # N: Revealed type is "builtins.tuple[builtins.int, ...]" [builtins fixtures/tuple.pyi] [case testTypeAliasWithBuiltinTupleInStub] @@ -290,7 +290,7 @@ d: type[str] [case testTypeAliasWithBuiltinListAliasInStub] # flags: --python-version 3.6 import m -reveal_type(m.a()[0]) # N: Revealed type is "builtins.int*" +reveal_type(m.a()[0]) # N: Revealed type is "builtins.int" [file m.pyi] List = list diff --git a/test-data/unit/check-generic-subtyping.test b/test-data/unit/check-generic-subtyping.test index f97e3015fa326..bd1f487bc895e 100644 --- a/test-data/unit/check-generic-subtyping.test +++ b/test-data/unit/check-generic-subtyping.test @@ -882,43 +882,43 @@ class X1(Iterator[U], Generic[T, U]): pass x1: X1[str, int] -reveal_type(list(x1)) # N: Revealed type is "builtins.list[builtins.int*]" -reveal_type([*x1]) # N: Revealed type is "builtins.list[builtins.int*]" +reveal_type(list(x1)) # N: Revealed type is "builtins.list[builtins.int]" +reveal_type([*x1]) # N: Revealed type is "builtins.list[builtins.int]" class X2(Iterator[T], Generic[T, U]): pass x2: X2[str, int] -reveal_type(list(x2)) # N: Revealed type is "builtins.list[builtins.str*]" -reveal_type([*x2]) # N: Revealed type is "builtins.list[builtins.str*]" +reveal_type(list(x2)) # N: Revealed type is "builtins.list[builtins.str]" +reveal_type([*x2]) # N: Revealed type is "builtins.list[builtins.str]" class X3(Generic[T, U], Iterator[U]): pass x3: X3[str, int] -reveal_type(list(x3)) # N: Revealed type is "builtins.list[builtins.int*]" -reveal_type([*x3]) # N: Revealed type is "builtins.list[builtins.int*]" +reveal_type(list(x3)) # N: Revealed type is "builtins.list[builtins.int]" +reveal_type([*x3]) # N: Revealed type is "builtins.list[builtins.int]" class X4(Generic[T, U], Iterator[T]): pass x4: X4[str, int] -reveal_type(list(x4)) # N: Revealed type is "builtins.list[builtins.str*]" -reveal_type([*x4]) # N: Revealed type is "builtins.list[builtins.str*]" +reveal_type(list(x4)) # N: Revealed type is "builtins.list[builtins.str]" +reveal_type([*x4]) # N: Revealed type is "builtins.list[builtins.str]" class X5(Iterator[T]): pass x5: X5[str] -reveal_type(list(x5)) # N: Revealed type is "builtins.list[builtins.str*]" -reveal_type([*x5]) # N: Revealed type is "builtins.list[builtins.str*]" +reveal_type(list(x5)) # N: Revealed type is "builtins.list[builtins.str]" +reveal_type([*x5]) # N: Revealed type is "builtins.list[builtins.str]" class X6(Generic[T, U], Iterator[bool]): pass x6: X6[str, int] -reveal_type(list(x6)) # N: Revealed type is "builtins.list[builtins.bool*]" -reveal_type([*x6]) # N: Revealed type is "builtins.list[builtins.bool*]" +reveal_type(list(x6)) # N: Revealed type is "builtins.list[builtins.bool]" +reveal_type([*x6]) # N: Revealed type is "builtins.list[builtins.bool]" [builtins fixtures/list.pyi] [case testSubtypingIterableUnpacking2] @@ -930,15 +930,15 @@ class X1(Generic[T, U], Iterator[U], Mapping[U, T]): pass x1: X1[str, int] -reveal_type(list(x1)) # N: Revealed type is "builtins.list[builtins.int*]" -reveal_type([*x1]) # N: Revealed type is "builtins.list[builtins.int*]" +reveal_type(list(x1)) # N: Revealed type is "builtins.list[builtins.int]" +reveal_type([*x1]) # N: Revealed type is "builtins.list[builtins.int]" class X2(Generic[T, U], Iterator[U], Mapping[T, U]): pass x2: X2[str, int] -reveal_type(list(x2)) # N: Revealed type is "builtins.list[builtins.int*]" -reveal_type([*x2]) # N: Revealed type is "builtins.list[builtins.int*]" +reveal_type(list(x2)) # N: Revealed type is "builtins.list[builtins.int]" +reveal_type([*x2]) # N: Revealed type is "builtins.list[builtins.int]" [builtins fixtures/list.pyi] [case testSubtypingMappingUnpacking1] @@ -951,22 +951,22 @@ class X1(Generic[T, U], Mapping[U, T]): pass x1: X1[str, int] -reveal_type(iter(x1)) # N: Revealed type is "typing.Iterator[builtins.int*]" -reveal_type({**x1}) # N: Revealed type is "builtins.dict[builtins.int*, builtins.str*]" +reveal_type(iter(x1)) # N: Revealed type is "typing.Iterator[builtins.int]" +reveal_type({**x1}) # N: Revealed type is "builtins.dict[builtins.int, builtins.str]" class X2(Generic[T, U], Mapping[T, U]): pass x2: X2[str, int] -reveal_type(iter(x2)) # N: Revealed type is "typing.Iterator[builtins.str*]" -reveal_type({**x2}) # N: Revealed type is "builtins.dict[builtins.str*, builtins.int*]" +reveal_type(iter(x2)) # N: Revealed type is "typing.Iterator[builtins.str]" +reveal_type({**x2}) # N: Revealed type is "builtins.dict[builtins.str, builtins.int]" class X3(Generic[T, U], Mapping[bool, float]): pass x3: X3[str, int] -reveal_type(iter(x3)) # N: Revealed type is "typing.Iterator[builtins.bool*]" -reveal_type({**x3}) # N: Revealed type is "builtins.dict[builtins.bool*, builtins.float*]" +reveal_type(iter(x3)) # N: Revealed type is "typing.Iterator[builtins.bool]" +reveal_type({**x3}) # N: Revealed type is "builtins.dict[builtins.bool, builtins.float]" [builtins fixtures/dict.pyi] [case testSubtypingMappingUnpacking2] @@ -985,8 +985,8 @@ reveal_type(iter(x1)) reveal_type({**x1}) func_with_kwargs(**x1) [out] -main:12: note: Revealed type is "typing.Iterator[builtins.int*]" -main:13: note: Revealed type is "builtins.dict[builtins.int*, builtins.str*]" +main:12: note: Revealed type is "typing.Iterator[builtins.int]" +main:13: note: Revealed type is "builtins.dict[builtins.int, builtins.str]" main:14: error: Keywords must be strings main:14: error: Argument 1 to "func_with_kwargs" has incompatible type "**X1[str, int]"; expected "int" [builtins fixtures/dict.pyi] @@ -1000,8 +1000,8 @@ class X1(Generic[T, U], Mapping[U, T], Iterable[U]): pass x1: X1[str, int] -reveal_type(iter(x1)) # N: Revealed type is "typing.Iterator[builtins.int*]" -reveal_type({**x1}) # N: Revealed type is "builtins.dict[builtins.int*, builtins.str*]" +reveal_type(iter(x1)) # N: Revealed type is "typing.Iterator[builtins.int]" +reveal_type({**x1}) # N: Revealed type is "builtins.dict[builtins.int, builtins.str]" # Some people would expect this to raise an error, but this currently does not: # `Mapping` has `Iterable[U]` base class, `X2` has direct `Iterable[T]` base class. @@ -1010,8 +1010,8 @@ class X2(Generic[T, U], Mapping[U, T], Iterable[T]): pass x2: X2[str, int] -reveal_type(iter(x2)) # N: Revealed type is "typing.Iterator[builtins.int*]" -reveal_type({**x2}) # N: Revealed type is "builtins.dict[builtins.int*, builtins.str*]" +reveal_type(iter(x2)) # N: Revealed type is "typing.Iterator[builtins.int]" +reveal_type({**x2}) # N: Revealed type is "builtins.dict[builtins.int, builtins.str]" [builtins fixtures/dict.pyi] [case testNotDirectIterableAndMappingSubtyping] @@ -1023,13 +1023,13 @@ class X1(Generic[T, U], Dict[U, T], Iterable[U]): def __iter__(self) -> Iterator[U]: pass x1: X1[str, int] -reveal_type(iter(x1)) # N: Revealed type is "typing.Iterator[builtins.int*]" -reveal_type({**x1}) # N: Revealed type is "builtins.dict[builtins.int*, builtins.str*]" +reveal_type(iter(x1)) # N: Revealed type is "typing.Iterator[builtins.int]" +reveal_type({**x1}) # N: Revealed type is "builtins.dict[builtins.int, builtins.str]" class X2(Generic[T, U], List[U]): def __iter__(self) -> Iterator[U]: pass x2: X2[str, int] -reveal_type(iter(x2)) # N: Revealed type is "typing.Iterator[builtins.int*]" -reveal_type([*x2]) # N: Revealed type is "builtins.list[builtins.int*]" +reveal_type(iter(x2)) # N: Revealed type is "typing.Iterator[builtins.int]" +reveal_type([*x2]) # N: Revealed type is "builtins.list[builtins.int]" [builtins fixtures/dict.pyi] diff --git a/test-data/unit/check-generics.test b/test-data/unit/check-generics.test index 61f6f6a7836ba..9c5f3a332dab5 100644 --- a/test-data/unit/check-generics.test +++ b/test-data/unit/check-generics.test @@ -468,8 +468,8 @@ class Dummy(Generic[T]): Dummy[int]().meth(1) Dummy[int]().meth('a') # E: Argument 1 to "meth" of "Dummy" has incompatible type "str"; expected "int" -reveal_type(Dummy[int]()) # N: Revealed type is "__main__.Dummy[builtins.int*]" -reveal_type(Dummy[int]().methout()) # N: Revealed type is "builtins.int*" +reveal_type(Dummy[int]()) # N: Revealed type is "__main__.Dummy[builtins.int]" +reveal_type(Dummy[int]().methout()) # N: Revealed type is "builtins.int" [out] [case testTypeApplicationArgTypesSubclasses] @@ -565,7 +565,7 @@ reveal_type(func) # N: Revealed type is "def [T] (x: __main__.Node[builtins.int, func(1) # E: Argument 1 to "func" has incompatible type "int"; expected "Node[int, ]" func(Node('x', 1)) # E: Argument 1 to "Node" has incompatible type "str"; expected "int" -reveal_type(func(Node(1, 'x'))) # N: Revealed type is "__main__.Node[builtins.int, builtins.str*]" +reveal_type(func(Node(1, 'x'))) # N: Revealed type is "__main__.Node[builtins.int, builtins.str]" def func2(x: SameNode[T]) -> SameNode[T]: return x @@ -573,13 +573,13 @@ reveal_type(func2) # N: Revealed type is "def [T] (x: __main__.Node[T`-1, T`-1]) func2(Node(1, 'x')) # E: Cannot infer type argument 1 of "func2" y = func2(Node('x', 'x')) -reveal_type(y) # N: Revealed type is "__main__.Node[builtins.str*, builtins.str*]" +reveal_type(y) # N: Revealed type is "__main__.Node[builtins.str, builtins.str]" def wrap(x: T) -> IntNode[T]: return Node(1, x) z = None # type: str -reveal_type(wrap(z)) # N: Revealed type is "__main__.Node[builtins.int, builtins.str*]" +reveal_type(wrap(z)) # N: Revealed type is "__main__.Node[builtins.int, builtins.str]" [out] main:13: error: Argument 2 to "Node" has incompatible type "int"; expected "str" @@ -640,7 +640,7 @@ Third = Union[int, Second[str]] def f2(x: T) -> Second[T]: return Node([1], [x]) -reveal_type(f2('a')) # N: Revealed type is "__main__.Node[builtins.list[builtins.int], builtins.list[builtins.str*]]" +reveal_type(f2('a')) # N: Revealed type is "__main__.Node[builtins.list[builtins.int], builtins.list[builtins.str]]" def f3() -> Third: return Node([1], ['x']) @@ -688,7 +688,7 @@ ListedNode = Node[List[T]] l = None # type: ListedNode[int] l.x.append(1) l.meth().append(1) -reveal_type(l.meth()) # N: Revealed type is "builtins.list*[builtins.int]" +reveal_type(l.meth()) # N: Revealed type is "builtins.list[builtins.int]" l.meth().append('x') # E: Argument 1 to "append" of "list" has incompatible type "str"; expected "int" ListedNode[str]([]).x = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "List[str]") @@ -720,7 +720,7 @@ y = D(5) # type: D[int] # E: Argument 1 to "D" has incompatible type "int"; expe def f(x: T) -> D[T]: return D((x, x)) -reveal_type(f('a')) # N: Revealed type is "__main__.D[builtins.str*]" +reveal_type(f('a')) # N: Revealed type is "__main__.D[builtins.str]" [builtins fixtures/list.pyi] [out] @@ -741,7 +741,7 @@ class C(TupledNode): ... # Same as TupledNode[Any] class D(TupledNode[T]): ... class E(Generic[T], UNode[T]): ... # E: Invalid base class "UNode" -reveal_type(D((1, 1))) # N: Revealed type is "__main__.D[builtins.int*]" +reveal_type(D((1, 1))) # N: Revealed type is "__main__.D[builtins.int]" [builtins fixtures/list.pyi] [case testGenericTypeAliasesUnion] @@ -769,7 +769,7 @@ def f(x: T) -> UNode[T]: else: return 1 -reveal_type(f(1)) # N: Revealed type is "Union[builtins.int, __main__.Node[builtins.int*]]" +reveal_type(f(1)) # N: Revealed type is "Union[builtins.int, __main__.Node[builtins.int]]" TNode = Union[T, Node[int]] s = 1 # type: TNode[str] # E: Incompatible types in assignment (expression has type "int", variable has type "Union[str, Node[int]]") @@ -801,7 +801,7 @@ def f2(x: IntTP[T]) -> IntTP[T]: return x f2((1, 2, 3)) # E: Argument 1 to "f2" has incompatible type "Tuple[int, int, int]"; expected "Tuple[int, ]" -reveal_type(f2((1, 'x'))) # N: Revealed type is "Tuple[builtins.int, builtins.str*]" +reveal_type(f2((1, 'x'))) # N: Revealed type is "Tuple[builtins.int, builtins.str]" [builtins fixtures/for.pyi] @@ -820,7 +820,7 @@ C2 = Callable[[T, T], Node[T]] def make_cb(x: T) -> C[T]: return lambda *args: x -reveal_type(make_cb(1)) # N: Revealed type is "def (*Any, **Any) -> builtins.int*" +reveal_type(make_cb(1)) # N: Revealed type is "def (*Any, **Any) -> builtins.int" def use_cb(arg: T, cb: C2[T]) -> Node[T]: return cb(arg, arg) @@ -848,11 +848,11 @@ def fun1(v: Vec[T]) -> T: def fun2(v: Vec[T], scale: T) -> Vec[T]: return v -reveal_type(fun1([(1, 1)])) # N: Revealed type is "builtins.int*" +reveal_type(fun1([(1, 1)])) # N: Revealed type is "builtins.int" fun1(1) # E: Argument 1 to "fun1" has incompatible type "int"; expected "List[Tuple[bool, bool]]" fun1([(1, 'x')]) # E: Cannot infer type argument 1 of "fun1" -reveal_type(fun2([(1, 1)], 1)) # N: Revealed type is "builtins.list[Tuple[builtins.int*, builtins.int*]]" +reveal_type(fun2([(1, 1)], 1)) # N: Revealed type is "builtins.list[Tuple[builtins.int, builtins.int]]" fun2([('x', 'x')], 'x') # E: Value of type variable "T" of "fun2" cannot be "str" [builtins fixtures/list.pyi] @@ -872,7 +872,7 @@ def f(x: Node[T, T]) -> TupledNode[T]: f(1) # E: Argument 1 to "f" has incompatible type "int"; expected "Node[, ]" f(Node(1, 'x')) # E: Cannot infer type argument 1 of "f" -reveal_type(Node('x', 'x')) # N: Revealed type is "a.Node[builtins.str*, builtins.str*]" +reveal_type(Node('x', 'x')) # N: Revealed type is "a.Node[builtins.str, builtins.str]" [file a.py] from typing import TypeVar, Generic, Tuple @@ -1012,7 +1012,7 @@ ff = SameNode[T](1, 1) a = SameNode(1, 'x') reveal_type(a) # N: Revealed type is "__main__.Node[Any, Any]" b = SameNode[int](1, 1) -reveal_type(b) # N: Revealed type is "__main__.Node[builtins.int*, builtins.int*]" +reveal_type(b) # N: Revealed type is "__main__.Node[builtins.int, builtins.int]" SameNode[int](1, 'x') # E: Argument 2 to "Node" has incompatible type "str"; expected "int" [out] @@ -1059,8 +1059,8 @@ class C(Generic[T]): a = None # type: SameA[T] b = SameB[T]([], []) -reveal_type(C[int]().a) # N: Revealed type is "__main__.A[builtins.int*, builtins.int*]" -reveal_type(C[str]().b) # N: Revealed type is "__main__.B[builtins.str*, builtins.str*]" +reveal_type(C[int]().a) # N: Revealed type is "__main__.A[builtins.int, builtins.int]" +reveal_type(C[str]().b) # N: Revealed type is "__main__.B[builtins.str, builtins.str]" [builtins fixtures/list.pyi] @@ -1110,7 +1110,7 @@ BuiltinAlias[int]() # E: "list" is not subscriptable T = TypeVar('T') BadGenList = list[T] # E: "list" is not subscriptable -reveal_type(BadGenList[int]()) # N: Revealed type is "builtins.list[builtins.int*]" +reveal_type(BadGenList[int]()) # N: Revealed type is "builtins.list[builtins.int]" reveal_type(BadGenList()) # N: Revealed type is "builtins.list[Any]" [builtins fixtures/list.pyi] @@ -1120,11 +1120,11 @@ reveal_type(BadGenList()) # N: Revealed type is "builtins.list[Any]" from m import Alias n = Alias[int]([1]) -reveal_type(n) # N: Revealed type is "m.Node[builtins.list*[builtins.int]]" +reveal_type(n) # N: Revealed type is "m.Node[builtins.list[builtins.int]]" bad = Alias[str]([1]) # E: List item 0 has incompatible type "int"; expected "str" n2 = Alias([1]) # Same as Node[List[Any]] -reveal_type(n2) # N: Revealed type is "m.Node[builtins.list*[Any]]" +reveal_type(n2) # N: Revealed type is "m.Node[builtins.list[Any]]" [file m.py] from typing import TypeVar, Generic, List T = TypeVar('T') @@ -1152,8 +1152,8 @@ class C(Generic[T]): class D(B[T], C[S]): ... -reveal_type(D[str, int]().b()) # N: Revealed type is "builtins.str*" -reveal_type(D[str, int]().c()) # N: Revealed type is "builtins.int*" +reveal_type(D[str, int]().b()) # N: Revealed type is "builtins.str" +reveal_type(D[str, int]().c()) # N: Revealed type is "builtins.int" [builtins fixtures/list.pyi] [out] @@ -1166,7 +1166,7 @@ class B(Generic[T]): class D(B[Callable[[T], S]]): ... -reveal_type(D[str, int]().b()) # N: Revealed type is "def (builtins.str*) -> builtins.int*" +reveal_type(D[str, int]().b()) # N: Revealed type is "def (builtins.str) -> builtins.int" [builtins fixtures/list.pyi] [out] @@ -1187,7 +1187,7 @@ class C(A[S, B[T, int]], B[U, A[int, T]]): pass c = C[object, int, str]() -reveal_type(c.m()) # N: Revealed type is "Tuple[builtins.str*, __main__.A*[builtins.int, builtins.int*]]" +reveal_type(c.m()) # N: Revealed type is "Tuple[builtins.str, __main__.A[builtins.int, builtins.int]]" [builtins fixtures/tuple.pyi] [out] @@ -1205,8 +1205,8 @@ class C(Generic[T]): class D(B[T], C[S], Generic[S, T]): ... -reveal_type(D[str, int]().b()) # N: Revealed type is "builtins.int*" -reveal_type(D[str, int]().c()) # N: Revealed type is "builtins.str*" +reveal_type(D[str, int]().b()) # N: Revealed type is "builtins.int" +reveal_type(D[str, int]().c()) # N: Revealed type is "builtins.str" [builtins fixtures/list.pyi] [out] @@ -1475,10 +1475,10 @@ class A: class B(Generic[T]): def meth(self) -> T: ... B[int]() - reveal_type(B[int]().meth) # N: Revealed type is "def () -> builtins.int*" + reveal_type(B[int]().meth) # N: Revealed type is "def () -> builtins.int" A.B[int]() -reveal_type(A.B[int]().meth) # N: Revealed type is "def () -> builtins.int*" +reveal_type(A.B[int]().meth) # N: Revealed type is "def () -> builtins.int" [case testGenericClassInnerFunctionTypeVariable] from typing import TypeVar, Generic @@ -1748,7 +1748,7 @@ g = f3 from typing import TypeVar, Container T = TypeVar('T') def f(x: Container[T]) -> T: ... -reveal_type(f((1, 2))) # N: Revealed type is "builtins.int*" +reveal_type(f((1, 2))) # N: Revealed type is "builtins.int" [typing fixtures/typing-full.pyi] [builtins fixtures/tuple.pyi] @@ -1870,8 +1870,8 @@ class C(Generic[T]): class D(C[str]): ... -reveal_type(D.get()) # N: Revealed type is "builtins.str*" -reveal_type(D().get()) # N: Revealed type is "builtins.str*" +reveal_type(D.get()) # N: Revealed type is "builtins.str" +reveal_type(D().get()) # N: Revealed type is "builtins.str" [builtins fixtures/classmethod.pyi] [case testGenericClassMethodExpansion] @@ -1884,8 +1884,8 @@ class C(Generic[T]): class D(C[Tuple[T, T]]): ... class E(D[str]): ... -reveal_type(E.get()) # N: Revealed type is "Tuple[builtins.str*, builtins.str*]" -reveal_type(E().get()) # N: Revealed type is "Tuple[builtins.str*, builtins.str*]" +reveal_type(E.get()) # N: Revealed type is "Tuple[builtins.str, builtins.str]" +reveal_type(E().get()) # N: Revealed type is "Tuple[builtins.str, builtins.str]" [builtins fixtures/classmethod.pyi] [case testGenericClassMethodExpansionReplacingTypeVar] @@ -1900,8 +1900,8 @@ class C(Generic[T]): class D(C[S]): ... class E(D[int]): ... -reveal_type(E.get()) # N: Revealed type is "builtins.int*" -reveal_type(E().get()) # N: Revealed type is "builtins.int*" +reveal_type(E.get()) # N: Revealed type is "builtins.int" +reveal_type(E().get()) # N: Revealed type is "builtins.int" [builtins fixtures/classmethod.pyi] [case testGenericClassMethodUnboundOnClass] @@ -1915,9 +1915,9 @@ class C(Generic[T]): def make_one(cls, x: T) -> C[T]: ... reveal_type(C.get) # N: Revealed type is "def [T] () -> T`1" -reveal_type(C[int].get) # N: Revealed type is "def () -> builtins.int*" +reveal_type(C[int].get) # N: Revealed type is "def () -> builtins.int" reveal_type(C.make_one) # N: Revealed type is "def [T] (x: T`1) -> __main__.C[T`1]" -reveal_type(C[int].make_one) # N: Revealed type is "def (x: builtins.int*) -> __main__.C[builtins.int*]" +reveal_type(C[int].make_one) # N: Revealed type is "def (x: builtins.int) -> __main__.C[builtins.int]" [builtins fixtures/classmethod.pyi] [case testGenericClassMethodUnboundOnSubClass] @@ -1934,9 +1934,9 @@ class D(C[Tuple[T, S]]): ... class E(D[S, str]): ... reveal_type(D.make_one) # N: Revealed type is "def [T, S] (x: Tuple[T`1, S`2]) -> __main__.C[Tuple[T`1, S`2]]" -reveal_type(D[int, str].make_one) # N: Revealed type is "def (x: Tuple[builtins.int*, builtins.str*]) -> __main__.C[Tuple[builtins.int*, builtins.str*]]" -reveal_type(E.make_one) # N: Revealed type is "def [S] (x: Tuple[S`1, builtins.str*]) -> __main__.C[Tuple[S`1, builtins.str*]]" -reveal_type(E[int].make_one) # N: Revealed type is "def (x: Tuple[builtins.int*, builtins.str*]) -> __main__.C[Tuple[builtins.int*, builtins.str*]]" +reveal_type(D[int, str].make_one) # N: Revealed type is "def (x: Tuple[builtins.int, builtins.str]) -> __main__.C[Tuple[builtins.int, builtins.str]]" +reveal_type(E.make_one) # N: Revealed type is "def [S] (x: Tuple[S`1, builtins.str]) -> __main__.C[Tuple[S`1, builtins.str]]" +reveal_type(E[int].make_one) # N: Revealed type is "def (x: Tuple[builtins.int, builtins.str]) -> __main__.C[Tuple[builtins.int, builtins.str]]" [builtins fixtures/classmethod.pyi] [case testGenericClassClsNonGeneric] @@ -2074,8 +2074,8 @@ class Base(Generic[T]): return cls(item) reveal_type(Base.make_some) # N: Revealed type is "Overload(def [T] (item: T`1) -> __main__.Base[T`1], def [T] (item: T`1, n: builtins.int) -> builtins.tuple[__main__.Base[T`1], ...])" -reveal_type(Base.make_some(1)) # N: Revealed type is "__main__.Base[builtins.int*]" -reveal_type(Base.make_some(1, 1)) # N: Revealed type is "builtins.tuple[__main__.Base[builtins.int*], ...]" +reveal_type(Base.make_some(1)) # N: Revealed type is "__main__.Base[builtins.int]" +reveal_type(Base.make_some(1, 1)) # N: Revealed type is "builtins.tuple[__main__.Base[builtins.int], ...]" class Sub(Base[str]): ... Sub.make_some(1) # E: No overload variant of "make_some" of "Base" matches argument type "int" \ @@ -2131,7 +2131,7 @@ class Base(Generic[T]): class Sub(Base[T]): ... -reveal_type(Sub.make_pair('yes')) # N: Revealed type is "Tuple[__main__.Sub[builtins.str*], __main__.Sub[builtins.str*]]" +reveal_type(Sub.make_pair('yes')) # N: Revealed type is "Tuple[__main__.Sub[builtins.str], __main__.Sub[builtins.str]]" Sub[int].make_pair('no') # E: Argument 1 to "make_pair" of "Base" has incompatible type "str"; expected "int" [builtins fixtures/classmethod.pyi] @@ -2182,8 +2182,8 @@ class C(Generic[T]): class D(C[str]): ... -reveal_type(D.get()) # N: Revealed type is "builtins.str*" -reveal_type(D.get(42)) # N: Revealed type is "builtins.tuple[builtins.str*, ...]" +reveal_type(D.get()) # N: Revealed type is "builtins.str" +reveal_type(D.get(42)) # N: Revealed type is "builtins.tuple[builtins.str, ...]" [builtins fixtures/classmethod.pyi] [case testGenericClassMethodAnnotation] @@ -2202,14 +2202,14 @@ def f(o: Maker[T]) -> T: return o.x return o.get() b = f(B()) -reveal_type(b) # N: Revealed type is "__main__.B*" +reveal_type(b) # N: Revealed type is "__main__.B" def g(t: Type[Maker[T]]) -> T: if bool(): return t.x return t.get() bb = g(B) -reveal_type(bb) # N: Revealed type is "__main__.B*" +reveal_type(bb) # N: Revealed type is "__main__.B" [builtins fixtures/classmethod.pyi] [case testGenericClassMethodAnnotationDecorator] @@ -2338,16 +2338,16 @@ class Test(): mte: MakeTwoConcrete[A], mtgsa: MakeTwoGenericSubAbstract[A], mtasa: MakeTwoAppliedSubAbstract) -> None: - reveal_type(mts(2)) # N: Revealed type is "__main__.TwoTypes[A`-1, builtins.int*]" - reveal_type(mte(2)) # N: Revealed type is "__main__.TwoTypes[A`-1, builtins.int*]" - reveal_type(mtgsa(2)) # N: Revealed type is "__main__.TwoTypes[A`-1, builtins.int*]" - reveal_type(mtasa(2)) # N: Revealed type is "__main__.TwoTypes[builtins.str, builtins.int*]" - reveal_type(MakeTwoConcrete[int]()('foo')) # N: Revealed type is "__main__.TwoTypes[builtins.int, builtins.str*]" - reveal_type(MakeTwoConcrete[str]()(2)) # N: Revealed type is "__main__.TwoTypes[builtins.str, builtins.int*]" - reveal_type(MakeTwoAppliedSubAbstract()('foo')) # N: Revealed type is "__main__.TwoTypes[builtins.str, builtins.str*]" - reveal_type(MakeTwoAppliedSubAbstract()(2)) # N: Revealed type is "__main__.TwoTypes[builtins.str, builtins.int*]" - reveal_type(MakeTwoGenericSubAbstract[str]()('foo')) # N: Revealed type is "__main__.TwoTypes[builtins.str, builtins.str*]" - reveal_type(MakeTwoGenericSubAbstract[str]()(2)) # N: Revealed type is "__main__.TwoTypes[builtins.str, builtins.int*]" + reveal_type(mts(2)) # N: Revealed type is "__main__.TwoTypes[A`-1, builtins.int]" + reveal_type(mte(2)) # N: Revealed type is "__main__.TwoTypes[A`-1, builtins.int]" + reveal_type(mtgsa(2)) # N: Revealed type is "__main__.TwoTypes[A`-1, builtins.int]" + reveal_type(mtasa(2)) # N: Revealed type is "__main__.TwoTypes[builtins.str, builtins.int]" + reveal_type(MakeTwoConcrete[int]()('foo')) # N: Revealed type is "__main__.TwoTypes[builtins.int, builtins.str]" + reveal_type(MakeTwoConcrete[str]()(2)) # N: Revealed type is "__main__.TwoTypes[builtins.str, builtins.int]" + reveal_type(MakeTwoAppliedSubAbstract()('foo')) # N: Revealed type is "__main__.TwoTypes[builtins.str, builtins.str]" + reveal_type(MakeTwoAppliedSubAbstract()(2)) # N: Revealed type is "__main__.TwoTypes[builtins.str, builtins.int]" + reveal_type(MakeTwoGenericSubAbstract[str]()('foo')) # N: Revealed type is "__main__.TwoTypes[builtins.str, builtins.str]" + reveal_type(MakeTwoGenericSubAbstract[str]()(2)) # N: Revealed type is "__main__.TwoTypes[builtins.str, builtins.int]" [case testGenericClassPropertyBound] from typing import Generic, TypeVar, Callable, Type, List, Dict @@ -2368,23 +2368,23 @@ class G(C[List[T]]): ... x: C[int] y: Type[C[int]] -reveal_type(x.test) # N: Revealed type is "builtins.int*" -reveal_type(y.test) # N: Revealed type is "builtins.int*" +reveal_type(x.test) # N: Revealed type is "builtins.int" +reveal_type(y.test) # N: Revealed type is "builtins.int" xd: D yd: Type[D] -reveal_type(xd.test) # N: Revealed type is "builtins.str*" -reveal_type(yd.test) # N: Revealed type is "builtins.str*" +reveal_type(xd.test) # N: Revealed type is "builtins.str" +reveal_type(yd.test) # N: Revealed type is "builtins.str" ye1: Type[E1[int, str]] ye2: Type[E2[int, str]] -reveal_type(ye1.test) # N: Revealed type is "builtins.int*" -reveal_type(ye2.test) # N: Revealed type is "builtins.str*" +reveal_type(ye1.test) # N: Revealed type is "builtins.int" +reveal_type(ye2.test) # N: Revealed type is "builtins.str" xg: G[int] yg: Type[G[int]] -reveal_type(xg.test) # N: Revealed type is "builtins.list*[builtins.int*]" -reveal_type(yg.test) # N: Revealed type is "builtins.list*[builtins.int*]" +reveal_type(xg.test) # N: Revealed type is "builtins.list[builtins.int]" +reveal_type(yg.test) # N: Revealed type is "builtins.list[builtins.int]" class Sup: attr: int @@ -2394,8 +2394,8 @@ def func(tp: Type[C[S]]) -> S: reveal_type(tp.test.attr) # N: Revealed type is "builtins.int" reg: Dict[S, G[S]] - reveal_type(reg[tp.test]) # N: Revealed type is "__main__.G*[S`-1]" - reveal_type(reg[tp.test].test) # N: Revealed type is "builtins.list*[S`-1]" + reveal_type(reg[tp.test]) # N: Revealed type is "__main__.G[S`-1]" + reveal_type(reg[tp.test].test) # N: Revealed type is "builtins.list[S`-1]" if bool(): return tp.test @@ -2413,7 +2413,7 @@ gen_a = gen S = TypeVar("S", int, str) class C: ... def test() -> Optional[S]: - reveal_type(gen_a(C())) # N: Revealed type is "__main__.C*" + reveal_type(gen_a(C())) # N: Revealed type is "__main__.C" return None [case testGenericFunctionMemberExpand] @@ -2428,7 +2428,7 @@ class A: S = TypeVar("S", int, str) class C: ... def test() -> Optional[S]: - reveal_type(A().gen(C())) # N: Revealed type is "__main__.C*" + reveal_type(A().gen(C())) # N: Revealed type is "__main__.C" return None [case testGenericJoinCovariant] @@ -2447,8 +2447,8 @@ b: B a_c: Container[A] b_c: Container[B] -reveal_type([a, b]) # N: Revealed type is "builtins.list[__main__.Base*]" -reveal_type([a_c, b_c]) # N: Revealed type is "builtins.list[__main__.Container*[__main__.Base]]" +reveal_type([a, b]) # N: Revealed type is "builtins.list[__main__.Base]" +reveal_type([a_c, b_c]) # N: Revealed type is "builtins.list[__main__.Container[__main__.Base]]" [builtins fixtures/list.pyi] [case testGenericJoinContravariant] @@ -2464,7 +2464,7 @@ a_c: Container[A] b_c: Container[B] # TODO: this can be more precise than "object", see a comment in mypy/join.py -reveal_type([a_c, b_c]) # N: Revealed type is "builtins.list[builtins.object*]" +reveal_type([a_c, b_c]) # N: Revealed type is "builtins.list[builtins.object]" [builtins fixtures/list.pyi] [case testGenericJoinRecursiveTypes] @@ -2476,7 +2476,7 @@ class B(Sequence[B]): ... a: A b: B -reveal_type([a, b]) # N: Revealed type is "builtins.list[typing.Sequence*[builtins.object]]" +reveal_type([a, b]) # N: Revealed type is "builtins.list[typing.Sequence[builtins.object]]" [builtins fixtures/list.pyi] [case testGenericJoinRecursiveInvariant] @@ -2490,7 +2490,7 @@ class B(I[B]): ... a: A b: B -reveal_type([a, b]) # N: Revealed type is "builtins.list[builtins.object*]" +reveal_type([a, b]) # N: Revealed type is "builtins.list[builtins.object]" [builtins fixtures/list.pyi] [case testGenericJoinNestedInvariantAny] @@ -2501,6 +2501,6 @@ class I(Generic[T]): ... a: I[I[int]] b: I[I[Any]] -reveal_type([a, b]) # N: Revealed type is "builtins.list[__main__.I*[__main__.I[Any]]]" -reveal_type([b, a]) # N: Revealed type is "builtins.list[__main__.I*[__main__.I[Any]]]" +reveal_type([a, b]) # N: Revealed type is "builtins.list[__main__.I[__main__.I[Any]]]" +reveal_type([b, a]) # N: Revealed type is "builtins.list[__main__.I[__main__.I[Any]]]" [builtins fixtures/list.pyi] diff --git a/test-data/unit/check-incremental.test b/test-data/unit/check-incremental.test index 1a73f9f33274b..c990f52e74c83 100644 --- a/test-data/unit/check-incremental.test +++ b/test-data/unit/check-incremental.test @@ -1980,14 +1980,14 @@ class D: reveal_type(D().a) [out1] tmp/crash.py:8: note: Revealed type is "crash.A@5" -tmp/crash.py:17: note: Revealed type is "crash.B@13[builtins.int*]" +tmp/crash.py:17: note: Revealed type is "crash.B@13[builtins.int]" main:2: note: Revealed type is "crash.A@5" -main:3: note: Revealed type is "crash.B@13[builtins.int*]" +main:3: note: Revealed type is "crash.B@13[builtins.int]" [out2] tmp/crash.py:8: note: Revealed type is "crash.A@5" -tmp/crash.py:17: note: Revealed type is "crash.B@13[builtins.int*]" +tmp/crash.py:17: note: Revealed type is "crash.B@13[builtins.int]" main:2: note: Revealed type is "crash.A@5" -main:3: note: Revealed type is "crash.B@13[builtins.int*]" +main:3: note: Revealed type is "crash.B@13[builtins.int]" [case testGenericMethodRestoreMetaLevel] from typing import Dict diff --git a/test-data/unit/check-inference-context.test b/test-data/unit/check-inference-context.test index e3ec55c516db5..3bab79f5aec26 100644 --- a/test-data/unit/check-inference-context.test +++ b/test-data/unit/check-inference-context.test @@ -913,7 +913,7 @@ from typing import TypeVar, Union, List T = TypeVar('T') def f(x: Union[T, List[int]]) -> Union[T, List[int]]: pass -reveal_type(f(1)) # N: Revealed type is "Union[builtins.int*, builtins.list[builtins.int]]" +reveal_type(f(1)) # N: Revealed type is "Union[builtins.int, builtins.list[builtins.int]]" reveal_type(f([])) # N: Revealed type is "builtins.list[builtins.int]" reveal_type(f(None)) # N: Revealed type is "builtins.list[builtins.int]" [builtins fixtures/list.pyi] @@ -925,7 +925,7 @@ from typing import TypeVar, Union, List T = TypeVar('T') def f(x: Union[T, List[int]]) -> Union[T, List[int]]: pass -reveal_type(f(1)) # N: Revealed type is "Union[builtins.int*, builtins.list[builtins.int]]" +reveal_type(f(1)) # N: Revealed type is "Union[builtins.int, builtins.list[builtins.int]]" reveal_type(f([])) # N: Revealed type is "builtins.list[builtins.int]" reveal_type(f(None)) # N: Revealed type is "Union[None, builtins.list[builtins.int]]" [builtins fixtures/list.pyi] @@ -940,7 +940,7 @@ class C(Generic[T]): def f(self, x: Union[T, S]) -> Union[T, S]: pass c = C[List[int]]() -reveal_type(c.f('')) # N: Revealed type is "Union[builtins.list[builtins.int], builtins.str*]" +reveal_type(c.f('')) # N: Revealed type is "Union[builtins.list[builtins.int], builtins.str]" reveal_type(c.f([1])) # N: Revealed type is "builtins.list[builtins.int]" reveal_type(c.f([])) # N: Revealed type is "builtins.list[builtins.int]" reveal_type(c.f(None)) # N: Revealed type is "builtins.list[builtins.int]" @@ -991,7 +991,7 @@ class D(C): ... def f(x: Sequence[T], y: Sequence[T]) -> List[T]: ... -reveal_type(f([C()], [D()])) # N: Revealed type is "builtins.list[__main__.C*]" +reveal_type(f([C()], [D()])) # N: Revealed type is "builtins.list[__main__.C]" [builtins fixtures/list.pyi] [case testInferTypeVariableFromTwoGenericTypes2] @@ -1023,7 +1023,7 @@ def f(x: A[T], y: A[T]) -> B[T]: ... c: B[C] d: B[D] -reveal_type(f(c, d)) # N: Revealed type is "__main__.B[__main__.D*]" +reveal_type(f(c, d)) # N: Revealed type is "__main__.B[__main__.D]" [case testInferTypeVariableFromTwoGenericTypes4] from typing import Generic, TypeVar, Callable, List @@ -1043,7 +1043,7 @@ def f(x: Callable[[B[T]], None], def gc(x: A[C]) -> None: pass # B[C] def gd(x: A[D]) -> None: pass # B[C] -reveal_type(f(gc, gd)) # N: Revealed type is "builtins.list[__main__.C*]" +reveal_type(f(gc, gd)) # N: Revealed type is "builtins.list[__main__.C]" [builtins fixtures/list.pyi] [case testWideOuterContextSubClassBound] diff --git a/test-data/unit/check-inference.test b/test-data/unit/check-inference.test index 4de6e4a76f925..21c96bf2df45c 100644 --- a/test-data/unit/check-inference.test +++ b/test-data/unit/check-inference.test @@ -699,7 +699,7 @@ def f(x: Callable[..., T]) -> T: return x() class A: pass x = None # type: Type[A] y = f(x) -reveal_type(y) # N: Revealed type is "__main__.A*" +reveal_type(y) # N: Revealed type is "__main__.A" -- Generic function inference with unions -- -------------------------------------- @@ -854,7 +854,7 @@ class V(T[_T], U[_T]): pass def wait_for(fut: Union[T[_T], U[_T]]) -> _T: ... -reveal_type(wait_for(V[str]())) # N: Revealed type is "builtins.str*" +reveal_type(wait_for(V[str]())) # N: Revealed type is "builtins.str" [case testAmbiguousUnionContextAndMultipleInheritance2] from typing import TypeVar, Union, Generic @@ -869,7 +869,7 @@ class V(T[_T, _S], U[_T, _S]): pass def wait_for(fut: Union[T[_T, _S], U[_T, _S]]) -> T[_T, _S]: ... reveal_type(wait_for(V[int, str]())) \ - # N: Revealed type is "__main__.T[builtins.int*, builtins.str*]" + # N: Revealed type is "__main__.T[builtins.int, builtins.str]" -- Literal expressions @@ -907,8 +907,8 @@ if int(): [case testSetWithStarExpr] s = {1, 2, *(3, 4)} t = {1, 2, *s} -reveal_type(s) # N: Revealed type is "builtins.set[builtins.int*]" -reveal_type(t) # N: Revealed type is "builtins.set[builtins.int*]" +reveal_type(s) # N: Revealed type is "builtins.set[builtins.int]" +reveal_type(t) # N: Revealed type is "builtins.set[builtins.int]" [builtins fixtures/set.pyi] [case testListLiteralWithFunctionsErasesNames] @@ -1556,7 +1556,7 @@ def f(blocks: object): a = [] if bool(): a = [1] -reveal_type(a) # N: Revealed type is "builtins.list[builtins.int*]" +reveal_type(a) # N: Revealed type is "builtins.list[builtins.int]" def f(): return [1] @@ -1568,7 +1568,7 @@ reveal_type(b) # N: Revealed type is "builtins.list[Any]" d = {} if bool(): d = {1: 'x'} -reveal_type(d) # N: Revealed type is "builtins.dict[builtins.int*, builtins.str*]" +reveal_type(d) # N: Revealed type is "builtins.dict[builtins.int, builtins.str]" dd = {} # E: Need type annotation for "dd" (hint: "dd: Dict[, ] = ...") if bool(): @@ -1586,7 +1586,7 @@ reveal_type(o) # N: Revealed type is "collections.OrderedDict[builtins.int, buil d = {1: 'x'} oo = OrderedDict() oo.update(d) -reveal_type(oo) # N: Revealed type is "collections.OrderedDict[builtins.int*, builtins.str*]" +reveal_type(oo) # N: Revealed type is "collections.OrderedDict[builtins.int, builtins.str]" [builtins fixtures/dict.pyi] [case testEmptyCollectionAssignedToVariableTwiceIncremental] @@ -1618,7 +1618,7 @@ class C: self.a = [] if bool(): self.a = [1] -reveal_type(C().a) # N: Revealed type is "builtins.list[builtins.int*]" +reveal_type(C().a) # N: Revealed type is "builtins.list[builtins.int]" [builtins fixtures/list.pyi] [case testInferAttributeInitializedToEmptyAndAppended] @@ -1773,13 +1773,13 @@ def f() -> None: [case testInferListTypeFromInplaceAdd] a = [] a += [1] -reveal_type(a) # N: Revealed type is "builtins.list[builtins.int*]" +reveal_type(a) # N: Revealed type is "builtins.list[builtins.int]" [builtins fixtures/list.pyi] [case testInferSetTypeFromInplaceOr] a = set() a |= {'x'} -reveal_type(a) # N: Revealed type is "builtins.set[builtins.str*]" +reveal_type(a) # N: Revealed type is "builtins.set[builtins.str]" [builtins fixtures/set.pyi] @@ -2998,15 +2998,15 @@ def q2(x: Union[Z[F], F]) -> F: return x b: B -reveal_type(q1(b)) # N: Revealed type is "__main__.B*" -reveal_type(q2(b)) # N: Revealed type is "__main__.B*" +reveal_type(q1(b)) # N: Revealed type is "__main__.B" +reveal_type(q2(b)) # N: Revealed type is "__main__.B" z: Z[B] -reveal_type(q1(z)) # N: Revealed type is "__main__.B*" -reveal_type(q2(z)) # N: Revealed type is "__main__.B*" +reveal_type(q1(z)) # N: Revealed type is "__main__.B" +reveal_type(q2(z)) # N: Revealed type is "__main__.B" -reveal_type(q1(Z(b))) # N: Revealed type is "__main__.B*" -reveal_type(q2(Z(b))) # N: Revealed type is "__main__.B*" +reveal_type(q1(Z(b))) # N: Revealed type is "__main__.B" +reveal_type(q2(Z(b))) # N: Revealed type is "__main__.B" [builtins fixtures/isinstancelist.pyi] [case testUnionInvariantSubClassAndCovariantBase] @@ -3022,7 +3022,7 @@ X = Union[Cov[T], Inv[T]] def f(x: X[T]) -> T: ... x: Inv[int] -reveal_type(f(x)) # N: Revealed type is "builtins.int*" +reveal_type(f(x)) # N: Revealed type is "builtins.int" [case testOptionalTypeVarAgainstOptional] # flags: --strict-optional @@ -3035,7 +3035,7 @@ def filter(__function: None, __iterable: Iterable[Optional[_T]]) -> List[_T]: .. x: Optional[str] y = filter(None, [x]) -reveal_type(y) # N: Revealed type is "builtins.list[builtins.str*]" +reveal_type(y) # N: Revealed type is "builtins.list[builtins.str]" [builtins fixtures/list.pyi] [case testPartialDefaultDict] @@ -3125,7 +3125,7 @@ from collections import defaultdict x = defaultdict(list) x['a'] = [1, 2, 3] -reveal_type(x) # N: Revealed type is "collections.defaultdict[builtins.str, builtins.list[builtins.int*]]" +reveal_type(x) # N: Revealed type is "collections.defaultdict[builtins.str, builtins.list[builtins.int]]" y = defaultdict(list) # E: Need type annotation for "y" y['a'] = [] @@ -3149,7 +3149,7 @@ def f(x: Callable[[], T]) -> T: return x() reveal_type(f(lambda: None)) # N: Revealed type is "None" -reveal_type(f(lambda: 1)) # N: Revealed type is "builtins.int*" +reveal_type(f(lambda: 1)) # N: Revealed type is "builtins.int" def g() -> None: pass @@ -3165,7 +3165,7 @@ def f(x: Callable[[], T]) -> T: return x() reveal_type(f(lambda: None)) # N: Revealed type is "None" -reveal_type(f(lambda: 1)) # N: Revealed type is "builtins.int*" +reveal_type(f(lambda: 1)) # N: Revealed type is "builtins.int" def g() -> None: pass @@ -3236,9 +3236,9 @@ class C(NamedTuple): t: Optional[C] d: Dict[C, bytes] x = t and d[t] -reveal_type(x) # N: Revealed type is "Union[None, builtins.bytes*]" +reveal_type(x) # N: Revealed type is "Union[None, builtins.bytes]" if x: - reveal_type(x) # N: Revealed type is "builtins.bytes*" + reveal_type(x) # N: Revealed type is "builtins.bytes" [builtins fixtures/dict.pyi] [case testRegression11705_NoStrict] @@ -3251,7 +3251,7 @@ class C(NamedTuple): t: Optional[C] d: Dict[C, bytes] x = t and d[t] -reveal_type(x) # N: Revealed type is "builtins.bytes*" +reveal_type(x) # N: Revealed type is "builtins.bytes" if x: - reveal_type(x) # N: Revealed type is "builtins.bytes*" + reveal_type(x) # N: Revealed type is "builtins.bytes" [builtins fixtures/dict.pyi] diff --git a/test-data/unit/check-isinstance.test b/test-data/unit/check-isinstance.test index 64c1a2aad3cbf..da6606504343f 100644 --- a/test-data/unit/check-isinstance.test +++ b/test-data/unit/check-isinstance.test @@ -1434,9 +1434,9 @@ a = [] # type: List[Union[int, str]] l = [x for x in a if isinstance(x, int)] g = (x for x in a if isinstance(x, int)) d = {0: x for x in a if isinstance(x, int)} -reveal_type(l) # N: Revealed type is "builtins.list[builtins.int*]" -reveal_type(g) # N: Revealed type is "typing.Generator[builtins.int*, None, None]" -reveal_type(d) # N: Revealed type is "builtins.dict[builtins.int*, builtins.int*]" +reveal_type(l) # N: Revealed type is "builtins.list[builtins.int]" +reveal_type(g) # N: Revealed type is "typing.Generator[builtins.int, None, None]" +reveal_type(d) # N: Revealed type is "builtins.dict[builtins.int, builtins.int]" [builtins fixtures/isinstancelist.pyi] [case testIsinstanceInWrongOrderInBooleanOp] @@ -2417,14 +2417,14 @@ else: y: A[Parent] if isinstance(y, B): reveal_type(y) # N: Revealed type is "__main__." - reveal_type(y.f()) # N: Revealed type is "__main__.Parent*" + reveal_type(y.f()) # N: Revealed type is "__main__.Parent" else: reveal_type(y) # N: Revealed type is "__main__.A[__main__.Parent]" z: A[Child] if isinstance(z, B): reveal_type(z) # N: Revealed type is "__main__.1" - reveal_type(z.f()) # N: Revealed type is "__main__.Child*" + reveal_type(z.f()) # N: Revealed type is "__main__.Child" else: reveal_type(z) # N: Revealed type is "__main__.A[__main__.Child]" [builtins fixtures/isinstance.pyi] @@ -2443,21 +2443,21 @@ class C: T1 = TypeVar('T1', A, B) def f1(x: T1) -> T1: if isinstance(x, A): - reveal_type(x) # N: Revealed type is "__main__.A*" \ + reveal_type(x) # N: Revealed type is "__main__.A" \ # N: Revealed type is "__main__." if isinstance(x, B): reveal_type(x) # N: Revealed type is "__main__." \ # N: Revealed type is "__main__." else: - reveal_type(x) # N: Revealed type is "__main__.A*" + reveal_type(x) # N: Revealed type is "__main__.A" else: - reveal_type(x) # N: Revealed type is "__main__.B*" + reveal_type(x) # N: Revealed type is "__main__.B" return x T2 = TypeVar('T2', B, C) def f2(x: T2) -> T2: if isinstance(x, B): - reveal_type(x) # N: Revealed type is "__main__.B*" + reveal_type(x) # N: Revealed type is "__main__.B" # Note: even though --warn-unreachable is set, we don't report # errors for the below: we don't yet have a way of filtering out # reachability errors that occur for only one variation of the @@ -2465,9 +2465,9 @@ def f2(x: T2) -> T2: if isinstance(x, C): reveal_type(x) else: - reveal_type(x) # N: Revealed type is "__main__.B*" + reveal_type(x) # N: Revealed type is "__main__.B" else: - reveal_type(x) # N: Revealed type is "__main__.C*" + reveal_type(x) # N: Revealed type is "__main__.C" return x [builtins fixtures/isinstance.pyi] diff --git a/test-data/unit/check-lists.test b/test-data/unit/check-lists.test index 8cb61b6f7c902..899b7c5b209fc 100644 --- a/test-data/unit/check-lists.test +++ b/test-data/unit/check-lists.test @@ -71,17 +71,17 @@ class C: pass [case testListWithStarExpr] (x, *a) = [1, 2, 3] a = [1, *[2, 3]] -reveal_type(a) # N: Revealed type is "builtins.list[builtins.int*]" +reveal_type(a) # N: Revealed type is "builtins.list[builtins.int]" b = [0, *a] -reveal_type(b) # N: Revealed type is "builtins.list[builtins.int*]" +reveal_type(b) # N: Revealed type is "builtins.list[builtins.int]" c = [*a, 0] -reveal_type(c) # N: Revealed type is "builtins.list[builtins.int*]" +reveal_type(c) # N: Revealed type is "builtins.list[builtins.int]" [builtins fixtures/list.pyi] [case testComprehensionShadowBinder] # flags: --strict-optional def foo(x: object) -> None: if isinstance(x, str): - [reveal_type(x) for x in [1, 2, 3]] # N: Revealed type is "builtins.int*" + [reveal_type(x) for x in [1, 2, 3]] # N: Revealed type is "builtins.int" [builtins fixtures/isinstancelist.pyi] diff --git a/test-data/unit/check-literal.test b/test-data/unit/check-literal.test index 3886d3c39eddc..ab6154428343a 100644 --- a/test-data/unit/check-literal.test +++ b/test-data/unit/check-literal.test @@ -1480,11 +1480,11 @@ g: List[List[List[Literal[1, 2, 3]]]] = [[[1, 2, 3], [3]]] h: List[Literal[1]] = [] reveal_type(a) # N: Revealed type is "builtins.list[Literal[1]]" -reveal_type(b) # N: Revealed type is "builtins.list[builtins.int*]" +reveal_type(b) # N: Revealed type is "builtins.list[builtins.int]" reveal_type(c) # N: Revealed type is "builtins.list[Union[Literal[1], Literal[2], Literal[3]]]" -reveal_type(d) # N: Revealed type is "builtins.list[builtins.int*]" +reveal_type(d) # N: Revealed type is "builtins.list[builtins.int]" reveal_type(e) # N: Revealed type is "builtins.list[Union[Literal[1], Literal['x']]]" -reveal_type(f) # N: Revealed type is "builtins.list[builtins.object*]" +reveal_type(f) # N: Revealed type is "builtins.list[builtins.object]" reveal_type(g) # N: Revealed type is "builtins.list[builtins.list[builtins.list[Union[Literal[1], Literal[2], Literal[3]]]]]" reveal_type(h) # N: Revealed type is "builtins.list[Literal[1]]" @@ -1499,10 +1499,10 @@ arr4 = [lit1, lit2, lit3] arr5 = [object(), lit1] reveal_type(arr1) # N: Revealed type is "builtins.list[Literal[1]]" -reveal_type(arr2) # N: Revealed type is "builtins.list[builtins.int*]" -reveal_type(arr3) # N: Revealed type is "builtins.list[builtins.int*]" -reveal_type(arr4) # N: Revealed type is "builtins.list[builtins.object*]" -reveal_type(arr5) # N: Revealed type is "builtins.list[builtins.object*]" +reveal_type(arr2) # N: Revealed type is "builtins.list[builtins.int]" +reveal_type(arr3) # N: Revealed type is "builtins.list[builtins.int]" +reveal_type(arr4) # N: Revealed type is "builtins.list[builtins.object]" +reveal_type(arr5) # N: Revealed type is "builtins.list[builtins.object]" bad: List[Literal[1, 2]] = [1, 2, 3] # E: List item 2 has incompatible type "Literal[3]"; expected "Literal[1, 2]" @@ -1533,7 +1533,7 @@ a = {"x": 1, "y": 2} b: Dict[str, Literal[1, 2]] = {"x": 1, "y": 2} c: Dict[Literal["x", "y"], int] = {"x": 1, "y": 2} -reveal_type(a) # N: Revealed type is "builtins.dict[builtins.str*, builtins.int*]" +reveal_type(a) # N: Revealed type is "builtins.dict[builtins.str, builtins.int]" [builtins fixtures/dict.pyi] [out] @@ -1674,7 +1674,7 @@ def f1(x: T, y: str) -> Union[T, str]: ... def f1(x, y): pass a: Literal[1] -reveal_type(f1(1, 1)) # N: Revealed type is "builtins.int*" +reveal_type(f1(1, 1)) # N: Revealed type is "builtins.int" reveal_type(f1(a, 1)) # N: Revealed type is "Literal[1]" @overload @@ -1683,7 +1683,7 @@ def f2(x: T, y: Literal[3]) -> T: ... def f2(x: T, y: str) -> Union[T]: ... def f2(x, y): pass -reveal_type(f2(1, 3)) # N: Revealed type is "builtins.int*" +reveal_type(f2(1, 3)) # N: Revealed type is "builtins.int" reveal_type(f2(a, 3)) # N: Revealed type is "Literal[1]" @overload @@ -1692,7 +1692,7 @@ def f3(x: Literal[3]) -> Literal[3]: ... def f3(x: T) -> T: ... def f3(x): pass -reveal_type(f3(1)) # N: Revealed type is "builtins.int*" +reveal_type(f3(1)) # N: Revealed type is "builtins.int" reveal_type(f3(a)) # N: Revealed type is "Literal[1]" @overload @@ -1702,7 +1702,7 @@ def f4(x: T) -> T: ... def f4(x): pass b: Literal['foo'] -reveal_type(f4(1)) # N: Revealed type is "builtins.int*" +reveal_type(f4(1)) # N: Revealed type is "builtins.int" reveal_type(f4(a)) # N: Revealed type is "Literal[1]" reveal_type(f4("foo")) # N: Revealed type is "builtins.str" @@ -1879,7 +1879,7 @@ def expects_literal(x: Literal[3]) -> None: pass def expects_int(x: int) -> None: pass a: Literal[3] -reveal_type(foo(3)) # N: Revealed type is "builtins.int*" +reveal_type(foo(3)) # N: Revealed type is "builtins.int" reveal_type(foo(a)) # N: Revealed type is "Literal[3]" expects_literal(3) @@ -1944,7 +1944,7 @@ def expects_literal(a: Literal[3]) -> None: pass def expects_literal_wrapper(x: Wrapper[Literal[3]]) -> None: pass a: Literal[3] -reveal_type(Wrapper(3)) # N: Revealed type is "__main__.Wrapper[builtins.int*]" +reveal_type(Wrapper(3)) # N: Revealed type is "__main__.Wrapper[builtins.int]" reveal_type(Wrapper[Literal[3]](3)) # N: Revealed type is "__main__.Wrapper[Literal[3]]" reveal_type(Wrapper(a)) # N: Revealed type is "__main__.Wrapper[Literal[3]]" @@ -1996,13 +1996,13 @@ reveal_type(func1(4)) # E: Value of type variable "TLiteral" of "func1" cannot reveal_type(func1(b)) # E: Value of type variable "TLiteral" of "func1" cannot be "Literal[4]" \ # N: Revealed type is "Literal[4]" reveal_type(func1(c)) # E: Value of type variable "TLiteral" of "func1" cannot be "int" \ - # N: Revealed type is "builtins.int*" + # N: Revealed type is "builtins.int" -reveal_type(func2(3)) # N: Revealed type is "builtins.int*" +reveal_type(func2(3)) # N: Revealed type is "builtins.int" reveal_type(func2(a)) # N: Revealed type is "Literal[3]" -reveal_type(func2(4)) # N: Revealed type is "builtins.int*" +reveal_type(func2(4)) # N: Revealed type is "builtins.int" reveal_type(func2(b)) # N: Revealed type is "Literal[4]" -reveal_type(func2(c)) # N: Revealed type is "builtins.int*" +reveal_type(func2(c)) # N: Revealed type is "builtins.int" [builtins fixtures/tuple.pyi] [out] @@ -2042,7 +2042,7 @@ reveal_type(func1(4)) # E: Value of type variable "TLiteral" of "func1" ca reveal_type(func1(i2)) # E: Value of type variable "TLiteral" of "func1" cannot be "Literal[4]" \ # N: Revealed type is "Literal[4]" reveal_type(func1(i)) # E: Value of type variable "TLiteral" of "func1" cannot be "int" \ - # N: Revealed type is "builtins.int*" + # N: Revealed type is "builtins.int" reveal_type(func1("foo")) # N: Revealed type is "Literal['foo']" reveal_type(func1(s1)) # N: Revealed type is "Literal['foo']" reveal_type(func1("bar")) # E: Value of type variable "TLiteral" of "func1" cannot be "Literal['bar']" \ @@ -2050,16 +2050,16 @@ reveal_type(func1("bar")) # E: Value of type variable "TLiteral" of "func1" ca reveal_type(func1(s2)) # E: Value of type variable "TLiteral" of "func1" cannot be "Literal['bar']" \ # N: Revealed type is "Literal['bar']" reveal_type(func1(s)) # E: Value of type variable "TLiteral" of "func1" cannot be "str" \ - # N: Revealed type is "builtins.str*" - -reveal_type(func2(3)) # N: Revealed type is "builtins.int*" -reveal_type(func2(i1)) # N: Revealed type is "builtins.int*" -reveal_type(func2(4)) # N: Revealed type is "builtins.int*" -reveal_type(func2(i2)) # N: Revealed type is "builtins.int*" -reveal_type(func2("foo")) # N: Revealed type is "builtins.str*" -reveal_type(func2(s1)) # N: Revealed type is "builtins.str*" -reveal_type(func2("bar")) # N: Revealed type is "builtins.str*" -reveal_type(func2(s2)) # N: Revealed type is "builtins.str*" + # N: Revealed type is "builtins.str" + +reveal_type(func2(3)) # N: Revealed type is "builtins.int" +reveal_type(func2(i1)) # N: Revealed type is "builtins.int" +reveal_type(func2(4)) # N: Revealed type is "builtins.int" +reveal_type(func2(i2)) # N: Revealed type is "builtins.int" +reveal_type(func2("foo")) # N: Revealed type is "builtins.str" +reveal_type(func2(s1)) # N: Revealed type is "builtins.str" +reveal_type(func2("bar")) # N: Revealed type is "builtins.str" +reveal_type(func2(s2)) # N: Revealed type is "builtins.str" [builtins fixtures/tuple.pyi] [out] @@ -2106,7 +2106,7 @@ arr4 = [a, d] arr5 = [a, e] reveal_type(arr1) # N: Revealed type is "builtins.list[def (Literal[1]) -> builtins.int]" -reveal_type(arr2) # N: Revealed type is "builtins.list[builtins.function*]" +reveal_type(arr2) # N: Revealed type is "builtins.list[builtins.function]" reveal_type(arr3) # N: Revealed type is "builtins.list[def (Literal[1]) -> builtins.object]" reveal_type(arr4) # N: Revealed type is "builtins.list[def (Literal[1]) -> builtins.object]" reveal_type(arr5) # N: Revealed type is "builtins.list[def (Literal[1]) -> builtins.object]" @@ -2143,7 +2143,7 @@ b: Callable[[Literal[2]], str] lit: Literal[1] arr = [a, b] -reveal_type(arr) # N: Revealed type is "builtins.list[builtins.function*]" +reveal_type(arr) # N: Revealed type is "builtins.list[builtins.function]" reveal_type(arr[0](lit)) # E: Cannot call function of unknown type \ # N: Revealed type is "Any" @@ -2342,7 +2342,7 @@ reveal_type(test.get(good_keys, 3)) # N: Revealed type is "Union[_ reveal_type(test.pop(optional_keys)) # N: Revealed type is "Union[__main__.D, __main__.E]" reveal_type(test.pop(optional_keys, 3)) # N: Revealed type is "Union[__main__.D, __main__.E, Literal[3]?]" reveal_type(test.setdefault(good_keys, AAndB())) # N: Revealed type is "Union[__main__.A, __main__.B]" -reveal_type(test.get(bad_keys)) # N: Revealed type is "builtins.object*" +reveal_type(test.get(bad_keys)) # N: Revealed type is "builtins.object" reveal_type(test.get(bad_keys, 3)) # N: Revealed type is "builtins.object" del test[optional_keys] @@ -2440,7 +2440,7 @@ x[bad_keys] # E: TypedDict "D1" has no key "d" \ reveal_type(x[good_keys]) # N: Revealed type is "Union[__main__.B, __main__.C]" reveal_type(x.get(good_keys)) # N: Revealed type is "Union[__main__.B, __main__.C]" reveal_type(x.get(good_keys, 3)) # N: Revealed type is "Union[__main__.B, Literal[3]?, __main__.C]" -reveal_type(x.get(bad_keys)) # N: Revealed type is "builtins.object*" +reveal_type(x.get(bad_keys)) # N: Revealed type is "builtins.object" reveal_type(x.get(bad_keys, 3)) # N: Revealed type is "builtins.object" [builtins fixtures/dict.pyi] @@ -2704,21 +2704,21 @@ direct = [1] def force1(x: List[Literal[1]]) -> None: pass def force2(x: Literal[1]) -> None: pass -reveal_type(implicit) # N: Revealed type is "builtins.list[builtins.int*]" +reveal_type(implicit) # N: Revealed type is "builtins.list[builtins.int]" force1(reveal_type(implicit)) # E: Argument 1 to "force1" has incompatible type "List[int]"; expected "List[Literal[1]]" \ - # N: Revealed type is "builtins.list[builtins.int*]" + # N: Revealed type is "builtins.list[builtins.int]" force2(reveal_type(implicit[0])) # E: Argument 1 to "force2" has incompatible type "int"; expected "Literal[1]" \ - # N: Revealed type is "builtins.int*" + # N: Revealed type is "builtins.int" reveal_type(explicit) # N: Revealed type is "builtins.list[Literal[1]]" force1(reveal_type(explicit)) # N: Revealed type is "builtins.list[Literal[1]]" force2(reveal_type(explicit[0])) # N: Revealed type is "Literal[1]" -reveal_type(direct) # N: Revealed type is "builtins.list[builtins.int*]" +reveal_type(direct) # N: Revealed type is "builtins.list[builtins.int]" force1(reveal_type(direct)) # E: Argument 1 to "force1" has incompatible type "List[int]"; expected "List[Literal[1]]" \ - # N: Revealed type is "builtins.list[builtins.int*]" + # N: Revealed type is "builtins.list[builtins.int]" force2(reveal_type(direct[0])) # E: Argument 1 to "force2" has incompatible type "int"; expected "Literal[1]" \ - # N: Revealed type is "builtins.int*" + # N: Revealed type is "builtins.int" [builtins fixtures/list.pyi] [out] @@ -2821,25 +2821,25 @@ def over_literal(x: WrapperClass[Literal[99]]) -> None: pass var1: Final = 99 w1 = WrapperClass(var1) force(reveal_type(w1.data)) # E: Argument 1 to "force" has incompatible type "int"; expected "Literal[99]" \ - # N: Revealed type is "builtins.int*" + # N: Revealed type is "builtins.int" force(reveal_type(WrapperClass(var1).data)) # E: Argument 1 to "force" has incompatible type "int"; expected "Literal[99]" \ - # N: Revealed type is "builtins.int*" + # N: Revealed type is "builtins.int" force(reveal_type(wrapper_func(var1))) # N: Revealed type is "Literal[99]" -over_int(reveal_type(w1)) # N: Revealed type is "__main__.WrapperClass[builtins.int*]" +over_int(reveal_type(w1)) # N: Revealed type is "__main__.WrapperClass[builtins.int]" over_literal(reveal_type(w1)) # E: Argument 1 to "over_literal" has incompatible type "WrapperClass[int]"; expected "WrapperClass[Literal[99]]" \ - # N: Revealed type is "__main__.WrapperClass[builtins.int*]" + # N: Revealed type is "__main__.WrapperClass[builtins.int]" over_int(reveal_type(WrapperClass(var1))) # N: Revealed type is "__main__.WrapperClass[builtins.int]" over_literal(reveal_type(WrapperClass(var1))) # N: Revealed type is "__main__.WrapperClass[Literal[99]]" w2 = WrapperClass(99) force(reveal_type(w2.data)) # E: Argument 1 to "force" has incompatible type "int"; expected "Literal[99]" \ - # N: Revealed type is "builtins.int*" + # N: Revealed type is "builtins.int" force(reveal_type(WrapperClass(99).data)) # E: Argument 1 to "force" has incompatible type "int"; expected "Literal[99]" \ - # N: Revealed type is "builtins.int*" + # N: Revealed type is "builtins.int" force(reveal_type(wrapper_func(99))) # N: Revealed type is "Literal[99]" -over_int(reveal_type(w2)) # N: Revealed type is "__main__.WrapperClass[builtins.int*]" +over_int(reveal_type(w2)) # N: Revealed type is "__main__.WrapperClass[builtins.int]" over_literal(reveal_type(w2)) # E: Argument 1 to "over_literal" has incompatible type "WrapperClass[int]"; expected "WrapperClass[Literal[99]]" \ - # N: Revealed type is "__main__.WrapperClass[builtins.int*]" + # N: Revealed type is "__main__.WrapperClass[builtins.int]" over_int(reveal_type(WrapperClass(99))) # N: Revealed type is "__main__.WrapperClass[builtins.int]" over_literal(reveal_type(WrapperClass(99))) # N: Revealed type is "__main__.WrapperClass[Literal[99]]" diff --git a/test-data/unit/check-modules.test b/test-data/unit/check-modules.test index 6c32c088255d1..67767a9114e15 100644 --- a/test-data/unit/check-modules.test +++ b/test-data/unit/check-modules.test @@ -1445,7 +1445,7 @@ def deco(f: Callable[[T], int]) -> Callable[[T], int]: a.x return f [out] -tmp/a.py:6: note: Revealed type is "def (builtins.str*) -> builtins.int" +tmp/a.py:6: note: Revealed type is "def (builtins.str) -> builtins.int" [case testDeferredClassContext] class A: @@ -1549,9 +1549,9 @@ second = XT[str]() last = XT[G]() reveal_type(notes) # N: Revealed type is "y.G[y.G[builtins.int]]" -reveal_type(another) # N: Revealed type is "y.G[y.G*[builtins.int]]" -reveal_type(second) # N: Revealed type is "y.G[builtins.str*]" -reveal_type(last) # N: Revealed type is "y.G[y.G*[Any]]" +reveal_type(another) # N: Revealed type is "y.G[y.G[builtins.int]]" +reveal_type(second) # N: Revealed type is "y.G[builtins.str]" +reveal_type(last) # N: Revealed type is "y.G[y.G[Any]]" [file y.py] from typing import Generic, TypeVar @@ -1962,7 +1962,7 @@ x = 42 [case testModuleAliasToQualifiedImport] import package.module alias = package.module -reveal_type(alias.whatever('/')) # N: Revealed type is "builtins.str*" +reveal_type(alias.whatever('/')) # N: Revealed type is "builtins.str" [file package/__init__.py] [file package/module.py] @@ -1975,7 +1975,7 @@ def whatever(x: T) -> T: pass import mod import othermod alias = mod.submod -reveal_type(alias.whatever('/')) # N: Revealed type is "builtins.str*" +reveal_type(alias.whatever('/')) # N: Revealed type is "builtins.str" if int(): alias = othermod # E: Cannot assign multiple modules to name "alias" without explicit "types.ModuleType" annotation [file mod.py] diff --git a/test-data/unit/check-newsemanal.test b/test-data/unit/check-newsemanal.test index 3b4b0303691a8..8a163e40b438a 100644 --- a/test-data/unit/check-newsemanal.test +++ b/test-data/unit/check-newsemanal.test @@ -543,7 +543,7 @@ c: C[int] c2: C[int, str] # E: "C" expects 1 type argument, but 2 given c3: C c = C('') # E: Argument 1 to "C" has incompatible type "str"; expected "int" -reveal_type(c.get()) # N: Revealed type is "builtins.int*" +reveal_type(c.get()) # N: Revealed type is "builtins.int" reveal_type(c2) # N: Revealed type is "__main__.C[Any]" reveal_type(c3) # N: Revealed type is "__main__.C[Any]" @@ -571,7 +571,7 @@ T = TypeVar('T') c: C[int] reveal_type(c) # N: Revealed type is "__main__.C[builtins.int]" c = C('') # E: Argument 1 to "C" has incompatible type "str"; expected "int" -reveal_type(c.get()) # N: Revealed type is "builtins.int*" +reveal_type(c.get()) # N: Revealed type is "builtins.int" [case testNewAnalyzerTypeAlias] from typing import Union, TypeVar, Generic @@ -820,7 +820,7 @@ class E: pass def f(x: T) -> T: return x -reveal_type(f(D())) # N: Revealed type is "__main__.D*" +reveal_type(f(D())) # N: Revealed type is "__main__.D" f(E()) # E: Value of type variable "T" of "f" cannot be "E" [case testNewAnalyzerNameExprRefersToIncompleteType] @@ -1393,7 +1393,7 @@ from a import x class B(List[B]): pass -reveal_type(x[0][0]) # N: Revealed type is "b.B*" +reveal_type(x[0][0]) # N: Revealed type is "b.B" [builtins fixtures/list.pyi] [case testNewAnalyzerAliasToNotReadyClass2] @@ -1404,7 +1404,7 @@ x: A class A(List[B]): pass B = A -reveal_type(x[0][0]) # N: Revealed type is "__main__.A*" +reveal_type(x[0][0]) # N: Revealed type is "__main__.A" [builtins fixtures/list.pyi] [case testNewAnalyzerAliasToNotReadyClass3] @@ -1415,7 +1415,7 @@ B = A A = C class C(List[B]): pass -reveal_type(x[0][0]) # N: Revealed type is "__main__.C*" +reveal_type(x[0][0]) # N: Revealed type is "__main__.C" [builtins fixtures/list.pyi] [case testNewAnalyzerAliasToNotReadyNestedClass] @@ -1432,7 +1432,7 @@ from a import x class Out: class B(List[B]): pass -reveal_type(x[0][0]) # N: Revealed type is "b.Out.B*" +reveal_type(x[0][0]) # N: Revealed type is "b.Out.B" [builtins fixtures/list.pyi] [case testNewAnalyzerAliasToNotReadyNestedClass2] @@ -1444,7 +1444,7 @@ class Out: class A(List[B]): pass B = Out.A -reveal_type(x[0][0]) # N: Revealed type is "__main__.Out.A*" +reveal_type(x[0][0]) # N: Revealed type is "__main__.Out.A" [builtins fixtures/list.pyi] [case testNewAnalyzerAliasToNotReadyClassGeneric] @@ -1522,7 +1522,7 @@ A = C class C(List[A]): pass reveal_type(x) # N: Revealed type is "builtins.list[__main__.C]" -reveal_type(x[0][0]) # N: Revealed type is "__main__.C*" +reveal_type(x[0][0]) # N: Revealed type is "__main__.C" [builtins fixtures/list.pyi] [case testNewAnalyzerAliasToNotReadyDirectBase] @@ -1966,18 +1966,18 @@ class NTStr(NamedTuple): y: str t1: T -reveal_type(t1.__iter__) # N: Revealed type is "def () -> typing.Iterator[__main__.A*]" +reveal_type(t1.__iter__) # N: Revealed type is "def () -> typing.Iterator[__main__.A]" t2: NTInt -reveal_type(t2.__iter__) # N: Revealed type is "def () -> typing.Iterator[builtins.int*]" +reveal_type(t2.__iter__) # N: Revealed type is "def () -> typing.Iterator[builtins.int]" nt: Union[NTInt, NTStr] -reveal_type(nt.__iter__) # N: Revealed type is "Union[def () -> typing.Iterator[builtins.int*], def () -> typing.Iterator[builtins.str*]]" +reveal_type(nt.__iter__) # N: Revealed type is "Union[def () -> typing.Iterator[builtins.int], def () -> typing.Iterator[builtins.str]]" for nx in nt: - reveal_type(nx) # N: Revealed type is "Union[builtins.int*, builtins.str*]" + reveal_type(nx) # N: Revealed type is "Union[builtins.int, builtins.str]" t: Union[Tuple[int, int], Tuple[str, str]] for x in t: - reveal_type(x) # N: Revealed type is "Union[builtins.int*, builtins.str*]" + reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]" [builtins fixtures/for.pyi] [out] @@ -2003,7 +2003,7 @@ class G(Generic[T]): pass t: Tuple[G[B], G[C]] # E: Type argument "B" of "G" must be a subtype of "A" \ # E: Type argument "C" of "G" must be a subtype of "A" -reveal_type(t.__iter__) # N: Revealed type is "def () -> typing.Iterator[builtins.object*]" +reveal_type(t.__iter__) # N: Revealed type is "def () -> typing.Iterator[builtins.object]" [builtins fixtures/tuple.pyi] [case testNewAnalyzerClassKeywordsForward] @@ -2102,7 +2102,7 @@ A = NewType('A', str) # E: Cannot redefine "A" as a NewType \ from typing import NewType, List x: C -reveal_type(x[0]) # N: Revealed type is "__main__.C*" +reveal_type(x[0]) # N: Revealed type is "__main__.C" C = NewType('C', B) @@ -2114,7 +2114,7 @@ class B(List[C]): from typing import NewType, List x: D -reveal_type(x[0]) # N: Revealed type is "__main__.C*" +reveal_type(x[0]) # N: Revealed type is "__main__.C" D = C C = NewType('C', B) @@ -2127,7 +2127,7 @@ class B(List[D]): from typing import NewType, List x: D -reveal_type(x[0][0]) # N: Revealed type is "__main__.C*" +reveal_type(x[0][0]) # N: Revealed type is "__main__.C" D = C C = NewType('C', List[B]) @@ -2203,7 +2203,7 @@ class C: ... x: B[int] # E: Type argument "int" of "B" must be a subtype of "B[Any]" y: B[B[Any]] -reveal_type(y.x) # N: Revealed type is "__main__.B*[Any]" +reveal_type(y.x) # N: Revealed type is "__main__.B[Any]" [case testNewAnalyzerDuplicateTypeVarImportCycle] import a @@ -2227,7 +2227,7 @@ y: B[B[Any]] reveal_type(y.x) [out] tmp/b.py:8: error: Type argument "int" of "B" must be a subtype of "B[Any]" -tmp/b.py:10: note: Revealed type is "b.B*[Any]" +tmp/b.py:10: note: Revealed type is "b.B[Any]" tmp/a.py:5: error: Cannot redefine "T" as a type variable tmp/a.py:5: error: Invalid assignment target tmp/a.py:5: error: "int" not callable @@ -2256,7 +2256,7 @@ y: B[B[Any]] reveal_type(y.x) [out] tmp/b.py:9: error: Type argument "int" of "B" must be a subtype of "B[Any]" -tmp/b.py:11: note: Revealed type is "b.B*[Any]" +tmp/b.py:11: note: Revealed type is "b.B[Any]" tmp/a.py:5: error: Cannot redefine "T" as a type variable tmp/a.py:5: error: Invalid assignment target @@ -2329,7 +2329,7 @@ C = NamedTuple('C', [('x', int)]) from typing import Generic, TypeVar x = C[int]() -reveal_type(x) # N: Revealed type is "__main__.C[builtins.int*]" +reveal_type(x) # N: Revealed type is "__main__.C[builtins.int]" T = TypeVar('T') class C(Generic[T]): ... @@ -2341,7 +2341,7 @@ T = TypeVar('T') class C(Generic[T]): ... x = C['A']() -reveal_type(x) # N: Revealed type is "__main__.C[__main__.A*]" +reveal_type(x) # N: Revealed type is "__main__.C[__main__.A]" class A: ... @@ -2349,7 +2349,7 @@ class A: ... from typing import Generic, TypeVar x = C[A]() -reveal_type(x) # N: Revealed type is "__main__.C[__main__.A*]" +reveal_type(x) # N: Revealed type is "__main__.C[__main__.A]" T = TypeVar('T') class C(Generic[T]): ... @@ -2360,7 +2360,7 @@ class A: ... from typing import Generic, TypeVar x = C[A]() # E: Value of type variable "T" of "C" cannot be "A" -reveal_type(x) # N: Revealed type is "__main__.C[__main__.A*]" +reveal_type(x) # N: Revealed type is "__main__.C[__main__.A]" T = TypeVar('T', bound='D') class C(Generic[T]): ... @@ -3074,7 +3074,7 @@ from typing import Tuple def f() -> None: t: Tuple[str, Tuple[str, str, str]] x, (y, *z) = t - reveal_type(z) # N: Revealed type is "builtins.list[builtins.str*]" + reveal_type(z) # N: Revealed type is "builtins.list[builtins.str]" [builtins fixtures/list.pyi] [case testNewAnalyzerIdentityAssignment1] diff --git a/test-data/unit/check-newsyntax.test b/test-data/unit/check-newsyntax.test index a70164c63f06f..81d5fbe6b1478 100644 --- a/test-data/unit/check-newsyntax.test +++ b/test-data/unit/check-newsyntax.test @@ -41,7 +41,7 @@ def tst_local(dct: Dict[int, T]) -> Dict[T, int]: ret: Dict[T, int] = {} return ret -reveal_type(tst_local({1: 'a'})) # N: Revealed type is "builtins.dict[builtins.str*, builtins.int]" +reveal_type(tst_local({1: 'a'})) # N: Revealed type is "builtins.dict[builtins.str, builtins.int]" [builtins fixtures/dict.pyi] [out] diff --git a/test-data/unit/check-newtype.test b/test-data/unit/check-newtype.test index a6580e1e52c68..426a3c04869bd 100644 --- a/test-data/unit/check-newtype.test +++ b/test-data/unit/check-newtype.test @@ -68,7 +68,7 @@ bar = IdList([UserId(2)]) baz = foo + bar reveal_type(foo) # N: Revealed type is "__main__.IdList" reveal_type(bar) # N: Revealed type is "__main__.IdList" -reveal_type(baz) # N: Revealed type is "builtins.list[__main__.UserId*]" +reveal_type(baz) # N: Revealed type is "builtins.list[__main__.UserId]" [builtins fixtures/list.pyi] [out] @@ -96,7 +96,7 @@ Derived2(Base('a')) Derived3(Base(1)) Derived3(Base('a')) -reveal_type(Derived1(Base('a')).getter()) # N: Revealed type is "builtins.str*" +reveal_type(Derived1(Base('a')).getter()) # N: Revealed type is "builtins.str" reveal_type(Derived3(Base('a')).getter()) # N: Revealed type is "Any" [out] diff --git a/test-data/unit/check-optional.test b/test-data/unit/check-optional.test index c6d3d1f486499..a0383a35c623a 100644 --- a/test-data/unit/check-optional.test +++ b/test-data/unit/check-optional.test @@ -466,7 +466,7 @@ def f() -> Generator[str, None, None]: pass x = f() reveal_type(x) # N: Revealed type is "typing.Generator[builtins.str, None, None]" l = [f()] -reveal_type(l) # N: Revealed type is "builtins.list[typing.Generator*[builtins.str, None, None]]" +reveal_type(l) # N: Revealed type is "builtins.list[typing.Generator[builtins.str, None, None]]" [builtins fixtures/list.pyi] [case testNoneListTernary] @@ -648,14 +648,14 @@ def u(x: T, y: S) -> Union[S, T]: pass a = None # type: Any # Test both orders -reveal_type(u(C(), None)) # N: Revealed type is "Union[None, __main__.C*]" -reveal_type(u(None, C())) # N: Revealed type is "Union[__main__.C*, None]" +reveal_type(u(C(), None)) # N: Revealed type is "Union[None, __main__.C]" +reveal_type(u(None, C())) # N: Revealed type is "Union[__main__.C, None]" reveal_type(u(a, None)) # N: Revealed type is "Union[None, Any]" reveal_type(u(None, a)) # N: Revealed type is "Union[Any, None]" -reveal_type(u(1, None)) # N: Revealed type is "Union[None, builtins.int*]" -reveal_type(u(None, 1)) # N: Revealed type is "Union[builtins.int*, None]" +reveal_type(u(1, None)) # N: Revealed type is "Union[None, builtins.int]" +reveal_type(u(None, 1)) # N: Revealed type is "Union[builtins.int, None]" [case testOptionalAndAnyBaseClass] from typing import Any, Optional diff --git a/test-data/unit/check-overloading.test b/test-data/unit/check-overloading.test index 591741f3e4e8b..0376b62ab2027 100644 --- a/test-data/unit/check-overloading.test +++ b/test-data/unit/check-overloading.test @@ -1870,7 +1870,7 @@ def make(*args): pass c = make(MyInt) -reveal_type(c) # N: Revealed type is "mod.MyInt*" +reveal_type(c) # N: Revealed type is "mod.MyInt" [file mod.pyi] from typing import overload @@ -2571,7 +2571,7 @@ def f1(x: A) -> B: ... def f2(x: B) -> C: ... def f3(x: C) -> D: ... -reveal_type(chain_call(A(), f1, f2)) # N: Revealed type is "__main__.C*" +reveal_type(chain_call(A(), f1, f2)) # N: Revealed type is "__main__.C" reveal_type(chain_call(A(), f1, f2, f3)) # N: Revealed type is "Any" reveal_type(chain_call(A(), f, f, f, f)) # N: Revealed type is "__main__.A" [builtins fixtures/list.pyi] @@ -3326,11 +3326,11 @@ def wrapper() -> None: a1: A = foo(obj1) a2 = foo(obj1) reveal_type(a1) # N: Revealed type is "__main__.A" - reveal_type(a2) # N: Revealed type is "__main__.A*" + reveal_type(a2) # N: Revealed type is "__main__.A" obj2: Union[W1[A], W2[B]] - reveal_type(foo(obj2)) # N: Revealed type is "Union[__main__.A*, __main__.B*]" + reveal_type(foo(obj2)) # N: Revealed type is "Union[__main__.A, __main__.B]" bar(obj2) # E: Cannot infer type argument 1 of "bar" b1_overload: A = foo(obj2) # E: Incompatible types in assignment (expression has type "Union[A, B]", variable has type "A") @@ -3359,7 +3359,7 @@ def wrapper() -> None: obj1: Union[W1[A], W2[A]] a1 = SomeType[A]().foo(obj1) - reveal_type(a1) # N: Revealed type is "__main__.A*" + reveal_type(a1) # N: Revealed type is "__main__.A" # Note: These should be fine, but mypy has an unrelated bug # that makes them error out? @@ -3462,7 +3462,7 @@ def t_is_same_bound(arg1: T1, arg2: S) -> Tuple[T1, S]: x4: Union[List[int], List[Tuple[C, int]]] y4: int - reveal_type(Dummy[C]().foo(x4, y4)) # N: Revealed type is "Union[builtins.int*, __main__.C]" + reveal_type(Dummy[C]().foo(x4, y4)) # N: Revealed type is "Union[builtins.int, __main__.C]" Dummy[A]().foo(x4, y4) # E: Argument 1 to "foo" of "Dummy" has incompatible type "Union[List[int], List[Tuple[C, int]]]"; expected "List[Tuple[A, int]]" return arg1, arg2 @@ -3535,8 +3535,8 @@ def t_is_compatible_bound(arg1: T3, arg2: S) -> Tuple[T3, S]: [out] main:22: note: Revealed type is "Union[S`-2, __main__.B]" main:22: note: Revealed type is "Union[S`-2, __main__.C]" -main:26: note: Revealed type is "__main__.B*" -main:26: note: Revealed type is "__main__.C*" +main:26: note: Revealed type is "__main__.B" +main:26: note: Revealed type is "__main__.C" [case testOverloadInferUnionReturnWithInconsistentTypevarNames] from typing import overload, TypeVar, Union @@ -3635,9 +3635,9 @@ f1: Callable[[int], str] f2: None f3: Optional[Callable[[int], str]] -reveal_type(mymap(f1, seq)) # N: Revealed type is "typing.Iterable[builtins.str*]" -reveal_type(mymap(f2, seq)) # N: Revealed type is "typing.Iterable[builtins.int*]" -reveal_type(mymap(f3, seq)) # N: Revealed type is "typing.Iterable[builtins.str*]" +reveal_type(mymap(f1, seq)) # N: Revealed type is "typing.Iterable[builtins.str]" +reveal_type(mymap(f2, seq)) # N: Revealed type is "typing.Iterable[builtins.int]" +reveal_type(mymap(f3, seq)) # N: Revealed type is "typing.Iterable[builtins.str]" [builtins fixtures/list.pyi] [typing fixtures/typing-medium.pyi] @@ -3660,9 +3660,9 @@ f1: Callable[[int], str] f2: None f3: Optional[Callable[[int], str]] -reveal_type(mymap(f1, seq)) # N: Revealed type is "typing.Iterable[builtins.str*]" -reveal_type(mymap(f2, seq)) # N: Revealed type is "typing.Iterable[builtins.int*]" -reveal_type(mymap(f3, seq)) # N: Revealed type is "Union[typing.Iterable[builtins.str*], typing.Iterable[builtins.int*]]" +reveal_type(mymap(f1, seq)) # N: Revealed type is "typing.Iterable[builtins.str]" +reveal_type(mymap(f2, seq)) # N: Revealed type is "typing.Iterable[builtins.int]" +reveal_type(mymap(f3, seq)) # N: Revealed type is "Union[typing.Iterable[builtins.str], typing.Iterable[builtins.int]]" [builtins fixtures/list.pyi] [typing fixtures/typing-medium.pyi] @@ -3978,11 +3978,11 @@ class MyModel: reveal_type(MyModel().my_number) # N: Revealed type is "builtins.int" MyModel().my_number.foo() # E: "int" has no attribute "foo" -reveal_type(MyModel.my_number) # N: Revealed type is "__main__.NumberAttribute[__main__.MyModel*]" +reveal_type(MyModel.my_number) # N: Revealed type is "__main__.NumberAttribute[__main__.MyModel]" reveal_type(MyModel.my_number.foo()) # N: Revealed type is "builtins.str" -reveal_type(NumberAttribute[MyModel]().__get__(None, MyModel)) # N: Revealed type is "__main__.NumberAttribute[__main__.MyModel*]" -reveal_type(NumberAttribute[str]().__get__(None, str)) # N: Revealed type is "__main__.NumberAttribute[builtins.str*]" +reveal_type(NumberAttribute[MyModel]().__get__(None, MyModel)) # N: Revealed type is "__main__.NumberAttribute[__main__.MyModel]" +reveal_type(NumberAttribute[str]().__get__(None, str)) # N: Revealed type is "__main__.NumberAttribute[builtins.str]" [builtins fixtures/isinstance.pyi] [typing fixtures/typing-medium.pyi] @@ -4025,7 +4025,7 @@ def add_proxy(x, y): # The lambda definition is a syntax error in Python 3 tup = (1, '2') -reveal_type(foo(lambda (x, y): add_proxy(x, y), tup)) # N: Revealed type is "builtins.str*" +reveal_type(foo(lambda (x, y): add_proxy(x, y), tup)) # N: Revealed type is "builtins.str" [builtins fixtures/primitives.pyi] [case testOverloadWithClassMethods] @@ -4536,10 +4536,10 @@ class Child(Parent): def child_only(self) -> int: pass x: Union[int, str] -reveal_type(Parent().foo(3)) # N: Revealed type is "__main__.Parent*" -reveal_type(Child().foo(3)) # N: Revealed type is "__main__.Child*" +reveal_type(Parent().foo(3)) # N: Revealed type is "__main__.Parent" +reveal_type(Child().foo(3)) # N: Revealed type is "__main__.Child" reveal_type(Child().foo("...")) # N: Revealed type is "builtins.str" -reveal_type(Child().foo(x)) # N: Revealed type is "Union[__main__.Child*, builtins.str]" +reveal_type(Child().foo(x)) # N: Revealed type is "Union[__main__.Child, builtins.str]" reveal_type(Child().foo(3).child_only()) # N: Revealed type is "builtins.int" [case testOverloadAndClassTypes] @@ -4567,10 +4567,10 @@ class Child(Parent): def child_only(self) -> int: pass x: Union[int, str] -reveal_type(Parent.foo(3)) # N: Revealed type is "Type[__main__.Parent*]" -reveal_type(Child.foo(3)) # N: Revealed type is "Type[__main__.Child*]" +reveal_type(Parent.foo(3)) # N: Revealed type is "Type[__main__.Parent]" +reveal_type(Child.foo(3)) # N: Revealed type is "Type[__main__.Child]" reveal_type(Child.foo("...")) # N: Revealed type is "builtins.str" -reveal_type(Child.foo(x)) # N: Revealed type is "Union[Type[__main__.Child*], builtins.str]" +reveal_type(Child.foo(x)) # N: Revealed type is "Union[Type[__main__.Child], builtins.str]" reveal_type(Child.foo(3)().child_only()) # N: Revealed type is "builtins.int" [builtins fixtures/classmethod.pyi] @@ -4893,7 +4893,7 @@ def f() -> None: # N: Possible overload variants: \ # N: def g(x: str) -> str \ # N: def [T] g(x: T, y: int) -> T - reveal_type(g(str(), int())) # N: Revealed type is "builtins.str*" + reveal_type(g(str(), int())) # N: Revealed type is "builtins.str" [out] [case testNestedOverloadsTypeVarOverlap] @@ -4922,14 +4922,14 @@ def f() -> None: @overload def g(x: T) -> Dict[int, T]: ... def g(*args, **kwargs) -> Any: - reveal_type(h(C())) # N: Revealed type is "builtins.dict[builtins.str, __main__.C*]" + reveal_type(h(C())) # N: Revealed type is "builtins.dict[builtins.str, __main__.C]" @overload def h() -> None: ... @overload def h(x: T) -> Dict[str, T]: ... def h(*args, **kwargs) -> Any: - reveal_type(g(C())) # N: Revealed type is "builtins.dict[builtins.int, __main__.C*]" + reveal_type(g(C())) # N: Revealed type is "builtins.dict[builtins.int, __main__.C]" [builtins fixtures/dict.pyi] [out] @@ -4938,7 +4938,7 @@ def f() -> None: from lib import attr from typing import Any -reveal_type(attr(1)) # N: Revealed type is "builtins.int*" +reveal_type(attr(1)) # N: Revealed type is "builtins.int" reveal_type(attr("hi")) # N: Revealed type is "builtins.int" x: Any reveal_type(attr(x)) # N: Revealed type is "Any" @@ -4961,7 +4961,7 @@ def attr(default: Any = ...) -> int: ... from lib import attr from typing import Any -reveal_type(attr(1)) # N: Revealed type is "builtins.int*" +reveal_type(attr(1)) # N: Revealed type is "builtins.int" reveal_type(attr("hi")) # N: Revealed type is "builtins.int" x: Any reveal_type(attr(x)) # N: Revealed type is "Any" @@ -5298,7 +5298,7 @@ def compose(f: Callable[[U], V], g: Callable[[W], U]) -> Callable[[W], V]: ID = NewType("ID", fakeint) compose(ID, fakeint)("test") -reveal_type(compose(ID, fakeint)) # N: Revealed type is "def (Union[builtins.str, builtins.bytes]) -> __main__.ID*" +reveal_type(compose(ID, fakeint)) # N: Revealed type is "def (Union[builtins.str, builtins.bytes]) -> __main__.ID" [builtins fixtures/tuple.pyi] diff --git a/test-data/unit/check-parameter-specification.test b/test-data/unit/check-parameter-specification.test index f2281babb193e..7b41db2c94d63 100644 --- a/test-data/unit/check-parameter-specification.test +++ b/test-data/unit/check-parameter-specification.test @@ -50,8 +50,8 @@ def tmpcontextmanagerlike(x: Callable[P, Iterator[T]]) -> Callable[P, List[T]]: def whatever(x: int) -> Iterator[int]: yield x -reveal_type(whatever) # N: Revealed type is "def (x: builtins.int) -> builtins.list[builtins.int*]" -reveal_type(whatever(217)) # N: Revealed type is "builtins.list[builtins.int*]" +reveal_type(whatever) # N: Revealed type is "def (x: builtins.int) -> builtins.list[builtins.int]" +reveal_type(whatever(217)) # N: Revealed type is "builtins.list[builtins.int]" [builtins fixtures/tuple.pyi] [case testInvalidParamSpecType] @@ -217,7 +217,7 @@ def dec(f: Callable[P, T]) -> Callable[P, List[T]]: @dec def g(x: int, y: str = '') -> int: ... -reveal_type(g) # N: Revealed type is "def (x: builtins.int, y: builtins.str =) -> builtins.list[builtins.int*]" +reveal_type(g) # N: Revealed type is "def (x: builtins.int, y: builtins.str =) -> builtins.list[builtins.int]" [builtins fixtures/dict.pyi] [case testParamSpecArgsAndKwargsTypes] @@ -298,19 +298,19 @@ def join(x: T, y: T) -> T: ... class C(Generic[P, P2]): def m(self, f: Callable[P, None], g: Callable[P2, None]) -> None: reveal_type(join(f, f)) # N: Revealed type is "def (*P.args, **P.kwargs)" - reveal_type(join(f, g)) # N: Revealed type is "builtins.function*" + reveal_type(join(f, g)) # N: Revealed type is "builtins.function" def m2(self, *args: P.args, **kwargs: P.kwargs) -> None: reveal_type(join(args, args)) # N: Revealed type is "P.args`1" reveal_type(join(kwargs, kwargs)) # N: Revealed type is "P.kwargs`1" - reveal_type(join(args, kwargs)) # N: Revealed type is "builtins.object*" + reveal_type(join(args, kwargs)) # N: Revealed type is "builtins.object" def f(*args2: P2.args, **kwargs2: P2.kwargs) -> None: - reveal_type(join(args, args2)) # N: Revealed type is "builtins.object*" - reveal_type(join(kwargs, kwargs2)) # N: Revealed type is "builtins.object*" + reveal_type(join(args, args2)) # N: Revealed type is "builtins.object" + reveal_type(join(kwargs, kwargs2)) # N: Revealed type is "builtins.object" def m3(self, c: C[P, P3]) -> None: - reveal_type(join(c, c)) # N: Revealed type is "__main__.C*[P`1, P3`-1]" - reveal_type(join(self, c)) # N: Revealed type is "builtins.object*" + reveal_type(join(c, c)) # N: Revealed type is "__main__.C[P`1, P3`-1]" + reveal_type(join(self, c)) # N: Revealed type is "builtins.object" [builtins fixtures/dict.pyi] [case testParamSpecClassWithAny] diff --git a/test-data/unit/check-protocols.test b/test-data/unit/check-protocols.test index 65fb30a3547f9..b71bd59cd7d57 100644 --- a/test-data/unit/check-protocols.test +++ b/test-data/unit/check-protocols.test @@ -625,10 +625,10 @@ def close_all(args: Sequence[Closeable[T]]) -> T: arg: Closeable[int] -reveal_type(close(F())) # N: Revealed type is "builtins.int*" -reveal_type(close(arg)) # N: Revealed type is "builtins.int*" -reveal_type(close_all([F()])) # N: Revealed type is "builtins.int*" -reveal_type(close_all([arg])) # N: Revealed type is "builtins.int*" +reveal_type(close(F())) # N: Revealed type is "builtins.int" +reveal_type(close(arg)) # N: Revealed type is "builtins.int" +reveal_type(close_all([F()])) # N: Revealed type is "builtins.int" +reveal_type(close_all([arg])) # N: Revealed type is "builtins.int" [builtins fixtures/isinstancelist.pyi] [typing fixtures/typing-medium.pyi] @@ -647,7 +647,7 @@ class C: def fun3(x: P[T, T]) -> T: pass -reveal_type(fun3(C())) # N: Revealed type is "builtins.int*" +reveal_type(fun3(C())) # N: Revealed type is "builtins.int" [case testProtocolGenericInferenceCovariant] from typing import Generic, TypeVar, Protocol @@ -665,7 +665,7 @@ class C: def fun4(x: U, y: P[U, U]) -> U: pass -reveal_type(fun4('a', C())) # N: Revealed type is "builtins.object*" +reveal_type(fun4('a', C())) # N: Revealed type is "builtins.object" [case testUnrealtedGenericProtolsEquivalent] from typing import TypeVar, Protocol @@ -912,7 +912,7 @@ class L: def last(seq: Linked[T]) -> T: pass -reveal_type(last(L())) # N: Revealed type is "builtins.int*" +reveal_type(last(L())) # N: Revealed type is "builtins.int" [builtins fixtures/list.pyi] [case testRecursiveProtocolSubtleMismatch] @@ -1050,7 +1050,7 @@ class C(Generic[T]): x: C[int] def f(arg: P[T]) -> T: pass -reveal_type(f(x)) #E: Revealed type is "builtins.int*" +reveal_type(f(x)) #E: Revealed type is "builtins.int" -- @property, @classmethod and @staticmethod in protocol types -- ----------------------------------------------------------- @@ -1353,9 +1353,9 @@ y: P2 l0 = [x, x] l1 = [y, y] l = [x, y] -reveal_type(l0) # N: Revealed type is "builtins.list[__main__.P*]" -reveal_type(l1) # N: Revealed type is "builtins.list[__main__.P2*]" -reveal_type(l) # N: Revealed type is "builtins.list[__main__.P*]" +reveal_type(l0) # N: Revealed type is "builtins.list[__main__.P]" +reveal_type(l1) # N: Revealed type is "builtins.list[__main__.P2]" +reveal_type(l) # N: Revealed type is "builtins.list[__main__.P]" [builtins fixtures/list.pyi] [case testJoinOfIncompatibleProtocols] @@ -1368,7 +1368,7 @@ class P2(Protocol): x: P y: P2 -reveal_type([x, y]) # N: Revealed type is "builtins.list[builtins.object*]" +reveal_type([x, y]) # N: Revealed type is "builtins.list[builtins.object]" [builtins fixtures/list.pyi] [case testJoinProtocolWithNormal] @@ -1385,7 +1385,7 @@ y: C l = [x, y] -reveal_type(l) # N: Revealed type is "builtins.list[__main__.P*]" +reveal_type(l) # N: Revealed type is "builtins.list[__main__.P]" [builtins fixtures/list.pyi] [case testMeetProtocolWithProtocol] @@ -1400,7 +1400,7 @@ class P2(Protocol): T = TypeVar('T') def f(x: Callable[[T, T], None]) -> T: pass def g(x: P, y: P2) -> None: pass -reveal_type(f(g)) # N: Revealed type is "__main__.P2*" +reveal_type(f(g)) # N: Revealed type is "__main__.P2" [case testMeetOfIncompatibleProtocols] from typing import Protocol, Callable, TypeVar @@ -1426,7 +1426,7 @@ class C: T = TypeVar('T') def f(x: Callable[[T, T], None]) -> T: pass def g(x: P, y: C) -> None: pass -reveal_type(f(g)) # N: Revealed type is "__main__.C*" +reveal_type(f(g)) # N: Revealed type is "__main__.C" [case testInferProtocolFromProtocol] from typing import Protocol, Sequence, TypeVar, Generic @@ -1445,8 +1445,8 @@ class L(Generic[T]): def last(seq: Linked[T]) -> T: pass -reveal_type(last(L[int]())) # N: Revealed type is "__main__.Box*[builtins.int*]" -reveal_type(last(L[str]()).content) # N: Revealed type is "builtins.str*" +reveal_type(last(L[int]())) # N: Revealed type is "__main__.Box[builtins.int]" +reveal_type(last(L[str]()).content) # N: Revealed type is "builtins.str" [case testOverloadOnProtocol] from typing import overload, Protocol, runtime_checkable @@ -1828,9 +1828,9 @@ fun(N2(1)) # E: Argument 1 to "fun" has incompatible type "N2"; expected "P[int, # N: "N2" is missing following "P" protocol member: \ # N: y -reveal_type(fun3(z)) # N: Revealed type is "builtins.object*" +reveal_type(fun3(z)) # N: Revealed type is "builtins.object" -reveal_type(fun3(z3)) # N: Revealed type is "builtins.int*" +reveal_type(fun3(z3)) # N: Revealed type is "builtins.int" [builtins fixtures/list.pyi] [case testBasicCallableStructuralSubtyping] @@ -1849,7 +1849,7 @@ T = TypeVar('T') def apply_gen(f: Callable[[T], T]) -> T: pass -reveal_type(apply_gen(Add5())) # N: Revealed type is "builtins.int*" +reveal_type(apply_gen(Add5())) # N: Revealed type is "builtins.int" def apply_str(f: Callable[[str], int], x: str) -> int: return f(x) apply_str(Add5(), 'a') # E: Argument 1 to "apply_str" has incompatible type "Add5"; expected "Callable[[str], int]" \ @@ -1890,7 +1890,7 @@ def inc(a: int, temp: str) -> int: def foo(f: Callable[[int], T]) -> T: return f(1) -reveal_type(foo(partial(inc, 'temp'))) # N: Revealed type is "builtins.int*" +reveal_type(foo(partial(inc, 'temp'))) # N: Revealed type is "builtins.int" [builtins fixtures/list.pyi] [case testStructuralInferenceForCallable] @@ -1903,7 +1903,7 @@ class Actual: def __call__(self, arg: int) -> str: pass def fun(cb: Callable[[T], S]) -> Tuple[T, S]: pass -reveal_type(fun(Actual())) # N: Revealed type is "Tuple[builtins.int*, builtins.str*]" +reveal_type(fun(Actual())) # N: Revealed type is "Tuple[builtins.int, builtins.str]" [builtins fixtures/tuple.pyi] -- Standard protocol types (SupportsInt, Sized, etc.) @@ -2028,8 +2028,8 @@ class A: class B(A): pass -reveal_type(list(b for b in B())) # N: Revealed type is "builtins.list[__main__.B*]" -reveal_type(list(B())) # N: Revealed type is "builtins.list[__main__.B*]" +reveal_type(list(b for b in B())) # N: Revealed type is "builtins.list[__main__.B]" +reveal_type(list(B())) # N: Revealed type is "builtins.list[__main__.B]" [builtins fixtures/list.pyi] [case testIterableProtocolOnMetaclass] @@ -2045,8 +2045,8 @@ class E(metaclass=EMeta): class C(E): pass -reveal_type(list(c for c in C)) # N: Revealed type is "builtins.list[__main__.C*]" -reveal_type(list(C)) # N: Revealed type is "builtins.list[__main__.C*]" +reveal_type(list(c for c in C)) # N: Revealed type is "builtins.list[__main__.C]" +reveal_type(list(C)) # N: Revealed type is "builtins.list[__main__.C]" [builtins fixtures/list.pyi] [case testClassesGetattrWithProtocols] @@ -2452,7 +2452,7 @@ def call(x: int, y: str) -> Tuple[int, str]: ... def func(caller: Caller[T, S]) -> Tuple[T, S]: pass -reveal_type(func(call)) # N: Revealed type is "Tuple[builtins.int*, builtins.str*]" +reveal_type(func(call)) # N: Revealed type is "Tuple[builtins.int, builtins.str]" [builtins fixtures/tuple.pyi] [out] @@ -2689,10 +2689,10 @@ foo(ONE) foo(TWO) foo(3) -reveal_type(abs(ONE)) # N: Revealed type is "builtins.int*" -reveal_type(abs(TWO)) # N: Revealed type is "builtins.int*" -reveal_type(abs(3)) # N: Revealed type is "builtins.int*" -reveal_type(abs(ALL)) # N: Revealed type is "builtins.int*" +reveal_type(abs(ONE)) # N: Revealed type is "builtins.int" +reveal_type(abs(TWO)) # N: Revealed type is "builtins.int" +reveal_type(abs(3)) # N: Revealed type is "builtins.int" +reveal_type(abs(ALL)) # N: Revealed type is "builtins.int" [builtins fixtures/float.pyi] [typing fixtures/typing-full.pyi] @@ -2744,13 +2744,13 @@ class Blooper: flap = None def bloop(self, x: Flapper) -> None: - reveal_type([self, x]) # N: Revealed type is "builtins.list[builtins.object*]" + reveal_type([self, x]) # N: Revealed type is "builtins.list[builtins.object]" class Gleemer: flap = [] # E: Need type annotation for "flap" (hint: "flap: List[] = ...") def gleem(self, x: Flapper) -> None: - reveal_type([self, x]) # N: Revealed type is "builtins.list[builtins.object*]" + reveal_type([self, x]) # N: Revealed type is "builtins.list[builtins.object]" [builtins fixtures/tuple.pyi] @@ -2768,7 +2768,7 @@ class DataArray(ObjectHashable): __hash__ = None def f(self, x: Hashable) -> None: - reveal_type([self, x]) # N: Revealed type is "builtins.list[builtins.object*]" + reveal_type([self, x]) # N: Revealed type is "builtins.list[builtins.object]" [builtins fixtures/tuple.pyi] diff --git a/test-data/unit/check-python310.test b/test-data/unit/check-python310.test index 6046b7ec7333d..cb39a519a1467 100644 --- a/test-data/unit/check-python310.test +++ b/test-data/unit/check-python310.test @@ -90,7 +90,7 @@ m: List[int] match m: case [a]: - reveal_type(a) # N: Revealed type is "builtins.int*" + reveal_type(a) # N: Revealed type is "builtins.int" [builtins fixtures/list.pyi] [case testMatchSequencePatternCapturesStarred] @@ -99,8 +99,8 @@ m: Sequence[int] match m: case [a, *b]: - reveal_type(a) # N: Revealed type is "builtins.int*" - reveal_type(b) # N: Revealed type is "builtins.list[builtins.int*]" + reveal_type(a) # N: Revealed type is "builtins.int" + reveal_type(b) # N: Revealed type is "builtins.list[builtins.int]" [builtins fixtures/list.pyi] [case testMatchSequencePatternNarrowsInner] @@ -191,27 +191,27 @@ match m1: match m2: case [b]: - reveal_type(b) # N: Revealed type is "builtins.int*" + reveal_type(b) # N: Revealed type is "builtins.int" match m3: case [c]: - reveal_type(c) # N: Revealed type is "builtins.int*" + reveal_type(c) # N: Revealed type is "builtins.int" match m4: case [d]: - reveal_type(d) # N: Revealed type is "builtins.int*" + reveal_type(d) # N: Revealed type is "builtins.int" match m5: case [e]: - reveal_type(e) # N: Revealed type is "builtins.int*" + reveal_type(e) # N: Revealed type is "builtins.int" match m6: case [f]: - reveal_type(f) # N: Revealed type is "builtins.int*" + reveal_type(f) # N: Revealed type is "builtins.int" match m7: case [g]: - reveal_type(g) # N: Revealed type is "builtins.int*" + reveal_type(g) # N: Revealed type is "builtins.int" match m8: case [h]: @@ -335,9 +335,9 @@ m: Dict[str, int] match m: case {"key": v}: - reveal_type(v) # N: Revealed type is "builtins.int*" + reveal_type(v) # N: Revealed type is "builtins.int" case {b.b: v2}: - reveal_type(v2) # N: Revealed type is "builtins.int*" + reveal_type(v2) # N: Revealed type is "builtins.int" [file b.py] b: str [builtins fixtures/dict.pyi] @@ -350,9 +350,9 @@ m: Dict[str, int] match m: case {1: v}: - reveal_type(v) # N: Revealed type is "builtins.int*" + reveal_type(v) # N: Revealed type is "builtins.int" case {b.b: v2}: - reveal_type(v2) # N: Revealed type is "builtins.int*" + reveal_type(v2) # N: Revealed type is "builtins.int" [file b.py] b: int [builtins fixtures/dict.pyi] @@ -375,7 +375,7 @@ match m: reveal_type(v3) # N: Revealed type is "builtins.str" reveal_type(v4) # N: Revealed type is "builtins.int" case {"o": v5}: - reveal_type(v5) # N: Revealed type is "builtins.object*" + reveal_type(v5) # N: Revealed type is "builtins.object" [typing fixtures/typing-typeddict.pyi] [case testMatchMappingPatternCapturesTypedDictWithLiteral] @@ -397,7 +397,7 @@ match m: reveal_type(v3) # N: Revealed type is "builtins.str" reveal_type(v4) # N: Revealed type is "builtins.int" case {b.o: v5}: - reveal_type(v5) # N: Revealed type is "builtins.object*" + reveal_type(v5) # N: Revealed type is "builtins.object" [file b.py] from typing import Final, Literal a: Final = "a" @@ -417,7 +417,7 @@ m: A match m: case {b.a: v}: - reveal_type(v) # N: Revealed type is "builtins.object*" + reveal_type(v) # N: Revealed type is "builtins.object" [file b.py] from typing import Final, Literal a: str @@ -458,7 +458,7 @@ m: Mapping[str, int] match m: case {'k': 1, **r}: - reveal_type(r) # N: Revealed type is "builtins.dict[builtins.str*, builtins.int*]" + reveal_type(r) # N: Revealed type is "builtins.dict[builtins.str, builtins.int]" [builtins fixtures/dict.pyi] -- Mapping patterns currently do not narrow -- @@ -698,7 +698,7 @@ m: A[int] match m: case A(a=i): reveal_type(m) # N: Revealed type is "__main__.A[builtins.int]" - reveal_type(i) # N: Revealed type is "builtins.int*" + reveal_type(i) # N: Revealed type is "builtins.int" [case testMatchClassPatternCaptureFilledGenericTypeAlias] from typing import Generic, TypeVar @@ -888,9 +888,9 @@ match x: case list([({-0-0j: int(real=0+0j, imag=0-0j) | (1) as z},)]): y = 0 -reveal_type(x) # N: Revealed type is "builtins.list[builtins.list*[builtins.dict*[builtins.int*, builtins.int*]]]" +reveal_type(x) # N: Revealed type is "builtins.list[builtins.list[builtins.dict[builtins.int, builtins.int]]]" reveal_type(y) # N: Revealed type is "builtins.int" -reveal_type(z) # N: Revealed type is "builtins.int*" +reveal_type(z) # N: Revealed type is "builtins.int" [builtins fixtures/dict.pyi] [case testMatchNonFinalMatchArgs] @@ -1023,7 +1023,7 @@ m: List[int] match m: case [x, y] | list(x): # E: Alternative patterns bind different names reveal_type(x) # N: Revealed type is "builtins.object" - reveal_type(y) # N: Revealed type is "builtins.int*" + reveal_type(y) # N: Revealed type is "builtins.int" [builtins fixtures/list.pyi] [case testMatchOrPatternCapturesJoin] @@ -1495,7 +1495,7 @@ from typing import List def f(x: List[int] | int) -> None: match x: case [*y]: - reveal_type(y) # N: Revealed type is "builtins.list[builtins.int*]" + reveal_type(y) # N: Revealed type is "builtins.list[builtins.int]" return reveal_type(x) # N: Revealed type is "builtins.int" [builtins fixtures/list.pyi] diff --git a/test-data/unit/check-python38.test b/test-data/unit/check-python38.test index ce1f9841e2409..6e21104c3d166 100644 --- a/test-data/unit/check-python38.test +++ b/test-data/unit/check-python38.test @@ -222,23 +222,23 @@ while b := "x": l = [y2 := 1, y2 + 2, y2 + 3] reveal_type(y2) # N: Revealed type is "builtins.int" -reveal_type(l) # N: Revealed type is "builtins.list[builtins.int*]" +reveal_type(l) # N: Revealed type is "builtins.list[builtins.int]" filtered_data = [y3 for x in l if (y3 := a) is not None] -reveal_type(filtered_data) # N: Revealed type is "builtins.list[builtins.int*]" +reveal_type(filtered_data) # N: Revealed type is "builtins.list[builtins.int]" reveal_type(y3) # N: Revealed type is "builtins.int" d = {'a': (a2 := 1), 'b': a2 + 1, 'c': a2 + 2} -reveal_type(d) # N: Revealed type is "builtins.dict[builtins.str*, builtins.int*]" +reveal_type(d) # N: Revealed type is "builtins.dict[builtins.str, builtins.int]" reveal_type(a2) # N: Revealed type is "builtins.int" d2 = {(prefix := 'key_') + 'a': (start_val := 1), prefix + 'b': start_val + 1, prefix + 'c': start_val + 2} -reveal_type(d2) # N: Revealed type is "builtins.dict[builtins.str*, builtins.int*]" +reveal_type(d2) # N: Revealed type is "builtins.dict[builtins.str, builtins.int]" reveal_type(prefix) # N: Revealed type is "builtins.str" reveal_type(start_val) # N: Revealed type is "builtins.int" filtered_dict = {k: new_v for k, v in [('a', 1), ('b', 2), ('c', 3)] if (new_v := v + 1) == 2} -reveal_type(filtered_dict) # N: Revealed type is "builtins.dict[builtins.str*, builtins.int*]" +reveal_type(filtered_dict) # N: Revealed type is "builtins.dict[builtins.str, builtins.int]" reveal_type(new_v) # N: Revealed type is "builtins.int" def f(x: int = (c := 4)) -> int: @@ -255,23 +255,23 @@ def f(x: int = (c := 4)) -> int: l = [y2 := 1, y2 + 2, y2 + 3] reveal_type(y2) # N: Revealed type is "builtins.int" - reveal_type(l) # N: Revealed type is "builtins.list[builtins.int*]" + reveal_type(l) # N: Revealed type is "builtins.list[builtins.int]" filtered_data = [y3 for x in l if (y3 := a) is not None] - reveal_type(filtered_data) # N: Revealed type is "builtins.list[builtins.int*]" + reveal_type(filtered_data) # N: Revealed type is "builtins.list[builtins.int]" reveal_type(y3) # N: Revealed type is "builtins.int" d = {'a': (a2 := 1), 'b': a2 + 1, 'c': a2 + 2} - reveal_type(d) # N: Revealed type is "builtins.dict[builtins.str*, builtins.int*]" + reveal_type(d) # N: Revealed type is "builtins.dict[builtins.str, builtins.int]" reveal_type(a2) # N: Revealed type is "builtins.int" d2 = {(prefix := 'key_') + 'a': (start_val := 1), prefix + 'b': start_val + 1, prefix + 'c': start_val + 2} - reveal_type(d2) # N: Revealed type is "builtins.dict[builtins.str*, builtins.int*]" + reveal_type(d2) # N: Revealed type is "builtins.dict[builtins.str, builtins.int]" reveal_type(prefix) # N: Revealed type is "builtins.str" reveal_type(start_val) # N: Revealed type is "builtins.int" filtered_dict = {k: new_v for k, v in [('a', 1), ('b', 2), ('c', 3)] if (new_v := v + 1) == 2} - reveal_type(filtered_dict) # N: Revealed type is "builtins.dict[builtins.str*, builtins.int*]" + reveal_type(filtered_dict) # N: Revealed type is "builtins.dict[builtins.str, builtins.int]" reveal_type(new_v) # N: Revealed type is "builtins.int" # https://www.python.org/dev/peps/pep-0572/#exceptional-cases @@ -372,10 +372,10 @@ class AssignmentExpressionsClass: l = [z2 := 1, z2 + 2, z2 + 3] reveal_type(z2) # N: Revealed type is "builtins.int" - reveal_type(l) # N: Revealed type is "builtins.list[builtins.int*]" + reveal_type(l) # N: Revealed type is "builtins.list[builtins.int]" filtered_data = [z3 for x in l if (z3 := 1) is not None] - reveal_type(filtered_data) # N: Revealed type is "builtins.list[builtins.int*]" + reveal_type(filtered_data) # N: Revealed type is "builtins.list[builtins.int]" reveal_type(z3) # N: Revealed type is "builtins.int" # Assignment expressions from inside the class should not escape the class scope. diff --git a/test-data/unit/check-redefine.test b/test-data/unit/check-redefine.test index 85208df0932aa..e73f715c9ec0f 100644 --- a/test-data/unit/check-redefine.test +++ b/test-data/unit/check-redefine.test @@ -57,10 +57,10 @@ T = TypeVar('T') def f(x: int) -> None: x = g(x) - reveal_type(x) # N: Revealed type is "Union[builtins.int*, builtins.str]" + reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]" y = 1 y = g(y) - reveal_type(y) # N: Revealed type is "Union[builtins.int*, builtins.str]" + reveal_type(y) # N: Revealed type is "Union[builtins.int, builtins.str]" def g(x: T) -> Union[T, str]: pass @@ -71,11 +71,11 @@ def f(a: Iterable[int], b: Iterable[str]) -> None: for x in a: x = '' \ # E: Incompatible types in assignment (expression has type "str", variable has type "int") - reveal_type(x) # N: Revealed type is "builtins.int*" + reveal_type(x) # N: Revealed type is "builtins.int" for x in b: x = 1 \ # E: Incompatible types in assignment (expression has type "int", variable has type "str") - reveal_type(x) # N: Revealed type is "builtins.str*" + reveal_type(x) # N: Revealed type is "builtins.str" def g(a: Iterable[int]) -> None: for x in a: pass @@ -376,10 +376,10 @@ for x in it2: reveal_type(x) reveal_type(x) [out] -tmp/m.py:6: note: Revealed type is "builtins.int*" -tmp/m.py:8: note: Revealed type is "builtins.str*" -tmp/m.py:9: note: Revealed type is "builtins.str*" -main:3: note: Revealed type is "builtins.str*" +tmp/m.py:6: note: Revealed type is "builtins.int" +tmp/m.py:8: note: Revealed type is "builtins.str" +tmp/m.py:9: note: Revealed type is "builtins.str" +main:3: note: Revealed type is "builtins.str" [case testRedefineGlobalBasedOnPreviousValues] # flags: --allow-redefinition @@ -388,7 +388,7 @@ T = TypeVar('T') def f(x: T) -> Iterable[T]: pass a = 0 a = f(a) -reveal_type(a) # N: Revealed type is "typing.Iterable[builtins.int*]" +reveal_type(a) # N: Revealed type is "typing.Iterable[builtins.int]" [case testRedefineGlobalWithSeparateDeclaration] # flags: --allow-redefinition @@ -412,7 +412,7 @@ x = 0 reveal_type(x) # N: Revealed type is "builtins.int" for x in f(x): pass -reveal_type(x) # N: Revealed type is "Union[builtins.int*, builtins.str]" +reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]" [case testNoRedefinitionIfOnlyInitialized] # flags: --allow-redefinition --no-strict-optional diff --git a/test-data/unit/check-selftype.test b/test-data/unit/check-selftype.test index 3948d215b192f..b59c22dfae062 100644 --- a/test-data/unit/check-selftype.test +++ b/test-data/unit/check-selftype.test @@ -9,10 +9,10 @@ class A: class B(A): pass -reveal_type(A().copy) # N: Revealed type is "def () -> __main__.A*" -reveal_type(B().copy) # N: Revealed type is "def () -> __main__.B*" -reveal_type(A().copy()) # N: Revealed type is "__main__.A*" -reveal_type(B().copy()) # N: Revealed type is "__main__.B*" +reveal_type(A().copy) # N: Revealed type is "def () -> __main__.A" +reveal_type(B().copy) # N: Revealed type is "def () -> __main__.B" +reveal_type(A().copy()) # N: Revealed type is "__main__.A" +reveal_type(B().copy()) # N: Revealed type is "__main__.B" [builtins fixtures/bool.pyi] @@ -99,10 +99,10 @@ class C: return cls() # E: Missing positional argument "a" in call to "C" -reveal_type(A.new) # N: Revealed type is "def () -> __main__.A*" -reveal_type(B.new) # N: Revealed type is "def () -> __main__.B*" -reveal_type(A.new()) # N: Revealed type is "__main__.A*" -reveal_type(B.new()) # N: Revealed type is "__main__.B*" +reveal_type(A.new) # N: Revealed type is "def () -> __main__.A" +reveal_type(B.new) # N: Revealed type is "def () -> __main__.B" +reveal_type(A.new()) # N: Revealed type is "__main__.A" +reveal_type(B.new()) # N: Revealed type is "__main__.B" [builtins fixtures/classmethod.pyi] @@ -121,10 +121,10 @@ Q = TypeVar('Q', bound='C', covariant=True) class C(A): def copy(self: Q) -> Q: pass -reveal_type(C().copy) # N: Revealed type is "def () -> __main__.C*" -reveal_type(C().copy()) # N: Revealed type is "__main__.C*" -reveal_type(cast(A, C()).copy) # N: Revealed type is "def () -> __main__.A*" -reveal_type(cast(A, C()).copy()) # N: Revealed type is "__main__.A*" +reveal_type(C().copy) # N: Revealed type is "def () -> __main__.C" +reveal_type(C().copy()) # N: Revealed type is "__main__.C" +reveal_type(cast(A, C()).copy) # N: Revealed type is "def () -> __main__.A" +reveal_type(cast(A, C()).copy()) # N: Revealed type is "__main__.A" [builtins fixtures/bool.pyi] @@ -164,10 +164,10 @@ class A: class B(A): pass -reveal_type(A().copy) # N: Revealed type is "def (factory: def (__main__.A*) -> __main__.A*) -> __main__.A*" -reveal_type(B().copy) # N: Revealed type is "def (factory: def (__main__.B*) -> __main__.B*) -> __main__.B*" -reveal_type(A.new) # N: Revealed type is "def (factory: def (__main__.A*) -> __main__.A*) -> __main__.A*" -reveal_type(B.new) # N: Revealed type is "def (factory: def (__main__.B*) -> __main__.B*) -> __main__.B*" +reveal_type(A().copy) # N: Revealed type is "def (factory: def (__main__.A) -> __main__.A) -> __main__.A" +reveal_type(B().copy) # N: Revealed type is "def (factory: def (__main__.B) -> __main__.B) -> __main__.B" +reveal_type(A.new) # N: Revealed type is "def (factory: def (__main__.A) -> __main__.A) -> __main__.A" +reveal_type(B.new) # N: Revealed type is "def (factory: def (__main__.B) -> __main__.B) -> __main__.B" [builtins fixtures/classmethod.pyi] @@ -220,10 +220,10 @@ class C: class D(C): pass -reveal_type(D.new) # N: Revealed type is "def () -> __main__.D*" -reveal_type(D().new) # N: Revealed type is "def () -> __main__.D*" -reveal_type(D.new()) # N: Revealed type is "__main__.D*" -reveal_type(D().new()) # N: Revealed type is "__main__.D*" +reveal_type(D.new) # N: Revealed type is "def () -> __main__.D" +reveal_type(D().new) # N: Revealed type is "def () -> __main__.D" +reveal_type(D.new()) # N: Revealed type is "__main__.D" +reveal_type(D().new()) # N: Revealed type is "__main__.D" Q = TypeVar('Q', bound=C) @@ -381,13 +381,13 @@ class B(A): pass reveal_type(A().g) # N: Revealed type is "builtins.int" -reveal_type(A().gt) # N: Revealed type is "__main__.A*" +reveal_type(A().gt) # N: Revealed type is "__main__.A" reveal_type(A().f()) # N: Revealed type is "builtins.int" -reveal_type(A().ft()) # N: Revealed type is "__main__.A*" +reveal_type(A().ft()) # N: Revealed type is "__main__.A" reveal_type(B().g) # N: Revealed type is "builtins.int" -reveal_type(B().gt) # N: Revealed type is "__main__.B*" +reveal_type(B().gt) # N: Revealed type is "__main__.B" reveal_type(B().f()) # N: Revealed type is "builtins.int" -reveal_type(B().ft()) # N: Revealed type is "__main__.B*" +reveal_type(B().ft()) # N: Revealed type is "__main__.B" [builtins fixtures/property.pyi] @@ -556,8 +556,8 @@ reveal_type(P(use_str=True)) # N: Revealed type is "lib.P[builtins.str]" reveal_type(P(use_str=False)) # N: Revealed type is "lib.P[builtins.int]" reveal_type(C) # N: Revealed type is "Overload(def [T] (item: T`1, use_tuple: Literal[False]) -> lib.C[T`1], def [T] (item: T`1, use_tuple: Literal[True]) -> lib.C[builtins.tuple[T`1, ...]])" -reveal_type(C(0, use_tuple=False)) # N: Revealed type is "lib.C[builtins.int*]" -reveal_type(C(0, use_tuple=True)) # N: Revealed type is "lib.C[builtins.tuple[builtins.int*, ...]]" +reveal_type(C(0, use_tuple=False)) # N: Revealed type is "lib.C[builtins.int]" +reveal_type(C(0, use_tuple=True)) # N: Revealed type is "lib.C[builtins.tuple[builtins.int, ...]]" T = TypeVar('T') class SubP(P[T]): @@ -674,7 +674,7 @@ b: Bad f.atomic_close() # OK b.atomic_close() # E: Invalid self argument "Bad" to attribute function "atomic_close" with type "Callable[[Resource], int]" -reveal_type(f.copy()) # N: Revealed type is "__main__.File*" +reveal_type(f.copy()) # N: Revealed type is "__main__.File" b.copy() # E: Invalid self argument "Bad" to attribute function "copy" with type "Callable[[T], T]" [builtins fixtures/tuple.pyi] @@ -873,7 +873,7 @@ class Super(Generic[Q]): class Sub(Super[int]): ... def test(x: List[Sub]) -> None: - reveal_type(Sub.meth(x)) # N: Revealed type is "builtins.list[__main__.Sub*]" + reveal_type(Sub.meth(x)) # N: Revealed type is "builtins.list[__main__.Sub]" [builtins fixtures/isinstancelist.pyi] [case testSelfTypeNoTypeVarsRestrict] @@ -885,7 +885,7 @@ S = TypeVar('S') class C(Generic[T]): def limited(self: C[str], arg: S) -> S: ... -reveal_type(C[str]().limited(0)) # N: Revealed type is "builtins.int*" +reveal_type(C[str]().limited(0)) # N: Revealed type is "builtins.int" [case testSelfTypeMultipleTypeVars] from typing import Generic, TypeVar, Tuple @@ -912,7 +912,7 @@ class C: def same(self: T) -> T: ... x: Union[A, C] -reveal_type(x.same) # N: Revealed type is "Union[builtins.int, def () -> __main__.C*]" +reveal_type(x.same) # N: Revealed type is "Union[builtins.int, def () -> __main__.C]" [case testSelfTypeOnUnionClassMethod] from typing import TypeVar, Union, Type @@ -927,7 +927,7 @@ class C: def same(cls: Type[T]) -> T: ... x: Union[A, C] -reveal_type(x.same) # N: Revealed type is "Union[builtins.int, def () -> __main__.C*]" +reveal_type(x.same) # N: Revealed type is "Union[builtins.int, def () -> __main__.C]" [builtins fixtures/classmethod.pyi] [case SelfTypeOverloadedClassMethod] @@ -948,8 +948,8 @@ class Sub(Base): class Other(Base): ... class Double(Sub): ... -reveal_type(Other.make()) # N: Revealed type is "__main__.Other*" -reveal_type(Other.make(3)) # N: Revealed type is "builtins.tuple[__main__.Other*, ...]" +reveal_type(Other.make()) # N: Revealed type is "__main__.Other" +reveal_type(Other.make(3)) # N: Revealed type is "builtins.tuple[__main__.Other, ...]" reveal_type(Double.make()) # N: Revealed type is "__main__.Sub" reveal_type(Double.make(3)) # N: Revealed type is "builtins.tuple[__main__.Sub, ...]" [file lib.pyi] @@ -978,9 +978,9 @@ class B(A): ... class C(A): ... t: Type[Union[B, C]] -reveal_type(t.meth) # N: Revealed type is "Union[def () -> __main__.B*, def () -> __main__.C*]" +reveal_type(t.meth) # N: Revealed type is "Union[def () -> __main__.B, def () -> __main__.C]" x = t.meth() -reveal_type(x) # N: Revealed type is "Union[__main__.B*, __main__.C*]" +reveal_type(x) # N: Revealed type is "Union[__main__.B, __main__.C]" [builtins fixtures/classmethod.pyi] [case testSelfTypeClassMethodOnUnionGeneric] @@ -1011,7 +1011,7 @@ class C(A): ... t: Type[Union[B, C]] x = t.meth()[0] -reveal_type(x) # N: Revealed type is "Union[__main__.B*, __main__.C*]" +reveal_type(x) # N: Revealed type is "Union[__main__.B, __main__.C]" [builtins fixtures/isinstancelist.pyi] [case testSelfTypeClassMethodOverloadedOnInstance] @@ -1035,14 +1035,14 @@ class AClass: ... def foo(x: Type[AClass]) -> None: - reveal_type(x.delete) # N: Revealed type is "Overload(def (id: builtins.int, id2: builtins.int) -> builtins.int, def (id: __main__.AClass*, id2: None =) -> builtins.int)" + reveal_type(x.delete) # N: Revealed type is "Overload(def (id: builtins.int, id2: builtins.int) -> builtins.int, def (id: __main__.AClass, id2: None =) -> builtins.int)" y = x() - reveal_type(y.delete) # N: Revealed type is "Overload(def (id: builtins.int, id2: builtins.int) -> builtins.int, def (id: __main__.AClass*, id2: None =) -> builtins.int)" + reveal_type(y.delete) # N: Revealed type is "Overload(def (id: builtins.int, id2: builtins.int) -> builtins.int, def (id: __main__.AClass, id2: None =) -> builtins.int)" y.delete(10, 20) y.delete(y) def bar(x: AClass) -> None: - reveal_type(x.delete) # N: Revealed type is "Overload(def (id: builtins.int, id2: builtins.int) -> builtins.int, def (id: __main__.AClass*, id2: None =) -> builtins.int)" + reveal_type(x.delete) # N: Revealed type is "Overload(def (id: builtins.int, id2: builtins.int) -> builtins.int, def (id: __main__.AClass, id2: None =) -> builtins.int)" x.delete(10, 20) [builtins fixtures/classmethod.pyi] @@ -1062,7 +1062,7 @@ class Base(Generic[T]): ... class Sub(Base[T]): def __init__(self: Base[T], item: T) -> None: ... -reveal_type(Sub(42)) # N: Revealed type is "__main__.Sub[builtins.int*]" +reveal_type(Sub(42)) # N: Revealed type is "__main__.Sub[builtins.int]" [case testSelfTypeBadTypeIgnoredInConstructorOverload] from typing import overload diff --git a/test-data/unit/check-serialize.test b/test-data/unit/check-serialize.test index 3a9d2266dd552..0d7e9f74fa756 100644 --- a/test-data/unit/check-serialize.test +++ b/test-data/unit/check-serialize.test @@ -81,8 +81,8 @@ T = TypeVar('T') def f(x: T) -> T: return x [out2] -tmp/a.py:2: note: Revealed type is "builtins.int*" -tmp/a.py:3: note: Revealed type is "builtins.str*" +tmp/a.py:2: note: Revealed type is "builtins.int" +tmp/a.py:3: note: Revealed type is "builtins.str" [case testSerializeFunctionReturningGenericFunction] import a @@ -100,7 +100,7 @@ T = TypeVar('T') def f() -> Callable[[T], T]: pass [out2] tmp/a.py:2: note: Revealed type is "def () -> def [T] (T`-1) -> T`-1" -tmp/a.py:3: note: Revealed type is "builtins.str*" +tmp/a.py:3: note: Revealed type is "builtins.str" [case testSerializeArgumentKinds] import a @@ -369,8 +369,8 @@ class A(Generic[T, S]): return self.x [out2] tmp/a.py:3: error: Argument 1 to "A" has incompatible type "str"; expected "int" -tmp/a.py:4: note: Revealed type is "builtins.str*" -tmp/a.py:5: note: Revealed type is "builtins.int*" +tmp/a.py:4: note: Revealed type is "builtins.str" +tmp/a.py:5: note: Revealed type is "builtins.int" [case testSerializeAbstractClass] import a @@ -484,8 +484,8 @@ T = TypeVar('T', bound='A') class A: def f(self: T) -> T: return self [out2] -tmp/a.py:2: note: Revealed type is "b.A*" -tmp/a.py:4: note: Revealed type is "a.B*" +tmp/a.py:2: note: Revealed type is "b.A" +tmp/a.py:4: note: Revealed type is "a.B" [case testSerializeInheritance] import a @@ -529,7 +529,7 @@ class A(Generic[T]): class B(A[A[T]]): pass [out2] -tmp/a.py:3: note: Revealed type is "b.A*[builtins.int*]" +tmp/a.py:3: note: Revealed type is "b.A[builtins.int]" [case testSerializeFixedLengthTupleBaseClass] import a @@ -565,7 +565,7 @@ class A(Tuple[int, ...]): [builtins fixtures/tuple.pyi] [out2] tmp/a.py:3: error: Too many arguments for "f" of "A" -tmp/a.py:4: note: Revealed type is "Tuple[builtins.int*, builtins.int*]" +tmp/a.py:4: note: Revealed type is "Tuple[builtins.int, builtins.int]" [case testSerializePlainTupleBaseClass] import a diff --git a/test-data/unit/check-statements.test b/test-data/unit/check-statements.test index 5819ace83603e..9768f43d0bb1a 100644 --- a/test-data/unit/check-statements.test +++ b/test-data/unit/check-statements.test @@ -1298,7 +1298,7 @@ T = TypeVar('T') def f(a: T) -> Generator[int, str, T]: pass def g() -> Generator[int, str, float]: r = yield from f('') - reveal_type(r) # N: Revealed type is "builtins.str*" + reveal_type(r) # N: Revealed type is "builtins.str" return 3.14 [case testYieldFromTupleStatement] @@ -2107,14 +2107,14 @@ class A: [case testAugmentedAssignmentIntFloatDict] from typing import Dict d = {'weight0': 65.5} -reveal_type(d['weight0']) # N: Revealed type is "builtins.float*" +reveal_type(d['weight0']) # N: Revealed type is "builtins.float" d['weight0'] = 65 -reveal_type(d['weight0']) # N: Revealed type is "builtins.float*" +reveal_type(d['weight0']) # N: Revealed type is "builtins.float" d['weight0'] *= 'a' # E: Unsupported operand types for * ("float" and "str") d['weight0'] *= 0.5 -reveal_type(d['weight0']) # N: Revealed type is "builtins.float*" +reveal_type(d['weight0']) # N: Revealed type is "builtins.float" d['weight0'] *= object() # E: Unsupported operand types for * ("float" and "object") -reveal_type(d['weight0']) # N: Revealed type is "builtins.float*" +reveal_type(d['weight0']) # N: Revealed type is "builtins.float" [builtins fixtures/floatdict.pyi] diff --git a/test-data/unit/check-tuples.test b/test-data/unit/check-tuples.test index b558e1520798c..fbe0c9f857dd2 100644 --- a/test-data/unit/check-tuples.test +++ b/test-data/unit/check-tuples.test @@ -674,9 +674,9 @@ c1, *c2 = c d1, *d2 = d e1, *e2 = e -reveal_type(a2) # N: Revealed type is "builtins.list[builtins.int*]" -reveal_type(b2) # N: Revealed type is "builtins.list[builtins.int*]" -reveal_type(c2) # N: Revealed type is "builtins.list[builtins.int*]" +reveal_type(a2) # N: Revealed type is "builtins.list[builtins.int]" +reveal_type(b2) # N: Revealed type is "builtins.list[builtins.int]" +reveal_type(c2) # N: Revealed type is "builtins.list[builtins.int]" reveal_type(d2) # N: Revealed type is "builtins.list[builtins.int]" reveal_type(e2) # N: Revealed type is "builtins.list[builtins.int]" [builtins fixtures/tuple.pyi] @@ -985,15 +985,15 @@ reveal_type(b) # N: Revealed type is "Tuple[builtins.int, builtins.int, builtin [case testTupleWithStarExpr2] a = [1] b = (0, *a) -reveal_type(b) # N: Revealed type is "builtins.tuple[builtins.int*, ...]" +reveal_type(b) # N: Revealed type is "builtins.tuple[builtins.int, ...]" [builtins fixtures/tuple.pyi] [case testTupleWithStarExpr3] a = [''] b = (0, *a) -reveal_type(b) # N: Revealed type is "builtins.tuple[builtins.object*, ...]" +reveal_type(b) # N: Revealed type is "builtins.tuple[builtins.object, ...]" c = (*a, '') -reveal_type(c) # N: Revealed type is "builtins.tuple[builtins.str*, ...]" +reveal_type(c) # N: Revealed type is "builtins.tuple[builtins.str, ...]" [builtins fixtures/tuple.pyi] [case testTupleWithStarExpr4] @@ -1132,8 +1132,8 @@ reveal_type(empty if int() else vartup) # N: Revealed type is "builtins.tuple[_ reveal_type(vartup if int() else empty) # N: Revealed type is "builtins.tuple[__main__.A, ...]" lst = None # type: List[A] -reveal_type(empty if int() else lst) # N: Revealed type is "typing.Sequence[__main__.A*]" -reveal_type(lst if int() else empty) # N: Revealed type is "typing.Sequence[__main__.A*]" +reveal_type(empty if int() else lst) # N: Revealed type is "typing.Sequence[__main__.A]" +reveal_type(lst if int() else empty) # N: Revealed type is "typing.Sequence[__main__.A]" [builtins fixtures/tuple.pyi] [out] @@ -1277,7 +1277,7 @@ def f(x: Base[T]) -> T: pass class DT(Tuple[str, str], Base[int]): pass -reveal_type(f(DT())) # N: Revealed type is "builtins.int*" +reveal_type(f(DT())) # N: Revealed type is "builtins.int" [builtins fixtures/tuple.pyi] [out] @@ -1364,10 +1364,10 @@ from typing import Union, Tuple, List tup: Union[Tuple[int, str], List[int]] reveal_type(tup[0]) # N: Revealed type is "builtins.int" -reveal_type(tup[1]) # N: Revealed type is "Union[builtins.str, builtins.int*]" +reveal_type(tup[1]) # N: Revealed type is "Union[builtins.str, builtins.int]" reveal_type(tup[2]) # E: Tuple index out of range \ - # N: Revealed type is "Union[Any, builtins.int*]" -reveal_type(tup[:]) # N: Revealed type is "Union[Tuple[builtins.int, builtins.str], builtins.list[builtins.int*]]" + # N: Revealed type is "Union[Any, builtins.int]" +reveal_type(tup[:]) # N: Revealed type is "Union[Tuple[builtins.int, builtins.str], builtins.list[builtins.int]]" [builtins fixtures/tuple.pyi] @@ -1433,24 +1433,24 @@ reveal_type(z) # N: Revealed type is "builtins.int" points2 = [1,2] x2, y2, z2= *points2, "test" -reveal_type(x2) # N: Revealed type is "builtins.int*" -reveal_type(y2) # N: Revealed type is "builtins.int*" +reveal_type(x2) # N: Revealed type is "builtins.int" +reveal_type(y2) # N: Revealed type is "builtins.int" reveal_type(z2) # N: Revealed type is "builtins.str" x3, x4, y3, y4, z3 = *points, *points2, "test" reveal_type(x3) # N: Revealed type is "builtins.int" reveal_type(x4) # N: Revealed type is "builtins.str" -reveal_type(y3) # N: Revealed type is "builtins.int*" -reveal_type(y4) # N: Revealed type is "builtins.int*" +reveal_type(y3) # N: Revealed type is "builtins.int" +reveal_type(y4) # N: Revealed type is "builtins.int" reveal_type(z3) # N: Revealed type is "builtins.str" x5, x6, y5, y6, z4 = *points2, *points2, "test" -reveal_type(x5) # N: Revealed type is "builtins.int*" -reveal_type(x6) # N: Revealed type is "builtins.int*" -reveal_type(y5) # N: Revealed type is "builtins.int*" -reveal_type(y6) # N: Revealed type is "builtins.int*" +reveal_type(x5) # N: Revealed type is "builtins.int" +reveal_type(x6) # N: Revealed type is "builtins.int" +reveal_type(y5) # N: Revealed type is "builtins.int" +reveal_type(y6) # N: Revealed type is "builtins.int" reveal_type(z4) # N: Revealed type is "builtins.str" points3 = ["test1", "test2"] @@ -1481,7 +1481,7 @@ t3 = ('', 1) * 2 reveal_type(t3) # N: Revealed type is "Tuple[builtins.str, builtins.int, builtins.str, builtins.int]" def f() -> Tuple[str, ...]: return ('', ) -reveal_type(f() * 2) # N: Revealed type is "builtins.tuple[builtins.str*, ...]" +reveal_type(f() * 2) # N: Revealed type is "builtins.tuple[builtins.str, ...]" [builtins fixtures/tuple.pyi] [case testMultiplyTupleByIntegerLiteralReverse] @@ -1494,7 +1494,7 @@ t3 = 2 * ('', 1) reveal_type(t3) # N: Revealed type is "Tuple[builtins.str, builtins.int, builtins.str, builtins.int]" def f() -> Tuple[str, ...]: return ('', ) -reveal_type(2 * f()) # N: Revealed type is "builtins.tuple[builtins.str*, ...]" +reveal_type(2 * f()) # N: Revealed type is "builtins.tuple[builtins.str, ...]" [builtins fixtures/tuple.pyi] [case testSingleUndefinedTypeAndTuple] diff --git a/test-data/unit/check-type-aliases.test b/test-data/unit/check-type-aliases.test index 4c5dacee1b3f6..61d53870d7242 100644 --- a/test-data/unit/check-type-aliases.test +++ b/test-data/unit/check-type-aliases.test @@ -341,14 +341,14 @@ x: N.A[C] reveal_type(x) # N: Revealed type is "__main__.C[__main__.C[Any]]" xx = N.A[C]() -reveal_type(xx) # N: Revealed type is "__main__.C[__main__.C*[Any]]" +reveal_type(xx) # N: Revealed type is "__main__.C[__main__.C[Any]]" y = N.A() reveal_type(y) # N: Revealed type is "__main__.C[Any]" M = N b = M.A[int]() -reveal_type(b) # N: Revealed type is "__main__.C[builtins.int*]" +reveal_type(b) # N: Revealed type is "__main__.C[builtins.int]" n: Type[N] w = n.B() @@ -457,8 +457,8 @@ class C: class D(C): ... -reveal_type(D.meth(1)) # N: Revealed type is "Union[__main__.D*, builtins.int]" -reveal_type(D().meth(1)) # N: Revealed type is "Union[__main__.D*, builtins.int]" +reveal_type(D.meth(1)) # N: Revealed type is "Union[__main__.D, builtins.int]" +reveal_type(D().meth(1)) # N: Revealed type is "Union[__main__.D, builtins.int]" [builtins fixtures/classmethod.pyi] [out] diff --git a/test-data/unit/check-typeddict.test b/test-data/unit/check-typeddict.test index a9321826b3ba4..297e2df78a9b4 100644 --- a/test-data/unit/check-typeddict.test +++ b/test-data/unit/check-typeddict.test @@ -6,7 +6,7 @@ Point = TypedDict('Point', {'x': int, 'y': int}) p = Point(x=42, y=1337) reveal_type(p) # N: Revealed type is "TypedDict('__main__.Point', {'x': builtins.int, 'y': builtins.int})" # Use values() to check fallback value type. -reveal_type(p.values()) # N: Revealed type is "typing.Iterable[builtins.object*]" +reveal_type(p.values()) # N: Revealed type is "typing.Iterable[builtins.object]" [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] [targets sys, __main__] @@ -17,7 +17,7 @@ Point = TypedDict('Point', {'x': int, 'y': int}) p = Point(dict(x=42, y=1337)) reveal_type(p) # N: Revealed type is "TypedDict('__main__.Point', {'x': builtins.int, 'y': builtins.int})" # Use values() to check fallback value type. -reveal_type(p.values()) # N: Revealed type is "typing.Iterable[builtins.object*]" +reveal_type(p.values()) # N: Revealed type is "typing.Iterable[builtins.object]" [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] @@ -27,7 +27,7 @@ Point = TypedDict('Point', {'x': int, 'y': int}) p = Point({'x': 42, 'y': 1337}) reveal_type(p) # N: Revealed type is "TypedDict('__main__.Point', {'x': builtins.int, 'y': builtins.int})" # Use values() to check fallback value type. -reveal_type(p.values()) # N: Revealed type is "typing.Iterable[builtins.object*]" +reveal_type(p.values()) # N: Revealed type is "typing.Iterable[builtins.object]" [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] @@ -37,7 +37,7 @@ from mypy_extensions import TypedDict EmptyDict = TypedDict('EmptyDict', {}) p = EmptyDict() reveal_type(p) # N: Revealed type is "TypedDict('__main__.EmptyDict', {})" -reveal_type(p.values()) # N: Revealed type is "typing.Iterable[builtins.object*]" +reveal_type(p.values()) # N: Revealed type is "typing.Iterable[builtins.object]" [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] @@ -488,8 +488,8 @@ def fun(arg: StrMap[T]) -> T: return arg['whatever'] a: A b: B -reveal_type(fun(a)) # N: Revealed type is "builtins.object*" -reveal_type(fun(b)) # N: Revealed type is "builtins.object*" +reveal_type(fun(a)) # N: Revealed type is "builtins.object" +reveal_type(fun(b)) # N: Revealed type is "builtins.object" [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] @@ -502,8 +502,8 @@ Point3D = TypedDict('Point3D', {'x': int, 'y': int, 'z': int}) p1 = TaggedPoint(type='2d', x=0, y=0) p2 = Point3D(x=1, y=1, z=1) joined_points = [p1, p2][0] -reveal_type(p1.values()) # N: Revealed type is "typing.Iterable[builtins.object*]" -reveal_type(p2.values()) # N: Revealed type is "typing.Iterable[builtins.object*]" +reveal_type(p1.values()) # N: Revealed type is "typing.Iterable[builtins.object]" +reveal_type(p2.values()) # N: Revealed type is "typing.Iterable[builtins.object]" reveal_type(joined_points) # N: Revealed type is "TypedDict({'x': builtins.int, 'y': builtins.int})" [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] @@ -540,8 +540,8 @@ left = Cell(value=42) right = {'score': 999} # type: Mapping[str, int] joined1 = [left, right] joined2 = [right, left] -reveal_type(joined1) # N: Revealed type is "builtins.list[typing.Mapping*[builtins.str, builtins.object]]" -reveal_type(joined2) # N: Revealed type is "builtins.list[typing.Mapping*[builtins.str, builtins.object]]" +reveal_type(joined1) # N: Revealed type is "builtins.list[typing.Mapping[builtins.str, builtins.object]]" +reveal_type(joined2) # N: Revealed type is "builtins.list[typing.Mapping[builtins.str, builtins.object]]" [builtins fixtures/dict.pyi] [case testJoinOfTypedDictWithCompatibleMappingSupertypeIsSupertype] @@ -552,8 +552,8 @@ left = Cell(value=42) right = {'score': 999} # type: Sized joined1 = [left, right] joined2 = [right, left] -reveal_type(joined1) # N: Revealed type is "builtins.list[typing.Sized*]" -reveal_type(joined2) # N: Revealed type is "builtins.list[typing.Sized*]" +reveal_type(joined1) # N: Revealed type is "builtins.list[typing.Sized]" +reveal_type(joined2) # N: Revealed type is "builtins.list[typing.Sized]" [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] @@ -565,8 +565,8 @@ left = Cell(value=42) right = 42 joined1 = [left, right] joined2 = [right, left] -reveal_type(joined1) # N: Revealed type is "builtins.list[builtins.object*]" -reveal_type(joined2) # N: Revealed type is "builtins.list[builtins.object*]" +reveal_type(joined1) # N: Revealed type is "builtins.list[builtins.object]" +reveal_type(joined2) # N: Revealed type is "builtins.list[builtins.object]" [builtins fixtures/dict.pyi] @@ -687,7 +687,7 @@ T = TypeVar('T') def f(x: Iterable[T]) -> T: pass A = TypedDict('A', {'x': int}) a: A -reveal_type(f(a)) # N: Revealed type is "builtins.str*" +reveal_type(f(a)) # N: Revealed type is "builtins.str" [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] @@ -868,11 +868,11 @@ m_s_s: Mapping[str, str] m_i_i: Mapping[int, int] m_s_a: Mapping[str, Any] -reveal_type(u(c, m_s_o)) # N: Revealed type is "typing.Mapping*[builtins.str, builtins.object]" -reveal_type(u(m_s_o, c)) # N: Revealed type is "typing.Mapping*[builtins.str, builtins.object]" -reveal_type(u(c, m_s_s)) # N: Revealed type is "Union[typing.Mapping*[builtins.str, builtins.str], TypedDict('__main__.C', {'a': builtins.int, 'b': builtins.int})]" -reveal_type(u(c, m_i_i)) # N: Revealed type is "Union[typing.Mapping*[builtins.int, builtins.int], TypedDict('__main__.C', {'a': builtins.int, 'b': builtins.int})]" -reveal_type(u(c, m_s_a)) # N: Revealed type is "Union[typing.Mapping*[builtins.str, Any], TypedDict('__main__.C', {'a': builtins.int, 'b': builtins.int})]" +reveal_type(u(c, m_s_o)) # N: Revealed type is "typing.Mapping[builtins.str, builtins.object]" +reveal_type(u(m_s_o, c)) # N: Revealed type is "typing.Mapping[builtins.str, builtins.object]" +reveal_type(u(c, m_s_s)) # N: Revealed type is "Union[typing.Mapping[builtins.str, builtins.str], TypedDict('__main__.C', {'a': builtins.int, 'b': builtins.int})]" +reveal_type(u(c, m_i_i)) # N: Revealed type is "Union[typing.Mapping[builtins.int, builtins.int], TypedDict('__main__.C', {'a': builtins.int, 'b': builtins.int})]" +reveal_type(u(c, m_s_a)) # N: Revealed type is "Union[typing.Mapping[builtins.str, Any], TypedDict('__main__.C', {'a': builtins.int, 'b': builtins.int})]" [builtins fixtures/dict.pyi] [case testTypedDictUnionUnambiguousCase] @@ -989,7 +989,7 @@ d: D reveal_type(d.get('x', [])) # N: Revealed type is "builtins.list[builtins.int]" d.get('x', ['x']) # E: List item 0 has incompatible type "str"; expected "int" a = [''] -reveal_type(d.get('x', a)) # N: Revealed type is "Union[builtins.list[builtins.int], builtins.list[builtins.str*]]" +reveal_type(d.get('x', a)) # N: Revealed type is "Union[builtins.list[builtins.int], builtins.list[builtins.str]]" [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] @@ -1006,10 +1006,10 @@ d.get('x', 1, 2) # E: No overload variant of "get" of "Mapping" matches argument # N: def get(self, k: str) -> object \ # N: def [V] get(self, k: str, default: Union[int, V]) -> object x = d.get('z') -reveal_type(x) # N: Revealed type is "builtins.object*" +reveal_type(x) # N: Revealed type is "builtins.object" s = '' y = d.get(s) -reveal_type(y) # N: Revealed type is "builtins.object*" +reveal_type(y) # N: Revealed type is "builtins.object" [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] @@ -1558,7 +1558,7 @@ def f1(x: T, y: S) -> Union[T, S]: ... A = TypedDict('A', {'y': int, 'x': str}) a: A -reveal_type(f1(**a)) # N: Revealed type is "Union[builtins.str*, builtins.int*]" +reveal_type(f1(**a)) # N: Revealed type is "Union[builtins.str, builtins.int]" [builtins fixtures/tuple.pyi] [case testTypedDictAsStarStarArgCalleeKwargs] @@ -1725,7 +1725,7 @@ td: Union[TDA, TDB] reveal_type(td.get('a')) # N: Revealed type is "builtins.int" reveal_type(td.get('b')) # N: Revealed type is "Union[builtins.str, builtins.int]" -reveal_type(td.get('c')) # N: Revealed type is "builtins.object*" +reveal_type(td.get('c')) # N: Revealed type is "builtins.object" reveal_type(td['a']) # N: Revealed type is "builtins.int" reveal_type(td['b']) # N: Revealed type is "Union[builtins.str, builtins.int]" @@ -2299,7 +2299,7 @@ class Foo2(TypedDict): def func(foo: Union[Foo1, Foo2]) -> str: reveal_type(foo["z"]) # N: Revealed type is "builtins.str" # ok, but type is incorrect: - reveal_type(foo.__getitem__("z")) # N: Revealed type is "builtins.object*" + reveal_type(foo.__getitem__("z")) # N: Revealed type is "builtins.object" reveal_type(foo["a"]) # N: Revealed type is "Union[builtins.int, Any]" \ # E: TypedDict "Foo2" has no key "a" diff --git a/test-data/unit/check-typeguard.test b/test-data/unit/check-typeguard.test index 32fe5e750989a..ecefce0914055 100644 --- a/test-data/unit/check-typeguard.test +++ b/test-data/unit/check-typeguard.test @@ -121,7 +121,7 @@ def filter(f: Callable[[T], TypeGuard[R]], it: Iterable[T]) -> Iterable[R]: pass def is_float(a: object) -> TypeGuard[float]: pass a: List[object] = ["a", 0, 0.0] b = filter(is_float, a) -reveal_type(b) # N: Revealed type is "typing.Iterable[builtins.float*]" +reveal_type(b) # N: Revealed type is "typing.Iterable[builtins.float]" [builtins fixtures/tuple.pyi] [case testTypeGuardMethod] @@ -242,8 +242,8 @@ def main1(a: object) -> None: la = [a] if is_float(*la): # E: Type guard requires positional argument - reveal_type(la) # N: Revealed type is "builtins.list[builtins.object*]" - reveal_type(a) # N: Revealed type is "builtins.object*" + reveal_type(la) # N: Revealed type is "builtins.list[builtins.object]" + reveal_type(a) # N: Revealed type is "builtins.object" [builtins fixtures/tuple.pyi] @@ -269,7 +269,7 @@ def main(a: List[Optional[int]]) -> None: reveal_type(bb) # N: Revealed type is "typing.Iterator[Union[builtins.int, None]]" # Also, if you replace 'bool' with 'Any' in the second overload, bb is Iterator[Any] cc = filter(is_int_typeguard, a) - reveal_type(cc) # N: Revealed type is "typing.Iterator[builtins.int*]" + reveal_type(cc) # N: Revealed type is "typing.Iterator[builtins.int]" dd = filter(is_int_bool, a) reveal_type(dd) # N: Revealed type is "typing.Iterator[Union[builtins.int, None]]" @@ -525,8 +525,8 @@ class filter(Generic[_T]): def is_int_typeguard(a: object) -> TypeGuard[int]: pass def returns_bool(a: object) -> bool: pass -reveal_type(filter(is_int_typeguard)) # N: Revealed type is "__main__.filter[builtins.int*]" -reveal_type(filter(returns_bool)) # N: Revealed type is "__main__.filter[builtins.object*]" +reveal_type(filter(is_int_typeguard)) # N: Revealed type is "__main__.filter[builtins.int]" +reveal_type(filter(returns_bool)) # N: Revealed type is "__main__.filter[builtins.object]" [builtins fixtures/tuple.pyi] [case testTypeGuardSubtypingVariance] diff --git a/test-data/unit/check-typevar-values.test b/test-data/unit/check-typevar-values.test index 2c25e9adc8bb8..d5a94f96fae7b 100644 --- a/test-data/unit/check-typevar-values.test +++ b/test-data/unit/check-typevar-values.test @@ -344,8 +344,8 @@ class C(Generic[X]): self.x = x # type: X ci: C[int] cs: C[str] -reveal_type(ci.x) # N: Revealed type is "builtins.int*" -reveal_type(cs.x) # N: Revealed type is "builtins.str*" +reveal_type(ci.x) # N: Revealed type is "builtins.int" +reveal_type(cs.x) # N: Revealed type is "builtins.str" [case testAttributeInGenericTypeWithTypevarValuesUsingInference1] from typing import TypeVar, Generic @@ -659,7 +659,7 @@ T = TypeVar("T", bound=Union[Data, Dict[str, str]]) def f(data: T) -> None: - reveal_type(data["x"]) # N: Revealed type is "Union[builtins.int, builtins.str*]" + reveal_type(data["x"]) # N: Revealed type is "Union[builtins.int, builtins.str]" [builtins fixtures/tuple.pyi] [builtins fixtures/dict.pyi] @@ -688,7 +688,7 @@ T = TypeVar("T", bound="Indexable") class Indexable: def __init__(self, index: str) -> None: - self.index = index + self.index = index def __getitem__(self: T, index: str) -> T: return self._new_instance(index) diff --git a/test-data/unit/check-unions.test b/test-data/unit/check-unions.test index 6966af289f28f..63b090e5743c6 100644 --- a/test-data/unit/check-unions.test +++ b/test-data/unit/check-unions.test @@ -209,13 +209,13 @@ def u(x: T, y: S) -> Union[S, T]: pass a = None # type: Any -reveal_type(u(C(), None)) # N: Revealed type is "__main__.C*" -reveal_type(u(None, C())) # N: Revealed type is "__main__.C*" +reveal_type(u(C(), None)) # N: Revealed type is "__main__.C" +reveal_type(u(None, C())) # N: Revealed type is "__main__.C" -reveal_type(u(C(), a)) # N: Revealed type is "Union[Any, __main__.C*]" -reveal_type(u(a, C())) # N: Revealed type is "Union[__main__.C*, Any]" +reveal_type(u(C(), a)) # N: Revealed type is "Union[Any, __main__.C]" +reveal_type(u(a, C())) # N: Revealed type is "Union[__main__.C, Any]" -reveal_type(u(C(), C())) # N: Revealed type is "__main__.C*" +reveal_type(u(C(), C())) # N: Revealed type is "__main__.C" reveal_type(u(a, a)) # N: Revealed type is "Any" [case testUnionSimplificationSpecialCase2] @@ -228,8 +228,8 @@ S = TypeVar('S') def u(x: T, y: S) -> Union[S, T]: pass def f(x: T) -> None: - reveal_type(u(C(), x)) # N: Revealed type is "Union[T`-1, __main__.C*]" - reveal_type(u(x, C())) # N: Revealed type is "Union[__main__.C*, T`-1]" + reveal_type(u(C(), x)) # N: Revealed type is "Union[T`-1, __main__.C]" + reveal_type(u(x, C())) # N: Revealed type is "Union[__main__.C, T`-1]" [case testUnionSimplificationSpecialCase3] from typing import Any, TypeVar, Generic, Union @@ -258,32 +258,32 @@ def u(x: T, y: S) -> Union[S, T]: pass a = None # type: Any # Base-class-Any and None, simplify -reveal_type(u(C(), None)) # N: Revealed type is "__main__.C*" -reveal_type(u(None, C())) # N: Revealed type is "__main__.C*" +reveal_type(u(C(), None)) # N: Revealed type is "__main__.C" +reveal_type(u(None, C())) # N: Revealed type is "__main__.C" # Normal instance type and None, simplify -reveal_type(u(1, None)) # N: Revealed type is "builtins.int*" -reveal_type(u(None, 1)) # N: Revealed type is "builtins.int*" +reveal_type(u(1, None)) # N: Revealed type is "builtins.int" +reveal_type(u(None, 1)) # N: Revealed type is "builtins.int" # Normal instance type and base-class-Any, no simplification -reveal_type(u(C(), 1)) # N: Revealed type is "Union[builtins.int*, __main__.C*]" -reveal_type(u(1, C())) # N: Revealed type is "Union[__main__.C*, builtins.int*]" +reveal_type(u(C(), 1)) # N: Revealed type is "Union[builtins.int, __main__.C]" +reveal_type(u(1, C())) # N: Revealed type is "Union[__main__.C, builtins.int]" # Normal instance type and Any, no simplification -reveal_type(u(1, a)) # N: Revealed type is "Union[Any, builtins.int*]" -reveal_type(u(a, 1)) # N: Revealed type is "Union[builtins.int*, Any]" +reveal_type(u(1, a)) # N: Revealed type is "Union[Any, builtins.int]" +reveal_type(u(a, 1)) # N: Revealed type is "Union[builtins.int, Any]" # Any and base-class-Any, no simplificaiton -reveal_type(u(C(), a)) # N: Revealed type is "Union[Any, __main__.C*]" -reveal_type(u(a, C())) # N: Revealed type is "Union[__main__.C*, Any]" +reveal_type(u(C(), a)) # N: Revealed type is "Union[Any, __main__.C]" +reveal_type(u(a, C())) # N: Revealed type is "Union[__main__.C, Any]" # Two normal instance types, simplify -reveal_type(u(1, object())) # N: Revealed type is "builtins.object*" -reveal_type(u(object(), 1)) # N: Revealed type is "builtins.object*" +reveal_type(u(1, object())) # N: Revealed type is "builtins.object" +reveal_type(u(object(), 1)) # N: Revealed type is "builtins.object" # Two normal instance types, no simplification -reveal_type(u(1, '')) # N: Revealed type is "Union[builtins.str*, builtins.int*]" -reveal_type(u('', 1)) # N: Revealed type is "Union[builtins.int*, builtins.str*]" +reveal_type(u(1, '')) # N: Revealed type is "Union[builtins.str, builtins.int]" +reveal_type(u('', 1)) # N: Revealed type is "Union[builtins.int, builtins.str]" [case testUnionSimplificationWithDuplicateItems] from typing import Any, TypeVar, Union @@ -297,11 +297,11 @@ def u(x: T, y: S, z: R) -> Union[R, S, T]: pass a = None # type: Any -reveal_type(u(1, 1, 1)) # N: Revealed type is "builtins.int*" -reveal_type(u(C(), C(), None)) # N: Revealed type is "__main__.C*" -reveal_type(u(a, a, 1)) # N: Revealed type is "Union[builtins.int*, Any]" -reveal_type(u(a, C(), a)) # N: Revealed type is "Union[Any, __main__.C*]" -reveal_type(u('', 1, 1)) # N: Revealed type is "Union[builtins.int*, builtins.str*]" +reveal_type(u(1, 1, 1)) # N: Revealed type is "builtins.int" +reveal_type(u(C(), C(), None)) # N: Revealed type is "__main__.C" +reveal_type(u(a, a, 1)) # N: Revealed type is "Union[builtins.int, Any]" +reveal_type(u(a, C(), a)) # N: Revealed type is "Union[Any, __main__.C]" +reveal_type(u('', 1, 1)) # N: Revealed type is "Union[builtins.int, builtins.str]" [case testUnionAndBinaryOperation] from typing import Union @@ -335,10 +335,10 @@ T = TypeVar('T') S = TypeVar('S') def u(x: T, y: S) -> Union[S, T]: pass -reveal_type(u(1, 2.3)) # N: Revealed type is "builtins.float*" -reveal_type(u(2.3, 1)) # N: Revealed type is "builtins.float*" -reveal_type(u(False, 2.2)) # N: Revealed type is "builtins.float*" -reveal_type(u(2.2, False)) # N: Revealed type is "builtins.float*" +reveal_type(u(1, 2.3)) # N: Revealed type is "builtins.float" +reveal_type(u(2.3, 1)) # N: Revealed type is "builtins.float" +reveal_type(u(False, 2.2)) # N: Revealed type is "builtins.float" +reveal_type(u(2.2, False)) # N: Revealed type is "builtins.float" [builtins fixtures/primitives.pyi] [case testSimplifyingUnionWithTypeTypes1] @@ -359,14 +359,14 @@ reveal_type(u(t_a, t_a)) # N: Revealed type is "Type[Any]" reveal_type(u(type, type)) # N: Revealed type is "def (x: builtins.object) -> builtins.type" # One type, other non-type -reveal_type(u(t_s, 1)) # N: Revealed type is "Union[builtins.int*, Type[builtins.str]]" -reveal_type(u(1, t_s)) # N: Revealed type is "Union[Type[builtins.str], builtins.int*]" -reveal_type(u(type, 1)) # N: Revealed type is "Union[builtins.int*, def (x: builtins.object) -> builtins.type]" -reveal_type(u(1, type)) # N: Revealed type is "Union[def (x: builtins.object) -> builtins.type, builtins.int*]" -reveal_type(u(t_a, 1)) # N: Revealed type is "Union[builtins.int*, Type[Any]]" -reveal_type(u(1, t_a)) # N: Revealed type is "Union[Type[Any], builtins.int*]" -reveal_type(u(t_o, 1)) # N: Revealed type is "Union[builtins.int*, Type[builtins.object]]" -reveal_type(u(1, t_o)) # N: Revealed type is "Union[Type[builtins.object], builtins.int*]" +reveal_type(u(t_s, 1)) # N: Revealed type is "Union[builtins.int, Type[builtins.str]]" +reveal_type(u(1, t_s)) # N: Revealed type is "Union[Type[builtins.str], builtins.int]" +reveal_type(u(type, 1)) # N: Revealed type is "Union[builtins.int, def (x: builtins.object) -> builtins.type]" +reveal_type(u(1, type)) # N: Revealed type is "Union[def (x: builtins.object) -> builtins.type, builtins.int]" +reveal_type(u(t_a, 1)) # N: Revealed type is "Union[builtins.int, Type[Any]]" +reveal_type(u(1, t_a)) # N: Revealed type is "Union[Type[Any], builtins.int]" +reveal_type(u(t_o, 1)) # N: Revealed type is "Union[builtins.int, Type[builtins.object]]" +reveal_type(u(1, t_o)) # N: Revealed type is "Union[Type[builtins.object], builtins.int]" [case testSimplifyingUnionWithTypeTypes2] from typing import TypeVar, Union, Type, Any @@ -381,12 +381,12 @@ t_a = None # type: Type[Any] t = None # type: type # Union with object -reveal_type(u(t_o, object())) # N: Revealed type is "builtins.object*" -reveal_type(u(object(), t_o)) # N: Revealed type is "builtins.object*" -reveal_type(u(t_s, object())) # N: Revealed type is "builtins.object*" -reveal_type(u(object(), t_s)) # N: Revealed type is "builtins.object*" -reveal_type(u(t_a, object())) # N: Revealed type is "builtins.object*" -reveal_type(u(object(), t_a)) # N: Revealed type is "builtins.object*" +reveal_type(u(t_o, object())) # N: Revealed type is "builtins.object" +reveal_type(u(object(), t_o)) # N: Revealed type is "builtins.object" +reveal_type(u(t_s, object())) # N: Revealed type is "builtins.object" +reveal_type(u(object(), t_s)) # N: Revealed type is "builtins.object" +reveal_type(u(t_a, object())) # N: Revealed type is "builtins.object" +reveal_type(u(object(), t_a)) # N: Revealed type is "builtins.object" # Union between type objects reveal_type(u(t_o, t_a)) # N: Revealed type is "Union[Type[Any], Type[builtins.object]]" @@ -395,12 +395,12 @@ reveal_type(u(t_s, t_o)) # N: Revealed type is "Type[builtins.object]" reveal_type(u(t_o, t_s)) # N: Revealed type is "Type[builtins.object]" reveal_type(u(t_o, type)) # N: Revealed type is "Type[builtins.object]" reveal_type(u(type, t_o)) # N: Revealed type is "Type[builtins.object]" -reveal_type(u(t_a, t)) # N: Revealed type is "builtins.type*" -reveal_type(u(t, t_a)) # N: Revealed type is "builtins.type*" +reveal_type(u(t_a, t)) # N: Revealed type is "builtins.type" +reveal_type(u(t, t_a)) # N: Revealed type is "builtins.type" # The following should arguably not be simplified, but it's unclear how to fix then # without causing regressions elsewhere. -reveal_type(u(t_o, t)) # N: Revealed type is "builtins.type*" -reveal_type(u(t, t_o)) # N: Revealed type is "builtins.type*" +reveal_type(u(t_o, t)) # N: Revealed type is "builtins.type" +reveal_type(u(t, t_o)) # N: Revealed type is "builtins.type" [case testNotSimplifyingUnionWithMetaclass] from typing import TypeVar, Union, Type, Any @@ -416,11 +416,11 @@ def u(x: T, y: S) -> Union[S, T]: pass a: Any t_a: Type[A] -reveal_type(u(M(*a), t_a)) # N: Revealed type is "__main__.M*" -reveal_type(u(t_a, M(*a))) # N: Revealed type is "__main__.M*" +reveal_type(u(M(*a), t_a)) # N: Revealed type is "__main__.M" +reveal_type(u(t_a, M(*a))) # N: Revealed type is "__main__.M" -reveal_type(u(M2(*a), t_a)) # N: Revealed type is "Union[Type[__main__.A], __main__.M2*]" -reveal_type(u(t_a, M2(*a))) # N: Revealed type is "Union[__main__.M2*, Type[__main__.A]]" +reveal_type(u(M2(*a), t_a)) # N: Revealed type is "Union[Type[__main__.A], __main__.M2]" +reveal_type(u(t_a, M2(*a))) # N: Revealed type is "Union[__main__.M2, Type[__main__.A]]" [case testSimplifyUnionWithCallable] from typing import TypeVar, Union, Any, Callable @@ -548,8 +548,8 @@ def pack_two(x: T, y: S) -> Union[Tuple[T, T], Tuple[S, S]]: pass (x, y) = pack_two(1, 'a') -reveal_type(x) # N: Revealed type is "Union[builtins.int*, builtins.str*]" -reveal_type(y) # N: Revealed type is "Union[builtins.int*, builtins.str*]" +reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]" +reveal_type(y) # N: Revealed type is "Union[builtins.int, builtins.str]" [builtins fixtures/tuple.pyi] [case testUnionMultiassignAny] @@ -572,7 +572,7 @@ class B(A): pass class C(A): pass a: Union[List[B], List[C]] x, y = a -reveal_type(x) # N: Revealed type is "Union[__main__.B*, __main__.C*]" +reveal_type(x) # N: Revealed type is "Union[__main__.B, __main__.C]" [builtins fixtures/list.pyi] [case testUnionMultiassignRebind] @@ -584,8 +584,8 @@ class C(A): pass obj: object a: Union[List[B], List[C]] obj, new = a -reveal_type(obj) # N: Revealed type is "Union[__main__.B*, __main__.C*]" -reveal_type(new) # N: Revealed type is "Union[__main__.B*, __main__.C*]" +reveal_type(obj) # N: Revealed type is "Union[__main__.B, __main__.C]" +reveal_type(new) # N: Revealed type is "Union[__main__.B, __main__.C]" obj = 1 reveal_type(obj) # N: Revealed type is "builtins.int" @@ -631,7 +631,7 @@ b: B a: Union[Tuple[int, int], Tuple[int, object]] (x[0], b.x) = a -reveal_type(x[0]) # N: Revealed type is "builtins.int*" +reveal_type(x[0]) # N: Revealed type is "builtins.int" reveal_type(b.x) # N: Revealed type is "builtins.object" [builtins fixtures/list.pyi] @@ -648,7 +648,7 @@ b: B a: Union[Tuple[int, int], Tuple[int, object]] (x[0], b.x) = a # E: Incompatible types in assignment (expression has type "int", target has type "A") \ # E: Incompatible types in assignment (expression has type "object", variable has type "int") -reveal_type(x[0]) # N: Revealed type is "__main__.A*" +reveal_type(x[0]) # N: Revealed type is "__main__.A" reveal_type(b.x) # N: Revealed type is "builtins.int" [builtins fixtures/list.pyi] @@ -661,7 +661,7 @@ a2: object (a1, *xs, a2) = a reveal_type(a1) # N: Revealed type is "builtins.int" -reveal_type(xs) # N: Revealed type is "builtins.list[builtins.int*]" +reveal_type(xs) # N: Revealed type is "builtins.list[builtins.int]" reveal_type(a2) # N: Revealed type is "Union[builtins.int, builtins.str]" [builtins fixtures/list.pyi] @@ -676,8 +676,8 @@ def f(x: bool) -> Union[List[int], List[str]]: def g(x: bool) -> None: a, b = f(x) - reveal_type(a) # N: Revealed type is "Union[builtins.int*, builtins.str*]" - reveal_type(b) # N: Revealed type is "Union[builtins.int*, builtins.str*]" + reveal_type(a) # N: Revealed type is "Union[builtins.int, builtins.str]" + reveal_type(b) # N: Revealed type is "Union[builtins.int, builtins.str]" [builtins fixtures/list.pyi] [case testUnionOfVariableLengthTupleUnpacking] @@ -692,7 +692,7 @@ a, b = x # E: Too many values to unpack (2 expected, 3 provided) a, b, c = x # E: Need more than 2 values to unpack (3 expected) c, *d = x reveal_type(c) # N: Revealed type is "builtins.int" -reveal_type(d) # N: Revealed type is "builtins.list[builtins.int*]" +reveal_type(d) # N: Revealed type is "builtins.list[builtins.int]" [builtins fixtures/tuple.pyi] [case testUnionOfNonIterableUnpacking] @@ -780,8 +780,8 @@ from typing import Union, List good: Union[List[int], List[str]] lst = x, y = good -reveal_type(x) # N: Revealed type is "Union[builtins.int*, builtins.str*]" -reveal_type(y) # N: Revealed type is "Union[builtins.int*, builtins.str*]" +reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]" +reveal_type(y) # N: Revealed type is "Union[builtins.int, builtins.str]" reveal_type(lst) # N: Revealed type is "Union[builtins.list[builtins.int], builtins.list[builtins.str]]" [builtins fixtures/list.pyi] [out] @@ -791,9 +791,9 @@ from typing import Union, List good: Union[List[int], List[str]] x, *y, z = lst = good -reveal_type(x) # N: Revealed type is "Union[builtins.int*, builtins.str*]" -reveal_type(y) # N: Revealed type is "Union[builtins.list[builtins.int*], builtins.list[builtins.str*]]" -reveal_type(z) # N: Revealed type is "Union[builtins.int*, builtins.str*]" +reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]" +reveal_type(y) # N: Revealed type is "Union[builtins.list[builtins.int], builtins.list[builtins.str]]" +reveal_type(z) # N: Revealed type is "Union[builtins.int, builtins.str]" reveal_type(lst) # N: Revealed type is "Union[builtins.list[builtins.int], builtins.list[builtins.str]]" [builtins fixtures/list.pyi] [out] @@ -808,15 +808,15 @@ class NTStr(NamedTuple): y: str t1: NTInt -reveal_type(t1.__iter__) # N: Revealed type is "def () -> typing.Iterator[builtins.int*]" +reveal_type(t1.__iter__) # N: Revealed type is "def () -> typing.Iterator[builtins.int]" nt: Union[NTInt, NTStr] -reveal_type(nt.__iter__) # N: Revealed type is "Union[def () -> typing.Iterator[builtins.int*], def () -> typing.Iterator[builtins.str*]]" +reveal_type(nt.__iter__) # N: Revealed type is "Union[def () -> typing.Iterator[builtins.int], def () -> typing.Iterator[builtins.str]]" for nx in nt: - reveal_type(nx) # N: Revealed type is "Union[builtins.int*, builtins.str*]" + reveal_type(nx) # N: Revealed type is "Union[builtins.int, builtins.str]" t: Union[Tuple[int, int], Tuple[str, str]] for x in t: - reveal_type(x) # N: Revealed type is "Union[builtins.int*, builtins.str*]" + reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]" [builtins fixtures/for.pyi] [out] diff --git a/test-data/unit/check-unreachable-code.test b/test-data/unit/check-unreachable-code.test index ad604b474ad4e..ef098c42901e1 100644 --- a/test-data/unit/check-unreachable-code.test +++ b/test-data/unit/check-unreachable-code.test @@ -1002,9 +1002,9 @@ def test1(x: T1) -> T1: def test2(x: T2) -> T2: if isinstance(x, int): - reveal_type(x) # N: Revealed type is "builtins.int*" + reveal_type(x) # N: Revealed type is "builtins.int" else: - reveal_type(x) # N: Revealed type is "builtins.str*" + reveal_type(x) # N: Revealed type is "builtins.str" if False: # This is unreachable, but we don't report an error, unfortunately. @@ -1020,9 +1020,9 @@ class Test3(Generic[T2]): def func(self) -> None: if isinstance(self.x, int): - reveal_type(self.x) # N: Revealed type is "builtins.int*" + reveal_type(self.x) # N: Revealed type is "builtins.int" else: - reveal_type(self.x) # N: Revealed type is "builtins.str*" + reveal_type(self.x) # N: Revealed type is "builtins.str" if False: # Same issue as above diff --git a/test-data/unit/check-varargs.test b/test-data/unit/check-varargs.test index 57a578401c517..d93618b85ba98 100644 --- a/test-data/unit/check-varargs.test +++ b/test-data/unit/check-varargs.test @@ -123,7 +123,7 @@ T4 = TypeVar('T4') def f(a: T1, b: T2, c: T3, d: T4) -> Tuple[T1, T2, T3, T4]: ... x: Tuple[int, str] y: Tuple[float, bool] -reveal_type(f(*x, *y)) # N: Revealed type is "Tuple[builtins.int*, builtins.str*, builtins.float*, builtins.bool*]" +reveal_type(f(*x, *y)) # N: Revealed type is "Tuple[builtins.int, builtins.str, builtins.float, builtins.bool]" [builtins fixtures/list.pyi] [case testCallVarargsFunctionWithIterableAndPositional] diff --git a/test-data/unit/fine-grained.test b/test-data/unit/fine-grained.test index 86872277c6e31..fa6dc52262ddd 100644 --- a/test-data/unit/fine-grained.test +++ b/test-data/unit/fine-grained.test @@ -8760,7 +8760,7 @@ from typing_extensions import Literal bar: Literal[3] = 3 [builtins fixtures/tuple.pyi] [out] -main:2: note: Revealed type is "builtins.int*" +main:2: note: Revealed type is "builtins.int" == main:2: note: Revealed type is "Literal[3]" diff --git a/test-data/unit/pythoneval.test b/test-data/unit/pythoneval.test index f560ac81e6450..a0b98d2501c75 100644 --- a/test-data/unit/pythoneval.test +++ b/test-data/unit/pythoneval.test @@ -905,9 +905,9 @@ _testCollectionsAliases.py:5: note: Revealed type is "collections.Counter[builti _testCollectionsAliases.py:6: error: Invalid index type "str" for "Counter[int]"; expected type "int" _testCollectionsAliases.py:9: note: Revealed type is "collections.ChainMap[builtins.int, builtins.str]" _testCollectionsAliases.py:12: note: Revealed type is "collections.deque[builtins.int]" -_testCollectionsAliases.py:15: note: Revealed type is "collections.Counter[builtins.int*]" -_testCollectionsAliases.py:18: note: Revealed type is "collections.ChainMap[builtins.int*, builtins.str*]" -_testCollectionsAliases.py:21: note: Revealed type is "collections.deque[builtins.int*]" +_testCollectionsAliases.py:15: note: Revealed type is "collections.Counter[builtins.int]" +_testCollectionsAliases.py:18: note: Revealed type is "collections.ChainMap[builtins.int, builtins.str]" +_testCollectionsAliases.py:21: note: Revealed type is "collections.deque[builtins.int]" [case testChainMapUnimported] ChainMap[int, str]() @@ -1060,10 +1060,10 @@ reveal_type(g) with f('') as s: reveal_type(s) [out] -_program.py:13: note: Revealed type is "def (x: builtins.int) -> contextlib._GeneratorContextManager[builtins.str*]" -_program.py:14: note: Revealed type is "def (*x: builtins.str) -> contextlib._GeneratorContextManager[builtins.int*]" +_program.py:13: note: Revealed type is "def (x: builtins.int) -> contextlib._GeneratorContextManager[builtins.str]" +_program.py:14: note: Revealed type is "def (*x: builtins.str) -> contextlib._GeneratorContextManager[builtins.int]" _program.py:16: error: Argument 1 to "f" has incompatible type "str"; expected "int" -_program.py:17: note: Revealed type is "builtins.str*" +_program.py:17: note: Revealed type is "builtins.str" [case testTypedDictGet] # Test that TypedDict get plugin works with typeshed stubs @@ -1081,12 +1081,12 @@ reveal_type(d.get(s)) [out] _testTypedDictGet.py:7: note: Revealed type is "builtins.int" _testTypedDictGet.py:8: note: Revealed type is "builtins.str" -_testTypedDictGet.py:9: note: Revealed type is "builtins.object*" +_testTypedDictGet.py:9: note: Revealed type is "builtins.object" _testTypedDictGet.py:10: error: All overload variants of "get" of "Mapping" require at least one argument _testTypedDictGet.py:10: note: Possible overload variants: _testTypedDictGet.py:10: note: def get(self, key: str) -> object _testTypedDictGet.py:10: note: def [_T] get(self, str, object) -> object -_testTypedDictGet.py:12: note: Revealed type is "builtins.object*" +_testTypedDictGet.py:12: note: Revealed type is "builtins.object" [case testTypedDictMappingMethods] from mypy_extensions import TypedDict @@ -1111,8 +1111,8 @@ Cell2 = TypedDict('Cell2', {'value': int}, total=False) c2 = Cell2() reveal_type(c2.pop('value')) [out] -_testTypedDictMappingMethods.py:5: note: Revealed type is "builtins.str*" -_testTypedDictMappingMethods.py:6: note: Revealed type is "typing.Iterator*[builtins.str*]" +_testTypedDictMappingMethods.py:5: note: Revealed type is "builtins.str" +_testTypedDictMappingMethods.py:6: note: Revealed type is "typing.Iterator[builtins.str]" _testTypedDictMappingMethods.py:7: note: Revealed type is "builtins.int" _testTypedDictMappingMethods.py:8: note: Revealed type is "builtins.bool" _testTypedDictMappingMethods.py:9: note: Revealed type is "typing.KeysView[builtins.str]" @@ -1203,8 +1203,8 @@ _testNoCrashOnGenericUnionUnpacking.py:6: note: Revealed type is "builtins.str" _testNoCrashOnGenericUnionUnpacking.py:7: note: Revealed type is "builtins.str" _testNoCrashOnGenericUnionUnpacking.py:10: note: Revealed type is "Union[builtins.str, builtins.int]" _testNoCrashOnGenericUnionUnpacking.py:11: note: Revealed type is "Union[builtins.str, builtins.int]" -_testNoCrashOnGenericUnionUnpacking.py:15: note: Revealed type is "Union[builtins.int*, builtins.str*]" -_testNoCrashOnGenericUnionUnpacking.py:16: note: Revealed type is "Union[builtins.int*, builtins.str*]" +_testNoCrashOnGenericUnionUnpacking.py:15: note: Revealed type is "Union[builtins.int, builtins.str]" +_testNoCrashOnGenericUnionUnpacking.py:16: note: Revealed type is "Union[builtins.int, builtins.str]" [case testMetaclassOpAccess] from typing import Type @@ -1272,8 +1272,8 @@ class E(Enum): for e in E: reveal_type(e) [out] -_testEnumIterationAndPreciseElementType.py:5: note: Revealed type is "_testEnumIterationAndPreciseElementType.E*" -_testEnumIterationAndPreciseElementType.py:7: note: Revealed type is "_testEnumIterationAndPreciseElementType.E*" +_testEnumIterationAndPreciseElementType.py:5: note: Revealed type is "_testEnumIterationAndPreciseElementType.E" +_testEnumIterationAndPreciseElementType.py:7: note: Revealed type is "_testEnumIterationAndPreciseElementType.E" [case testEnumIterable] from enum import Enum @@ -1297,7 +1297,7 @@ f(N) g(N) reveal_type(list(N)) [out] -_testIntEnumIterable.py:11: note: Revealed type is "builtins.list[_testIntEnumIterable.N*]" +_testIntEnumIterable.py:11: note: Revealed type is "builtins.list[_testIntEnumIterable.N]" [case testDerivedEnumIterable] from enum import Enum @@ -1357,7 +1357,7 @@ def print_custom_table() -> None: for row in simple_map(format_row, a, a, a, a, a, a, a, a): # 8 columns reveal_type(row) [out] -_testLoadsOfOverloads.py:24: note: Revealed type is "builtins.str*" +_testLoadsOfOverloads.py:24: note: Revealed type is "builtins.str" [case testReduceWithAnyInstance] from typing import Iterable @@ -1423,7 +1423,7 @@ from typing import Dict, List, Tuple x: Dict[str, List[int]] reveal_type(x['test'][0]) [out] -_testNewAnalyzerBasicTypeshed_newsemanal.py:4: note: Revealed type is "builtins.int*" +_testNewAnalyzerBasicTypeshed_newsemanal.py:4: note: Revealed type is "builtins.int" [case testNewAnalyzerTypedDictInStub_newsemanal] import stub From 7ac5a1993f28d4a3ef8b7c7fbc541fc4210e5414 Mon Sep 17 00:00:00 2001 From: jhance Date: Mon, 28 Mar 2022 14:22:18 -0700 Subject: [PATCH 204/377] Unify a codepath in typevarlike semanal (#12480) --- mypy/semanal.py | 34 ++++++++++++++++-------------- test-data/unit/semanal-errors.test | 4 ++-- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index eded9a5ea913b..8872e6f4aa8ad 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -3093,14 +3093,8 @@ def process_typevar_declaration(self, s: AssignmentStmt) -> bool: if not call: return False - lvalue = s.lvalues[0] - assert isinstance(lvalue, NameExpr) - if s.type: - self.fail("Cannot declare the type of a type variable", s) - return False - - name = lvalue.name - if not self.check_typevarlike_name(call, name, s): + name = self.extract_typevarlike_name(s, call) + if name is None: return False # Constraining types @@ -3279,6 +3273,20 @@ def process_typevar_parameters(self, args: List[Expression], variance = INVARIANT return variance, upper_bound + def extract_typevarlike_name(self, s: AssignmentStmt, call: CallExpr) -> Optional[str]: + if not call: + return None + + lvalue = s.lvalues[0] + assert isinstance(lvalue, NameExpr) + if s.type: + self.fail("Cannot declare the type of a TypeVar or similar construct", s) + return None + + if not self.check_typevarlike_name(call, lvalue.name, s): + return None + return lvalue.name + def process_paramspec_declaration(self, s: AssignmentStmt) -> bool: """Checks if s declares a ParamSpec; if yes, store it in symbol table. @@ -3293,14 +3301,8 @@ def process_paramspec_declaration(self, s: AssignmentStmt) -> bool: if not call: return False - lvalue = s.lvalues[0] - assert isinstance(lvalue, NameExpr) - if s.type: - self.fail("Cannot declare the type of a parameter specification", s) - return False - - name = lvalue.name - if not self.check_typevarlike_name(call, name, s): + name = self.extract_typevarlike_name(s, call) + if name is None: return False # ParamSpec is different from a regular TypeVar: diff --git a/test-data/unit/semanal-errors.test b/test-data/unit/semanal-errors.test index a0efccef59134..34ec4f3c5b63e 100644 --- a/test-data/unit/semanal-errors.test +++ b/test-data/unit/semanal-errors.test @@ -1081,7 +1081,7 @@ x = TypeVar('x') # E: Cannot redefine "x" as a type variable [case testTypevarWithType] from typing import TypeVar -x = TypeVar('x') # type: int # E: Cannot declare the type of a type variable +x = TypeVar('x') # type: int # E: Cannot declare the type of a TypeVar or similar construct [out] [case testRedefineTypevar] @@ -1432,7 +1432,7 @@ from typing_extensions import ParamSpec TParams = ParamSpec('TParams') TP = ParamSpec('?') # E: String argument 1 "?" to ParamSpec(...) does not match variable name "TP" -TP2: int = ParamSpec('TP2') # E: Cannot declare the type of a parameter specification +TP2: int = ParamSpec('TP2') # E: Cannot declare the type of a TypeVar or similar construct [out] From 433544bf6f8b886f5f364e3a8de4cc1c0eb43da9 Mon Sep 17 00:00:00 2001 From: Spencer Brown Date: Tue, 29 Mar 2022 12:10:13 +1000 Subject: [PATCH 205/377] Recognise both `attrs` and `attr` package names in the plugin (#12469) Recognise new 'attrs' package name in the attrs plugin --- mypy/plugins/attrs.py | 8 +- test-data/unit/check-attr.test | 36 ++++++ test-data/unit/lib-stub/attrs/__init__.pyi | 128 +++++++++++++++++++ test-data/unit/lib-stub/attrs/converters.pyi | 12 ++ 4 files changed, 181 insertions(+), 3 deletions(-) create mode 100644 test-data/unit/lib-stub/attrs/__init__.pyi create mode 100644 test-data/unit/lib-stub/attrs/converters.pyi diff --git a/mypy/plugins/attrs.py b/mypy/plugins/attrs.py index 9e4b80c905cfb..0f6431d4700a2 100644 --- a/mypy/plugins/attrs.py +++ b/mypy/plugins/attrs.py @@ -41,14 +41,16 @@ attr_dataclass_makers: Final = { 'attr.dataclass', } -attr_frozen_makers: Final = {"attr.frozen"} -attr_define_makers: Final = {"attr.define", "attr.mutable"} +attr_frozen_makers: Final = {"attr.frozen", "attrs.frozen"} +attr_define_makers: Final = {"attr.define", "attr.mutable", "attrs.define", "attrs.mutable"} attr_attrib_makers: Final = { 'attr.ib', 'attr.attrib', 'attr.attr', 'attr.field', + 'attrs.field', } +attr_optional_converters: Final = {'attr.converters.optional', 'attrs.converters.optional'} SELF_TVAR_NAME: Final = "_AT" MAGIC_ATTR_NAME: Final = "__attrs_attrs__" @@ -609,7 +611,7 @@ def _parse_converter(ctx: 'mypy.plugin.ClassDefContext', if (isinstance(converter, CallExpr) and isinstance(converter.callee, RefExpr) - and converter.callee.fullname == "attr.converters.optional" + and converter.callee.fullname in attr_optional_converters and converter.args and converter.args[0]): # Special handling for attr.converters.optional(type) diff --git a/test-data/unit/check-attr.test b/test-data/unit/check-attr.test index 688366e616171..a69bd473624d1 100644 --- a/test-data/unit/check-attr.test +++ b/test-data/unit/check-attr.test @@ -400,7 +400,22 @@ reveal_type(D) # N: Revealed type is "def (b: Any) -> __main__.D" [builtins fixtures/bool.pyi] +[case testAttrsNewPackage] +import attrs +@attrs.define +class A: + a: int = attrs.field() + b: bool + +@attrs.frozen +class B: + a: bool + b: int +reveal_type(A) # N: Revealed type is "def (a: builtins.int, b: builtins.bool) -> __main__.A" +reveal_type(B) # N: Revealed type is "def (a: builtins.bool, b: builtins.int) -> __main__.B" + +[builtins fixtures/bool.pyi] [case testAttrsDataClass] import attr @@ -1133,6 +1148,27 @@ A(None, None) [builtins fixtures/attr.pyi] +[case testAttrsOptionalConverterNewPackage] +# flags: --strict-optional +import attrs +from attrs.converters import optional +from typing import Optional + +def converter(s:int) -> str: + return 'hello' + + +@attrs.define +class A: + y: Optional[int] = attrs.field(converter=optional(int)) + z: Optional[str] = attrs.field(converter=optional(converter)) + + +A(None, None) + +[builtins fixtures/attr.pyi] + + [case testAttrsTypeVarNoCollision] from typing import TypeVar, Generic import attr diff --git a/test-data/unit/lib-stub/attrs/__init__.pyi b/test-data/unit/lib-stub/attrs/__init__.pyi new file mode 100644 index 0000000000000..d257740451324 --- /dev/null +++ b/test-data/unit/lib-stub/attrs/__init__.pyi @@ -0,0 +1,128 @@ +from typing import TypeVar, overload, Callable, Any, Optional, Union, Sequence, Mapping + +_T = TypeVar('_T') +_C = TypeVar('_C', bound=type) + +_ValidatorType = Callable[[Any, Any, _T], Any] +_ConverterType = Callable[[Any], _T] +_ValidatorArgType = Union[_ValidatorType[_T], Sequence[_ValidatorType[_T]]] + +@overload +def define( + maybe_cls: _C, + *, + these: Optional[Mapping[str, Any]] = ..., + repr: bool = ..., + hash: Optional[bool] = ..., + init: bool = ..., + slots: bool = ..., + frozen: bool = ..., + weakref_slot: bool = ..., + str: bool = ..., + auto_attribs: bool = ..., + kw_only: bool = ..., + cache_hash: bool = ..., + auto_exc: bool = ..., + eq: Optional[bool] = ..., + order: Optional[bool] = ..., + auto_detect: bool = ..., + getstate_setstate: Optional[bool] = ..., + on_setattr: Optional[object] = ..., +) -> _C: ... +@overload +def define( + maybe_cls: None = ..., + *, + these: Optional[Mapping[str, Any]] = ..., + repr: bool = ..., + hash: Optional[bool] = ..., + init: bool = ..., + slots: bool = ..., + frozen: bool = ..., + weakref_slot: bool = ..., + str: bool = ..., + auto_attribs: bool = ..., + kw_only: bool = ..., + cache_hash: bool = ..., + auto_exc: bool = ..., + eq: Optional[bool] = ..., + order: Optional[bool] = ..., + auto_detect: bool = ..., + getstate_setstate: Optional[bool] = ..., + on_setattr: Optional[object] = ..., +) -> Callable[[_C], _C]: ... + +mutable = define +frozen = define # they differ only in their defaults + +@overload +def field( + *, + default: None = ..., + validator: None = ..., + repr: object = ..., + hash: Optional[bool] = ..., + init: bool = ..., + metadata: Optional[Mapping[Any, Any]] = ..., + converter: None = ..., + factory: None = ..., + kw_only: bool = ..., + eq: Optional[bool] = ..., + order: Optional[bool] = ..., + on_setattr: Optional[_OnSetAttrArgType] = ..., +) -> Any: ... + +# This form catches an explicit None or no default and infers the type from the +# other arguments. +@overload +def field( + *, + default: None = ..., + validator: Optional[_ValidatorArgType[_T]] = ..., + repr: object = ..., + hash: Optional[bool] = ..., + init: bool = ..., + metadata: Optional[Mapping[Any, Any]] = ..., + converter: Optional[_ConverterType] = ..., + factory: Optional[Callable[[], _T]] = ..., + kw_only: bool = ..., + eq: Optional[bool] = ..., + order: Optional[bool] = ..., + on_setattr: Optional[object] = ..., +) -> _T: ... + +# This form catches an explicit default argument. +@overload +def field( + *, + default: _T, + validator: Optional[_ValidatorArgType[_T]] = ..., + repr: object = ..., + hash: Optional[bool] = ..., + init: bool = ..., + metadata: Optional[Mapping[Any, Any]] = ..., + converter: Optional[_ConverterType] = ..., + factory: Optional[Callable[[], _T]] = ..., + kw_only: bool = ..., + eq: Optional[bool] = ..., + order: Optional[bool] = ..., + on_setattr: Optional[object] = ..., +) -> _T: ... + +# This form covers type=non-Type: e.g. forward references (str), Any +@overload +def field( + *, + default: Optional[_T] = ..., + validator: Optional[_ValidatorArgType[_T]] = ..., + repr: object = ..., + hash: Optional[bool] = ..., + init: bool = ..., + metadata: Optional[Mapping[Any, Any]] = ..., + converter: Optional[_ConverterType] = ..., + factory: Optional[Callable[[], _T]] = ..., + kw_only: bool = ..., + eq: Optional[bool] = ..., + order: Optional[bool] = ..., + on_setattr: Optional[object] = ..., +) -> Any: ... diff --git a/test-data/unit/lib-stub/attrs/converters.pyi b/test-data/unit/lib-stub/attrs/converters.pyi new file mode 100644 index 0000000000000..33800490894d8 --- /dev/null +++ b/test-data/unit/lib-stub/attrs/converters.pyi @@ -0,0 +1,12 @@ +from typing import TypeVar, Optional, Callable, overload +from attr import _ConverterType + +_T = TypeVar("_T") + +def optional( + converter: _ConverterType[_T] +) -> _ConverterType[Optional[_T]]: ... +@overload +def default_if_none(default: _T) -> _ConverterType[_T]: ... +@overload +def default_if_none(*, factory: Callable[[], _T]) -> _ConverterType[_T]: ... From b7d74f3e202fa60ff0d8a2efc299913aad68e2ed Mon Sep 17 00:00:00 2001 From: Ikko Ashimine Date: Tue, 29 Mar 2022 15:56:15 +0900 Subject: [PATCH 206/377] Fix typo in checkpattern.py (#12484) lenght -> length --- mypy/checkpattern.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/checkpattern.py b/mypy/checkpattern.py index a20dfb714025f..0fedec24cc372 100644 --- a/mypy/checkpattern.py +++ b/mypy/checkpattern.py @@ -358,7 +358,7 @@ def expand_starred_pattern_types(self, """Undoes the contraction done by contract_starred_pattern_types. For example if the sequence pattern is [a, *b, c] and types [bool, int, str] are extended - to lenght 4 the result is [bool, int, int, str]. + to length 4 the result is [bool, int, int, str]. """ if star_pos is None: return types From a33d2353a81d075850a487f3913720037f2473aa Mon Sep 17 00:00:00 2001 From: Jordan Speicher Date: Tue, 29 Mar 2022 12:53:43 -0500 Subject: [PATCH 207/377] propertize Callable attributes before freezing dataclasses (#12383) Co-authored-by: Jelle Zijlstra --- mypy/plugins/dataclasses.py | 7 +++++-- test-data/unit/check-dataclasses.test | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/mypy/plugins/dataclasses.py b/mypy/plugins/dataclasses.py index 211f0a8dda839..18caed8bbb8e4 100644 --- a/mypy/plugins/dataclasses.py +++ b/mypy/plugins/dataclasses.py @@ -210,6 +210,7 @@ def transform(self) -> None: ) if decorator_arguments['frozen']: + self._propertize_callables(attributes, settable=False) self._freeze(attributes) else: self._propertize_callables(attributes) @@ -466,7 +467,9 @@ def _freeze(self, attributes: List[DataclassAttribute]) -> None: var._fullname = info.fullname + '.' + var.name info.names[var.name] = SymbolTableNode(MDEF, var) - def _propertize_callables(self, attributes: List[DataclassAttribute]) -> None: + def _propertize_callables(self, + attributes: List[DataclassAttribute], + settable: bool = True) -> None: """Converts all attributes with callable types to @property methods. This avoids the typechecker getting confused and thinking that @@ -480,7 +483,7 @@ def _propertize_callables(self, attributes: List[DataclassAttribute]) -> None: var = attr.to_var() var.info = info var.is_property = True - var.is_settable_property = True + var.is_settable_property = settable var._fullname = info.fullname + '.' + var.name info.names[var.name] = SymbolTableNode(MDEF, var) diff --git a/test-data/unit/check-dataclasses.test b/test-data/unit/check-dataclasses.test index 869f8397ef067..594df103841cf 100644 --- a/test-data/unit/check-dataclasses.test +++ b/test-data/unit/check-dataclasses.test @@ -1537,6 +1537,22 @@ A(1) A(a="foo") # E: Argument "a" to "A" has incompatible type "str"; expected "int" [builtins fixtures/dataclasses.pyi] +[case testDataclassesCallableFrozen] +# flags: --python-version 3.7 +from dataclasses import dataclass +from typing import Any, Callable +@dataclass(frozen=True) +class A: + a: Callable[..., None] + +def func() -> None: + pass + +reveal_type(A.a) # N: Revealed type is "def (*Any, **Any)" +A(a=func).a() +A(a=func).a = func # E: Property "a" defined in "A" is read-only +[builtins fixtures/dataclasses.pyi] + [case testDataclassesMultipleInheritanceWithNonDataclass] # flags: --python-version 3.10 from dataclasses import dataclass From 7b2f86111473a32a753e46a74c954c64cbc3dccb Mon Sep 17 00:00:00 2001 From: Kevin Mai-Husan Chia Date: Wed, 30 Mar 2022 06:58:47 +0800 Subject: [PATCH 208/377] Remove an unused AnyStr import --- docs/source/cheat_sheet_py3.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/cheat_sheet_py3.rst b/docs/source/cheat_sheet_py3.rst index 734bc16ddea59..e14cde7d50df1 100644 --- a/docs/source/cheat_sheet_py3.rst +++ b/docs/source/cheat_sheet_py3.rst @@ -296,7 +296,7 @@ Miscellaneous import sys import re - from typing import Match, AnyStr, IO + from typing import Match, IO # "typing.Match" describes regex matches from the re module x: Match[str] = re.match(r'[0-9]+', "15") From 909ec85c5d9dea50ec137d183b6975e55c7190c1 Mon Sep 17 00:00:00 2001 From: luzpaz Date: Wed, 30 Mar 2022 13:33:50 -0400 Subject: [PATCH 209/377] Fix typos (#12495) Found via `codespell -q 3 -S ./mypyc/external/googletest -L alo,ans,asend,ba,bre,dne,fo,haa,ist,larg,myu,nams,spawnve,statics,thow,ure,whet,wont,zar` --- docs/source/common_issues.rst | 2 +- docs/source/literal_types.rst | 4 ++-- mypy/api.py | 2 +- mypy/message_registry.py | 2 +- mypyc/doc/introduction.rst | 2 +- mypyc/test-data/run-classes.test | 2 +- test-data/unit/check-enum.test | 2 +- test-data/unit/check-unions.test | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/source/common_issues.rst b/docs/source/common_issues.rst index c4adc9b563bd6..9d0961894a7ef 100644 --- a/docs/source/common_issues.rst +++ b/docs/source/common_issues.rst @@ -607,7 +607,7 @@ method signature. E.g.: The third line elicits an error because mypy sees the argument type ``bytes`` as a reference to the method by that name. Other than -renaming the method, a work-around is to use an alias: +renaming the method, a workaround is to use an alias: .. code-block:: python diff --git a/docs/source/literal_types.rst b/docs/source/literal_types.rst index 2bca6db71ac79..8aad55c392e03 100644 --- a/docs/source/literal_types.rst +++ b/docs/source/literal_types.rst @@ -431,7 +431,7 @@ You can use enums to annotate types as you would expect: self.speed = speed Movement(Direction.up, 5.0) # ok - Movement('up', 5.0) # E: Argument 1 to "Movemement" has incompatible type "str"; expected "Direction" + Movement('up', 5.0) # E: Argument 1 to "Movement" has incompatible type "str"; expected "Direction" Exhaustiveness checking *********************** @@ -505,7 +505,7 @@ the same way Python's runtime does: left = 'left' right = 'right' -- All ``Enum`` fields are implictly ``final`` as well. +- All ``Enum`` fields are implicitly ``final`` as well. .. code-block:: python diff --git a/mypy/api.py b/mypy/api.py index f6e40b4fc3eca..28e8d835c7f8a 100644 --- a/mypy/api.py +++ b/mypy/api.py @@ -3,7 +3,7 @@ Since mypy still changes, the API was kept utterly simple and non-intrusive. It just mimics command line activation without starting a new interpreter. So the normal docs about the mypy command line apply. -Changes in the command line version of mypy will be immediately useable. +Changes in the command line version of mypy will be immediately usable. Just import this module and then call the 'run' function with a parameter of type List[str], containing what normally would have been the command line diff --git a/mypy/message_registry.py b/mypy/message_registry.py index 78fe07f70c92b..8b5452d5753d6 100644 --- a/mypy/message_registry.py +++ b/mypy/message_registry.py @@ -211,7 +211,7 @@ def format(self, *args: object, **kwargs: object) -> "ErrorMessage": # Enum ENUM_MEMBERS_ATTR_WILL_BE_OVERRIDEN: Final = ErrorMessage( - 'Assigned "__members__" will be overriden by "Enum" internally' + 'Assigned "__members__" will be overridden by "Enum" internally' ) # ClassVar diff --git a/mypyc/doc/introduction.rst b/mypyc/doc/introduction.rst index 547643a3705c3..874071bac23fd 100644 --- a/mypyc/doc/introduction.rst +++ b/mypyc/doc/introduction.rst @@ -139,7 +139,7 @@ Mypyc uses several techniques to produce fast code: * Mypyc treats compiled functions, classes, and attributes declared ``Final`` as immutable. -* Mypyc has memory-efficient, unboxed representions for integers and +* Mypyc has memory-efficient, unboxed representations for integers and booleans. Development status diff --git a/mypyc/test-data/run-classes.test b/mypyc/test-data/run-classes.test index 83838e1887625..e238c2b02284c 100644 --- a/mypyc/test-data/run-classes.test +++ b/mypyc/test-data/run-classes.test @@ -1816,7 +1816,7 @@ class B(A): def x(self, val : int) -> None: self._x = val + 1 -#Inerits base property setters and getters +# Inherits base property setters and getters class C(A): def __init__(self) -> None: A.__init__(self) diff --git a/test-data/unit/check-enum.test b/test-data/unit/check-enum.test index 2504e8e0e9c30..84ac3904772a7 100644 --- a/test-data/unit/check-enum.test +++ b/test-data/unit/check-enum.test @@ -2064,7 +2064,7 @@ import typing from enum import Enum class WritingMembers(Enum): - __members__: typing.Dict[Enum, Enum] = {} # E: Assigned "__members__" will be overriden by "Enum" internally + __members__: typing.Dict[Enum, Enum] = {} # E: Assigned "__members__" will be overridden by "Enum" internally class OnlyAnnotatedMembers(Enum): __members__: typing.Dict[Enum, Enum] diff --git a/test-data/unit/check-unions.test b/test-data/unit/check-unions.test index 63b090e5743c6..c3802a46ff41c 100644 --- a/test-data/unit/check-unions.test +++ b/test-data/unit/check-unions.test @@ -273,7 +273,7 @@ reveal_type(u(1, C())) # N: Revealed type is "Union[__main__.C, builtins.int]" reveal_type(u(1, a)) # N: Revealed type is "Union[Any, builtins.int]" reveal_type(u(a, 1)) # N: Revealed type is "Union[builtins.int, Any]" -# Any and base-class-Any, no simplificaiton +# Any and base-class-Any, no simplification reveal_type(u(C(), a)) # N: Revealed type is "Union[Any, __main__.C]" reveal_type(u(a, C())) # N: Revealed type is "Union[__main__.C, Any]" From 544d21a43762a526bdc53098a1fae87627d4a454 Mon Sep 17 00:00:00 2001 From: gresm <78505251+gresm@users.noreply.github.com> Date: Thu, 31 Mar 2022 02:29:19 +0200 Subject: [PATCH 210/377] Include link to PEP484 in README (#12492) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6b23ddb8a93a7..86a92df18d1d9 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,7 @@ Mypy can be integrated into popular IDEs: * Sublime Text: [SublimeLinter-contrib-mypy](https://github.com/fredcallaway/SublimeLinter-contrib-mypy) * Atom: [linter-mypy](https://atom.io/packages/linter-mypy) * PyCharm: [mypy plugin](https://github.com/dropbox/mypy-PyCharm-plugin) (PyCharm integrates - [its own implementation of PEP 484](https://www.jetbrains.com/help/pycharm/type-hinting-in-product.html)) + [its own implementation](https://www.jetbrains.com/help/pycharm/type-hinting-in-product.html) of [PEP 484](https://peps.python.org/pep-0484/)) * VS Code: provides [basic integration](https://code.visualstudio.com/docs/python/linting#_mypy) with mypy. * pre-commit: use [pre-commit mirrors-mypy](https://github.com/pre-commit/mirrors-mypy). From b44d2bc54ff0401eed8ff69afd03db6a09910140 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 31 Mar 2022 17:01:09 +0100 Subject: [PATCH 211/377] Refactoring: Remove the "erased" attribute of Instance (#12499) It's not used for anything. --- mypy/checkexpr.py | 5 ----- mypy/checkmember.py | 7 +------ mypy/expandtype.py | 8 ++------ mypy/types.py | 12 ++++-------- 4 files changed, 7 insertions(+), 25 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 4ece9ac4c94bf..2c0bf9656d060 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -3320,8 +3320,6 @@ def fast_container_type( vt = join.join_type_list(values) if not isinstance(vt, Instance): return None - # TODO: update tests instead? - vt.erased = True return self.chk.named_generic_type(container_fullname, [vt]) def check_lst_expr(self, items: List[Expression], fullname: str, @@ -3448,9 +3446,6 @@ def fast_dict_type(self, e: DictExpr) -> Optional[Type]: return None if stargs and (stargs[0] != kt or stargs[1] != vt): return None - # TODO: update tests instead? - kt.erased = True - vt.erased = True return self.chk.named_generic_type('builtins.dict', [kt, vt]) def visit_dict_expr(self, e: DictExpr) -> Type: diff --git a/mypy/checkmember.py b/mypy/checkmember.py index e7af3978867f4..16bd0e074c3f3 100644 --- a/mypy/checkmember.py +++ b/mypy/checkmember.py @@ -842,12 +842,7 @@ def analyze_enum_class_attribute_access(itype: Instance, return None enum_literal = LiteralType(name, fallback=itype) - # When we analyze enums, the corresponding Instance is always considered to be erased - # due to how the signature of Enum.__new__ is `(cls: Type[_T], value: object) -> _T` - # in typeshed. However, this is really more of an implementation detail of how Enums - # are typed, and we really don't want to treat every single Enum value as if it were - # from type variable substitution. So we reset the 'erased' field here. - return itype.copy_modified(erased=False, last_known_value=enum_literal) + return itype.copy_modified(last_known_value=enum_literal) def analyze_typeddict_access(name: str, typ: TypedDictType, diff --git a/mypy/expandtype.py b/mypy/expandtype.py index 7e1645b75645e..36cc83f439dd6 100644 --- a/mypy/expandtype.py +++ b/mypy/expandtype.py @@ -93,9 +93,7 @@ def visit_type_var(self, t: TypeVarType) -> Type: repl = get_proper_type(self.variables.get(t.id, t)) if isinstance(repl, Instance): inst = repl - # Return copy of instance with type erasure flag on. - return Instance(inst.type, inst.args, line=inst.line, - column=inst.column, erased=True) + return Instance(inst.type, inst.args, line=inst.line, column=inst.column) else: return repl @@ -103,9 +101,7 @@ def visit_param_spec(self, t: ParamSpecType) -> Type: repl = get_proper_type(self.variables.get(t.id, t)) if isinstance(repl, Instance): inst = repl - # Return copy of instance with type erasure flag on. - return Instance(inst.type, inst.args, line=inst.line, - column=inst.column, erased=True) + return Instance(inst.type, inst.args, line=inst.line, column=inst.column) elif isinstance(repl, ParamSpecType): return repl.with_flavor(t.flavor) else: diff --git a/mypy/types.py b/mypy/types.py index 9fc0c1831a010..465af1c50e337 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -1029,19 +1029,16 @@ def try_getting_instance_fallback(typ: ProperType) -> Optional[Instance]: """ - __slots__ = ('type', 'args', 'erased', 'invalid', 'type_ref', 'last_known_value') + __slots__ = ('type', 'args', 'invalid', 'type_ref', 'last_known_value') def __init__(self, typ: mypy.nodes.TypeInfo, args: Sequence[Type], - line: int = -1, column: int = -1, erased: bool = False, + line: int = -1, column: int = -1, *, last_known_value: Optional['LiteralType'] = None) -> None: super().__init__(line, column) self.type = typ self.args = tuple(args) self.type_ref: Optional[str] = None - # True if result of type variable substitution - self.erased = erased - # True if recovered after incorrect number of type arguments error self.invalid = False @@ -1137,15 +1134,14 @@ def deserialize(cls, data: Union[JsonDict, str]) -> 'Instance': def copy_modified(self, *, args: Bogus[List[Type]] = _dummy, - erased: Bogus[bool] = _dummy, last_known_value: Bogus[Optional['LiteralType']] = _dummy) -> 'Instance': return Instance( self.type, args if args is not _dummy else self.args, self.line, self.column, - erased if erased is not _dummy else self.erased, - last_known_value if last_known_value is not _dummy else self.last_known_value, + last_known_value=last_known_value if last_known_value is not _dummy + else self.last_known_value, ) def has_readable_member(self, name: str) -> bool: From 1c5073044f2266099e0b619687d007b522672eb0 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Sun, 3 Apr 2022 15:36:37 +0100 Subject: [PATCH 212/377] Fix minor docs inaccuracy: `NoneType` is exposed in the `types` module on Python 3.10+ (#12515) --- docs/source/kinds_of_types.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/source/kinds_of_types.rst b/docs/source/kinds_of_types.rst index 866535949d748..dd19d7fc06220 100644 --- a/docs/source/kinds_of_types.rst +++ b/docs/source/kinds_of_types.rst @@ -391,8 +391,9 @@ case you should add an explicit ``Optional[...]`` annotation (or type comment). The Python interpreter internally uses the name ``NoneType`` for the type of ``None``, but ``None`` is always used in type - annotations. The latter is shorter and reads better. (Besides, - ``NoneType`` is not even defined in the standard library.) + annotations. The latter is shorter and reads better. (``NoneType`` + is available as :py:data:`types.NoneType` on Python 3.10+, but is + not exposed at all on earlier versions of Python.) .. note:: From ee0638f3c3b68f5970cf8c2c643156c370017ee4 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Mon, 4 Apr 2022 04:34:05 +0100 Subject: [PATCH 213/377] [mypyc] Fix incorrect borrowed flag for setdefault() primitive (#12514) `CPyDict_SetDefaultWithNone` doesn't return a borrowed reference, since it just calls `CPyDict_SetDefault` which doesn't return a borrowed reference. --- mypyc/primitives/dict_ops.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mypyc/primitives/dict_ops.py b/mypyc/primitives/dict_ops.py index 4fe8693c66c54..c97d49d71d01b 100644 --- a/mypyc/primitives/dict_ops.py +++ b/mypyc/primitives/dict_ops.py @@ -140,7 +140,6 @@ arg_types=[dict_rprimitive, object_rprimitive], return_type=object_rprimitive, c_function_name='CPyDict_SetDefaultWithNone', - is_borrowed=True, error_kind=ERR_MAGIC) # dict.setdefault(key, empty tuple/list/set) From 0e8a03cb5c9954149da38096b496b7a74f74a1b0 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Tue, 5 Apr 2022 08:32:06 +0100 Subject: [PATCH 214/377] Implement boxed constant integers as literals (#12507) This avoids creating a new int object every time we evaluate an integer literal in a context that requires a boxed value. This speeds up this microbenchmark by about 60%: ``` def f() -> None: for j in range(1000 * 1000): a = [] for i in range(10): a.append(10) ``` In more realistic workloads the impact is hard to measure and is likely below the noise floor. --- mypyc/irbuild/ll_builder.py | 2 + mypyc/test-data/exceptions-freq.test | 3 +- mypyc/test-data/irbuild-basic.test | 69 +++++++++++----------- mypyc/test-data/irbuild-constant-fold.test | 12 ++-- mypyc/test-data/irbuild-dict.test | 23 ++++---- mypyc/test-data/irbuild-generics.test | 4 +- mypyc/test-data/irbuild-lists.test | 16 ++--- mypyc/test-data/irbuild-optional.test | 10 ++-- mypyc/test-data/irbuild-set.test | 52 ++++++++-------- mypyc/test-data/irbuild-statements.test | 38 ++++++------ mypyc/test-data/irbuild-strip-asserts.test | 3 +- mypyc/test-data/irbuild-tuple.test | 13 ++-- mypyc/test-data/refcount.test | 9 +-- 13 files changed, 130 insertions(+), 124 deletions(-) diff --git a/mypyc/irbuild/ll_builder.py b/mypyc/irbuild/ll_builder.py index 27419fcc7385e..98a69d92406d8 100644 --- a/mypyc/irbuild/ll_builder.py +++ b/mypyc/irbuild/ll_builder.py @@ -149,6 +149,8 @@ def self(self) -> Register: def box(self, src: Value) -> Value: if src.type.is_unboxed: + if isinstance(src, Integer) and is_tagged(src.type): + return self.add(LoadLiteral(src.value >> 1, rtype=object_rprimitive)) return self.add(Box(src)) else: return src diff --git a/mypyc/test-data/exceptions-freq.test b/mypyc/test-data/exceptions-freq.test index 26b690a995031..a655eed44d90e 100644 --- a/mypyc/test-data/exceptions-freq.test +++ b/mypyc/test-data/exceptions-freq.test @@ -85,7 +85,8 @@ def f(x): r1 :: bit r2 :: None L0: - r0 = box(short_int, 2) + r0 = object 1 + inc_ref r0 r1 = CPyList_SetItem(x, 0, r0) if not r1 goto L2 (error at f:3) else goto L1 :: bool L1: diff --git a/mypyc/test-data/irbuild-basic.test b/mypyc/test-data/irbuild-basic.test index 5aa5e25487c4b..ecce9248a4c8a 100644 --- a/mypyc/test-data/irbuild-basic.test +++ b/mypyc/test-data/irbuild-basic.test @@ -720,7 +720,7 @@ L0: r0 = builtins :: module r1 = 'print' r2 = CPyObject_GetAttr(r0, r1) - r3 = box(short_int, 10) + r3 = object 5 r4 = PyObject_CallFunctionObjArgs(r2, r3, 0) return 1 @@ -738,7 +738,7 @@ L0: r0 = builtins :: module r1 = 'print' r2 = CPyObject_GetAttr(r0, r1) - r3 = box(short_int, 10) + r3 = object 5 r4 = PyObject_CallFunctionObjArgs(r2, r3, 0) return 1 @@ -810,7 +810,7 @@ def g(y): L0: r0 = g(y) r1 = PyList_New(1) - r2 = box(short_int, 2) + r2 = object 1 r3 = get_element_ptr r1 ob_item :: PyListObject r4 = load_mem r3 :: ptr* set_mem r4, r2 :: builtins.object* @@ -838,7 +838,7 @@ def g(y): r7 :: bit r8, r9 :: object L0: - r0 = box(short_int, 2) + r0 = object 1 r1 = g(r0) r2 = PyList_New(1) r3 = get_element_ptr r2 ob_item :: PyListObject @@ -851,7 +851,7 @@ L0: r7 = CPyList_SetItem(a, 0, r6) r8 = box(bool, 1) y = r8 - r9 = box(short_int, 6) + r9 = object 3 return r9 [case testCoerceToObject2] @@ -869,7 +869,7 @@ def f(a, o): r2 :: int r3 :: object L0: - r0 = box(short_int, 2) + r0 = object 1 a.x = r0; r1 = is_error r2 = a.n r3 = box(int, r2) @@ -1204,7 +1204,7 @@ L0: r0 = load_address PyLong_Type r1 = 'base' r2 = PyTuple_Pack(1, x) - r3 = box(short_int, 4) + r3 = object 2 r4 = CPyDict_Build(1, r1, r3) r5 = PyObject_Call(r0, r2, r4) r6 = unbox(int, r5) @@ -1231,7 +1231,7 @@ L0: r0 = 'insert' r1 = CPyObject_GetAttr(xs, r0) r2 = 'x' - r3 = box(short_int, 0) + r3 = object 0 r4 = PyTuple_Pack(1, r3) r5 = box(int, first) r6 = CPyDict_Build(1, r2, r5) @@ -1242,7 +1242,7 @@ L0: r11 = 'i' r12 = PyTuple_Pack(0) r13 = box(int, second) - r14 = box(short_int, 2) + r14 = object 1 r15 = CPyDict_Build(2, r10, r13, r11, r14) r16 = PyObject_Call(r9, r12, r15) return xs @@ -1482,7 +1482,7 @@ L1: L2: r5 = __main__.globals :: static r6 = 'x' - r7 = box(short_int, 2) + r7 = object 1 r8 = CPyDict_SetItem(r5, r6, r7) r9 = r8 >= 0 :: signed r10 = __main__.globals :: static @@ -1516,7 +1516,7 @@ L0: r0 = m :: module r1 = 'f' r2 = CPyObject_GetAttr(r0, r1) - r3 = box(short_int, 2) + r3 = object 1 r4 = PyObject_CallFunctionObjArgs(r2, r3, 0) r5 = cast(str, r4) return r5 @@ -1545,7 +1545,7 @@ def main(): r1 :: union[int, str] r2, x :: int L0: - r0 = box(short_int, 0) + r0 = object 0 r1 = foo(r0) r2 = unbox(int, r1) x = r2 @@ -1598,7 +1598,7 @@ def main(): r1 :: __main__.A r2, x :: __main__.B L0: - r0 = box(short_int, 0) + r0 = object 0 r1 = foo(r0) r2 = cast(__main__.B, r1) x = r2 @@ -1713,7 +1713,7 @@ L0: r2 = 'f' r3 = CPyDict_GetItem(r1, r2) r4 = PyList_New(1) - r5 = box(short_int, 2) + r5 = object 1 r6 = get_element_ptr r4 ob_item :: PyListObject r7 = load_mem r6 :: ptr* set_mem r7, r5 :: builtins.object* @@ -1757,9 +1757,9 @@ L0: r0 = 'a' r1 = 'b' r2 = 'c' - r3 = box(short_int, 2) - r4 = box(short_int, 4) - r5 = box(short_int, 6) + r3 = object 1 + r4 = object 2 + r5 = object 3 r6 = CPyDict_Build(3, r0, r3, r1, r4, r2, r5) r7 = __main__.globals :: static r8 = 'f' @@ -1787,8 +1787,8 @@ def h(): L0: r0 = 'b' r1 = 'c' - r2 = box(short_int, 4) - r3 = box(short_int, 6) + r2 = object 2 + r3 = object 3 r4 = CPyDict_Build(2, r0, r2, r1, r3) r5 = __main__.globals :: static r6 = 'f' @@ -1796,7 +1796,7 @@ L0: r8 = PyDict_New() r9 = CPyDict_UpdateInDisplay(r8, r4) r10 = r9 >= 0 :: signed - r11 = box(short_int, 2) + r11 = object 1 r12 = PyTuple_Pack(1, r11) r13 = PyObject_Call(r7, r12, r8) r14 = unbox(tuple[int, int, int], r13) @@ -1913,9 +1913,9 @@ def f(): L0: r0 = PyList_New(0) r1 = PyList_New(3) - r2 = box(short_int, 2) - r3 = box(short_int, 4) - r4 = box(short_int, 6) + r2 = object 1 + r3 = object 2 + r4 = object 3 r5 = get_element_ptr r1 ob_item :: PyListObject r6 = load_mem r5 :: ptr* set_mem r6, r2 :: builtins.object* @@ -2012,9 +2012,9 @@ def f(): L0: r0 = PyDict_New() r1 = PyList_New(3) - r2 = box(short_int, 2) - r3 = box(short_int, 4) - r4 = box(short_int, 6) + r2 = object 1 + r3 = object 2 + r4 = object 3 r5 = get_element_ptr r1 ob_item :: PyListObject r6 = load_mem r5 :: ptr* set_mem r6, r2 :: builtins.object* @@ -2429,7 +2429,7 @@ def SubclassedTrait.boxed(self): self :: __main__.SubclassedTrait r0 :: object L0: - r0 = box(short_int, 6) + r0 = object 3 return r0 def DerivingObject.this(self): self :: __main__.DerivingObject @@ -2637,7 +2637,7 @@ L2: r57 = __main__.globals :: static r58 = 'Lol' r59 = CPyDict_GetItem(r57, r58) - r60 = box(short_int, 2) + r60 = object 1 r61 = PyObject_CallFunctionObjArgs(r59, r60, r56, 0) r62 = cast(tuple, r61) r63 = __main__.globals :: static @@ -2666,9 +2666,9 @@ L2: r86 = CPyDict_SetItem(r84, r85, r83) r87 = r86 >= 0 :: signed r88 = PyList_New(3) - r89 = box(short_int, 2) - r90 = box(short_int, 4) - r91 = box(short_int, 6) + r89 = object 1 + r90 = object 2 + r91 = object 3 r92 = get_element_ptr r88 ob_item :: PyListObject r93 = load_mem r92 :: ptr* set_mem r93, r89 :: builtins.object* @@ -3738,9 +3738,9 @@ def range_object(): r10 :: bit L0: r0 = load_address PyRange_Type - r1 = box(short_int, 8) - r2 = box(short_int, 24) - r3 = box(short_int, 4) + r1 = object 4 + r2 = object 12 + r3 = object 2 r4 = PyObject_CallFunctionObjArgs(r0, r1, r2, r3, 0) r5 = cast(range, r4) r = r5 @@ -3784,6 +3784,7 @@ L3: goto L1 L4: return 1 + [case testLocalRedefinition] # mypy: allow-redefinition def f() -> None: diff --git a/mypyc/test-data/irbuild-constant-fold.test b/mypyc/test-data/irbuild-constant-fold.test index 7c09021c27ecc..eab4df4e2b27b 100644 --- a/mypyc/test-data/irbuild-constant-fold.test +++ b/mypyc/test-data/irbuild-constant-fold.test @@ -145,13 +145,13 @@ def unsupported_div(): r4, r5, r6 :: object r7, y :: float L0: - r0 = box(short_int, 8) - r1 = box(short_int, 12) + r0 = object 4 + r1 = object 6 r2 = PyNumber_TrueDivide(r0, r1) r3 = cast(float, r2) x = r3 - r4 = box(short_int, 20) - r5 = box(short_int, 10) + r4 = object 10 + r5 = object 5 r6 = PyNumber_TrueDivide(r4, r5) r7 = cast(float, r6) y = r7 @@ -160,8 +160,8 @@ def unsupported_pow(): r0, r1, r2 :: object r3, p :: float L0: - r0 = box(short_int, 6) - r1 = box(short_int, -2) + r0 = object 3 + r1 = object -1 r2 = CPyNumber_Power(r0, r1) r3 = cast(float, r2) p = r3 diff --git a/mypyc/test-data/irbuild-dict.test b/mypyc/test-data/irbuild-dict.test index 089a9a02b0b04..3e2c295637ab5 100644 --- a/mypyc/test-data/irbuild-dict.test +++ b/mypyc/test-data/irbuild-dict.test @@ -8,7 +8,7 @@ def f(d): r0, r1 :: object r2 :: bool L0: - r0 = box(short_int, 0) + r0 = object 0 r1 = CPyDict_GetItem(d, r0) r2 = unbox(bool, r1) return r2 @@ -24,7 +24,7 @@ def f(d): r2 :: int32 r3 :: bit L0: - r0 = box(short_int, 0) + r0 = object 0 r1 = box(bool, 0) r2 = CPyDict_SetItem(d, r0, r1) r3 = r2 >= 0 :: signed @@ -66,8 +66,8 @@ def f(x): r3, d :: dict L0: r0 = '' - r1 = box(short_int, 2) - r2 = box(short_int, 4) + r1 = object 1 + r2 = object 2 r3 = CPyDict_Build(2, r1, r2, r0, x) d = r3 return 1 @@ -87,7 +87,7 @@ def f(d): r2 :: bit r3 :: bool L0: - r0 = box(short_int, 8) + r0 = object 4 r1 = PyDict_Contains(d, r0) r2 = r1 >= 0 :: signed r3 = truncate r1: int32 to builtins.bool @@ -114,7 +114,7 @@ def f(d): r2 :: bit r3, r4 :: bool L0: - r0 = box(short_int, 8) + r0 = object 4 r1 = PyDict_Contains(d, r0) r2 = r1 >= 0 :: signed r3 = truncate r1: int32 to builtins.bool @@ -178,7 +178,7 @@ L2: r8 = cast(str, r7) k = r8 r9 = CPyDict_GetItem(d, k) - r10 = box(short_int, 2) + r10 = object 1 r11 = PyNumber_InPlaceAdd(r9, r10) r12 = CPyDict_SetItem(d, k, r11) r13 = r12 >= 0 :: signed @@ -208,11 +208,11 @@ def f(x, y): r7 :: bit L0: r0 = 'z' - r1 = box(short_int, 4) + r1 = object 2 r2 = CPyDict_Build(1, x, r1) r3 = CPyDict_UpdateInDisplay(r2, y) r4 = r3 >= 0 :: signed - r5 = box(short_int, 6) + r5 = object 3 r6 = CPyDict_SetItem(r2, r0, r5) r7 = r6 >= 0 :: signed return r2 @@ -423,7 +423,7 @@ L1: L2: r2 = 'a' r3 = PyList_New(1) - r4 = box(short_int, 2) + r4 = object 1 r5 = get_element_ptr r3 ob_item :: PyListObject r6 = load_mem r5 :: ptr* set_mem r6, r4 :: builtins.object* @@ -451,10 +451,11 @@ L1: L2: r2 = 'a' r3 = 'c' - r4 = box(short_int, 2) + r4 = object 1 r5 = CPyDict_Build(1, r3, r4) r6 = CPyDict_SetDefault(d, r2, r5) return r6 L3: r7 = box(None, 1) return r7 + diff --git a/mypyc/test-data/irbuild-generics.test b/mypyc/test-data/irbuild-generics.test index 6ec8eb58fe7d1..10f8e737d6392 100644 --- a/mypyc/test-data/irbuild-generics.test +++ b/mypyc/test-data/irbuild-generics.test @@ -60,7 +60,7 @@ def f(): L0: r0 = C() c = r0 - r1 = box(short_int, 2) + r1 = object 1 c.x = r1; r2 = is_error r3 = c.x r4 = unbox(int, r3) @@ -118,7 +118,7 @@ L0: r2 = CPyTagged_Add(y, 2) r3 = box(int, r2) r4 = x.set(r3) - r5 = box(short_int, 4) + r5 = object 2 r6 = C(r5) x = r6 return 1 diff --git a/mypyc/test-data/irbuild-lists.test b/mypyc/test-data/irbuild-lists.test index 0d29f256cc597..3173469c8db6f 100644 --- a/mypyc/test-data/irbuild-lists.test +++ b/mypyc/test-data/irbuild-lists.test @@ -54,7 +54,7 @@ def f(x): r0 :: object r1 :: bit L0: - r0 = box(short_int, 2) + r0 = object 1 r1 = CPyList_SetItem(x, 0, r0) return 1 @@ -95,8 +95,8 @@ def f(): x :: list L0: r0 = PyList_New(2) - r1 = box(short_int, 2) - r2 = box(short_int, 4) + r1 = object 1 + r2 = object 2 r3 = get_element_ptr r0 ob_item :: PyListObject r4 = load_mem r3 :: ptr* set_mem r4, r1 :: builtins.object* @@ -145,7 +145,7 @@ L0: r0 = CPySequence_Multiply(a, 4) b = r0 r1 = PyList_New(1) - r2 = box(short_int, 8) + r2 = object 4 r3 = get_element_ptr r1 ob_item :: PyListObject r4 = load_mem r3 :: ptr* set_mem r4, r2 :: builtins.object* @@ -217,7 +217,7 @@ L1: if r4 goto L2 else goto L4 :: bool L2: r5 = CPyList_GetItem(l, i) - r6 = box(short_int, 2) + r6 = object 1 r7 = PyNumber_InPlaceAdd(r5, r6) r8 = CPyList_SetItem(l, i, r7) L3: @@ -242,8 +242,8 @@ def f(x, y): r10 :: bit L0: r0 = PyList_New(2) - r1 = box(short_int, 2) - r2 = box(short_int, 4) + r1 = object 1 + r2 = object 2 r3 = get_element_ptr r0 ob_item :: PyListObject r4 = load_mem r3 :: ptr* set_mem r4, r1 :: builtins.object* @@ -252,7 +252,7 @@ L0: keep_alive r0 r6 = CPyList_Extend(r0, x) r7 = CPyList_Extend(r0, y) - r8 = box(short_int, 6) + r8 = object 3 r9 = PyList_Append(r0, r8) r10 = r9 >= 0 :: signed return r0 diff --git a/mypyc/test-data/irbuild-optional.test b/mypyc/test-data/irbuild-optional.test index bed07154db937..cc8653ee3e822 100644 --- a/mypyc/test-data/irbuild-optional.test +++ b/mypyc/test-data/irbuild-optional.test @@ -142,11 +142,11 @@ L0: r1 = A() x = r1 x = y - r2 = box(short_int, 2) + r2 = object 1 z = r2 r3 = A() a = r3 - r4 = box(short_int, 2) + r4 = object 1 a.a = r4; r5 = is_error r6 = box(None, 1) a.a = r6; r7 = is_error @@ -166,7 +166,7 @@ def f(x): r2 :: object r3 :: bit L0: - r0 = box(short_int, 0) + r0 = object 0 r1 = CPyList_SetItem(x, 0, r0) r2 = box(None, 1) r3 = CPyList_SetItem(x, 2, r2) @@ -417,13 +417,13 @@ L2: if r11 goto L3 else goto L4 :: bool L3: r12 = cast(__main__.B, o) - r13 = box(short_int, 2) + r13 = object 1 r14 = r12.f(r13) r7 = r14 goto L5 L4: r15 = cast(__main__.C, o) - r16 = box(short_int, 2) + r16 = object 1 r17 = r15.f(r16) r18 = box(int, r17) r7 = r18 diff --git a/mypyc/test-data/irbuild-set.test b/mypyc/test-data/irbuild-set.test index f620039b76557..fec76751c9154 100644 --- a/mypyc/test-data/irbuild-set.test +++ b/mypyc/test-data/irbuild-set.test @@ -16,13 +16,13 @@ def f(): r9 :: bit L0: r0 = PySet_New(0) - r1 = box(short_int, 2) + r1 = object 1 r2 = PySet_Add(r0, r1) r3 = r2 >= 0 :: signed - r4 = box(short_int, 4) + r4 = object 2 r5 = PySet_Add(r0, r4) r6 = r5 >= 0 :: signed - r7 = box(short_int, 6) + r7 = object 3 r8 = PySet_Add(r0, r7) r9 = r8 >= 0 :: signed return r0 @@ -96,9 +96,9 @@ def test1(): a :: set L0: r0 = PyList_New(3) - r1 = box(short_int, 2) - r2 = box(short_int, 6) - r3 = box(short_int, 10) + r1 = object 1 + r2 = object 3 + r3 = object 5 r4 = get_element_ptr r0 ob_item :: PyListObject r5 = load_mem r4 :: ptr* set_mem r5, r1 :: builtins.object* @@ -186,9 +186,9 @@ L0: r0 = '1' r1 = '3' r2 = '5' - r3 = box(short_int, 2) - r4 = box(short_int, 6) - r5 = box(short_int, 10) + r3 = object 1 + r4 = object 3 + r5 = object 5 r6 = CPyDict_Build(3, r3, r0, r4, r1, r5, r2) tmp_dict = r6 r7 = PySet_New(0) @@ -347,11 +347,11 @@ def test(): a :: set L0: r0 = PyList_New(5) - r1 = box(short_int, 2) - r2 = box(short_int, 4) - r3 = box(short_int, 6) - r4 = box(short_int, 8) - r5 = box(short_int, 10) + r1 = object 1 + r2 = object 2 + r3 = object 3 + r4 = object 4 + r5 = object 5 r6 = get_element_ptr r0 ob_item :: PyListObject r7 = load_mem r6 :: ptr* set_mem r7, r1 :: builtins.object* @@ -465,13 +465,13 @@ def f(): r12 :: short_int L0: r0 = PySet_New(0) - r1 = box(short_int, 2) + r1 = object 1 r2 = PySet_Add(r0, r1) r3 = r2 >= 0 :: signed - r4 = box(short_int, 4) + r4 = object 2 r5 = PySet_Add(r0, r4) r6 = r5 >= 0 :: signed - r7 = box(short_int, 6) + r7 = object 3 r8 = PySet_Add(r0, r7) r9 = r8 >= 0 :: signed r10 = get_element_ptr r0 used :: PySetObject @@ -501,14 +501,14 @@ def f(): r10 :: bool L0: r0 = PySet_New(0) - r1 = box(short_int, 6) + r1 = object 3 r2 = PySet_Add(r0, r1) r3 = r2 >= 0 :: signed - r4 = box(short_int, 8) + r4 = object 4 r5 = PySet_Add(r0, r4) r6 = r5 >= 0 :: signed x = r0 - r7 = box(short_int, 10) + r7 = object 5 r8 = PySet_Contains(x, r7) r9 = r8 >= 0 :: signed r10 = truncate r8: int32 to builtins.bool @@ -528,7 +528,7 @@ def f(): L0: r0 = PySet_New(0) x = r0 - r1 = box(short_int, 2) + r1 = object 1 r2 = CPySet_Remove(x, r1) return x @@ -547,7 +547,7 @@ def f(): L0: r0 = PySet_New(0) x = r0 - r1 = box(short_int, 2) + r1 = object 1 r2 = PySet_Discard(x, r1) r3 = r2 >= 0 :: signed return x @@ -567,7 +567,7 @@ def f(): L0: r0 = PySet_New(0) x = r0 - r1 = box(short_int, 2) + r1 = object 1 r2 = PySet_Add(x, r1) r3 = r2 >= 0 :: signed return x @@ -641,17 +641,17 @@ def f(x, y): r13 :: bit L0: r0 = PySet_New(0) - r1 = box(short_int, 2) + r1 = object 1 r2 = PySet_Add(r0, r1) r3 = r2 >= 0 :: signed - r4 = box(short_int, 4) + r4 = object 2 r5 = PySet_Add(r0, r4) r6 = r5 >= 0 :: signed r7 = _PySet_Update(r0, x) r8 = r7 >= 0 :: signed r9 = _PySet_Update(r0, y) r10 = r9 >= 0 :: signed - r11 = box(short_int, 6) + r11 = object 3 r12 = PySet_Add(r0, r11) r13 = r12 >= 0 :: signed return r0 diff --git a/mypyc/test-data/irbuild-statements.test b/mypyc/test-data/irbuild-statements.test index 8b85e494b07db..98a6fa2403595 100644 --- a/mypyc/test-data/irbuild-statements.test +++ b/mypyc/test-data/irbuild-statements.test @@ -760,8 +760,8 @@ def delList(): r8 :: bit L0: r0 = PyList_New(2) - r1 = box(short_int, 2) - r2 = box(short_int, 4) + r1 = object 1 + r2 = object 2 r3 = get_element_ptr r0 ob_item :: PyListObject r4 = load_mem r3 :: ptr* set_mem r4, r1 :: builtins.object* @@ -769,7 +769,7 @@ L0: set_mem r5, r2 :: builtins.object* keep_alive r0 l = r0 - r6 = box(short_int, 2) + r6 = object 1 r7 = PyObject_DelItem(l, r6) r8 = r7 >= 0 :: signed return 1 @@ -789,13 +789,13 @@ def delListMultiple(): r24 :: bit L0: r0 = PyList_New(7) - r1 = box(short_int, 2) - r2 = box(short_int, 4) - r3 = box(short_int, 6) - r4 = box(short_int, 8) - r5 = box(short_int, 10) - r6 = box(short_int, 12) - r7 = box(short_int, 14) + r1 = object 1 + r2 = object 2 + r3 = object 3 + r4 = object 4 + r5 = object 5 + r6 = object 6 + r7 = object 7 r8 = get_element_ptr r0 ob_item :: PyListObject r9 = load_mem r8 :: ptr* set_mem r9, r1 :: builtins.object* @@ -813,13 +813,13 @@ L0: set_mem r15, r7 :: builtins.object* keep_alive r0 l = r0 - r16 = box(short_int, 2) + r16 = object 1 r17 = PyObject_DelItem(l, r16) r18 = r17 >= 0 :: signed - r19 = box(short_int, 4) + r19 = object 2 r20 = PyObject_DelItem(l, r19) r21 = r20 >= 0 :: signed - r22 = box(short_int, 6) + r22 = object 3 r23 = PyObject_DelItem(l, r22) r24 = r23 >= 0 :: signed return 1 @@ -842,8 +842,8 @@ def delDict(): L0: r0 = 'one' r1 = 'two' - r2 = box(short_int, 2) - r3 = box(short_int, 4) + r2 = object 1 + r3 = object 2 r4 = CPyDict_Build(2, r0, r2, r1, r3) d = r4 r5 = 'one' @@ -864,10 +864,10 @@ L0: r1 = 'two' r2 = 'three' r3 = 'four' - r4 = box(short_int, 2) - r5 = box(short_int, 4) - r6 = box(short_int, 6) - r7 = box(short_int, 8) + r4 = object 1 + r5 = object 2 + r6 = object 3 + r7 = object 4 r8 = CPyDict_Build(4, r0, r4, r1, r5, r2, r6, r3, r7) d = r8 r9 = 'one' diff --git a/mypyc/test-data/irbuild-strip-asserts.test b/mypyc/test-data/irbuild-strip-asserts.test index 5772fc8911fe4..e90905dc5d814 100644 --- a/mypyc/test-data/irbuild-strip-asserts.test +++ b/mypyc/test-data/irbuild-strip-asserts.test @@ -7,6 +7,7 @@ def g(): def g(): r0, x :: object L0: - r0 = box(short_int, 6) + r0 = object 3 x = r0 return x + diff --git a/mypyc/test-data/irbuild-tuple.test b/mypyc/test-data/irbuild-tuple.test index 564a4bf74d506..6a86a6c6781b9 100644 --- a/mypyc/test-data/irbuild-tuple.test +++ b/mypyc/test-data/irbuild-tuple.test @@ -108,8 +108,8 @@ def f(x, y): r11 :: tuple L0: r0 = PyList_New(2) - r1 = box(short_int, 2) - r2 = box(short_int, 4) + r1 = object 1 + r2 = object 2 r3 = get_element_ptr r0 ob_item :: PyListObject r4 = load_mem r3 :: ptr* set_mem r4, r1 :: builtins.object* @@ -118,7 +118,7 @@ L0: keep_alive r0 r6 = CPyList_Extend(r0, x) r7 = CPyList_Extend(r0, y) - r8 = box(short_int, 6) + r8 = object 3 r9 = PyList_Append(r0, r8) r10 = r9 >= 0 :: signed r11 = PyList_AsTuple(r0) @@ -310,9 +310,9 @@ def test(): a :: tuple L0: r0 = PyList_New(3) - r1 = box(short_int, 2) - r2 = box(short_int, 4) - r3 = box(short_int, 6) + r1 = object 1 + r2 = object 2 + r3 = object 3 r4 = get_element_ptr r0 ob_item :: PyListObject r5 = load_mem r4 :: ptr* set_mem r5, r1 :: builtins.object* @@ -349,7 +349,6 @@ L4: a = r10 return 1 - [case testTupleBuiltFromStr] def f2(val: str) -> str: return val + "f2" diff --git a/mypyc/test-data/refcount.test b/mypyc/test-data/refcount.test index c48ae1acce098..909251741a303 100644 --- a/mypyc/test-data/refcount.test +++ b/mypyc/test-data/refcount.test @@ -548,12 +548,14 @@ def f(): a :: list L0: r0 = PyList_New(2) - r1 = box(short_int, 0) - r2 = box(short_int, 2) + r1 = object 0 + r2 = object 1 r3 = get_element_ptr r0 ob_item :: PyListObject r4 = load_mem r3 :: ptr* + inc_ref r1 set_mem r4, r1 :: builtins.object* r5 = r4 + WORD_SIZE*1 + inc_ref r2 set_mem r5, r2 :: builtins.object* a = r0 dec_ref a @@ -682,9 +684,8 @@ L0: r0 = load_address PyLong_Type r1 = 'base' r2 = PyTuple_Pack(1, x) - r3 = box(short_int, 4) + r3 = object 2 r4 = CPyDict_Build(1, r1, r3) - dec_ref r3 r5 = PyObject_Call(r0, r2, r4) dec_ref r2 dec_ref r4 From 4ff8d0425618d19ba99b562389fb26e914ea100e Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Tue, 5 Apr 2022 09:23:53 +0100 Subject: [PATCH 215/377] Fix union simplification performance regression (#12519) #11962 can generate large unions with many Instance types with last_known_value set. This caused our union simplification algorithm to be extremely slow, as it hit an O(n**2) code path. We already had a fast code path for unions of regular literal types. This generalizes it for unions containing Instance types with last known values (which behave similarly to literals in a literal type context). Also fix a union simplification bug that I encountered while writing tests for this change. Work on #12408. --- mypy/test/testtypes.py | 39 +++++++++++++++++++++++++++++++ mypy/test/typefixture.py | 9 ++++++++ mypy/typeops.py | 50 ++++++++++++++++++++++++---------------- 3 files changed, 78 insertions(+), 20 deletions(-) diff --git a/mypy/test/testtypes.py b/mypy/test/testtypes.py index 6af1c18145cfe..923e39571ad94 100644 --- a/mypy/test/testtypes.py +++ b/mypy/test/testtypes.py @@ -465,7 +465,12 @@ def test_simplified_union(self) -> None: self.assert_simplified_union([fx.a, UnionType([fx.a])], fx.a) self.assert_simplified_union([fx.b, UnionType([fx.c, UnionType([fx.d])])], UnionType([fx.b, fx.c, fx.d])) + + def test_simplified_union_with_literals(self) -> None: + fx = self.fx + self.assert_simplified_union([fx.lit1, fx.a], fx.a) + self.assert_simplified_union([fx.lit1, fx.lit2, fx.a], fx.a) self.assert_simplified_union([fx.lit1, fx.lit1], fx.lit1) self.assert_simplified_union([fx.lit1, fx.lit2], UnionType([fx.lit1, fx.lit2])) self.assert_simplified_union([fx.lit1, fx.lit3], UnionType([fx.lit1, fx.lit3])) @@ -481,6 +486,40 @@ def test_simplified_union(self) -> None: self.assert_simplified_union([fx.lit1, fx.lit2_inst], UnionType([fx.lit1, fx.lit2_inst])) self.assert_simplified_union([fx.lit1, fx.lit3_inst], UnionType([fx.lit1, fx.lit3_inst])) + def test_simplified_union_with_str_literals(self) -> None: + fx = self.fx + + self.assert_simplified_union([fx.lit_str1, fx.lit_str2, fx.str_type], fx.str_type) + self.assert_simplified_union([fx.lit_str1, fx.lit_str1, fx.lit_str1], fx.lit_str1) + self.assert_simplified_union([fx.lit_str1, fx.lit_str2, fx.lit_str3], + UnionType([fx.lit_str1, fx.lit_str2, fx.lit_str3])) + self.assert_simplified_union([fx.lit_str1, fx.lit_str2, fx.uninhabited], + UnionType([fx.lit_str1, fx.lit_str2])) + + def test_simplified_union_with_str_instance_literals(self) -> None: + fx = self.fx + + self.assert_simplified_union([fx.lit_str1_inst, fx.lit_str2_inst, fx.str_type], + fx.str_type) + self.assert_simplified_union([fx.lit_str1_inst, fx.lit_str1_inst, fx.lit_str1_inst], + fx.lit_str1_inst) + self.assert_simplified_union([fx.lit_str1_inst, fx.lit_str2_inst, fx.lit_str3_inst], + UnionType([fx.lit_str1_inst, + fx.lit_str2_inst, + fx.lit_str3_inst])) + self.assert_simplified_union([fx.lit_str1_inst, fx.lit_str2_inst, fx.uninhabited], + UnionType([fx.lit_str1_inst, fx.lit_str2_inst])) + + def test_simplified_union_with_mixed_str_literals(self) -> None: + fx = self.fx + + self.assert_simplified_union([fx.lit_str1, fx.lit_str2, fx.lit_str3_inst], + UnionType([fx.lit_str1, + fx.lit_str2, + fx.lit_str3_inst])) + self.assert_simplified_union([fx.lit_str1, fx.lit_str1, fx.lit_str1_inst], + UnionType([fx.lit_str1, fx.lit_str1_inst])) + def assert_simplified_union(self, original: List[Type], union: Type) -> None: assert_equal(make_simplified_union(original), union) assert_equal(make_simplified_union(list(reversed(original))), union) diff --git a/mypy/test/typefixture.py b/mypy/test/typefixture.py index 7d4faeccf432b..c8bbf67510a65 100644 --- a/mypy/test/typefixture.py +++ b/mypy/test/typefixture.py @@ -65,6 +65,7 @@ def make_type_var(name: str, id: int, values: List[Type], upper_bound: Type, variances=[COVARIANT]) # class tuple self.type_typei = self.make_type_info('builtins.type') # class type self.bool_type_info = self.make_type_info('builtins.bool') + self.str_type_info = self.make_type_info('builtins.str') self.functioni = self.make_type_info('builtins.function') # function TODO self.ai = self.make_type_info('A', mro=[self.oi]) # class A self.bi = self.make_type_info('B', mro=[self.ai, self.oi]) # class B(A) @@ -109,6 +110,7 @@ def make_type_var(name: str, id: int, values: List[Type], upper_bound: Type, self.std_tuple = Instance(self.std_tuplei, [self.anyt]) # tuple self.type_type = Instance(self.type_typei, []) # type self.function = Instance(self.functioni, []) # function TODO + self.str_type = Instance(self.str_type_info, []) self.a = Instance(self.ai, []) # A self.b = Instance(self.bi, []) # B self.c = Instance(self.ci, []) # C @@ -163,6 +165,13 @@ def make_type_var(name: str, id: int, values: List[Type], upper_bound: Type, self.lit3_inst = Instance(self.di, [], last_known_value=self.lit3) self.lit4_inst = Instance(self.ai, [], last_known_value=self.lit4) + self.lit_str1 = LiteralType("x", self.str_type) + self.lit_str2 = LiteralType("y", self.str_type) + self.lit_str3 = LiteralType("z", self.str_type) + self.lit_str1_inst = Instance(self.str_type_info, [], last_known_value=self.lit_str1) + self.lit_str2_inst = Instance(self.str_type_info, [], last_known_value=self.lit_str2) + self.lit_str3_inst = Instance(self.str_type_info, [], last_known_value=self.lit_str3) + self.type_a = TypeType.make_normalized(self.a) self.type_b = TypeType.make_normalized(self.b) self.type_c = TypeType.make_normalized(self.c) diff --git a/mypy/typeops.py b/mypy/typeops.py index 007a54e17b95e..fa05231109414 100644 --- a/mypy/typeops.py +++ b/mypy/typeops.py @@ -299,15 +299,23 @@ def callable_corresponding_argument(typ: CallableType, return by_name if by_name is not None else by_pos -def is_simple_literal(t: ProperType) -> bool: - """ - Whether a type is a simple enough literal to allow for fast Union simplification +def simple_literal_value_key(t: ProperType) -> Optional[Tuple[str, ...]]: + """Return a hashable description of simple literal type. + + Return None if not a simple literal type. - For now this means enum or string + The return value can be used to simplify away duplicate types in + unions by comparing keys for equality. For now enum, string or + Instance with string last_known_value are supported. """ - return isinstance(t, LiteralType) and ( - t.fallback.type.is_enum or t.fallback.type.fullname == 'builtins.str' - ) + if isinstance(t, LiteralType): + if t.fallback.type.is_enum or t.fallback.type.fullname == 'builtins.str': + assert isinstance(t.value, str) + return 'literal', t.value, t.fallback.type.fullname + if isinstance(t, Instance): + if t.last_known_value is not None and isinstance(t.last_known_value.value, str): + return 'instance', t.last_known_value.value, t.type.fullname + return None def make_simplified_union(items: Sequence[Type], @@ -341,10 +349,20 @@ def make_simplified_union(items: Sequence[Type], all_items.append(typ) items = all_items + simplified_set = _remove_redundant_union_items(items, keep_erased) + + # If more than one literal exists in the union, try to simplify + if (contract_literals and sum(isinstance(item, LiteralType) for item in simplified_set) > 1): + simplified_set = try_contracting_literals_in_union(simplified_set) + + return UnionType.make_union(simplified_set, line, column) + + +def _remove_redundant_union_items(items: List[ProperType], keep_erased: bool) -> List[ProperType]: from mypy.subtypes import is_proper_subtype removed: Set[int] = set() - seen: Set[Tuple[str, str]] = set() + seen: Set[Tuple[str, ...]] = set() # NB: having a separate fast path for Union of Literal and slow path for other things # would arguably be cleaner, however it breaks down when simplifying the Union of two @@ -354,10 +372,8 @@ def make_simplified_union(items: Sequence[Type], if i in removed: continue # Avoid slow nested for loop for Union of Literal of strings/enums (issue #9169) - if is_simple_literal(item): - assert isinstance(item, LiteralType) - assert isinstance(item.value, str) - k = (item.value, item.fallback.type.fullname) + k = simple_literal_value_key(item) + if k is not None: if k in seen: removed.add(i) continue @@ -373,13 +389,13 @@ def make_simplified_union(items: Sequence[Type], seen.add(k) if safe_skip: continue + # Keep track of the truishness info for deleted subtypes which can be relevant cbt = cbf = False for j, tj in enumerate(items): # NB: we don't need to check literals as the fast path above takes care of that if ( i != j - and not is_simple_literal(tj) and is_proper_subtype(tj, item, keep_erased_types=keep_erased) and is_redundant_literal_instance(item, tj) # XXX? ): @@ -393,13 +409,7 @@ def make_simplified_union(items: Sequence[Type], elif not item.can_be_false and cbf: items[i] = true_or_false(item) - simplified_set = [items[i] for i in range(len(items)) if i not in removed] - - # If more than one literal exists in the union, try to simplify - if (contract_literals and sum(isinstance(item, LiteralType) for item in simplified_set) > 1): - simplified_set = try_contracting_literals_in_union(simplified_set) - - return UnionType.make_union(simplified_set, line, column) + return [items[i] for i in range(len(items)) if i not in removed] def _get_type_special_method_bool_ret_type(t: Type) -> Optional[Type]: From 07d88787774fabbd3108d18621b30df9b42e7c83 Mon Sep 17 00:00:00 2001 From: EXPLOSION Date: Thu, 7 Apr 2022 19:05:36 +0900 Subject: [PATCH 216/377] Basic ParamSpec Concatenate and literal support (#11847) This PR adds a new Parameters proper type to represent ParamSpec parameters (more about this in the PR), along with supporting the Concatenate operator. Closes #11833 Closes #12276 Closes #12257 Refs #8645 External ref python/typeshed#4827 Co-authored-by: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Co-authored-by: Marc Mueller <30130371+cdce8p@users.noreply.github.com> --- docs/source/config_file.rst | 7 + mypy/applytype.py | 4 +- mypy/checker.py | 3 +- mypy/checkexpr.py | 2 +- mypy/constraints.py | 82 ++- mypy/erasetype.py | 5 +- mypy/expandtype.py | 48 +- mypy/fixup.py | 7 +- mypy/indirection.py | 3 + mypy/join.py | 8 +- mypy/main.py | 4 + mypy/meet.py | 13 +- mypy/messages.py | 108 ++- mypy/nodes.py | 18 +- mypy/options.py | 4 + mypy/sametypes.py | 8 +- mypy/semanal.py | 44 +- mypy/server/astdiff.py | 8 +- mypy/server/astmerge.py | 6 +- mypy/server/deps.py | 8 +- mypy/subtypes.py | 107 ++- mypy/type_visitor.py | 12 +- mypy/typeanal.py | 171 ++++- mypy/typeops.py | 6 +- mypy/types.py | 285 +++++++- mypy/typetraverser.py | 5 +- .../unit/check-parameter-specification.test | 618 +++++++++++++++++- 27 files changed, 1473 insertions(+), 121 deletions(-) diff --git a/docs/source/config_file.rst b/docs/source/config_file.rst index 5cfc5f86e37f1..22893ff069d5f 100644 --- a/docs/source/config_file.rst +++ b/docs/source/config_file.rst @@ -676,6 +676,13 @@ section of the command line docs. from foo import bar __all__ = ['bar'] +.. confval:: strict_concatenate + + :type: boolean + :default: False + + Make arguments prepended via ``Concatenate`` be truly positional-only. + .. confval:: strict_equality :type: boolean diff --git a/mypy/applytype.py b/mypy/applytype.py index 5b803a4aaa0b4..a967d834f1a2e 100644 --- a/mypy/applytype.py +++ b/mypy/applytype.py @@ -5,7 +5,7 @@ from mypy.expandtype import expand_type from mypy.types import ( Type, TypeVarId, TypeVarType, CallableType, AnyType, PartialType, get_proper_types, - TypeVarLikeType, ProperType, ParamSpecType, get_proper_type + TypeVarLikeType, ProperType, ParamSpecType, Parameters, get_proper_type ) from mypy.nodes import Context @@ -94,7 +94,7 @@ def apply_generic_arguments( nt = id_to_type.get(param_spec.id) if nt is not None: nt = get_proper_type(nt) - if isinstance(nt, CallableType): + if isinstance(nt, CallableType) or isinstance(nt, Parameters): callable = callable.expand_param_spec(nt) # Apply arguments to argument types. diff --git a/mypy/checker.py b/mypy/checker.py index a02a877a808fe..d0f6922fdf5e2 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -5224,7 +5224,7 @@ def check_subtype(self, code: Optional[ErrorCode] = None, outer_context: Optional[Context] = None) -> bool: """Generate an error if the subtype is not compatible with supertype.""" - if is_subtype(subtype, supertype): + if is_subtype(subtype, supertype, options=self.options): return True if isinstance(msg, ErrorMessage): @@ -5260,6 +5260,7 @@ def check_subtype(self, self.msg.note(note, context, code=code) if note_msg: self.note(note_msg, context, code=code) + self.msg.maybe_note_concatenate_pos_args(subtype, supertype, context, code=code) if (isinstance(supertype, Instance) and supertype.type.is_protocol and isinstance(subtype, (Instance, TupleType, TypedDictType))): self.msg.report_protocol_problems(subtype, supertype, context, code=code) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 2c0bf9656d060..45d5818d4eeba 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -1556,7 +1556,7 @@ def check_arg(self, isinstance(callee_type.item, Instance) and (callee_type.item.type.is_abstract or callee_type.item.type.is_protocol)): self.msg.concrete_only_call(callee_type, context) - elif not is_subtype(caller_type, callee_type): + elif not is_subtype(caller_type, callee_type, options=self.chk.options): if self.chk.should_suppress_optional_error([caller_type, callee_type]): return code = messages.incompatible_argument(n, diff --git a/mypy/constraints.py b/mypy/constraints.py index 8a05b527b6bd2..0b2217b21ae0c 100644 --- a/mypy/constraints.py +++ b/mypy/constraints.py @@ -8,7 +8,7 @@ TupleType, TypedDictType, UnionType, Overloaded, ErasedType, PartialType, DeletedType, UninhabitedType, TypeType, TypeVarId, TypeQuery, is_named_instance, TypeOfAny, LiteralType, ProperType, ParamSpecType, get_proper_type, TypeAliasType, is_union_with_any, - UnpackType, callable_with_ellipsis, TUPLE_LIKE_INSTANCE_NAMES, + UnpackType, callable_with_ellipsis, Parameters, TUPLE_LIKE_INSTANCE_NAMES, ) from mypy.maptype import map_instance_to_supertype import mypy.subtypes @@ -406,6 +406,9 @@ def visit_param_spec(self, template: ParamSpecType) -> List[Constraint]: def visit_unpack_type(self, template: UnpackType) -> List[Constraint]: raise NotImplementedError + def visit_parameters(self, template: Parameters) -> List[Constraint]: + raise RuntimeError("Parameters cannot be constrained to") + # Non-leaf types def visit_instance(self, template: Instance) -> List[Constraint]: @@ -446,7 +449,7 @@ def visit_instance(self, template: Instance) -> List[Constraint]: # N.B: We use zip instead of indexing because the lengths might have # mismatches during daemon reprocessing. for tvar, mapped_arg, instance_arg in zip(tvars, mapped.args, instance.args): - # TODO: ParamSpecType + # TODO(PEP612): More ParamSpec work (or is Parameters the only thing accepted) if isinstance(tvar, TypeVarType): # The constraints for generic type parameters depend on variance. # Include constraints from both directions if invariant. @@ -456,6 +459,27 @@ def visit_instance(self, template: Instance) -> List[Constraint]: if tvar.variance != COVARIANT: res.extend(infer_constraints( mapped_arg, instance_arg, neg_op(self.direction))) + elif isinstance(tvar, ParamSpecType) and isinstance(mapped_arg, ParamSpecType): + suffix = get_proper_type(instance_arg) + + if isinstance(suffix, CallableType): + prefix = mapped_arg.prefix + from_concat = bool(prefix.arg_types) or suffix.from_concatenate + suffix = suffix.copy_modified(from_concatenate=from_concat) + + if isinstance(suffix, Parameters) or isinstance(suffix, CallableType): + # no such thing as variance for ParamSpecs + # TODO: is there a case I am missing? + # TODO: constraints between prefixes + prefix = mapped_arg.prefix + suffix = suffix.copy_modified( + suffix.arg_types[len(prefix.arg_types):], + suffix.arg_kinds[len(prefix.arg_kinds):], + suffix.arg_names[len(prefix.arg_names):]) + res.append(Constraint(mapped_arg.id, SUPERTYPE_OF, suffix)) + elif isinstance(suffix, ParamSpecType): + res.append(Constraint(mapped_arg.id, SUPERTYPE_OF, suffix)) + return res elif (self.direction == SUPERTYPE_OF and instance.type.has_base(template.type.fullname)): @@ -464,7 +488,6 @@ def visit_instance(self, template: Instance) -> List[Constraint]: # N.B: We use zip instead of indexing because the lengths might have # mismatches during daemon reprocessing. for tvar, mapped_arg, template_arg in zip(tvars, mapped.args, template.args): - # TODO: ParamSpecType if isinstance(tvar, TypeVarType): # The constraints for generic type parameters depend on variance. # Include constraints from both directions if invariant. @@ -474,6 +497,28 @@ def visit_instance(self, template: Instance) -> List[Constraint]: if tvar.variance != COVARIANT: res.extend(infer_constraints( template_arg, mapped_arg, neg_op(self.direction))) + elif (isinstance(tvar, ParamSpecType) and + isinstance(template_arg, ParamSpecType)): + suffix = get_proper_type(mapped_arg) + + if isinstance(suffix, CallableType): + prefix = template_arg.prefix + from_concat = bool(prefix.arg_types) or suffix.from_concatenate + suffix = suffix.copy_modified(from_concatenate=from_concat) + + if isinstance(suffix, Parameters) or isinstance(suffix, CallableType): + # no such thing as variance for ParamSpecs + # TODO: is there a case I am missing? + # TODO: constraints between prefixes + prefix = template_arg.prefix + + suffix = suffix.copy_modified( + suffix.arg_types[len(prefix.arg_types):], + suffix.arg_kinds[len(prefix.arg_kinds):], + suffix.arg_names[len(prefix.arg_names):]) + res.append(Constraint(template_arg.id, SUPERTYPE_OF, suffix)) + elif isinstance(suffix, ParamSpecType): + res.append(Constraint(template_arg.id, SUPERTYPE_OF, suffix)) return res if (template.type.is_protocol and self.direction == SUPERTYPE_OF and # We avoid infinite recursion for structural subtypes by checking @@ -564,11 +609,34 @@ def visit_callable_type(self, template: CallableType) -> List[Constraint]: # Negate direction due to function argument type contravariance. res.extend(infer_constraints(t, a, neg_op(self.direction))) else: + # sometimes, it appears we try to get constraints between two paramspec callables? # TODO: Direction - # TODO: Deal with arguments that come before param spec ones? - res.append(Constraint(param_spec.id, - SUBTYPE_OF, - cactual.copy_modified(ret_type=NoneType()))) + # TODO: check the prefixes match + prefix = param_spec.prefix + prefix_len = len(prefix.arg_types) + cactual_ps = cactual.param_spec() + + if not cactual_ps: + res.append(Constraint(param_spec.id, + SUBTYPE_OF, + cactual.copy_modified( + arg_types=cactual.arg_types[prefix_len:], + arg_kinds=cactual.arg_kinds[prefix_len:], + arg_names=cactual.arg_names[prefix_len:], + ret_type=NoneType()))) + else: + res.append(Constraint(param_spec.id, SUBTYPE_OF, cactual_ps)) + + # compare prefixes + cactual_prefix = cactual.copy_modified( + arg_types=cactual.arg_types[:prefix_len], + arg_kinds=cactual.arg_kinds[:prefix_len], + arg_names=cactual.arg_names[:prefix_len]) + + # TODO: see above "FIX" comments for param_spec is None case + # TODO: this assume positional arguments + for t, a in zip(prefix.arg_types, cactual_prefix.arg_types): + res.extend(infer_constraints(t, a, neg_op(self.direction))) template_ret_type, cactual_ret_type = template.ret_type, cactual.ret_type if template.type_guard is not None: diff --git a/mypy/erasetype.py b/mypy/erasetype.py index e1a0becc8447b..ff0ef6c0784ee 100644 --- a/mypy/erasetype.py +++ b/mypy/erasetype.py @@ -4,7 +4,7 @@ Type, TypeVisitor, UnboundType, AnyType, NoneType, TypeVarId, Instance, TypeVarType, CallableType, TupleType, TypedDictType, UnionType, Overloaded, ErasedType, PartialType, DeletedType, TypeTranslator, UninhabitedType, TypeType, TypeOfAny, LiteralType, ProperType, - get_proper_type, get_proper_types, TypeAliasType, ParamSpecType, UnpackType + get_proper_type, get_proper_types, TypeAliasType, ParamSpecType, Parameters, UnpackType ) from mypy.nodes import ARG_STAR, ARG_STAR2 @@ -59,6 +59,9 @@ def visit_type_var(self, t: TypeVarType) -> ProperType: def visit_param_spec(self, t: ParamSpecType) -> ProperType: return AnyType(TypeOfAny.special_form) + def visit_parameters(self, t: Parameters) -> ProperType: + raise RuntimeError("Parameters should have been bound to a class") + def visit_unpack_type(self, t: UnpackType) -> ProperType: raise NotImplementedError diff --git a/mypy/expandtype.py b/mypy/expandtype.py index 36cc83f439dd6..39606c263f6b7 100644 --- a/mypy/expandtype.py +++ b/mypy/expandtype.py @@ -5,7 +5,8 @@ NoneType, Overloaded, TupleType, TypedDictType, UnionType, ErasedType, PartialType, DeletedType, UninhabitedType, TypeType, TypeVarId, FunctionLike, TypeVarType, LiteralType, get_proper_type, ProperType, - TypeAliasType, ParamSpecType, TypeVarLikeType, UnpackType + TypeAliasType, ParamSpecType, TypeVarLikeType, Parameters, ParamSpecFlavor, + UnpackType ) @@ -101,15 +102,41 @@ def visit_param_spec(self, t: ParamSpecType) -> Type: repl = get_proper_type(self.variables.get(t.id, t)) if isinstance(repl, Instance): inst = repl + # Return copy of instance with type erasure flag on. + # TODO: what does prefix mean in this case? + # TODO: why does this case even happen? Instances aren't plural. return Instance(inst.type, inst.args, line=inst.line, column=inst.column) elif isinstance(repl, ParamSpecType): - return repl.with_flavor(t.flavor) + return repl.copy_modified(flavor=t.flavor, prefix=t.prefix.copy_modified( + arg_types=t.prefix.arg_types + repl.prefix.arg_types, + arg_kinds=t.prefix.arg_kinds + repl.prefix.arg_kinds, + arg_names=t.prefix.arg_names + repl.prefix.arg_names, + )) + elif isinstance(repl, Parameters) or isinstance(repl, CallableType): + # if the paramspec is *P.args or **P.kwargs: + if t.flavor != ParamSpecFlavor.BARE: + assert isinstance(repl, CallableType), "Should not be able to get here." + # Is this always the right thing to do? + param_spec = repl.param_spec() + if param_spec: + return param_spec.with_flavor(t.flavor) + else: + return repl + else: + return Parameters(t.prefix.arg_types + repl.arg_types, + t.prefix.arg_kinds + repl.arg_kinds, + t.prefix.arg_names + repl.arg_names, + variables=[*t.prefix.variables, *repl.variables]) else: + # TODO: should this branch be removed? better not to fail silently return repl def visit_unpack_type(self, t: UnpackType) -> Type: raise NotImplementedError + def visit_parameters(self, t: Parameters) -> Type: + return t.copy_modified(arg_types=self.expand_types(t.arg_types)) + def visit_callable_type(self, t: CallableType) -> Type: param_spec = t.param_spec() if param_spec is not None: @@ -121,13 +148,18 @@ def visit_callable_type(self, t: CallableType) -> Type: # must expand both of them with all the argument types, # kinds and names in the replacement. The return type in # the replacement is ignored. - if isinstance(repl, CallableType): + if isinstance(repl, CallableType) or isinstance(repl, Parameters): # Substitute *args: P.args, **kwargs: P.kwargs - t = t.expand_param_spec(repl) - # TODO: Substitute remaining arg types - return t.copy_modified(ret_type=t.ret_type.accept(self), - type_guard=(t.type_guard.accept(self) - if t.type_guard is not None else None)) + prefix = param_spec.prefix + # we need to expand the types in the prefix, so might as well + # not get them in the first place + t = t.expand_param_spec(repl, no_prefix=True) + return t.copy_modified( + arg_types=self.expand_types(prefix.arg_types) + t.arg_types, + arg_kinds=prefix.arg_kinds + t.arg_kinds, + arg_names=prefix.arg_names + t.arg_names, + ret_type=t.ret_type.accept(self), + type_guard=(t.type_guard.accept(self) if t.type_guard is not None else None)) return t.copy_modified(arg_types=self.expand_types(t.arg_types), ret_type=t.ret_type.accept(self), diff --git a/mypy/fixup.py b/mypy/fixup.py index cd10ae9156116..302bd38097b30 100644 --- a/mypy/fixup.py +++ b/mypy/fixup.py @@ -11,7 +11,7 @@ CallableType, Instance, Overloaded, TupleType, TypedDictType, TypeVarType, UnboundType, UnionType, TypeVisitor, LiteralType, TypeType, NOT_READY, TypeAliasType, AnyType, TypeOfAny, ParamSpecType, - UnpackType, + Parameters, UnpackType, ) from mypy.visitor import NodeVisitor from mypy.lookup import lookup_fully_qualified @@ -255,6 +255,11 @@ def visit_param_spec(self, p: ParamSpecType) -> None: def visit_unpack_type(self, u: UnpackType) -> None: u.type.accept(self) + def visit_parameters(self, p: Parameters) -> None: + for argt in p.arg_types: + if argt is not None: + argt.accept(self) + def visit_unbound_type(self, o: UnboundType) -> None: for a in o.args: a.accept(self) diff --git a/mypy/indirection.py b/mypy/indirection.py index 9c9959c5f6566..0888c2afad209 100644 --- a/mypy/indirection.py +++ b/mypy/indirection.py @@ -70,6 +70,9 @@ def visit_param_spec(self, t: types.ParamSpecType) -> Set[str]: def visit_unpack_type(self, t: types.UnpackType) -> Set[str]: return t.type.accept(self) + def visit_parameters(self, t: types.Parameters) -> Set[str]: + return self._visit(t.arg_types) + def visit_instance(self, t: types.Instance) -> Set[str]: out = self._visit(t.args) if t.type: diff --git a/mypy/join.py b/mypy/join.py index e11cccb5fa447..a184efcc4bb43 100644 --- a/mypy/join.py +++ b/mypy/join.py @@ -7,7 +7,7 @@ Type, AnyType, NoneType, TypeVisitor, Instance, UnboundType, TypeVarType, CallableType, TupleType, TypedDictType, ErasedType, UnionType, FunctionLike, Overloaded, LiteralType, PartialType, DeletedType, UninhabitedType, TypeType, TypeOfAny, get_proper_type, - ProperType, get_proper_types, TypeAliasType, PlaceholderType, ParamSpecType, + ProperType, get_proper_types, TypeAliasType, PlaceholderType, ParamSpecType, Parameters, UnpackType ) from mypy.maptype import map_instance_to_supertype @@ -260,6 +260,12 @@ def visit_param_spec(self, t: ParamSpecType) -> ProperType: def visit_unpack_type(self, t: UnpackType) -> UnpackType: raise NotImplementedError + def visit_parameters(self, t: Parameters) -> ProperType: + if self.s == t: + return t + else: + return self.default(self.s) + def visit_instance(self, t: Instance) -> ProperType: if isinstance(self.s, Instance): if self.instance_joiner is None: diff --git a/mypy/main.py b/mypy/main.py index 3d98365872509..c4548ea9b6250 100644 --- a/mypy/main.py +++ b/mypy/main.py @@ -679,6 +679,10 @@ def add_invertible_flag(flag: str, " non-overlapping types", group=strictness_group) + add_invertible_flag('--strict-concatenate', default=False, strict_flag=True, + help="Make arguments prepended via Concatenate be truly positional-only", + group=strictness_group) + strict_help = "Strict mode; enables the following flags: {}".format( ", ".join(strict_flag_names)) strictness_group.add_argument( diff --git a/mypy/meet.py b/mypy/meet.py index e6b62ff13ad87..8a996146a344e 100644 --- a/mypy/meet.py +++ b/mypy/meet.py @@ -6,7 +6,7 @@ TupleType, TypedDictType, ErasedType, UnionType, PartialType, DeletedType, UninhabitedType, TypeType, TypeOfAny, Overloaded, FunctionLike, LiteralType, ProperType, get_proper_type, get_proper_types, TypeAliasType, TypeGuardedType, - ParamSpecType, UnpackType, + ParamSpecType, Parameters, UnpackType, ) from mypy.subtypes import is_equivalent, is_subtype, is_callable_compatible, is_proper_subtype from mypy.erasetype import erase_type @@ -509,6 +509,17 @@ def visit_param_spec(self, t: ParamSpecType) -> ProperType: def visit_unpack_type(self, t: UnpackType) -> ProperType: raise NotImplementedError + def visit_parameters(self, t: Parameters) -> ProperType: + # TODO: is this the right variance? + if isinstance(self.s, Parameters) or isinstance(self.s, CallableType): + if len(t.arg_types) != len(self.s.arg_types): + return self.default(self.s) + return t.copy_modified( + arg_types=[meet_types(s_a, t_a) for s_a, t_a in zip(self.s.arg_types, t.arg_types)] + ) + else: + return self.default(self.s) + def visit_instance(self, t: Instance) -> ProperType: if isinstance(self.s, Instance): if t.type == self.s.type: diff --git a/mypy/messages.py b/mypy/messages.py index f067e7e06bd4b..0e9a59ea40160 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -15,7 +15,9 @@ import difflib from textwrap import dedent -from typing import cast, List, Dict, Any, Sequence, Iterable, Iterator, Tuple, Set, Optional, Union +from typing import ( + cast, List, Dict, Any, Sequence, Iterable, Iterator, Tuple, Set, Optional, Union, Callable +) from typing_extensions import Final from mypy.erasetype import erase_type @@ -24,7 +26,7 @@ Type, CallableType, Instance, TypeVarType, TupleType, TypedDictType, LiteralType, UnionType, NoneType, AnyType, Overloaded, FunctionLike, DeletedType, TypeType, UninhabitedType, TypeOfAny, UnboundType, PartialType, get_proper_type, ProperType, - ParamSpecType, get_proper_types + ParamSpecType, Parameters, get_proper_types ) from mypy.typetraverser import TypeTraverserVisitor from mypy.nodes import ( @@ -624,6 +626,32 @@ def incompatible_argument_note(self, if call: self.note_call(original_caller_type, call, context, code=code) + self.maybe_note_concatenate_pos_args(original_caller_type, callee_type, context, code) + + def maybe_note_concatenate_pos_args(self, + original_caller_type: ProperType, + callee_type: ProperType, + context: Context, + code: Optional[ErrorCode] = None) -> None: + # pos-only vs positional can be confusing, with Concatenate + if (isinstance(callee_type, CallableType) and + isinstance(original_caller_type, CallableType) and + (original_caller_type.from_concatenate or callee_type.from_concatenate)): + names: List[str] = [] + for c, o in zip( + callee_type.formal_arguments(), + original_caller_type.formal_arguments()): + if None in (c.pos, o.pos): + # non-positional + continue + if c.name != o.name and c.name is None and o.name is not None: + names.append(o.name) + + if names: + missing_arguments = '"' + '", "'.join(names) + '"' + self.note(f'This may be because "{original_caller_type.name}" has arguments ' + f'named: {missing_arguments}', context, code=code) + def invalid_index_type(self, index_type: Type, expected_type: Type, base_str: str, context: Context, *, code: ErrorCode) -> None: index_str, expected_str = format_type_distinctly(index_type, expected_type) @@ -1652,6 +1680,32 @@ def quote_type_string(type_string: str) -> str: return '"{}"'.format(type_string) +def format_callable_args(arg_types: List[Type], arg_kinds: List[ArgKind], + arg_names: List[Optional[str]], format: Callable[[Type], str], + verbosity: int) -> str: + """Format a bunch of Callable arguments into a string""" + arg_strings = [] + for arg_name, arg_type, arg_kind in zip( + arg_names, arg_types, arg_kinds): + if (arg_kind == ARG_POS and arg_name is None + or verbosity == 0 and arg_kind.is_positional()): + + arg_strings.append(format(arg_type)) + else: + constructor = ARG_CONSTRUCTOR_NAMES[arg_kind] + if arg_kind.is_star() or arg_name is None: + arg_strings.append("{}({})".format( + constructor, + format(arg_type))) + else: + arg_strings.append("{}({}, {})".format( + constructor, + format(arg_type), + repr(arg_name))) + + return ", ".join(arg_strings) + + def format_type_inner(typ: Type, verbosity: int, fullnames: Optional[Set[str]]) -> str: @@ -1705,7 +1759,18 @@ def format_literal_value(typ: LiteralType) -> str: # This is similar to non-generic instance types. return typ.name elif isinstance(typ, ParamSpecType): - return typ.name_with_suffix() + # Concatenate[..., P] + if typ.prefix.arg_types: + args = format_callable_args( + typ.prefix.arg_types, + typ.prefix.arg_kinds, + typ.prefix.arg_names, + format, + verbosity) + + return f'[{args}, **{typ.name_with_suffix()}]' + else: + return typ.name_with_suffix() elif isinstance(typ, TupleType): # Prefer the name of the fallback class (if not tuple), as it's more informative. if typ.partial_fallback.type.fullname != 'builtins.tuple': @@ -1782,27 +1847,14 @@ def format_literal_value(typ: LiteralType) -> str: return 'Callable[..., {}]'.format(return_type) param_spec = func.param_spec() if param_spec is not None: - return f'Callable[{param_spec.name}, {return_type}]' - arg_strings = [] - for arg_name, arg_type, arg_kind in zip( - func.arg_names, func.arg_types, func.arg_kinds): - if (arg_kind == ARG_POS and arg_name is None - or verbosity == 0 and arg_kind.is_positional()): - - arg_strings.append(format(arg_type)) - else: - constructor = ARG_CONSTRUCTOR_NAMES[arg_kind] - if arg_kind.is_star() or arg_name is None: - arg_strings.append("{}({})".format( - constructor, - format(arg_type))) - else: - arg_strings.append("{}({}, {})".format( - constructor, - format(arg_type), - repr(arg_name))) - - return 'Callable[[{}], {}]'.format(", ".join(arg_strings), return_type) + return f'Callable[{format(param_spec)}, {return_type}]' + args = format_callable_args( + func.arg_types, + func.arg_kinds, + func.arg_names, + format, + verbosity) + return 'Callable[[{}], {}]'.format(args, return_type) else: # Use a simple representation for function types; proper # function types may result in long and difficult-to-read @@ -1810,6 +1862,14 @@ def format_literal_value(typ: LiteralType) -> str: return 'overloaded function' elif isinstance(typ, UnboundType): return str(typ) + elif isinstance(typ, Parameters): + args = format_callable_args( + typ.arg_types, + typ.arg_kinds, + typ.arg_names, + format, + verbosity) + return f'[{args}]' elif typ is None: raise RuntimeError('Type is None') else: diff --git a/mypy/nodes.py b/mypy/nodes.py index 98402ab9b71b0..7fcf5d85673cf 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -1037,7 +1037,9 @@ def deserialize(self, data: JsonDict) -> 'ClassDef': assert data['.class'] == 'ClassDef' res = ClassDef(data['name'], Block([]), - [mypy.types.TypeVarType.deserialize(v) for v in data['type_vars']], + # https://github.com/python/mypy/issues/12257 + [cast(mypy.types.TypeVarLikeType, mypy.types.deserialize_type(v)) + for v in data['type_vars']], ) res.fullname = data['fullname'] return res @@ -2507,8 +2509,8 @@ class is generic then it will be a type constructor of higher kind. 'declared_metaclass', 'metaclass_type', 'names', 'is_abstract', 'is_protocol', 'runtime_protocol', 'abstract_attributes', 'deletable_attributes', 'slots', 'assuming', 'assuming_proper', - 'inferring', 'is_enum', 'fallback_to_any', 'type_vars', 'bases', - '_promote', 'tuple_type', 'is_named_tuple', 'typeddict_type', + 'inferring', 'is_enum', 'fallback_to_any', 'type_vars', 'has_param_spec_type', + 'bases', '_promote', 'tuple_type', 'is_named_tuple', 'typeddict_type', 'is_newtype', 'is_intersection', 'metadata', ) @@ -2591,6 +2593,9 @@ class is generic then it will be a type constructor of higher kind. # Generic type variable names (full names) type_vars: List[str] + # Whether this class has a ParamSpec type variable + has_param_spec_type: bool + # Direct base classes. bases: List["mypy.types.Instance"] @@ -2638,6 +2643,7 @@ def __init__(self, names: 'SymbolTable', defn: ClassDef, module_name: str) -> No self.defn = defn self.module_name = module_name self.type_vars = [] + self.has_param_spec_type = False self.bases = [] self.mro = [] self._mro_refs = None @@ -2668,7 +2674,9 @@ def __init__(self, names: 'SymbolTable', defn: ClassDef, module_name: str) -> No def add_type_vars(self) -> None: if self.defn.type_vars: for vd in self.defn.type_vars: - self.type_vars.append(vd.fullname) + if isinstance(vd, mypy.types.ParamSpecType): + self.has_param_spec_type = True + self.type_vars.append(vd.name) @property def name(self) -> str: @@ -2832,6 +2840,7 @@ def serialize(self) -> JsonDict: 'defn': self.defn.serialize(), 'abstract_attributes': self.abstract_attributes, 'type_vars': self.type_vars, + 'has_param_spec_type': self.has_param_spec_type, 'bases': [b.serialize() for b in self.bases], 'mro': [c.fullname for c in self.mro], '_promote': None if self._promote is None else self._promote.serialize(), @@ -2857,6 +2866,7 @@ def deserialize(cls, data: JsonDict) -> 'TypeInfo': # TODO: Is there a reason to reconstruct ti.subtypes? ti.abstract_attributes = data['abstract_attributes'] ti.type_vars = data['type_vars'] + ti.has_param_spec_type = data['has_param_spec_type'] ti.bases = [mypy.types.Instance.deserialize(b) for b in data['bases']] ti._promote = (None if data['_promote'] is None else mypy.types.deserialize_type(data['_promote'])) diff --git a/mypy/options.py b/mypy/options.py index b0dead4146b58..8e56d67bbeb8b 100644 --- a/mypy/options.py +++ b/mypy/options.py @@ -46,6 +46,7 @@ class BuildType: "mypyc", "no_implicit_optional", "show_none_errors", + "strict_concatenate", "strict_equality", "strict_optional", "strict_optional_whitelist", @@ -183,6 +184,9 @@ def __init__(self) -> None: # This makes 1 == '1', 1 in ['1'], and 1 is '1' errors. self.strict_equality = False + # Make arguments prepended via Concatenate be truly positional-only. + self.strict_concatenate = False + # Report an error for any branches inferred to be unreachable as a result of # type analysis. self.warn_unreachable = False diff --git a/mypy/sametypes.py b/mypy/sametypes.py index 70cd216031797..46798018410d2 100644 --- a/mypy/sametypes.py +++ b/mypy/sametypes.py @@ -4,7 +4,7 @@ Type, UnboundType, AnyType, NoneType, TupleType, TypedDictType, UnionType, CallableType, TypeVarType, Instance, TypeVisitor, ErasedType, Overloaded, PartialType, DeletedType, UninhabitedType, TypeType, LiteralType, - ProperType, get_proper_type, TypeAliasType, ParamSpecType, UnpackType + ProperType, get_proper_type, TypeAliasType, ParamSpecType, Parameters, UnpackType ) from mypy.typeops import tuple_fallback, make_simplified_union @@ -106,6 +106,12 @@ def visit_unpack_type(self, left: UnpackType) -> bool: return (isinstance(self.right, UnpackType) and is_same_type(left.type, self.right.type)) + def visit_parameters(self, left: Parameters) -> bool: + return (isinstance(self.right, Parameters) and + left.arg_names == self.right.arg_names and + is_same_types(left.arg_types, self.right.arg_types) and + left.arg_kinds == self.right.arg_kinds) + def visit_callable_type(self, left: CallableType) -> bool: # FIX generics if isinstance(self.right, CallableType): diff --git a/mypy/semanal.py b/mypy/semanal.py index 8872e6f4aa8ad..44ece06747321 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -97,7 +97,7 @@ NEVER_NAMES, FunctionLike, UnboundType, TypeVarType, TupleType, UnionType, StarType, CallableType, Overloaded, Instance, Type, AnyType, LiteralType, LiteralValue, TypeTranslator, TypeOfAny, TypeType, NoneType, PlaceholderType, TPDICT_NAMES, ProperType, - get_proper_type, get_proper_types, TypeAliasType, TypeVarLikeType, + get_proper_type, get_proper_types, TypeAliasType, TypeVarLikeType, Parameters, ParamSpecType, PROTOCOL_NAMES, TYPE_ALIAS_NAMES, FINAL_TYPE_NAMES, FINAL_DECORATOR_NAMES, REVEAL_TYPE_NAMES, is_named_instance, ) @@ -1184,7 +1184,9 @@ def analyze_class(self, defn: ClassDef) -> None: self.prepare_class_def(defn) defn.type_vars = tvar_defs - defn.info.type_vars = [tvar.name for tvar in tvar_defs] + defn.info.type_vars = [] + # we want to make sure any additional logic in add_type_vars gets run + defn.info.add_type_vars() if base_error: defn.info.fallback_to_any = True @@ -4138,6 +4140,27 @@ def analyze_type_application_args(self, expr: IndexExpr) -> Optional[List[Type]] items = items[:-1] else: items = [index] + + # whether param spec literals be allowed here + # TODO: should this be computed once and passed in? + # or is there a better way to do this? + base = expr.base + if isinstance(base, RefExpr) and isinstance(base.node, TypeAlias): + alias = base.node + target = get_proper_type(alias.target) + if isinstance(target, Instance): + has_param_spec = target.type.has_param_spec_type + num_args = len(target.type.type_vars) + else: + has_param_spec = False + num_args = -1 + elif isinstance(base, NameExpr) and isinstance(base.node, TypeInfo): + has_param_spec = base.node.has_param_spec_type + num_args = len(base.node.type_vars) + else: + has_param_spec = False + num_args = -1 + for item in items: try: typearg = self.expr_to_unanalyzed_type(item) @@ -4148,10 +4171,19 @@ def analyze_type_application_args(self, expr: IndexExpr) -> Optional[List[Type]] # may be analysing a type alias definition rvalue. The error will be # reported elsewhere if it is not the case. analyzed = self.anal_type(typearg, allow_unbound_tvars=True, - allow_placeholder=True) + allow_placeholder=True, + allow_param_spec_literals=has_param_spec) if analyzed is None: return None types.append(analyzed) + + if has_param_spec and num_args == 1 and len(types) > 0: + first_arg = get_proper_type(types[0]) + if not (len(types) == 1 and (isinstance(first_arg, Parameters) or + isinstance(first_arg, ParamSpecType) or + isinstance(first_arg, AnyType))): + types = [Parameters(types, [ARG_POS] * len(types), [None] * len(types))] + return types def visit_slice_expr(self, expr: SliceExpr) -> None: @@ -5288,6 +5320,7 @@ def type_analyzer(self, *, allow_unbound_tvars: bool = False, allow_placeholder: bool = False, allow_required: bool = False, + allow_param_spec_literals: bool = False, report_invalid_types: bool = True) -> TypeAnalyser: if tvar_scope is None: tvar_scope = self.tvar_scope @@ -5300,7 +5333,8 @@ def type_analyzer(self, *, allow_tuple_literal=allow_tuple_literal, report_invalid_types=report_invalid_types, allow_placeholder=allow_placeholder, - allow_required=allow_required) + allow_required=allow_required, + allow_param_spec_literals=allow_param_spec_literals) tpan.in_dynamic_func = bool(self.function_stack and self.function_stack[-1].is_dynamic()) tpan.global_scope = not self.type and not self.function_stack return tpan @@ -5315,6 +5349,7 @@ def anal_type(self, allow_unbound_tvars: bool = False, allow_placeholder: bool = False, allow_required: bool = False, + allow_param_spec_literals: bool = False, report_invalid_types: bool = True, third_pass: bool = False) -> Optional[Type]: """Semantically analyze a type. @@ -5342,6 +5377,7 @@ def anal_type(self, allow_tuple_literal=allow_tuple_literal, allow_placeholder=allow_placeholder, allow_required=allow_required, + allow_param_spec_literals=allow_param_spec_literals, report_invalid_types=report_invalid_types) tag = self.track_incomplete_refs() typ = typ.accept(a) diff --git a/mypy/server/astdiff.py b/mypy/server/astdiff.py index 28d9423420b8f..437cb777c8d53 100644 --- a/mypy/server/astdiff.py +++ b/mypy/server/astdiff.py @@ -60,7 +60,7 @@ class level -- these are handled at attribute level (say, 'mod.Cls.method' Type, TypeVisitor, UnboundType, AnyType, NoneType, UninhabitedType, ErasedType, DeletedType, Instance, TypeVarType, CallableType, TupleType, TypedDictType, UnionType, Overloaded, PartialType, TypeType, LiteralType, TypeAliasType, ParamSpecType, - UnpackType, + Parameters, UnpackType, ) from mypy.util import get_prefix @@ -321,6 +321,12 @@ def visit_param_spec(self, typ: ParamSpecType) -> SnapshotItem: def visit_unpack_type(self, typ: UnpackType) -> SnapshotItem: return ('UnpackType', snapshot_type(typ.type)) + def visit_parameters(self, typ: Parameters) -> SnapshotItem: + return ('Parameters', + snapshot_types(typ.arg_types), + tuple(encode_optional_str(name) for name in typ.arg_names), + tuple(typ.arg_kinds)) + def visit_callable_type(self, typ: CallableType) -> SnapshotItem: # FIX generics return ('CallableType', diff --git a/mypy/server/astmerge.py b/mypy/server/astmerge.py index 24e771fc868a1..deaf7a6e21b71 100644 --- a/mypy/server/astmerge.py +++ b/mypy/server/astmerge.py @@ -59,7 +59,7 @@ Type, SyntheticTypeVisitor, Instance, AnyType, NoneType, CallableType, ErasedType, DeletedType, TupleType, TypeType, TypedDictType, UnboundType, UninhabitedType, UnionType, Overloaded, TypeVarType, TypeList, CallableArgument, EllipsisType, StarType, LiteralType, - RawExpressionType, PartialType, PlaceholderType, TypeAliasType, ParamSpecType, + RawExpressionType, PartialType, PlaceholderType, TypeAliasType, ParamSpecType, Parameters, UnpackType ) from mypy.util import get_prefix, replace_object_state @@ -415,6 +415,10 @@ def visit_param_spec(self, typ: ParamSpecType) -> None: def visit_unpack_type(self, typ: UnpackType) -> None: typ.type.accept(self) + def visit_parameters(self, typ: Parameters) -> None: + for arg in typ.arg_types: + arg.accept(self) + def visit_typeddict_type(self, typ: TypedDictType) -> None: for value_type in typ.items.values(): value_type.accept(self) diff --git a/mypy/server/deps.py b/mypy/server/deps.py index ebd808de6a6df..646a024340482 100644 --- a/mypy/server/deps.py +++ b/mypy/server/deps.py @@ -99,7 +99,7 @@ class 'mod.Cls'. This can also refer to an attribute inherited from a Type, Instance, AnyType, NoneType, TypeVisitor, CallableType, DeletedType, PartialType, TupleType, TypeType, TypeVarType, TypedDictType, UnboundType, UninhabitedType, UnionType, FunctionLike, Overloaded, TypeOfAny, LiteralType, ErasedType, get_proper_type, ProperType, - TypeAliasType, ParamSpecType, UnpackType + TypeAliasType, ParamSpecType, Parameters, UnpackType ) from mypy.server.trigger import make_trigger, make_wildcard_trigger from mypy.util import correct_relative_import @@ -964,6 +964,12 @@ def visit_param_spec(self, typ: ParamSpecType) -> List[str]: def visit_unpack_type(self, typ: UnpackType) -> List[str]: return typ.type.accept(self) + def visit_parameters(self, typ: Parameters) -> List[str]: + triggers = [] + for arg in typ.arg_types: + triggers.extend(self.get_type_triggers(arg)) + return triggers + def visit_typeddict_type(self, typ: TypedDictType) -> List[str]: triggers = [] for item in typ.items.values(): diff --git a/mypy/subtypes.py b/mypy/subtypes.py index 17caea9db6f5a..314c260f293d3 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -8,7 +8,7 @@ Instance, TypeVarType, CallableType, TupleType, TypedDictType, UnionType, Overloaded, ErasedType, PartialType, DeletedType, UninhabitedType, TypeType, is_named_instance, FunctionLike, TypeOfAny, LiteralType, get_proper_type, TypeAliasType, ParamSpecType, - UnpackType, TUPLE_LIKE_INSTANCE_NAMES, + Parameters, UnpackType, TUPLE_LIKE_INSTANCE_NAMES, ) import mypy.applytype import mypy.constraints @@ -24,6 +24,7 @@ from mypy.maptype import map_instance_to_supertype from mypy.expandtype import expand_type_by_instance from mypy.typestate import TypeState, SubtypeKind +from mypy.options import Options from mypy import state # Flags for detected protocol members @@ -52,7 +53,8 @@ def is_subtype(left: Type, right: Type, ignore_type_params: bool = False, ignore_pos_arg_names: bool = False, ignore_declared_variance: bool = False, - ignore_promotions: bool = False) -> bool: + ignore_promotions: bool = False, + options: Optional[Options] = None) -> bool: """Is 'left' subtype of 'right'? Also consider Any to be a subtype of any type, and vice versa. This @@ -90,12 +92,14 @@ def is_subtype(left: Type, right: Type, ignore_type_params=ignore_type_params, ignore_pos_arg_names=ignore_pos_arg_names, ignore_declared_variance=ignore_declared_variance, - ignore_promotions=ignore_promotions) + ignore_promotions=ignore_promotions, + options=options) return _is_subtype(left, right, ignore_type_params=ignore_type_params, ignore_pos_arg_names=ignore_pos_arg_names, ignore_declared_variance=ignore_declared_variance, - ignore_promotions=ignore_promotions) + ignore_promotions=ignore_promotions, + options=options) def _is_subtype(left: Type, right: Type, @@ -103,7 +107,8 @@ def _is_subtype(left: Type, right: Type, ignore_type_params: bool = False, ignore_pos_arg_names: bool = False, ignore_declared_variance: bool = False, - ignore_promotions: bool = False) -> bool: + ignore_promotions: bool = False, + options: Optional[Options] = None) -> bool: orig_right = right orig_left = left left = get_proper_type(left) @@ -120,7 +125,8 @@ def _is_subtype(left: Type, right: Type, ignore_type_params=ignore_type_params, ignore_pos_arg_names=ignore_pos_arg_names, ignore_declared_variance=ignore_declared_variance, - ignore_promotions=ignore_promotions) + ignore_promotions=ignore_promotions, + options=options) for item in right.items) # Recombine rhs literal types, to make an enum type a subtype # of a union of all enum items as literal types. Only do it if @@ -135,7 +141,8 @@ def _is_subtype(left: Type, right: Type, ignore_type_params=ignore_type_params, ignore_pos_arg_names=ignore_pos_arg_names, ignore_declared_variance=ignore_declared_variance, - ignore_promotions=ignore_promotions) + ignore_promotions=ignore_promotions, + options=options) for item in right.items) # However, if 'left' is a type variable T, T might also have # an upper bound which is itself a union. This case will be @@ -152,19 +159,21 @@ def _is_subtype(left: Type, right: Type, ignore_type_params=ignore_type_params, ignore_pos_arg_names=ignore_pos_arg_names, ignore_declared_variance=ignore_declared_variance, - ignore_promotions=ignore_promotions)) + ignore_promotions=ignore_promotions, + options=options)) def is_equivalent(a: Type, b: Type, *, ignore_type_params: bool = False, - ignore_pos_arg_names: bool = False + ignore_pos_arg_names: bool = False, + options: Optional[Options] = None ) -> bool: return ( is_subtype(a, b, ignore_type_params=ignore_type_params, - ignore_pos_arg_names=ignore_pos_arg_names) + ignore_pos_arg_names=ignore_pos_arg_names, options=options) and is_subtype(b, a, ignore_type_params=ignore_type_params, - ignore_pos_arg_names=ignore_pos_arg_names)) + ignore_pos_arg_names=ignore_pos_arg_names, options=options)) class SubtypeVisitor(TypeVisitor[bool]): @@ -174,7 +183,8 @@ def __init__(self, right: Type, ignore_type_params: bool, ignore_pos_arg_names: bool = False, ignore_declared_variance: bool = False, - ignore_promotions: bool = False) -> None: + ignore_promotions: bool = False, + options: Optional[Options] = None) -> None: self.right = get_proper_type(right) self.orig_right = right self.ignore_type_params = ignore_type_params @@ -183,6 +193,7 @@ def __init__(self, right: Type, self.ignore_promotions = ignore_promotions self.check_type_parameter = (ignore_type_parameter if ignore_type_params else check_type_parameter) + self.options = options self._subtype_kind = SubtypeVisitor.build_subtype_kind( ignore_type_params=ignore_type_params, ignore_pos_arg_names=ignore_pos_arg_names, @@ -206,7 +217,8 @@ def _is_subtype(self, left: Type, right: Type) -> bool: ignore_type_params=self.ignore_type_params, ignore_pos_arg_names=self.ignore_pos_arg_names, ignore_declared_variance=self.ignore_declared_variance, - ignore_promotions=self.ignore_promotions) + ignore_promotions=self.ignore_promotions, + options=self.options) # visit_x(left) means: is left (which is an instance of X) a subtype of # right? @@ -278,7 +290,7 @@ def visit_instance(self, left: Instance) -> bool: if not self.check_type_parameter(lefta, righta, tvar.variance): nominal = False else: - if not is_equivalent(lefta, righta): + if not self.check_type_parameter(lefta, righta, COVARIANT): nominal = False if nominal: TypeState.record_subtype_cache_entry(self._subtype_kind, left, right) @@ -330,6 +342,16 @@ def visit_param_spec(self, left: ParamSpecType) -> bool: def visit_unpack_type(self, left: UnpackType) -> bool: raise NotImplementedError + def visit_parameters(self, left: Parameters) -> bool: + right = self.right + if isinstance(right, Parameters) or isinstance(right, CallableType): + return are_parameters_compatible( + left, right, + is_compat=self._is_subtype, + ignore_pos_arg_names=self.ignore_pos_arg_names) + else: + return False + def visit_callable_type(self, left: CallableType) -> bool: right = self.right if isinstance(right, CallableType): @@ -343,7 +365,8 @@ def visit_callable_type(self, left: CallableType) -> bool: return is_callable_compatible( left, right, is_compat=self._is_subtype, - ignore_pos_arg_names=self.ignore_pos_arg_names) + ignore_pos_arg_names=self.ignore_pos_arg_names, + strict_concatenate=self.options.strict_concatenate if self.options else True) elif isinstance(right, Overloaded): return all(self._is_subtype(left, item) for item in right.items) elif isinstance(right, Instance): @@ -358,6 +381,12 @@ def visit_callable_type(self, left: CallableType) -> bool: elif isinstance(right, TypeType): # This is unsound, we don't check the __init__ signature. return left.is_type_obj() and self._is_subtype(left.ret_type, right.item) + elif isinstance(right, Parameters): + # this doesn't check return types.... but is needed for is_equivalent + return are_parameters_compatible( + left, right, + is_compat=self._is_subtype, + ignore_pos_arg_names=self.ignore_pos_arg_names) else: return False @@ -404,7 +433,8 @@ def visit_typeddict_type(self, left: TypedDictType) -> bool: return False for name, l, r in left.zip(right): if not is_equivalent(l, r, - ignore_type_params=self.ignore_type_params): + ignore_type_params=self.ignore_type_params, + options=self.options): return False # Non-required key is not compatible with a required key since # indexing may fail unexpectedly if a required key is missing. @@ -471,12 +501,15 @@ def visit_overloaded(self, left: Overloaded) -> bool: else: # If this one overlaps with the supertype in any way, but it wasn't # an exact match, then it's a potential error. + strict_concat = self.options.strict_concatenate if self.options else True if (is_callable_compatible(left_item, right_item, is_compat=self._is_subtype, ignore_return=True, - ignore_pos_arg_names=self.ignore_pos_arg_names) or + ignore_pos_arg_names=self.ignore_pos_arg_names, + strict_concatenate=strict_concat) or is_callable_compatible(right_item, left_item, is_compat=self._is_subtype, ignore_return=True, - ignore_pos_arg_names=self.ignore_pos_arg_names)): + ignore_pos_arg_names=self.ignore_pos_arg_names, + strict_concatenate=strict_concat)): # If this is an overload that's already been matched, there's no # problem. if left_item not in matched_overloads: @@ -778,7 +811,8 @@ def is_callable_compatible(left: CallableType, right: CallableType, ignore_return: bool = False, ignore_pos_arg_names: bool = False, check_args_covariantly: bool = False, - allow_partial_overlap: bool = False) -> bool: + allow_partial_overlap: bool = False, + strict_concatenate: bool = False) -> bool: """Is the left compatible with the right, using the provided compatibility check? is_compat: @@ -914,6 +948,27 @@ def g(x: int) -> int: ... if check_args_covariantly: is_compat = flip_compat_check(is_compat) + if not strict_concatenate and (left.from_concatenate or right.from_concatenate): + strict_concatenate_check = False + else: + strict_concatenate_check = True + + return are_parameters_compatible(left, right, is_compat=is_compat, + ignore_pos_arg_names=ignore_pos_arg_names, + check_args_covariantly=check_args_covariantly, + allow_partial_overlap=allow_partial_overlap, + strict_concatenate_check=strict_concatenate_check) + + +def are_parameters_compatible(left: Union[Parameters, CallableType], + right: Union[Parameters, CallableType], + *, + is_compat: Callable[[Type, Type], bool], + ignore_pos_arg_names: bool = False, + check_args_covariantly: bool = False, + allow_partial_overlap: bool = False, + strict_concatenate_check: bool = True) -> bool: + """Helper function for is_callable_compatible, used for Parameter compatibility""" if right.is_ellipsis_args: return True @@ -1001,7 +1056,9 @@ def _incompatible(left_arg: Optional[FormalArgument], right_names = {name for name in right.arg_names if name is not None} left_only_names = set() for name, kind in zip(left.arg_names, left.arg_kinds): - if name is None or kind.is_star() or name in right_names: + if (name is None or kind.is_star() + or name in right_names + or not strict_concatenate_check): continue left_only_names.add(name) @@ -1037,7 +1094,8 @@ def _incompatible(left_arg: Optional[FormalArgument], if (right_by_name is not None and right_by_pos is not None and right_by_name != right_by_pos - and (right_by_pos.required or right_by_name.required)): + and (right_by_pos.required or right_by_name.required) + and strict_concatenate_check): return False # All *required* left-hand arguments must have a corresponding @@ -1363,6 +1421,13 @@ def visit_param_spec(self, left: ParamSpecType) -> bool: def visit_unpack_type(self, left: UnpackType) -> bool: raise NotImplementedError + def visit_parameters(self, left: Parameters) -> bool: + right = self.right + if isinstance(right, Parameters) or isinstance(right, CallableType): + return are_parameters_compatible(left, right, is_compat=self._is_proper_subtype) + else: + return False + def visit_callable_type(self, left: CallableType) -> bool: right = self.right if isinstance(right, CallableType): diff --git a/mypy/type_visitor.py b/mypy/type_visitor.py index 2adc73c009387..05688a1e5071e 100644 --- a/mypy/type_visitor.py +++ b/mypy/type_visitor.py @@ -20,7 +20,7 @@ from mypy.types import ( Type, AnyType, CallableType, Overloaded, TupleType, TypedDictType, LiteralType, - RawExpressionType, Instance, NoneType, TypeType, + Parameters, RawExpressionType, Instance, NoneType, TypeType, UnionType, TypeVarType, PartialType, DeletedType, UninhabitedType, TypeVarLikeType, UnboundType, ErasedType, StarType, EllipsisType, TypeList, CallableArgument, PlaceholderType, TypeAliasType, ParamSpecType, UnpackType, get_proper_type @@ -67,6 +67,10 @@ def visit_type_var(self, t: TypeVarType) -> T: def visit_param_spec(self, t: ParamSpecType) -> T: pass + @abstractmethod + def visit_parameters(self, t: Parameters) -> T: + pass + @abstractmethod def visit_instance(self, t: Instance) -> T: pass @@ -190,6 +194,9 @@ def visit_type_var(self, t: TypeVarType) -> Type: def visit_param_spec(self, t: ParamSpecType) -> Type: return t + def visit_parameters(self, t: Parameters) -> Type: + return t.copy_modified(arg_types=self.translate_types(t.arg_types)) + def visit_partial_type(self, t: PartialType) -> Type: return t @@ -311,6 +318,9 @@ def visit_param_spec(self, t: ParamSpecType) -> T: def visit_unpack_type(self, t: UnpackType) -> T: return self.query_types([t.type]) + def visit_parameters(self, t: Parameters) -> T: + return self.query_types(t.arg_types) + def visit_partial_type(self, t: PartialType) -> T: return self.strategy([]) diff --git a/mypy/typeanal.py b/mypy/typeanal.py index b40bec6ca3379..276e46df03ee4 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -15,7 +15,7 @@ NEVER_NAMES, Type, UnboundType, TupleType, TypedDictType, UnionType, Instance, AnyType, CallableType, NoneType, ErasedType, DeletedType, TypeList, TypeVarType, SyntheticTypeVisitor, StarType, PartialType, EllipsisType, UninhabitedType, TypeType, CallableArgument, - TypeQuery, union_items, TypeOfAny, LiteralType, RawExpressionType, + Parameters, TypeQuery, union_items, TypeOfAny, LiteralType, RawExpressionType, PlaceholderType, Overloaded, get_proper_type, TypeAliasType, RequiredType, TypeVarLikeType, ParamSpecType, ParamSpecFlavor, UnpackType, callable_with_ellipsis, TYPE_ALIAS_NAMES, FINAL_TYPE_NAMES, @@ -129,6 +129,7 @@ def __init__(self, allow_unbound_tvars: bool = False, allow_placeholder: bool = False, allow_required: bool = False, + allow_param_spec_literals: bool = False, report_invalid_types: bool = True) -> None: self.api = api self.lookup_qualified = api.lookup_qualified @@ -153,6 +154,8 @@ def __init__(self, self.allow_placeholder = allow_placeholder # Are we in a context where Required[] is allowed? self.allow_required = allow_required + # Are we in a context where ParamSpec literals are allowed? + self.allow_param_spec_literals = allow_param_spec_literals # Should we report an error whenever we encounter a RawExpressionType outside # of a Literal context: e.g. whenever we encounter an invalid type? Normally, # we want to report an error, but the caller may want to do more specialized @@ -264,6 +267,10 @@ def visit_unbound_type_nonoptional(self, t: UnboundType, defining_literal: bool) return self.analyze_type_with_type_info(node, t.args, t) elif node.fullname in TYPE_ALIAS_NAMES: return AnyType(TypeOfAny.special_form) + # Concatenate is an operator, no need for a proper type + elif node.fullname in ('typing_extensions.Concatenate', 'typing.Concatenate'): + # We check the return type further up the stack for valid use locations + return self.apply_concatenate_operator(t) else: return self.analyze_unbound_type_without_type_info(t, sym, defining_literal) else: # sym is None @@ -277,6 +284,33 @@ def cannot_resolve_type(self, t: UnboundType) -> None: 'Cannot resolve name "{}" (possible cyclic definition)'.format(t.name), t) + def apply_concatenate_operator(self, t: UnboundType) -> Type: + if len(t.args) == 0: + self.api.fail('Concatenate needs type arguments', t) + return AnyType(TypeOfAny.from_error) + + # last argument has to be ParamSpec + ps = self.anal_type(t.args[-1], allow_param_spec=True) + if not isinstance(ps, ParamSpecType): + self.api.fail('The last parameter to Concatenate needs to be a ParamSpec', t) + return AnyType(TypeOfAny.from_error) + + # TODO: this may not work well with aliases, if those worked. + # Those should be special-cased. + elif ps.prefix.arg_types: + self.api.fail('Nested Concatenates are invalid', t) + + args = self.anal_array(t.args[:-1]) + pre = ps.prefix + + # mypy can't infer this :( + names: List[Optional[str]] = [None] * len(args) + + pre = Parameters(args + pre.arg_types, + [ARG_POS] * len(args) + pre.arg_kinds, + names + pre.arg_names) + return ps.copy_modified(prefix=pre) + def try_analyze_special_unbound_type(self, t: UnboundType, fullname: str) -> Optional[Type]: """Bind special type that is recognized through magic name such as 'typing.Any'. @@ -403,13 +437,32 @@ def analyze_type_with_type_info( if len(args) > 0 and info.fullname == 'builtins.tuple': fallback = Instance(info, [AnyType(TypeOfAny.special_form)], ctx.line) return TupleType(self.anal_array(args), fallback, ctx.line) - # Analyze arguments and (usually) construct Instance type. The - # number of type arguments and their values are - # checked only later, since we do not always know the - # valid count at this point. Thus we may construct an - # Instance with an invalid number of type arguments. - instance = Instance(info, self.anal_array(args, allow_param_spec=True), - ctx.line, ctx.column) + + # This is a heuristic: it will be checked later anyways but the error + # message may be worse. + with self.set_allow_param_spec_literals(info.has_param_spec_type): + # Analyze arguments and (usually) construct Instance type. The + # number of type arguments and their values are + # checked only later, since we do not always know the + # valid count at this point. Thus we may construct an + # Instance with an invalid number of type arguments. + instance = Instance(info, self.anal_array(args, allow_param_spec=True), + ctx.line, ctx.column) + + # "aesthetic" paramspec literals + # these do not support mypy_extensions VarArgs, etc. as they were already analyzed + # TODO: should these be re-analyzed to get rid of this inconsistency? + # another inconsistency is with empty type args (Z[] is more possibly an error imo) + if len(info.type_vars) == 1 and info.has_param_spec_type and len(instance.args) > 0: + first_arg = get_proper_type(instance.args[0]) + + # TODO: can I use tuple syntax to isinstance multiple in 3.6? + if not (len(instance.args) == 1 and (isinstance(first_arg, Parameters) or + isinstance(first_arg, ParamSpecType) or + isinstance(first_arg, AnyType))): + args = instance.args + instance.args = (Parameters(args, [ARG_POS] * len(args), [None] * len(args)),) + # Check type argument count. if len(instance.args) != len(info.type_vars) and not self.defining_alias: fix_instance(instance, self.fail, self.note, @@ -546,9 +599,19 @@ def visit_deleted_type(self, t: DeletedType) -> Type: return t def visit_type_list(self, t: TypeList) -> Type: - self.fail('Bracketed expression "[...]" is not valid as a type', t) - self.note('Did you mean "List[...]"?', t) - return AnyType(TypeOfAny.from_error) + # paramspec literal (Z[[int, str, Whatever]]) + if self.allow_param_spec_literals: + params = self.analyze_callable_args(t) + if params: + ts, kinds, names = params + # bind these types + return Parameters(self.anal_array(ts), kinds, names) + else: + return AnyType(TypeOfAny.from_error) + else: + self.fail('Bracketed expression "[...]" is not valid as a type', t) + self.note('Did you mean "List[...]"?', t) + return AnyType(TypeOfAny.from_error) def visit_callable_argument(self, t: CallableArgument) -> Type: self.fail('Invalid type', t) @@ -570,6 +633,9 @@ def visit_param_spec(self, t: ParamSpecType) -> Type: def visit_unpack_type(self, t: UnpackType) -> Type: raise NotImplementedError + def visit_parameters(self, t: Parameters) -> Type: + raise NotImplementedError("ParamSpec literals cannot have unbound TypeVars") + def visit_callable_type(self, t: CallableType, nested: bool = True) -> Type: # Every Callable can bind its own type variables, if they're not in the outer scope with self.tvar_scope_frame(): @@ -728,8 +794,15 @@ def visit_partial_type(self, t: PartialType) -> Type: assert False, "Internal error: Unexpected partial type" def visit_ellipsis_type(self, t: EllipsisType) -> Type: - self.fail('Unexpected "..."', t) - return AnyType(TypeOfAny.from_error) + if self.allow_param_spec_literals: + any_type = AnyType(TypeOfAny.explicit) + return Parameters([any_type, any_type], + [ARG_STAR, ARG_STAR2], + [None, None], + is_ellipsis_args=True) + else: + self.fail('Unexpected "..."', t) + return AnyType(TypeOfAny.from_error) def visit_type_type(self, t: TypeType) -> Type: return TypeType.make_normalized(self.anal_type(t.item), line=t.line) @@ -773,6 +846,48 @@ def analyze_callable_args_for_paramspec( fallback=fallback, ) + def analyze_callable_args_for_concatenate( + self, + callable_args: Type, + ret_type: Type, + fallback: Instance, + ) -> Optional[CallableType]: + """Construct a 'Callable[C, RET]', where C is Concatenate[..., P], returning None if we + cannot. + """ + if not isinstance(callable_args, UnboundType): + return None + sym = self.lookup_qualified(callable_args.name, callable_args) + if sym is None: + return None + if sym.node is None: + return None + if sym.node.fullname not in ('typing_extensions.Concatenate', 'typing.Concatenate'): + return None + + tvar_def = self.anal_type(callable_args, allow_param_spec=True) + if not isinstance(tvar_def, ParamSpecType): + return None + + # TODO: Use tuple[...] or Mapping[..] instead? + obj = self.named_type('builtins.object') + # ick, CallableType should take ParamSpecType + prefix = tvar_def.prefix + # we don't set the prefix here as generic arguments will get updated at some point + # in the future. CallableType.param_spec() accounts for this. + return CallableType( + [*prefix.arg_types, + ParamSpecType(tvar_def.name, tvar_def.fullname, tvar_def.id, ParamSpecFlavor.ARGS, + upper_bound=obj), + ParamSpecType(tvar_def.name, tvar_def.fullname, tvar_def.id, ParamSpecFlavor.KWARGS, + upper_bound=obj)], + [*prefix.arg_kinds, nodes.ARG_STAR, nodes.ARG_STAR2], + [*prefix.arg_names, None, None], + ret_type=ret_type, + fallback=fallback, + from_concatenate=True, + ) + def analyze_callable_type(self, t: UnboundType) -> Type: fallback = self.named_type('builtins.function') if len(t.args) == 0: @@ -804,6 +919,10 @@ def analyze_callable_type(self, t: UnboundType) -> Type: callable_args, ret_type, fallback + ) or self.analyze_callable_args_for_concatenate( + callable_args, + ret_type, + fallback ) if maybe_ret is None: # Callable[?, RET] (where ? is something invalid) @@ -1039,12 +1158,15 @@ def anal_type(self, t: Type, nested: bool = True, *, allow_param_spec: bool = Fa if (not allow_param_spec and isinstance(analyzed, ParamSpecType) and analyzed.flavor == ParamSpecFlavor.BARE): - self.fail('Invalid location for ParamSpec "{}"'.format(analyzed.name), t) - self.note( - 'You can use ParamSpec as the first argument to Callable, e.g., ' - "'Callable[{}, int]'".format(analyzed.name), - t - ) + if analyzed.prefix.arg_types: + self.fail('Invalid location for Concatenate', t) + else: + self.fail('Invalid location for ParamSpec "{}"'.format(analyzed.name), t) + self.note( + 'You can use ParamSpec as the first argument to Callable, e.g., ' + "'Callable[{}, int]'".format(analyzed.name), + t + ) return analyzed def anal_var_def(self, var_def: TypeVarLikeType) -> TypeVarLikeType: @@ -1089,6 +1211,15 @@ def tuple_type(self, items: List[Type]) -> TupleType: any_type = AnyType(TypeOfAny.special_form) return TupleType(items, fallback=self.named_type('builtins.tuple', [any_type])) + @contextmanager + def set_allow_param_spec_literals(self, to: bool) -> Iterator[None]: + old = self.allow_param_spec_literals + try: + self.allow_param_spec_literals = to + yield + finally: + self.allow_param_spec_literals = old + TypeVarLikeList = List[Tuple[str, TypeVarLikeExpr]] @@ -1280,7 +1411,7 @@ def __init__(self, def _seems_like_callable(self, type: UnboundType) -> bool: if not type.args: return False - if isinstance(type.args[0], (EllipsisType, TypeList)): + if isinstance(type.args[0], (EllipsisType, TypeList, ParamSpecType)): return True return False diff --git a/mypy/typeops.py b/mypy/typeops.py index fa05231109414..d97e9f7baf359 100644 --- a/mypy/typeops.py +++ b/mypy/typeops.py @@ -5,7 +5,7 @@ since these may assume that MROs are ready. """ -from typing import cast, Optional, List, Sequence, Set, Iterable, TypeVar, Dict, Tuple, Any +from typing import cast, Optional, List, Sequence, Set, Iterable, TypeVar, Dict, Tuple, Any, Union from typing_extensions import Type as TypingType import itertools import sys @@ -14,7 +14,7 @@ TupleType, Instance, FunctionLike, Type, CallableType, TypeVarLikeType, Overloaded, TypeVarType, UninhabitedType, FormalArgument, UnionType, NoneType, AnyType, TypeOfAny, TypeType, ProperType, LiteralType, get_proper_type, get_proper_types, - copy_type, TypeAliasType, TypeQuery, ParamSpecType, + copy_type, TypeAliasType, TypeQuery, ParamSpecType, Parameters, ENUM_REMOVED_PROPS ) from mypy.nodes import ( @@ -272,7 +272,7 @@ def erase_to_bound(t: Type) -> Type: return t -def callable_corresponding_argument(typ: CallableType, +def callable_corresponding_argument(typ: Union[CallableType, Parameters], model: FormalArgument) -> Optional[FormalArgument]: """Return the argument a function that corresponds to `model`""" diff --git a/mypy/types.py b/mypy/types.py index 465af1c50e337..06cf3f9e9dff8 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -559,26 +559,44 @@ class ParamSpecType(TypeVarLikeType): always just 'object'). """ - __slots__ = ('flavor',) + __slots__ = ('flavor', 'prefix') flavor: int + prefix: 'Parameters' def __init__( self, name: str, fullname: str, id: Union[TypeVarId, int], flavor: int, - upper_bound: Type, *, line: int = -1, column: int = -1 + upper_bound: Type, *, line: int = -1, column: int = -1, + prefix: Optional['Parameters'] = None ) -> None: super().__init__(name, fullname, id, upper_bound, line=line, column=column) self.flavor = flavor + self.prefix = prefix or Parameters([], [], []) @staticmethod def new_unification_variable(old: 'ParamSpecType') -> 'ParamSpecType': new_id = TypeVarId.new(meta_level=1) return ParamSpecType(old.name, old.fullname, new_id, old.flavor, old.upper_bound, - line=old.line, column=old.column) + line=old.line, column=old.column, prefix=old.prefix) def with_flavor(self, flavor: int) -> 'ParamSpecType': return ParamSpecType(self.name, self.fullname, self.id, flavor, - upper_bound=self.upper_bound) + upper_bound=self.upper_bound, prefix=self.prefix) + + def copy_modified(self, *, + id: Bogus[Union[TypeVarId, int]] = _dummy, + flavor: Bogus[int] = _dummy, + prefix: Bogus['Parameters'] = _dummy) -> 'ParamSpecType': + return ParamSpecType( + self.name, + self.fullname, + id if id is not _dummy else self.id, + flavor if flavor is not _dummy else self.flavor, + self.upper_bound, + line=self.line, + column=self.column, + prefix=prefix if prefix is not _dummy else self.prefix, + ) def accept(self, visitor: 'TypeVisitor[T]') -> T: return visitor.visit_param_spec(self) @@ -609,6 +627,7 @@ def serialize(self) -> JsonDict: 'id': self.id.raw_id, 'flavor': self.flavor, 'upper_bound': self.upper_bound.serialize(), + 'prefix': self.prefix.serialize() } @classmethod @@ -620,6 +639,7 @@ def deserialize(cls, data: JsonDict) -> 'ParamSpecType': data['id'], data['flavor'], deserialize_type(data['upper_bound']), + prefix=Parameters.deserialize(data['prefix']) ) @@ -1183,6 +1203,183 @@ def get_name(self) -> Optional[str]: pass ('required', bool)]) +# TODO: should this take bound typevars too? what would this take? +# ex: class Z(Generic[P, T]): ...; Z[[V], V] +# What does a typevar even mean in this context? +class Parameters(ProperType): + """Type that represents the parameters to a function. + + Used for ParamSpec analysis.""" + __slots__ = ('arg_types', + 'arg_kinds', + 'arg_names', + 'min_args', + 'is_ellipsis_args', + 'variables') + + def __init__(self, + arg_types: Sequence[Type], + arg_kinds: List[ArgKind], + arg_names: Sequence[Optional[str]], + *, + variables: Optional[Sequence[TypeVarLikeType]] = None, + is_ellipsis_args: bool = False, + line: int = -1, + column: int = -1 + ) -> None: + super().__init__(line, column) + self.arg_types = list(arg_types) + self.arg_kinds = arg_kinds + self.arg_names = list(arg_names) + assert len(arg_types) == len(arg_kinds) == len(arg_names) + self.min_args = arg_kinds.count(ARG_POS) + self.is_ellipsis_args = is_ellipsis_args + self.variables = variables or [] + + def copy_modified(self, + arg_types: Bogus[Sequence[Type]] = _dummy, + arg_kinds: Bogus[List[ArgKind]] = _dummy, + arg_names: Bogus[Sequence[Optional[str]]] = _dummy, + *, + variables: Bogus[Sequence[TypeVarLikeType]] = _dummy, + is_ellipsis_args: Bogus[bool] = _dummy + ) -> 'Parameters': + return Parameters( + arg_types=arg_types if arg_types is not _dummy else self.arg_types, + arg_kinds=arg_kinds if arg_kinds is not _dummy else self.arg_kinds, + arg_names=arg_names if arg_names is not _dummy else self.arg_names, + is_ellipsis_args=(is_ellipsis_args if is_ellipsis_args is not _dummy + else self.is_ellipsis_args), + variables=variables if variables is not _dummy else self.variables + ) + + # the following are copied from CallableType. Is there a way to decrease code duplication? + def var_arg(self) -> Optional[FormalArgument]: + """The formal argument for *args.""" + for position, (type, kind) in enumerate(zip(self.arg_types, self.arg_kinds)): + if kind == ARG_STAR: + return FormalArgument(None, position, type, False) + return None + + def kw_arg(self) -> Optional[FormalArgument]: + """The formal argument for **kwargs.""" + for position, (type, kind) in enumerate(zip(self.arg_types, self.arg_kinds)): + if kind == ARG_STAR2: + return FormalArgument(None, position, type, False) + return None + + def formal_arguments(self, include_star_args: bool = False) -> List[FormalArgument]: + """Yields the formal arguments corresponding to this callable, ignoring *arg and **kwargs. + + To handle *args and **kwargs, use the 'callable.var_args' and 'callable.kw_args' fields, + if they are not None. + + If you really want to include star args in the yielded output, set the + 'include_star_args' parameter to 'True'.""" + args = [] + done_with_positional = False + for i in range(len(self.arg_types)): + kind = self.arg_kinds[i] + if kind.is_named() or kind.is_star(): + done_with_positional = True + if not include_star_args and kind.is_star(): + continue + + required = kind.is_required() + pos = None if done_with_positional else i + arg = FormalArgument( + self.arg_names[i], + pos, + self.arg_types[i], + required + ) + args.append(arg) + return args + + def argument_by_name(self, name: Optional[str]) -> Optional[FormalArgument]: + if name is None: + return None + seen_star = False + for i, (arg_name, kind, typ) in enumerate( + zip(self.arg_names, self.arg_kinds, self.arg_types)): + # No more positional arguments after these. + if kind.is_named() or kind.is_star(): + seen_star = True + if kind.is_star(): + continue + if arg_name == name: + position = None if seen_star else i + return FormalArgument(name, position, typ, kind.is_required()) + return self.try_synthesizing_arg_from_kwarg(name) + + def argument_by_position(self, position: Optional[int]) -> Optional[FormalArgument]: + if position is None: + return None + if position >= len(self.arg_names): + return self.try_synthesizing_arg_from_vararg(position) + name, kind, typ = ( + self.arg_names[position], + self.arg_kinds[position], + self.arg_types[position], + ) + if kind.is_positional(): + return FormalArgument(name, position, typ, kind == ARG_POS) + else: + return self.try_synthesizing_arg_from_vararg(position) + + def try_synthesizing_arg_from_kwarg(self, + name: Optional[str]) -> Optional[FormalArgument]: + kw_arg = self.kw_arg() + if kw_arg is not None: + return FormalArgument(name, None, kw_arg.typ, False) + else: + return None + + def try_synthesizing_arg_from_vararg(self, + position: Optional[int]) -> Optional[FormalArgument]: + var_arg = self.var_arg() + if var_arg is not None: + return FormalArgument(None, position, var_arg.typ, False) + else: + return None + + def accept(self, visitor: 'TypeVisitor[T]') -> T: + return visitor.visit_parameters(self) + + def serialize(self) -> JsonDict: + return {'.class': 'Parameters', + 'arg_types': [t.serialize() for t in self.arg_types], + 'arg_kinds': [int(x.value) for x in self.arg_kinds], + 'arg_names': self.arg_names, + 'variables': [tv.serialize() for tv in self.variables], + } + + @classmethod + def deserialize(cls, data: JsonDict) -> 'Parameters': + assert data['.class'] == 'Parameters' + return Parameters( + [deserialize_type(t) for t in data['arg_types']], + [ArgKind(x) for x in data['arg_kinds']], + data['arg_names'], + variables=[cast(TypeVarLikeType, deserialize_type(v)) for v in data['variables']], + ) + + def __hash__(self) -> int: + return hash((self.is_ellipsis_args, tuple(self.arg_types), + tuple(self.arg_names), tuple(self.arg_kinds))) + + def __eq__(self, other: object) -> bool: + if isinstance(other, Parameters) or isinstance(other, CallableType): + return ( + self.arg_types == other.arg_types and + self.arg_names == other.arg_names and + self.arg_kinds == other.arg_kinds and + self.is_ellipsis_args == other.is_ellipsis_args + ) + else: + return NotImplemented + + class CallableType(FunctionLike): """Type of a non-overloaded callable object (such as function).""" @@ -1209,9 +1406,12 @@ class CallableType(FunctionLike): 'def_extras', # Information about original definition we want to serialize. # This is used for more detailed error messages. 'type_guard', # T, if -> TypeGuard[T] (ret_type is bool in this case). + 'from_concatenate', # whether this callable is from a concatenate object + # (this is used for error messages) ) def __init__(self, + # maybe this should be refactored to take a Parameters object arg_types: Sequence[Type], arg_kinds: List[ArgKind], arg_names: Sequence[Optional[str]], @@ -1229,6 +1429,7 @@ def __init__(self, bound_args: Sequence[Optional[Type]] = (), def_extras: Optional[Dict[str, Any]] = None, type_guard: Optional[Type] = None, + from_concatenate: bool = False ) -> None: super().__init__(line, column) assert len(arg_types) == len(arg_kinds) == len(arg_names) @@ -1248,6 +1449,7 @@ def __init__(self, self.implicit = implicit self.special_sig = special_sig self.from_type_type = from_type_type + self.from_concatenate = from_concatenate if not bound_args: bound_args = () self.bound_args = bound_args @@ -1290,6 +1492,7 @@ def copy_modified(self, bound_args: Bogus[List[Optional[Type]]] = _dummy, def_extras: Bogus[Dict[str, Any]] = _dummy, type_guard: Bogus[Optional[Type]] = _dummy, + from_concatenate: Bogus[bool] = _dummy, ) -> 'CallableType': return CallableType( arg_types=arg_types if arg_types is not _dummy else self.arg_types, @@ -1310,6 +1513,8 @@ def copy_modified(self, bound_args=bound_args if bound_args is not _dummy else self.bound_args, def_extras=def_extras if def_extras is not _dummy else dict(self.def_extras), type_guard=type_guard if type_guard is not _dummy else self.type_guard, + from_concatenate=(from_concatenate if from_concatenate is not _dummy + else self.from_concatenate), ) def var_arg(self) -> Optional[FormalArgument]: @@ -1468,13 +1673,32 @@ def param_spec(self) -> Optional[ParamSpecType]: arg_type = self.arg_types[-2] if not isinstance(arg_type, ParamSpecType): return None + # sometimes paramspectypes are analyzed in from mysterious places, + # e.g. def f(prefix..., *args: P.args, **kwargs: P.kwargs) -> ...: ... + prefix = arg_type.prefix + if not prefix.arg_types: + # TODO: confirm that all arg kinds are positional + prefix = Parameters(self.arg_types[:-2], self.arg_kinds[:-2], self.arg_names[:-2]) return ParamSpecType(arg_type.name, arg_type.fullname, arg_type.id, ParamSpecFlavor.BARE, - arg_type.upper_bound) - - def expand_param_spec(self, c: 'CallableType') -> 'CallableType': - return self.copy_modified(arg_types=self.arg_types[:-2] + c.arg_types, - arg_kinds=self.arg_kinds[:-2] + c.arg_kinds, - arg_names=self.arg_names[:-2] + c.arg_names) + arg_type.upper_bound, prefix=prefix) + + def expand_param_spec(self, + c: Union['CallableType', Parameters], + no_prefix: bool = False) -> 'CallableType': + variables = c.variables + + if no_prefix: + return self.copy_modified(arg_types=c.arg_types, + arg_kinds=c.arg_kinds, + arg_names=c.arg_names, + is_ellipsis_args=c.is_ellipsis_args, + variables=[*variables, *self.variables]) + else: + return self.copy_modified(arg_types=self.arg_types[:-2] + c.arg_types, + arg_kinds=self.arg_kinds[:-2] + c.arg_kinds, + arg_names=self.arg_names[:-2] + c.arg_names, + is_ellipsis_args=c.is_ellipsis_args, + variables=[*variables, *self.variables]) def __hash__(self) -> int: return hash((self.ret_type, self.is_type_obj(), @@ -1511,6 +1735,7 @@ def serialize(self) -> JsonDict: for t in self.bound_args], 'def_extras': dict(self.def_extras), 'type_guard': self.type_guard.serialize() if self.type_guard is not None else None, + 'from_concatenate': self.from_concatenate, } @classmethod @@ -1531,6 +1756,7 @@ def deserialize(cls, data: JsonDict) -> 'CallableType': def_extras=data['def_extras'], type_guard=(deserialize_type(data['type_guard']) if data['type_guard'] is not None else None), + from_concatenate=data['from_concatenate'], ) @@ -2362,14 +2588,49 @@ def visit_type_var(self, t: TypeVarType) -> str: return s def visit_param_spec(self, t: ParamSpecType) -> str: + # prefixes are displayed as Concatenate + s = '' + if t.prefix.arg_types: + s += f'[{self.list_str(t.prefix.arg_types)}, **' if t.name is None: # Anonymous type variable type (only numeric id). - s = f'`{t.id}' + s += f'`{t.id}' else: # Named type variable type. - s = f'{t.name_with_suffix()}`{t.id}' + s += f'{t.name_with_suffix()}`{t.id}' + if t.prefix.arg_types: + s += ']' return s + def visit_parameters(self, t: Parameters) -> str: + # This is copied from visit_callable -- is there a way to decrease duplication? + if t.is_ellipsis_args: + return '...' + + s = '' + bare_asterisk = False + for i in range(len(t.arg_types)): + if s != '': + s += ', ' + if t.arg_kinds[i].is_named() and not bare_asterisk: + s += '*, ' + bare_asterisk = True + if t.arg_kinds[i] == ARG_STAR: + s += '*' + if t.arg_kinds[i] == ARG_STAR2: + s += '**' + name = t.arg_names[i] + if name: + s += f'{name}: ' + r = t.arg_types[i].accept(self) + + s += r + + if t.arg_kinds[i].is_optional(): + s += ' =' + + return f'[{s}]' + def visit_callable_type(self, t: CallableType) -> str: param_spec = t.param_spec() if param_spec is not None: diff --git a/mypy/typetraverser.py b/mypy/typetraverser.py index 7bfae5aed1c27..94eeee79be93c 100644 --- a/mypy/typetraverser.py +++ b/mypy/typetraverser.py @@ -6,7 +6,7 @@ Type, SyntheticTypeVisitor, AnyType, UninhabitedType, NoneType, ErasedType, DeletedType, TypeVarType, LiteralType, Instance, CallableType, TupleType, TypedDictType, UnionType, Overloaded, TypeType, CallableArgument, UnboundType, TypeList, StarType, EllipsisType, - PlaceholderType, PartialType, RawExpressionType, TypeAliasType, ParamSpecType, + PlaceholderType, PartialType, RawExpressionType, TypeAliasType, ParamSpecType, Parameters, UnpackType ) @@ -41,6 +41,9 @@ def visit_type_var(self, t: TypeVarType) -> None: def visit_param_spec(self, t: ParamSpecType) -> None: pass + def visit_parameters(self, t: Parameters) -> None: + self.traverse_types(t.arg_types) + def visit_literal_type(self, t: LiteralType) -> None: t.fallback.accept(self) diff --git a/test-data/unit/check-parameter-specification.test b/test-data/unit/check-parameter-specification.test index 7b41db2c94d63..fe2354612fbb9 100644 --- a/test-data/unit/check-parameter-specification.test +++ b/test-data/unit/check-parameter-specification.test @@ -25,8 +25,7 @@ def foo1(x: Callable[P, int]) -> Callable[P, str]: ... def foo2(x: P) -> P: ... # E: Invalid location for ParamSpec "P" \ # N: You can use ParamSpec as the first argument to Callable, e.g., 'Callable[P, int]' -# TODO(PEP612): uncomment once we have support for Concatenate -# def foo3(x: Concatenate[int, P]) -> int: ... $ E: Invalid location for Concatenate +def foo3(x: Concatenate[int, P]) -> int: ... # E: Invalid location for Concatenate def foo4(x: List[P]) -> None: ... # E: Invalid location for ParamSpec "P" \ # N: You can use ParamSpec as the first argument to Callable, e.g., 'Callable[P, int]' @@ -100,7 +99,7 @@ class C(Generic[P]): def f(x: int, y: str) -> None: ... -reveal_type(C(f)) # N: Revealed type is "__main__.C[def (x: builtins.int, y: builtins.str)]" +reveal_type(C(f)) # N: Revealed type is "__main__.C[[x: builtins.int, y: builtins.str]]" reveal_type(C(f).m) # N: Revealed type is "def (x: builtins.int, y: builtins.str) -> builtins.int" [builtins fixtures/dict.pyi] @@ -142,7 +141,7 @@ def dec() -> Callable[[Callable[P, R]], W[P, R]]: @dec() def f(a: int, b: str) -> None: ... -reveal_type(f) # N: Revealed type is "__main__.W[def (a: builtins.int, b: builtins.str), None]" +reveal_type(f) # N: Revealed type is "__main__.W[[a: builtins.int, b: builtins.str], None]" reveal_type(f(1, '')) # N: Revealed type is "None" reveal_type(f.x) # N: Revealed type is "builtins.int" @@ -416,3 +415,614 @@ with f() as x: pass [builtins fixtures/dict.pyi] [typing fixtures/typing-full.pyi] + +[case testParamSpecLiterals] +from typing_extensions import ParamSpec, TypeAlias +from typing import Generic, TypeVar + +P = ParamSpec("P") +T = TypeVar("T") + +class Z(Generic[P]): ... + +# literals can be applied +n: Z[[int]] + +# TODO: type aliases too +nt1 = Z[[int]] +nt2: TypeAlias = Z[[int]] + +unt1: nt1 +unt2: nt2 + +# literals actually keep types +reveal_type(n) # N: Revealed type is "__main__.Z[[builtins.int]]" +reveal_type(unt1) # N: Revealed type is "__main__.Z[[builtins.int]]" +reveal_type(unt2) # N: Revealed type is "__main__.Z[[builtins.int]]" + +# passing into a function keeps the type +def fT(a: T) -> T: ... +def fP(a: Z[P]) -> Z[P]: ... + +reveal_type(fT(n)) # N: Revealed type is "__main__.Z[[builtins.int]]" +reveal_type(fP(n)) # N: Revealed type is "__main__.Z[[builtins.int]]" + +# literals can be in function args and return type +def k(a: Z[[int]]) -> Z[[str]]: ... + +# functions work +reveal_type(k(n)) # N: Revealed type is "__main__.Z[[builtins.str]]" + +# literals can be matched in arguments +def kb(a: Z[[bytes]]) -> Z[[str]]: ... + +reveal_type(kb(n)) # N: Revealed type is "__main__.Z[[builtins.str]]" \ + # E: Argument 1 to "kb" has incompatible type "Z[[int]]"; expected "Z[[bytes]]" + + +n2: Z[bytes] + +reveal_type(kb(n2)) # N: Revealed type is "__main__.Z[[builtins.str]]" +[builtins fixtures/tuple.pyi] + +[case testParamSpecConcatenateFromPep] +from typing_extensions import ParamSpec, Concatenate +from typing import Callable, TypeVar, Generic + +P = ParamSpec("P") +R = TypeVar("R") + +# CASE 1 +class Request: + ... + +def with_request(f: Callable[Concatenate[Request, P], R]) -> Callable[P, R]: + def inner(*args: P.args, **kwargs: P.kwargs) -> R: + return f(Request(), *args, **kwargs) + return inner + +@with_request +def takes_int_str(request: Request, x: int, y: str) -> int: + # use request + return x + 7 + +reveal_type(takes_int_str) # N: Revealed type is "def (x: builtins.int, y: builtins.str) -> builtins.int" + +takes_int_str(1, "A") # Accepted +takes_int_str("B", 2) # E: Argument 1 to "takes_int_str" has incompatible type "str"; expected "int" \ + # E: Argument 2 to "takes_int_str" has incompatible type "int"; expected "str" + +# CASE 2 +T = TypeVar("T") +P_2 = ParamSpec("P_2") + +class X(Generic[T, P]): + f: Callable[P, int] + x: T + +def f1(x: X[int, P_2]) -> str: ... # Accepted +def f2(x: X[int, Concatenate[int, P_2]]) -> str: ... # Accepted +def f3(x: X[int, [int, bool]]) -> str: ... # Accepted +# ellipsis only show up here, but I can assume it works like Callable[..., R] +def f4(x: X[int, ...]) -> str: ... # Accepted +# TODO: this is not rejected: +# def f5(x: X[int, int]) -> str: ... # Rejected + +# CASE 3 +def bar(x: int, *args: bool) -> int: ... +def add(x: Callable[P, int]) -> Callable[Concatenate[str, P], bool]: ... + +reveal_type(add(bar)) # N: Revealed type is "def (builtins.str, x: builtins.int, *args: builtins.bool) -> builtins.bool" + +def remove(x: Callable[Concatenate[int, P], int]) -> Callable[P, bool]: ... + +reveal_type(remove(bar)) # N: Revealed type is "def (*args: builtins.bool) -> builtins.bool" + +def transform( + x: Callable[Concatenate[int, P], int] +) -> Callable[Concatenate[str, P], bool]: ... + +# In the PEP, "__a" appears. What is that? Autogenerated names? To what spec? +reveal_type(transform(bar)) # N: Revealed type is "def (builtins.str, *args: builtins.bool) -> builtins.bool" + +# CASE 4 +def expects_int_first(x: Callable[Concatenate[int, P], int]) -> None: ... + +@expects_int_first # E: Argument 1 to "expects_int_first" has incompatible type "Callable[[str], int]"; expected "Callable[[int], int]" \ + # N: This may be because "one" has arguments named: "x" +def one(x: str) -> int: ... + +@expects_int_first # E: Argument 1 to "expects_int_first" has incompatible type "Callable[[NamedArg(int, 'x')], int]"; expected "Callable[[int], int]" +def two(*, x: int) -> int: ... + +@expects_int_first # E: Argument 1 to "expects_int_first" has incompatible type "Callable[[KwArg(int)], int]"; expected "Callable[[int], int]" +def three(**kwargs: int) -> int: ... + +@expects_int_first # Accepted +def four(*args: int) -> int: ... +[builtins fixtures/tuple.pyi] +[builtins fixtures/dict.pyi] + +[case testParamSpecTwiceSolving] +from typing_extensions import ParamSpec, Concatenate +from typing import Callable, TypeVar + +P = ParamSpec("P") +R = TypeVar("R") + +def f(one: Callable[Concatenate[int, P], R], two: Callable[Concatenate[str, P], R]) -> Callable[P, R]: ... + +a: Callable[[int, bytes], str] +b: Callable[[str, bytes], str] + +reveal_type(f(a, b)) # N: Revealed type is "def (builtins.bytes) -> builtins.str" +[builtins fixtures/tuple.pyi] + +[case testParamSpecConcatenateInReturn] +from typing_extensions import ParamSpec, Concatenate +from typing import Callable, Protocol + +P = ParamSpec("P") + +def f(i: Callable[Concatenate[int, P], str]) -> Callable[Concatenate[int, P], str]: ... + +n: Callable[[int, bytes], str] + +reveal_type(f(n)) # N: Revealed type is "def (builtins.int, builtins.bytes) -> builtins.str" +[builtins fixtures/tuple.pyi] + +[case testParamSpecConcatenateNamedArgs] +# flags: --strict-concatenate +# this is one noticeable deviation from PEP but I believe it is for the better +from typing_extensions import ParamSpec, Concatenate +from typing import Callable, TypeVar + +P = ParamSpec("P") +R = TypeVar("R") + +def f1(c: Callable[P, R]) -> Callable[Concatenate[int, P], R]: + def result(x: int, /, *args: P.args, **kwargs: P.kwargs) -> R: ... + + return result # Accepted + +def f2(c: Callable[P, R]) -> Callable[Concatenate[int, P], R]: + def result(x: int, *args: P.args, **kwargs: P.kwargs) -> R: ... + + return result # Rejected + +# reason for rejection: +f2(lambda x: 42)(42, x=42) +[builtins fixtures/tuple.pyi] +[out] +main:10: error: invalid syntax +[out version>=3.8] +main:17: error: Incompatible return value type (got "Callable[[Arg(int, 'x'), **P], R]", expected "Callable[[int, **P], R]") +main:17: note: This may be because "result" has arguments named: "x" + +[case testNonStrictParamSpecConcatenateNamedArgs] +# this is one noticeable deviation from PEP but I believe it is for the better +from typing_extensions import ParamSpec, Concatenate +from typing import Callable, TypeVar + +P = ParamSpec("P") +R = TypeVar("R") + +def f1(c: Callable[P, R]) -> Callable[Concatenate[int, P], R]: + def result(x: int, /, *args: P.args, **kwargs: P.kwargs) -> R: ... + + return result # Accepted + +def f2(c: Callable[P, R]) -> Callable[Concatenate[int, P], R]: + def result(x: int, *args: P.args, **kwargs: P.kwargs) -> R: ... + + return result # Rejected -> Accepted + +# reason for rejection: +f2(lambda x: 42)(42, x=42) +[builtins fixtures/tuple.pyi] +[out] +main:9: error: invalid syntax +[out version>=3.8] + +[case testParamSpecConcatenateWithTypeVar] +from typing_extensions import ParamSpec, Concatenate +from typing import Callable, TypeVar + +P = ParamSpec("P") +R = TypeVar("R") +S = TypeVar("S") + +def f(c: Callable[Concatenate[S, P], R]) -> Callable[Concatenate[S, P], R]: ... + +def a(n: int) -> None: ... + +n = f(a) + +reveal_type(n) # N: Revealed type is "def (builtins.int)" +reveal_type(n(42)) # N: Revealed type is "None" +[builtins fixtures/tuple.pyi] + +[case testCallablesAsParameters] +# credits to https://github.com/microsoft/pyright/issues/2705 +from typing_extensions import ParamSpec, Concatenate +from typing import Generic, Callable, Any + +P = ParamSpec("P") + +class Foo(Generic[P]): + def __init__(self, func: Callable[P, Any]) -> None: ... +def bar(baz: Foo[Concatenate[int, P]]) -> Foo[P]: ... + +def test(a: int, /, b: str) -> str: ... + +abc = Foo(test) +reveal_type(abc) +bar(abc) +[builtins fixtures/tuple.pyi] +[out] +main:11: error: invalid syntax +[out version>=3.8] +main:14: note: Revealed type is "__main__.Foo[[builtins.int, b: builtins.str]]" + +[case testSolveParamSpecWithSelfType] +from typing_extensions import ParamSpec, Concatenate +from typing import Callable, Generic + +P = ParamSpec("P") + +class Foo(Generic[P]): + def foo(self: 'Foo[P]', other: Callable[P, None]) -> None: ... + +n: Foo[[int]] +def f(x: int) -> None: ... + +n.foo(f) +[builtins fixtures/tuple.pyi] + +[case testParamSpecLiteralsTypeApplication] +from typing_extensions import ParamSpec +from typing import Generic, Callable + +P = ParamSpec("P") + +class Z(Generic[P]): + def __init__(self, c: Callable[P, None]) -> None: + ... + +# it allows valid functions +reveal_type(Z[[int]](lambda x: None)) # N: Revealed type is "__main__.Z[[builtins.int]]" +reveal_type(Z[[]](lambda: None)) # N: Revealed type is "__main__.Z[[]]" +reveal_type(Z[bytes, str](lambda b, s: None)) # N: Revealed type is "__main__.Z[[builtins.bytes, builtins.str]]" + +# it disallows invalid functions +def f1(n: str) -> None: ... +def f2(b: bytes, i: int) -> None: ... + +Z[[int]](lambda one, two: None) # E: Cannot infer type of lambda \ + # E: Argument 1 to "Z" has incompatible type "Callable[[Any, Any], None]"; expected "Callable[[int], None]" +Z[[int]](f1) # E: Argument 1 to "Z" has incompatible type "Callable[[str], None]"; expected "Callable[[int], None]" + +Z[[]](lambda one: None) # E: Cannot infer type of lambda \ + # E: Argument 1 to "Z" has incompatible type "Callable[[Any], None]"; expected "Callable[[], None]" + +Z[bytes, str](lambda one: None) # E: Cannot infer type of lambda \ + # E: Argument 1 to "Z" has incompatible type "Callable[[Any], None]"; expected "Callable[[bytes, str], None]" +Z[bytes, str](f2) # E: Argument 1 to "Z" has incompatible type "Callable[[bytes, int], None]"; expected "Callable[[bytes, str], None]" + +[builtins fixtures/tuple.pyi] + +[case testParamSpecLiteralEllipsis] +from typing_extensions import ParamSpec +from typing import Generic, Callable + +P = ParamSpec("P") + +class Z(Generic[P]): + def __init__(self: 'Z[P]', c: Callable[P, None]) -> None: + ... + +def f1() -> None: ... +def f2(*args: int) -> None: ... +def f3(a: int, *, b: bytes) -> None: ... + +def f4(b: bytes) -> None: ... + +argh: Callable[..., None] = f4 + +# check it works +Z[...](f1) +Z[...](f2) +Z[...](f3) + +# check subtyping works +n: Z[...] +n = Z(f1) +n = Z(f2) +n = Z(f3) + +[builtins fixtures/tuple.pyi] + +[case testParamSpecApplyConcatenateTwice] +from typing_extensions import ParamSpec, Concatenate +from typing import Generic, Callable, Optional + +P = ParamSpec("P") + +class C(Generic[P]): + # think PhantomData from rust + phantom: Optional[Callable[P, None]] + + def add_str(self) -> C[Concatenate[int, P]]: + return C[Concatenate[int, P]]() + + def add_int(self) -> C[Concatenate[str, P]]: + return C[Concatenate[str, P]]() + +def f(c: C[P]) -> None: + reveal_type(c) # N: Revealed type is "__main__.C[P`-1]" + + n1 = c.add_str() + reveal_type(n1) # N: Revealed type is "__main__.C[[builtins.int, **P`-1]]" + n2 = n1.add_int() + reveal_type(n2) # N: Revealed type is "__main__.C[[builtins.str, builtins.int, **P`-1]]" + + p1 = c.add_int() + reveal_type(p1) # N: Revealed type is "__main__.C[[builtins.str, **P`-1]]" + p2 = p1.add_str() + reveal_type(p2) # N: Revealed type is "__main__.C[[builtins.int, builtins.str, **P`-1]]" +[builtins fixtures/tuple.pyi] + +[case testParamSpecLiteralJoin] +from typing import Generic, Callable, Union +from typing_extensions import ParamSpec + + +_P = ParamSpec("_P") + +class Job(Generic[_P]): + def __init__(self, target: Callable[_P, None]) -> None: + self.target = target + +def func( + action: Union[Job[int], Callable[[int], None]], +) -> None: + job = action if isinstance(action, Job) else Job(action) + reveal_type(job) # N: Revealed type is "__main__.Job[[builtins.int]]" +[builtins fixtures/tuple.pyi] + +[case testApplyParamSpecToParamSpecLiterals] +from typing import TypeVar, Generic, Callable +from typing_extensions import ParamSpec + +_P = ParamSpec("_P") +_R_co = TypeVar("_R_co", covariant=True) + +class Job(Generic[_P, _R_co]): + def __init__(self, target: Callable[_P, _R_co]) -> None: + self.target = target + +def run_job(job: Job[_P, None], *args: _P.args, **kwargs: _P.kwargs) -> None: # N: "run_job" defined here + ... + + +def func(job: Job[[int, str], None]) -> None: + run_job(job, 42, "Hello") + run_job(job, "Hello", 42) # E: Argument 2 to "run_job" has incompatible type "str"; expected "int" \ + # E: Argument 3 to "run_job" has incompatible type "int"; expected "str" + run_job(job, 42, msg="Hello") # E: Unexpected keyword argument "msg" for "run_job" + run_job(job, "Hello") # E: Too few arguments for "run_job" \ + # E: Argument 2 to "run_job" has incompatible type "str"; expected "int" + +def func2(job: Job[..., None]) -> None: + run_job(job, 42, "Hello") + run_job(job, "Hello", 42) + run_job(job, 42, msg="Hello") + run_job(job, x=42, msg="Hello") +[builtins fixtures/tuple.pyi] + +[case testExpandNonBareParamSpecAgainstCallable] +from typing import Callable, TypeVar, Any +from typing_extensions import ParamSpec + +CallableT = TypeVar("CallableT", bound=Callable[..., Any]) +_P = ParamSpec("_P") +_R = TypeVar("_R") + +def simple_decorator(callable: CallableT) -> CallableT: + # set some attribute on 'callable' + return callable + + +class A: + @simple_decorator + def func(self, action: Callable[_P, _R], *args: _P.args, **kwargs: _P.kwargs) -> _R: + ... + +reveal_type(A.func) # N: Revealed type is "def [_P, _R] (self: __main__.A, action: def (*_P.args, **_P.kwargs) -> _R`-2, *_P.args, **_P.kwargs) -> _R`-2" + +# TODO: _R` keeps flip-flopping between 5 (?), 13, 14, 15. Spooky. +# reveal_type(A().func) $ N: Revealed type is "def [_P, _R] (action: def (*_P.args, **_P.kwargs) -> _R`13, *_P.args, **_P.kwargs) -> _R`13" + +def f(x: int) -> int: + ... + +reveal_type(A().func(f, 42)) # N: Revealed type is "builtins.int" + +# TODO: this should reveal `int` +reveal_type(A().func(lambda x: x + x, 42)) # N: Revealed type is "Any" +[builtins fixtures/tuple.pyi] + +[case testParamSpecConstraintOnOtherParamSpec] +from typing import Callable, TypeVar, Any, Generic +from typing_extensions import ParamSpec + +CallableT = TypeVar("CallableT", bound=Callable[..., Any]) +_P = ParamSpec("_P") +_R_co = TypeVar("_R_co", covariant=True) + +def simple_decorator(callable: CallableT) -> CallableT: + ... + +class Job(Generic[_P, _R_co]): + def __init__(self, target: Callable[_P, _R_co]) -> None: + ... + + +class A: + @simple_decorator + def func(self, action: Job[_P, None]) -> Job[_P, None]: + ... + +reveal_type(A.func) # N: Revealed type is "def [_P] (self: __main__.A, action: __main__.Job[_P`-1, None]) -> __main__.Job[_P`-1, None]" +# TODO: flakey, _P`4 alternates around. +# reveal_type(A().func) $ N: Revealed type is "def [_P] (action: __main__.Job[_P`4, None]) -> __main__.Job[_P`4, None]" +reveal_type(A().func(Job(lambda x: x))) # N: Revealed type is "__main__.Job[[x: Any], None]" + +def f(x: int, y: int) -> None: ... +reveal_type(A().func(Job(f))) # N: Revealed type is "__main__.Job[[x: builtins.int, y: builtins.int], None]" +[builtins fixtures/tuple.pyi] + +[case testConstraintBetweenParamSpecFunctions1] +from typing import Callable, TypeVar, Any, Generic +from typing_extensions import ParamSpec + +_P = ParamSpec("_P") +_R_co = TypeVar("_R_co", covariant=True) + +def simple_decorator(callable: Callable[_P, _R_co]) -> Callable[_P, _R_co]: ... +class Job(Generic[_P]): ... + + +@simple_decorator +def func(__action: Job[_P]) -> Callable[_P, None]: + ... + +reveal_type(func) # N: Revealed type is "def [_P] (__main__.Job[_P`-1]) -> def (*_P.args, **_P.kwargs)" +[builtins fixtures/tuple.pyi] + +[case testConstraintBetweenParamSpecFunctions2] +from typing import Callable, TypeVar, Any, Generic +from typing_extensions import ParamSpec + +CallableT = TypeVar("CallableT", bound=Callable[..., Any]) +_P = ParamSpec("_P") + +def simple_decorator(callable: CallableT) -> CallableT: ... +class Job(Generic[_P]): ... + + +@simple_decorator +def func(__action: Job[_P]) -> Callable[_P, None]: + ... + +reveal_type(func) # N: Revealed type is "def [_P] (__main__.Job[_P`-1]) -> def (*_P.args, **_P.kwargs)" +[builtins fixtures/tuple.pyi] + +[case testConstraintsBetweenConcatenatePrefixes] +from typing import Any, Callable, Generic, TypeVar +from typing_extensions import Concatenate, ParamSpec + +_P = ParamSpec("_P") +_T = TypeVar("_T") + +class Awaitable(Generic[_T]): ... + +def adds_await() -> Callable[ + [Callable[Concatenate[_T, _P], None]], + Callable[Concatenate[_T, _P], Awaitable[None]], +]: + def decorator( + func: Callable[Concatenate[_T, _P], None], + ) -> Callable[Concatenate[_T, _P], Awaitable[None]]: + ... + + return decorator # we want `_T` and `_P` to refer to the same things. +[builtins fixtures/tuple.pyi] + +[case testParamSpecVariance] +from typing import Callable, Generic +from typing_extensions import ParamSpec + +_P = ParamSpec("_P") + +class Job(Generic[_P]): + def __init__(self, target: Callable[_P, None]) -> None: ... + def into_callable(self) -> Callable[_P, None]: ... + +class A: + def func(self, var: int) -> None: ... + def other_func(self, job: Job[[int]]) -> None: ... + + +job = Job(A().func) +reveal_type(job) # N: Revealed type is "__main__.Job[[var: builtins.int]]" +A().other_func(job) # This should NOT error (despite the keyword) + +# and yet the keyword should remain +job.into_callable()(var=42) +job.into_callable()(x=42) # E: Unexpected keyword argument "x" + +# similar for other functions +def f1(n: object) -> None: ... +def f2(n: int) -> None: ... +def f3(n: bool) -> None: ... + +# just like how this is legal... +a1: Callable[[bool], None] +a1 = f3 +a1 = f2 +a1 = f1 + +# ... this is also legal +a2: Job[[bool]] +a2 = Job(f3) +a2 = Job(f2) +a2 = Job(f1) + +# and this is not legal +def f4(n: bytes) -> None: ... +a1 = f4 # E: Incompatible types in assignment (expression has type "Callable[[bytes], None]", variable has type "Callable[[bool], None]") +a2 = Job(f4) # E: Argument 1 to "Job" has incompatible type "Callable[[bytes], None]"; expected "Callable[[bool], None]" + +# nor is this: +a4: Job[[int]] +a4 = Job(f3) # E: Argument 1 to "Job" has incompatible type "Callable[[bool], None]"; expected "Callable[[int], None]" +a4 = Job(f2) +a4 = Job(f1) + +# just like this: +a3: Callable[[int], None] +a3 = f3 # E: Incompatible types in assignment (expression has type "Callable[[bool], None]", variable has type "Callable[[int], None]") +a3 = f2 +a3 = f1 +[builtins fixtures/tuple.pyi] + +[case testGenericsInInferredParamspec] +from typing import Callable, TypeVar, Generic +from typing_extensions import ParamSpec + +_P = ParamSpec("_P") +_T = TypeVar("_T") + +class Job(Generic[_P]): + def __init__(self, target: Callable[_P, None]) -> None: ... + def into_callable(self) -> Callable[_P, None]: ... + +def generic_f(x: _T) -> None: ... + +j = Job(generic_f) +reveal_type(j) # N: Revealed type is "__main__.Job[[x: _T`-1]]" + +jf = j.into_callable() +reveal_type(jf) # N: Revealed type is "def [_T] (x: _T`-1)" +reveal_type(jf(1)) # N: Revealed type is "None" +[builtins fixtures/tuple.pyi] + +[case testStackedConcatenateIsIllegal] +from typing_extensions import Concatenate, ParamSpec +from typing import Callable + +P = ParamSpec("P") + +def x(f: Callable[Concatenate[int, Concatenate[int, P]], None]) -> None: ... # E: Nested Concatenates are invalid +[builtins fixtures/tuple.pyi] From e7e1db6a5ad3d07a7a4d46cf280e972f2342a90f Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 7 Apr 2022 11:06:19 +0100 Subject: [PATCH 217/377] Improve checking of "__slots__" (#12531) Don't rely on `object.__slots__` being defined, since it's not defined at runtime (and currently it's removed in typeshed). --- mypy/checker.py | 14 ++++++++++++++ mypy/message_registry.py | 1 + mypy/typeshed/stdlib/builtins.pyi | 1 - test-data/unit/pythoneval.test | 8 ++++++-- 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index d0f6922fdf5e2..a8c8aee4fb2ce 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -1439,6 +1439,17 @@ def check_setattr_method(self, typ: Type, context: Context) -> None: if not is_subtype(typ, method_type): self.msg.invalid_signature_for_special_method(typ, context, '__setattr__') + def check_slots_definition(self, typ: Type, context: Context) -> None: + """Check the type of __slots__.""" + str_type = self.named_type("builtins.str") + expected_type = UnionType([str_type, + self.named_generic_type("typing.Iterable", [str_type])]) + self.check_subtype(typ, expected_type, context, + message_registry.INVALID_TYPE_FOR_SLOTS, + 'actual type', + 'expected type', + code=codes.ASSIGNMENT) + def check_match_args(self, var: Var, typ: Type, context: Context) -> None: """Check that __match_args__ contains literal strings""" typ = get_proper_type(typ) @@ -2281,6 +2292,9 @@ def check_assignment(self, lvalue: Lvalue, rvalue: Expression, infer_lvalue_type else: self.check_getattr_method(signature, lvalue, name) + if name == '__slots__': + typ = lvalue_type or self.expr_checker.accept(rvalue) + self.check_slots_definition(typ, lvalue) if name == '__match_args__' and inferred is not None: typ = self.expr_checker.accept(rvalue) self.check_match_args(inferred, typ, lvalue) diff --git a/mypy/message_registry.py b/mypy/message_registry.py index 8b5452d5753d6..0f14d706ccca2 100644 --- a/mypy/message_registry.py +++ b/mypy/message_registry.py @@ -60,6 +60,7 @@ def format(self, *args: object, **kwargs: object) -> "ErrorMessage": 'Incompatible types in "async with" for "__aexit__"' ) INCOMPATIBLE_TYPES_IN_ASYNC_FOR: Final = 'Incompatible types in "async for"' +INVALID_TYPE_FOR_SLOTS: Final = 'Invalid type for "__slots__"' ASYNC_FOR_OUTSIDE_COROUTINE: Final = '"async for" outside async function' ASYNC_WITH_OUTSIDE_COROUTINE: Final = '"async with" outside async function' diff --git a/mypy/typeshed/stdlib/builtins.pyi b/mypy/typeshed/stdlib/builtins.pyi index 5547afc217f64..b38d645ef9fc4 100644 --- a/mypy/typeshed/stdlib/builtins.pyi +++ b/mypy/typeshed/stdlib/builtins.pyi @@ -85,7 +85,6 @@ class _SupportsAiter(Protocol[_T_co]): class object: __doc__: str | None __dict__: dict[str, Any] - __slots__: str | Iterable[str] __module__: str __annotations__: dict[str, Any] @property diff --git a/test-data/unit/pythoneval.test b/test-data/unit/pythoneval.test index a0b98d2501c75..bba2885bf77be 100644 --- a/test-data/unit/pythoneval.test +++ b/test-data/unit/pythoneval.test @@ -1312,13 +1312,17 @@ f(E) g(E) [case testInvalidSlots] +from typing import List class A: __slots__ = 1 class B: __slots__ = (1, 2) +class C: + __slots__: List[int] = [] [out] -_testInvalidSlots.py:2: error: Incompatible types in assignment (expression has type "int", base class "object" defined the type as "Union[str, Iterable[str]]") -_testInvalidSlots.py:4: error: Incompatible types in assignment (expression has type "Tuple[int, int]", base class "object" defined the type as "Union[str, Iterable[str]]") +_testInvalidSlots.py:3: error: Invalid type for "__slots__" (actual type "int", expected type "Union[str, Iterable[str]]") +_testInvalidSlots.py:5: error: Invalid type for "__slots__" (actual type "Tuple[int, int]", expected type "Union[str, Iterable[str]]") +_testInvalidSlots.py:7: error: Invalid type for "__slots__" (actual type "List[int]", expected type "Union[str, Iterable[str]]") [case testDictWithStarStarSpecialCase] from typing import Dict From ab1b48808897d73d6f269c51fc29e5c8078fd303 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 7 Apr 2022 14:00:08 +0100 Subject: [PATCH 218/377] Speed up Instance.__hash__ (#12538) This shows up as a bottleneck in some use cases, based on profiling. This should help with union simplification (#12526). --- mypy/types.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/mypy/types.py b/mypy/types.py index 06cf3f9e9dff8..487dd1387bad3 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -1049,7 +1049,7 @@ def try_getting_instance_fallback(typ: ProperType) -> Optional[Instance]: """ - __slots__ = ('type', 'args', 'invalid', 'type_ref', 'last_known_value') + __slots__ = ('type', 'args', 'invalid', 'type_ref', 'last_known_value', '_hash') def __init__(self, typ: mypy.nodes.TypeInfo, args: Sequence[Type], line: int = -1, column: int = -1, *, @@ -1107,11 +1107,16 @@ def __init__(self, typ: mypy.nodes.TypeInfo, args: Sequence[Type], # Literal context. self.last_known_value = last_known_value + # Cached hash value + self._hash = -1 + def accept(self, visitor: 'TypeVisitor[T]') -> T: return visitor.visit_instance(self) def __hash__(self) -> int: - return hash((self.type, tuple(self.args), self.last_known_value)) + if self._hash == -1: + self._hash = hash((self.type, self.args, self.last_known_value)) + return self._hash def __eq__(self, other: object) -> bool: if not isinstance(other, Instance): From 75e907d95f99da5b21e83caa94b5734459ce8916 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 7 Apr 2022 17:27:53 +0100 Subject: [PATCH 219/377] Speed up LiteralType.__hash__ (#12540) It can be a bottleneck in some use cases. --- mypy/types.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mypy/types.py b/mypy/types.py index 487dd1387bad3..07f7cc845773c 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -2130,13 +2130,14 @@ class LiteralType(ProperType): As another example, `Literal[Color.RED]` (where Color is an enum) is represented as `LiteralType(value="RED", fallback=instance_of_color)'. """ - __slots__ = ('value', 'fallback') + __slots__ = ('value', 'fallback', '_hash') def __init__(self, value: LiteralValue, fallback: Instance, line: int = -1, column: int = -1) -> None: self.value = value super().__init__(line, column) self.fallback = fallback + self._hash = -1 # Cached hash value def can_be_false_default(self) -> bool: return not self.value @@ -2148,7 +2149,9 @@ def accept(self, visitor: 'TypeVisitor[T]') -> T: return visitor.visit_literal_type(self) def __hash__(self) -> int: - return hash((self.value, self.fallback)) + if self._hash == -1: + self._hash = hash((self.value, self.fallback)) + return self._hash def __eq__(self, other: object) -> bool: if isinstance(other, LiteralType): From cddd819d82e08c4c4dcd9edadd16db949972898c Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 7 Apr 2022 18:55:09 +0100 Subject: [PATCH 220/377] Speed up caching of subtype checks (#12539) This is very performance critical. Implement a few micro-optimizations to speed caching a bit. In particular, we use dict.get to reduce the number of dict lookups required, and avoid tuple concatenation which tends to be a bit slow, as it has to construct temporary objects. It would probably be even better to avoid using tuples as keys altogether. This could be a reasonable follow-up improvement. Avoid caching if last known value is set, since it reduces the likelihood of cache hits a lot, because the space of literal values is big (essentially infinite). Also make the global strict_optional attribute an instance-level attribute for faster access, as we might now use it more frequently. I extracted the cached subtype check code into a microbenchmark and the new implementation seems about twice as fast (in an artificial setting, though). Work on #12526 (but should generally make things a little better). --- mypy/checker.py | 3 ++- mypy/join.py | 2 +- mypy/meet.py | 2 +- mypy/semanal_main.py | 6 +++--- mypy/state.py | 32 ++++++++++++++++++++------------ mypy/stubtest.py | 5 +++-- mypy/subtypes.py | 11 ++++++++--- mypy/suggestions.py | 8 ++++---- mypy/test/testtypes.py | 14 +++++++------- mypy/typeops.py | 2 +- mypy/types.py | 2 +- mypy/typestate.py | 22 +++++++++++++++------- mypyc/irbuild/main.py | 4 ++-- 13 files changed, 68 insertions(+), 45 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index a8c8aee4fb2ce..e53e306a7e5d0 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -83,7 +83,8 @@ from mypy.plugin import Plugin, CheckerPluginInterface from mypy.sharedparse import BINARY_MAGIC_METHODS from mypy.scope import Scope -from mypy import state, errorcodes as codes +from mypy import errorcodes as codes +from mypy.state import state from mypy.traverser import has_return_statement, all_return_statements from mypy.errorcodes import ErrorCode, UNUSED_AWAITABLE, UNUSED_COROUTINE from mypy.util import is_typeshed_file, is_dunder, is_sunder diff --git a/mypy/join.py b/mypy/join.py index a184efcc4bb43..7e8fd5d61491c 100644 --- a/mypy/join.py +++ b/mypy/join.py @@ -17,7 +17,7 @@ ) from mypy.nodes import INVARIANT, COVARIANT, CONTRAVARIANT import mypy.typeops -from mypy import state +from mypy.state import state class InstanceJoiner: diff --git a/mypy/meet.py b/mypy/meet.py index 8a996146a344e..535e48bc3a23a 100644 --- a/mypy/meet.py +++ b/mypy/meet.py @@ -12,7 +12,7 @@ from mypy.erasetype import erase_type from mypy.maptype import map_instance_to_supertype from mypy.typeops import tuple_fallback, make_simplified_union, is_recursive_pair -from mypy import state +from mypy.state import state from mypy import join # TODO Describe this module. diff --git a/mypy/semanal_main.py b/mypy/semanal_main.py index d935252ba9cf8..7a82032b46b7b 100644 --- a/mypy/semanal_main.py +++ b/mypy/semanal_main.py @@ -32,7 +32,7 @@ MypyFile, TypeInfo, FuncDef, Decorator, OverloadedFuncDef, Var ) from mypy.semanal_typeargs import TypeArgumentAnalyzer -from mypy.state import strict_optional_set +import mypy.state from mypy.semanal import ( SemanticAnalyzer, apply_semantic_analyzer_patches, remove_imported_names_from_symtable ) @@ -356,7 +356,7 @@ def check_type_arguments(graph: 'Graph', scc: List[str], errors: Errors) -> None state.options, is_typeshed_file(state.path or '')) with state.wrap_context(): - with strict_optional_set(state.options.strict_optional): + with mypy.state.state.strict_optional_set(state.options.strict_optional): state.tree.accept(analyzer) @@ -371,7 +371,7 @@ def check_type_arguments_in_targets(targets: List[FineGrainedDeferredNode], stat state.options, is_typeshed_file(state.path or '')) with state.wrap_context(): - with strict_optional_set(state.options.strict_optional): + with mypy.state.state.strict_optional_set(state.options.strict_optional): for target in targets: func: Optional[Union[FuncDef, OverloadedFuncDef]] = None if isinstance(target.node, (FuncDef, OverloadedFuncDef)): diff --git a/mypy/state.py b/mypy/state.py index 475559899da68..8aba966a33c06 100644 --- a/mypy/state.py +++ b/mypy/state.py @@ -1,20 +1,28 @@ from contextlib import contextmanager from typing import Optional, Tuple, Iterator +from typing_extensions import Final + # These are global mutable state. Don't add anything here unless there's a very # good reason. -# Value varies by file being processed -strict_optional = False -find_occurrences: Optional[Tuple[str, str]] = None +class StrictOptionalState: + # Wrap this in a class since it's faster that using a module-level attribute. + + def __init__(self, strict_optional: bool) -> None: + # Value varies by file being processed + self.strict_optional = strict_optional -@contextmanager -def strict_optional_set(value: bool) -> Iterator[None]: - global strict_optional - saved = strict_optional - strict_optional = value - try: - yield - finally: - strict_optional = saved + @contextmanager + def strict_optional_set(self, value: bool) -> Iterator[None]: + saved = self.strict_optional + self.strict_optional = value + try: + yield + finally: + self.strict_optional = saved + + +state: Final = StrictOptionalState(strict_optional=False) +find_occurrences: Optional[Tuple[str, str]] = None diff --git a/mypy/stubtest.py b/mypy/stubtest.py index 07727615dfcfe..582c467ee2b01 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -21,6 +21,7 @@ import mypy.build import mypy.modulefinder +import mypy.state import mypy.types from mypy import nodes from mypy.config_parser import parse_config_file @@ -560,7 +561,7 @@ def get_position(arg_name: str) -> int: return max(index for _, index in all_args[arg_name]) def get_type(arg_name: str) -> mypy.types.ProperType: - with mypy.state.strict_optional_set(True): + with mypy.state.state.strict_optional_set(True): all_types = [ arg.variable.type or arg.type_annotation for arg, _ in all_args[arg_name] ] @@ -1099,7 +1100,7 @@ def is_subtype_helper(left: mypy.types.Type, right: mypy.types.Type) -> bool: # Special case checks against TypedDicts return True - with mypy.state.strict_optional_set(True): + with mypy.state.state.strict_optional_set(True): return mypy.subtypes.is_subtype(left, right) diff --git a/mypy/subtypes.py b/mypy/subtypes.py index 314c260f293d3..03a232b409704 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -25,7 +25,7 @@ from mypy.expandtype import expand_type_by_instance from mypy.typestate import TypeState, SubtypeKind from mypy.options import Options -from mypy import state +from mypy.state import state # Flags for detected protocol members IS_SETTABLE: Final = 1 @@ -206,7 +206,8 @@ def build_subtype_kind(*, ignore_pos_arg_names: bool = False, ignore_declared_variance: bool = False, ignore_promotions: bool = False) -> SubtypeKind: - return (False, # is proper subtype? + return (state.strict_optional, + False, # is proper subtype? ignore_type_params, ignore_pos_arg_names, ignore_declared_variance, @@ -1316,7 +1317,11 @@ def build_subtype_kind(*, ignore_promotions: bool = False, erase_instances: bool = False, keep_erased_types: bool = False) -> SubtypeKind: - return True, ignore_promotions, erase_instances, keep_erased_types + return (state.strict_optional, + True, + ignore_promotions, + erase_instances, + keep_erased_types) def _is_proper_subtype(self, left: Type, right: Type) -> bool: return is_proper_subtype(left, right, diff --git a/mypy/suggestions.py b/mypy/suggestions.py index af42cca8a2165..46f8ff28dc761 100644 --- a/mypy/suggestions.py +++ b/mypy/suggestions.py @@ -27,7 +27,7 @@ ) from typing_extensions import TypedDict -from mypy.state import strict_optional_set +from mypy.state import state from mypy.types import ( Type, AnyType, TypeOfAny, CallableType, UnionType, NoneType, Instance, TupleType, TypeVarType, FunctionLike, UninhabitedType, @@ -439,7 +439,7 @@ def get_suggestion(self, mod: str, node: FuncDef) -> PyAnnotateSignature: is_method = bool(node.info) and not node.is_static - with strict_optional_set(graph[mod].options.strict_optional): + with state.strict_optional_set(graph[mod].options.strict_optional): guesses = self.get_guesses( is_method, self.get_starting_type(node), @@ -454,7 +454,7 @@ def get_suggestion(self, mod: str, node: FuncDef) -> PyAnnotateSignature: # Now try to find the return type! self.try_type(node, best) returns = get_return_types(self.manager.all_types, node) - with strict_optional_set(graph[mod].options.strict_optional): + with state.strict_optional_set(graph[mod].options.strict_optional): if returns: ret_types = generate_type_combinations(returns) else: @@ -988,7 +988,7 @@ def refine_union(t: UnionType, s: ProperType) -> Type: # Turn strict optional on when simplifying the union since we # don't want to drop Nones. - with strict_optional_set(True): + with state.strict_optional_set(True): return make_simplified_union(new_items) diff --git a/mypy/test/testtypes.py b/mypy/test/testtypes.py index 923e39571ad94..9ee6a35e8efa2 100644 --- a/mypy/test/testtypes.py +++ b/mypy/test/testtypes.py @@ -17,7 +17,7 @@ from mypy.nodes import ARG_POS, ARG_OPT, ARG_STAR, ARG_STAR2, CONTRAVARIANT, INVARIANT, COVARIANT from mypy.subtypes import is_subtype, is_more_precise, is_proper_subtype from mypy.test.typefixture import TypeFixture, InterfaceTypeFixture -from mypy.state import strict_optional_set +from mypy.state import state from mypy.typeops import true_only, false_only, make_simplified_union @@ -410,15 +410,15 @@ def test_true_only_of_union(self) -> None: assert to.items[1] is tup_type def test_false_only_of_true_type_is_uninhabited(self) -> None: - with strict_optional_set(True): + with state.strict_optional_set(True): fo = false_only(self.tuple(AnyType(TypeOfAny.special_form))) assert_type(UninhabitedType, fo) def test_false_only_tuple(self) -> None: - with strict_optional_set(False): + with state.strict_optional_set(False): fo = false_only(self.tuple(self.fx.a)) assert_equal(fo, NoneType()) - with strict_optional_set(True): + with state.strict_optional_set(True): fo = false_only(self.tuple(self.fx.a)) assert_equal(fo, UninhabitedType()) @@ -437,7 +437,7 @@ def test_false_only_of_instance(self) -> None: assert self.fx.a.can_be_true def test_false_only_of_union(self) -> None: - with strict_optional_set(True): + with state.strict_optional_set(True): tup_type = self.tuple() # Union of something that is unknown, something that is always true, something # that is always false @@ -1059,9 +1059,9 @@ def test_literal_type(self) -> None: # FIX generic interfaces + ranges def assert_meet_uninhabited(self, s: Type, t: Type) -> None: - with strict_optional_set(False): + with state.strict_optional_set(False): self.assert_meet(s, t, self.fx.nonet) - with strict_optional_set(True): + with state.strict_optional_set(True): self.assert_meet(s, t, self.fx.uninhabited) def assert_meet(self, s: Type, t: Type, meet: Type) -> None: diff --git a/mypy/typeops.py b/mypy/typeops.py index d97e9f7baf359..ce5f3a3ba61b7 100644 --- a/mypy/typeops.py +++ b/mypy/typeops.py @@ -26,7 +26,7 @@ from mypy.typevars import fill_typevars -from mypy import state +from mypy.state import state def is_recursive_pair(s: Type, t: Type) -> bool: diff --git a/mypy/types.py b/mypy/types.py index 07f7cc845773c..b423350961986 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -12,7 +12,7 @@ from mypy.backports import OrderedDict import mypy.nodes -from mypy import state +from mypy.state import state from mypy.nodes import ( INVARIANT, SymbolNode, FuncDef, ArgKind, ARG_POS, ARG_STAR, ARG_STAR2, diff --git a/mypy/typestate.py b/mypy/typestate.py index 4cf2e19a1d26e..9e3d724bb185b 100644 --- a/mypy/typestate.py +++ b/mypy/typestate.py @@ -9,7 +9,6 @@ from mypy.nodes import TypeInfo from mypy.types import Instance, TypeAliasType, get_proper_type, Type from mypy.server.trigger import make_trigger -from mypy import state # Represents that the 'left' instance is a subtype of the 'right' instance SubtypeRelationship: _TypeAlias = Tuple[Instance, Instance] @@ -124,20 +123,29 @@ def reset_all_subtype_caches_for(info: TypeInfo) -> None: @staticmethod def is_cached_subtype_check(kind: SubtypeKind, left: Instance, right: Instance) -> bool: + if left.last_known_value is not None or right.last_known_value is not None: + # If there is a literal last known value, give up. There + # will be an unbounded number of potential types to cache, + # making caching less effective. + return False info = right.type - if info not in TypeState._subtype_caches: + cache = TypeState._subtype_caches.get(info) + if cache is None: return False - cache = TypeState._subtype_caches[info] - key = (state.strict_optional,) + kind - if key not in cache: + subcache = cache.get(kind) + if subcache is None: return False - return (left, right) in cache[key] + return (left, right) in subcache @staticmethod def record_subtype_cache_entry(kind: SubtypeKind, left: Instance, right: Instance) -> None: + if left.last_known_value is not None or right.last_known_value is not None: + # These are unlikely to match, due to the large space of + # possible values. Avoid uselessly increasing cache sizes. + return cache = TypeState._subtype_caches.setdefault(right.type, dict()) - cache.setdefault((state.strict_optional,) + kind, set()).add((left, right)) + cache.setdefault(kind, set()).add((left, right)) @staticmethod def reset_protocol_deps() -> None: diff --git a/mypyc/irbuild/main.py b/mypyc/irbuild/main.py index b86b6f2dd3c16..f2c49359b69a0 100644 --- a/mypyc/irbuild/main.py +++ b/mypyc/irbuild/main.py @@ -25,7 +25,7 @@ def f(x: int) -> int: from mypy.nodes import MypyFile, Expression, ClassDef from mypy.types import Type -from mypy.state import strict_optional_set +from mypy.state import state from mypy.build import Graph from mypyc.common import TOP_LEVEL_NAME @@ -45,7 +45,7 @@ def f(x: int) -> int: # The stubs for callable contextmanagers are busted so cast it to the # right type... F = TypeVar('F', bound=Callable[..., Any]) -strict_optional_dec = cast(Callable[[F], F], strict_optional_set(True)) +strict_optional_dec = cast(Callable[[F], F], state.strict_optional_set(True)) @strict_optional_dec # Turn on strict optional for any type manipulations we do From ab6185e29227d392f6534a95cd0a2258c5b4817c Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 7 Apr 2022 18:55:32 +0100 Subject: [PATCH 221/377] Further speed up union simplification (#12541) This tweaks a change made in #12539 that may have slowed things down. The behavior introduced in the PR was more correct, but it's not worth a potential major performance regression, since union simplification is not something we have to get always right for correctness. Work on #12526. --- mypy/test/testtypes.py | 10 +++++++++- mypy/typeops.py | 40 ++++++++++++++++++++++++++++++++-------- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/mypy/test/testtypes.py b/mypy/test/testtypes.py index 9ee6a35e8efa2..7458dfa9c6bf3 100644 --- a/mypy/test/testtypes.py +++ b/mypy/test/testtypes.py @@ -12,7 +12,7 @@ from mypy.types import ( UnboundType, AnyType, CallableType, TupleType, TypeVarType, Type, Instance, NoneType, Overloaded, TypeType, UnionType, UninhabitedType, TypeVarId, TypeOfAny, ProperType, - get_proper_type + LiteralType, get_proper_type ) from mypy.nodes import ARG_POS, ARG_OPT, ARG_STAR, ARG_STAR2, CONTRAVARIANT, INVARIANT, COVARIANT from mypy.subtypes import is_subtype, is_more_precise, is_proper_subtype @@ -496,6 +496,14 @@ def test_simplified_union_with_str_literals(self) -> None: self.assert_simplified_union([fx.lit_str1, fx.lit_str2, fx.uninhabited], UnionType([fx.lit_str1, fx.lit_str2])) + def test_simplify_very_large_union(self) -> None: + fx = self.fx + literals = [] + for i in range(5000): + literals.append(LiteralType("v%d" % i, fx.str_type)) + # This shouldn't be very slow, even if the union is big. + self.assert_simplified_union([*literals, fx.str_type], fx.str_type) + def test_simplified_union_with_str_instance_literals(self) -> None: fx = self.fx diff --git a/mypy/typeops.py b/mypy/typeops.py index ce5f3a3ba61b7..bb5d8c291b124 100644 --- a/mypy/typeops.py +++ b/mypy/typeops.py @@ -318,6 +318,15 @@ def simple_literal_value_key(t: ProperType) -> Optional[Tuple[str, ...]]: return None +def is_simple_literal(t: ProperType) -> bool: + """Fast way to check if simple_literal_value_key() would return a non-None value.""" + if isinstance(t, LiteralType): + return t.fallback.type.is_enum or t.fallback.type.fullname == 'builtins.str' + if isinstance(t, Instance): + return t.last_known_value is not None and isinstance(t.last_known_value.value, str) + return False + + def make_simplified_union(items: Sequence[Type], line: int = -1, column: int = -1, *, keep_erased: bool = False, @@ -392,17 +401,26 @@ def _remove_redundant_union_items(items: List[ProperType], keep_erased: bool) -> # Keep track of the truishness info for deleted subtypes which can be relevant cbt = cbf = False + num_items = len(items) for j, tj in enumerate(items): - # NB: we don't need to check literals as the fast path above takes care of that - if ( - i != j + if i != j: + # NB: The first check below is an optimization to + # avoid very expensive computations with large + # unions involving literals. We approximate the + # results for unions with many items. This is + # "fine" since simplifying these union items is + # (almost) always optional. + if ( + (num_items < 5 + or is_likely_literal_supertype(item) + or not is_simple_literal(tj)) and is_proper_subtype(tj, item, keep_erased_types=keep_erased) and is_redundant_literal_instance(item, tj) # XXX? - ): - # We found a redundant item in the union. - removed.add(j) - cbt = cbt or tj.can_be_true - cbf = cbf or tj.can_be_false + ): + # We found a redundant item in the union. + removed.add(j) + cbt = cbt or tj.can_be_true + cbf = cbf or tj.can_be_false # if deleted subtypes had more general truthiness, use that if not item.can_be_true and cbt: items[i] = true_or_false(item) @@ -412,6 +430,12 @@ def _remove_redundant_union_items(items: List[ProperType], keep_erased: bool) -> return [items[i] for i in range(len(items)) if i not in removed] +def is_likely_literal_supertype(t: ProperType) -> bool: + """Is the type likely to cause simplification of literal types in unions?""" + return isinstance(t, Instance) and t.type.fullname in ('builtins.object', + 'builtins.str') + + def _get_type_special_method_bool_ret_type(t: Type) -> Optional[Type]: t = get_proper_type(t) From 222029b07e0fdcb3c174f15b61915b3b2e1665ca Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 7 Apr 2022 19:16:02 +0100 Subject: [PATCH 222/377] Minor proper subtype check optimization (#12536) Mypyc is bad at compiling nested functions. In one use case we were spending 7% of the mypy runtime just creating closure objects for `check_argument`. Here I manually inline the nested function to avoid this overhead. Work on #12526. Co-authored-by: Jelle Zijlstra --- mypy/subtypes.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/mypy/subtypes.py b/mypy/subtypes.py index 03a232b409704..af35821d7ef4d 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -1370,13 +1370,6 @@ def visit_instance(self, left: Instance) -> bool: return True if left.type.has_base(right.type.fullname): - def check_argument(leftarg: Type, rightarg: Type, variance: int) -> bool: - if variance == COVARIANT: - return self._is_proper_subtype(leftarg, rightarg) - elif variance == CONTRAVARIANT: - return self._is_proper_subtype(rightarg, leftarg) - else: - return mypy.sametypes.is_same_type(leftarg, rightarg) # Map left type to corresponding right instances. left = map_instance_to_supertype(left, right.type) if self.erase_instances: @@ -1387,9 +1380,17 @@ def check_argument(leftarg: Type, rightarg: Type, variance: int) -> bool: nominal = True for ta, ra, tvar in zip(left.args, right.args, right.type.defn.type_vars): if isinstance(tvar, TypeVarType): - nominal = nominal and check_argument(ta, ra, tvar.variance) + variance = tvar.variance + if variance == COVARIANT: + nominal = self._is_proper_subtype(ta, ra) + elif variance == CONTRAVARIANT: + nominal = self._is_proper_subtype(ra, ta) + else: + nominal = mypy.sametypes.is_same_type(ta, ra) else: - nominal = nominal and mypy.sametypes.is_same_type(ta, ra) + nominal = mypy.sametypes.is_same_type(ta, ra) + if not nominal: + break if nominal: TypeState.record_subtype_cache_entry(self._subtype_kind, left, right) From 756277c8bbab01dab0833c7f18d3f2765211352b Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 8 Apr 2022 14:33:07 +0100 Subject: [PATCH 223/377] Sync typeshed (#12321) Source commit: https://github.com/python/typeshed/commit/3c85f36b7f9afd599409d10a214aafdecf38251e --- .../stdlib/@python2/BaseHTTPServer.pyi | 10 +- .../stdlib/@python2/CGIHTTPServer.pyi | 3 +- .../typeshed/stdlib/@python2/ConfigParser.pyi | 30 +- mypy/typeshed/stdlib/@python2/Cookie.pyi | 6 +- mypy/typeshed/stdlib/@python2/HTMLParser.pyi | 6 +- mypy/typeshed/stdlib/@python2/Queue.pyi | 5 +- .../typeshed/stdlib/@python2/SocketServer.pyi | 27 +- mypy/typeshed/stdlib/@python2/StringIO.pyi | 4 +- mypy/typeshed/stdlib/@python2/UserDict.pyi | 16 +- mypy/typeshed/stdlib/@python2/UserList.pyi | 8 +- mypy/typeshed/stdlib/@python2/UserString.pyi | 76 +- mypy/typeshed/stdlib/@python2/__builtin__.pyi | 366 ++++---- mypy/typeshed/stdlib/@python2/__future__.pyi | 3 +- mypy/typeshed/stdlib/@python2/_ast.pyi | 96 ++- mypy/typeshed/stdlib/@python2/_codecs.pyi | 86 +- .../typeshed/stdlib/@python2/_collections.pyi | 12 +- mypy/typeshed/stdlib/@python2/_csv.pyi | 10 +- mypy/typeshed/stdlib/@python2/_curses.pyi | 24 +- .../stdlib/@python2/_dummy_threading.pyi | 35 +- mypy/typeshed/stdlib/@python2/_functools.pyi | 6 +- mypy/typeshed/stdlib/@python2/_heapq.pyi | 16 +- mypy/typeshed/stdlib/@python2/_hotshot.pyi | 4 +- mypy/typeshed/stdlib/@python2/_io.pyi | 30 +- mypy/typeshed/stdlib/@python2/_json.pyi | 4 +- mypy/typeshed/stdlib/@python2/_markupbase.pyi | 4 +- mypy/typeshed/stdlib/@python2/_msi.pyi | 19 +- .../typeshed/stdlib/@python2/_osx_support.pyi | 32 +- mypy/typeshed/stdlib/@python2/_random.pyi | 4 +- mypy/typeshed/stdlib/@python2/_socket.pyi | 20 +- mypy/typeshed/stdlib/@python2/_sre.pyi | 22 +- mypy/typeshed/stdlib/@python2/_struct.pyi | 10 +- mypy/typeshed/stdlib/@python2/_symtable.pyi | 8 +- mypy/typeshed/stdlib/@python2/_thread.pyi | 6 +- .../stdlib/@python2/_typeshed/__init__.pyi | 16 +- .../stdlib/@python2/_typeshed/wsgi.pyi | 10 +- mypy/typeshed/stdlib/@python2/_warnings.pyi | 18 +- mypy/typeshed/stdlib/@python2/_weakref.pyi | 4 +- mypy/typeshed/stdlib/@python2/_weakrefset.pyi | 26 +- mypy/typeshed/stdlib/@python2/_winreg.pyi | 15 +- mypy/typeshed/stdlib/@python2/abc.pyi | 6 +- mypy/typeshed/stdlib/@python2/aifc.pyi | 12 +- mypy/typeshed/stdlib/@python2/argparse.pyi | 116 ++- mypy/typeshed/stdlib/@python2/array.pyi | 19 +- mypy/typeshed/stdlib/@python2/asynchat.pyi | 4 +- mypy/typeshed/stdlib/@python2/asyncore.pyi | 19 +- mypy/typeshed/stdlib/@python2/audioop.pyi | 16 +- mypy/typeshed/stdlib/@python2/base64.pyi | 6 +- mypy/typeshed/stdlib/@python2/bdb.pyi | 37 +- mypy/typeshed/stdlib/@python2/binhex.pyi | 6 +- mypy/typeshed/stdlib/@python2/builtins.pyi | 366 ++++---- mypy/typeshed/stdlib/@python2/bz2.pyi | 13 +- mypy/typeshed/stdlib/@python2/cPickle.pyi | 4 +- mypy/typeshed/stdlib/@python2/cProfile.pyi | 16 +- mypy/typeshed/stdlib/@python2/cStringIO.pyi | 6 +- mypy/typeshed/stdlib/@python2/calendar.pyi | 26 +- mypy/typeshed/stdlib/@python2/cgi.pyi | 18 +- mypy/typeshed/stdlib/@python2/cgitb.pyi | 12 +- mypy/typeshed/stdlib/@python2/cmath.pyi | 6 +- mypy/typeshed/stdlib/@python2/cmd.pyi | 22 +- mypy/typeshed/stdlib/@python2/codecs.pyi | 98 +-- mypy/typeshed/stdlib/@python2/collections.pyi | 41 +- mypy/typeshed/stdlib/@python2/colorsys.pyi | 14 +- mypy/typeshed/stdlib/@python2/commands.pyi | 4 +- mypy/typeshed/stdlib/@python2/contextlib.pyi | 10 +- mypy/typeshed/stdlib/@python2/copy.pyi | 4 +- mypy/typeshed/stdlib/@python2/copy_reg.pyi | 6 +- mypy/typeshed/stdlib/@python2/copyreg.pyi | 6 +- mypy/typeshed/stdlib/@python2/csv.pyi | 20 +- .../stdlib/@python2/ctypes/__init__.pyi | 105 ++- .../stdlib/@python2/curses/__init__.pyi | 2 +- .../typeshed/stdlib/@python2/curses/ascii.pyi | 4 +- mypy/typeshed/stdlib/@python2/datetime.pyi | 58 +- .../typeshed/stdlib/@python2/dbm/__init__.pyi | 13 +- mypy/typeshed/stdlib/@python2/dbm/dumb.pyi | 11 +- mypy/typeshed/stdlib/@python2/dbm/gnu.pyi | 17 +- mypy/typeshed/stdlib/@python2/dbm/ndbm.pyi | 19 +- mypy/typeshed/stdlib/@python2/decimal.pyi | 36 +- mypy/typeshed/stdlib/@python2/difflib.pyi | 31 +- mypy/typeshed/stdlib/@python2/dircache.pyi | 4 +- mypy/typeshed/stdlib/@python2/dis.pyi | 12 +- .../stdlib/@python2/distutils/ccompiler.pyi | 126 +-- .../stdlib/@python2/distutils/cmd.pyi | 18 +- .../@python2/distutils/command/bdist_msi.pyi | 1 + .../@python2/distutils/command/config.pyi | 8 +- .../distutils/command/install_egg_info.pyi | 6 +- .../@python2/distutils/command/upload.pyi | 4 +- .../stdlib/@python2/distutils/config.pyi | 6 +- .../stdlib/@python2/distutils/core.pyi | 44 +- .../stdlib/@python2/distutils/dep_util.pyi | 6 +- .../stdlib/@python2/distutils/dir_util.pyi | 8 +- .../stdlib/@python2/distutils/dist.pyi | 6 +- .../stdlib/@python2/distutils/extension.pyi | 26 +- .../@python2/distutils/fancy_getopt.pyi | 22 +- .../stdlib/@python2/distutils/file_util.pyi | 4 +- .../stdlib/@python2/distutils/spawn.pyi | 4 +- .../stdlib/@python2/distutils/text_file.pyi | 6 +- .../stdlib/@python2/distutils/util.pyi | 11 +- .../stdlib/@python2/distutils/version.pyi | 20 +- mypy/typeshed/stdlib/@python2/doctest.pyi | 50 +- .../typeshed/stdlib/@python2/dummy_thread.pyi | 4 +- .../@python2/email/mime/application.pyi | 4 +- .../stdlib/@python2/encodings/utf_8.pyi | 4 +- mypy/typeshed/stdlib/@python2/filecmp.pyi | 32 +- mypy/typeshed/stdlib/@python2/fnmatch.pyi | 6 +- mypy/typeshed/stdlib/@python2/formatter.pyi | 16 +- mypy/typeshed/stdlib/@python2/fractions.pyi | 20 +- mypy/typeshed/stdlib/@python2/ftplib.pyi | 27 +- mypy/typeshed/stdlib/@python2/functools.pyi | 8 +- mypy/typeshed/stdlib/@python2/gc.pyi | 14 +- mypy/typeshed/stdlib/@python2/genericpath.pyi | 10 +- mypy/typeshed/stdlib/@python2/getopt.pyi | 7 +- mypy/typeshed/stdlib/@python2/gettext.pyi | 8 +- mypy/typeshed/stdlib/@python2/glob.pyi | 8 +- mypy/typeshed/stdlib/@python2/grp.pyi | 6 +- mypy/typeshed/stdlib/@python2/hashlib.pyi | 10 +- mypy/typeshed/stdlib/@python2/heapq.pyi | 18 +- mypy/typeshed/stdlib/@python2/hmac.pyi | 4 +- .../stdlib/@python2/htmlentitydefs.pyi | 8 +- mypy/typeshed/stdlib/@python2/httplib.pyi | 6 +- mypy/typeshed/stdlib/@python2/imaplib.pyi | 37 +- mypy/typeshed/stdlib/@python2/imghdr.pyi | 6 +- mypy/typeshed/stdlib/@python2/imp.pyi | 8 +- mypy/typeshed/stdlib/@python2/inspect.pyi | 44 +- mypy/typeshed/stdlib/@python2/itertools.pyi | 43 +- mypy/typeshed/stdlib/@python2/json.pyi | 26 +- .../stdlib/@python2/lib2to3/pgen2/grammar.pyi | 31 +- .../@python2/lib2to3/pgen2/literals.pyi | 4 +- .../stdlib/@python2/lib2to3/pgen2/parse.pyi | 6 +- .../stdlib/@python2/lib2to3/pgen2/pgen.pyi | 32 +- .../stdlib/@python2/lib2to3/pgen2/token.pyi | 4 +- .../@python2/lib2to3/pgen2/tokenize.pyi | 10 +- .../stdlib/@python2/lib2to3/pytree.pyi | 35 +- mypy/typeshed/stdlib/@python2/linecache.pyi | 8 +- mypy/typeshed/stdlib/@python2/locale.pyi | 12 +- .../stdlib/@python2/logging/__init__.pyi | 82 +- .../stdlib/@python2/logging/config.pyi | 6 +- .../stdlib/@python2/logging/handlers.pyi | 26 +- mypy/typeshed/stdlib/@python2/macpath.pyi | 4 +- mypy/typeshed/stdlib/@python2/mailbox.pyi | 57 +- mypy/typeshed/stdlib/@python2/mailcap.pyi | 10 +- mypy/typeshed/stdlib/@python2/markupbase.pyi | 4 +- mypy/typeshed/stdlib/@python2/math.pyi | 6 +- mypy/typeshed/stdlib/@python2/mimetypes.pyi | 32 +- mypy/typeshed/stdlib/@python2/mmap.pyi | 1 + .../typeshed/stdlib/@python2/modulefinder.pyi | 33 +- .../stdlib/@python2/msilib/__init__.pyi | 39 +- .../stdlib/@python2/msilib/schema.pyi | 5 +- .../stdlib/@python2/msilib/sequence.pyi | 5 +- mypy/typeshed/stdlib/@python2/msilib/text.pyi | 7 +- .../multiprocessing/dummy/__init__.pyi | 4 +- .../multiprocessing/dummy/connection.pyi | 6 +- .../stdlib/@python2/multiprocessing/pool.pyi | 13 +- mypy/typeshed/stdlib/@python2/mutex.pyi | 5 +- mypy/typeshed/stdlib/@python2/netrc.pyi | 8 +- mypy/typeshed/stdlib/@python2/nis.pyi | 6 +- mypy/typeshed/stdlib/@python2/nntplib.pyi | 53 +- mypy/typeshed/stdlib/@python2/ntpath.pyi | 12 +- mypy/typeshed/stdlib/@python2/numbers.pyi | 4 +- mypy/typeshed/stdlib/@python2/opcode.pyi | 20 +- mypy/typeshed/stdlib/@python2/operator.pyi | 30 +- mypy/typeshed/stdlib/@python2/optparse.pyi | 76 +- mypy/typeshed/stdlib/@python2/os/__init__.pyi | 59 +- mypy/typeshed/stdlib/@python2/os/path.pyi | 12 +- mypy/typeshed/stdlib/@python2/os2emxpath.pyi | 12 +- mypy/typeshed/stdlib/@python2/ossaudiodev.pyi | 251 +++--- mypy/typeshed/stdlib/@python2/parser.pyi | 10 +- mypy/typeshed/stdlib/@python2/pdb.pyi | 32 +- mypy/typeshed/stdlib/@python2/pickle.pyi | 12 +- mypy/typeshed/stdlib/@python2/pickletools.pyi | 18 +- mypy/typeshed/stdlib/@python2/pkgutil.pyi | 9 +- mypy/typeshed/stdlib/@python2/platform.pyi | 20 +- mypy/typeshed/stdlib/@python2/plistlib.pyi | 6 +- mypy/typeshed/stdlib/@python2/popen2.pyi | 8 +- mypy/typeshed/stdlib/@python2/poplib.pyi | 6 +- mypy/typeshed/stdlib/@python2/posix.pyi | 38 +- mypy/typeshed/stdlib/@python2/posixpath.pyi | 12 +- mypy/typeshed/stdlib/@python2/pprint.pyi | 4 +- mypy/typeshed/stdlib/@python2/profile.pyi | 16 +- mypy/typeshed/stdlib/@python2/pstats.pyi | 31 +- mypy/typeshed/stdlib/@python2/pty.pyi | 8 +- mypy/typeshed/stdlib/@python2/pwd.pyi | 5 +- mypy/typeshed/stdlib/@python2/py_compile.pyi | 8 +- mypy/typeshed/stdlib/@python2/pyclbr.pyi | 12 +- mypy/typeshed/stdlib/@python2/pydoc.pyi | 47 +- .../stdlib/@python2/pydoc_data/topics.pyi | 4 +- .../stdlib/@python2/pyexpat/__init__.pyi | 14 +- mypy/typeshed/stdlib/@python2/random.pyi | 6 +- mypy/typeshed/stdlib/@python2/re.pyi | 18 +- mypy/typeshed/stdlib/@python2/readline.pyi | 4 +- mypy/typeshed/stdlib/@python2/repr.pyi | 4 +- mypy/typeshed/stdlib/@python2/resource.pyi | 7 +- mypy/typeshed/stdlib/@python2/rlcompleter.pyi | 8 +- mypy/typeshed/stdlib/@python2/sched.pyi | 12 +- mypy/typeshed/stdlib/@python2/select.pyi | 10 +- mypy/typeshed/stdlib/@python2/sets.pyi | 42 +- mypy/typeshed/stdlib/@python2/shelve.pyi | 21 +- mypy/typeshed/stdlib/@python2/shlex.pyi | 9 +- mypy/typeshed/stdlib/@python2/shutil.pyi | 14 +- mypy/typeshed/stdlib/@python2/signal.pyi | 100 +-- mypy/typeshed/stdlib/@python2/site.pyi | 6 +- mypy/typeshed/stdlib/@python2/smtpd.pyi | 19 +- mypy/typeshed/stdlib/@python2/sndhdr.pyi | 4 +- mypy/typeshed/stdlib/@python2/socket.pyi | 35 +- mypy/typeshed/stdlib/@python2/spwd.pyi | 4 +- .../stdlib/@python2/sqlite3/__init__.pyi | 2 +- .../stdlib/@python2/sqlite3/dbapi2.pyi | 17 +- mypy/typeshed/stdlib/@python2/sre_compile.pyi | 4 +- .../stdlib/@python2/sre_constants.pyi | 16 +- mypy/typeshed/stdlib/@python2/sre_parse.pyi | 40 +- mypy/typeshed/stdlib/@python2/ssl.pyi | 36 +- mypy/typeshed/stdlib/@python2/string.pyi | 10 +- mypy/typeshed/stdlib/@python2/stringold.pyi | 8 +- mypy/typeshed/stdlib/@python2/strop.pyi | 6 +- mypy/typeshed/stdlib/@python2/struct.pyi | 16 +- mypy/typeshed/stdlib/@python2/subprocess.pyi | 12 +- mypy/typeshed/stdlib/@python2/sunau.pyi | 6 +- mypy/typeshed/stdlib/@python2/symbol.pyi | 4 +- mypy/typeshed/stdlib/@python2/symtable.pyi | 16 +- mypy/typeshed/stdlib/@python2/sys.pyi | 30 +- mypy/typeshed/stdlib/@python2/sysconfig.pyi | 16 +- mypy/typeshed/stdlib/@python2/tabnanny.pyi | 4 +- mypy/typeshed/stdlib/@python2/tarfile.pyi | 39 +- mypy/typeshed/stdlib/@python2/telnetlib.pyi | 4 +- mypy/typeshed/stdlib/@python2/tempfile.pyi | 13 +- mypy/typeshed/stdlib/@python2/termios.pyi | 7 +- mypy/typeshed/stdlib/@python2/textwrap.pyi | 8 +- mypy/typeshed/stdlib/@python2/this.pyi | 4 +- mypy/typeshed/stdlib/@python2/thread.pyi | 2 + mypy/typeshed/stdlib/@python2/threading.pyi | 35 +- mypy/typeshed/stdlib/@python2/time.pyi | 8 +- mypy/typeshed/stdlib/@python2/timeit.pyi | 10 +- mypy/typeshed/stdlib/@python2/toaiff.pyi | 5 +- mypy/typeshed/stdlib/@python2/token.pyi | 4 +- mypy/typeshed/stdlib/@python2/tokenize.pyi | 22 +- mypy/typeshed/stdlib/@python2/trace.pyi | 16 +- mypy/typeshed/stdlib/@python2/traceback.pyi | 22 +- mypy/typeshed/stdlib/@python2/tty.pyi | 4 +- mypy/typeshed/stdlib/@python2/turtle.pyi | 69 +- mypy/typeshed/stdlib/@python2/types.pyi | 58 +- mypy/typeshed/stdlib/@python2/typing.pyi | 96 ++- .../stdlib/@python2/typing_extensions.pyi | 45 +- mypy/typeshed/stdlib/@python2/unittest.pyi | 75 +- mypy/typeshed/stdlib/@python2/urllib.pyi | 11 +- mypy/typeshed/stdlib/@python2/urllib2.pyi | 24 +- mypy/typeshed/stdlib/@python2/urlparse.pyi | 26 +- mypy/typeshed/stdlib/@python2/uu.pyi | 4 +- mypy/typeshed/stdlib/@python2/uuid.pyi | 4 +- mypy/typeshed/stdlib/@python2/warnings.pyi | 20 +- mypy/typeshed/stdlib/@python2/wave.pyi | 6 +- mypy/typeshed/stdlib/@python2/weakref.pyi | 33 +- mypy/typeshed/stdlib/@python2/webbrowser.pyi | 23 +- .../stdlib/@python2/wsgiref/handlers.pyi | 16 +- .../stdlib/@python2/wsgiref/headers.pyi | 10 +- .../stdlib/@python2/wsgiref/simple_server.pyi | 8 +- mypy/typeshed/stdlib/@python2/xdrlib.pyi | 8 +- .../stdlib/@python2/xml/dom/domreg.pyi | 8 +- .../stdlib/@python2/xml/dom/minicompat.pyi | 12 +- .../stdlib/@python2/xml/dom/minidom.pyi | 9 +- .../stdlib/@python2/xml/dom/xmlbuilder.pyi | 4 +- .../stdlib/@python2/xml/etree/ElementPath.pyi | 22 +- .../stdlib/@python2/xml/etree/ElementTree.pyi | 60 +- .../@python2/xml/etree/cElementTree.pyi | 2 +- .../stdlib/@python2/xml/sax/__init__.pyi | 6 +- .../stdlib/@python2/xml/sax/xmlreader.pyi | 4 +- mypy/typeshed/stdlib/@python2/xmlrpclib.pyi | 48 +- mypy/typeshed/stdlib/@python2/zipfile.pyi | 27 +- mypy/typeshed/stdlib/VERSIONS | 13 + mypy/typeshed/stdlib/_ast.pyi | 163 +++- mypy/typeshed/stdlib/_bisect.pyi | 66 +- mypy/typeshed/stdlib/_codecs.pyi | 4 +- mypy/typeshed/stdlib/_collections_abc.pyi | 9 +- mypy/typeshed/stdlib/_compression.pyi | 8 +- mypy/typeshed/stdlib/_csv.pyi | 15 +- mypy/typeshed/stdlib/_curses.pyi | 12 +- mypy/typeshed/stdlib/_decimal.pyi | 2 + mypy/typeshed/stdlib/_dummy_thread.pyi | 3 +- mypy/typeshed/stdlib/_dummy_threading.pyi | 81 +- mypy/typeshed/stdlib/_heapq.pyi | 2 + mypy/typeshed/stdlib/_imp.pyi | 2 +- mypy/typeshed/stdlib/_json.pyi | 27 +- mypy/typeshed/stdlib/_msi.pyi | 6 +- mypy/typeshed/stdlib/_operator.pyi | 27 +- mypy/typeshed/stdlib/_osx_support.pyi | 2 +- mypy/typeshed/stdlib/_py_abc.pyi | 12 +- mypy/typeshed/stdlib/_socket.pyi | 21 +- mypy/typeshed/stdlib/_thread.pyi | 14 +- mypy/typeshed/stdlib/_threading_local.pyi | 1 + mypy/typeshed/stdlib/_tkinter.pyi | 96 ++- mypy/typeshed/stdlib/_typeshed/__init__.pyi | 64 +- mypy/typeshed/stdlib/_typeshed/dbapi.pyi | 5 +- mypy/typeshed/stdlib/_typeshed/wsgi.pyi | 5 +- mypy/typeshed/stdlib/_warnings.pyi | 12 +- mypy/typeshed/stdlib/_weakrefset.pyi | 28 +- mypy/typeshed/stdlib/_winapi.pyi | 1 + mypy/typeshed/stdlib/abc.pyi | 22 +- mypy/typeshed/stdlib/aifc.pyi | 13 +- mypy/typeshed/stdlib/argparse.pyi | 112 ++- mypy/typeshed/stdlib/array.pyi | 28 +- mypy/typeshed/stdlib/ast.pyi | 4 + mypy/typeshed/stdlib/asyncio/__init__.pyi | 134 +-- mypy/typeshed/stdlib/asyncio/base_events.pyi | 102 ++- mypy/typeshed/stdlib/asyncio/base_futures.pyi | 12 +- .../stdlib/asyncio/base_subprocess.pyi | 4 +- mypy/typeshed/stdlib/asyncio/compat.pyi | 10 +- mypy/typeshed/stdlib/asyncio/coroutines.pyi | 7 + mypy/typeshed/stdlib/asyncio/events.pyi | 196 ++++- mypy/typeshed/stdlib/asyncio/exceptions.pyi | 34 +- .../stdlib/asyncio/format_helpers.pyi | 22 +- mypy/typeshed/stdlib/asyncio/futures.pyi | 41 +- mypy/typeshed/stdlib/asyncio/locks.pyi | 45 +- mypy/typeshed/stdlib/asyncio/mixins.pyi | 7 + .../stdlib/asyncio/proactor_events.pyi | 41 +- mypy/typeshed/stdlib/asyncio/protocols.pyi | 13 +- mypy/typeshed/stdlib/asyncio/queues.pyi | 7 +- mypy/typeshed/stdlib/asyncio/runners.pyi | 14 +- .../stdlib/asyncio/selector_events.pyi | 6 + mypy/typeshed/stdlib/asyncio/sslproto.pyi | 4 + mypy/typeshed/stdlib/asyncio/staggered.pyi | 10 +- mypy/typeshed/stdlib/asyncio/streams.pyi | 73 +- mypy/typeshed/stdlib/asyncio/subprocess.pyi | 9 +- mypy/typeshed/stdlib/asyncio/taskgroups.pyi | 17 + mypy/typeshed/stdlib/asyncio/tasks.pyi | 194 +++-- mypy/typeshed/stdlib/asyncio/threads.pyi | 5 +- mypy/typeshed/stdlib/asyncio/transports.pyi | 6 + mypy/typeshed/stdlib/asyncio/trsock.pyi | 75 +- mypy/typeshed/stdlib/asyncio/unix_events.pyi | 96 ++- .../stdlib/asyncio/windows_events.pyi | 16 +- .../typeshed/stdlib/asyncio/windows_utils.pyi | 42 +- mypy/typeshed/stdlib/asyncore.pyi | 1 + mypy/typeshed/stdlib/base64.pyi | 45 + mypy/typeshed/stdlib/bdb.pyi | 13 +- mypy/typeshed/stdlib/binhex.pyi | 13 +- mypy/typeshed/stdlib/builtins.pyi | 359 +++++--- mypy/typeshed/stdlib/bz2.pyi | 7 +- mypy/typeshed/stdlib/cProfile.pyi | 8 +- mypy/typeshed/stdlib/calendar.pyi | 57 +- mypy/typeshed/stdlib/cgi.pyi | 53 +- mypy/typeshed/stdlib/cgitb.pyi | 8 +- mypy/typeshed/stdlib/cmath.pyi | 6 +- mypy/typeshed/stdlib/cmd.pyi | 8 +- mypy/typeshed/stdlib/code.pyi | 2 + mypy/typeshed/stdlib/codecs.pyi | 133 ++- mypy/typeshed/stdlib/codeop.pyi | 2 + mypy/typeshed/stdlib/collections/__init__.pyi | 222 +++-- mypy/typeshed/stdlib/colorsys.pyi | 2 + mypy/typeshed/stdlib/compileall.pyi | 2 + .../stdlib/concurrent/futures/__init__.pyi | 16 + .../stdlib/concurrent/futures/_base.pyi | 29 +- .../stdlib/concurrent/futures/process.pyi | 4 +- .../stdlib/concurrent/futures/thread.pyi | 2 + mypy/typeshed/stdlib/configparser.pyi | 47 +- mypy/typeshed/stdlib/contextlib.pyi | 130 ++- mypy/typeshed/stdlib/contextvars.pyi | 19 +- mypy/typeshed/stdlib/copy.pyi | 2 + mypy/typeshed/stdlib/copyreg.pyi | 19 +- mypy/typeshed/stdlib/crypt.pyi | 1 + mypy/typeshed/stdlib/csv.pyi | 33 +- mypy/typeshed/stdlib/ctypes/__init__.pyi | 101 +-- mypy/typeshed/stdlib/curses/__init__.pyi | 4 +- mypy/typeshed/stdlib/curses/panel.pyi | 2 + mypy/typeshed/stdlib/curses/textpad.pyi | 1 + mypy/typeshed/stdlib/dataclasses.pyi | 89 +- mypy/typeshed/stdlib/datetime.pyi | 149 ++-- mypy/typeshed/stdlib/dbm/__init__.pyi | 12 +- mypy/typeshed/stdlib/dbm/dumb.pyi | 12 +- mypy/typeshed/stdlib/dbm/gnu.pyi | 68 +- mypy/typeshed/stdlib/dbm/ndbm.pyi | 60 +- mypy/typeshed/stdlib/decimal.pyi | 27 +- mypy/typeshed/stdlib/difflib.pyi | 27 +- mypy/typeshed/stdlib/dis.pyi | 55 +- mypy/typeshed/stdlib/distutils/ccompiler.pyi | 4 +- mypy/typeshed/stdlib/distutils/cmd.pyi | 2 +- .../stdlib/distutils/command/__init__.pyi | 40 - .../stdlib/distutils/command/bdist_msi.pyi | 2 + .../distutils/command/bdist_wininst.pyi | 16 + mypy/typeshed/stdlib/distutils/core.pyi | 6 +- mypy/typeshed/stdlib/distutils/dist.pyi | 4 +- mypy/typeshed/stdlib/distutils/extension.pyi | 18 +- .../stdlib/distutils/fancy_getopt.pyi | 4 +- mypy/typeshed/stdlib/distutils/util.pyi | 3 +- mypy/typeshed/stdlib/distutils/version.pyi | 30 +- mypy/typeshed/stdlib/doctest.pyi | 43 +- mypy/typeshed/stdlib/email/__init__.pyi | 7 +- .../stdlib/email/_header_value_parser.pyi | 23 +- mypy/typeshed/stdlib/email/base64mime.pyi | 2 + mypy/typeshed/stdlib/email/charset.pyi | 9 +- mypy/typeshed/stdlib/email/encoders.pyi | 2 + mypy/typeshed/stdlib/email/feedparser.pyi | 17 +- mypy/typeshed/stdlib/email/generator.pyi | 24 +- mypy/typeshed/stdlib/email/header.pyi | 8 +- mypy/typeshed/stdlib/email/headerregistry.pyi | 16 +- mypy/typeshed/stdlib/email/iterators.pyi | 7 + mypy/typeshed/stdlib/email/message.pyi | 13 +- .../stdlib/email/mime/application.pyi | 5 +- mypy/typeshed/stdlib/email/mime/audio.pyi | 5 +- mypy/typeshed/stdlib/email/mime/base.pyi | 4 +- mypy/typeshed/stdlib/email/mime/image.pyi | 5 +- mypy/typeshed/stdlib/email/mime/message.pyi | 2 + mypy/typeshed/stdlib/email/mime/multipart.pyi | 5 +- .../stdlib/email/mime/nonmultipart.pyi | 2 + mypy/typeshed/stdlib/email/mime/text.pyi | 2 + mypy/typeshed/stdlib/email/parser.pyi | 7 +- mypy/typeshed/stdlib/email/policy.pyi | 2 + mypy/typeshed/stdlib/email/quoprimime.pyi | 13 + mypy/typeshed/stdlib/email/utils.pyi | 24 +- mypy/typeshed/stdlib/ensurepip/__init__.pyi | 2 + mypy/typeshed/stdlib/enum.pyi | 206 +++-- mypy/typeshed/stdlib/errno.pyi | 23 +- mypy/typeshed/stdlib/fcntl.pyi | 132 +-- mypy/typeshed/stdlib/filecmp.pyi | 9 +- mypy/typeshed/stdlib/fileinput.pyi | 26 +- mypy/typeshed/stdlib/fnmatch.pyi | 2 + mypy/typeshed/stdlib/fractions.pyi | 116 +-- mypy/typeshed/stdlib/ftplib.pyi | 19 +- mypy/typeshed/stdlib/functools.pyi | 103 ++- mypy/typeshed/stdlib/gc.pyi | 20 +- mypy/typeshed/stdlib/genericpath.pyi | 14 + mypy/typeshed/stdlib/getopt.pyi | 2 + mypy/typeshed/stdlib/getpass.pyi | 2 + mypy/typeshed/stdlib/gettext.pyi | 85 +- mypy/typeshed/stdlib/glob.pyi | 22 +- mypy/typeshed/stdlib/graphlib.pyi | 10 +- mypy/typeshed/stdlib/grp.pyi | 9 +- mypy/typeshed/stdlib/gzip.pyi | 5 + mypy/typeshed/stdlib/hashlib.pyi | 24 +- mypy/typeshed/stdlib/heapq.pyi | 18 +- mypy/typeshed/stdlib/hmac.pyi | 7 +- mypy/typeshed/stdlib/html/__init__.pyi | 2 + mypy/typeshed/stdlib/html/entities.pyi | 2 + mypy/typeshed/stdlib/html/parser.pyi | 2 + mypy/typeshed/stdlib/http/__init__.pyi | 2 + mypy/typeshed/stdlib/http/client.pyi | 35 +- mypy/typeshed/stdlib/http/cookiejar.pyi | 15 +- mypy/typeshed/stdlib/http/cookies.pyi | 20 +- mypy/typeshed/stdlib/http/server.pyi | 6 + mypy/typeshed/stdlib/imaplib.pyi | 22 +- mypy/typeshed/stdlib/imghdr.pyi | 2 + mypy/typeshed/stdlib/imp.pyi | 7 +- mypy/typeshed/stdlib/importlib/__init__.pyi | 2 + mypy/typeshed/stdlib/importlib/abc.pyi | 10 +- mypy/typeshed/stdlib/importlib/machinery.pyi | 11 +- .../stdlib/importlib/metadata/__init__.pyi | 267 ++++-- mypy/typeshed/stdlib/importlib/resources.pyi | 63 +- mypy/typeshed/stdlib/inspect.pyi | 169 +++- mypy/typeshed/stdlib/io.pyi | 62 +- mypy/typeshed/stdlib/ipaddress.pyi | 82 +- mypy/typeshed/stdlib/itertools.pyi | 61 +- mypy/typeshed/stdlib/json/__init__.pyi | 12 +- mypy/typeshed/stdlib/json/decoder.pyi | 2 + mypy/typeshed/stdlib/keyword.pyi | 5 + mypy/typeshed/stdlib/lib2to3/pgen2/driver.pyi | 2 + .../typeshed/stdlib/lib2to3/pgen2/grammar.pyi | 8 +- mypy/typeshed/stdlib/lib2to3/pgen2/pgen.pyi | 2 +- .../stdlib/lib2to3/pgen2/tokenize.pyi | 147 +++- mypy/typeshed/stdlib/lib2to3/pytree.pyi | 16 +- mypy/typeshed/stdlib/linecache.pyi | 6 + mypy/typeshed/stdlib/locale.pyi | 45 +- mypy/typeshed/stdlib/logging/__init__.pyi | 72 +- mypy/typeshed/stdlib/logging/handlers.pyi | 14 +- mypy/typeshed/stdlib/lzma.pyi | 99 ++- mypy/typeshed/stdlib/mailbox.pyi | 94 ++- mypy/typeshed/stdlib/mailcap.pyi | 6 +- mypy/typeshed/stdlib/math.pyi | 8 +- mypy/typeshed/stdlib/mimetypes.pyi | 17 + mypy/typeshed/stdlib/mmap.pyi | 22 +- mypy/typeshed/stdlib/modulefinder.pyi | 2 +- mypy/typeshed/stdlib/msilib/__init__.pyi | 25 +- mypy/typeshed/stdlib/msilib/sequence.pyi | 3 +- mypy/typeshed/stdlib/msvcrt.pyi | 11 +- .../stdlib/multiprocessing/__init__.pyi | 86 +- .../stdlib/multiprocessing/connection.pyi | 15 +- .../stdlib/multiprocessing/context.pyi | 55 +- .../stdlib/multiprocessing/dummy/__init__.pyi | 25 +- .../multiprocessing/dummy/connection.pyi | 8 +- .../stdlib/multiprocessing/managers.pyi | 17 +- mypy/typeshed/stdlib/multiprocessing/pool.pyi | 14 +- .../stdlib/multiprocessing/process.pyi | 11 +- .../stdlib/multiprocessing/queues.pyi | 3 + .../stdlib/multiprocessing/reduction.pyi | 84 ++ .../stdlib/multiprocessing/shared_memory.pyi | 52 +- .../stdlib/multiprocessing/sharedctypes.pyi | 29 +- .../typeshed/stdlib/multiprocessing/spawn.pyi | 10 + .../stdlib/multiprocessing/synchronize.pyi | 16 +- mypy/typeshed/stdlib/netrc.pyi | 5 +- mypy/typeshed/stdlib/nis.pyi | 1 + mypy/typeshed/stdlib/nntplib.pyi | 58 +- mypy/typeshed/stdlib/ntpath.pyi | 88 +- mypy/typeshed/stdlib/numbers.pyi | 7 +- mypy/typeshed/stdlib/opcode.pyi | 41 +- mypy/typeshed/stdlib/operator.pyi | 116 +++ mypy/typeshed/stdlib/optparse.pyi | 36 +- mypy/typeshed/stdlib/os/__init__.pyi | 194 +++-- mypy/typeshed/stdlib/os/path.pyi | 2 + mypy/typeshed/stdlib/ossaudiodev.pyi | 249 +++--- mypy/typeshed/stdlib/parser.pyi | 2 + mypy/typeshed/stdlib/pathlib.pyi | 100 ++- mypy/typeshed/stdlib/pdb.pyi | 9 +- mypy/typeshed/stdlib/pickle.pyi | 179 +++- mypy/typeshed/stdlib/pickletools.pyi | 10 +- mypy/typeshed/stdlib/pipes.pyi | 2 + mypy/typeshed/stdlib/pkgutil.pyi | 23 +- mypy/typeshed/stdlib/plistlib.pyi | 76 +- mypy/typeshed/stdlib/poplib.pyi | 22 +- mypy/typeshed/stdlib/posix.pyi | 4 +- mypy/typeshed/stdlib/posixpath.pyi | 41 + mypy/typeshed/stdlib/pprint.pyi | 10 +- mypy/typeshed/stdlib/profile.pyi | 13 +- mypy/typeshed/stdlib/pstats.pyi | 62 +- mypy/typeshed/stdlib/pwd.pyi | 5 +- mypy/typeshed/stdlib/py_compile.pyi | 16 +- mypy/typeshed/stdlib/pyclbr.pyi | 45 +- mypy/typeshed/stdlib/pydoc.pyi | 44 +- mypy/typeshed/stdlib/pyexpat/__init__.pyi | 4 +- mypy/typeshed/stdlib/queue.pyi | 14 +- mypy/typeshed/stdlib/quopri.pyi | 2 + mypy/typeshed/stdlib/random.pyi | 140 +++- mypy/typeshed/stdlib/re.pyi | 147 +++- mypy/typeshed/stdlib/readline.pyi | 17 +- mypy/typeshed/stdlib/reprlib.pyi | 2 + mypy/typeshed/stdlib/resource.pyi | 22 +- mypy/typeshed/stdlib/rlcompleter.pyi | 4 + mypy/typeshed/stdlib/runpy.pyi | 6 +- mypy/typeshed/stdlib/sched.pyi | 30 +- mypy/typeshed/stdlib/secrets.pyi | 2 + mypy/typeshed/stdlib/select.pyi | 12 +- mypy/typeshed/stdlib/selectors.pyi | 2 +- mypy/typeshed/stdlib/shelve.pyi | 12 +- mypy/typeshed/stdlib/shlex.pyi | 23 +- mypy/typeshed/stdlib/shutil.pyi | 95 ++- mypy/typeshed/stdlib/signal.pyi | 40 +- mypy/typeshed/stdlib/smtpd.pyi | 15 +- mypy/typeshed/stdlib/smtplib.pyi | 40 +- mypy/typeshed/stdlib/sndhdr.pyi | 2 + mypy/typeshed/stdlib/socket.pyi | 19 +- mypy/typeshed/stdlib/socketserver.pyi | 81 +- mypy/typeshed/stdlib/spwd.pyi | 15 +- mypy/typeshed/stdlib/sqlite3/__init__.pyi | 2 +- mypy/typeshed/stdlib/sqlite3/dbapi2.pyi | 34 +- mypy/typeshed/stdlib/sre_constants.pyi | 3 +- mypy/typeshed/stdlib/sre_parse.pyi | 12 +- mypy/typeshed/stdlib/ssl.pyi | 44 +- mypy/typeshed/stdlib/statistics.pyi | 90 +- mypy/typeshed/stdlib/string.pyi | 15 + mypy/typeshed/stdlib/struct.pyi | 2 + mypy/typeshed/stdlib/subprocess.pyi | 137 ++- mypy/typeshed/stdlib/sunau.pyi | 15 +- mypy/typeshed/stdlib/symtable.pyi | 3 + mypy/typeshed/stdlib/sys.pyi | 223 +++-- mypy/typeshed/stdlib/sysconfig.pyi | 14 + mypy/typeshed/stdlib/tabnanny.pyi | 2 + mypy/typeshed/stdlib/tarfile.pyi | 78 +- mypy/typeshed/stdlib/telnetlib.pyi | 7 +- mypy/typeshed/stdlib/tempfile.pyi | 34 +- mypy/typeshed/stdlib/termios.pyi | 5 +- mypy/typeshed/stdlib/textwrap.pyi | 2 + mypy/typeshed/stdlib/threading.pyi | 118 ++- mypy/typeshed/stdlib/time.pyi | 21 +- mypy/typeshed/stdlib/timeit.pyi | 11 +- mypy/typeshed/stdlib/tkinter/__init__.pyi | 428 ++++++---- mypy/typeshed/stdlib/tkinter/colorchooser.pyi | 4 + mypy/typeshed/stdlib/tkinter/commondialog.pyi | 4 + mypy/typeshed/stdlib/tkinter/dialog.pyi | 4 + mypy/typeshed/stdlib/tkinter/dnd.pyi | 4 + mypy/typeshed/stdlib/tkinter/filedialog.pyi | 20 +- mypy/typeshed/stdlib/tkinter/font.pyi | 24 +- mypy/typeshed/stdlib/tkinter/messagebox.pyi | 13 + mypy/typeshed/stdlib/tkinter/scrolledtext.pyi | 2 + mypy/typeshed/stdlib/tkinter/simpledialog.pyi | 8 +- mypy/typeshed/stdlib/tkinter/tix.pyi | 2 +- mypy/typeshed/stdlib/tkinter/ttk.pyi | 127 ++- mypy/typeshed/stdlib/token.pyi | 279 +++++++ mypy/typeshed/stdlib/tokenize.pyi | 311 ++++++- mypy/typeshed/stdlib/tomllib.pyi | 10 + mypy/typeshed/stdlib/trace.pyi | 7 +- mypy/typeshed/stdlib/traceback.pyi | 116 ++- mypy/typeshed/stdlib/tracemalloc.pyi | 65 +- mypy/typeshed/stdlib/tty.pyi | 4 +- mypy/typeshed/stdlib/turtle.pyi | 150 +++- mypy/typeshed/stdlib/types.pyi | 456 +++++++--- mypy/typeshed/stdlib/typing.pyi | 784 ++++++++++++++---- mypy/typeshed/stdlib/typing_extensions.pyi | 89 +- mypy/typeshed/stdlib/unicodedata.pyi | 7 +- mypy/typeshed/stdlib/unittest/__init__.pyi | 54 +- mypy/typeshed/stdlib/unittest/_log.pyi | 5 +- mypy/typeshed/stdlib/unittest/async_case.pyi | 15 +- mypy/typeshed/stdlib/unittest/case.pyi | 80 +- mypy/typeshed/stdlib/unittest/loader.pyi | 14 +- mypy/typeshed/stdlib/unittest/main.pyi | 5 +- mypy/typeshed/stdlib/unittest/mock.pyi | 257 +++--- mypy/typeshed/stdlib/unittest/result.pyi | 4 +- mypy/typeshed/stdlib/unittest/runner.pyi | 8 +- mypy/typeshed/stdlib/unittest/suite.pyi | 5 +- mypy/typeshed/stdlib/unittest/util.pyi | 2 +- mypy/typeshed/stdlib/urllib/error.pyi | 4 +- mypy/typeshed/stdlib/urllib/parse.pyi | 51 +- mypy/typeshed/stdlib/urllib/request.pyi | 57 +- mypy/typeshed/stdlib/urllib/response.pyi | 9 +- mypy/typeshed/stdlib/urllib/robotparser.pyi | 6 +- mypy/typeshed/stdlib/uu.pyi | 6 +- mypy/typeshed/stdlib/uuid.pyi | 13 +- mypy/typeshed/stdlib/venv/__init__.pyi | 1 + mypy/typeshed/stdlib/warnings.pyi | 29 +- mypy/typeshed/stdlib/wave.pyi | 29 +- mypy/typeshed/stdlib/weakref.pyi | 84 +- mypy/typeshed/stdlib/webbrowser.pyi | 25 +- mypy/typeshed/stdlib/winreg.pyi | 6 +- mypy/typeshed/stdlib/winsound.pyi | 28 +- mypy/typeshed/stdlib/wsgiref/handlers.pyi | 10 +- .../typeshed/stdlib/wsgiref/simple_server.pyi | 8 +- mypy/typeshed/stdlib/wsgiref/util.pyi | 3 + mypy/typeshed/stdlib/wsgiref/validate.pyi | 2 + mypy/typeshed/stdlib/xdrlib.pyi | 2 + mypy/typeshed/stdlib/xml/dom/minicompat.pyi | 8 +- mypy/typeshed/stdlib/xml/dom/minidom.pyi | 11 +- mypy/typeshed/stdlib/xml/dom/pulldom.pyi | 16 +- mypy/typeshed/stdlib/xml/dom/xmlbuilder.pyi | 12 +- .../stdlib/xml/etree/ElementInclude.pyi | 1 + .../typeshed/stdlib/xml/etree/ElementTree.pyi | 136 ++- .../stdlib/xml/etree/cElementTree.pyi | 2 +- mypy/typeshed/stdlib/xml/sax/__init__.pyi | 10 +- mypy/typeshed/stdlib/xmlrpc/client.pyi | 22 +- mypy/typeshed/stdlib/xmlrpc/server.pyi | 13 +- mypy/typeshed/stdlib/xxlimited.pyi | 3 + mypy/typeshed/stdlib/zipapp.pyi | 6 +- mypy/typeshed/stdlib/zipfile.pyi | 59 +- mypy/typeshed/stdlib/zipimport.pyi | 4 + mypy/typeshed/stdlib/zlib.pyi | 43 +- mypy/typeshed/stdlib/zoneinfo/__init__.pyi | 11 +- .../stubs/mypy-extensions/mypy_extensions.pyi | 17 +- test-data/unit/check-flags.test | 10 + test-data/unit/check-functools.test | 5 + test-data/unit/check-generic-alias.test | 8 - test-data/unit/pythoneval.test | 6 +- 633 files changed, 13444 insertions(+), 6825 deletions(-) create mode 100644 mypy/typeshed/stdlib/asyncio/mixins.pyi create mode 100644 mypy/typeshed/stdlib/asyncio/taskgroups.pyi create mode 100644 mypy/typeshed/stdlib/multiprocessing/reduction.pyi create mode 100644 mypy/typeshed/stdlib/tomllib.pyi diff --git a/mypy/typeshed/stdlib/@python2/BaseHTTPServer.pyi b/mypy/typeshed/stdlib/@python2/BaseHTTPServer.pyi index 46946aa37c460..9aad705bde6ce 100644 --- a/mypy/typeshed/stdlib/@python2/BaseHTTPServer.pyi +++ b/mypy/typeshed/stdlib/@python2/BaseHTTPServer.pyi @@ -1,14 +1,14 @@ import mimetools import SocketServer -from typing import Any, BinaryIO, Callable, Mapping, Tuple +from typing import Any, BinaryIO, Callable, Mapping class HTTPServer(SocketServer.TCPServer): server_name: str server_port: int - def __init__(self, server_address: Tuple[str, int], RequestHandlerClass: Callable[..., BaseHTTPRequestHandler]) -> None: ... + def __init__(self, server_address: tuple[str, int], RequestHandlerClass: Callable[..., BaseHTTPRequestHandler]) -> None: ... class BaseHTTPRequestHandler(SocketServer.StreamRequestHandler): - client_address: Tuple[str, int] + client_address: tuple[str, int] server: SocketServer.BaseServer close_connection: bool command: str @@ -23,8 +23,8 @@ class BaseHTTPRequestHandler(SocketServer.StreamRequestHandler): error_content_type: str protocol_version: str MessageClass: type - responses: Mapping[int, Tuple[str, str]] - def __init__(self, request: bytes, client_address: Tuple[str, int], server: SocketServer.BaseServer) -> None: ... + responses: Mapping[int, tuple[str, str]] + def __init__(self, request: bytes, client_address: tuple[str, int], server: SocketServer.BaseServer) -> None: ... def handle(self) -> None: ... def handle_one_request(self) -> None: ... def send_error(self, code: int, message: str | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/CGIHTTPServer.pyi b/mypy/typeshed/stdlib/@python2/CGIHTTPServer.pyi index 393dcb83217fc..cc08bc02d6661 100644 --- a/mypy/typeshed/stdlib/@python2/CGIHTTPServer.pyi +++ b/mypy/typeshed/stdlib/@python2/CGIHTTPServer.pyi @@ -1,6 +1,5 @@ import SimpleHTTPServer -from typing import List class CGIHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): - cgi_directories: List[str] + cgi_directories: list[str] def do_POST(self) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/ConfigParser.pyi b/mypy/typeshed/stdlib/@python2/ConfigParser.pyi index 89167b3e7ec8d..ebf2a434e5965 100644 --- a/mypy/typeshed/stdlib/@python2/ConfigParser.pyi +++ b/mypy/typeshed/stdlib/@python2/ConfigParser.pyi @@ -1,5 +1,5 @@ from _typeshed import SupportsNoArgReadline -from typing import IO, Any, Dict, List, Sequence, Tuple +from typing import IO, Any, Sequence DEFAULTSECT: str MAX_INTERPOLATION_DEPTH: int @@ -9,8 +9,6 @@ class Error(Exception): def __init__(self, msg: str = ...) -> None: ... def _get_message(self) -> None: ... def _set_message(self, value: str) -> None: ... - def __repr__(self) -> str: ... - def __str__(self) -> str: ... class NoSectionError(Error): section: str @@ -42,7 +40,7 @@ class InterpolationDepthError(InterpolationError): class ParsingError(Error): filename: str - errors: List[Tuple[Any, Any]] + errors: list[tuple[Any, Any]] def __init__(self, filename: str) -> None: ... def append(self, lineno: Any, line: Any) -> None: ... @@ -53,26 +51,26 @@ class MissingSectionHeaderError(ParsingError): class RawConfigParser: _dict: Any - _sections: Dict[Any, Any] - _defaults: Dict[Any, Any] + _sections: dict[Any, Any] + _defaults: dict[Any, Any] _optcre: Any SECTCRE: Any OPTCRE: Any OPTCRE_NV: Any - def __init__(self, defaults: Dict[Any, Any] = ..., dict_type: Any = ..., allow_no_value: bool = ...) -> None: ... - def defaults(self) -> Dict[Any, Any]: ... - def sections(self) -> List[str]: ... + def __init__(self, defaults: dict[Any, Any] = ..., dict_type: Any = ..., allow_no_value: bool = ...) -> None: ... + def defaults(self) -> dict[Any, Any]: ... + def sections(self) -> list[str]: ... def add_section(self, section: str) -> None: ... def has_section(self, section: str) -> bool: ... - def options(self, section: str) -> List[str]: ... - def read(self, filenames: str | Sequence[str]) -> List[str]: ... + def options(self, section: str) -> list[str]: ... + def read(self, filenames: str | Sequence[str]) -> list[str]: ... def readfp(self, fp: SupportsNoArgReadline[str], filename: str = ...) -> None: ... def get(self, section: str, option: str) -> str: ... - def items(self, section: str) -> List[Tuple[Any, Any]]: ... + def items(self, section: str) -> list[tuple[Any, Any]]: ... def _get(self, section: str, conv: type, option: str) -> Any: ... def getint(self, section: str, option: str) -> int: ... def getfloat(self, section: str, option: str) -> float: ... - _boolean_states: Dict[str, bool] + _boolean_states: dict[str, bool] def getboolean(self, section: str, option: str) -> bool: ... def optionxform(self, optionstr: str) -> str: ... def has_option(self, section: str, option: str) -> bool: ... @@ -84,8 +82,8 @@ class RawConfigParser: class ConfigParser(RawConfigParser): _KEYCRE: Any - def get(self, section: str, option: str, raw: bool = ..., vars: Dict[Any, Any] | None = ...) -> Any: ... - def items(self, section: str, raw: bool = ..., vars: Dict[Any, Any] | None = ...) -> List[Tuple[str, Any]]: ... + def get(self, section: str, option: str, raw: bool = ..., vars: dict[Any, Any] | None = ...) -> Any: ... + def items(self, section: str, raw: bool = ..., vars: dict[Any, Any] | None = ...) -> list[tuple[str, Any]]: ... def _interpolate(self, section: str, option: str, rawval: Any, vars: Any) -> str: ... def _interpolation_replace(self, match: Any) -> str: ... @@ -93,5 +91,5 @@ class SafeConfigParser(ConfigParser): _interpvar_re: Any def _interpolate(self, section: str, option: str, rawval: Any, vars: Any) -> str: ... def _interpolate_some( - self, option: str, accum: List[Any], rest: str, section: str, map: Dict[Any, Any], depth: int + self, option: str, accum: list[Any], rest: str, section: str, map: dict[Any, Any], depth: int ) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/Cookie.pyi b/mypy/typeshed/stdlib/@python2/Cookie.pyi index 3d01c3c661525..dcc27a2d349dc 100644 --- a/mypy/typeshed/stdlib/@python2/Cookie.pyi +++ b/mypy/typeshed/stdlib/@python2/Cookie.pyi @@ -1,8 +1,8 @@ -from typing import Any, Dict +from typing import Any class CookieError(Exception): ... -class Morsel(Dict[Any, Any]): +class Morsel(dict[Any, Any]): key: Any def __init__(self): ... def __setitem__(self, K, V): ... @@ -14,7 +14,7 @@ class Morsel(Dict[Any, Any]): def js_output(self, attrs: Any | None = ...): ... def OutputString(self, attrs: Any | None = ...): ... -class BaseCookie(Dict[Any, Any]): +class BaseCookie(dict[Any, Any]): def value_decode(self, val): ... def value_encode(self, val): ... def __init__(self, input: Any | None = ...): ... diff --git a/mypy/typeshed/stdlib/@python2/HTMLParser.pyi b/mypy/typeshed/stdlib/@python2/HTMLParser.pyi index ebc2735e9c484..755f0d058b15c 100644 --- a/mypy/typeshed/stdlib/@python2/HTMLParser.pyi +++ b/mypy/typeshed/stdlib/@python2/HTMLParser.pyi @@ -1,4 +1,4 @@ -from typing import AnyStr, List, Tuple +from typing import AnyStr from markupbase import ParserBase @@ -10,8 +10,8 @@ class HTMLParser(ParserBase): def get_starttag_text(self) -> AnyStr: ... def set_cdata_mode(self, AnyStr) -> None: ... def clear_cdata_mode(self) -> None: ... - def handle_startendtag(self, tag: AnyStr, attrs: List[Tuple[AnyStr, AnyStr]]): ... - def handle_starttag(self, tag: AnyStr, attrs: List[Tuple[AnyStr, AnyStr]]): ... + def handle_startendtag(self, tag: AnyStr, attrs: list[tuple[AnyStr, AnyStr]]): ... + def handle_starttag(self, tag: AnyStr, attrs: list[tuple[AnyStr, AnyStr]]): ... def handle_endtag(self, tag: AnyStr): ... def handle_charref(self, name: AnyStr): ... def handle_entityref(self, name: AnyStr): ... diff --git a/mypy/typeshed/stdlib/@python2/Queue.pyi b/mypy/typeshed/stdlib/@python2/Queue.pyi index 24743a80280dc..a533807231885 100644 --- a/mypy/typeshed/stdlib/@python2/Queue.pyi +++ b/mypy/typeshed/stdlib/@python2/Queue.pyi @@ -1,4 +1,5 @@ -from typing import Any, Deque, Generic, TypeVar +from collections import deque +from typing import Any, Generic, TypeVar _T = TypeVar("_T") @@ -12,7 +13,7 @@ class Queue(Generic[_T]): not_full: Any all_tasks_done: Any unfinished_tasks: Any - queue: Deque[Any] # undocumented + queue: deque[Any] # undocumented def __init__(self, maxsize: int = ...) -> None: ... def task_done(self) -> None: ... def join(self) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/SocketServer.pyi b/mypy/typeshed/stdlib/@python2/SocketServer.pyi index e5a19ffd5e686..545ee8464f16d 100644 --- a/mypy/typeshed/stdlib/@python2/SocketServer.pyi +++ b/mypy/typeshed/stdlib/@python2/SocketServer.pyi @@ -1,11 +1,11 @@ import sys from socket import SocketType -from typing import Any, BinaryIO, Callable, ClassVar, List, Text, Tuple, Union +from typing import Any, BinaryIO, Callable, ClassVar, Text class BaseServer: address_family: int RequestHandlerClass: Callable[..., BaseRequestHandler] - server_address: Tuple[str, int] + server_address: tuple[str, int] socket: SocketType allow_reuse_address: bool request_queue_size: int @@ -17,19 +17,19 @@ class BaseServer: def serve_forever(self, poll_interval: float = ...) -> None: ... def shutdown(self) -> None: ... def server_close(self) -> None: ... - def finish_request(self, request: bytes, client_address: Tuple[str, int]) -> None: ... - def get_request(self) -> Tuple[SocketType, Tuple[str, int]]: ... - def handle_error(self, request: bytes, client_address: Tuple[str, int]) -> None: ... + def finish_request(self, request: bytes, client_address: tuple[str, int]) -> None: ... + def get_request(self) -> tuple[SocketType, tuple[str, int]]: ... + def handle_error(self, request: bytes, client_address: tuple[str, int]) -> None: ... def handle_timeout(self) -> None: ... - def process_request(self, request: bytes, client_address: Tuple[str, int]) -> None: ... + def process_request(self, request: bytes, client_address: tuple[str, int]) -> None: ... def server_activate(self) -> None: ... def server_bind(self) -> None: ... - def verify_request(self, request: bytes, client_address: Tuple[str, int]) -> bool: ... + def verify_request(self, request: bytes, client_address: tuple[str, int]) -> bool: ... class TCPServer(BaseServer): def __init__( self, - server_address: Tuple[str, int], + server_address: tuple[str, int], RequestHandlerClass: Callable[..., BaseRequestHandler], bind_and_activate: bool = ..., ) -> None: ... @@ -37,7 +37,7 @@ class TCPServer(BaseServer): class UDPServer(BaseServer): def __init__( self, - server_address: Tuple[str, int], + server_address: tuple[str, int], RequestHandlerClass: Callable[..., BaseRequestHandler], bind_and_activate: bool = ..., ) -> None: ... @@ -50,6 +50,7 @@ if sys.platform != "win32": RequestHandlerClass: Callable[..., BaseRequestHandler], bind_and_activate: bool = ..., ) -> None: ... + class UnixDatagramServer(BaseServer): def __init__( self, @@ -61,16 +62,16 @@ if sys.platform != "win32": if sys.platform != "win32": class ForkingMixIn: timeout: float | None # undocumented - active_children: List[int] | None # undocumented + active_children: list[int] | None # undocumented max_children: int # undocumented def collect_children(self) -> None: ... # undocumented def handle_timeout(self) -> None: ... # undocumented - def process_request(self, request: bytes, client_address: Tuple[str, int]) -> None: ... + def process_request(self, request: bytes, client_address: tuple[str, int]) -> None: ... class ThreadingMixIn: daemon_threads: bool - def process_request_thread(self, request: bytes, client_address: Tuple[str, int]) -> None: ... # undocumented - def process_request(self, request: bytes, client_address: Tuple[str, int]) -> None: ... + def process_request_thread(self, request: bytes, client_address: tuple[str, int]) -> None: ... # undocumented + def process_request(self, request: bytes, client_address: tuple[str, int]) -> None: ... if sys.platform != "win32": class ForkingTCPServer(ForkingMixIn, TCPServer): ... diff --git a/mypy/typeshed/stdlib/@python2/StringIO.pyi b/mypy/typeshed/stdlib/@python2/StringIO.pyi index efa90f8e0330a..4aa0cb3fcd5a5 100644 --- a/mypy/typeshed/stdlib/@python2/StringIO.pyi +++ b/mypy/typeshed/stdlib/@python2/StringIO.pyi @@ -1,4 +1,4 @@ -from typing import IO, Any, AnyStr, Generic, Iterable, Iterator, List +from typing import IO, Any, AnyStr, Generic, Iterable, Iterator class StringIO(IO[AnyStr], Generic[AnyStr]): closed: bool @@ -14,7 +14,7 @@ class StringIO(IO[AnyStr], Generic[AnyStr]): def tell(self) -> int: ... def read(self, n: int = ...) -> AnyStr: ... def readline(self, length: int = ...) -> AnyStr: ... - def readlines(self, sizehint: int = ...) -> List[AnyStr]: ... + def readlines(self, sizehint: int = ...) -> list[AnyStr]: ... def truncate(self, size: int | None = ...) -> int: ... def write(self, s: AnyStr) -> int: ... def writelines(self, iterable: Iterable[AnyStr]) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/UserDict.pyi b/mypy/typeshed/stdlib/@python2/UserDict.pyi index dce7bebafd668..fd21ff0e684b9 100644 --- a/mypy/typeshed/stdlib/@python2/UserDict.pyi +++ b/mypy/typeshed/stdlib/@python2/UserDict.pyi @@ -1,11 +1,11 @@ -from typing import Any, Container, Dict, Generic, Iterable, Iterator, List, Mapping, Sized, Tuple, TypeVar, overload +from typing import Any, Container, Generic, Iterable, Iterator, Mapping, Sized, TypeVar, overload _KT = TypeVar("_KT") _VT = TypeVar("_VT") _T = TypeVar("_T") -class UserDict(Dict[_KT, _VT], Generic[_KT, _VT]): - data: Dict[_KT, _VT] +class UserDict(dict[_KT, _VT], Generic[_KT, _VT]): + data: dict[_KT, _VT] def __init__(self, initialdata: Mapping[_KT, _VT] = ...) -> None: ... # TODO: __iter__ is not available for UserDict @@ -21,18 +21,18 @@ class DictMixin(Iterable[_KT], Container[_KT], Sized, Generic[_KT, _VT]): def get(self, k: _KT) -> _VT | None: ... @overload def get(self, k: _KT, default: _VT | _T) -> _VT | _T: ... - def values(self) -> List[_VT]: ... - def items(self) -> List[Tuple[_KT, _VT]]: ... + def values(self) -> list[_VT]: ... + def items(self) -> list[tuple[_KT, _VT]]: ... def iterkeys(self) -> Iterator[_KT]: ... def itervalues(self) -> Iterator[_VT]: ... - def iteritems(self) -> Iterator[Tuple[_KT, _VT]]: ... + def iteritems(self) -> Iterator[tuple[_KT, _VT]]: ... def __contains__(self, o: Any) -> bool: ... # From typing.MutableMapping[_KT, _VT] def clear(self) -> None: ... def pop(self, k: _KT, default: _VT = ...) -> _VT: ... - def popitem(self) -> Tuple[_KT, _VT]: ... + def popitem(self) -> tuple[_KT, _VT]: ... def setdefault(self, k: _KT, default: _VT = ...) -> _VT: ... @overload def update(self, m: Mapping[_KT, _VT], **kwargs: _VT) -> None: ... @overload - def update(self, m: Iterable[Tuple[_KT, _VT]], **kwargs: _VT) -> None: ... + def update(self, m: Iterable[tuple[_KT, _VT]], **kwargs: _VT) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/UserList.pyi b/mypy/typeshed/stdlib/@python2/UserList.pyi index be4ebce5a815a..36a4bc6a001c6 100644 --- a/mypy/typeshed/stdlib/@python2/UserList.pyi +++ b/mypy/typeshed/stdlib/@python2/UserList.pyi @@ -1,10 +1,10 @@ -from typing import Iterable, List, MutableSequence, TypeVar, overload +from _typeshed import Self +from typing import Iterable, MutableSequence, TypeVar, overload _T = TypeVar("_T") -_S = TypeVar("_S") class UserList(MutableSequence[_T]): - data: List[_T] + data: list[_T] def insert(self, index: int, object: _T) -> None: ... @overload def __setitem__(self, i: int, o: _T) -> None: ... @@ -15,5 +15,5 @@ class UserList(MutableSequence[_T]): @overload def __getitem__(self, i: int) -> _T: ... @overload - def __getitem__(self: _S, s: slice) -> _S: ... + def __getitem__(self: Self, s: slice) -> Self: ... def sort(self) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/UserString.pyi b/mypy/typeshed/stdlib/@python2/UserString.pyi index f60dbe18f9b19..7598fcaee04da 100644 --- a/mypy/typeshed/stdlib/@python2/UserString.pyi +++ b/mypy/typeshed/stdlib/@python2/UserString.pyi @@ -1,7 +1,5 @@ -from typing import Any, Iterable, List, MutableSequence, Sequence, Text, Tuple, TypeVar, overload - -_UST = TypeVar("_UST", bound=UserString) -_MST = TypeVar("_MST", bound=MutableString) +from _typeshed import Self +from typing import Any, Iterable, MutableSequence, Sequence, Text, overload class UserString(Sequence[UserString]): data: unicode @@ -13,21 +11,21 @@ class UserString(Sequence[UserString]): def __hash__(self) -> int: ... def __len__(self) -> int: ... @overload - def __getitem__(self: _UST, i: int) -> _UST: ... + def __getitem__(self: Self, i: int) -> Self: ... @overload - def __getitem__(self: _UST, s: slice) -> _UST: ... - def __add__(self: _UST, other: Any) -> _UST: ... - def __radd__(self: _UST, other: Any) -> _UST: ... - def __mul__(self: _UST, other: int) -> _UST: ... - def __rmul__(self: _UST, other: int) -> _UST: ... - def __mod__(self: _UST, args: Any) -> _UST: ... - def capitalize(self: _UST) -> _UST: ... - def center(self: _UST, width: int, *args: Any) -> _UST: ... + def __getitem__(self: Self, s: slice) -> Self: ... + def __add__(self: Self, other: Any) -> Self: ... + def __radd__(self: Self, other: Any) -> Self: ... + def __mul__(self: Self, other: int) -> Self: ... + def __rmul__(self: Self, other: int) -> Self: ... + def __mod__(self: Self, args: Any) -> Self: ... + def capitalize(self: Self) -> Self: ... + def center(self: Self, width: int, *args: Any) -> Self: ... def count(self, sub: int, start: int = ..., end: int = ...) -> int: ... - def decode(self: _UST, encoding: str | None = ..., errors: str | None = ...) -> _UST: ... - def encode(self: _UST, encoding: str | None = ..., errors: str | None = ...) -> _UST: ... - def endswith(self, suffix: Text | Tuple[Text, ...], start: int | None = ..., end: int | None = ...) -> bool: ... - def expandtabs(self: _UST, tabsize: int = ...) -> _UST: ... + def decode(self: Self, encoding: str | None = ..., errors: str | None = ...) -> Self: ... + def encode(self: Self, encoding: str | None = ..., errors: str | None = ...) -> Self: ... + def endswith(self, suffix: Text | tuple[Text, ...], start: int | None = ..., end: int | None = ...) -> bool: ... + def expandtabs(self: Self, tabsize: int = ...) -> Self: ... def find(self, sub: Text, start: int = ..., end: int = ...) -> int: ... def index(self, sub: Text, start: int = ..., end: int = ...) -> int: ... def isalpha(self) -> bool: ... @@ -40,35 +38,35 @@ class UserString(Sequence[UserString]): def istitle(self) -> bool: ... def isupper(self) -> bool: ... def join(self, seq: Iterable[Text]) -> Text: ... - def ljust(self: _UST, width: int, *args: Any) -> _UST: ... - def lower(self: _UST) -> _UST: ... - def lstrip(self: _UST, chars: Text | None = ...) -> _UST: ... - def partition(self, sep: Text) -> Tuple[Text, Text, Text]: ... - def replace(self: _UST, old: Text, new: Text, maxsplit: int = ...) -> _UST: ... + def ljust(self: Self, width: int, *args: Any) -> Self: ... + def lower(self: Self) -> Self: ... + def lstrip(self: Self, chars: Text | None = ...) -> Self: ... + def partition(self, sep: Text) -> tuple[Text, Text, Text]: ... + def replace(self: Self, old: Text, new: Text, maxsplit: int = ...) -> Self: ... def rfind(self, sub: Text, start: int = ..., end: int = ...) -> int: ... def rindex(self, sub: Text, start: int = ..., end: int = ...) -> int: ... - def rjust(self: _UST, width: int, *args: Any) -> _UST: ... - def rpartition(self, sep: Text) -> Tuple[Text, Text, Text]: ... - def rstrip(self: _UST, chars: Text | None = ...) -> _UST: ... - def split(self, sep: Text | None = ..., maxsplit: int = ...) -> List[Text]: ... - def rsplit(self, sep: Text | None = ..., maxsplit: int = ...) -> List[Text]: ... - def splitlines(self, keepends: int = ...) -> List[Text]: ... - def startswith(self, prefix: Text | Tuple[Text, ...], start: int | None = ..., end: int | None = ...) -> bool: ... - def strip(self: _UST, chars: Text | None = ...) -> _UST: ... - def swapcase(self: _UST) -> _UST: ... - def title(self: _UST) -> _UST: ... - def translate(self: _UST, *args: Any) -> _UST: ... - def upper(self: _UST) -> _UST: ... - def zfill(self: _UST, width: int) -> _UST: ... + def rjust(self: Self, width: int, *args: Any) -> Self: ... + def rpartition(self, sep: Text) -> tuple[Text, Text, Text]: ... + def rstrip(self: Self, chars: Text | None = ...) -> Self: ... + def split(self, sep: Text | None = ..., maxsplit: int = ...) -> list[Text]: ... + def rsplit(self, sep: Text | None = ..., maxsplit: int = ...) -> list[Text]: ... + def splitlines(self, keepends: int = ...) -> list[Text]: ... + def startswith(self, prefix: Text | tuple[Text, ...], start: int | None = ..., end: int | None = ...) -> bool: ... + def strip(self: Self, chars: Text | None = ...) -> Self: ... + def swapcase(self: Self) -> Self: ... + def title(self: Self) -> Self: ... + def translate(self: Self, *args: Any) -> Self: ... + def upper(self: Self) -> Self: ... + def zfill(self: Self, width: int) -> Self: ... class MutableString(UserString, MutableSequence[MutableString]): @overload - def __getitem__(self: _MST, i: int) -> _MST: ... + def __getitem__(self: Self, i: int) -> Self: ... @overload - def __getitem__(self: _MST, s: slice) -> _MST: ... + def __getitem__(self: Self, s: slice) -> Self: ... def __setitem__(self, index: int | slice, sub: Any) -> None: ... def __delitem__(self, index: int | slice) -> None: ... def immutable(self) -> UserString: ... - def __iadd__(self: _MST, other: Any) -> _MST: ... - def __imul__(self, n: int) -> _MST: ... + def __iadd__(self: Self, other: Any) -> Self: ... + def __imul__(self: Self, n: int) -> Self: ... def insert(self, index: int, value: Any) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/__builtin__.pyi b/mypy/typeshed/stdlib/@python2/__builtin__.pyi index fad8b2b4e7d8e..d936e08b82660 100644 --- a/mypy/typeshed/stdlib/@python2/__builtin__.pyi +++ b/mypy/typeshed/stdlib/@python2/__builtin__.pyi @@ -1,7 +1,7 @@ # True and False are deliberately omitted because they are keywords in # Python 3, and stub files conform to Python 3 syntax. -from _typeshed import ReadableBuffer, SupportsKeysAndGetItem, SupportsWrite +from _typeshed import ReadableBuffer, Self, SupportsKeysAndGetItem, SupportsWrite from abc import ABCMeta from ast import mod from types import CodeType @@ -12,15 +12,13 @@ from typing import ( BinaryIO, ByteString, Callable, + ClassVar, Container, - Dict, - FrozenSet, Generic, ItemsView, Iterable, Iterator, KeysView, - List, Mapping, MutableMapping, MutableSequence, @@ -29,15 +27,12 @@ from typing import ( Protocol, Reversible, Sequence, - Set, Sized, SupportsAbs, SupportsComplex, SupportsFloat, SupportsInt, Text, - Tuple, - Type, TypeVar, ValuesView, overload, @@ -60,70 +55,68 @@ _T2 = TypeVar("_T2") _T3 = TypeVar("_T3") _T4 = TypeVar("_T4") _T5 = TypeVar("_T5") -_TT = TypeVar("_TT", bound="type") -_TBE = TypeVar("_TBE", bound="BaseException") +_TT = TypeVar("_TT", bound=type) class object: __doc__: str | None - __dict__: Dict[str, Any] - __slots__: Text | Iterable[Text] + __dict__: dict[str, Any] __module__: str @property - def __class__(self: _T) -> Type[_T]: ... + def __class__(self: _T) -> type[_T]: ... @__class__.setter - def __class__(self, __type: Type[object]) -> None: ... # noqa: F811 + def __class__(self, __type: type[object]) -> None: ... # noqa: F811 def __init__(self) -> None: ... def __new__(cls) -> Any: ... def __setattr__(self, name: str, value: Any) -> None: ... def __eq__(self, o: object) -> bool: ... def __ne__(self, o: object) -> bool: ... - def __str__(self) -> str: ... - def __repr__(self) -> str: ... + def __str__(self) -> str: ... # noqa: Y029 + def __repr__(self) -> str: ... # noqa: Y029 def __hash__(self) -> int: ... def __format__(self, format_spec: str) -> str: ... def __getattribute__(self, name: str) -> Any: ... def __delattr__(self, name: str) -> None: ... def __sizeof__(self) -> int: ... - def __reduce__(self) -> str | Tuple[Any, ...]: ... - def __reduce_ex__(self, protocol: int) -> str | Tuple[Any, ...]: ... + def __reduce__(self) -> str | tuple[Any, ...]: ... + def __reduce_ex__(self, protocol: int) -> str | tuple[Any, ...]: ... class staticmethod(object): # Special, only valid as a decorator. __func__: Callable[..., Any] def __init__(self, f: Callable[..., Any]) -> None: ... - def __new__(cls: Type[_T], *args: Any, **kwargs: Any) -> _T: ... - def __get__(self, obj: _T, type: Type[_T] | None = ...) -> Callable[..., Any]: ... + def __new__(cls: type[Self], *args: Any, **kwargs: Any) -> Self: ... + def __get__(self, obj: _T, type: type[_T] | None = ...) -> Callable[..., Any]: ... class classmethod(object): # Special, only valid as a decorator. __func__: Callable[..., Any] def __init__(self, f: Callable[..., Any]) -> None: ... - def __new__(cls: Type[_T], *args: Any, **kwargs: Any) -> _T: ... - def __get__(self, obj: _T, type: Type[_T] | None = ...) -> Callable[..., Any]: ... + def __new__(cls: type[Self], *args: Any, **kwargs: Any) -> Self: ... + def __get__(self, obj: _T, type: type[_T] | None = ...) -> Callable[..., Any]: ... class type(object): __base__: type - __bases__: Tuple[type, ...] + __bases__: tuple[type, ...] __basicsize__: int - __dict__: Dict[str, Any] + __dict__: dict[str, Any] __dictoffset__: int __flags__: int __itemsize__: int __module__: str - __mro__: Tuple[type, ...] + __mro__: tuple[type, ...] __name__: str __weakrefoffset__: int @overload def __init__(self, o: object) -> None: ... @overload - def __init__(self, name: str, bases: Tuple[type, ...], dict: Dict[str, Any]) -> None: ... + def __init__(self, name: str, bases: tuple[type, ...], dict: dict[str, Any]) -> None: ... @overload def __new__(cls, o: object) -> type: ... @overload - def __new__(cls, name: str, bases: Tuple[type, ...], namespace: Dict[str, Any]) -> type: ... + def __new__(cls, name: str, bases: tuple[type, ...], namespace: dict[str, Any]) -> type: ... def __call__(self, *args: Any, **kwds: Any) -> Any: ... - def __subclasses__(self: _TT) -> List[_TT]: ... + def __subclasses__(self: _TT) -> list[_TT]: ... # Note: the documentation doesn't specify what the return type is, the standard # implementation seems to be returning a list. - def mro(self) -> List[type]: ... + def mro(self) -> list[type]: ... def __instancecheck__(self, instance: Any) -> bool: ... def __subclasscheck__(self, subclass: type) -> bool: ... @@ -135,9 +128,9 @@ class super(object): class int: @overload - def __new__(cls: Type[_T], x: Text | bytes | SupportsInt | _SupportsIndex | _SupportsTrunc = ...) -> _T: ... + def __new__(cls: type[Self], x: Text | bytes | SupportsInt | _SupportsIndex | _SupportsTrunc = ...) -> Self: ... @overload - def __new__(cls: Type[_T], x: Text | bytes | bytearray, base: int) -> _T: ... + def __new__(cls: type[Self], x: Text | bytes | bytearray, base: int) -> Self: ... @property def real(self) -> int: ... @property @@ -155,7 +148,7 @@ class int: def __div__(self, x: int) -> int: ... def __truediv__(self, x: int) -> float: ... def __mod__(self, x: int) -> int: ... - def __divmod__(self, x: int) -> Tuple[int, int]: ... + def __divmod__(self, x: int) -> tuple[int, int]: ... def __radd__(self, x: int) -> int: ... def __rsub__(self, x: int) -> int: ... def __rmul__(self, x: int) -> int: ... @@ -163,7 +156,7 @@ class int: def __rdiv__(self, x: int) -> int: ... def __rtruediv__(self, x: int) -> float: ... def __rmod__(self, x: int) -> int: ... - def __rdivmod__(self, x: int) -> Tuple[int, int]: ... + def __rdivmod__(self, x: int) -> tuple[int, int]: ... @overload def __pow__(self, __x: Literal[2], __modulo: int | None = ...) -> int: ... @overload @@ -183,14 +176,13 @@ class int: def __pos__(self) -> int: ... def __invert__(self) -> int: ... def __trunc__(self) -> int: ... - def __getnewargs__(self) -> Tuple[int]: ... + def __getnewargs__(self) -> tuple[int]: ... def __eq__(self, x: object) -> bool: ... def __ne__(self, x: object) -> bool: ... def __lt__(self, x: int) -> bool: ... def __le__(self, x: int) -> bool: ... def __gt__(self, x: int) -> bool: ... def __ge__(self, x: int) -> bool: ... - def __str__(self) -> str: ... def __float__(self) -> float: ... def __int__(self) -> int: ... def __abs__(self) -> int: ... @@ -199,8 +191,8 @@ class int: def __index__(self) -> int: ... class float: - def __new__(cls: Type[_T], x: SupportsFloat | _SupportsIndex | Text | bytes | bytearray = ...) -> _T: ... - def as_integer_ratio(self) -> Tuple[int, int]: ... + def __new__(cls: type[Self], x: SupportsFloat | _SupportsIndex | Text | bytes | bytearray = ...) -> Self: ... + def as_integer_ratio(self) -> tuple[int, int]: ... def hex(self) -> str: ... def is_integer(self) -> bool: ... @classmethod @@ -217,7 +209,7 @@ class float: def __div__(self, x: float) -> float: ... def __truediv__(self, x: float) -> float: ... def __mod__(self, x: float) -> float: ... - def __divmod__(self, x: float) -> Tuple[float, float]: ... + def __divmod__(self, x: float) -> tuple[float, float]: ... def __pow__( self, x: float, mod: None = ... ) -> float: ... # In Python 3, returns complex if self is negative and x is not whole @@ -228,9 +220,9 @@ class float: def __rdiv__(self, x: float) -> float: ... def __rtruediv__(self, x: float) -> float: ... def __rmod__(self, x: float) -> float: ... - def __rdivmod__(self, x: float) -> Tuple[float, float]: ... + def __rdivmod__(self, x: float) -> tuple[float, float]: ... def __rpow__(self, x: float, mod: None = ...) -> float: ... - def __getnewargs__(self) -> Tuple[float]: ... + def __getnewargs__(self) -> tuple[float]: ... def __trunc__(self) -> int: ... def __eq__(self, x: object) -> bool: ... def __ne__(self, x: object) -> bool: ... @@ -240,7 +232,6 @@ class float: def __ge__(self, x: float) -> bool: ... def __neg__(self) -> float: ... def __pos__(self) -> float: ... - def __str__(self) -> str: ... def __int__(self) -> int: ... def __float__(self) -> float: ... def __abs__(self) -> float: ... @@ -249,9 +240,9 @@ class float: class complex: @overload - def __new__(cls: Type[_T], real: float = ..., imag: float = ...) -> _T: ... + def __new__(cls: type[Self], real: float = ..., imag: float = ...) -> Self: ... @overload - def __new__(cls: Type[_T], real: str | SupportsComplex | _SupportsIndex) -> _T: ... + def __new__(cls: type[Self], real: str | SupportsComplex | _SupportsIndex) -> Self: ... @property def real(self) -> float: ... @property @@ -273,7 +264,6 @@ class complex: def __ne__(self, x: object) -> bool: ... def __neg__(self) -> complex: ... def __pos__(self) -> complex: ... - def __str__(self) -> str: ... def __complex__(self) -> complex: ... def __abs__(self) -> float: ... def __hash__(self) -> int: ... @@ -293,7 +283,7 @@ class unicode(basestring, Sequence[unicode]): def count(self, x: unicode) -> int: ... def decode(self, encoding: unicode = ..., errors: unicode = ...) -> unicode: ... def encode(self, encoding: unicode = ..., errors: unicode = ...) -> str: ... - def endswith(self, __suffix: unicode | Tuple[unicode, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... + def endswith(self, __suffix: unicode | tuple[unicode, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... def expandtabs(self, tabsize: int = ...) -> unicode: ... def find(self, sub: unicode, start: int = ..., end: int = ...) -> int: ... def format(self, *args: object, **kwargs: object) -> unicode: ... @@ -313,21 +303,21 @@ class unicode(basestring, Sequence[unicode]): def ljust(self, width: int, fillchar: unicode = ...) -> unicode: ... def lower(self) -> unicode: ... def lstrip(self, chars: unicode = ...) -> unicode: ... - def partition(self, sep: unicode) -> Tuple[unicode, unicode, unicode]: ... + def partition(self, sep: unicode) -> tuple[unicode, unicode, unicode]: ... def replace(self, old: unicode, new: unicode, count: int = ...) -> unicode: ... def rfind(self, sub: unicode, start: int = ..., end: int = ...) -> int: ... def rindex(self, sub: unicode, start: int = ..., end: int = ...) -> int: ... def rjust(self, width: int, fillchar: unicode = ...) -> unicode: ... - def rpartition(self, sep: unicode) -> Tuple[unicode, unicode, unicode]: ... - def rsplit(self, sep: unicode | None = ..., maxsplit: int = ...) -> List[unicode]: ... + def rpartition(self, sep: unicode) -> tuple[unicode, unicode, unicode]: ... + def rsplit(self, sep: unicode | None = ..., maxsplit: int = ...) -> list[unicode]: ... def rstrip(self, chars: unicode = ...) -> unicode: ... - def split(self, sep: unicode | None = ..., maxsplit: int = ...) -> List[unicode]: ... - def splitlines(self, keepends: bool = ...) -> List[unicode]: ... - def startswith(self, __prefix: unicode | Tuple[unicode, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... + def split(self, sep: unicode | None = ..., maxsplit: int = ...) -> list[unicode]: ... + def splitlines(self, keepends: bool = ...) -> list[unicode]: ... + def startswith(self, __prefix: unicode | tuple[unicode, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... def strip(self, chars: unicode = ...) -> unicode: ... def swapcase(self) -> unicode: ... def title(self) -> unicode: ... - def translate(self, table: Dict[int, Any] | unicode) -> unicode: ... + def translate(self, table: dict[int, Any] | unicode) -> unicode: ... def upper(self) -> unicode: ... def zfill(self, width: int) -> unicode: ... @overload @@ -347,14 +337,12 @@ class unicode(basestring, Sequence[unicode]): def __ge__(self, x: unicode) -> bool: ... def __len__(self) -> int: ... # The argument type is incompatible with Sequence - def __contains__(self, s: unicode | bytes) -> bool: ... # type: ignore + def __contains__(self, s: unicode | bytes) -> bool: ... # type: ignore[override] def __iter__(self) -> Iterator[unicode]: ... - def __str__(self) -> str: ... - def __repr__(self) -> str: ... def __int__(self) -> int: ... def __float__(self) -> float: ... def __hash__(self) -> int: ... - def __getnewargs__(self) -> Tuple[unicode]: ... + def __getnewargs__(self) -> tuple[unicode]: ... class _FormatMapMapping(Protocol): def __getitem__(self, __key: str) -> Any: ... @@ -366,7 +354,7 @@ class str(Sequence[str], basestring): def count(self, x: Text, __start: int | None = ..., __end: int | None = ...) -> int: ... def decode(self, encoding: Text = ..., errors: Text = ...) -> unicode: ... def encode(self, encoding: Text = ..., errors: Text = ...) -> bytes: ... - def endswith(self, __suffix: Text | Tuple[Text, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... + def endswith(self, __suffix: Text | tuple[Text, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... def expandtabs(self, tabsize: int = ...) -> str: ... def find(self, sub: Text, __start: int | None = ..., __end: int | None = ...) -> int: ... def format(self, *args: object, **kwargs: object) -> str: ... @@ -387,35 +375,35 @@ class str(Sequence[str], basestring): @overload def lstrip(self, __chars: unicode) -> unicode: ... @overload - def partition(self, __sep: bytearray) -> Tuple[str, bytearray, str]: ... + def partition(self, __sep: bytearray) -> tuple[str, bytearray, str]: ... @overload - def partition(self, __sep: str) -> Tuple[str, str, str]: ... + def partition(self, __sep: str) -> tuple[str, str, str]: ... @overload - def partition(self, __sep: unicode) -> Tuple[unicode, unicode, unicode]: ... + def partition(self, __sep: unicode) -> tuple[unicode, unicode, unicode]: ... def replace(self, __old: AnyStr, __new: AnyStr, __count: int = ...) -> AnyStr: ... def rfind(self, sub: Text, __start: int | None = ..., __end: int | None = ...) -> int: ... def rindex(self, sub: Text, __start: int | None = ..., __end: int | None = ...) -> int: ... def rjust(self, __width: int, __fillchar: str = ...) -> str: ... @overload - def rpartition(self, __sep: bytearray) -> Tuple[str, bytearray, str]: ... + def rpartition(self, __sep: bytearray) -> tuple[str, bytearray, str]: ... @overload - def rpartition(self, __sep: str) -> Tuple[str, str, str]: ... + def rpartition(self, __sep: str) -> tuple[str, str, str]: ... @overload - def rpartition(self, __sep: unicode) -> Tuple[unicode, unicode, unicode]: ... + def rpartition(self, __sep: unicode) -> tuple[unicode, unicode, unicode]: ... @overload - def rsplit(self, sep: str | None = ..., maxsplit: int = ...) -> List[str]: ... + def rsplit(self, sep: str | None = ..., maxsplit: int = ...) -> list[str]: ... @overload - def rsplit(self, sep: unicode, maxsplit: int = ...) -> List[unicode]: ... + def rsplit(self, sep: unicode, maxsplit: int = ...) -> list[unicode]: ... @overload def rstrip(self, __chars: str = ...) -> str: ... @overload def rstrip(self, __chars: unicode) -> unicode: ... @overload - def split(self, sep: str | None = ..., maxsplit: int = ...) -> List[str]: ... + def split(self, sep: str | None = ..., maxsplit: int = ...) -> list[str]: ... @overload - def split(self, sep: unicode, maxsplit: int = ...) -> List[unicode]: ... - def splitlines(self, keepends: bool = ...) -> List[str]: ... - def startswith(self, __prefix: Text | Tuple[Text, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... + def split(self, sep: unicode, maxsplit: int = ...) -> list[unicode]: ... + def splitlines(self, keepends: bool = ...) -> list[str]: ... + def startswith(self, __prefix: Text | tuple[Text, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... @overload def strip(self, __chars: str = ...) -> str: ... @overload @@ -427,7 +415,7 @@ class str(Sequence[str], basestring): def zfill(self, __width: int) -> str: ... def __add__(self, s: AnyStr) -> AnyStr: ... # Incompatible with Sequence.__contains__ - def __contains__(self, o: str | Text) -> bool: ... # type: ignore + def __contains__(self, o: str | Text) -> bool: ... # type: ignore[override] def __eq__(self, x: object) -> bool: ... def __ge__(self, x: Text) -> bool: ... def __getitem__(self, i: int | slice) -> str: ... @@ -440,10 +428,8 @@ class str(Sequence[str], basestring): def __mod__(self, x: Any) -> str: ... def __mul__(self, n: int) -> str: ... def __ne__(self, x: object) -> bool: ... - def __repr__(self) -> str: ... def __rmul__(self, n: int) -> str: ... - def __str__(self) -> str: ... - def __getnewargs__(self) -> Tuple[str]: ... + def __getnewargs__(self) -> tuple[str]: ... def __getslice__(self, start: int, stop: int) -> str: ... def __float__(self) -> float: ... def __int__(self) -> int: ... @@ -465,7 +451,7 @@ class bytearray(MutableSequence[int], ByteString): def center(self, __width: int, __fillchar: bytes = ...) -> bytearray: ... def count(self, __sub: str) -> int: ... def decode(self, encoding: Text = ..., errors: Text = ...) -> str: ... - def endswith(self, __suffix: bytes | Tuple[bytes, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... + def endswith(self, __suffix: bytes | tuple[bytes, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... def expandtabs(self, tabsize: int = ...) -> bytearray: ... def extend(self, iterable: str | Iterable[int]) -> None: ... def find(self, __sub: str, __start: int = ..., __end: int = ...) -> int: ... @@ -482,17 +468,17 @@ class bytearray(MutableSequence[int], ByteString): def ljust(self, __width: int, __fillchar: str = ...) -> bytearray: ... def lower(self) -> bytearray: ... def lstrip(self, __bytes: bytes | None = ...) -> bytearray: ... - def partition(self, __sep: bytes) -> Tuple[bytearray, bytearray, bytearray]: ... + def partition(self, __sep: bytes) -> tuple[bytearray, bytearray, bytearray]: ... def replace(self, __old: bytes, __new: bytes, __count: int = ...) -> bytearray: ... def rfind(self, __sub: bytes, __start: int = ..., __end: int = ...) -> int: ... def rindex(self, __sub: bytes, __start: int = ..., __end: int = ...) -> int: ... def rjust(self, __width: int, __fillchar: bytes = ...) -> bytearray: ... - def rpartition(self, __sep: bytes) -> Tuple[bytearray, bytearray, bytearray]: ... - def rsplit(self, sep: bytes | None = ..., maxsplit: int = ...) -> List[bytearray]: ... + def rpartition(self, __sep: bytes) -> tuple[bytearray, bytearray, bytearray]: ... + def rsplit(self, sep: bytes | None = ..., maxsplit: int = ...) -> list[bytearray]: ... def rstrip(self, __bytes: bytes | None = ...) -> bytearray: ... - def split(self, sep: bytes | None = ..., maxsplit: int = ...) -> List[bytearray]: ... - def splitlines(self, keepends: bool = ...) -> List[bytearray]: ... - def startswith(self, __prefix: bytes | Tuple[bytes, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... + def split(self, sep: bytes | None = ..., maxsplit: int = ...) -> list[bytearray]: ... + def splitlines(self, keepends: bool = ...) -> list[bytearray]: ... + def startswith(self, __prefix: bytes | tuple[bytes, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... def strip(self, __bytes: bytes | None = ...) -> bytearray: ... def swapcase(self) -> bytearray: ... def title(self) -> bytearray: ... @@ -503,11 +489,9 @@ class bytearray(MutableSequence[int], ByteString): def fromhex(cls, __string: str) -> bytearray: ... def __len__(self) -> int: ... def __iter__(self) -> Iterator[int]: ... - def __str__(self) -> str: ... - def __repr__(self) -> str: ... def __int__(self) -> int: ... def __float__(self) -> float: ... - __hash__: None # type: ignore + __hash__: ClassVar[None] # type: ignore[assignment] @overload def __getitem__(self, i: int) -> int: ... @overload @@ -523,7 +507,7 @@ class bytearray(MutableSequence[int], ByteString): def __add__(self, s: bytes) -> bytearray: ... def __mul__(self, n: int) -> bytearray: ... # Incompatible with Sequence.__contains__ - def __contains__(self, o: int | bytes) -> bool: ... # type: ignore + def __contains__(self, o: int | bytes) -> bool: ... # type: ignore[override] def __eq__(self, x: object) -> bool: ... def __ne__(self, x: object) -> bool: ... def __lt__(self, x: bytes) -> bool: ... @@ -534,9 +518,9 @@ class bytearray(MutableSequence[int], ByteString): class memoryview(Sized, Container[str]): format: str itemsize: int - shape: Tuple[int, ...] | None - strides: Tuple[int, ...] | None - suboffsets: Tuple[int, ...] | None + shape: tuple[int, ...] | None + strides: tuple[int, ...] | None + suboffsets: tuple[int, ...] | None readonly: bool ndim: int def __init__(self, obj: ReadableBuffer) -> None: ... @@ -552,11 +536,11 @@ class memoryview(Sized, Container[str]): @overload def __setitem__(self, i: int, o: int) -> None: ... def tobytes(self) -> bytes: ... - def tolist(self) -> List[int]: ... + def tolist(self) -> list[int]: ... @final class bool(int): - def __new__(cls: Type[_T], __o: object = ...) -> _T: ... + def __new__(cls: type[Self], __o: object = ...) -> Self: ... @overload def __and__(self, x: bool) -> bool: ... @overload @@ -581,7 +565,7 @@ class bool(int): def __rxor__(self, x: bool) -> bool: ... @overload def __rxor__(self, x: int) -> int: ... - def __getnewargs__(self) -> Tuple[int]: ... + def __getnewargs__(self) -> tuple[int]: ... class slice(object): start: Any @@ -591,28 +575,28 @@ class slice(object): def __init__(self, stop: Any) -> None: ... @overload def __init__(self, start: Any, stop: Any, step: Any = ...) -> None: ... - __hash__: None # type: ignore - def indices(self, len: int) -> Tuple[int, int, int]: ... + __hash__: ClassVar[None] # type: ignore[assignment] + def indices(self, len: int) -> tuple[int, int, int]: ... class tuple(Sequence[_T_co], Generic[_T_co]): - def __new__(cls: Type[_T], iterable: Iterable[_T_co] = ...) -> _T: ... + def __new__(cls: type[Self], iterable: Iterable[_T_co] = ...) -> Self: ... def __len__(self) -> int: ... def __contains__(self, x: object) -> bool: ... @overload def __getitem__(self, x: int) -> _T_co: ... @overload - def __getitem__(self, x: slice) -> Tuple[_T_co, ...]: ... + def __getitem__(self, x: slice) -> tuple[_T_co, ...]: ... def __iter__(self) -> Iterator[_T_co]: ... - def __lt__(self, x: Tuple[_T_co, ...]) -> bool: ... - def __le__(self, x: Tuple[_T_co, ...]) -> bool: ... - def __gt__(self, x: Tuple[_T_co, ...]) -> bool: ... - def __ge__(self, x: Tuple[_T_co, ...]) -> bool: ... + def __lt__(self, x: tuple[_T_co, ...]) -> bool: ... + def __le__(self, x: tuple[_T_co, ...]) -> bool: ... + def __gt__(self, x: tuple[_T_co, ...]) -> bool: ... + def __ge__(self, x: tuple[_T_co, ...]) -> bool: ... @overload - def __add__(self, x: Tuple[_T_co, ...]) -> Tuple[_T_co, ...]: ... + def __add__(self, x: tuple[_T_co, ...]) -> tuple[_T_co, ...]: ... @overload - def __add__(self, x: Tuple[Any, ...]) -> Tuple[Any, ...]: ... - def __mul__(self, n: int) -> Tuple[_T_co, ...]: ... - def __rmul__(self, n: int) -> Tuple[_T_co, ...]: ... + def __add__(self, x: tuple[Any, ...]) -> tuple[Any, ...]: ... + def __mul__(self, n: int) -> tuple[_T_co, ...]: ... + def __rmul__(self, n: int) -> tuple[_T_co, ...]: ... def count(self, __value: Any) -> int: ... def index(self, __value: Any) -> int: ... @@ -638,30 +622,29 @@ class list(MutableSequence[_T], Generic[_T]): def sort(self, cmp: Callable[[_T, _T], Any] = ..., key: Callable[[_T], Any] = ..., reverse: bool = ...) -> None: ... def __len__(self) -> int: ... def __iter__(self) -> Iterator[_T]: ... - def __str__(self) -> str: ... - __hash__: None # type: ignore + __hash__: ClassVar[None] # type: ignore[assignment] @overload def __getitem__(self, i: int) -> _T: ... @overload - def __getitem__(self, s: slice) -> List[_T]: ... + def __getitem__(self, s: slice) -> list[_T]: ... @overload def __setitem__(self, i: int, o: _T) -> None: ... @overload def __setitem__(self, s: slice, o: Iterable[_T]) -> None: ... def __delitem__(self, i: int | slice) -> None: ... - def __getslice__(self, start: int, stop: int) -> List[_T]: ... + def __getslice__(self, start: int, stop: int) -> list[_T]: ... def __setslice__(self, start: int, stop: int, o: Sequence[_T]) -> None: ... def __delslice__(self, start: int, stop: int) -> None: ... - def __add__(self, x: List[_T]) -> List[_T]: ... - def __iadd__(self: _S, x: Iterable[_T]) -> _S: ... - def __mul__(self, n: int) -> List[_T]: ... - def __rmul__(self, n: int) -> List[_T]: ... + def __add__(self, x: list[_T]) -> list[_T]: ... + def __iadd__(self: Self, x: Iterable[_T]) -> Self: ... + def __mul__(self, n: int) -> list[_T]: ... + def __rmul__(self, n: int) -> list[_T]: ... def __contains__(self, o: object) -> bool: ... def __reversed__(self) -> Iterator[_T]: ... - def __gt__(self, x: List[_T]) -> bool: ... - def __ge__(self, x: List[_T]) -> bool: ... - def __lt__(self, x: List[_T]) -> bool: ... - def __le__(self, x: List[_T]) -> bool: ... + def __gt__(self, x: list[_T]) -> bool: ... + def __ge__(self, x: list[_T]) -> bool: ... + def __lt__(self, x: list[_T]) -> bool: ... + def __le__(self, x: list[_T]) -> bool: ... class dict(MutableMapping[_KT, _VT], Generic[_KT, _VT]): # NOTE: Keyword arguments are special. If they are used, _KT must include @@ -671,109 +654,106 @@ class dict(MutableMapping[_KT, _VT], Generic[_KT, _VT]): @overload def __init__(self, map: SupportsKeysAndGetItem[_KT, _VT], **kwargs: _VT) -> None: ... @overload - def __init__(self, iterable: Iterable[Tuple[_KT, _VT]], **kwargs: _VT) -> None: ... - def __new__(cls: Type[_T1], *args: Any, **kwargs: Any) -> _T1: ... + def __init__(self, iterable: Iterable[tuple[_KT, _VT]], **kwargs: _VT) -> None: ... + def __new__(cls: type[Self], *args: Any, **kwargs: Any) -> Self: ... def has_key(self, k: _KT) -> bool: ... def clear(self) -> None: ... - def copy(self) -> Dict[_KT, _VT]: ... - def popitem(self) -> Tuple[_KT, _VT]: ... + def copy(self) -> dict[_KT, _VT]: ... + def popitem(self) -> tuple[_KT, _VT]: ... def setdefault(self, __key: _KT, __default: _VT = ...) -> _VT: ... @overload def update(self, __m: Mapping[_KT, _VT], **kwargs: _VT) -> None: ... @overload - def update(self, __m: Iterable[Tuple[_KT, _VT]], **kwargs: _VT) -> None: ... + def update(self, __m: Iterable[tuple[_KT, _VT]], **kwargs: _VT) -> None: ... @overload def update(self, **kwargs: _VT) -> None: ... def iterkeys(self) -> Iterator[_KT]: ... def itervalues(self) -> Iterator[_VT]: ... - def iteritems(self) -> Iterator[Tuple[_KT, _VT]]: ... + def iteritems(self) -> Iterator[tuple[_KT, _VT]]: ... def viewkeys(self) -> KeysView[_KT]: ... def viewvalues(self) -> ValuesView[_VT]: ... def viewitems(self) -> ItemsView[_KT, _VT]: ... @classmethod @overload - def fromkeys(cls, __iterable: Iterable[_T]) -> Dict[_T, Any]: ... + def fromkeys(cls, __iterable: Iterable[_T]) -> dict[_T, Any]: ... @classmethod @overload - def fromkeys(cls, __iterable: Iterable[_T], __value: _S) -> Dict[_T, _S]: ... + def fromkeys(cls, __iterable: Iterable[_T], __value: _S) -> dict[_T, _S]: ... def __len__(self) -> int: ... def __getitem__(self, k: _KT) -> _VT: ... def __setitem__(self, k: _KT, v: _VT) -> None: ... def __delitem__(self, v: _KT) -> None: ... def __iter__(self) -> Iterator[_KT]: ... - def __str__(self) -> str: ... - __hash__: None # type: ignore + __hash__: ClassVar[None] # type: ignore[assignment] class set(MutableSet[_T], Generic[_T]): def __init__(self, iterable: Iterable[_T] = ...) -> None: ... def add(self, element: _T) -> None: ... def clear(self) -> None: ... - def copy(self) -> Set[_T]: ... - def difference(self, *s: Iterable[Any]) -> Set[_T]: ... + def copy(self) -> set[_T]: ... + def difference(self, *s: Iterable[Any]) -> set[_T]: ... def difference_update(self, *s: Iterable[Any]) -> None: ... def discard(self, element: _T) -> None: ... - def intersection(self, *s: Iterable[Any]) -> Set[_T]: ... + def intersection(self, *s: Iterable[Any]) -> set[_T]: ... def intersection_update(self, *s: Iterable[Any]) -> None: ... def isdisjoint(self, s: Iterable[Any]) -> bool: ... def issubset(self, s: Iterable[Any]) -> bool: ... def issuperset(self, s: Iterable[Any]) -> bool: ... def pop(self) -> _T: ... def remove(self, element: _T) -> None: ... - def symmetric_difference(self, s: Iterable[_T]) -> Set[_T]: ... + def symmetric_difference(self, s: Iterable[_T]) -> set[_T]: ... def symmetric_difference_update(self, s: Iterable[_T]) -> None: ... - def union(self, *s: Iterable[_T]) -> Set[_T]: ... + def union(self, *s: Iterable[_T]) -> set[_T]: ... def update(self, *s: Iterable[_T]) -> None: ... def __len__(self) -> int: ... def __contains__(self, o: object) -> bool: ... def __iter__(self) -> Iterator[_T]: ... - def __str__(self) -> str: ... - def __and__(self, s: AbstractSet[object]) -> Set[_T]: ... - def __iand__(self, s: AbstractSet[object]) -> Set[_T]: ... - def __or__(self, s: AbstractSet[_S]) -> Set[_T | _S]: ... - def __ior__(self, s: AbstractSet[_S]) -> Set[_T | _S]: ... + def __and__(self, s: AbstractSet[object]) -> set[_T]: ... + def __iand__(self: Self, s: AbstractSet[object]) -> Self: ... + def __or__(self, s: AbstractSet[_S]) -> set[_T | _S]: ... + def __ior__(self: Self, s: AbstractSet[_T]) -> Self: ... @overload - def __sub__(self: Set[str], s: AbstractSet[Text | None]) -> Set[_T]: ... + def __sub__(self: set[str], s: AbstractSet[Text | None]) -> set[_T]: ... @overload - def __sub__(self, s: AbstractSet[_T | None]) -> Set[_T]: ... + def __sub__(self, s: AbstractSet[_T | None]) -> set[_T]: ... @overload # type: ignore - def __isub__(self: Set[str], s: AbstractSet[Text | None]) -> Set[_T]: ... + def __isub__(self: set[str], s: AbstractSet[Text | None]) -> set[_T]: ... @overload - def __isub__(self, s: AbstractSet[_T | None]) -> Set[_T]: ... - def __xor__(self, s: AbstractSet[_S]) -> Set[_T | _S]: ... - def __ixor__(self, s: AbstractSet[_S]) -> Set[_T | _S]: ... + def __isub__(self, s: AbstractSet[_T | None]) -> set[_T]: ... + def __xor__(self, s: AbstractSet[_S]) -> set[_T | _S]: ... + def __ixor__(self: Self, s: AbstractSet[_T]) -> Self: ... def __le__(self, s: AbstractSet[object]) -> bool: ... def __lt__(self, s: AbstractSet[object]) -> bool: ... def __ge__(self, s: AbstractSet[object]) -> bool: ... def __gt__(self, s: AbstractSet[object]) -> bool: ... - __hash__: None # type: ignore + __hash__: ClassVar[None] # type: ignore[assignment] class frozenset(AbstractSet[_T_co], Generic[_T_co]): def __init__(self, iterable: Iterable[_T_co] = ...) -> None: ... - def copy(self) -> FrozenSet[_T_co]: ... - def difference(self, *s: Iterable[object]) -> FrozenSet[_T_co]: ... - def intersection(self, *s: Iterable[object]) -> FrozenSet[_T_co]: ... + def copy(self) -> frozenset[_T_co]: ... + def difference(self, *s: Iterable[object]) -> frozenset[_T_co]: ... + def intersection(self, *s: Iterable[object]) -> frozenset[_T_co]: ... def isdisjoint(self, s: Iterable[_T_co]) -> bool: ... def issubset(self, s: Iterable[object]) -> bool: ... def issuperset(self, s: Iterable[object]) -> bool: ... - def symmetric_difference(self, s: Iterable[_T_co]) -> FrozenSet[_T_co]: ... - def union(self, *s: Iterable[_T_co]) -> FrozenSet[_T_co]: ... + def symmetric_difference(self, s: Iterable[_T_co]) -> frozenset[_T_co]: ... + def union(self, *s: Iterable[_T_co]) -> frozenset[_T_co]: ... def __len__(self) -> int: ... def __contains__(self, o: object) -> bool: ... def __iter__(self) -> Iterator[_T_co]: ... - def __str__(self) -> str: ... - def __and__(self, s: AbstractSet[_T_co]) -> FrozenSet[_T_co]: ... - def __or__(self, s: AbstractSet[_S]) -> FrozenSet[_T_co | _S]: ... - def __sub__(self, s: AbstractSet[_T_co]) -> FrozenSet[_T_co]: ... - def __xor__(self, s: AbstractSet[_S]) -> FrozenSet[_T_co | _S]: ... + def __and__(self, s: AbstractSet[_T_co]) -> frozenset[_T_co]: ... + def __or__(self, s: AbstractSet[_S]) -> frozenset[_T_co | _S]: ... + def __sub__(self, s: AbstractSet[_T_co]) -> frozenset[_T_co]: ... + def __xor__(self, s: AbstractSet[_S]) -> frozenset[_T_co | _S]: ... def __le__(self, s: AbstractSet[object]) -> bool: ... def __lt__(self, s: AbstractSet[object]) -> bool: ... def __ge__(self, s: AbstractSet[object]) -> bool: ... def __gt__(self, s: AbstractSet[object]) -> bool: ... -class enumerate(Iterator[Tuple[int, _T]], Generic[_T]): +class enumerate(Iterator[tuple[int, _T]], Generic[_T]): def __init__(self, iterable: Iterable[_T], start: int = ...) -> None: ... - def __iter__(self) -> Iterator[Tuple[int, _T]]: ... - def next(self) -> Tuple[int, _T]: ... + def __iter__(self: Self) -> Self: ... + def next(self) -> tuple[int, _T]: ... class xrange(Sized, Iterable[int], Reversible[int]): @overload @@ -805,10 +785,10 @@ class property(object): long = int -class _NotImplementedType(Any): # type: ignore +class _NotImplementedType(Any): # type: ignore[misc] # A little weird, but typing the __call__ as NotImplemented makes the error message # for NotImplemented() much better - __call__: NotImplemented # type: ignore + __call__: NotImplemented # type: ignore[valid-type] NotImplemented: _NotImplementedType @@ -823,29 +803,29 @@ def cmp(__x: Any, __y: Any) -> int: ... _N1 = TypeVar("_N1", bool, int, float, complex) -def coerce(__x: _N1, __y: _N1) -> Tuple[_N1, _N1]: ... +def coerce(__x: _N1, __y: _N1) -> tuple[_N1, _N1]: ... def compile(source: Text | mod, filename: Text, mode: Text, flags: int = ..., dont_inherit: int = ...) -> Any: ... def delattr(__obj: Any, __name: Text) -> None: ... -def dir(__o: object = ...) -> List[str]: ... +def dir(__o: object = ...) -> list[str]: ... _N2 = TypeVar("_N2", int, float) -def divmod(__x: _N2, __y: _N2) -> Tuple[_N2, _N2]: ... +def divmod(__x: _N2, __y: _N2) -> tuple[_N2, _N2]: ... def eval( - __source: Text | bytes | CodeType, __globals: Dict[str, Any] | None = ..., __locals: Mapping[str, Any] | None = ... + __source: Text | bytes | CodeType, __globals: dict[str, Any] | None = ..., __locals: Mapping[str, Any] | None = ... ) -> Any: ... -def execfile(__filename: str, __globals: Dict[str, Any] | None = ..., __locals: Dict[str, Any] | None = ...) -> None: ... +def execfile(__filename: str, __globals: dict[str, Any] | None = ..., __locals: dict[str, Any] | None = ...) -> None: ... def exit(code: object = ...) -> NoReturn: ... @overload def filter(__function: Callable[[AnyStr], Any], __iterable: AnyStr) -> AnyStr: ... # type: ignore @overload -def filter(__function: None, __iterable: Tuple[_T | None, ...]) -> Tuple[_T, ...]: ... # type: ignore +def filter(__function: None, __iterable: tuple[_T | None, ...]) -> tuple[_T, ...]: ... # type: ignore @overload -def filter(__function: Callable[[_T], Any], __iterable: Tuple[_T, ...]) -> Tuple[_T, ...]: ... # type: ignore +def filter(__function: Callable[[_T], Any], __iterable: tuple[_T, ...]) -> tuple[_T, ...]: ... # type: ignore @overload -def filter(__function: None, __iterable: Iterable[_T | None]) -> List[_T]: ... +def filter(__function: None, __iterable: Iterable[_T | None]) -> list[_T]: ... @overload -def filter(__function: Callable[[_T], Any], __iterable: Iterable[_T]) -> List[_T]: ... +def filter(__function: Callable[[_T], Any], __iterable: Iterable[_T]) -> list[_T]: ... def format(__value: object, __format_spec: str = ...) -> str: ... # TODO unicode @overload def getattr(__o: Any, name: Text) -> Any: ... @@ -863,7 +843,7 @@ def getattr(__o: object, name: str, __default: list[Any]) -> Any | list[Any]: .. def getattr(__o: object, name: str, __default: dict[Any, Any]) -> Any | dict[Any, Any]: ... @overload def getattr(__o: Any, name: Text, __default: _T) -> Any | _T: ... -def globals() -> Dict[str, Any]: ... +def globals() -> dict[str, Any]: ... def hasattr(__obj: Any, __name: Text) -> bool: ... def hash(__obj: object) -> int: ... def hex(__number: int | _SupportsIndex) -> str: ... @@ -876,20 +856,20 @@ def iter(__iterable: Iterable[_T]) -> Iterator[_T]: ... def iter(__function: Callable[[], _T | None], __sentinel: None) -> Iterator[_T]: ... @overload def iter(__function: Callable[[], _T], __sentinel: Any) -> Iterator[_T]: ... -def isinstance(__obj: object, __class_or_tuple: type | Tuple[type | Tuple[Any, ...], ...]) -> bool: ... -def issubclass(__cls: type, __class_or_tuple: type | Tuple[type | Tuple[Any, ...], ...]) -> bool: ... +def isinstance(__obj: object, __class_or_tuple: type | tuple[type | tuple[Any, ...], ...]) -> bool: ... +def issubclass(__cls: type, __class_or_tuple: type | tuple[type | tuple[Any, ...], ...]) -> bool: ... def len(__obj: Sized) -> int: ... -def locals() -> Dict[str, Any]: ... +def locals() -> dict[str, Any]: ... @overload -def map(__func: None, __iter1: Iterable[_T1]) -> List[_T1]: ... +def map(__func: None, __iter1: Iterable[_T1]) -> list[_T1]: ... @overload -def map(__func: None, __iter1: Iterable[_T1], __iter2: Iterable[_T2]) -> List[Tuple[_T1, _T2]]: ... +def map(__func: None, __iter1: Iterable[_T1], __iter2: Iterable[_T2]) -> list[tuple[_T1, _T2]]: ... @overload -def map(__func: None, __iter1: Iterable[_T1], __iter2: Iterable[_T2], __iter3: Iterable[_T3]) -> List[Tuple[_T1, _T2, _T3]]: ... +def map(__func: None, __iter1: Iterable[_T1], __iter2: Iterable[_T2], __iter3: Iterable[_T3]) -> list[tuple[_T1, _T2, _T3]]: ... @overload def map( __func: None, __iter1: Iterable[_T1], __iter2: Iterable[_T2], __iter3: Iterable[_T3], __iter4: Iterable[_T4] -) -> List[Tuple[_T1, _T2, _T3, _T4]]: ... +) -> list[tuple[_T1, _T2, _T3, _T4]]: ... @overload def map( __func: None, @@ -898,7 +878,7 @@ def map( __iter3: Iterable[_T3], __iter4: Iterable[_T4], __iter5: Iterable[_T5], -) -> List[Tuple[_T1, _T2, _T3, _T4, _T5]]: ... +) -> list[tuple[_T1, _T2, _T3, _T4, _T5]]: ... @overload def map( __func: None, @@ -909,15 +889,15 @@ def map( __iter5: Iterable[Any], __iter6: Iterable[Any], *iterables: Iterable[Any], -) -> List[Tuple[Any, ...]]: ... +) -> list[tuple[Any, ...]]: ... @overload -def map(__func: Callable[[_T1], _S], __iter1: Iterable[_T1]) -> List[_S]: ... +def map(__func: Callable[[_T1], _S], __iter1: Iterable[_T1]) -> list[_S]: ... @overload -def map(__func: Callable[[_T1, _T2], _S], __iter1: Iterable[_T1], __iter2: Iterable[_T2]) -> List[_S]: ... +def map(__func: Callable[[_T1, _T2], _S], __iter1: Iterable[_T1], __iter2: Iterable[_T2]) -> list[_S]: ... @overload def map( __func: Callable[[_T1, _T2, _T3], _S], __iter1: Iterable[_T1], __iter2: Iterable[_T2], __iter3: Iterable[_T3] -) -> List[_S]: ... +) -> list[_S]: ... @overload def map( __func: Callable[[_T1, _T2, _T3, _T4], _S], @@ -925,7 +905,7 @@ def map( __iter2: Iterable[_T2], __iter3: Iterable[_T3], __iter4: Iterable[_T4], -) -> List[_S]: ... +) -> list[_S]: ... @overload def map( __func: Callable[[_T1, _T2, _T3, _T4, _T5], _S], @@ -934,7 +914,7 @@ def map( __iter3: Iterable[_T3], __iter4: Iterable[_T4], __iter5: Iterable[_T5], -) -> List[_S]: ... +) -> list[_S]: ... @overload def map( __func: Callable[..., _S], @@ -945,7 +925,7 @@ def map( __iter5: Iterable[Any], __iter6: Iterable[Any], *iterables: Iterable[Any], -) -> List[_S]: ... +) -> list[_S]: ... @overload def max(__arg1: _T, __arg2: _T, *_args: _T, key: Callable[[_T], Any] = ...) -> _T: ... @overload @@ -985,7 +965,7 @@ def pow(__base: _SupportsPow2[_E, _T_co], __exp: _E) -> _T_co: ... @overload def pow(__base: _SupportsPow3[_E, _M, _T_co], __exp: _E, __mod: _M) -> _T_co: ... def quit(code: object = ...) -> NoReturn: ... -def range(__x: int, __y: int = ..., __step: int = ...) -> List[int]: ... # noqa: F811 +def range(__x: int, __y: int = ..., __step: int = ...) -> list[int]: ... def raw_input(__prompt: Any = ...) -> str: ... @overload def reduce(__function: Callable[[_T, _S], _T], __iterable: Iterable[_S], __initializer: _T) -> _T: ... @@ -1008,27 +988,27 @@ def round(number: SupportsFloat, ndigits: int) -> float: ... def setattr(__obj: Any, __name: Text, __value: Any) -> None: ... def sorted( __iterable: Iterable[_T], *, cmp: Callable[[_T, _T], int] = ..., key: Callable[[_T], Any] | None = ..., reverse: bool = ... -) -> List[_T]: ... +) -> list[_T]: ... @overload def sum(__iterable: Iterable[_T]) -> _T | int: ... @overload def sum(__iterable: Iterable[_T], __start: _S) -> _T | _S: ... def unichr(__i: int) -> unicode: ... -def vars(__object: Any = ...) -> Dict[str, Any]: ... +def vars(__object: Any = ...) -> dict[str, Any]: ... @overload -def zip(__iter1: Iterable[_T1]) -> List[Tuple[_T1]]: ... +def zip(__iter1: Iterable[_T1]) -> list[tuple[_T1]]: ... @overload -def zip(__iter1: Iterable[_T1], __iter2: Iterable[_T2]) -> List[Tuple[_T1, _T2]]: ... +def zip(__iter1: Iterable[_T1], __iter2: Iterable[_T2]) -> list[tuple[_T1, _T2]]: ... @overload -def zip(__iter1: Iterable[_T1], __iter2: Iterable[_T2], __iter3: Iterable[_T3]) -> List[Tuple[_T1, _T2, _T3]]: ... +def zip(__iter1: Iterable[_T1], __iter2: Iterable[_T2], __iter3: Iterable[_T3]) -> list[tuple[_T1, _T2, _T3]]: ... @overload def zip( __iter1: Iterable[_T1], __iter2: Iterable[_T2], __iter3: Iterable[_T3], __iter4: Iterable[_T4] -) -> List[Tuple[_T1, _T2, _T3, _T4]]: ... +) -> list[tuple[_T1, _T2, _T3, _T4]]: ... @overload def zip( __iter1: Iterable[_T1], __iter2: Iterable[_T2], __iter3: Iterable[_T3], __iter4: Iterable[_T4], __iter5: Iterable[_T5] -) -> List[Tuple[_T1, _T2, _T3, _T4, _T5]]: ... +) -> list[tuple[_T1, _T2, _T3, _T4, _T5]]: ... @overload def zip( __iter1: Iterable[Any], @@ -1038,7 +1018,7 @@ def zip( __iter5: Iterable[Any], __iter6: Iterable[Any], *iterables: Iterable[Any], -) -> List[Tuple[Any, ...]]: ... +) -> list[tuple[Any, ...]]: ... def __import__( name: Text, globals: Mapping[str, Any] | None = ..., @@ -1066,13 +1046,11 @@ class buffer(Sized): def __mul__(self, x: int) -> str: ... class BaseException(object): - args: Tuple[Any, ...] + args: tuple[Any, ...] message: Any def __init__(self, *args: object) -> None: ... - def __str__(self) -> str: ... - def __repr__(self) -> str: ... def __getitem__(self, i: int) -> Any: ... - def __getslice__(self, start: int, stop: int) -> Tuple[Any, ...]: ... + def __getslice__(self, start: int, stop: int) -> tuple[Any, ...]: ... class GeneratorExit(BaseException): ... class KeyboardInterrupt(BaseException): ... @@ -1181,7 +1159,7 @@ class file(BinaryIO): def seek(self, offset: int, whence: int = ...) -> int: ... def tell(self) -> int: ... def readline(self, limit: int = ...) -> str: ... - def readlines(self, hint: int = ...) -> List[str]: ... + def readlines(self, hint: int = ...) -> list[str]: ... def write(self, data: str) -> int: ... def writelines(self, data: Iterable[str]) -> None: ... def truncate(self, pos: int | None = ...) -> int: ... diff --git a/mypy/typeshed/stdlib/@python2/__future__.pyi b/mypy/typeshed/stdlib/@python2/__future__.pyi index 8f5ff06ac080b..df05b0d7c2de0 100644 --- a/mypy/typeshed/stdlib/@python2/__future__.pyi +++ b/mypy/typeshed/stdlib/@python2/__future__.pyi @@ -1,5 +1,4 @@ import sys -from typing import List class _Feature: def __init__(self, optionalRelease: sys._version_info, mandatoryRelease: sys._version_info, compiler_flag: int) -> None: ... @@ -14,4 +13,4 @@ nested_scopes: _Feature print_function: _Feature unicode_literals: _Feature with_statement: _Feature -all_feature_names: List[str] # undocumented +all_feature_names: list[str] # undocumented diff --git a/mypy/typeshed/stdlib/@python2/_ast.pyi b/mypy/typeshed/stdlib/@python2/_ast.pyi index 05cbc70c41d2d..c81dc09abb57a 100644 --- a/mypy/typeshed/stdlib/@python2/_ast.pyi +++ b/mypy/typeshed/stdlib/@python2/_ast.pyi @@ -1,27 +1,25 @@ -import typing - __version__: str PyCF_ONLY_AST: int _identifier = str class AST: - _attributes: typing.Tuple[str, ...] - _fields: typing.Tuple[str, ...] + _attributes: tuple[str, ...] + _fields: tuple[str, ...] def __init__(self, *args, **kwargs) -> None: ... class mod(AST): ... class Module(mod): - body: typing.List[stmt] + body: list[stmt] class Interactive(mod): - body: typing.List[stmt] + body: list[stmt] class Expression(mod): body: expr class Suite(mod): - body: typing.List[stmt] + body: list[stmt] class stmt(AST): lineno: int @@ -30,23 +28,23 @@ class stmt(AST): class FunctionDef(stmt): name: _identifier args: arguments - body: typing.List[stmt] - decorator_list: typing.List[expr] + body: list[stmt] + decorator_list: list[expr] class ClassDef(stmt): name: _identifier - bases: typing.List[expr] - body: typing.List[stmt] - decorator_list: typing.List[expr] + bases: list[expr] + body: list[stmt] + decorator_list: list[expr] class Return(stmt): value: expr | None class Delete(stmt): - targets: typing.List[expr] + targets: list[expr] class Assign(stmt): - targets: typing.List[expr] + targets: list[expr] value: expr class AugAssign(stmt): @@ -56,29 +54,29 @@ class AugAssign(stmt): class Print(stmt): dest: expr | None - values: typing.List[expr] + values: list[expr] nl: bool class For(stmt): target: expr iter: expr - body: typing.List[stmt] - orelse: typing.List[stmt] + body: list[stmt] + orelse: list[stmt] class While(stmt): test: expr - body: typing.List[stmt] - orelse: typing.List[stmt] + body: list[stmt] + orelse: list[stmt] class If(stmt): test: expr - body: typing.List[stmt] - orelse: typing.List[stmt] + body: list[stmt] + orelse: list[stmt] class With(stmt): context_expr: expr optional_vars: expr | None - body: typing.List[stmt] + body: list[stmt] class Raise(stmt): type: expr | None @@ -86,24 +84,24 @@ class Raise(stmt): tback: expr | None class TryExcept(stmt): - body: typing.List[stmt] - handlers: typing.List[ExceptHandler] - orelse: typing.List[stmt] + body: list[stmt] + handlers: list[ExceptHandler] + orelse: list[stmt] class TryFinally(stmt): - body: typing.List[stmt] - finalbody: typing.List[stmt] + body: list[stmt] + finalbody: list[stmt] class Assert(stmt): test: expr msg: expr | None class Import(stmt): - names: typing.List[alias] + names: list[alias] class ImportFrom(stmt): module: _identifier | None - names: typing.List[alias] + names: list[alias] level: int | None class Exec(stmt): @@ -112,7 +110,7 @@ class Exec(stmt): locals: expr | None class Global(stmt): - names: typing.List[_identifier] + names: list[_identifier] class Expr(stmt): value: expr @@ -130,7 +128,7 @@ class Slice(slice): step: expr | None class ExtSlice(slice): - dims: typing.List[slice] + dims: list[slice] class Index(slice): value: expr @@ -143,7 +141,7 @@ class expr(AST): class BoolOp(expr): op: boolop - values: typing.List[expr] + values: list[expr] class BinOp(expr): left: expr @@ -164,41 +162,41 @@ class IfExp(expr): orelse: expr class Dict(expr): - keys: typing.List[expr] - values: typing.List[expr] + keys: list[expr] + values: list[expr] class Set(expr): - elts: typing.List[expr] + elts: list[expr] class ListComp(expr): elt: expr - generators: typing.List[comprehension] + generators: list[comprehension] class SetComp(expr): elt: expr - generators: typing.List[comprehension] + generators: list[comprehension] class DictComp(expr): key: expr value: expr - generators: typing.List[comprehension] + generators: list[comprehension] class GeneratorExp(expr): elt: expr - generators: typing.List[comprehension] + generators: list[comprehension] class Yield(expr): value: expr | None class Compare(expr): left: expr - ops: typing.List[cmpop] - comparators: typing.List[expr] + ops: list[cmpop] + comparators: list[expr] class Call(expr): func: expr - args: typing.List[expr] - keywords: typing.List[keyword] + args: list[expr] + keywords: list[keyword] starargs: expr | None kwargs: expr | None @@ -226,11 +224,11 @@ class Name(expr): ctx: expr_context class List(expr): - elts: typing.List[expr] + elts: list[expr] ctx: expr_context class Tuple(expr): - elts: typing.List[expr] + elts: list[expr] ctx: expr_context class expr_context(AST): ... @@ -276,22 +274,22 @@ class NotIn(cmpop): ... class comprehension(AST): target: expr iter: expr - ifs: typing.List[expr] + ifs: list[expr] class excepthandler(AST): ... class ExceptHandler(excepthandler): type: expr | None name: expr | None - body: typing.List[stmt] + body: list[stmt] lineno: int col_offset: int class arguments(AST): - args: typing.List[expr] + args: list[expr] vararg: _identifier | None kwarg: _identifier | None - defaults: typing.List[expr] + defaults: list[expr] class keyword(AST): arg: _identifier diff --git a/mypy/typeshed/stdlib/@python2/_codecs.pyi b/mypy/typeshed/stdlib/@python2/_codecs.pyi index 83601f6621bbf..1028cfec1aefc 100644 --- a/mypy/typeshed/stdlib/@python2/_codecs.pyi +++ b/mypy/typeshed/stdlib/@python2/_codecs.pyi @@ -1,19 +1,19 @@ import codecs import sys -from typing import Any, Callable, Dict, Text, Tuple, Union +from typing import Any, Callable, Text # For convenience: -_Handler = Callable[[Exception], Tuple[Text, int]] -_String = Union[bytes, str] -_Errors = Union[str, Text, None] -_Decodable = Union[bytes, Text] -_Encodable = Union[bytes, Text] +_Handler = Callable[[Exception], tuple[Text, int]] +_String = bytes | str +_Errors = str | Text | None +_Decodable = bytes | Text +_Encodable = bytes | Text # This type is not exposed; it is defined in unicodeobject.c class _EncodingMap(object): def size(self) -> int: ... -_MapT = Union[Dict[int, int], _EncodingMap] +_MapT = dict[int, int] | _EncodingMap def register(__search_function: Callable[[str], Any]) -> None: ... def register_error(__errors: str | Text, __handler: _Handler) -> None: ... @@ -22,45 +22,45 @@ def lookup_error(__name: str | Text) -> _Handler: ... def decode(obj: Any, encoding: str | Text = ..., errors: _Errors = ...) -> Any: ... def encode(obj: Any, encoding: str | Text = ..., errors: _Errors = ...) -> Any: ... def charmap_build(__map: Text) -> _MapT: ... -def ascii_decode(__data: _Decodable, __errors: _Errors = ...) -> Tuple[Text, int]: ... -def ascii_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... -def charbuffer_encode(__data: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... -def charmap_decode(__data: _Decodable, __errors: _Errors = ..., __mapping: _MapT | None = ...) -> Tuple[Text, int]: ... -def charmap_encode(__str: _Encodable, __errors: _Errors = ..., __mapping: _MapT | None = ...) -> Tuple[bytes, int]: ... -def escape_decode(__data: _String, __errors: _Errors = ...) -> Tuple[str, int]: ... -def escape_encode(__data: bytes, __errors: _Errors = ...) -> Tuple[bytes, int]: ... -def latin_1_decode(__data: _Decodable, __errors: _Errors = ...) -> Tuple[Text, int]: ... -def latin_1_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... -def raw_unicode_escape_decode(__data: _String, __errors: _Errors = ...) -> Tuple[Text, int]: ... -def raw_unicode_escape_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... -def readbuffer_encode(__data: _String, __errors: _Errors = ...) -> Tuple[bytes, int]: ... -def unicode_escape_decode(__data: _String, __errors: _Errors = ...) -> Tuple[Text, int]: ... -def unicode_escape_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... -def unicode_internal_decode(__obj: _String, __errors: _Errors = ...) -> Tuple[Text, int]: ... -def unicode_internal_encode(__obj: _String, __errors: _Errors = ...) -> Tuple[bytes, int]: ... -def utf_16_be_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> Tuple[Text, int]: ... -def utf_16_be_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... -def utf_16_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> Tuple[Text, int]: ... -def utf_16_encode(__str: _Encodable, __errors: _Errors = ..., __byteorder: int = ...) -> Tuple[bytes, int]: ... +def ascii_decode(__data: _Decodable, __errors: _Errors = ...) -> tuple[Text, int]: ... +def ascii_encode(__str: _Encodable, __errors: _Errors = ...) -> tuple[bytes, int]: ... +def charbuffer_encode(__data: _Encodable, __errors: _Errors = ...) -> tuple[bytes, int]: ... +def charmap_decode(__data: _Decodable, __errors: _Errors = ..., __mapping: _MapT | None = ...) -> tuple[Text, int]: ... +def charmap_encode(__str: _Encodable, __errors: _Errors = ..., __mapping: _MapT | None = ...) -> tuple[bytes, int]: ... +def escape_decode(__data: _String, __errors: _Errors = ...) -> tuple[str, int]: ... +def escape_encode(__data: bytes, __errors: _Errors = ...) -> tuple[bytes, int]: ... +def latin_1_decode(__data: _Decodable, __errors: _Errors = ...) -> tuple[Text, int]: ... +def latin_1_encode(__str: _Encodable, __errors: _Errors = ...) -> tuple[bytes, int]: ... +def raw_unicode_escape_decode(__data: _String, __errors: _Errors = ...) -> tuple[Text, int]: ... +def raw_unicode_escape_encode(__str: _Encodable, __errors: _Errors = ...) -> tuple[bytes, int]: ... +def readbuffer_encode(__data: _String, __errors: _Errors = ...) -> tuple[bytes, int]: ... +def unicode_escape_decode(__data: _String, __errors: _Errors = ...) -> tuple[Text, int]: ... +def unicode_escape_encode(__str: _Encodable, __errors: _Errors = ...) -> tuple[bytes, int]: ... +def unicode_internal_decode(__obj: _String, __errors: _Errors = ...) -> tuple[Text, int]: ... +def unicode_internal_encode(__obj: _String, __errors: _Errors = ...) -> tuple[bytes, int]: ... +def utf_16_be_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> tuple[Text, int]: ... +def utf_16_be_encode(__str: _Encodable, __errors: _Errors = ...) -> tuple[bytes, int]: ... +def utf_16_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> tuple[Text, int]: ... +def utf_16_encode(__str: _Encodable, __errors: _Errors = ..., __byteorder: int = ...) -> tuple[bytes, int]: ... def utf_16_ex_decode( __data: _Decodable, __errors: _Errors = ..., __byteorder: int = ..., __final: int = ... -) -> Tuple[Text, int, int]: ... -def utf_16_le_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> Tuple[Text, int]: ... -def utf_16_le_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... -def utf_32_be_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> Tuple[Text, int]: ... -def utf_32_be_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... -def utf_32_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> Tuple[Text, int]: ... -def utf_32_encode(__str: _Encodable, __errors: _Errors = ..., __byteorder: int = ...) -> Tuple[bytes, int]: ... +) -> tuple[Text, int, int]: ... +def utf_16_le_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> tuple[Text, int]: ... +def utf_16_le_encode(__str: _Encodable, __errors: _Errors = ...) -> tuple[bytes, int]: ... +def utf_32_be_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> tuple[Text, int]: ... +def utf_32_be_encode(__str: _Encodable, __errors: _Errors = ...) -> tuple[bytes, int]: ... +def utf_32_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> tuple[Text, int]: ... +def utf_32_encode(__str: _Encodable, __errors: _Errors = ..., __byteorder: int = ...) -> tuple[bytes, int]: ... def utf_32_ex_decode( __data: _Decodable, __errors: _Errors = ..., __byteorder: int = ..., __final: int = ... -) -> Tuple[Text, int, int]: ... -def utf_32_le_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> Tuple[Text, int]: ... -def utf_32_le_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... -def utf_7_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> Tuple[Text, int]: ... -def utf_7_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... -def utf_8_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> Tuple[Text, int]: ... -def utf_8_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... +) -> tuple[Text, int, int]: ... +def utf_32_le_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> tuple[Text, int]: ... +def utf_32_le_encode(__str: _Encodable, __errors: _Errors = ...) -> tuple[bytes, int]: ... +def utf_7_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> tuple[Text, int]: ... +def utf_7_encode(__str: _Encodable, __errors: _Errors = ...) -> tuple[bytes, int]: ... +def utf_8_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> tuple[Text, int]: ... +def utf_8_encode(__str: _Encodable, __errors: _Errors = ...) -> tuple[bytes, int]: ... if sys.platform == "win32": - def mbcs_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> Tuple[Text, int]: ... - def mbcs_encode(__str: _Encodable, __errors: _Errors = ...) -> Tuple[bytes, int]: ... + def mbcs_decode(__data: _Decodable, __errors: _Errors = ..., __final: int = ...) -> tuple[Text, int]: ... + def mbcs_encode(__str: _Encodable, __errors: _Errors = ...) -> tuple[bytes, int]: ... diff --git a/mypy/typeshed/stdlib/@python2/_collections.pyi b/mypy/typeshed/stdlib/@python2/_collections.pyi index 22ada07d0f245..6f0ee3f8740b8 100644 --- a/mypy/typeshed/stdlib/@python2/_collections.pyi +++ b/mypy/typeshed/stdlib/@python2/_collections.pyi @@ -1,16 +1,16 @@ -from typing import Any, Callable, Dict, Generic, Iterator, TypeVar +from _typeshed import Self +from typing import Any, Callable, Generic, Iterator, TypeVar _K = TypeVar("_K") _V = TypeVar("_V") _T = TypeVar("_T") -_T2 = TypeVar("_T2") -class defaultdict(Dict[_K, _V]): +class defaultdict(dict[_K, _V]): default_factory: None def __init__(self, __default_factory: Callable[[], _V] = ..., init: Any = ...) -> None: ... def __missing__(self, key: _K) -> _V: ... - def __copy__(self: _T) -> _T: ... - def copy(self: _T) -> _T: ... + def __copy__(self: Self) -> Self: ... + def copy(self: Self) -> Self: ... class deque(Generic[_T]): maxlen: int | None @@ -29,7 +29,7 @@ class deque(Generic[_T]): def __contains__(self, o: Any) -> bool: ... def __copy__(self) -> deque[_T]: ... def __getitem__(self, i: int) -> _T: ... - def __iadd__(self, other: deque[_T2]) -> deque[_T | _T2]: ... + def __iadd__(self: Self, other: deque[_T]) -> Self: ... def __iter__(self) -> Iterator[_T]: ... def __len__(self) -> int: ... def __reversed__(self) -> Iterator[_T]: ... diff --git a/mypy/typeshed/stdlib/@python2/_csv.pyi b/mypy/typeshed/stdlib/@python2/_csv.pyi index ebe44bab67d94..e01ccc19cb19f 100644 --- a/mypy/typeshed/stdlib/@python2/_csv.pyi +++ b/mypy/typeshed/stdlib/@python2/_csv.pyi @@ -1,4 +1,4 @@ -from typing import Any, Iterable, Iterator, List, Protocol, Sequence, Text, Type, Union +from typing import Any, Iterable, Iterator, Protocol, Sequence, Text, Union QUOTE_ALL: int QUOTE_MINIMAL: int @@ -18,12 +18,12 @@ class Dialect: strict: int def __init__(self) -> None: ... -_DialectLike = Union[str, Dialect, Type[Dialect]] +_DialectLike = Union[str, Dialect, type[Dialect]] -class _reader(Iterator[List[str]]): +class _reader(Iterator[list[str]]): dialect: Dialect line_num: int - def next(self) -> List[str]: ... + def next(self) -> list[str]: ... class _writer: dialect: Dialect @@ -38,5 +38,5 @@ def reader(csvfile: Iterable[Text], dialect: _DialectLike = ..., **fmtparams: An def register_dialect(name: str, dialect: Any = ..., **fmtparams: Any) -> None: ... def unregister_dialect(name: str) -> None: ... def get_dialect(name: str) -> Dialect: ... -def list_dialects() -> List[str]: ... +def list_dialects() -> list[str]: ... def field_size_limit(new_limit: int = ...) -> int: ... diff --git a/mypy/typeshed/stdlib/@python2/_curses.pyi b/mypy/typeshed/stdlib/@python2/_curses.pyi index 32c1f761ac9e3..81de0ea96e3ff 100644 --- a/mypy/typeshed/stdlib/@python2/_curses.pyi +++ b/mypy/typeshed/stdlib/@python2/_curses.pyi @@ -1,6 +1,6 @@ -from typing import IO, Any, BinaryIO, Tuple, Union, overload +from typing import IO, Any, BinaryIO, overload -_chtype = Union[str, bytes, int] +_chtype = str | bytes | int # ACS codes are only initialized after initscr is called ACS_BBSS: int @@ -263,7 +263,7 @@ def baudrate() -> int: ... def beep() -> None: ... def can_change_color() -> bool: ... def cbreak(__flag: bool = ...) -> None: ... -def color_content(__color_number: int) -> Tuple[int, int, int]: ... +def color_content(__color_number: int) -> tuple[int, int, int]: ... # Changed in Python 3.8.8 and 3.9.2 def color_pair(__color_number: int) -> int: ... @@ -278,8 +278,8 @@ def erasechar() -> bytes: ... def filter() -> None: ... def flash() -> None: ... def flushinp() -> None: ... -def getmouse() -> Tuple[int, int, int, int, int]: ... -def getsyx() -> Tuple[int, int]: ... +def getmouse() -> tuple[int, int, int, int, int]: ... +def getsyx() -> tuple[int, int]: ... def getwin(__file: BinaryIO) -> _CursesWindow: ... def halfdelay(__tenths: int) -> None: ... def has_colors() -> bool: ... @@ -297,7 +297,7 @@ def killchar() -> bytes: ... def longname() -> bytes: ... def meta(__yes: bool) -> None: ... def mouseinterval(__interval: int) -> None: ... -def mousemask(__newmask: int) -> Tuple[int, int]: ... +def mousemask(__newmask: int) -> tuple[int, int]: ... def napms(__ms: int) -> int: ... def newpad(__nlines: int, __ncols: int) -> _CursesWindow: ... def newwin(__nlines: int, __ncols: int, __begin_y: int = ..., __begin_x: int = ...) -> _CursesWindow: ... @@ -307,7 +307,7 @@ def noecho() -> None: ... def nonl() -> None: ... def noqiflush() -> None: ... def noraw() -> None: ... -def pair_content(__pair_number: int) -> Tuple[int, int]: ... +def pair_content(__pair_number: int) -> tuple[int, int]: ... def pair_number(__attr: int) -> int: ... def putp(__string: bytes) -> None: ... def qiflush(__flag: bool = ...) -> None: ... @@ -405,8 +405,8 @@ class _CursesWindow: def echochar(self, __ch: _chtype, __attr: int = ...) -> None: ... def enclose(self, __y: int, __x: int) -> bool: ... def erase(self) -> None: ... - def getbegyx(self) -> Tuple[int, int]: ... - def getbkgd(self) -> Tuple[int, int]: ... + def getbegyx(self) -> tuple[int, int]: ... + def getbkgd(self) -> tuple[int, int]: ... @overload def getch(self) -> int: ... @overload @@ -415,8 +415,8 @@ class _CursesWindow: def getkey(self) -> str: ... @overload def getkey(self, y: int, x: int) -> str: ... - def getmaxyx(self) -> Tuple[int, int]: ... - def getparyx(self) -> Tuple[int, int]: ... + def getmaxyx(self) -> tuple[int, int]: ... + def getparyx(self) -> tuple[int, int]: ... @overload def getstr(self) -> _chtype: ... @overload @@ -425,7 +425,7 @@ class _CursesWindow: def getstr(self, y: int, x: int) -> _chtype: ... @overload def getstr(self, y: int, x: int, n: int) -> _chtype: ... - def getyx(self) -> Tuple[int, int]: ... + def getyx(self) -> tuple[int, int]: ... @overload def hline(self, ch: _chtype, n: int) -> None: ... @overload diff --git a/mypy/typeshed/stdlib/@python2/_dummy_threading.pyi b/mypy/typeshed/stdlib/@python2/_dummy_threading.pyi index e45a1b5c4a894..e7b0a9e4b363a 100644 --- a/mypy/typeshed/stdlib/@python2/_dummy_threading.pyi +++ b/mypy/typeshed/stdlib/@python2/_dummy_threading.pyi @@ -1,19 +1,36 @@ from types import FrameType, TracebackType -from typing import Any, Callable, Iterable, List, Mapping, Optional, Text, Type, TypeVar +from typing import Any, Callable, Iterable, Mapping, Text # TODO recursive type -_TF = Callable[[FrameType, str, Any], Optional[Callable[..., Any]]] +_TF = Callable[[FrameType, str, Any], Callable[..., Any] | None] _PF = Callable[[FrameType, str, Any], None] -_T = TypeVar("_T") -__all__: List[str] +__all__ = [ + "activeCount", + "active_count", + "Condition", + "currentThread", + "current_thread", + "enumerate", + "Event", + "Lock", + "RLock", + "Semaphore", + "BoundedSemaphore", + "Thread", + "Timer", + "setprofile", + "settrace", + "local", + "stack_size", +] def active_count() -> int: ... def activeCount() -> int: ... def current_thread() -> Thread: ... def currentThread() -> Thread: ... -def enumerate() -> List[Thread]: ... +def enumerate() -> list[Thread]: ... def settrace(func: _TF) -> None: ... def setprofile(func: _PF | None) -> None: ... def stack_size(size: int = ...) -> int: ... @@ -53,7 +70,7 @@ class Lock: def __init__(self) -> None: ... def __enter__(self) -> bool: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> bool | None: ... def acquire(self, blocking: bool = ...) -> bool: ... def release(self) -> None: ... @@ -63,7 +80,7 @@ class _RLock: def __init__(self) -> None: ... def __enter__(self) -> bool: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> bool | None: ... def acquire(self, blocking: bool = ...) -> bool: ... def release(self) -> None: ... @@ -74,7 +91,7 @@ class Condition: def __init__(self, lock: Lock | _RLock | None = ...) -> None: ... def __enter__(self) -> bool: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> bool | None: ... def acquire(self, blocking: bool = ...) -> bool: ... def release(self) -> None: ... @@ -86,7 +103,7 @@ class Condition: class Semaphore: def __init__(self, value: int = ...) -> None: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> bool | None: ... def acquire(self, blocking: bool = ...) -> bool: ... def __enter__(self, blocking: bool = ...) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/_functools.pyi b/mypy/typeshed/stdlib/@python2/_functools.pyi index e68398238f9b0..d695e76994c91 100644 --- a/mypy/typeshed/stdlib/@python2/_functools.pyi +++ b/mypy/typeshed/stdlib/@python2/_functools.pyi @@ -1,4 +1,4 @@ -from typing import Any, Callable, Dict, Iterable, Tuple, TypeVar, overload +from typing import Any, Callable, Iterable, TypeVar, overload _T = TypeVar("_T") _S = TypeVar("_S") @@ -10,7 +10,7 @@ def reduce(function: Callable[[_T, _S], _T], sequence: Iterable[_S], initial: _T class partial(object): func: Callable[..., Any] - args: Tuple[Any, ...] - keywords: Dict[str, Any] + args: tuple[Any, ...] + keywords: dict[str, Any] def __init__(self, func: Callable[..., Any], *args: Any, **kwargs: Any) -> None: ... def __call__(self, *args: Any, **kwargs: Any) -> Any: ... diff --git a/mypy/typeshed/stdlib/@python2/_heapq.pyi b/mypy/typeshed/stdlib/@python2/_heapq.pyi index 08a8add08e9a1..a2a38dc9c3edb 100644 --- a/mypy/typeshed/stdlib/@python2/_heapq.pyi +++ b/mypy/typeshed/stdlib/@python2/_heapq.pyi @@ -1,11 +1,11 @@ -from typing import Any, Callable, Iterable, List, TypeVar +from typing import Any, Callable, Iterable, TypeVar _T = TypeVar("_T") -def heapify(__heap: List[Any]) -> None: ... -def heappop(__heap: List[_T]) -> _T: ... -def heappush(__heap: List[_T], __item: _T) -> None: ... -def heappushpop(__heap: List[_T], __item: _T) -> _T: ... -def heapreplace(__heap: List[_T], __item: _T) -> _T: ... -def nlargest(__n: int, __iterable: Iterable[_T], __key: Callable[[_T], Any] | None = ...) -> List[_T]: ... -def nsmallest(__n: int, __iterable: Iterable[_T], __key: Callable[[_T], Any] | None = ...) -> List[_T]: ... +def heapify(__heap: list[Any]) -> None: ... +def heappop(__heap: list[_T]) -> _T: ... +def heappush(__heap: list[_T], __item: _T) -> None: ... +def heappushpop(__heap: list[_T], __item: _T) -> _T: ... +def heapreplace(__heap: list[_T], __item: _T) -> _T: ... +def nlargest(__n: int, __iterable: Iterable[_T], __key: Callable[[_T], Any] | None = ...) -> list[_T]: ... +def nsmallest(__n: int, __iterable: Iterable[_T], __key: Callable[[_T], Any] | None = ...) -> list[_T]: ... diff --git a/mypy/typeshed/stdlib/@python2/_hotshot.pyi b/mypy/typeshed/stdlib/@python2/_hotshot.pyi index b048f6fb83d59..aa188a2b4fae1 100644 --- a/mypy/typeshed/stdlib/@python2/_hotshot.pyi +++ b/mypy/typeshed/stdlib/@python2/_hotshot.pyi @@ -1,9 +1,9 @@ -from typing import Any, Tuple +from typing import Any def coverage(a: str) -> Any: ... def logreader(a: str) -> LogReaderType: ... def profiler(a: str, *args, **kwargs) -> Any: ... -def resolution() -> Tuple[Any, ...]: ... +def resolution() -> tuple[Any, ...]: ... class LogReaderType(object): def close(self) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/_io.pyi b/mypy/typeshed/stdlib/@python2/_io.pyi index fedbbe1379409..65c59ccf77159 100644 --- a/mypy/typeshed/stdlib/@python2/_io.pyi +++ b/mypy/typeshed/stdlib/@python2/_io.pyi @@ -1,8 +1,8 @@ from _typeshed import Self from mmap import mmap -from typing import IO, Any, BinaryIO, Iterable, List, Text, TextIO, Tuple, Type, TypeVar, Union +from typing import IO, Any, BinaryIO, Iterable, Text, TextIO -_bytearray_like = Union[bytearray, mmap] +_bytearray_like = bytearray | mmap DEFAULT_BUFFER_SIZE: int @@ -11,8 +11,6 @@ class BlockingIOError(IOError): class UnsupportedOperation(ValueError, IOError): ... -_T = TypeVar("_T") - class _IOBase(BinaryIO): @property def closed(self) -> bool: ... @@ -32,13 +30,13 @@ class _IOBase(BinaryIO): def truncate(self, size: int | None = ...) -> int: ... def writable(self) -> bool: ... def __enter__(self: Self) -> Self: ... - def __exit__(self, t: Type[BaseException] | None, value: BaseException | None, traceback: Any | None) -> bool | None: ... - def __iter__(self: _T) -> _T: ... + def __exit__(self, t: type[BaseException] | None, value: BaseException | None, traceback: Any | None) -> bool | None: ... + def __iter__(self: Self) -> Self: ... # The parameter type of writelines[s]() is determined by that of write(): def writelines(self, lines: Iterable[bytes]) -> None: ... # The return type of readline[s]() and next() is determined by that of read(): - def readline(self, limit: int = ...) -> bytes: ... - def readlines(self, hint: int = ...) -> List[bytes]: ... + def readline(self, limit: int | None = ...) -> bytes: ... + def readlines(self, hint: int = ...) -> list[bytes]: ... def next(self) -> bytes: ... # These don't actually exist but we need to pretend that it does # so that this class is concrete. @@ -79,8 +77,8 @@ class BufferedWriter(_BufferedIOBase): class BytesIO(_BufferedIOBase): def __init__(self, initial_bytes: bytes = ...) -> None: ... - def __setstate__(self, state: Tuple[Any, ...]) -> None: ... - def __getstate__(self) -> Tuple[Any, ...]: ... + def __setstate__(self, state: tuple[Any, ...]) -> None: ... + def __getstate__(self) -> tuple[Any, ...]: ... # BytesIO does not contain a "name" field. This workaround is necessary # to allow BytesIO sub-classes to add this field, as it is defined # as a read-only property on IO[]. @@ -106,8 +104,8 @@ class IncrementalNewlineDecoder(object): newlines: str | unicode def __init__(self, decoder, translate, z=...) -> None: ... def decode(self, input, final) -> Any: ... - def getstate(self) -> Tuple[Any, int]: ... - def setstate(self, state: Tuple[Any, int]) -> None: ... + def getstate(self) -> tuple[Any, int]: ... + def setstate(self, state: tuple[Any, int]) -> None: ... def reset(self) -> None: ... # Note: In the actual _io.py, _TextIOBase inherits from _IOBase. @@ -140,14 +138,14 @@ class _TextIOBase(TextIO): def write(self, pbuf: unicode) -> int: ... def writelines(self, lines: Iterable[unicode]) -> None: ... def __enter__(self: Self) -> Self: ... - def __exit__(self, t: Type[BaseException] | None, value: BaseException | None, traceback: Any | None) -> bool | None: ... - def __iter__(self: _T) -> _T: ... + def __exit__(self, t: type[BaseException] | None, value: BaseException | None, traceback: Any | None) -> bool | None: ... + def __iter__(self: Self) -> Self: ... class StringIO(_TextIOBase): line_buffering: bool def __init__(self, initial_value: unicode | None = ..., newline: unicode | None = ...) -> None: ... - def __setstate__(self, state: Tuple[Any, ...]) -> None: ... - def __getstate__(self) -> Tuple[Any, ...]: ... + def __setstate__(self, state: tuple[Any, ...]) -> None: ... + def __getstate__(self) -> tuple[Any, ...]: ... # StringIO does not contain a "name" field. This workaround is necessary # to allow StringIO sub-classes to add this field, as it is defined # as a read-only property on IO[]. diff --git a/mypy/typeshed/stdlib/@python2/_json.pyi b/mypy/typeshed/stdlib/@python2/_json.pyi index a9868b3e60fda..57c70e80564e2 100644 --- a/mypy/typeshed/stdlib/@python2/_json.pyi +++ b/mypy/typeshed/stdlib/@python2/_json.pyi @@ -1,7 +1,7 @@ -from typing import Any, Tuple +from typing import Any def encode_basestring_ascii(*args, **kwargs) -> str: ... -def scanstring(a, b, *args, **kwargs) -> Tuple[Any, ...]: ... +def scanstring(a, b, *args, **kwargs) -> tuple[Any, ...]: ... class Encoder(object): ... class Scanner(object): ... diff --git a/mypy/typeshed/stdlib/@python2/_markupbase.pyi b/mypy/typeshed/stdlib/@python2/_markupbase.pyi index d8bc79f34e8cf..368d32bd5b4c0 100644 --- a/mypy/typeshed/stdlib/@python2/_markupbase.pyi +++ b/mypy/typeshed/stdlib/@python2/_markupbase.pyi @@ -1,8 +1,6 @@ -from typing import Tuple - class ParserBase: def __init__(self) -> None: ... def error(self, message: str) -> None: ... def reset(self) -> None: ... - def getpos(self) -> Tuple[int, int]: ... + def getpos(self) -> tuple[int, int]: ... def unknown_decl(self, data: str) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/_msi.pyi b/mypy/typeshed/stdlib/@python2/_msi.pyi index a1030a66160fc..b7e852f38ae9c 100644 --- a/mypy/typeshed/stdlib/@python2/_msi.pyi +++ b/mypy/typeshed/stdlib/@python2/_msi.pyi @@ -1,5 +1,4 @@ import sys -from typing import List if sys.platform == "win32": @@ -11,8 +10,8 @@ if sys.platform == "win32": def Modify(self, mode: int, record: _Record) -> None: ... def Close(self) -> None: ... # Don't exist at runtime - __new__: None # type: ignore - __init__: None # type: ignore + __new__: None # type: ignore[assignment] + __init__: None # type: ignore[assignment] # Actual typename Summary, not exposed by the implementation class _Summary: def GetProperty(self, propid: int) -> str | bytes | None: ... @@ -20,8 +19,8 @@ if sys.platform == "win32": def SetProperty(self, propid: int, value: str | bytes) -> None: ... def Persist(self) -> None: ... # Don't exist at runtime - __new__: None # type: ignore - __init__: None # type: ignore + __new__: None # type: ignore[assignment] + __init__: None # type: ignore[assignment] # Actual typename Database, not exposed by the implementation class _Database: def OpenView(self, sql: str) -> _View: ... @@ -29,8 +28,8 @@ if sys.platform == "win32": def GetSummaryInformation(self, updateCount: int) -> _Summary: ... def Close(self) -> None: ... # Don't exist at runtime - __new__: None # type: ignore - __init__: None # type: ignore + __new__: None # type: ignore[assignment] + __init__: None # type: ignore[assignment] # Actual typename Record, not exposed by the implementation class _Record: def GetFieldCount(self) -> int: ... @@ -41,9 +40,9 @@ if sys.platform == "win32": def SetInteger(self, field: int, int: int) -> None: ... def ClearData(self) -> None: ... # Don't exist at runtime - __new__: None # type: ignore - __init__: None # type: ignore + __new__: None # type: ignore[assignment] + __init__: None # type: ignore[assignment] def UuidCreate() -> str: ... - def FCICreate(cabname: str, files: List[str]) -> None: ... + def FCICreate(cabname: str, files: list[str]) -> None: ... def OpenDatabase(name: str, flags: int) -> _Database: ... def CreateRecord(count: int) -> _Record: ... diff --git a/mypy/typeshed/stdlib/@python2/_osx_support.pyi b/mypy/typeshed/stdlib/@python2/_osx_support.pyi index 1b890d8d8a0a6..27a4a019de58d 100644 --- a/mypy/typeshed/stdlib/@python2/_osx_support.pyi +++ b/mypy/typeshed/stdlib/@python2/_osx_support.pyi @@ -1,13 +1,13 @@ -from typing import Dict, Iterable, List, Sequence, Tuple, TypeVar +from typing import Iterable, Sequence, TypeVar _T = TypeVar("_T") _K = TypeVar("_K") _V = TypeVar("_V") -__all__: List[str] +__all__ = ["compiler_fixup", "customize_config_vars", "customize_compiler", "get_platform_osx"] -_UNIVERSAL_CONFIG_VARS: Tuple[str, ...] # undocumented -_COMPILER_CONFIG_VARS: Tuple[str, ...] # undocumented +_UNIVERSAL_CONFIG_VARS: tuple[str, ...] # undocumented +_COMPILER_CONFIG_VARS: tuple[str, ...] # undocumented _INITPRE: str # undocumented def _find_executable(executable: str, path: str | None = ...) -> str | None: ... # undocumented @@ -17,17 +17,17 @@ def _find_build_tool(toolname: str) -> str: ... # undocumented _SYSTEM_VERSION: str | None # undocumented def _get_system_version() -> str: ... # undocumented -def _remove_original_values(_config_vars: Dict[str, str]) -> None: ... # undocumented -def _save_modified_value(_config_vars: Dict[str, str], cv: str, newvalue: str) -> None: ... # undocumented +def _remove_original_values(_config_vars: dict[str, str]) -> None: ... # undocumented +def _save_modified_value(_config_vars: dict[str, str], cv: str, newvalue: str) -> None: ... # undocumented def _supports_universal_builds() -> bool: ... # undocumented -def _find_appropriate_compiler(_config_vars: Dict[str, str]) -> Dict[str, str]: ... # undocumented -def _remove_universal_flags(_config_vars: Dict[str, str]) -> Dict[str, str]: ... # undocumented -def _remove_unsupported_archs(_config_vars: Dict[str, str]) -> Dict[str, str]: ... # undocumented -def _override_all_archs(_config_vars: Dict[str, str]) -> Dict[str, str]: ... # undocumented -def _check_for_unavailable_sdk(_config_vars: Dict[str, str]) -> Dict[str, str]: ... # undocumented -def compiler_fixup(compiler_so: Iterable[str], cc_args: Sequence[str]) -> List[str]: ... -def customize_config_vars(_config_vars: Dict[str, str]) -> Dict[str, str]: ... -def customize_compiler(_config_vars: Dict[str, str]) -> Dict[str, str]: ... +def _find_appropriate_compiler(_config_vars: dict[str, str]) -> dict[str, str]: ... # undocumented +def _remove_universal_flags(_config_vars: dict[str, str]) -> dict[str, str]: ... # undocumented +def _remove_unsupported_archs(_config_vars: dict[str, str]) -> dict[str, str]: ... # undocumented +def _override_all_archs(_config_vars: dict[str, str]) -> dict[str, str]: ... # undocumented +def _check_for_unavailable_sdk(_config_vars: dict[str, str]) -> dict[str, str]: ... # undocumented +def compiler_fixup(compiler_so: Iterable[str], cc_args: Sequence[str]) -> list[str]: ... +def customize_config_vars(_config_vars: dict[str, str]) -> dict[str, str]: ... +def customize_compiler(_config_vars: dict[str, str]) -> dict[str, str]: ... def get_platform_osx( - _config_vars: Dict[str, str], osname: _T, release: _K, machine: _V -) -> Tuple[str | _T, str | _K, str | _V]: ... + _config_vars: dict[str, str], osname: _T, release: _K, machine: _V +) -> tuple[str | _T, str | _K, str | _V]: ... diff --git a/mypy/typeshed/stdlib/@python2/_random.pyi b/mypy/typeshed/stdlib/@python2/_random.pyi index 7c2dd61af49f4..8bd1afad48cb7 100644 --- a/mypy/typeshed/stdlib/@python2/_random.pyi +++ b/mypy/typeshed/stdlib/@python2/_random.pyi @@ -1,7 +1,5 @@ -from typing import Tuple - # Actually Tuple[(int,) * 625] -_State = Tuple[int, ...] +_State = tuple[int, ...] class Random(object): def __init__(self, seed: object = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/_socket.pyi b/mypy/typeshed/stdlib/@python2/_socket.pyi index c505384c5226e..d081494be68ff 100644 --- a/mypy/typeshed/stdlib/@python2/_socket.pyi +++ b/mypy/typeshed/stdlib/@python2/_socket.pyi @@ -1,4 +1,4 @@ -from typing import IO, Any, Tuple, overload +from typing import IO, Any, overload AF_APPLETALK: int AF_ASH: int @@ -252,29 +252,29 @@ class SocketType(object): proto: int timeout: float def __init__(self, family: int = ..., type: int = ..., proto: int = ...) -> None: ... - def accept(self) -> Tuple[SocketType, Tuple[Any, ...]]: ... - def bind(self, address: Tuple[Any, ...]) -> None: ... + def accept(self) -> tuple[SocketType, tuple[Any, ...]]: ... + def bind(self, address: tuple[Any, ...]) -> None: ... def close(self) -> None: ... - def connect(self, address: Tuple[Any, ...]) -> None: ... - def connect_ex(self, address: Tuple[Any, ...]) -> int: ... + def connect(self, address: tuple[Any, ...]) -> None: ... + def connect_ex(self, address: tuple[Any, ...]) -> int: ... def dup(self) -> SocketType: ... def fileno(self) -> int: ... - def getpeername(self) -> Tuple[Any, ...]: ... - def getsockname(self) -> Tuple[Any, ...]: ... + def getpeername(self) -> tuple[Any, ...]: ... + def getsockname(self) -> tuple[Any, ...]: ... def getsockopt(self, level: int, option: int, buffersize: int = ...) -> str: ... def gettimeout(self) -> float: ... def listen(self, backlog: int) -> None: ... def makefile(self, mode: str = ..., buffersize: int = ...) -> IO[Any]: ... def recv(self, buffersize: int, flags: int = ...) -> str: ... def recv_into(self, buffer: bytearray, nbytes: int = ..., flags: int = ...) -> int: ... - def recvfrom(self, buffersize: int, flags: int = ...) -> Tuple[Any, ...]: ... + def recvfrom(self, buffersize: int, flags: int = ...) -> tuple[Any, ...]: ... def recvfrom_into(self, buffer: bytearray, nbytes: int = ..., flags: int = ...) -> int: ... def send(self, data: str, flags: int = ...) -> int: ... def sendall(self, data: str, flags: int = ...) -> None: ... @overload - def sendto(self, data: str, address: Tuple[Any, ...]) -> int: ... + def sendto(self, data: str, address: tuple[Any, ...]) -> int: ... @overload - def sendto(self, data: str, flags: int, address: Tuple[Any, ...]) -> int: ... + def sendto(self, data: str, flags: int, address: tuple[Any, ...]) -> int: ... def setblocking(self, flag: bool) -> None: ... def setsockopt(self, level: int, option: int, value: int | str) -> None: ... def settimeout(self, value: float | None) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/_sre.pyi b/mypy/typeshed/stdlib/@python2/_sre.pyi index 3bacc097451eb..ba61c56344ac7 100644 --- a/mypy/typeshed/stdlib/@python2/_sre.pyi +++ b/mypy/typeshed/stdlib/@python2/_sre.pyi @@ -1,4 +1,4 @@ -from typing import Any, Dict, Iterable, List, Mapping, Sequence, Tuple, overload +from typing import Any, Iterable, Mapping, Sequence, overload CODESIZE: int MAGIC: int @@ -13,11 +13,11 @@ class SRE_Match(object): def group(self) -> str: ... @overload def group(self, group: int = ...) -> str | None: ... - def groupdict(self) -> Dict[int, str | None]: ... - def groups(self) -> Tuple[str | None, ...]: ... - def span(self) -> Tuple[int, int]: ... + def groupdict(self) -> dict[int, str | None]: ... + def groups(self) -> tuple[str | None, ...]: ... + def span(self) -> tuple[int, int]: ... @property - def regs(self) -> Tuple[Tuple[int, int], ...]: ... # undocumented + def regs(self) -> tuple[tuple[int, int], ...]: ... # undocumented class SRE_Scanner(object): pattern: str @@ -30,19 +30,19 @@ class SRE_Pattern(object): groups: int groupindex: Mapping[str, int] indexgroup: Sequence[int] - def findall(self, source: str, pos: int = ..., endpos: int = ...) -> List[Tuple[Any, ...] | str]: ... - def finditer(self, source: str, pos: int = ..., endpos: int = ...) -> Iterable[Tuple[Any, ...] | str]: ... + def findall(self, source: str, pos: int = ..., endpos: int = ...) -> list[tuple[Any, ...] | str]: ... + def finditer(self, source: str, pos: int = ..., endpos: int = ...) -> Iterable[tuple[Any, ...] | str]: ... def match(self, pattern, pos: int = ..., endpos: int = ...) -> SRE_Match: ... def scanner(self, s: str, start: int = ..., end: int = ...) -> SRE_Scanner: ... def search(self, pattern, pos: int = ..., endpos: int = ...) -> SRE_Match: ... - def split(self, source: str, maxsplit: int = ...) -> List[str | None]: ... - def sub(self, repl: str, string: str, count: int = ...) -> Tuple[Any, ...]: ... - def subn(self, repl: str, string: str, count: int = ...) -> Tuple[Any, ...]: ... + def split(self, source: str, maxsplit: int = ...) -> list[str | None]: ... + def sub(self, repl: str, string: str, count: int = ...) -> tuple[Any, ...]: ... + def subn(self, repl: str, string: str, count: int = ...) -> tuple[Any, ...]: ... def compile( pattern: str, flags: int, - code: List[int], + code: list[int], groups: int = ..., groupindex: Mapping[str, int] = ..., indexgroup: Sequence[int] = ..., diff --git a/mypy/typeshed/stdlib/@python2/_struct.pyi b/mypy/typeshed/stdlib/@python2/_struct.pyi index 316307eaabca6..89357ab0bbc8c 100644 --- a/mypy/typeshed/stdlib/@python2/_struct.pyi +++ b/mypy/typeshed/stdlib/@python2/_struct.pyi @@ -1,4 +1,4 @@ -from typing import Any, AnyStr, Tuple +from typing import Any, AnyStr class error(Exception): ... @@ -8,12 +8,12 @@ class Struct(object): def __init__(self, fmt: str) -> None: ... def pack_into(self, buffer: bytearray, offset: int, obj: Any) -> None: ... def pack(self, *args) -> str: ... - def unpack(self, s: str) -> Tuple[Any, ...]: ... - def unpack_from(self, buffer: bytearray, offset: int = ...) -> Tuple[Any, ...]: ... + def unpack(self, s: str) -> tuple[Any, ...]: ... + def unpack_from(self, buffer: bytearray, offset: int = ...) -> tuple[Any, ...]: ... def _clearcache() -> None: ... def calcsize(fmt: str) -> int: ... def pack(fmt: AnyStr, obj: Any) -> str: ... def pack_into(fmt: AnyStr, buffer: bytearray, offset: int, obj: Any) -> None: ... -def unpack(fmt: AnyStr, data: str) -> Tuple[Any, ...]: ... -def unpack_from(fmt: AnyStr, buffer: bytearray, offset: int = ...) -> Tuple[Any, ...]: ... +def unpack(fmt: AnyStr, data: str) -> tuple[Any, ...]: ... +def unpack_from(fmt: AnyStr, buffer: bytearray, offset: int = ...) -> tuple[Any, ...]: ... diff --git a/mypy/typeshed/stdlib/@python2/_symtable.pyi b/mypy/typeshed/stdlib/@python2/_symtable.pyi index 5b2370449c317..ca21f8d5e521d 100644 --- a/mypy/typeshed/stdlib/@python2/_symtable.pyi +++ b/mypy/typeshed/stdlib/@python2/_symtable.pyi @@ -1,5 +1,3 @@ -from typing import Dict, List - CELL: int DEF_BOUND: int DEF_FREE: int @@ -25,13 +23,13 @@ USE: int class _symtable_entry(object): ... class symtable(object): - children: List[_symtable_entry] + children: list[_symtable_entry] id: int lineno: int name: str nested: int optimized: int - symbols: Dict[str, int] + symbols: dict[str, int] type: int - varnames: List[str] + varnames: list[str] def __init__(self, src: str, filename: str, startstr: str) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/_thread.pyi b/mypy/typeshed/stdlib/@python2/_thread.pyi index 562ece61e0421..0470ebd4830ff 100644 --- a/mypy/typeshed/stdlib/@python2/_thread.pyi +++ b/mypy/typeshed/stdlib/@python2/_thread.pyi @@ -1,5 +1,5 @@ from types import TracebackType -from typing import Any, Callable, Dict, NoReturn, Tuple, Type +from typing import Any, Callable, NoReturn error = RuntimeError @@ -13,10 +13,10 @@ class LockType: def locked(self) -> bool: ... def __enter__(self) -> bool: ... def __exit__( - self, type: Type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None + self, type: type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None ) -> None: ... -def start_new_thread(function: Callable[..., Any], args: Tuple[Any, ...], kwargs: Dict[str, Any] = ...) -> int: ... +def start_new_thread(function: Callable[..., Any], args: tuple[Any, ...], kwargs: dict[str, Any] = ...) -> int: ... def interrupt_main() -> None: ... def exit() -> NoReturn: ... def allocate_lock() -> LockType: ... diff --git a/mypy/typeshed/stdlib/@python2/_typeshed/__init__.pyi b/mypy/typeshed/stdlib/@python2/_typeshed/__init__.pyi index ca698e29ae8a2..657164f81f6d8 100644 --- a/mypy/typeshed/stdlib/@python2/_typeshed/__init__.pyi +++ b/mypy/typeshed/stdlib/@python2/_typeshed/__init__.pyi @@ -14,7 +14,7 @@ import array import mmap -from typing import Any, Container, Iterable, Protocol, Text, Tuple, TypeVar, Union +from typing import Any, Container, Iterable, Protocol, Text, TypeVar from typing_extensions import Literal, final _KT = TypeVar("_KT") @@ -28,7 +28,7 @@ _T_contra = TypeVar("_T_contra", contravariant=True) # Use for "self" annotations: # def __enter__(self: Self) -> Self: ... -Self = TypeVar("Self") # noqa Y001 +Self = TypeVar("Self") # noqa: Y001 class IdentityFunction(Protocol): def __call__(self, __x: _T) -> _T: ... @@ -48,7 +48,7 @@ class SupportsRDivMod(Protocol[_T_contra, _T_co]): class SupportsItems(Protocol[_KT_co, _VT_co]): # We want dictionaries to support this on Python 2. - def items(self) -> Iterable[Tuple[_KT_co, _VT_co]]: ... + def items(self) -> Iterable[tuple[_KT_co, _VT_co]]: ... class SupportsKeysAndGetItem(Protocol[_KT, _VT_co]): def keys(self) -> Iterable[_KT]: ... @@ -104,7 +104,7 @@ OpenTextModeUpdating = Literal[ ] OpenTextModeWriting = Literal["w", "wt", "tw", "a", "at", "ta", "x", "xt", "tx"] OpenTextModeReading = Literal["r", "rt", "tr", "U", "rU", "Ur", "rtU", "rUt", "Urt", "trU", "tUr", "Utr"] -OpenTextMode = Union[OpenTextModeUpdating, OpenTextModeWriting, OpenTextModeReading] +OpenTextMode = OpenTextModeUpdating | OpenTextModeWriting | OpenTextModeReading OpenBinaryModeUpdating = Literal[ "rb+", "r+b", @@ -133,13 +133,13 @@ OpenBinaryModeUpdating = Literal[ ] OpenBinaryModeWriting = Literal["wb", "bw", "ab", "ba", "xb", "bx"] OpenBinaryModeReading = Literal["rb", "br", "rbU", "rUb", "Urb", "brU", "bUr", "Ubr"] -OpenBinaryMode = Union[OpenBinaryModeUpdating, OpenBinaryModeReading, OpenBinaryModeWriting] +OpenBinaryMode = OpenBinaryModeUpdating | OpenBinaryModeReading | OpenBinaryModeWriting class HasFileno(Protocol): def fileno(self) -> int: ... FileDescriptor = int -FileDescriptorLike = Union[int, HasFileno] +FileDescriptorLike = int | HasFileno class SupportsRead(Protocol[_T_co]): def read(self, __length: int = ...) -> _T_co: ... @@ -153,8 +153,8 @@ class SupportsNoArgReadline(Protocol[_T_co]): class SupportsWrite(Protocol[_T_contra]): def write(self, __s: _T_contra) -> Any: ... -ReadableBuffer = Union[bytes, bytearray, memoryview, array.array[Any], mmap.mmap, buffer] -WriteableBuffer = Union[bytearray, memoryview, array.array[Any], mmap.mmap, buffer] +ReadableBuffer = bytes | bytearray | memoryview | array.array[Any] | mmap.mmap | buffer +WriteableBuffer = bytearray | memoryview | array.array[Any] | mmap.mmap | buffer # Used by type checkers for checks involving None (does not exist at runtime) @final diff --git a/mypy/typeshed/stdlib/@python2/_typeshed/wsgi.pyi b/mypy/typeshed/stdlib/@python2/_typeshed/wsgi.pyi index a1f10443a6f06..4380949c9c1c3 100644 --- a/mypy/typeshed/stdlib/@python2/_typeshed/wsgi.pyi +++ b/mypy/typeshed/stdlib/@python2/_typeshed/wsgi.pyi @@ -4,28 +4,28 @@ # file. They are provided for type checking purposes. from sys import _OptExcInfo -from typing import Any, Callable, Dict, Iterable, List, Optional, Protocol, Text, Tuple +from typing import Any, Callable, Iterable, Protocol, Text class StartResponse(Protocol): def __call__( - self, status: str, headers: List[Tuple[str, str]], exc_info: _OptExcInfo | None = ... + self, status: str, headers: list[tuple[str, str]], exc_info: _OptExcInfo | None = ... ) -> Callable[[bytes], Any]: ... -WSGIEnvironment = Dict[Text, Any] +WSGIEnvironment = dict[Text, Any] WSGIApplication = Callable[[WSGIEnvironment, StartResponse], Iterable[bytes]] # WSGI input streams per PEP 3333 class InputStream(Protocol): def read(self, size: int = ...) -> bytes: ... def readline(self, size: int = ...) -> bytes: ... - def readlines(self, hint: int = ...) -> List[bytes]: ... + def readlines(self, hint: int = ...) -> list[bytes]: ... def __iter__(self) -> Iterable[bytes]: ... # WSGI error streams per PEP 3333 class ErrorStream(Protocol): def flush(self) -> None: ... def write(self, s: str) -> None: ... - def writelines(self, seq: List[str]) -> None: ... + def writelines(self, seq: list[str]) -> None: ... class _Readable(Protocol): def read(self, size: int = ...) -> bytes: ... diff --git a/mypy/typeshed/stdlib/@python2/_warnings.pyi b/mypy/typeshed/stdlib/@python2/_warnings.pyi index ccc51fecb8daa..8f531c47af55b 100644 --- a/mypy/typeshed/stdlib/@python2/_warnings.pyi +++ b/mypy/typeshed/stdlib/@python2/_warnings.pyi @@ -1,23 +1,23 @@ -from typing import Any, Dict, List, Tuple, Type, overload +from typing import Any, overload default_action: str -once_registry: Dict[Any, Any] +once_registry: dict[Any, Any] -filters: List[Tuple[Any, ...]] +filters: list[tuple[Any, ...]] @overload -def warn(message: str, category: Type[Warning] | None = ..., stacklevel: int = ...) -> None: ... +def warn(message: str, category: type[Warning] | None = ..., stacklevel: int = ...) -> None: ... @overload def warn(message: Warning, category: Any = ..., stacklevel: int = ...) -> None: ... @overload def warn_explicit( message: str, - category: Type[Warning], + category: type[Warning], filename: str, lineno: int, module: str | None = ..., - registry: Dict[str | Tuple[str, Type[Warning], int], int] | None = ..., - module_globals: Dict[str, Any] | None = ..., + registry: dict[str | tuple[str, type[Warning], int], int] | None = ..., + module_globals: dict[str, Any] | None = ..., ) -> None: ... @overload def warn_explicit( @@ -26,6 +26,6 @@ def warn_explicit( filename: str, lineno: int, module: str | None = ..., - registry: Dict[str | Tuple[str, Type[Warning], int], int] | None = ..., - module_globals: Dict[str, Any] | None = ..., + registry: dict[str | tuple[str, type[Warning], int], int] | None = ..., + module_globals: dict[str, Any] | None = ..., ) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/_weakref.pyi b/mypy/typeshed/stdlib/@python2/_weakref.pyi index a283d4cb60d31..9a37de3174b6a 100644 --- a/mypy/typeshed/stdlib/@python2/_weakref.pyi +++ b/mypy/typeshed/stdlib/@python2/_weakref.pyi @@ -1,4 +1,4 @@ -from typing import Any, Callable, Generic, List, TypeVar, overload +from typing import Any, Callable, Generic, TypeVar, overload _C = TypeVar("_C", bound=Callable[..., Any]) _T = TypeVar("_T") @@ -17,7 +17,7 @@ class ReferenceType(Generic[_T]): ref = ReferenceType def getweakrefcount(__object: Any) -> int: ... -def getweakrefs(object: Any) -> List[Any]: ... +def getweakrefs(object: Any) -> list[Any]: ... @overload def proxy(object: _C, callback: Callable[[_C], Any] | None = ...) -> CallableProxyType[_C]: ... diff --git a/mypy/typeshed/stdlib/@python2/_weakrefset.pyi b/mypy/typeshed/stdlib/@python2/_weakrefset.pyi index f2cde7d67e52b..0d2c7fc42f223 100644 --- a/mypy/typeshed/stdlib/@python2/_weakrefset.pyi +++ b/mypy/typeshed/stdlib/@python2/_weakrefset.pyi @@ -1,30 +1,30 @@ +from _typeshed import Self from typing import Any, Generic, Iterable, Iterator, MutableSet, TypeVar _S = TypeVar("_S") _T = TypeVar("_T") -_SelfT = TypeVar("_SelfT", bound=WeakSet[Any]) class WeakSet(MutableSet[_T], Generic[_T]): def __init__(self, data: Iterable[_T] | None = ...) -> None: ... def add(self, item: _T) -> None: ... def clear(self) -> None: ... def discard(self, item: _T) -> None: ... - def copy(self: _SelfT) -> _SelfT: ... + def copy(self: Self) -> Self: ... def pop(self) -> _T: ... def remove(self, item: _T) -> None: ... def update(self, other: Iterable[_T]) -> None: ... def __contains__(self, item: object) -> bool: ... def __len__(self) -> int: ... def __iter__(self) -> Iterator[_T]: ... - def __ior__(self, other: Iterable[_S]) -> WeakSet[_S | _T]: ... - def difference(self: _SelfT, other: Iterable[_T]) -> _SelfT: ... - def __sub__(self: _SelfT, other: Iterable[_T]) -> _SelfT: ... - def difference_update(self, other: Iterable[_T]) -> None: ... - def __isub__(self: _SelfT, other: Iterable[_T]) -> _SelfT: ... - def intersection(self: _SelfT, other: Iterable[_T]) -> _SelfT: ... - def __and__(self: _SelfT, other: Iterable[_T]) -> _SelfT: ... - def intersection_update(self, other: Iterable[_T]) -> None: ... - def __iand__(self: _SelfT, other: Iterable[_T]) -> _SelfT: ... + def __ior__(self: Self, other: Iterable[_T]) -> Self: ... # type: ignore[override,misc] + def difference(self: Self, other: Iterable[_T]) -> Self: ... + def __sub__(self: Self, other: Iterable[Any]) -> Self: ... + def difference_update(self, other: Iterable[Any]) -> None: ... + def __isub__(self: Self, other: Iterable[Any]) -> Self: ... + def intersection(self: Self, other: Iterable[_T]) -> Self: ... + def __and__(self: Self, other: Iterable[Any]) -> Self: ... + def intersection_update(self, other: Iterable[Any]) -> None: ... + def __iand__(self: Self, other: Iterable[Any]) -> Self: ... def issubset(self, other: Iterable[_T]) -> bool: ... def __le__(self, other: Iterable[_T]) -> bool: ... def __lt__(self, other: Iterable[_T]) -> bool: ... @@ -34,8 +34,8 @@ class WeakSet(MutableSet[_T], Generic[_T]): def __eq__(self, other: object) -> bool: ... def symmetric_difference(self, other: Iterable[_S]) -> WeakSet[_S | _T]: ... def __xor__(self, other: Iterable[_S]) -> WeakSet[_S | _T]: ... - def symmetric_difference_update(self, other: Iterable[Any]) -> None: ... - def __ixor__(self, other: Iterable[_S]) -> WeakSet[_S | _T]: ... + def symmetric_difference_update(self, other: Iterable[_T]) -> None: ... + def __ixor__(self: Self, other: Iterable[_T]) -> Self: ... # type: ignore[override,misc] def union(self, other: Iterable[_S]) -> WeakSet[_S | _T]: ... def __or__(self, other: Iterable[_S]) -> WeakSet[_S | _T]: ... def isdisjoint(self, other: Iterable[_T]) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/_winreg.pyi b/mypy/typeshed/stdlib/@python2/_winreg.pyi index 5b8ec1130ca1c..395024fcc2fd7 100644 --- a/mypy/typeshed/stdlib/@python2/_winreg.pyi +++ b/mypy/typeshed/stdlib/@python2/_winreg.pyi @@ -1,9 +1,10 @@ import sys +from _typeshed import Self from types import TracebackType -from typing import Any, Tuple, Type, Union +from typing import Any if sys.platform == "win32": - _KeyType = Union[HKEYType, int] + _KeyType = HKEYType | int def CloseKey(__hkey: _KeyType) -> None: ... def ConnectRegistry(__computer_name: str | None, __key: _KeyType) -> HKEYType: ... def CreateKey(__key: _KeyType, __sub_key: str | None) -> HKEYType: ... @@ -12,15 +13,15 @@ if sys.platform == "win32": def DeleteKeyEx(key: _KeyType, sub_key: str, access: int = ..., reserved: int = ...) -> None: ... def DeleteValue(__key: _KeyType, __value: str) -> None: ... def EnumKey(__key: _KeyType, __index: int) -> str: ... - def EnumValue(__key: _KeyType, __index: int) -> Tuple[str, Any, int]: ... + def EnumValue(__key: _KeyType, __index: int) -> tuple[str, Any, int]: ... def ExpandEnvironmentStrings(__str: str) -> str: ... def FlushKey(__key: _KeyType) -> None: ... def LoadKey(__key: _KeyType, __sub_key: str, __file_name: str) -> None: ... def OpenKey(key: _KeyType, sub_key: str, reserved: int = ..., access: int = ...) -> HKEYType: ... def OpenKeyEx(key: _KeyType, sub_key: str, reserved: int = ..., access: int = ...) -> HKEYType: ... - def QueryInfoKey(__key: _KeyType) -> Tuple[int, int, int]: ... + def QueryInfoKey(__key: _KeyType) -> tuple[int, int, int]: ... def QueryValue(__key: _KeyType, __sub_key: str | None) -> str: ... - def QueryValueEx(__key: _KeyType, __name: str) -> Tuple[Any, int]: ... + def QueryValueEx(__key: _KeyType, __name: str) -> tuple[Any, int]: ... def SaveKey(__key: _KeyType, __file_name: str) -> None: ... def SetValue(__key: _KeyType, __sub_key: str, __type: int, __value: str) -> None: ... def SetValueEx( @@ -88,9 +89,9 @@ if sys.platform == "win32": class HKEYType: def __bool__(self) -> bool: ... def __int__(self) -> int: ... - def __enter__(self) -> HKEYType: ... + def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> bool | None: ... def Close(self) -> None: ... def Detach(self) -> int: ... diff --git a/mypy/typeshed/stdlib/@python2/abc.pyi b/mypy/typeshed/stdlib/@python2/abc.pyi index ac14246d44a5c..49ec775f91e87 100644 --- a/mypy/typeshed/stdlib/@python2/abc.pyi +++ b/mypy/typeshed/stdlib/@python2/abc.pyi @@ -1,6 +1,6 @@ import _weakrefset from _typeshed import SupportsWrite -from typing import Any, Callable, Dict, Set, Tuple, Type, TypeVar +from typing import Any, Callable, TypeVar _FuncT = TypeVar("_FuncT", bound=Callable[..., Any]) @@ -15,11 +15,11 @@ class ABCMeta(type): _abc_negative_cache: _weakrefset.WeakSet[Any] _abc_negative_cache_version: int _abc_registry: _weakrefset.WeakSet[Any] - def __init__(self, name: str, bases: Tuple[type, ...], namespace: Dict[str, Any]) -> None: ... + def __init__(self, name: str, bases: tuple[type, ...], namespace: dict[str, Any]) -> None: ... def __instancecheck__(cls: ABCMeta, instance: Any) -> Any: ... def __subclasscheck__(cls: ABCMeta, subclass: Any) -> Any: ... def _dump_registry(cls: ABCMeta, file: SupportsWrite[Any] | None = ...) -> None: ... - def register(cls: ABCMeta, subclass: Type[Any]) -> None: ... + def register(cls: ABCMeta, subclass: type[Any]) -> None: ... # TODO: The real abc.abstractproperty inherits from "property". class abstractproperty(object): diff --git a/mypy/typeshed/stdlib/@python2/aifc.pyi b/mypy/typeshed/stdlib/@python2/aifc.pyi index 42f20b7466a12..766ccde956f9f 100644 --- a/mypy/typeshed/stdlib/@python2/aifc.pyi +++ b/mypy/typeshed/stdlib/@python2/aifc.pyi @@ -1,4 +1,4 @@ -from typing import IO, Any, List, NamedTuple, Text, Tuple, Union, overload +from typing import IO, Any, NamedTuple, Text, overload from typing_extensions import Literal class Error(Exception): ... @@ -11,8 +11,8 @@ class _aifc_params(NamedTuple): comptype: bytes compname: bytes -_File = Union[Text, IO[bytes]] -_Marker = Tuple[int, int, bytes] +_File = Text | IO[bytes] +_Marker = tuple[int, int, bytes] class Aifc_read: def __init__(self, f: _File) -> None: ... @@ -28,7 +28,7 @@ class Aifc_read: def getcomptype(self) -> bytes: ... def getcompname(self) -> bytes: ... def getparams(self) -> _aifc_params: ... - def getmarkers(self) -> List[_Marker] | None: ... + def getmarkers(self) -> list[_Marker] | None: ... def getmark(self, id: int) -> _Marker: ... def setpos(self, pos: int) -> None: ... def readframes(self, nframes: int) -> bytes: ... @@ -50,11 +50,11 @@ class Aifc_write: def setcomptype(self, comptype: bytes, compname: bytes) -> None: ... def getcomptype(self) -> bytes: ... def getcompname(self) -> bytes: ... - def setparams(self, params: Tuple[int, int, int, int, bytes, bytes]) -> None: ... + def setparams(self, params: tuple[int, int, int, int, bytes, bytes]) -> None: ... def getparams(self) -> _aifc_params: ... def setmark(self, id: int, pos: int, name: bytes) -> None: ... def getmark(self, id: int) -> _Marker: ... - def getmarkers(self) -> List[_Marker] | None: ... + def getmarkers(self) -> list[_Marker] | None: ... def tell(self) -> int: ... def writeframesraw(self, data: Any) -> None: ... # Actual type for data is Buffer Protocol def writeframes(self, data: Any) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/argparse.pyi b/mypy/typeshed/stdlib/@python2/argparse.pyi index 4d77f6582c5f5..a9a57ea0ea55a 100644 --- a/mypy/typeshed/stdlib/@python2/argparse.pyi +++ b/mypy/typeshed/stdlib/@python2/argparse.pyi @@ -1,28 +1,10 @@ -from typing import ( - IO, - Any, - Callable, - Dict, - Generator, - Iterable, - List, - NoReturn, - Pattern, - Protocol, - Sequence, - Text, - Tuple, - Type, - TypeVar, - Union, - overload, -) +from typing import IO, Any, Callable, Generator, Iterable, NoReturn, Pattern, Protocol, Sequence, Text, TypeVar, overload _T = TypeVar("_T") _ActionT = TypeVar("_ActionT", bound=Action) _N = TypeVar("_N") -_Text = Union[str, unicode] +_Text = str | unicode ONE_OR_MORE: str OPTIONAL: str @@ -39,8 +21,8 @@ class ArgumentError(Exception): # undocumented class _AttributeHolder: - def _get_kwargs(self) -> List[Tuple[str, Any]]: ... - def _get_args(self) -> List[Any]: ... + def _get_kwargs(self) -> list[tuple[str, Any]]: ... + def _get_args(self) -> list[Any]: ... # undocumented class _ActionsContainer: @@ -49,14 +31,14 @@ class _ActionsContainer: argument_default: Any conflict_handler: _Text - _registries: Dict[_Text, Dict[Any, Any]] - _actions: List[Action] - _option_string_actions: Dict[_Text, Action] - _action_groups: List[_ArgumentGroup] - _mutually_exclusive_groups: List[_MutuallyExclusiveGroup] - _defaults: Dict[str, Any] + _registries: dict[_Text, dict[Any, Any]] + _actions: list[Action] + _option_string_actions: dict[_Text, Action] + _action_groups: list[_ArgumentGroup] + _mutually_exclusive_groups: list[_MutuallyExclusiveGroup] + _defaults: dict[str, Any] _negative_number_matcher: Pattern[str] - _has_negative_number_optionals: List[bool] + _has_negative_number_optionals: list[bool] def __init__(self, description: Text | None, prefix_chars: Text, argument_default: Any, conflict_handler: Text) -> None: ... def register(self, registry_name: Text, value: Any, object: Any) -> None: ... def _registry_get(self, registry_name: Text, value: Any, default: Any = ...) -> Any: ... @@ -65,7 +47,7 @@ class _ActionsContainer: def add_argument( self, *name_or_flags: Text, - action: Text | Type[Action] = ..., + action: Text | type[Action] = ..., nargs: int | Text = ..., const: Any = ..., default: Any = ..., @@ -73,7 +55,7 @@ class _ActionsContainer: choices: Iterable[_T] = ..., required: bool = ..., help: Text | None = ..., - metavar: Text | Tuple[Text, ...] | None = ..., + metavar: Text | tuple[Text, ...] | None = ..., dest: Text | None = ..., version: Text = ..., **kwargs: Any, @@ -83,13 +65,13 @@ class _ActionsContainer: def _add_action(self, action: _ActionT) -> _ActionT: ... def _remove_action(self, action: Action) -> None: ... def _add_container_actions(self, container: _ActionsContainer) -> None: ... - def _get_positional_kwargs(self, dest: Text, **kwargs: Any) -> Dict[str, Any]: ... - def _get_optional_kwargs(self, *args: Any, **kwargs: Any) -> Dict[str, Any]: ... - def _pop_action_class(self, kwargs: Any, default: Type[Action] | None = ...) -> Type[Action]: ... - def _get_handler(self) -> Callable[[Action, Iterable[Tuple[Text, Action]]], Any]: ... + def _get_positional_kwargs(self, dest: Text, **kwargs: Any) -> dict[str, Any]: ... + def _get_optional_kwargs(self, *args: Any, **kwargs: Any) -> dict[str, Any]: ... + def _pop_action_class(self, kwargs: Any, default: type[Action] | None = ...) -> type[Action]: ... + def _get_handler(self) -> Callable[[Action, Iterable[tuple[Text, Action]]], Any]: ... def _check_conflict(self, action: Action) -> None: ... - def _handle_conflict_error(self, action: Action, conflicting_actions: Iterable[Tuple[Text, Action]]) -> NoReturn: ... - def _handle_conflict_resolve(self, action: Action, conflicting_actions: Iterable[Tuple[Text, Action]]) -> None: ... + def _handle_conflict_error(self, action: Action, conflicting_actions: Iterable[tuple[Text, Action]]) -> NoReturn: ... + def _handle_conflict_resolve(self, action: Action, conflicting_actions: Iterable[tuple[Text, Action]]) -> None: ... class _FormatterClass(Protocol): def __call__(self, prog: str) -> HelpFormatter: ... @@ -125,11 +107,11 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): @overload def parse_args(self, args: Sequence[Text] | None = ...) -> Namespace: ... @overload - def parse_args(self, args: Sequence[Text] | None, namespace: None) -> Namespace: ... # type: ignore + def parse_args(self, args: Sequence[Text] | None, namespace: None) -> Namespace: ... # type: ignore[misc] @overload def parse_args(self, args: Sequence[Text] | None, namespace: _N) -> _N: ... @overload - def parse_args(self, *, namespace: None) -> Namespace: ... # type: ignore + def parse_args(self, *, namespace: None) -> Namespace: ... # type: ignore[misc] @overload def parse_args(self, *, namespace: _N) -> _N: ... def add_subparsers( @@ -138,8 +120,8 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): title: Text = ..., description: Text | None = ..., prog: Text = ..., - parser_class: Type[ArgumentParser] = ..., - action: Type[Action] = ..., + parser_class: type[ArgumentParser] = ..., + action: type[Action] = ..., option_string: Text = ..., dest: Text | None = ..., help: Text | None = ..., @@ -151,21 +133,21 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): def format_help(self) -> str: ... def parse_known_args( self, args: Sequence[Text] | None = ..., namespace: Namespace | None = ... - ) -> Tuple[Namespace, List[str]]: ... - def convert_arg_line_to_args(self, arg_line: Text) -> List[str]: ... + ) -> tuple[Namespace, list[str]]: ... + def convert_arg_line_to_args(self, arg_line: Text) -> list[str]: ... def exit(self, status: int = ..., message: Text | None = ...) -> NoReturn: ... def error(self, message: Text) -> NoReturn: ... # undocumented - def _get_optional_actions(self) -> List[Action]: ... - def _get_positional_actions(self) -> List[Action]: ... - def _parse_known_args(self, arg_strings: List[Text], namespace: Namespace) -> Tuple[Namespace, List[str]]: ... - def _read_args_from_files(self, arg_strings: List[Text]) -> List[Text]: ... + def _get_optional_actions(self) -> list[Action]: ... + def _get_positional_actions(self) -> list[Action]: ... + def _parse_known_args(self, arg_strings: list[Text], namespace: Namespace) -> tuple[Namespace, list[str]]: ... + def _read_args_from_files(self, arg_strings: list[Text]) -> list[Text]: ... def _match_argument(self, action: Action, arg_strings_pattern: Text) -> int: ... - def _match_arguments_partial(self, actions: Sequence[Action], arg_strings_pattern: Text) -> List[int]: ... - def _parse_optional(self, arg_string: Text) -> Tuple[Action | None, Text, Text | None] | None: ... - def _get_option_tuples(self, option_string: Text) -> List[Tuple[Action, Text, Text | None]]: ... + def _match_arguments_partial(self, actions: Sequence[Action], arg_strings_pattern: Text) -> list[int]: ... + def _parse_optional(self, arg_string: Text) -> tuple[Action | None, Text, Text | None] | None: ... + def _get_option_tuples(self, option_string: Text) -> list[tuple[Action, Text, Text | None]]: ... def _get_nargs_pattern(self, action: Action) -> _Text: ... - def _get_values(self, action: Action, arg_strings: List[Text]) -> Any: ... + def _get_values(self, action: Action, arg_strings: list[Text]) -> Any: ... def _get_value(self, action: Action, arg_string: Text) -> Any: ... def _check_value(self, action: Action, value: Any) -> None: ... def _get_formatter(self) -> HelpFormatter: ... @@ -184,7 +166,7 @@ class HelpFormatter: _current_section: Any _whitespace_matcher: Pattern[str] _long_break_matcher: Pattern[str] - _Section: Type[Any] # Nested class + _Section: type[Any] # Nested class def __init__( self, prog: Text, indent_increment: int = ..., max_help_position: int = ..., width: int | None = ... ) -> None: ... @@ -208,11 +190,11 @@ class HelpFormatter: def _format_text(self, text: Text) -> _Text: ... def _format_action(self, action: Action) -> _Text: ... def _format_action_invocation(self, action: Action) -> _Text: ... - def _metavar_formatter(self, action: Action, default_metavar: Text) -> Callable[[int], Tuple[_Text, ...]]: ... + def _metavar_formatter(self, action: Action, default_metavar: Text) -> Callable[[int], tuple[_Text, ...]]: ... def _format_args(self, action: Action, default_metavar: Text) -> _Text: ... def _expand_help(self, action: Action) -> _Text: ... def _iter_indented_subactions(self, action: Action) -> Generator[Action, None, None]: ... - def _split_lines(self, text: Text, width: int) -> List[_Text]: ... + def _split_lines(self, text: Text, width: int) -> list[_Text]: ... def _fill_text(self, text: Text, width: int, indent: Text) -> _Text: ... def _get_help_string(self, action: Action) -> _Text | None: ... def _get_default_metavar_for_optional(self, action: Action) -> _Text: ... @@ -232,7 +214,7 @@ class Action(_AttributeHolder): choices: Iterable[Any] | None required: bool help: _Text | None - metavar: _Text | Tuple[_Text, ...] | None + metavar: _Text | tuple[_Text, ...] | None def __init__( self, option_strings: Sequence[Text], @@ -244,7 +226,7 @@ class Action(_AttributeHolder): choices: Iterable[_T] | None = ..., required: bool = ..., help: Text | None = ..., - metavar: Text | Tuple[Text, ...] | None = ..., + metavar: Text | tuple[Text, ...] | None = ..., ) -> None: ... def __call__( self, parser: ArgumentParser, namespace: Namespace, values: Text | Sequence[Any] | None, option_string: Text | None = ... @@ -266,7 +248,7 @@ class FileType: # undocumented class _ArgumentGroup(_ActionsContainer): title: _Text | None - _group_actions: List[Action] + _group_actions: list[Action] def __init__( self, container: _ActionsContainer, title: Text | None = ..., description: Text | None = ..., **kwargs: Any ) -> None: ... @@ -290,7 +272,7 @@ class _StoreConstAction(Action): default: Any = ..., required: bool = ..., help: Text | None = ..., - metavar: Text | Tuple[Text, ...] | None = ..., + metavar: Text | tuple[Text, ...] | None = ..., ) -> None: ... # undocumented @@ -318,7 +300,7 @@ class _AppendConstAction(Action): default: Any = ..., required: bool = ..., help: Text | None = ..., - metavar: Text | Tuple[Text, ...] | None = ..., + metavar: Text | tuple[Text, ...] | None = ..., ) -> None: ... # undocumented @@ -342,24 +324,24 @@ class _VersionAction(Action): # undocumented class _SubParsersAction(Action): - _ChoicesPseudoAction: Type[Any] # nested class + _ChoicesPseudoAction: type[Any] # nested class _prog_prefix: _Text - _parser_class: Type[ArgumentParser] - _name_parser_map: Dict[_Text, ArgumentParser] - choices: Dict[_Text, ArgumentParser] - _choices_actions: List[Action] + _parser_class: type[ArgumentParser] + _name_parser_map: dict[_Text, ArgumentParser] + choices: dict[_Text, ArgumentParser] + _choices_actions: list[Action] def __init__( self, option_strings: Sequence[Text], prog: Text, - parser_class: Type[ArgumentParser], + parser_class: type[ArgumentParser], dest: Text = ..., help: Text | None = ..., - metavar: Text | Tuple[Text, ...] | None = ..., + metavar: Text | tuple[Text, ...] | None = ..., ) -> None: ... # TODO: Type keyword args properly. def add_parser(self, name: Text, **kwargs: Any) -> ArgumentParser: ... - def _get_subactions(self) -> List[Action]: ... + def _get_subactions(self) -> list[Action]: ... # undocumented class ArgumentTypeError(Exception): ... diff --git a/mypy/typeshed/stdlib/@python2/array.pyi b/mypy/typeshed/stdlib/@python2/array.pyi index 39670fe734fc8..a47b845d19337 100644 --- a/mypy/typeshed/stdlib/@python2/array.pyi +++ b/mypy/typeshed/stdlib/@python2/array.pyi @@ -1,10 +1,11 @@ -from typing import Any, BinaryIO, Generic, Iterable, List, MutableSequence, Text, Tuple, TypeVar, Union, overload +from _typeshed import Self +from typing import Any, BinaryIO, Generic, Iterable, MutableSequence, Text, TypeVar, overload from typing_extensions import Literal _IntTypeCode = Literal["b", "B", "h", "H", "i", "I", "l", "L", "q", "Q"] _FloatTypeCode = Literal["f", "d"] _UnicodeTypeCode = Literal["u"] -_TypeCode = Union[_IntTypeCode, _FloatTypeCode, _UnicodeTypeCode] +_TypeCode = _IntTypeCode | _FloatTypeCode | _UnicodeTypeCode _T = TypeVar("_T", int, float, Text) @@ -20,21 +21,21 @@ class array(MutableSequence[_T], Generic[_T]): @overload def __init__(self, typecode: str, __initializer: bytes | Iterable[_T] = ...) -> None: ... def append(self, __v: _T) -> None: ... - def buffer_info(self) -> Tuple[int, int]: ... + def buffer_info(self) -> tuple[int, int]: ... def byteswap(self) -> None: ... def count(self, __v: Any) -> int: ... def extend(self, __bb: Iterable[_T]) -> None: ... def fromfile(self, __f: BinaryIO, __n: int) -> None: ... - def fromlist(self, __list: List[_T]) -> None: ... + def fromlist(self, __list: list[_T]) -> None: ... def fromunicode(self, __ustr: str) -> None: ... - def index(self, __v: _T) -> int: ... # type: ignore # Overrides Sequence + def index(self, __v: _T) -> int: ... # Overrides Sequence def insert(self, __i: int, __v: _T) -> None: ... def pop(self, __i: int = ...) -> _T: ... def read(self, f: BinaryIO, n: int) -> None: ... def remove(self, __v: Any) -> None: ... def reverse(self) -> None: ... def tofile(self, __f: BinaryIO) -> None: ... - def tolist(self) -> List[_T]: ... + def tolist(self) -> list[_T]: ... def tounicode(self) -> str: ... def write(self, f: BinaryIO) -> None: ... def fromstring(self, __buffer: bytes) -> None: ... @@ -44,7 +45,7 @@ class array(MutableSequence[_T], Generic[_T]): def __getitem__(self, i: int) -> _T: ... @overload def __getitem__(self, s: slice) -> array[_T]: ... - @overload # type: ignore # Overrides MutableSequence + @overload # type: ignore[override] def __setitem__(self, i: int, o: _T) -> None: ... @overload def __setitem__(self, s: slice, o: array[_T]) -> None: ... @@ -52,8 +53,8 @@ class array(MutableSequence[_T], Generic[_T]): def __add__(self, x: array[_T]) -> array[_T]: ... def __ge__(self, other: array[_T]) -> bool: ... def __gt__(self, other: array[_T]) -> bool: ... - def __iadd__(self, x: array[_T]) -> array[_T]: ... # type: ignore # Overrides MutableSequence - def __imul__(self, n: int) -> array[_T]: ... + def __iadd__(self: Self, x: array[_T]) -> Self: ... # type: ignore[override] + def __imul__(self: Self, n: int) -> Self: ... def __le__(self, other: array[_T]) -> bool: ... def __lt__(self, other: array[_T]) -> bool: ... def __mul__(self, n: int) -> array[_T]: ... diff --git a/mypy/typeshed/stdlib/@python2/asynchat.pyi b/mypy/typeshed/stdlib/@python2/asynchat.pyi index 0f5526d71b1dc..e55dbf258a140 100644 --- a/mypy/typeshed/stdlib/@python2/asynchat.pyi +++ b/mypy/typeshed/stdlib/@python2/asynchat.pyi @@ -1,7 +1,7 @@ import asyncore import socket from abc import abstractmethod -from typing import Sequence, Tuple +from typing import Sequence class simple_producer: def __init__(self, data: bytes, buffer_size: int = ...) -> None: ... @@ -34,4 +34,4 @@ class fifo: def is_empty(self) -> bool: ... def first(self) -> bytes: ... def push(self, data: bytes | simple_producer) -> None: ... - def pop(self) -> Tuple[int, bytes]: ... + def pop(self) -> tuple[int, bytes]: ... diff --git a/mypy/typeshed/stdlib/@python2/asyncore.pyi b/mypy/typeshed/stdlib/@python2/asyncore.pyi index 95acf9b706d38..a9f07613bb9cd 100644 --- a/mypy/typeshed/stdlib/@python2/asyncore.pyi +++ b/mypy/typeshed/stdlib/@python2/asyncore.pyi @@ -1,12 +1,12 @@ import sys from _typeshed import FileDescriptorLike from socket import SocketType -from typing import Any, Dict, Optional, Tuple, overload +from typing import Any, overload # cyclic dependence with asynchat -_maptype = Dict[int, Any] +_maptype = dict[int, Any] -socket_map: _maptype = ... # undocumented +socket_map: _maptype # undocumented class ExitNow(Exception): ... @@ -40,9 +40,9 @@ class dispatcher: def readable(self) -> bool: ... def writable(self) -> bool: ... def listen(self, num: int) -> None: ... - def bind(self, addr: Tuple[Any, ...] | str) -> None: ... - def connect(self, address: Tuple[Any, ...] | str) -> None: ... - def accept(self) -> Tuple[SocketType, Any] | None: ... + def bind(self, addr: tuple[Any, ...] | str) -> None: ... + def connect(self, address: tuple[Any, ...] | str) -> None: ... + def accept(self) -> tuple[SocketType, Any] | None: ... def send(self, data: bytes) -> int: ... def recv(self, buffer_size: int) -> bytes: ... def close(self) -> None: ... @@ -73,7 +73,7 @@ class dispatcher: @overload def getsockopt(self, level: int, optname: int, buflen: int) -> bytes: ... def gettimeout(self) -> float: ... - def ioctl(self, control: object, option: Tuple[int, int, int]) -> None: ... + def ioctl(self, control: object, option: tuple[int, int, int]) -> None: ... # TODO the return value may be BinaryIO or TextIO, depending on mode def makefile( self, mode: str = ..., buffering: int = ..., encoding: str = ..., errors: str = ..., newline: str = ... @@ -83,7 +83,7 @@ class dispatcher: def recvfrom_into(self, buffer: bytes, nbytes: int, flags: int = ...) -> Any: ... def recv_into(self, buffer: bytes, nbytes: int, flags: int = ...) -> Any: ... def sendall(self, data: bytes, flags: int = ...) -> None: ... - def sendto(self, data: bytes, address: Tuple[str, int] | str, flags: int = ...) -> int: ... + def sendto(self, data: bytes, address: tuple[str, int] | str, flags: int = ...) -> int: ... def setblocking(self, flag: bool) -> None: ... def settimeout(self, value: float | None) -> None: ... def setsockopt(self, level: int, optname: int, value: int | bytes) -> None: ... @@ -96,7 +96,7 @@ class dispatcher_with_send(dispatcher): # incompatible signature: # def send(self, data: bytes) -> Optional[int]: ... -def compact_traceback() -> Tuple[Tuple[str, str, str], type, type, str]: ... +def compact_traceback() -> tuple[tuple[str, str, str], type, type, str]: ... def close_all(map: _maptype | None = ..., ignore_all: bool = ...) -> None: ... if sys.platform != "win32": @@ -113,6 +113,7 @@ if sys.platform != "win32": def write(self, data: bytes, flags: int = ...) -> int: ... def close(self) -> None: ... def fileno(self) -> int: ... + class file_dispatcher(dispatcher): def __init__(self, fd: FileDescriptorLike, map: _maptype | None = ...) -> None: ... def set_file(self, fd: int) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/audioop.pyi b/mypy/typeshed/stdlib/@python2/audioop.pyi index 71671afe487eb..b08731b85b0ba 100644 --- a/mypy/typeshed/stdlib/@python2/audioop.pyi +++ b/mypy/typeshed/stdlib/@python2/audioop.pyi @@ -1,12 +1,10 @@ -from typing import Tuple - -AdpcmState = Tuple[int, int] -RatecvState = Tuple[int, Tuple[Tuple[int, int], ...]] +AdpcmState = tuple[int, int] +RatecvState = tuple[int, tuple[tuple[int, int], ...]] class error(Exception): ... def add(__fragment1: bytes, __fragment2: bytes, __width: int) -> bytes: ... -def adpcm2lin(__fragment: bytes, __width: int, __state: AdpcmState | None) -> Tuple[bytes, AdpcmState]: ... +def adpcm2lin(__fragment: bytes, __width: int, __state: AdpcmState | None) -> tuple[bytes, AdpcmState]: ... def alaw2lin(__fragment: bytes, __width: int) -> bytes: ... def avg(__fragment: bytes, __width: int) -> int: ... def avgpp(__fragment: bytes, __width: int) -> int: ... @@ -14,16 +12,16 @@ def bias(__fragment: bytes, __width: int, __bias: int) -> bytes: ... def byteswap(__fragment: bytes, __width: int) -> bytes: ... def cross(__fragment: bytes, __width: int) -> int: ... def findfactor(__fragment: bytes, __reference: bytes) -> float: ... -def findfit(__fragment: bytes, __reference: bytes) -> Tuple[int, float]: ... +def findfit(__fragment: bytes, __reference: bytes) -> tuple[int, float]: ... def findmax(__fragment: bytes, __length: int) -> int: ... def getsample(__fragment: bytes, __width: int, __index: int) -> int: ... -def lin2adpcm(__fragment: bytes, __width: int, __state: AdpcmState | None) -> Tuple[bytes, AdpcmState]: ... +def lin2adpcm(__fragment: bytes, __width: int, __state: AdpcmState | None) -> tuple[bytes, AdpcmState]: ... def lin2alaw(__fragment: bytes, __width: int) -> bytes: ... def lin2lin(__fragment: bytes, __width: int, __newwidth: int) -> bytes: ... def lin2ulaw(__fragment: bytes, __width: int) -> bytes: ... def max(__fragment: bytes, __width: int) -> int: ... def maxpp(__fragment: bytes, __width: int) -> int: ... -def minmax(__fragment: bytes, __width: int) -> Tuple[int, int]: ... +def minmax(__fragment: bytes, __width: int) -> tuple[int, int]: ... def mul(__fragment: bytes, __width: int, __factor: float) -> bytes: ... def ratecv( __fragment: bytes, @@ -34,7 +32,7 @@ def ratecv( __state: RatecvState | None, __weightA: int = ..., __weightB: int = ..., -) -> Tuple[bytes, RatecvState]: ... +) -> tuple[bytes, RatecvState]: ... def reverse(__fragment: bytes, __width: int) -> bytes: ... def rms(__fragment: bytes, __width: int) -> int: ... def tomono(__fragment: bytes, __width: int, __lfactor: float, __rfactor: float) -> bytes: ... diff --git a/mypy/typeshed/stdlib/@python2/base64.pyi b/mypy/typeshed/stdlib/@python2/base64.pyi index 00856aafddbe7..4a32006ea98be 100644 --- a/mypy/typeshed/stdlib/@python2/base64.pyi +++ b/mypy/typeshed/stdlib/@python2/base64.pyi @@ -1,7 +1,7 @@ -from typing import IO, Union +from typing import IO -_encodable = Union[bytes, unicode] -_decodable = Union[bytes, unicode] +_encodable = bytes | unicode +_decodable = bytes | unicode def b64encode(s: _encodable, altchars: bytes | None = ...) -> bytes: ... def b64decode(s: _decodable, altchars: bytes | None = ..., validate: bool = ...) -> bytes: ... diff --git a/mypy/typeshed/stdlib/@python2/bdb.pyi b/mypy/typeshed/stdlib/@python2/bdb.pyi index 5bee9dadb9284..ec2fe4956b6c5 100644 --- a/mypy/typeshed/stdlib/@python2/bdb.pyi +++ b/mypy/typeshed/stdlib/@python2/bdb.pyi @@ -1,19 +1,21 @@ from types import CodeType, FrameType, TracebackType -from typing import IO, Any, Callable, Dict, Iterable, List, Mapping, Set, SupportsInt, Tuple, Type, TypeVar +from typing import IO, Any, Callable, Iterable, Mapping, SupportsInt, TypeVar +from typing_extensions import ParamSpec _T = TypeVar("_T") +_P = ParamSpec("_P") _TraceDispatch = Callable[[FrameType, str, Any], Any] # TODO: Recursive type -_ExcInfo = Tuple[Type[BaseException], BaseException, FrameType] +_ExcInfo = tuple[type[BaseException], BaseException, FrameType] -GENERATOR_AND_COROUTINE_FLAGS: int = ... +GENERATOR_AND_COROUTINE_FLAGS: int class BdbQuit(Exception): ... class Bdb: - skip: Set[str] | None - breaks: Dict[str, List[int]] - fncache: Dict[str, str] + skip: set[str] | None + breaks: dict[str, list[int]] + fncache: dict[str, str] frame_returning: FrameType | None botframe: FrameType | None quitting: bool @@ -53,21 +55,21 @@ class Bdb: def clear_all_breaks(self) -> None: ... def get_bpbynumber(self, arg: SupportsInt) -> Breakpoint: ... def get_break(self, filename: str, lineno: int) -> bool: ... - def get_breaks(self, filename: str, lineno: int) -> List[Breakpoint]: ... - def get_file_breaks(self, filename: str) -> List[Breakpoint]: ... - def get_all_breaks(self) -> List[Breakpoint]: ... - def get_stack(self, f: FrameType | None, t: TracebackType | None) -> Tuple[List[Tuple[FrameType, int]], int]: ... + def get_breaks(self, filename: str, lineno: int) -> list[Breakpoint]: ... + def get_file_breaks(self, filename: str) -> list[Breakpoint]: ... + def get_all_breaks(self) -> list[Breakpoint]: ... + def get_stack(self, f: FrameType | None, t: TracebackType | None) -> tuple[list[tuple[FrameType, int]], int]: ... def format_stack_entry(self, frame_lineno: int, lprefix: str = ...) -> str: ... - def run(self, cmd: str | CodeType, globals: Dict[str, Any] | None = ..., locals: Mapping[str, Any] | None = ...) -> None: ... - def runeval(self, expr: str, globals: Dict[str, Any] | None = ..., locals: Mapping[str, Any] | None = ...) -> None: ... - def runctx(self, cmd: str | CodeType, globals: Dict[str, Any] | None, locals: Mapping[str, Any] | None) -> None: ... - def runcall(self, __func: Callable[..., _T], *args: Any, **kwds: Any) -> _T | None: ... + def run(self, cmd: str | CodeType, globals: dict[str, Any] | None = ..., locals: Mapping[str, Any] | None = ...) -> None: ... + def runeval(self, expr: str, globals: dict[str, Any] | None = ..., locals: Mapping[str, Any] | None = ...) -> None: ... + def runctx(self, cmd: str | CodeType, globals: dict[str, Any] | None, locals: Mapping[str, Any] | None) -> None: ... + def runcall(self, __func: Callable[_P, _T], *args: _P.args, **kwds: _P.kwargs) -> _T | None: ... class Breakpoint: next: int = ... - bplist: Dict[Tuple[str, int], List[Breakpoint]] = ... - bpbynumber: List[Breakpoint | None] = ... + bplist: dict[tuple[str, int], list[Breakpoint]] = ... + bpbynumber: list[Breakpoint | None] = ... funcname: str | None func_first_executable_line: int | None @@ -87,8 +89,7 @@ class Breakpoint: def disable(self) -> None: ... def bpprint(self, out: IO[str] | None = ...) -> None: ... def bpformat(self) -> str: ... - def __str__(self) -> str: ... def checkfuncname(b: Breakpoint, frame: FrameType) -> bool: ... -def effective(file: str, line: int, frame: FrameType) -> Tuple[Breakpoint, bool] | Tuple[None, None]: ... +def effective(file: str, line: int, frame: FrameType) -> tuple[Breakpoint, bool] | tuple[None, None]: ... def set_trace() -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/binhex.pyi b/mypy/typeshed/stdlib/@python2/binhex.pyi index 02d094faf9232..10a5a3ee56330 100644 --- a/mypy/typeshed/stdlib/@python2/binhex.pyi +++ b/mypy/typeshed/stdlib/@python2/binhex.pyi @@ -1,4 +1,4 @@ -from typing import IO, Any, Tuple, Union +from typing import IO, Any class Error(Exception): ... @@ -12,8 +12,8 @@ class FInfo: Creator: str Flags: int -_FileInfoTuple = Tuple[str, FInfo, int, int] -_FileHandleUnion = Union[str, IO[bytes]] +_FileInfoTuple = tuple[str, FInfo, int, int] +_FileHandleUnion = str | IO[bytes] def getfileinfo(name: str) -> _FileInfoTuple: ... diff --git a/mypy/typeshed/stdlib/@python2/builtins.pyi b/mypy/typeshed/stdlib/@python2/builtins.pyi index fad8b2b4e7d8e..d936e08b82660 100644 --- a/mypy/typeshed/stdlib/@python2/builtins.pyi +++ b/mypy/typeshed/stdlib/@python2/builtins.pyi @@ -1,7 +1,7 @@ # True and False are deliberately omitted because they are keywords in # Python 3, and stub files conform to Python 3 syntax. -from _typeshed import ReadableBuffer, SupportsKeysAndGetItem, SupportsWrite +from _typeshed import ReadableBuffer, Self, SupportsKeysAndGetItem, SupportsWrite from abc import ABCMeta from ast import mod from types import CodeType @@ -12,15 +12,13 @@ from typing import ( BinaryIO, ByteString, Callable, + ClassVar, Container, - Dict, - FrozenSet, Generic, ItemsView, Iterable, Iterator, KeysView, - List, Mapping, MutableMapping, MutableSequence, @@ -29,15 +27,12 @@ from typing import ( Protocol, Reversible, Sequence, - Set, Sized, SupportsAbs, SupportsComplex, SupportsFloat, SupportsInt, Text, - Tuple, - Type, TypeVar, ValuesView, overload, @@ -60,70 +55,68 @@ _T2 = TypeVar("_T2") _T3 = TypeVar("_T3") _T4 = TypeVar("_T4") _T5 = TypeVar("_T5") -_TT = TypeVar("_TT", bound="type") -_TBE = TypeVar("_TBE", bound="BaseException") +_TT = TypeVar("_TT", bound=type) class object: __doc__: str | None - __dict__: Dict[str, Any] - __slots__: Text | Iterable[Text] + __dict__: dict[str, Any] __module__: str @property - def __class__(self: _T) -> Type[_T]: ... + def __class__(self: _T) -> type[_T]: ... @__class__.setter - def __class__(self, __type: Type[object]) -> None: ... # noqa: F811 + def __class__(self, __type: type[object]) -> None: ... # noqa: F811 def __init__(self) -> None: ... def __new__(cls) -> Any: ... def __setattr__(self, name: str, value: Any) -> None: ... def __eq__(self, o: object) -> bool: ... def __ne__(self, o: object) -> bool: ... - def __str__(self) -> str: ... - def __repr__(self) -> str: ... + def __str__(self) -> str: ... # noqa: Y029 + def __repr__(self) -> str: ... # noqa: Y029 def __hash__(self) -> int: ... def __format__(self, format_spec: str) -> str: ... def __getattribute__(self, name: str) -> Any: ... def __delattr__(self, name: str) -> None: ... def __sizeof__(self) -> int: ... - def __reduce__(self) -> str | Tuple[Any, ...]: ... - def __reduce_ex__(self, protocol: int) -> str | Tuple[Any, ...]: ... + def __reduce__(self) -> str | tuple[Any, ...]: ... + def __reduce_ex__(self, protocol: int) -> str | tuple[Any, ...]: ... class staticmethod(object): # Special, only valid as a decorator. __func__: Callable[..., Any] def __init__(self, f: Callable[..., Any]) -> None: ... - def __new__(cls: Type[_T], *args: Any, **kwargs: Any) -> _T: ... - def __get__(self, obj: _T, type: Type[_T] | None = ...) -> Callable[..., Any]: ... + def __new__(cls: type[Self], *args: Any, **kwargs: Any) -> Self: ... + def __get__(self, obj: _T, type: type[_T] | None = ...) -> Callable[..., Any]: ... class classmethod(object): # Special, only valid as a decorator. __func__: Callable[..., Any] def __init__(self, f: Callable[..., Any]) -> None: ... - def __new__(cls: Type[_T], *args: Any, **kwargs: Any) -> _T: ... - def __get__(self, obj: _T, type: Type[_T] | None = ...) -> Callable[..., Any]: ... + def __new__(cls: type[Self], *args: Any, **kwargs: Any) -> Self: ... + def __get__(self, obj: _T, type: type[_T] | None = ...) -> Callable[..., Any]: ... class type(object): __base__: type - __bases__: Tuple[type, ...] + __bases__: tuple[type, ...] __basicsize__: int - __dict__: Dict[str, Any] + __dict__: dict[str, Any] __dictoffset__: int __flags__: int __itemsize__: int __module__: str - __mro__: Tuple[type, ...] + __mro__: tuple[type, ...] __name__: str __weakrefoffset__: int @overload def __init__(self, o: object) -> None: ... @overload - def __init__(self, name: str, bases: Tuple[type, ...], dict: Dict[str, Any]) -> None: ... + def __init__(self, name: str, bases: tuple[type, ...], dict: dict[str, Any]) -> None: ... @overload def __new__(cls, o: object) -> type: ... @overload - def __new__(cls, name: str, bases: Tuple[type, ...], namespace: Dict[str, Any]) -> type: ... + def __new__(cls, name: str, bases: tuple[type, ...], namespace: dict[str, Any]) -> type: ... def __call__(self, *args: Any, **kwds: Any) -> Any: ... - def __subclasses__(self: _TT) -> List[_TT]: ... + def __subclasses__(self: _TT) -> list[_TT]: ... # Note: the documentation doesn't specify what the return type is, the standard # implementation seems to be returning a list. - def mro(self) -> List[type]: ... + def mro(self) -> list[type]: ... def __instancecheck__(self, instance: Any) -> bool: ... def __subclasscheck__(self, subclass: type) -> bool: ... @@ -135,9 +128,9 @@ class super(object): class int: @overload - def __new__(cls: Type[_T], x: Text | bytes | SupportsInt | _SupportsIndex | _SupportsTrunc = ...) -> _T: ... + def __new__(cls: type[Self], x: Text | bytes | SupportsInt | _SupportsIndex | _SupportsTrunc = ...) -> Self: ... @overload - def __new__(cls: Type[_T], x: Text | bytes | bytearray, base: int) -> _T: ... + def __new__(cls: type[Self], x: Text | bytes | bytearray, base: int) -> Self: ... @property def real(self) -> int: ... @property @@ -155,7 +148,7 @@ class int: def __div__(self, x: int) -> int: ... def __truediv__(self, x: int) -> float: ... def __mod__(self, x: int) -> int: ... - def __divmod__(self, x: int) -> Tuple[int, int]: ... + def __divmod__(self, x: int) -> tuple[int, int]: ... def __radd__(self, x: int) -> int: ... def __rsub__(self, x: int) -> int: ... def __rmul__(self, x: int) -> int: ... @@ -163,7 +156,7 @@ class int: def __rdiv__(self, x: int) -> int: ... def __rtruediv__(self, x: int) -> float: ... def __rmod__(self, x: int) -> int: ... - def __rdivmod__(self, x: int) -> Tuple[int, int]: ... + def __rdivmod__(self, x: int) -> tuple[int, int]: ... @overload def __pow__(self, __x: Literal[2], __modulo: int | None = ...) -> int: ... @overload @@ -183,14 +176,13 @@ class int: def __pos__(self) -> int: ... def __invert__(self) -> int: ... def __trunc__(self) -> int: ... - def __getnewargs__(self) -> Tuple[int]: ... + def __getnewargs__(self) -> tuple[int]: ... def __eq__(self, x: object) -> bool: ... def __ne__(self, x: object) -> bool: ... def __lt__(self, x: int) -> bool: ... def __le__(self, x: int) -> bool: ... def __gt__(self, x: int) -> bool: ... def __ge__(self, x: int) -> bool: ... - def __str__(self) -> str: ... def __float__(self) -> float: ... def __int__(self) -> int: ... def __abs__(self) -> int: ... @@ -199,8 +191,8 @@ class int: def __index__(self) -> int: ... class float: - def __new__(cls: Type[_T], x: SupportsFloat | _SupportsIndex | Text | bytes | bytearray = ...) -> _T: ... - def as_integer_ratio(self) -> Tuple[int, int]: ... + def __new__(cls: type[Self], x: SupportsFloat | _SupportsIndex | Text | bytes | bytearray = ...) -> Self: ... + def as_integer_ratio(self) -> tuple[int, int]: ... def hex(self) -> str: ... def is_integer(self) -> bool: ... @classmethod @@ -217,7 +209,7 @@ class float: def __div__(self, x: float) -> float: ... def __truediv__(self, x: float) -> float: ... def __mod__(self, x: float) -> float: ... - def __divmod__(self, x: float) -> Tuple[float, float]: ... + def __divmod__(self, x: float) -> tuple[float, float]: ... def __pow__( self, x: float, mod: None = ... ) -> float: ... # In Python 3, returns complex if self is negative and x is not whole @@ -228,9 +220,9 @@ class float: def __rdiv__(self, x: float) -> float: ... def __rtruediv__(self, x: float) -> float: ... def __rmod__(self, x: float) -> float: ... - def __rdivmod__(self, x: float) -> Tuple[float, float]: ... + def __rdivmod__(self, x: float) -> tuple[float, float]: ... def __rpow__(self, x: float, mod: None = ...) -> float: ... - def __getnewargs__(self) -> Tuple[float]: ... + def __getnewargs__(self) -> tuple[float]: ... def __trunc__(self) -> int: ... def __eq__(self, x: object) -> bool: ... def __ne__(self, x: object) -> bool: ... @@ -240,7 +232,6 @@ class float: def __ge__(self, x: float) -> bool: ... def __neg__(self) -> float: ... def __pos__(self) -> float: ... - def __str__(self) -> str: ... def __int__(self) -> int: ... def __float__(self) -> float: ... def __abs__(self) -> float: ... @@ -249,9 +240,9 @@ class float: class complex: @overload - def __new__(cls: Type[_T], real: float = ..., imag: float = ...) -> _T: ... + def __new__(cls: type[Self], real: float = ..., imag: float = ...) -> Self: ... @overload - def __new__(cls: Type[_T], real: str | SupportsComplex | _SupportsIndex) -> _T: ... + def __new__(cls: type[Self], real: str | SupportsComplex | _SupportsIndex) -> Self: ... @property def real(self) -> float: ... @property @@ -273,7 +264,6 @@ class complex: def __ne__(self, x: object) -> bool: ... def __neg__(self) -> complex: ... def __pos__(self) -> complex: ... - def __str__(self) -> str: ... def __complex__(self) -> complex: ... def __abs__(self) -> float: ... def __hash__(self) -> int: ... @@ -293,7 +283,7 @@ class unicode(basestring, Sequence[unicode]): def count(self, x: unicode) -> int: ... def decode(self, encoding: unicode = ..., errors: unicode = ...) -> unicode: ... def encode(self, encoding: unicode = ..., errors: unicode = ...) -> str: ... - def endswith(self, __suffix: unicode | Tuple[unicode, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... + def endswith(self, __suffix: unicode | tuple[unicode, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... def expandtabs(self, tabsize: int = ...) -> unicode: ... def find(self, sub: unicode, start: int = ..., end: int = ...) -> int: ... def format(self, *args: object, **kwargs: object) -> unicode: ... @@ -313,21 +303,21 @@ class unicode(basestring, Sequence[unicode]): def ljust(self, width: int, fillchar: unicode = ...) -> unicode: ... def lower(self) -> unicode: ... def lstrip(self, chars: unicode = ...) -> unicode: ... - def partition(self, sep: unicode) -> Tuple[unicode, unicode, unicode]: ... + def partition(self, sep: unicode) -> tuple[unicode, unicode, unicode]: ... def replace(self, old: unicode, new: unicode, count: int = ...) -> unicode: ... def rfind(self, sub: unicode, start: int = ..., end: int = ...) -> int: ... def rindex(self, sub: unicode, start: int = ..., end: int = ...) -> int: ... def rjust(self, width: int, fillchar: unicode = ...) -> unicode: ... - def rpartition(self, sep: unicode) -> Tuple[unicode, unicode, unicode]: ... - def rsplit(self, sep: unicode | None = ..., maxsplit: int = ...) -> List[unicode]: ... + def rpartition(self, sep: unicode) -> tuple[unicode, unicode, unicode]: ... + def rsplit(self, sep: unicode | None = ..., maxsplit: int = ...) -> list[unicode]: ... def rstrip(self, chars: unicode = ...) -> unicode: ... - def split(self, sep: unicode | None = ..., maxsplit: int = ...) -> List[unicode]: ... - def splitlines(self, keepends: bool = ...) -> List[unicode]: ... - def startswith(self, __prefix: unicode | Tuple[unicode, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... + def split(self, sep: unicode | None = ..., maxsplit: int = ...) -> list[unicode]: ... + def splitlines(self, keepends: bool = ...) -> list[unicode]: ... + def startswith(self, __prefix: unicode | tuple[unicode, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... def strip(self, chars: unicode = ...) -> unicode: ... def swapcase(self) -> unicode: ... def title(self) -> unicode: ... - def translate(self, table: Dict[int, Any] | unicode) -> unicode: ... + def translate(self, table: dict[int, Any] | unicode) -> unicode: ... def upper(self) -> unicode: ... def zfill(self, width: int) -> unicode: ... @overload @@ -347,14 +337,12 @@ class unicode(basestring, Sequence[unicode]): def __ge__(self, x: unicode) -> bool: ... def __len__(self) -> int: ... # The argument type is incompatible with Sequence - def __contains__(self, s: unicode | bytes) -> bool: ... # type: ignore + def __contains__(self, s: unicode | bytes) -> bool: ... # type: ignore[override] def __iter__(self) -> Iterator[unicode]: ... - def __str__(self) -> str: ... - def __repr__(self) -> str: ... def __int__(self) -> int: ... def __float__(self) -> float: ... def __hash__(self) -> int: ... - def __getnewargs__(self) -> Tuple[unicode]: ... + def __getnewargs__(self) -> tuple[unicode]: ... class _FormatMapMapping(Protocol): def __getitem__(self, __key: str) -> Any: ... @@ -366,7 +354,7 @@ class str(Sequence[str], basestring): def count(self, x: Text, __start: int | None = ..., __end: int | None = ...) -> int: ... def decode(self, encoding: Text = ..., errors: Text = ...) -> unicode: ... def encode(self, encoding: Text = ..., errors: Text = ...) -> bytes: ... - def endswith(self, __suffix: Text | Tuple[Text, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... + def endswith(self, __suffix: Text | tuple[Text, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... def expandtabs(self, tabsize: int = ...) -> str: ... def find(self, sub: Text, __start: int | None = ..., __end: int | None = ...) -> int: ... def format(self, *args: object, **kwargs: object) -> str: ... @@ -387,35 +375,35 @@ class str(Sequence[str], basestring): @overload def lstrip(self, __chars: unicode) -> unicode: ... @overload - def partition(self, __sep: bytearray) -> Tuple[str, bytearray, str]: ... + def partition(self, __sep: bytearray) -> tuple[str, bytearray, str]: ... @overload - def partition(self, __sep: str) -> Tuple[str, str, str]: ... + def partition(self, __sep: str) -> tuple[str, str, str]: ... @overload - def partition(self, __sep: unicode) -> Tuple[unicode, unicode, unicode]: ... + def partition(self, __sep: unicode) -> tuple[unicode, unicode, unicode]: ... def replace(self, __old: AnyStr, __new: AnyStr, __count: int = ...) -> AnyStr: ... def rfind(self, sub: Text, __start: int | None = ..., __end: int | None = ...) -> int: ... def rindex(self, sub: Text, __start: int | None = ..., __end: int | None = ...) -> int: ... def rjust(self, __width: int, __fillchar: str = ...) -> str: ... @overload - def rpartition(self, __sep: bytearray) -> Tuple[str, bytearray, str]: ... + def rpartition(self, __sep: bytearray) -> tuple[str, bytearray, str]: ... @overload - def rpartition(self, __sep: str) -> Tuple[str, str, str]: ... + def rpartition(self, __sep: str) -> tuple[str, str, str]: ... @overload - def rpartition(self, __sep: unicode) -> Tuple[unicode, unicode, unicode]: ... + def rpartition(self, __sep: unicode) -> tuple[unicode, unicode, unicode]: ... @overload - def rsplit(self, sep: str | None = ..., maxsplit: int = ...) -> List[str]: ... + def rsplit(self, sep: str | None = ..., maxsplit: int = ...) -> list[str]: ... @overload - def rsplit(self, sep: unicode, maxsplit: int = ...) -> List[unicode]: ... + def rsplit(self, sep: unicode, maxsplit: int = ...) -> list[unicode]: ... @overload def rstrip(self, __chars: str = ...) -> str: ... @overload def rstrip(self, __chars: unicode) -> unicode: ... @overload - def split(self, sep: str | None = ..., maxsplit: int = ...) -> List[str]: ... + def split(self, sep: str | None = ..., maxsplit: int = ...) -> list[str]: ... @overload - def split(self, sep: unicode, maxsplit: int = ...) -> List[unicode]: ... - def splitlines(self, keepends: bool = ...) -> List[str]: ... - def startswith(self, __prefix: Text | Tuple[Text, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... + def split(self, sep: unicode, maxsplit: int = ...) -> list[unicode]: ... + def splitlines(self, keepends: bool = ...) -> list[str]: ... + def startswith(self, __prefix: Text | tuple[Text, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... @overload def strip(self, __chars: str = ...) -> str: ... @overload @@ -427,7 +415,7 @@ class str(Sequence[str], basestring): def zfill(self, __width: int) -> str: ... def __add__(self, s: AnyStr) -> AnyStr: ... # Incompatible with Sequence.__contains__ - def __contains__(self, o: str | Text) -> bool: ... # type: ignore + def __contains__(self, o: str | Text) -> bool: ... # type: ignore[override] def __eq__(self, x: object) -> bool: ... def __ge__(self, x: Text) -> bool: ... def __getitem__(self, i: int | slice) -> str: ... @@ -440,10 +428,8 @@ class str(Sequence[str], basestring): def __mod__(self, x: Any) -> str: ... def __mul__(self, n: int) -> str: ... def __ne__(self, x: object) -> bool: ... - def __repr__(self) -> str: ... def __rmul__(self, n: int) -> str: ... - def __str__(self) -> str: ... - def __getnewargs__(self) -> Tuple[str]: ... + def __getnewargs__(self) -> tuple[str]: ... def __getslice__(self, start: int, stop: int) -> str: ... def __float__(self) -> float: ... def __int__(self) -> int: ... @@ -465,7 +451,7 @@ class bytearray(MutableSequence[int], ByteString): def center(self, __width: int, __fillchar: bytes = ...) -> bytearray: ... def count(self, __sub: str) -> int: ... def decode(self, encoding: Text = ..., errors: Text = ...) -> str: ... - def endswith(self, __suffix: bytes | Tuple[bytes, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... + def endswith(self, __suffix: bytes | tuple[bytes, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... def expandtabs(self, tabsize: int = ...) -> bytearray: ... def extend(self, iterable: str | Iterable[int]) -> None: ... def find(self, __sub: str, __start: int = ..., __end: int = ...) -> int: ... @@ -482,17 +468,17 @@ class bytearray(MutableSequence[int], ByteString): def ljust(self, __width: int, __fillchar: str = ...) -> bytearray: ... def lower(self) -> bytearray: ... def lstrip(self, __bytes: bytes | None = ...) -> bytearray: ... - def partition(self, __sep: bytes) -> Tuple[bytearray, bytearray, bytearray]: ... + def partition(self, __sep: bytes) -> tuple[bytearray, bytearray, bytearray]: ... def replace(self, __old: bytes, __new: bytes, __count: int = ...) -> bytearray: ... def rfind(self, __sub: bytes, __start: int = ..., __end: int = ...) -> int: ... def rindex(self, __sub: bytes, __start: int = ..., __end: int = ...) -> int: ... def rjust(self, __width: int, __fillchar: bytes = ...) -> bytearray: ... - def rpartition(self, __sep: bytes) -> Tuple[bytearray, bytearray, bytearray]: ... - def rsplit(self, sep: bytes | None = ..., maxsplit: int = ...) -> List[bytearray]: ... + def rpartition(self, __sep: bytes) -> tuple[bytearray, bytearray, bytearray]: ... + def rsplit(self, sep: bytes | None = ..., maxsplit: int = ...) -> list[bytearray]: ... def rstrip(self, __bytes: bytes | None = ...) -> bytearray: ... - def split(self, sep: bytes | None = ..., maxsplit: int = ...) -> List[bytearray]: ... - def splitlines(self, keepends: bool = ...) -> List[bytearray]: ... - def startswith(self, __prefix: bytes | Tuple[bytes, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... + def split(self, sep: bytes | None = ..., maxsplit: int = ...) -> list[bytearray]: ... + def splitlines(self, keepends: bool = ...) -> list[bytearray]: ... + def startswith(self, __prefix: bytes | tuple[bytes, ...], __start: int | None = ..., __end: int | None = ...) -> bool: ... def strip(self, __bytes: bytes | None = ...) -> bytearray: ... def swapcase(self) -> bytearray: ... def title(self) -> bytearray: ... @@ -503,11 +489,9 @@ class bytearray(MutableSequence[int], ByteString): def fromhex(cls, __string: str) -> bytearray: ... def __len__(self) -> int: ... def __iter__(self) -> Iterator[int]: ... - def __str__(self) -> str: ... - def __repr__(self) -> str: ... def __int__(self) -> int: ... def __float__(self) -> float: ... - __hash__: None # type: ignore + __hash__: ClassVar[None] # type: ignore[assignment] @overload def __getitem__(self, i: int) -> int: ... @overload @@ -523,7 +507,7 @@ class bytearray(MutableSequence[int], ByteString): def __add__(self, s: bytes) -> bytearray: ... def __mul__(self, n: int) -> bytearray: ... # Incompatible with Sequence.__contains__ - def __contains__(self, o: int | bytes) -> bool: ... # type: ignore + def __contains__(self, o: int | bytes) -> bool: ... # type: ignore[override] def __eq__(self, x: object) -> bool: ... def __ne__(self, x: object) -> bool: ... def __lt__(self, x: bytes) -> bool: ... @@ -534,9 +518,9 @@ class bytearray(MutableSequence[int], ByteString): class memoryview(Sized, Container[str]): format: str itemsize: int - shape: Tuple[int, ...] | None - strides: Tuple[int, ...] | None - suboffsets: Tuple[int, ...] | None + shape: tuple[int, ...] | None + strides: tuple[int, ...] | None + suboffsets: tuple[int, ...] | None readonly: bool ndim: int def __init__(self, obj: ReadableBuffer) -> None: ... @@ -552,11 +536,11 @@ class memoryview(Sized, Container[str]): @overload def __setitem__(self, i: int, o: int) -> None: ... def tobytes(self) -> bytes: ... - def tolist(self) -> List[int]: ... + def tolist(self) -> list[int]: ... @final class bool(int): - def __new__(cls: Type[_T], __o: object = ...) -> _T: ... + def __new__(cls: type[Self], __o: object = ...) -> Self: ... @overload def __and__(self, x: bool) -> bool: ... @overload @@ -581,7 +565,7 @@ class bool(int): def __rxor__(self, x: bool) -> bool: ... @overload def __rxor__(self, x: int) -> int: ... - def __getnewargs__(self) -> Tuple[int]: ... + def __getnewargs__(self) -> tuple[int]: ... class slice(object): start: Any @@ -591,28 +575,28 @@ class slice(object): def __init__(self, stop: Any) -> None: ... @overload def __init__(self, start: Any, stop: Any, step: Any = ...) -> None: ... - __hash__: None # type: ignore - def indices(self, len: int) -> Tuple[int, int, int]: ... + __hash__: ClassVar[None] # type: ignore[assignment] + def indices(self, len: int) -> tuple[int, int, int]: ... class tuple(Sequence[_T_co], Generic[_T_co]): - def __new__(cls: Type[_T], iterable: Iterable[_T_co] = ...) -> _T: ... + def __new__(cls: type[Self], iterable: Iterable[_T_co] = ...) -> Self: ... def __len__(self) -> int: ... def __contains__(self, x: object) -> bool: ... @overload def __getitem__(self, x: int) -> _T_co: ... @overload - def __getitem__(self, x: slice) -> Tuple[_T_co, ...]: ... + def __getitem__(self, x: slice) -> tuple[_T_co, ...]: ... def __iter__(self) -> Iterator[_T_co]: ... - def __lt__(self, x: Tuple[_T_co, ...]) -> bool: ... - def __le__(self, x: Tuple[_T_co, ...]) -> bool: ... - def __gt__(self, x: Tuple[_T_co, ...]) -> bool: ... - def __ge__(self, x: Tuple[_T_co, ...]) -> bool: ... + def __lt__(self, x: tuple[_T_co, ...]) -> bool: ... + def __le__(self, x: tuple[_T_co, ...]) -> bool: ... + def __gt__(self, x: tuple[_T_co, ...]) -> bool: ... + def __ge__(self, x: tuple[_T_co, ...]) -> bool: ... @overload - def __add__(self, x: Tuple[_T_co, ...]) -> Tuple[_T_co, ...]: ... + def __add__(self, x: tuple[_T_co, ...]) -> tuple[_T_co, ...]: ... @overload - def __add__(self, x: Tuple[Any, ...]) -> Tuple[Any, ...]: ... - def __mul__(self, n: int) -> Tuple[_T_co, ...]: ... - def __rmul__(self, n: int) -> Tuple[_T_co, ...]: ... + def __add__(self, x: tuple[Any, ...]) -> tuple[Any, ...]: ... + def __mul__(self, n: int) -> tuple[_T_co, ...]: ... + def __rmul__(self, n: int) -> tuple[_T_co, ...]: ... def count(self, __value: Any) -> int: ... def index(self, __value: Any) -> int: ... @@ -638,30 +622,29 @@ class list(MutableSequence[_T], Generic[_T]): def sort(self, cmp: Callable[[_T, _T], Any] = ..., key: Callable[[_T], Any] = ..., reverse: bool = ...) -> None: ... def __len__(self) -> int: ... def __iter__(self) -> Iterator[_T]: ... - def __str__(self) -> str: ... - __hash__: None # type: ignore + __hash__: ClassVar[None] # type: ignore[assignment] @overload def __getitem__(self, i: int) -> _T: ... @overload - def __getitem__(self, s: slice) -> List[_T]: ... + def __getitem__(self, s: slice) -> list[_T]: ... @overload def __setitem__(self, i: int, o: _T) -> None: ... @overload def __setitem__(self, s: slice, o: Iterable[_T]) -> None: ... def __delitem__(self, i: int | slice) -> None: ... - def __getslice__(self, start: int, stop: int) -> List[_T]: ... + def __getslice__(self, start: int, stop: int) -> list[_T]: ... def __setslice__(self, start: int, stop: int, o: Sequence[_T]) -> None: ... def __delslice__(self, start: int, stop: int) -> None: ... - def __add__(self, x: List[_T]) -> List[_T]: ... - def __iadd__(self: _S, x: Iterable[_T]) -> _S: ... - def __mul__(self, n: int) -> List[_T]: ... - def __rmul__(self, n: int) -> List[_T]: ... + def __add__(self, x: list[_T]) -> list[_T]: ... + def __iadd__(self: Self, x: Iterable[_T]) -> Self: ... + def __mul__(self, n: int) -> list[_T]: ... + def __rmul__(self, n: int) -> list[_T]: ... def __contains__(self, o: object) -> bool: ... def __reversed__(self) -> Iterator[_T]: ... - def __gt__(self, x: List[_T]) -> bool: ... - def __ge__(self, x: List[_T]) -> bool: ... - def __lt__(self, x: List[_T]) -> bool: ... - def __le__(self, x: List[_T]) -> bool: ... + def __gt__(self, x: list[_T]) -> bool: ... + def __ge__(self, x: list[_T]) -> bool: ... + def __lt__(self, x: list[_T]) -> bool: ... + def __le__(self, x: list[_T]) -> bool: ... class dict(MutableMapping[_KT, _VT], Generic[_KT, _VT]): # NOTE: Keyword arguments are special. If they are used, _KT must include @@ -671,109 +654,106 @@ class dict(MutableMapping[_KT, _VT], Generic[_KT, _VT]): @overload def __init__(self, map: SupportsKeysAndGetItem[_KT, _VT], **kwargs: _VT) -> None: ... @overload - def __init__(self, iterable: Iterable[Tuple[_KT, _VT]], **kwargs: _VT) -> None: ... - def __new__(cls: Type[_T1], *args: Any, **kwargs: Any) -> _T1: ... + def __init__(self, iterable: Iterable[tuple[_KT, _VT]], **kwargs: _VT) -> None: ... + def __new__(cls: type[Self], *args: Any, **kwargs: Any) -> Self: ... def has_key(self, k: _KT) -> bool: ... def clear(self) -> None: ... - def copy(self) -> Dict[_KT, _VT]: ... - def popitem(self) -> Tuple[_KT, _VT]: ... + def copy(self) -> dict[_KT, _VT]: ... + def popitem(self) -> tuple[_KT, _VT]: ... def setdefault(self, __key: _KT, __default: _VT = ...) -> _VT: ... @overload def update(self, __m: Mapping[_KT, _VT], **kwargs: _VT) -> None: ... @overload - def update(self, __m: Iterable[Tuple[_KT, _VT]], **kwargs: _VT) -> None: ... + def update(self, __m: Iterable[tuple[_KT, _VT]], **kwargs: _VT) -> None: ... @overload def update(self, **kwargs: _VT) -> None: ... def iterkeys(self) -> Iterator[_KT]: ... def itervalues(self) -> Iterator[_VT]: ... - def iteritems(self) -> Iterator[Tuple[_KT, _VT]]: ... + def iteritems(self) -> Iterator[tuple[_KT, _VT]]: ... def viewkeys(self) -> KeysView[_KT]: ... def viewvalues(self) -> ValuesView[_VT]: ... def viewitems(self) -> ItemsView[_KT, _VT]: ... @classmethod @overload - def fromkeys(cls, __iterable: Iterable[_T]) -> Dict[_T, Any]: ... + def fromkeys(cls, __iterable: Iterable[_T]) -> dict[_T, Any]: ... @classmethod @overload - def fromkeys(cls, __iterable: Iterable[_T], __value: _S) -> Dict[_T, _S]: ... + def fromkeys(cls, __iterable: Iterable[_T], __value: _S) -> dict[_T, _S]: ... def __len__(self) -> int: ... def __getitem__(self, k: _KT) -> _VT: ... def __setitem__(self, k: _KT, v: _VT) -> None: ... def __delitem__(self, v: _KT) -> None: ... def __iter__(self) -> Iterator[_KT]: ... - def __str__(self) -> str: ... - __hash__: None # type: ignore + __hash__: ClassVar[None] # type: ignore[assignment] class set(MutableSet[_T], Generic[_T]): def __init__(self, iterable: Iterable[_T] = ...) -> None: ... def add(self, element: _T) -> None: ... def clear(self) -> None: ... - def copy(self) -> Set[_T]: ... - def difference(self, *s: Iterable[Any]) -> Set[_T]: ... + def copy(self) -> set[_T]: ... + def difference(self, *s: Iterable[Any]) -> set[_T]: ... def difference_update(self, *s: Iterable[Any]) -> None: ... def discard(self, element: _T) -> None: ... - def intersection(self, *s: Iterable[Any]) -> Set[_T]: ... + def intersection(self, *s: Iterable[Any]) -> set[_T]: ... def intersection_update(self, *s: Iterable[Any]) -> None: ... def isdisjoint(self, s: Iterable[Any]) -> bool: ... def issubset(self, s: Iterable[Any]) -> bool: ... def issuperset(self, s: Iterable[Any]) -> bool: ... def pop(self) -> _T: ... def remove(self, element: _T) -> None: ... - def symmetric_difference(self, s: Iterable[_T]) -> Set[_T]: ... + def symmetric_difference(self, s: Iterable[_T]) -> set[_T]: ... def symmetric_difference_update(self, s: Iterable[_T]) -> None: ... - def union(self, *s: Iterable[_T]) -> Set[_T]: ... + def union(self, *s: Iterable[_T]) -> set[_T]: ... def update(self, *s: Iterable[_T]) -> None: ... def __len__(self) -> int: ... def __contains__(self, o: object) -> bool: ... def __iter__(self) -> Iterator[_T]: ... - def __str__(self) -> str: ... - def __and__(self, s: AbstractSet[object]) -> Set[_T]: ... - def __iand__(self, s: AbstractSet[object]) -> Set[_T]: ... - def __or__(self, s: AbstractSet[_S]) -> Set[_T | _S]: ... - def __ior__(self, s: AbstractSet[_S]) -> Set[_T | _S]: ... + def __and__(self, s: AbstractSet[object]) -> set[_T]: ... + def __iand__(self: Self, s: AbstractSet[object]) -> Self: ... + def __or__(self, s: AbstractSet[_S]) -> set[_T | _S]: ... + def __ior__(self: Self, s: AbstractSet[_T]) -> Self: ... @overload - def __sub__(self: Set[str], s: AbstractSet[Text | None]) -> Set[_T]: ... + def __sub__(self: set[str], s: AbstractSet[Text | None]) -> set[_T]: ... @overload - def __sub__(self, s: AbstractSet[_T | None]) -> Set[_T]: ... + def __sub__(self, s: AbstractSet[_T | None]) -> set[_T]: ... @overload # type: ignore - def __isub__(self: Set[str], s: AbstractSet[Text | None]) -> Set[_T]: ... + def __isub__(self: set[str], s: AbstractSet[Text | None]) -> set[_T]: ... @overload - def __isub__(self, s: AbstractSet[_T | None]) -> Set[_T]: ... - def __xor__(self, s: AbstractSet[_S]) -> Set[_T | _S]: ... - def __ixor__(self, s: AbstractSet[_S]) -> Set[_T | _S]: ... + def __isub__(self, s: AbstractSet[_T | None]) -> set[_T]: ... + def __xor__(self, s: AbstractSet[_S]) -> set[_T | _S]: ... + def __ixor__(self: Self, s: AbstractSet[_T]) -> Self: ... def __le__(self, s: AbstractSet[object]) -> bool: ... def __lt__(self, s: AbstractSet[object]) -> bool: ... def __ge__(self, s: AbstractSet[object]) -> bool: ... def __gt__(self, s: AbstractSet[object]) -> bool: ... - __hash__: None # type: ignore + __hash__: ClassVar[None] # type: ignore[assignment] class frozenset(AbstractSet[_T_co], Generic[_T_co]): def __init__(self, iterable: Iterable[_T_co] = ...) -> None: ... - def copy(self) -> FrozenSet[_T_co]: ... - def difference(self, *s: Iterable[object]) -> FrozenSet[_T_co]: ... - def intersection(self, *s: Iterable[object]) -> FrozenSet[_T_co]: ... + def copy(self) -> frozenset[_T_co]: ... + def difference(self, *s: Iterable[object]) -> frozenset[_T_co]: ... + def intersection(self, *s: Iterable[object]) -> frozenset[_T_co]: ... def isdisjoint(self, s: Iterable[_T_co]) -> bool: ... def issubset(self, s: Iterable[object]) -> bool: ... def issuperset(self, s: Iterable[object]) -> bool: ... - def symmetric_difference(self, s: Iterable[_T_co]) -> FrozenSet[_T_co]: ... - def union(self, *s: Iterable[_T_co]) -> FrozenSet[_T_co]: ... + def symmetric_difference(self, s: Iterable[_T_co]) -> frozenset[_T_co]: ... + def union(self, *s: Iterable[_T_co]) -> frozenset[_T_co]: ... def __len__(self) -> int: ... def __contains__(self, o: object) -> bool: ... def __iter__(self) -> Iterator[_T_co]: ... - def __str__(self) -> str: ... - def __and__(self, s: AbstractSet[_T_co]) -> FrozenSet[_T_co]: ... - def __or__(self, s: AbstractSet[_S]) -> FrozenSet[_T_co | _S]: ... - def __sub__(self, s: AbstractSet[_T_co]) -> FrozenSet[_T_co]: ... - def __xor__(self, s: AbstractSet[_S]) -> FrozenSet[_T_co | _S]: ... + def __and__(self, s: AbstractSet[_T_co]) -> frozenset[_T_co]: ... + def __or__(self, s: AbstractSet[_S]) -> frozenset[_T_co | _S]: ... + def __sub__(self, s: AbstractSet[_T_co]) -> frozenset[_T_co]: ... + def __xor__(self, s: AbstractSet[_S]) -> frozenset[_T_co | _S]: ... def __le__(self, s: AbstractSet[object]) -> bool: ... def __lt__(self, s: AbstractSet[object]) -> bool: ... def __ge__(self, s: AbstractSet[object]) -> bool: ... def __gt__(self, s: AbstractSet[object]) -> bool: ... -class enumerate(Iterator[Tuple[int, _T]], Generic[_T]): +class enumerate(Iterator[tuple[int, _T]], Generic[_T]): def __init__(self, iterable: Iterable[_T], start: int = ...) -> None: ... - def __iter__(self) -> Iterator[Tuple[int, _T]]: ... - def next(self) -> Tuple[int, _T]: ... + def __iter__(self: Self) -> Self: ... + def next(self) -> tuple[int, _T]: ... class xrange(Sized, Iterable[int], Reversible[int]): @overload @@ -805,10 +785,10 @@ class property(object): long = int -class _NotImplementedType(Any): # type: ignore +class _NotImplementedType(Any): # type: ignore[misc] # A little weird, but typing the __call__ as NotImplemented makes the error message # for NotImplemented() much better - __call__: NotImplemented # type: ignore + __call__: NotImplemented # type: ignore[valid-type] NotImplemented: _NotImplementedType @@ -823,29 +803,29 @@ def cmp(__x: Any, __y: Any) -> int: ... _N1 = TypeVar("_N1", bool, int, float, complex) -def coerce(__x: _N1, __y: _N1) -> Tuple[_N1, _N1]: ... +def coerce(__x: _N1, __y: _N1) -> tuple[_N1, _N1]: ... def compile(source: Text | mod, filename: Text, mode: Text, flags: int = ..., dont_inherit: int = ...) -> Any: ... def delattr(__obj: Any, __name: Text) -> None: ... -def dir(__o: object = ...) -> List[str]: ... +def dir(__o: object = ...) -> list[str]: ... _N2 = TypeVar("_N2", int, float) -def divmod(__x: _N2, __y: _N2) -> Tuple[_N2, _N2]: ... +def divmod(__x: _N2, __y: _N2) -> tuple[_N2, _N2]: ... def eval( - __source: Text | bytes | CodeType, __globals: Dict[str, Any] | None = ..., __locals: Mapping[str, Any] | None = ... + __source: Text | bytes | CodeType, __globals: dict[str, Any] | None = ..., __locals: Mapping[str, Any] | None = ... ) -> Any: ... -def execfile(__filename: str, __globals: Dict[str, Any] | None = ..., __locals: Dict[str, Any] | None = ...) -> None: ... +def execfile(__filename: str, __globals: dict[str, Any] | None = ..., __locals: dict[str, Any] | None = ...) -> None: ... def exit(code: object = ...) -> NoReturn: ... @overload def filter(__function: Callable[[AnyStr], Any], __iterable: AnyStr) -> AnyStr: ... # type: ignore @overload -def filter(__function: None, __iterable: Tuple[_T | None, ...]) -> Tuple[_T, ...]: ... # type: ignore +def filter(__function: None, __iterable: tuple[_T | None, ...]) -> tuple[_T, ...]: ... # type: ignore @overload -def filter(__function: Callable[[_T], Any], __iterable: Tuple[_T, ...]) -> Tuple[_T, ...]: ... # type: ignore +def filter(__function: Callable[[_T], Any], __iterable: tuple[_T, ...]) -> tuple[_T, ...]: ... # type: ignore @overload -def filter(__function: None, __iterable: Iterable[_T | None]) -> List[_T]: ... +def filter(__function: None, __iterable: Iterable[_T | None]) -> list[_T]: ... @overload -def filter(__function: Callable[[_T], Any], __iterable: Iterable[_T]) -> List[_T]: ... +def filter(__function: Callable[[_T], Any], __iterable: Iterable[_T]) -> list[_T]: ... def format(__value: object, __format_spec: str = ...) -> str: ... # TODO unicode @overload def getattr(__o: Any, name: Text) -> Any: ... @@ -863,7 +843,7 @@ def getattr(__o: object, name: str, __default: list[Any]) -> Any | list[Any]: .. def getattr(__o: object, name: str, __default: dict[Any, Any]) -> Any | dict[Any, Any]: ... @overload def getattr(__o: Any, name: Text, __default: _T) -> Any | _T: ... -def globals() -> Dict[str, Any]: ... +def globals() -> dict[str, Any]: ... def hasattr(__obj: Any, __name: Text) -> bool: ... def hash(__obj: object) -> int: ... def hex(__number: int | _SupportsIndex) -> str: ... @@ -876,20 +856,20 @@ def iter(__iterable: Iterable[_T]) -> Iterator[_T]: ... def iter(__function: Callable[[], _T | None], __sentinel: None) -> Iterator[_T]: ... @overload def iter(__function: Callable[[], _T], __sentinel: Any) -> Iterator[_T]: ... -def isinstance(__obj: object, __class_or_tuple: type | Tuple[type | Tuple[Any, ...], ...]) -> bool: ... -def issubclass(__cls: type, __class_or_tuple: type | Tuple[type | Tuple[Any, ...], ...]) -> bool: ... +def isinstance(__obj: object, __class_or_tuple: type | tuple[type | tuple[Any, ...], ...]) -> bool: ... +def issubclass(__cls: type, __class_or_tuple: type | tuple[type | tuple[Any, ...], ...]) -> bool: ... def len(__obj: Sized) -> int: ... -def locals() -> Dict[str, Any]: ... +def locals() -> dict[str, Any]: ... @overload -def map(__func: None, __iter1: Iterable[_T1]) -> List[_T1]: ... +def map(__func: None, __iter1: Iterable[_T1]) -> list[_T1]: ... @overload -def map(__func: None, __iter1: Iterable[_T1], __iter2: Iterable[_T2]) -> List[Tuple[_T1, _T2]]: ... +def map(__func: None, __iter1: Iterable[_T1], __iter2: Iterable[_T2]) -> list[tuple[_T1, _T2]]: ... @overload -def map(__func: None, __iter1: Iterable[_T1], __iter2: Iterable[_T2], __iter3: Iterable[_T3]) -> List[Tuple[_T1, _T2, _T3]]: ... +def map(__func: None, __iter1: Iterable[_T1], __iter2: Iterable[_T2], __iter3: Iterable[_T3]) -> list[tuple[_T1, _T2, _T3]]: ... @overload def map( __func: None, __iter1: Iterable[_T1], __iter2: Iterable[_T2], __iter3: Iterable[_T3], __iter4: Iterable[_T4] -) -> List[Tuple[_T1, _T2, _T3, _T4]]: ... +) -> list[tuple[_T1, _T2, _T3, _T4]]: ... @overload def map( __func: None, @@ -898,7 +878,7 @@ def map( __iter3: Iterable[_T3], __iter4: Iterable[_T4], __iter5: Iterable[_T5], -) -> List[Tuple[_T1, _T2, _T3, _T4, _T5]]: ... +) -> list[tuple[_T1, _T2, _T3, _T4, _T5]]: ... @overload def map( __func: None, @@ -909,15 +889,15 @@ def map( __iter5: Iterable[Any], __iter6: Iterable[Any], *iterables: Iterable[Any], -) -> List[Tuple[Any, ...]]: ... +) -> list[tuple[Any, ...]]: ... @overload -def map(__func: Callable[[_T1], _S], __iter1: Iterable[_T1]) -> List[_S]: ... +def map(__func: Callable[[_T1], _S], __iter1: Iterable[_T1]) -> list[_S]: ... @overload -def map(__func: Callable[[_T1, _T2], _S], __iter1: Iterable[_T1], __iter2: Iterable[_T2]) -> List[_S]: ... +def map(__func: Callable[[_T1, _T2], _S], __iter1: Iterable[_T1], __iter2: Iterable[_T2]) -> list[_S]: ... @overload def map( __func: Callable[[_T1, _T2, _T3], _S], __iter1: Iterable[_T1], __iter2: Iterable[_T2], __iter3: Iterable[_T3] -) -> List[_S]: ... +) -> list[_S]: ... @overload def map( __func: Callable[[_T1, _T2, _T3, _T4], _S], @@ -925,7 +905,7 @@ def map( __iter2: Iterable[_T2], __iter3: Iterable[_T3], __iter4: Iterable[_T4], -) -> List[_S]: ... +) -> list[_S]: ... @overload def map( __func: Callable[[_T1, _T2, _T3, _T4, _T5], _S], @@ -934,7 +914,7 @@ def map( __iter3: Iterable[_T3], __iter4: Iterable[_T4], __iter5: Iterable[_T5], -) -> List[_S]: ... +) -> list[_S]: ... @overload def map( __func: Callable[..., _S], @@ -945,7 +925,7 @@ def map( __iter5: Iterable[Any], __iter6: Iterable[Any], *iterables: Iterable[Any], -) -> List[_S]: ... +) -> list[_S]: ... @overload def max(__arg1: _T, __arg2: _T, *_args: _T, key: Callable[[_T], Any] = ...) -> _T: ... @overload @@ -985,7 +965,7 @@ def pow(__base: _SupportsPow2[_E, _T_co], __exp: _E) -> _T_co: ... @overload def pow(__base: _SupportsPow3[_E, _M, _T_co], __exp: _E, __mod: _M) -> _T_co: ... def quit(code: object = ...) -> NoReturn: ... -def range(__x: int, __y: int = ..., __step: int = ...) -> List[int]: ... # noqa: F811 +def range(__x: int, __y: int = ..., __step: int = ...) -> list[int]: ... def raw_input(__prompt: Any = ...) -> str: ... @overload def reduce(__function: Callable[[_T, _S], _T], __iterable: Iterable[_S], __initializer: _T) -> _T: ... @@ -1008,27 +988,27 @@ def round(number: SupportsFloat, ndigits: int) -> float: ... def setattr(__obj: Any, __name: Text, __value: Any) -> None: ... def sorted( __iterable: Iterable[_T], *, cmp: Callable[[_T, _T], int] = ..., key: Callable[[_T], Any] | None = ..., reverse: bool = ... -) -> List[_T]: ... +) -> list[_T]: ... @overload def sum(__iterable: Iterable[_T]) -> _T | int: ... @overload def sum(__iterable: Iterable[_T], __start: _S) -> _T | _S: ... def unichr(__i: int) -> unicode: ... -def vars(__object: Any = ...) -> Dict[str, Any]: ... +def vars(__object: Any = ...) -> dict[str, Any]: ... @overload -def zip(__iter1: Iterable[_T1]) -> List[Tuple[_T1]]: ... +def zip(__iter1: Iterable[_T1]) -> list[tuple[_T1]]: ... @overload -def zip(__iter1: Iterable[_T1], __iter2: Iterable[_T2]) -> List[Tuple[_T1, _T2]]: ... +def zip(__iter1: Iterable[_T1], __iter2: Iterable[_T2]) -> list[tuple[_T1, _T2]]: ... @overload -def zip(__iter1: Iterable[_T1], __iter2: Iterable[_T2], __iter3: Iterable[_T3]) -> List[Tuple[_T1, _T2, _T3]]: ... +def zip(__iter1: Iterable[_T1], __iter2: Iterable[_T2], __iter3: Iterable[_T3]) -> list[tuple[_T1, _T2, _T3]]: ... @overload def zip( __iter1: Iterable[_T1], __iter2: Iterable[_T2], __iter3: Iterable[_T3], __iter4: Iterable[_T4] -) -> List[Tuple[_T1, _T2, _T3, _T4]]: ... +) -> list[tuple[_T1, _T2, _T3, _T4]]: ... @overload def zip( __iter1: Iterable[_T1], __iter2: Iterable[_T2], __iter3: Iterable[_T3], __iter4: Iterable[_T4], __iter5: Iterable[_T5] -) -> List[Tuple[_T1, _T2, _T3, _T4, _T5]]: ... +) -> list[tuple[_T1, _T2, _T3, _T4, _T5]]: ... @overload def zip( __iter1: Iterable[Any], @@ -1038,7 +1018,7 @@ def zip( __iter5: Iterable[Any], __iter6: Iterable[Any], *iterables: Iterable[Any], -) -> List[Tuple[Any, ...]]: ... +) -> list[tuple[Any, ...]]: ... def __import__( name: Text, globals: Mapping[str, Any] | None = ..., @@ -1066,13 +1046,11 @@ class buffer(Sized): def __mul__(self, x: int) -> str: ... class BaseException(object): - args: Tuple[Any, ...] + args: tuple[Any, ...] message: Any def __init__(self, *args: object) -> None: ... - def __str__(self) -> str: ... - def __repr__(self) -> str: ... def __getitem__(self, i: int) -> Any: ... - def __getslice__(self, start: int, stop: int) -> Tuple[Any, ...]: ... + def __getslice__(self, start: int, stop: int) -> tuple[Any, ...]: ... class GeneratorExit(BaseException): ... class KeyboardInterrupt(BaseException): ... @@ -1181,7 +1159,7 @@ class file(BinaryIO): def seek(self, offset: int, whence: int = ...) -> int: ... def tell(self) -> int: ... def readline(self, limit: int = ...) -> str: ... - def readlines(self, hint: int = ...) -> List[str]: ... + def readlines(self, hint: int = ...) -> list[str]: ... def write(self, data: str) -> int: ... def writelines(self, data: Iterable[str]) -> None: ... def truncate(self, pos: int | None = ...) -> int: ... diff --git a/mypy/typeshed/stdlib/@python2/bz2.pyi b/mypy/typeshed/stdlib/@python2/bz2.pyi index 81ee6f6ce26a5..95377347cce8d 100644 --- a/mypy/typeshed/stdlib/@python2/bz2.pyi +++ b/mypy/typeshed/stdlib/@python2/bz2.pyi @@ -1,22 +1,21 @@ import io -from _typeshed import ReadableBuffer, WriteableBuffer -from typing import IO, Any, Iterable, List, Text, TypeVar, Union +from _typeshed import ReadableBuffer, Self, WriteableBuffer +from typing import IO, Any, Iterable, Text from typing_extensions import SupportsIndex -_PathOrFile = Union[Text, IO[bytes]] -_T = TypeVar("_T") +_PathOrFile = Text | IO[bytes] def compress(data: bytes, compresslevel: int = ...) -> bytes: ... def decompress(data: bytes) -> bytes: ... class BZ2File(io.BufferedIOBase, IO[bytes]): - def __enter__(self: _T) -> _T: ... + def __enter__(self: Self) -> Self: ... def __init__(self, filename: _PathOrFile, mode: str = ..., buffering: Any | None = ..., compresslevel: int = ...) -> None: ... def read(self, size: int | None = ...) -> bytes: ... def read1(self, size: int = ...) -> bytes: ... - def readline(self, size: SupportsIndex = ...) -> bytes: ... # type: ignore + def readline(self, size: SupportsIndex = ...) -> bytes: ... # type: ignore[override] def readinto(self, b: WriteableBuffer) -> int: ... - def readlines(self, size: SupportsIndex = ...) -> List[bytes]: ... + def readlines(self, size: SupportsIndex = ...) -> list[bytes]: ... def seek(self, offset: int, whence: int = ...) -> int: ... def write(self, data: ReadableBuffer) -> int: ... def writelines(self, seq: Iterable[ReadableBuffer]) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/cPickle.pyi b/mypy/typeshed/stdlib/@python2/cPickle.pyi index d8db140cdda13..9169a8df02b0c 100644 --- a/mypy/typeshed/stdlib/@python2/cPickle.pyi +++ b/mypy/typeshed/stdlib/@python2/cPickle.pyi @@ -1,7 +1,7 @@ -from typing import IO, Any, List +from typing import IO, Any HIGHEST_PROTOCOL: int -compatible_formats: List[str] +compatible_formats: list[str] format_version: str class Pickler: diff --git a/mypy/typeshed/stdlib/@python2/cProfile.pyi b/mypy/typeshed/stdlib/@python2/cProfile.pyi index 1257b0cc92eb1..40731e2f3d76f 100644 --- a/mypy/typeshed/stdlib/@python2/cProfile.pyi +++ b/mypy/typeshed/stdlib/@python2/cProfile.pyi @@ -1,14 +1,16 @@ +from _typeshed import Self from types import CodeType -from typing import Any, Callable, Dict, Text, Tuple, TypeVar +from typing import Any, Callable, Text, TypeVar +from typing_extensions import ParamSpec def run(statement: str, filename: str | None = ..., sort: str | int = ...) -> None: ... def runctx( - statement: str, globals: Dict[str, Any], locals: Dict[str, Any], filename: str | None = ..., sort: str | int = ... + statement: str, globals: dict[str, Any], locals: dict[str, Any], filename: str | None = ..., sort: str | int = ... ) -> None: ... -_SelfT = TypeVar("_SelfT", bound=Profile) _T = TypeVar("_T") -_Label = Tuple[str, int, str] +_P = ParamSpec("_P") +_Label = tuple[str, int, str] class Profile: stats: dict[_Label, tuple[int, int, int, int, dict[_Label, tuple[int, int, int, int]]]] # undocumented @@ -21,8 +23,8 @@ class Profile: def dump_stats(self, file: Text) -> None: ... def create_stats(self) -> None: ... def snapshot_stats(self) -> None: ... - def run(self: _SelfT, cmd: str) -> _SelfT: ... - def runctx(self: _SelfT, cmd: str, globals: Dict[str, Any], locals: Dict[str, Any]) -> _SelfT: ... - def runcall(self, __func: Callable[..., _T], *args: Any, **kw: Any) -> _T: ... + def run(self: Self, cmd: str) -> Self: ... + def runctx(self: Self, cmd: str, globals: dict[str, Any], locals: dict[str, Any]) -> Self: ... + def runcall(self, __func: Callable[_P, _T], *args: _P.args, **kw: _P.kwargs) -> _T: ... def label(code: str | CodeType) -> _Label: ... # undocumented diff --git a/mypy/typeshed/stdlib/@python2/cStringIO.pyi b/mypy/typeshed/stdlib/@python2/cStringIO.pyi index 7703e030c3324..33a20dd4a7393 100644 --- a/mypy/typeshed/stdlib/@python2/cStringIO.pyi +++ b/mypy/typeshed/stdlib/@python2/cStringIO.pyi @@ -1,5 +1,5 @@ from abc import ABCMeta -from typing import IO, Iterable, Iterator, List, overload +from typing import IO, Iterable, Iterator, overload # This class isn't actually abstract, but you can't instantiate it # directly, so we might as well treat it as abstract in the stub. @@ -12,7 +12,7 @@ class InputType(IO[str], Iterator[str], metaclass=ABCMeta): def isatty(self) -> bool: ... def read(self, size: int = ...) -> str: ... def readline(self, size: int = ...) -> str: ... - def readlines(self, hint: int = ...) -> List[str]: ... + def readlines(self, hint: int = ...) -> list[str]: ... def seek(self, offset: int, whence: int = ...) -> int: ... def tell(self) -> int: ... def truncate(self, size: int | None = ...) -> int: ... @@ -31,7 +31,7 @@ class OutputType(IO[str], Iterator[str], metaclass=ABCMeta): def isatty(self) -> bool: ... def read(self, size: int = ...) -> str: ... def readline(self, size: int = ...) -> str: ... - def readlines(self, hint: int = ...) -> List[str]: ... + def readlines(self, hint: int = ...) -> list[str]: ... def seek(self, offset: int, whence: int = ...) -> int: ... def tell(self) -> int: ... def truncate(self, size: int | None = ...) -> int: ... diff --git a/mypy/typeshed/stdlib/@python2/calendar.pyi b/mypy/typeshed/stdlib/@python2/calendar.pyi index ce765210dc1e8..f14b0735fa67d 100644 --- a/mypy/typeshed/stdlib/@python2/calendar.pyi +++ b/mypy/typeshed/stdlib/@python2/calendar.pyi @@ -1,21 +1,19 @@ import datetime from time import struct_time -from typing import Any, Iterable, List, Optional, Sequence, Tuple +from typing import Any, Iterable, Sequence -_LocaleType = Tuple[Optional[str], Optional[str]] +_LocaleType = tuple[str | None, str | None] class IllegalMonthError(ValueError): def __init__(self, month: int) -> None: ... - def __str__(self) -> str: ... class IllegalWeekdayError(ValueError): def __init__(self, weekday: int) -> None: ... - def __str__(self) -> str: ... def isleap(year: int) -> bool: ... def leapdays(y1: int, y2: int) -> int: ... def weekday(year: int, month: int, day: int) -> int: ... -def monthrange(year: int, month: int) -> Tuple[int, int]: ... +def monthrange(year: int, month: int) -> tuple[int, int]: ... class Calendar: firstweekday: int @@ -24,14 +22,14 @@ class Calendar: def setfirstweekday(self, firstweekday: int) -> None: ... def iterweekdays(self) -> Iterable[int]: ... def itermonthdates(self, year: int, month: int) -> Iterable[datetime.date]: ... - def itermonthdays2(self, year: int, month: int) -> Iterable[Tuple[int, int]]: ... + def itermonthdays2(self, year: int, month: int) -> Iterable[tuple[int, int]]: ... def itermonthdays(self, year: int, month: int) -> Iterable[int]: ... - def monthdatescalendar(self, year: int, month: int) -> List[List[datetime.date]]: ... - def monthdays2calendar(self, year: int, month: int) -> List[List[Tuple[int, int]]]: ... - def monthdayscalendar(self, year: int, month: int) -> List[List[int]]: ... - def yeardatescalendar(self, year: int, width: int = ...) -> List[List[int]]: ... - def yeardays2calendar(self, year: int, width: int = ...) -> List[List[Tuple[int, int]]]: ... - def yeardayscalendar(self, year: int, width: int = ...) -> List[List[int]]: ... + def monthdatescalendar(self, year: int, month: int) -> list[list[datetime.date]]: ... + def monthdays2calendar(self, year: int, month: int) -> list[list[tuple[int, int]]]: ... + def monthdayscalendar(self, year: int, month: int) -> list[list[int]]: ... + def yeardatescalendar(self, year: int, width: int = ...) -> list[list[int]]: ... + def yeardays2calendar(self, year: int, width: int = ...) -> list[list[tuple[int, int]]]: ... + def yeardayscalendar(self, year: int, width: int = ...) -> list[list[int]]: ... class TextCalendar(Calendar): def prweek(self, theweek: int, width: int) -> None: ... @@ -46,7 +44,7 @@ class TextCalendar(Calendar): def pryear(self, theyear: int, w: int = ..., l: int = ..., c: int = ..., m: int = ...) -> None: ... def firstweekday() -> int: ... -def monthcalendar(year: int, month: int) -> List[List[int]]: ... +def monthcalendar(year: int, month: int) -> list[list[int]]: ... def prweek(theweek: int, width: int) -> None: ... def week(theweek: int, width: int) -> str: ... def weekheader(width: int) -> str: ... @@ -85,7 +83,7 @@ c: TextCalendar def setfirstweekday(firstweekday: int) -> None: ... def format(cols: int, colwidth: int = ..., spacing: int = ...) -> str: ... def formatstring(cols: int, colwidth: int = ..., spacing: int = ...) -> str: ... -def timegm(tuple: Tuple[int, ...] | struct_time) -> int: ... +def timegm(tuple: tuple[int, ...] | struct_time) -> int: ... # Data attributes day_name: Sequence[str] diff --git a/mypy/typeshed/stdlib/@python2/cgi.pyi b/mypy/typeshed/stdlib/@python2/cgi.pyi index 674748242ebbf..6c83a9c27e55d 100644 --- a/mypy/typeshed/stdlib/@python2/cgi.pyi +++ b/mypy/typeshed/stdlib/@python2/cgi.pyi @@ -1,19 +1,17 @@ from _typeshed import SupportsGetItem, SupportsItemAccess -from builtins import type as _type -from typing import IO, Any, AnyStr, Iterable, Iterator, List, Mapping, Protocol, TypeVar +from builtins import list as List, type as _type # aliases to avoid name clashes with `FieldStorage` attributes +from typing import IO, Any, AnyStr, Iterable, Iterator, Mapping, Protocol from UserDict import UserDict -_T = TypeVar("_T", bound=FieldStorage) - def parse( fp: IO[Any] | None = ..., environ: SupportsItemAccess[str, str] = ..., keep_blank_values: bool = ..., strict_parsing: bool = ..., -) -> dict[str, List[str]]: ... -def parse_qs(qs: str, keep_blank_values: bool = ..., strict_parsing: bool = ...) -> dict[str, List[str]]: ... -def parse_qsl(qs: str, keep_blank_values: bool = ..., strict_parsing: bool = ...) -> List[tuple[str, str]]: ... -def parse_multipart(fp: IO[Any], pdict: SupportsGetItem[str, bytes]) -> dict[str, List[bytes]]: ... +) -> dict[str, list[str]]: ... +def parse_qs(qs: str, keep_blank_values: bool = ..., strict_parsing: bool = ...) -> dict[str, list[str]]: ... +def parse_qsl(qs: str, keep_blank_values: bool = ..., strict_parsing: bool = ...) -> list[tuple[str, str]]: ... +def parse_multipart(fp: IO[Any], pdict: SupportsGetItem[str, bytes]) -> dict[str, list[bytes]]: ... class _Environ(Protocol): def __getitem__(self, __k: str) -> str: ... @@ -40,7 +38,6 @@ class MiniFieldStorage: name: Any value: Any def __init__(self, name: Any, value: Any) -> None: ... - def __repr__(self) -> str: ... class FieldStorage(object): FieldStorageClass: _type | None @@ -74,7 +71,6 @@ class FieldStorage(object): keep_blank_values: int = ..., strict_parsing: int = ..., ) -> None: ... - def __repr__(self) -> str: ... def __iter__(self) -> Iterator[str]: ... def __getitem__(self, key: str) -> Any: ... def getvalue(self, key: str, default: Any = ...) -> Any: ... @@ -88,7 +84,7 @@ class FieldStorage(object): # In Python 2 it always returns bytes and ignores the "binary" flag def make_file(self, binary: Any = ...) -> IO[bytes]: ... -class FormContentDict(UserDict[str, List[str]]): +class FormContentDict(UserDict[str, list[str]]): query_string: str def __init__(self, environ: Mapping[str, str] = ..., keep_blank_values: int = ..., strict_parsing: int = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/cgitb.pyi b/mypy/typeshed/stdlib/@python2/cgitb.pyi index daa0233ee69ae..aff45db6198ca 100644 --- a/mypy/typeshed/stdlib/@python2/cgitb.pyi +++ b/mypy/typeshed/stdlib/@python2/cgitb.pyi @@ -1,16 +1,16 @@ from types import FrameType, TracebackType -from typing import IO, Any, Callable, Dict, List, Optional, Text, Tuple, Type +from typing import IO, Any, Callable, Optional, Text -_ExcInfo = Tuple[Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType]] +_ExcInfo = tuple[Optional[type[BaseException]], Optional[BaseException], Optional[TracebackType]] def reset() -> str: ... # undocumented def small(text: str) -> str: ... # undocumented def strong(text: str) -> str: ... # undocumented def grey(text: str) -> str: ... # undocumented -def lookup(name: str, frame: FrameType, locals: Dict[str, Any]) -> Tuple[str | None, Any]: ... # undocumented +def lookup(name: str, frame: FrameType, locals: dict[str, Any]) -> tuple[str | None, Any]: ... # undocumented def scanvars( - reader: Callable[[], bytes], frame: FrameType, locals: Dict[str, Any] -) -> List[Tuple[str, str | None, Any]]: ... # undocumented + reader: Callable[[], bytes], frame: FrameType, locals: dict[str, Any] +) -> list[tuple[str, str | None, Any]]: ... # undocumented def html(einfo: _ExcInfo, context: int = ...) -> str: ... def text(einfo: _ExcInfo, context: int = ...) -> str: ... @@ -18,7 +18,7 @@ class Hook: # undocumented def __init__( self, display: int = ..., logdir: Text | None = ..., context: int = ..., file: IO[str] | None = ..., format: str = ... ) -> None: ... - def __call__(self, etype: Type[BaseException] | None, evalue: BaseException | None, etb: TracebackType | None) -> None: ... + def __call__(self, etype: type[BaseException] | None, evalue: BaseException | None, etb: TracebackType | None) -> None: ... def handle(self, info: _ExcInfo | None = ...) -> None: ... def handler(info: _ExcInfo | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/cmath.pyi b/mypy/typeshed/stdlib/@python2/cmath.pyi index 1e19687b48852..1053b22698129 100644 --- a/mypy/typeshed/stdlib/@python2/cmath.pyi +++ b/mypy/typeshed/stdlib/@python2/cmath.pyi @@ -1,8 +1,8 @@ -from typing import SupportsComplex, SupportsFloat, Tuple, Union +from typing import SupportsComplex, SupportsFloat e: float pi: float -_C = Union[SupportsFloat, SupportsComplex, complex] +_C = SupportsFloat | SupportsComplex | complex def acos(__z: _C) -> complex: ... def acosh(__z: _C) -> complex: ... @@ -18,7 +18,7 @@ def isnan(__z: _C) -> bool: ... def log(__x: _C, __y_obj: _C = ...) -> complex: ... def log10(__z: _C) -> complex: ... def phase(__z: _C) -> float: ... -def polar(__z: _C) -> Tuple[float, float]: ... +def polar(__z: _C) -> tuple[float, float]: ... def rect(__r: float, __phi: float) -> complex: ... def sin(__z: _C) -> complex: ... def sinh(__z: _C) -> complex: ... diff --git a/mypy/typeshed/stdlib/@python2/cmd.pyi b/mypy/typeshed/stdlib/@python2/cmd.pyi index ffccba84ec163..f6d818591a4ea 100644 --- a/mypy/typeshed/stdlib/@python2/cmd.pyi +++ b/mypy/typeshed/stdlib/@python2/cmd.pyi @@ -1,4 +1,4 @@ -from typing import IO, Any, Callable, List, Tuple +from typing import IO, Any, Callable class Cmd: prompt: str @@ -14,7 +14,7 @@ class Cmd: use_rawinput: bool stdin: IO[str] stdout: IO[str] - cmdqueue: List[str] + cmdqueue: list[str] completekey: str def __init__(self, completekey: str = ..., stdin: IO[str] | None = ..., stdout: IO[str] | None = ...) -> None: ... old_completer: Callable[[str, int], str | None] | None @@ -23,17 +23,17 @@ class Cmd: def postcmd(self, stop: bool, line: str) -> bool: ... def preloop(self) -> None: ... def postloop(self) -> None: ... - def parseline(self, line: str) -> Tuple[str | None, str | None, str]: ... + def parseline(self, line: str) -> tuple[str | None, str | None, str]: ... def onecmd(self, line: str) -> bool: ... def emptyline(self) -> bool: ... def default(self, line: str) -> bool: ... - def completedefault(self, *ignored: Any) -> List[str]: ... - def completenames(self, text: str, *ignored: Any) -> List[str]: ... - completion_matches: List[str] | None - def complete(self, text: str, state: int) -> List[str] | None: ... - def get_names(self) -> List[str]: ... + def completedefault(self, *ignored: Any) -> list[str]: ... + def completenames(self, text: str, *ignored: Any) -> list[str]: ... + completion_matches: list[str] | None + def complete(self, text: str, state: int) -> list[str] | None: ... + def get_names(self) -> list[str]: ... # Only the first element of args matters. - def complete_help(self, *args: Any) -> List[str]: ... + def complete_help(self, *args: Any) -> list[str]: ... def do_help(self, arg: str) -> bool | None: ... - def print_topics(self, header: str, cmds: List[str] | None, cmdlen: Any, maxcol: int) -> None: ... - def columnize(self, list: List[str] | None, displaywidth: int = ...) -> None: ... + def print_topics(self, header: str, cmds: list[str] | None, cmdlen: Any, maxcol: int) -> None: ... + def columnize(self, list: list[str] | None, displaywidth: int = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/codecs.pyi b/mypy/typeshed/stdlib/@python2/codecs.pyi index a7835106336d4..9ed83567c148a 100644 --- a/mypy/typeshed/stdlib/@python2/codecs.pyi +++ b/mypy/typeshed/stdlib/@python2/codecs.pyi @@ -1,23 +1,7 @@ import types +from _typeshed import Self from abc import abstractmethod -from typing import ( - IO, - Any, - BinaryIO, - Callable, - Generator, - Iterable, - Iterator, - List, - Protocol, - Text, - TextIO, - Tuple, - Type, - TypeVar, - Union, - overload, -) +from typing import IO, Any, BinaryIO, Callable, Generator, Iterable, Iterator, Protocol, Text, TextIO, overload from typing_extensions import Literal # TODO: this only satisfies the most common interface, where @@ -30,10 +14,10 @@ _Decoded = Text _Encoded = bytes class _Encoder(Protocol): - def __call__(self, input: _Decoded, errors: str = ...) -> Tuple[_Encoded, int]: ... # signature of Codec().encode + def __call__(self, input: _Decoded, errors: str = ...) -> tuple[_Encoded, int]: ... # signature of Codec().encode class _Decoder(Protocol): - def __call__(self, input: _Encoded, errors: str = ...) -> Tuple[_Decoded, int]: ... # signature of Codec().decode + def __call__(self, input: _Encoded, errors: str = ...) -> tuple[_Decoded, int]: ... # signature of Codec().decode class _StreamReader(Protocol): def __call__(self, stream: IO[_Encoded], errors: str = ...) -> StreamReader: ... @@ -71,11 +55,11 @@ _BytesToBytesEncodingT = Literal[ @overload def encode(obj: bytes, encoding: _BytesToBytesEncodingT, errors: str = ...) -> bytes: ... @overload -def encode(obj: str, encoding: Literal["rot13", "rot_13"] = ..., errors: str = ...) -> str: ... # type: ignore +def encode(obj: str, encoding: Literal["rot13", "rot_13"] = ..., errors: str = ...) -> str: ... @overload def encode(obj: _Decoded, encoding: str = ..., errors: str = ...) -> _Encoded: ... @overload -def decode(obj: bytes, encoding: _BytesToBytesEncodingT, errors: str = ...) -> bytes: ... # type: ignore +def decode(obj: bytes, encoding: _BytesToBytesEncodingT, errors: str = ...) -> bytes: ... # type: ignore[misc] @overload def decode(obj: str, encoding: Literal["rot13", "rot_13"] = ..., errors: str = ...) -> Text: ... @overload @@ -83,10 +67,10 @@ def decode(obj: _Encoded, encoding: str = ..., errors: str = ...) -> _Decoded: . def lookup(__encoding: str) -> CodecInfo: ... def utf_16_be_decode( __data: _Encoded, __errors: str | None = ..., __final: bool = ... -) -> Tuple[_Decoded, int]: ... # undocumented -def utf_16_be_encode(__str: _Decoded, __errors: str | None = ...) -> Tuple[_Encoded, int]: ... # undocumented +) -> tuple[_Decoded, int]: ... # undocumented +def utf_16_be_encode(__str: _Decoded, __errors: str | None = ...) -> tuple[_Encoded, int]: ... # undocumented -class CodecInfo(Tuple[_Encoder, _Decoder, _StreamReader, _StreamWriter]): +class CodecInfo(tuple[_Encoder, _Decoder, _StreamReader, _StreamWriter]): @property def encode(self) -> _Encoder: ... @property @@ -101,7 +85,7 @@ class CodecInfo(Tuple[_Encoder, _Decoder, _StreamReader, _StreamWriter]): def incrementaldecoder(self) -> _IncrementalDecoder: ... name: str def __new__( - cls, + cls: type[Self], encode: _Encoder, decode: _Decoder, streamreader: _StreamReader | None = ..., @@ -111,7 +95,7 @@ class CodecInfo(Tuple[_Encoder, _Decoder, _StreamReader, _StreamWriter]): name: str | None = ..., *, _is_text_encoding: bool | None = ..., - ) -> CodecInfo: ... + ) -> Self: ... def getencoder(encoding: str) -> _Encoder: ... def getdecoder(encoding: str) -> _Decoder: ... @@ -141,19 +125,19 @@ BOM_UTF32_LE: bytes # It is expected that different actions be taken depending on which of the # three subclasses of `UnicodeError` is actually ...ed. However, the Union # is still needed for at least one of the cases. -def register_error(__errors: str, __handler: Callable[[UnicodeError], Tuple[str | bytes, int]]) -> None: ... -def lookup_error(__name: str) -> Callable[[UnicodeError], Tuple[str | bytes, int]]: ... -def strict_errors(exception: UnicodeError) -> Tuple[str | bytes, int]: ... -def replace_errors(exception: UnicodeError) -> Tuple[str | bytes, int]: ... -def ignore_errors(exception: UnicodeError) -> Tuple[str | bytes, int]: ... -def xmlcharrefreplace_errors(exception: UnicodeError) -> Tuple[str | bytes, int]: ... -def backslashreplace_errors(exception: UnicodeError) -> Tuple[str | bytes, int]: ... +def register_error(__errors: str, __handler: Callable[[UnicodeError], tuple[str | bytes, int]]) -> None: ... +def lookup_error(__name: str) -> Callable[[UnicodeError], tuple[str | bytes, int]]: ... +def strict_errors(exception: UnicodeError) -> tuple[str | bytes, int]: ... +def replace_errors(exception: UnicodeError) -> tuple[str | bytes, int]: ... +def ignore_errors(exception: UnicodeError) -> tuple[str | bytes, int]: ... +def xmlcharrefreplace_errors(exception: UnicodeError) -> tuple[str | bytes, int]: ... +def backslashreplace_errors(exception: UnicodeError) -> tuple[str | bytes, int]: ... class Codec: # These are sort of @abstractmethod but sort of not. # The StreamReader and StreamWriter subclasses only implement one. - def encode(self, input: _Decoded, errors: str = ...) -> Tuple[_Encoded, int]: ... - def decode(self, input: _Encoded, errors: str = ...) -> Tuple[_Decoded, int]: ... + def encode(self, input: _Decoded, errors: str = ...) -> tuple[_Encoded, int]: ... + def decode(self, input: _Encoded, errors: str = ...) -> tuple[_Decoded, int]: ... class IncrementalEncoder: errors: str @@ -171,8 +155,8 @@ class IncrementalDecoder: @abstractmethod def decode(self, input: _Encoded, final: bool = ...) -> _Decoded: ... def reset(self) -> None: ... - def getstate(self) -> Tuple[_Encoded, int]: ... - def setstate(self, state: Tuple[_Encoded, int]) -> None: ... + def getstate(self) -> tuple[_Encoded, int]: ... + def setstate(self, state: tuple[_Encoded, int]) -> None: ... # These are not documented but used in encodings/*.py implementations. class BufferedIncrementalEncoder(IncrementalEncoder): @@ -186,11 +170,9 @@ class BufferedIncrementalDecoder(IncrementalDecoder): buffer: bytes def __init__(self, errors: str = ...) -> None: ... @abstractmethod - def _buffer_decode(self, input: _Encoded, errors: str, final: bool) -> Tuple[_Decoded, int]: ... + def _buffer_decode(self, input: _Encoded, errors: str, final: bool) -> tuple[_Decoded, int]: ... def decode(self, input: _Encoded, final: bool = ...) -> _Decoded: ... -_SW = TypeVar("_SW", bound=StreamWriter) - # TODO: it is not possible to specify the requirement that all other # attributes and methods are passed-through from the stream. class StreamWriter(Codec): @@ -199,43 +181,39 @@ class StreamWriter(Codec): def write(self, object: _Decoded) -> None: ... def writelines(self, list: Iterable[_Decoded]) -> None: ... def reset(self) -> None: ... - def __enter__(self: _SW) -> _SW: ... - def __exit__(self, typ: Type[BaseException] | None, exc: BaseException | None, tb: types.TracebackType | None) -> None: ... + def __enter__(self: Self) -> Self: ... + def __exit__(self, typ: type[BaseException] | None, exc: BaseException | None, tb: types.TracebackType | None) -> None: ... def __getattr__(self, name: str, getattr: Callable[[str], Any] = ...) -> Any: ... -_SR = TypeVar("_SR", bound=StreamReader) - class StreamReader(Codec): errors: str def __init__(self, stream: IO[_Encoded], errors: str = ...) -> None: ... def read(self, size: int = ..., chars: int = ..., firstline: bool = ...) -> _Decoded: ... def readline(self, size: int | None = ..., keepends: bool = ...) -> _Decoded: ... - def readlines(self, sizehint: int | None = ..., keepends: bool = ...) -> List[_Decoded]: ... + def readlines(self, sizehint: int | None = ..., keepends: bool = ...) -> list[_Decoded]: ... def reset(self) -> None: ... - def __enter__(self: _SR) -> _SR: ... - def __exit__(self, typ: Type[BaseException] | None, exc: BaseException | None, tb: types.TracebackType | None) -> None: ... + def __enter__(self: Self) -> Self: ... + def __exit__(self, typ: type[BaseException] | None, exc: BaseException | None, tb: types.TracebackType | None) -> None: ... def __iter__(self) -> Iterator[_Decoded]: ... def __getattr__(self, name: str, getattr: Callable[[str], Any] = ...) -> Any: ... -_T = TypeVar("_T", bound=StreamReaderWriter) - # Doesn't actually inherit from TextIO, but wraps a BinaryIO to provide text reading and writing # and delegates attributes to the underlying binary stream with __getattr__. class StreamReaderWriter(TextIO): def __init__(self, stream: IO[_Encoded], Reader: _StreamReader, Writer: _StreamWriter, errors: str = ...) -> None: ... def read(self, size: int = ...) -> _Decoded: ... def readline(self, size: int | None = ...) -> _Decoded: ... - def readlines(self, sizehint: int | None = ...) -> List[_Decoded]: ... + def readlines(self, sizehint: int | None = ...) -> list[_Decoded]: ... def next(self) -> Text: ... - def __iter__(self: _T) -> _T: ... + def __iter__(self: Self) -> Self: ... # This actually returns None, but that's incompatible with the supertype def write(self, data: _Decoded) -> int: ... def writelines(self, list: Iterable[_Decoded]) -> None: ... def reset(self) -> None: ... # Same as write() def seek(self, offset: int, whence: int = ...) -> int: ... - def __enter__(self: _T) -> _T: ... - def __exit__(self, typ: Type[BaseException] | None, exc: BaseException | None, tb: types.TracebackType | None) -> None: ... + def __enter__(self: Self) -> Self: ... + def __exit__(self, typ: type[BaseException] | None, exc: BaseException | None, tb: types.TracebackType | None) -> None: ... def __getattr__(self, name: str) -> Any: ... # These methods don't actually exist directly, but they are needed to satisfy the TextIO # interface. At runtime, they are delegated through __getattr__. @@ -249,8 +227,6 @@ class StreamReaderWriter(TextIO): def tell(self) -> int: ... def writable(self) -> bool: ... -_SRT = TypeVar("_SRT", bound=StreamRecoder) - class StreamRecoder(BinaryIO): def __init__( self, @@ -263,15 +239,15 @@ class StreamRecoder(BinaryIO): ) -> None: ... def read(self, size: int = ...) -> bytes: ... def readline(self, size: int | None = ...) -> bytes: ... - def readlines(self, sizehint: int | None = ...) -> List[bytes]: ... + def readlines(self, sizehint: int | None = ...) -> list[bytes]: ... def next(self) -> bytes: ... - def __iter__(self: _SRT) -> _SRT: ... + def __iter__(self: Self) -> Self: ... def write(self, data: bytes) -> int: ... - def writelines(self, list: Iterable[bytes]) -> int: ... # type: ignore # it's supposed to return None + def writelines(self, list: Iterable[bytes]) -> int: ... # type: ignore[override] # it's supposed to return None def reset(self) -> None: ... def __getattr__(self, name: str) -> Any: ... - def __enter__(self: _SRT) -> _SRT: ... - def __exit__(self, type: Type[BaseException] | None, value: BaseException | None, tb: types.TracebackType | None) -> None: ... + def __enter__(self: Self) -> Self: ... + def __exit__(self, type: type[BaseException] | None, value: BaseException | None, tb: types.TracebackType | None) -> None: ... # These methods don't actually exist directly, but they are needed to satisfy the BinaryIO # interface. At runtime, they are delegated through __getattr__. def seek(self, offset: int, whence: int = ...) -> int: ... diff --git a/mypy/typeshed/stdlib/@python2/collections.pyi b/mypy/typeshed/stdlib/@python2/collections.pyi index 5a2f73aed7cec..e7a2e7d1793f9 100644 --- a/mypy/typeshed/stdlib/@python2/collections.pyi +++ b/mypy/typeshed/stdlib/@python2/collections.pyi @@ -1,16 +1,15 @@ +from _typeshed import Self from typing import ( AbstractSet, Any, Callable as Callable, Container as Container, - Dict, Generic, Hashable as Hashable, ItemsView as ItemsView, Iterable as Iterable, Iterator as Iterator, KeysView as KeysView, - List, Mapping as Mapping, MappingView as MappingView, MutableMapping as MutableMapping, @@ -19,8 +18,6 @@ from typing import ( Reversible, Sequence as Sequence, Sized as Sized, - Tuple, - Type, TypeVar, ValuesView as ValuesView, overload, @@ -28,7 +25,6 @@ from typing import ( Set = AbstractSet -_S = TypeVar("_S") _T = TypeVar("_T") _KT = TypeVar("_KT") _VT = TypeVar("_VT") @@ -36,7 +32,7 @@ _VT = TypeVar("_VT") # namedtuple is special-cased in the type checker; the initializer is ignored. def namedtuple( typename: str | unicode, field_names: str | unicode | Iterable[str | unicode], verbose: bool = ..., rename: bool = ... -) -> Type[Tuple[Any, ...]]: ... +) -> type[tuple[Any, ...]]: ... class deque(Sized, Iterable[_T], Reversible[_T], Generic[_T]): def __init__(self, iterable: Iterable[_T] = ..., maxlen: int = ...) -> None: ... @@ -55,24 +51,23 @@ class deque(Sized, Iterable[_T], Reversible[_T], Generic[_T]): def rotate(self, n: int = ...) -> None: ... def __len__(self) -> int: ... def __iter__(self) -> Iterator[_T]: ... - def __str__(self) -> str: ... def __hash__(self) -> int: ... def __getitem__(self, i: int) -> _T: ... def __setitem__(self, i: int, x: _T) -> None: ... def __contains__(self, o: _T) -> bool: ... def __reversed__(self) -> Iterator[_T]: ... - def __iadd__(self: _S, iterable: Iterable[_T]) -> _S: ... + def __iadd__(self: Self, iterable: Iterable[_T]) -> Self: ... -class Counter(Dict[_T, int], Generic[_T]): +class Counter(dict[_T, int], Generic[_T]): @overload def __init__(self, **kwargs: int) -> None: ... @overload def __init__(self, mapping: Mapping[_T, int]) -> None: ... @overload def __init__(self, iterable: Iterable[_T]) -> None: ... - def copy(self: _S) -> _S: ... + def copy(self: Self) -> Self: ... def elements(self) -> Iterator[_T]: ... - def most_common(self, n: int | None = ...) -> List[Tuple[_T, int]]: ... + def most_common(self, n: int | None = ...) -> list[tuple[_T, int]]: ... @overload def subtract(self, __mapping: Mapping[_T, int]) -> None: ... @overload @@ -85,24 +80,24 @@ class Counter(Dict[_T, int], Generic[_T]): @overload def update(self, __m: Mapping[_T, int], **kwargs: int) -> None: ... @overload - def update(self, __m: Iterable[_T] | Iterable[Tuple[_T, int]], **kwargs: int) -> None: ... + def update(self, __m: Iterable[_T] | Iterable[tuple[_T, int]], **kwargs: int) -> None: ... @overload def update(self, **kwargs: int) -> None: ... def __add__(self, other: Counter[_T]) -> Counter[_T]: ... def __sub__(self, other: Counter[_T]) -> Counter[_T]: ... def __and__(self, other: Counter[_T]) -> Counter[_T]: ... def __or__(self, other: Counter[_T]) -> Counter[_T]: ... - def __iadd__(self, other: Counter[_T]) -> Counter[_T]: ... - def __isub__(self, other: Counter[_T]) -> Counter[_T]: ... - def __iand__(self, other: Counter[_T]) -> Counter[_T]: ... - def __ior__(self, other: Counter[_T]) -> Counter[_T]: ... + def __iadd__(self: Self, other: Counter[_T]) -> Self: ... + def __isub__(self: Self, other: Counter[_T]) -> Self: ... + def __iand__(self: Self, other: Counter[_T]) -> Self: ... + def __ior__(self: Self, other: Counter[_T]) -> Self: ... -class OrderedDict(Dict[_KT, _VT], Reversible[_KT], Generic[_KT, _VT]): - def popitem(self, last: bool = ...) -> Tuple[_KT, _VT]: ... - def copy(self: _S) -> _S: ... +class OrderedDict(dict[_KT, _VT], Reversible[_KT], Generic[_KT, _VT]): + def popitem(self, last: bool = ...) -> tuple[_KT, _VT]: ... + def copy(self: Self) -> Self: ... def __reversed__(self) -> Iterator[_KT]: ... -class defaultdict(Dict[_KT, _VT], Generic[_KT, _VT]): +class defaultdict(dict[_KT, _VT], Generic[_KT, _VT]): default_factory: Callable[[], _VT] @overload def __init__(self, **kwargs: _VT) -> None: ... @@ -115,8 +110,8 @@ class defaultdict(Dict[_KT, _VT], Generic[_KT, _VT]): @overload def __init__(self, default_factory: Callable[[], _VT] | None, map: Mapping[_KT, _VT], **kwargs: _VT) -> None: ... @overload - def __init__(self, default_factory: Callable[[], _VT] | None, iterable: Iterable[Tuple[_KT, _VT]]) -> None: ... + def __init__(self, default_factory: Callable[[], _VT] | None, iterable: Iterable[tuple[_KT, _VT]]) -> None: ... @overload - def __init__(self, default_factory: Callable[[], _VT] | None, iterable: Iterable[Tuple[_KT, _VT]], **kwargs: _VT) -> None: ... + def __init__(self, default_factory: Callable[[], _VT] | None, iterable: Iterable[tuple[_KT, _VT]], **kwargs: _VT) -> None: ... def __missing__(self, key: _KT) -> _VT: ... - def copy(self: _S) -> _S: ... + def copy(self: Self) -> Self: ... diff --git a/mypy/typeshed/stdlib/@python2/colorsys.pyi b/mypy/typeshed/stdlib/@python2/colorsys.pyi index 8db2e2c9ab3a3..00c5f9d22cb12 100644 --- a/mypy/typeshed/stdlib/@python2/colorsys.pyi +++ b/mypy/typeshed/stdlib/@python2/colorsys.pyi @@ -1,11 +1,9 @@ -from typing import Tuple - -def rgb_to_yiq(r: float, g: float, b: float) -> Tuple[float, float, float]: ... -def yiq_to_rgb(y: float, i: float, q: float) -> Tuple[float, float, float]: ... -def rgb_to_hls(r: float, g: float, b: float) -> Tuple[float, float, float]: ... -def hls_to_rgb(h: float, l: float, s: float) -> Tuple[float, float, float]: ... -def rgb_to_hsv(r: float, g: float, b: float) -> Tuple[float, float, float]: ... -def hsv_to_rgb(h: float, s: float, v: float) -> Tuple[float, float, float]: ... +def rgb_to_yiq(r: float, g: float, b: float) -> tuple[float, float, float]: ... +def yiq_to_rgb(y: float, i: float, q: float) -> tuple[float, float, float]: ... +def rgb_to_hls(r: float, g: float, b: float) -> tuple[float, float, float]: ... +def hls_to_rgb(h: float, l: float, s: float) -> tuple[float, float, float]: ... +def rgb_to_hsv(r: float, g: float, b: float) -> tuple[float, float, float]: ... +def hsv_to_rgb(h: float, s: float, v: float) -> tuple[float, float, float]: ... # TODO undocumented ONE_SIXTH: float diff --git a/mypy/typeshed/stdlib/@python2/commands.pyi b/mypy/typeshed/stdlib/@python2/commands.pyi index 970d6ccf20325..2c36033583ec4 100644 --- a/mypy/typeshed/stdlib/@python2/commands.pyi +++ b/mypy/typeshed/stdlib/@python2/commands.pyi @@ -1,8 +1,8 @@ -from typing import AnyStr, Text, Tuple, overload +from typing import AnyStr, Text, overload def getstatus(file: Text) -> str: ... def getoutput(cmd: Text) -> str: ... -def getstatusoutput(cmd: Text) -> Tuple[int, str]: ... +def getstatusoutput(cmd: Text) -> tuple[int, str]: ... @overload def mk2arg(head: bytes, x: bytes) -> bytes: ... @overload diff --git a/mypy/typeshed/stdlib/@python2/contextlib.pyi b/mypy/typeshed/stdlib/@python2/contextlib.pyi index 6782fbf1874c2..4f39ba5dad5ec 100644 --- a/mypy/typeshed/stdlib/@python2/contextlib.pyi +++ b/mypy/typeshed/stdlib/@python2/contextlib.pyi @@ -1,18 +1,18 @@ from types import TracebackType -from typing import IO, Any, Callable, ContextManager, Iterable, Iterator, Optional, Protocol, Type, TypeVar +from typing import IO, Any, Callable, ContextManager, Iterable, Iterator, Protocol, TypeVar +from typing_extensions import ParamSpec _T = TypeVar("_T") _T_co = TypeVar("_T_co", covariant=True) -_T_io = TypeVar("_T_io", bound=Optional[IO[str]]) _F = TypeVar("_F", bound=Callable[..., Any]) +_P = ParamSpec("_P") -_ExitFunc = Callable[[Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType]], bool] -_CM_EF = TypeVar("_CM_EF", ContextManager[Any], _ExitFunc) +_ExitFunc = Callable[[type[BaseException] | None, BaseException | None, TracebackType | None], bool] class GeneratorContextManager(ContextManager[_T_co]): def __call__(self, func: _F) -> _F: ... -def contextmanager(func: Callable[..., Iterator[_T]]) -> Callable[..., ContextManager[_T]]: ... +def contextmanager(func: Callable[_P, Iterator[_T]]) -> Callable[_P, ContextManager[_T]]: ... def nested(*mgr: ContextManager[Any]) -> ContextManager[Iterable[Any]]: ... class _SupportsClose(Protocol): diff --git a/mypy/typeshed/stdlib/@python2/copy.pyi b/mypy/typeshed/stdlib/@python2/copy.pyi index c88f92846ddf0..a5f9420e3811a 100644 --- a/mypy/typeshed/stdlib/@python2/copy.pyi +++ b/mypy/typeshed/stdlib/@python2/copy.pyi @@ -1,4 +1,4 @@ -from typing import Any, Dict, TypeVar +from typing import Any, TypeVar _T = TypeVar("_T") @@ -6,7 +6,7 @@ _T = TypeVar("_T") PyStringMap: Any # Note: memo and _nil are internal kwargs. -def deepcopy(x: _T, memo: Dict[int, Any] | None = ..., _nil: Any = ...) -> _T: ... +def deepcopy(x: _T, memo: dict[int, Any] | None = ..., _nil: Any = ...) -> _T: ... def copy(x: _T) -> _T: ... class Error(Exception): ... diff --git a/mypy/typeshed/stdlib/@python2/copy_reg.pyi b/mypy/typeshed/stdlib/@python2/copy_reg.pyi index 91b099888babb..2fccfcbf2208e 100644 --- a/mypy/typeshed/stdlib/@python2/copy_reg.pyi +++ b/mypy/typeshed/stdlib/@python2/copy_reg.pyi @@ -1,9 +1,9 @@ -from typing import Any, Callable, Hashable, List, Optional, SupportsInt, Tuple, TypeVar, Union +from typing import Any, Callable, Hashable, SupportsInt, TypeVar, Union _TypeT = TypeVar("_TypeT", bound=type) -_Reduce = Union[Tuple[Callable[..., _TypeT], Tuple[Any, ...]], Tuple[Callable[..., _TypeT], Tuple[Any, ...], Optional[Any]]] +_Reduce = Union[tuple[Callable[..., _TypeT], tuple[Any, ...]], tuple[Callable[..., _TypeT], tuple[Any, ...], Any | None]] -__all__: List[str] +__all__ = ["pickle", "constructor", "add_extension", "remove_extension", "clear_extension_cache"] def pickle( ob_type: _TypeT, diff --git a/mypy/typeshed/stdlib/@python2/copyreg.pyi b/mypy/typeshed/stdlib/@python2/copyreg.pyi index 91b099888babb..2fccfcbf2208e 100644 --- a/mypy/typeshed/stdlib/@python2/copyreg.pyi +++ b/mypy/typeshed/stdlib/@python2/copyreg.pyi @@ -1,9 +1,9 @@ -from typing import Any, Callable, Hashable, List, Optional, SupportsInt, Tuple, TypeVar, Union +from typing import Any, Callable, Hashable, SupportsInt, TypeVar, Union _TypeT = TypeVar("_TypeT", bound=type) -_Reduce = Union[Tuple[Callable[..., _TypeT], Tuple[Any, ...]], Tuple[Callable[..., _TypeT], Tuple[Any, ...], Optional[Any]]] +_Reduce = Union[tuple[Callable[..., _TypeT], tuple[Any, ...]], tuple[Callable[..., _TypeT], tuple[Any, ...], Any | None]] -__all__: List[str] +__all__ = ["pickle", "constructor", "add_extension", "remove_extension", "clear_extension_cache"] def pickle( ob_type: _TypeT, diff --git a/mypy/typeshed/stdlib/@python2/csv.pyi b/mypy/typeshed/stdlib/@python2/csv.pyi index 886de6210ca9e..a52db42291af9 100644 --- a/mypy/typeshed/stdlib/@python2/csv.pyi +++ b/mypy/typeshed/stdlib/@python2/csv.pyi @@ -16,20 +16,8 @@ from _csv import ( unregister_dialect as unregister_dialect, writer as writer, ) -from typing import ( - Any, - Dict as _DictReadMapping, - Generic, - Iterable, - Iterator, - List, - Mapping, - Sequence, - Text, - Type, - TypeVar, - overload, -) +from builtins import dict as _DictReadMapping +from typing import Any, Generic, Iterable, Iterator, Mapping, Sequence, Text, TypeVar, overload _T = TypeVar("_T") @@ -96,7 +84,7 @@ class DictWriter(Generic[_T]): def writerows(self, rowdicts: Iterable[Mapping[_T, Any]]) -> None: ... class Sniffer(object): - preferred: List[str] + preferred: list[str] def __init__(self) -> None: ... - def sniff(self, sample: str, delimiters: str | None = ...) -> Type[Dialect]: ... + def sniff(self, sample: str, delimiters: str | None = ...) -> type[Dialect]: ... def has_header(self, sample: str) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/ctypes/__init__.pyi b/mypy/typeshed/stdlib/@python2/ctypes/__init__.pyi index 8a10ff954e273..18d5cbc77e94d 100644 --- a/mypy/typeshed/stdlib/@python2/ctypes/__init__.pyi +++ b/mypy/typeshed/stdlib/@python2/ctypes/__init__.pyi @@ -1,4 +1,5 @@ import sys +from _typeshed import Self from array import array from typing import ( Any, @@ -7,13 +8,9 @@ from typing import ( Generic, Iterable, Iterator, - List, Mapping, - Optional, Sequence, Text, - Tuple, - Type, TypeVar, Union as _UnionT, overload, @@ -23,16 +20,16 @@ _T = TypeVar("_T") _DLLT = TypeVar("_DLLT", bound=CDLL) _CT = TypeVar("_CT", bound=_CData) -RTLD_GLOBAL: int = ... -RTLD_LOCAL: int = ... -DEFAULT_MODE: int = ... +RTLD_GLOBAL: int +RTLD_LOCAL: int +DEFAULT_MODE: int class CDLL(object): _func_flags_: ClassVar[int] = ... _func_restype_: ClassVar[_CData] = ... _name: str = ... _handle: int = ... - _FuncPtr: Type[_FuncPointer] = ... + _FuncPtr: type[_FuncPointer] = ... def __init__( self, name: str | None, mode: int = ..., handle: int | None = ..., use_errno: bool = ..., use_last_error: bool = ... ) -> None: ... @@ -46,65 +43,65 @@ if sys.platform == "win32": class PyDLL(CDLL): ... class LibraryLoader(Generic[_DLLT]): - def __init__(self, dlltype: Type[_DLLT]) -> None: ... + def __init__(self, dlltype: type[_DLLT]) -> None: ... def __getattr__(self, name: str) -> _DLLT: ... def __getitem__(self, name: str) -> _DLLT: ... def LoadLibrary(self, name: str) -> _DLLT: ... -cdll: LibraryLoader[CDLL] = ... +cdll: LibraryLoader[CDLL] if sys.platform == "win32": - windll: LibraryLoader[WinDLL] = ... - oledll: LibraryLoader[OleDLL] = ... -pydll: LibraryLoader[PyDLL] = ... -pythonapi: PyDLL = ... + windll: LibraryLoader[WinDLL] + oledll: LibraryLoader[OleDLL] +pydll: LibraryLoader[PyDLL] +pythonapi: PyDLL # Anything that implements the read-write buffer interface. # The buffer interface is defined purely on the C level, so we cannot define a normal Protocol # for it. Instead we have to list the most common stdlib buffer classes in a Union. -_WritableBuffer = _UnionT[bytearray, memoryview, array[Any], _CData] +_WritableBuffer = bytearray | memoryview | array[Any] | _CData # Same as _WritableBuffer, but also includes read-only buffer types (like bytes). -_ReadOnlyBuffer = _UnionT[_WritableBuffer, bytes] +_ReadOnlyBuffer = _WritableBuffer | bytes class _CDataMeta(type): # By default mypy complains about the following two methods, because strictly speaking cls # might not be a Type[_CT]. However this can never actually happen, because the only class that # uses _CDataMeta as its metaclass is _CData. So it's safe to ignore the errors here. - def __mul__(cls: Type[_CT], other: int) -> Type[Array[_CT]]: ... # type: ignore - def __rmul__(cls: Type[_CT], other: int) -> Type[Array[_CT]]: ... # type: ignore + def __mul__(cls: type[_CT], other: int) -> type[Array[_CT]]: ... # type: ignore[misc] + def __rmul__(cls: type[_CT], other: int) -> type[Array[_CT]]: ... # type: ignore[misc] class _CData(metaclass=_CDataMeta): _b_base: int = ... _b_needsfree_: bool = ... _objects: Mapping[Any, int] | None = ... @classmethod - def from_buffer(cls: Type[_CT], source: _WritableBuffer, offset: int = ...) -> _CT: ... + def from_buffer(cls: type[Self], source: _WritableBuffer, offset: int = ...) -> Self: ... @classmethod - def from_buffer_copy(cls: Type[_CT], source: _ReadOnlyBuffer, offset: int = ...) -> _CT: ... + def from_buffer_copy(cls: type[Self], source: _ReadOnlyBuffer, offset: int = ...) -> Self: ... @classmethod - def from_address(cls: Type[_CT], address: int) -> _CT: ... + def from_address(cls: type[Self], address: int) -> Self: ... @classmethod - def from_param(cls: Type[_CT], obj: Any) -> _UnionT[_CT, _CArgObject]: ... + def from_param(cls: type[_CT], obj: Any) -> _CT | _CArgObject: ... @classmethod - def in_dll(cls: Type[_CT], library: CDLL, name: str) -> _CT: ... + def in_dll(cls: type[Self], library: CDLL, name: str) -> Self: ... class _CanCastTo(_CData): ... class _PointerLike(_CanCastTo): ... -_ECT = Callable[[Optional[Type[_CData]], _FuncPointer, Tuple[_CData, ...]], _CData] -_PF = _UnionT[Tuple[int], Tuple[int, str], Tuple[int, str, Any]] +_ECT = Callable[[type[_CData] | None, _FuncPointer, tuple[_CData, ...]], _CData] +_PF = _UnionT[tuple[int], tuple[int, str], tuple[int, str, Any]] class _FuncPointer(_PointerLike, _CData): - restype: _UnionT[Type[_CData], Callable[[int], Any], None] = ... - argtypes: Sequence[Type[_CData]] = ... + restype: type[_CData] | Callable[[int], Any] | None = ... + argtypes: Sequence[type[_CData]] = ... errcheck: _ECT = ... @overload def __init__(self, address: int) -> None: ... @overload def __init__(self, callable: Callable[..., Any]) -> None: ... @overload - def __init__(self, func_spec: Tuple[_UnionT[str, int], CDLL], paramflags: Tuple[_PF, ...] = ...) -> None: ... + def __init__(self, func_spec: tuple[_UnionT[str, int], CDLL], paramflags: tuple[_PF, ...] = ...) -> None: ... @overload - def __init__(self, vtlb_index: int, name: str, paramflags: Tuple[_PF, ...] = ..., iid: pointer[c_int] = ...) -> None: ... + def __init__(self, vtlb_index: int, name: str, paramflags: tuple[_PF, ...] = ..., iid: pointer[c_int] = ...) -> None: ... def __call__(self, *args: Any, **kwargs: Any) -> Any: ... class _NamedFuncPointer(_FuncPointer): @@ -113,39 +110,39 @@ class _NamedFuncPointer(_FuncPointer): class ArgumentError(Exception): ... def CFUNCTYPE( - restype: Type[_CData] | None, *argtypes: Type[_CData], use_errno: bool = ..., use_last_error: bool = ... -) -> Type[_FuncPointer]: ... + restype: type[_CData] | None, *argtypes: type[_CData], use_errno: bool = ..., use_last_error: bool = ... +) -> type[_FuncPointer]: ... if sys.platform == "win32": def WINFUNCTYPE( - restype: Type[_CData] | None, *argtypes: Type[_CData], use_errno: bool = ..., use_last_error: bool = ... - ) -> Type[_FuncPointer]: ... + restype: type[_CData] | None, *argtypes: type[_CData], use_errno: bool = ..., use_last_error: bool = ... + ) -> type[_FuncPointer]: ... -def PYFUNCTYPE(restype: Type[_CData] | None, *argtypes: Type[_CData]) -> Type[_FuncPointer]: ... +def PYFUNCTYPE(restype: type[_CData] | None, *argtypes: type[_CData]) -> type[_FuncPointer]: ... class _CArgObject: ... # Any type that can be implicitly converted to c_void_p when passed as a C function argument. # (bytes is not included here, see below.) -_CVoidPLike = _UnionT[_PointerLike, Array[Any], _CArgObject, int] +_CVoidPLike = _PointerLike | Array[Any] | _CArgObject | int # Same as above, but including types known to be read-only (i. e. bytes). # This distinction is not strictly necessary (ctypes doesn't differentiate between const # and non-const pointers), but it catches errors like memmove(b'foo', buf, 4) # when memmove(buf, b'foo', 4) was intended. -_CVoidConstPLike = _UnionT[_CVoidPLike, bytes] +_CVoidConstPLike = _CVoidPLike | bytes def addressof(obj: _CData) -> int: ... -def alignment(obj_or_type: _UnionT[_CData, Type[_CData]]) -> int: ... +def alignment(obj_or_type: _CData | type[_CData]) -> int: ... def byref(obj: _CData, offset: int = ...) -> _CArgObject: ... _CastT = TypeVar("_CastT", bound=_CanCastTo) -def cast(obj: _UnionT[_CData, _CArgObject, int], typ: Type[_CastT]) -> _CastT: ... -def create_string_buffer(init: _UnionT[int, bytes], size: int | None = ...) -> Array[c_char]: ... +def cast(obj: _CData | _CArgObject | int, typ: type[_CastT]) -> _CastT: ... +def create_string_buffer(init: int | bytes, size: int | None = ...) -> Array[c_char]: ... c_buffer = create_string_buffer -def create_unicode_buffer(init: _UnionT[int, Text], size: int | None = ...) -> Array[c_wchar]: ... +def create_unicode_buffer(init: int | Text, size: int | None = ...) -> Array[c_wchar]: ... if sys.platform == "win32": def DllCanUnloadNow() -> int: ... @@ -160,32 +157,32 @@ if sys.platform == "win32": def memmove(dst: _CVoidPLike, src: _CVoidConstPLike, count: int) -> None: ... def memset(dst: _CVoidPLike, c: int, count: int) -> None: ... -def POINTER(type: Type[_CT]) -> Type[pointer[_CT]]: ... +def POINTER(type: type[_CT]) -> type[pointer[_CT]]: ... # The real ctypes.pointer is a function, not a class. The stub version of pointer behaves like # ctypes._Pointer in that it is the base class for all pointer types. Unlike the real _Pointer, # it can be instantiated directly (to mimic the behavior of the real pointer function). class pointer(Generic[_CT], _PointerLike, _CData): - _type_: Type[_CT] = ... + _type_: type[_CT] = ... contents: _CT = ... def __init__(self, arg: _CT = ...) -> None: ... @overload def __getitem__(self, i: int) -> _CT: ... @overload - def __getitem__(self, s: slice) -> List[_CT]: ... + def __getitem__(self, s: slice) -> list[_CT]: ... @overload def __setitem__(self, i: int, o: _CT) -> None: ... @overload def __setitem__(self, s: slice, o: Iterable[_CT]) -> None: ... def resize(obj: _CData, size: int) -> None: ... -def set_conversion_mode(encoding: str, errors: str) -> Tuple[str, str]: ... +def set_conversion_mode(encoding: str, errors: str) -> tuple[str, str]: ... def set_errno(value: int) -> int: ... if sys.platform == "win32": def set_last_error(value: int) -> int: ... -def sizeof(obj_or_type: _UnionT[_CData, Type[_CData]]) -> int: ... +def sizeof(obj_or_type: _CData | type[_CData]) -> int: ... def string_at(address: _CVoidConstPLike, size: int = ...) -> bytes: ... if sys.platform == "win32": @@ -200,10 +197,10 @@ class _SimpleCData(Generic[_T], _CData): class c_byte(_SimpleCData[int]): ... class c_char(_SimpleCData[bytes]): - def __init__(self, value: _UnionT[int, bytes] = ...) -> None: ... + def __init__(self, value: int | bytes = ...) -> None: ... -class c_char_p(_PointerLike, _SimpleCData[Optional[bytes]]): - def __init__(self, value: _UnionT[int, bytes] | None = ...) -> None: ... +class c_char_p(_PointerLike, _SimpleCData[bytes | None]): + def __init__(self, value: int | bytes | None = ...) -> None: ... class c_double(_SimpleCData[float]): ... class c_longdouble(_SimpleCData[float]): ... @@ -227,11 +224,11 @@ class c_uint64(_SimpleCData[int]): ... class c_ulong(_SimpleCData[int]): ... class c_ulonglong(_SimpleCData[int]): ... class c_ushort(_SimpleCData[int]): ... -class c_void_p(_PointerLike, _SimpleCData[Optional[int]]): ... +class c_void_p(_PointerLike, _SimpleCData[int | None]): ... class c_wchar(_SimpleCData[Text]): ... -class c_wchar_p(_PointerLike, _SimpleCData[Optional[Text]]): - def __init__(self, value: _UnionT[int, Text] | None = ...) -> None: ... +class c_wchar_p(_PointerLike, _SimpleCData[Text | None]): + def __init__(self, value: int | Text | None = ...) -> None: ... class c_bool(_SimpleCData[bool]): def __init__(self, value: bool = ...) -> None: ... @@ -246,7 +243,7 @@ class _CField: size: int = ... class _StructUnionMeta(_CDataMeta): - _fields_: Sequence[_UnionT[Tuple[str, Type[_CData]], Tuple[str, Type[_CData], int]]] = ... + _fields_: Sequence[_UnionT[tuple[str, type[_CData]], tuple[str, type[_CData], int]]] = ... _pack_: int = ... _anonymous_: Sequence[str] = ... def __getattr__(self, name: str) -> _CField: ... @@ -263,7 +260,7 @@ class LittleEndianStructure(Structure): ... class Array(Generic[_CT], _CData): _length_: int = ... - _type_: Type[_CT] = ... + _type_: type[_CT] = ... raw: bytes = ... # Note: only available if _CT == c_char value: Any = ... # Note: bytes if _CT == c_char, Text if _CT == c_wchar, unavailable otherwise # TODO These methods cannot be annotated correctly at the moment. @@ -282,7 +279,7 @@ class Array(Generic[_CT], _CData): @overload def __getitem__(self, i: int) -> Any: ... @overload - def __getitem__(self, s: slice) -> List[Any]: ... + def __getitem__(self, s: slice) -> list[Any]: ... @overload def __setitem__(self, i: int, o: Any) -> None: ... @overload diff --git a/mypy/typeshed/stdlib/@python2/curses/__init__.pyi b/mypy/typeshed/stdlib/@python2/curses/__init__.pyi index 73e84fba3763e..d5581ce11c229 100644 --- a/mypy/typeshed/stdlib/@python2/curses/__init__.pyi +++ b/mypy/typeshed/stdlib/@python2/curses/__init__.pyi @@ -1,4 +1,4 @@ -from _curses import * # noqa: F403 +from _curses import * from _curses import _CursesWindow as _CursesWindow from typing import Any, Callable, TypeVar diff --git a/mypy/typeshed/stdlib/@python2/curses/ascii.pyi b/mypy/typeshed/stdlib/@python2/curses/ascii.pyi index 05efb326687aa..66efbe36a7df2 100644 --- a/mypy/typeshed/stdlib/@python2/curses/ascii.pyi +++ b/mypy/typeshed/stdlib/@python2/curses/ascii.pyi @@ -1,4 +1,4 @@ -from typing import List, TypeVar +from typing import TypeVar _CharT = TypeVar("_CharT", str, int) @@ -39,7 +39,7 @@ US: int SP: int DEL: int -controlnames: List[int] +controlnames: list[int] def isalnum(c: str | int) -> bool: ... def isalpha(c: str | int) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/datetime.pyi b/mypy/typeshed/stdlib/@python2/datetime.pyi index 8b19a3d316f2b..62791461c8858 100644 --- a/mypy/typeshed/stdlib/@python2/datetime.pyi +++ b/mypy/typeshed/stdlib/@python2/datetime.pyi @@ -1,9 +1,8 @@ +from _typeshed import Self from time import struct_time -from typing import AnyStr, ClassVar, SupportsAbs, Tuple, Type, TypeVar, Union, overload +from typing import AnyStr, ClassVar, SupportsAbs, overload -_S = TypeVar("_S") - -_Text = Union[str, unicode] +_Text = str | unicode MINYEAR: int MAXYEAR: int @@ -20,13 +19,13 @@ class date: min: ClassVar[date] max: ClassVar[date] resolution: ClassVar[timedelta] - def __new__(cls: Type[_S], year: int, month: int, day: int) -> _S: ... + def __new__(cls: type[Self], year: int, month: int, day: int) -> Self: ... @classmethod - def fromtimestamp(cls: Type[_S], __timestamp: float) -> _S: ... + def fromtimestamp(cls: type[Self], __timestamp: float) -> Self: ... @classmethod - def today(cls: Type[_S]) -> _S: ... + def today(cls: type[Self]) -> Self: ... @classmethod - def fromordinal(cls: Type[_S], n: int) -> _S: ... + def fromordinal(cls: type[Self], n: int) -> Self: ... @property def year(self) -> int: ... @property @@ -53,15 +52,20 @@ class date: def __hash__(self) -> int: ... def weekday(self) -> int: ... def isoweekday(self) -> int: ... - def isocalendar(self) -> Tuple[int, int, int]: ... + def isocalendar(self) -> tuple[int, int, int]: ... class time: min: ClassVar[time] max: ClassVar[time] resolution: ClassVar[timedelta] def __new__( - cls: Type[_S], hour: int = ..., minute: int = ..., second: int = ..., microsecond: int = ..., tzinfo: _tzinfo | None = ... - ) -> _S: ... + cls: type[Self], + hour: int = ..., + minute: int = ..., + second: int = ..., + microsecond: int = ..., + tzinfo: _tzinfo | None = ..., + ) -> Self: ... @property def hour(self) -> int: ... @property @@ -95,7 +99,7 @@ class timedelta(SupportsAbs[timedelta]): max: ClassVar[timedelta] resolution: ClassVar[timedelta] def __new__( - cls: Type[_S], + cls: type[Self], days: float = ..., seconds: float = ..., microseconds: float = ..., @@ -103,7 +107,7 @@ class timedelta(SupportsAbs[timedelta]): minutes: float = ..., hours: float = ..., weeks: float = ..., - ) -> _S: ... + ) -> Self: ... @property def days(self) -> int: ... @property @@ -139,7 +143,7 @@ class datetime(date): max: ClassVar[datetime] resolution: ClassVar[timedelta] def __new__( - cls: Type[_S], + cls: type[Self], year: int, month: int, day: int, @@ -148,7 +152,7 @@ class datetime(date): second: int = ..., microsecond: int = ..., tzinfo: _tzinfo | None = ..., - ) -> _S: ... + ) -> Self: ... @property def year(self) -> int: ... @property @@ -166,21 +170,21 @@ class datetime(date): @property def tzinfo(self) -> _tzinfo | None: ... @classmethod - def fromtimestamp(cls: Type[_S], t: float, tz: _tzinfo | None = ...) -> _S: ... + def fromtimestamp(cls: type[Self], t: float, tz: _tzinfo | None = ...) -> Self: ... @classmethod - def utcfromtimestamp(cls: Type[_S], t: float) -> _S: ... + def utcfromtimestamp(cls: type[Self], t: float) -> Self: ... @classmethod - def today(cls: Type[_S]) -> _S: ... + def today(cls: type[Self]) -> Self: ... @classmethod - def fromordinal(cls: Type[_S], n: int) -> _S: ... + def fromordinal(cls: type[Self], n: int) -> Self: ... @overload @classmethod - def now(cls: Type[_S], tz: None = ...) -> _S: ... + def now(cls: type[Self], tz: None = ...) -> Self: ... @overload @classmethod def now(cls, tz: _tzinfo) -> datetime: ... @classmethod - def utcnow(cls: Type[_S]) -> _S: ... + def utcnow(cls: type[Self]) -> Self: ... @classmethod def combine(cls, date: _date, time: _time) -> datetime: ... def strftime(self, fmt: _Text) -> str: ... @@ -210,17 +214,17 @@ class datetime(date): def utcoffset(self) -> timedelta | None: ... def tzname(self) -> str | None: ... def dst(self) -> timedelta | None: ... - def __le__(self, other: datetime) -> bool: ... # type: ignore - def __lt__(self, other: datetime) -> bool: ... # type: ignore - def __ge__(self, other: datetime) -> bool: ... # type: ignore - def __gt__(self, other: datetime) -> bool: ... # type: ignore + def __le__(self, other: datetime) -> bool: ... # type: ignore[override] + def __lt__(self, other: datetime) -> bool: ... # type: ignore[override] + def __ge__(self, other: datetime) -> bool: ... # type: ignore[override] + def __gt__(self, other: datetime) -> bool: ... # type: ignore[override] def __add__(self, other: timedelta) -> datetime: ... def __radd__(self, other: timedelta) -> datetime: ... - @overload # type: ignore + @overload # type: ignore[override] def __sub__(self, other: datetime) -> timedelta: ... @overload def __sub__(self, other: timedelta) -> datetime: ... def __hash__(self) -> int: ... def weekday(self) -> int: ... def isoweekday(self) -> int: ... - def isocalendar(self) -> Tuple[int, int, int]: ... + def isocalendar(self) -> tuple[int, int, int]: ... diff --git a/mypy/typeshed/stdlib/@python2/dbm/__init__.pyi b/mypy/typeshed/stdlib/@python2/dbm/__init__.pyi index 95f6d9cf03632..e9c1d01a5c9bd 100644 --- a/mypy/typeshed/stdlib/@python2/dbm/__init__.pyi +++ b/mypy/typeshed/stdlib/@python2/dbm/__init__.pyi @@ -1,9 +1,10 @@ +from _typeshed import Self from types import TracebackType -from typing import Iterator, MutableMapping, Tuple, Type, Union +from typing import Iterator, MutableMapping from typing_extensions import Literal -_KeyType = Union[str, bytes] -_ValueType = Union[str, bytes] +_KeyType = str | bytes +_ValueType = str | bytes class _Database(MutableMapping[_KeyType, bytes]): def close(self) -> None: ... @@ -13,14 +14,14 @@ class _Database(MutableMapping[_KeyType, bytes]): def __iter__(self) -> Iterator[bytes]: ... def __len__(self) -> int: ... def __del__(self) -> None: ... - def __enter__(self) -> _Database: ... + def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> None: ... class _error(Exception): ... -error = Tuple[Type[_error], Type[OSError]] +error = tuple[type[_error], type[OSError]] def whichdb(filename: str) -> str: ... def open(file: str, flag: Literal["r", "w", "c", "n"] = ..., mode: int = ...) -> _Database: ... diff --git a/mypy/typeshed/stdlib/@python2/dbm/dumb.pyi b/mypy/typeshed/stdlib/@python2/dbm/dumb.pyi index fb5e2da5fa2c9..acb4b3b7ae7fc 100644 --- a/mypy/typeshed/stdlib/@python2/dbm/dumb.pyi +++ b/mypy/typeshed/stdlib/@python2/dbm/dumb.pyi @@ -1,8 +1,9 @@ +from _typeshed import Self from types import TracebackType -from typing import Iterator, MutableMapping, Type, Union +from typing import Iterator, MutableMapping -_KeyType = Union[str, bytes] -_ValueType = Union[str, bytes] +_KeyType = str | bytes +_ValueType = str | bytes error = OSError @@ -17,9 +18,9 @@ class _Database(MutableMapping[_KeyType, bytes]): def __iter__(self) -> Iterator[bytes]: ... def __len__(self) -> int: ... def __del__(self) -> None: ... - def __enter__(self) -> _Database: ... + def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> None: ... def open(file: str, flag: str = ..., mode: int = ...) -> _Database: ... diff --git a/mypy/typeshed/stdlib/@python2/dbm/gnu.pyi b/mypy/typeshed/stdlib/@python2/dbm/gnu.pyi index 0e9339bf81f99..c6eed0be2098c 100644 --- a/mypy/typeshed/stdlib/@python2/dbm/gnu.pyi +++ b/mypy/typeshed/stdlib/@python2/dbm/gnu.pyi @@ -1,9 +1,10 @@ +from _typeshed import Self from types import TracebackType -from typing import List, Type, TypeVar, Union, overload +from typing import TypeVar, overload _T = TypeVar("_T") -_KeyType = Union[str, bytes] -_ValueType = Union[str, bytes] +_KeyType = str | bytes +_ValueType = str | bytes class error(OSError): ... @@ -18,18 +19,18 @@ class _gdbm: def __setitem__(self, key: _KeyType, value: _ValueType) -> None: ... def __delitem__(self, key: _KeyType) -> None: ... def __len__(self) -> int: ... - def __enter__(self) -> _gdbm: ... + def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> None: ... @overload def get(self, k: _KeyType) -> bytes | None: ... @overload def get(self, k: _KeyType, default: bytes | _T) -> bytes | _T: ... - def keys(self) -> List[bytes]: ... + def keys(self) -> list[bytes]: ... def setdefault(self, k: _KeyType, default: _ValueType = ...) -> bytes: ... # Don't exist at runtime - __new__: None # type: ignore - __init__: None # type: ignore + __new__: None # type: ignore[assignment] + __init__: None # type: ignore[assignment] def open(__filename: str, __flags: str = ..., __mode: int = ...) -> _gdbm: ... diff --git a/mypy/typeshed/stdlib/@python2/dbm/ndbm.pyi b/mypy/typeshed/stdlib/@python2/dbm/ndbm.pyi index 28f4dd8e4e591..764aed01a3574 100644 --- a/mypy/typeshed/stdlib/@python2/dbm/ndbm.pyi +++ b/mypy/typeshed/stdlib/@python2/dbm/ndbm.pyi @@ -1,13 +1,14 @@ +from _typeshed import Self from types import TracebackType -from typing import List, Type, TypeVar, Union, overload +from typing import TypeVar, overload _T = TypeVar("_T") -_KeyType = Union[str, bytes] -_ValueType = Union[str, bytes] +_KeyType = str | bytes +_ValueType = str | bytes class error(OSError): ... -library: str = ... +library: str # Actual typename dbm, not exposed by the implementation class _dbm: @@ -17,18 +18,18 @@ class _dbm: def __delitem__(self, key: _KeyType) -> None: ... def __len__(self) -> int: ... def __del__(self) -> None: ... - def __enter__(self) -> _dbm: ... + def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> None: ... @overload def get(self, k: _KeyType) -> bytes | None: ... @overload def get(self, k: _KeyType, default: bytes | _T) -> bytes | _T: ... - def keys(self) -> List[bytes]: ... + def keys(self) -> list[bytes]: ... def setdefault(self, k: _KeyType, default: _ValueType = ...) -> bytes: ... # Don't exist at runtime - __new__: None # type: ignore - __init__: None # type: ignore + __new__: None # type: ignore[assignment] + __init__: None # type: ignore[assignment] def open(__filename: str, __flags: str = ..., __mode: int = ...) -> _dbm: ... diff --git a/mypy/typeshed/stdlib/@python2/decimal.pyi b/mypy/typeshed/stdlib/@python2/decimal.pyi index 915bddadb5846..5ea7348c2eafc 100644 --- a/mypy/typeshed/stdlib/@python2/decimal.pyi +++ b/mypy/typeshed/stdlib/@python2/decimal.pyi @@ -1,14 +1,14 @@ +from _typeshed import Self from types import TracebackType -from typing import Any, Container, Dict, List, NamedTuple, Sequence, Text, Tuple, Type, TypeVar, Union +from typing import Any, Container, NamedTuple, Sequence, Text, Union -_Decimal = Union[Decimal, int] -_DecimalNew = Union[Decimal, float, Text, Tuple[int, Sequence[int], int]] -_ComparableNum = Union[Decimal, float] -_DecimalT = TypeVar("_DecimalT", bound=Decimal) +_Decimal = Decimal | int +_DecimalNew = Union[Decimal, float, Text, tuple[int, Sequence[int], int]] +_ComparableNum = Decimal | float class DecimalTuple(NamedTuple): sign: int - digits: Tuple[int, ...] + digits: tuple[int, ...] exponent: int ROUND_DOWN: str @@ -41,7 +41,7 @@ def getcontext() -> Context: ... def localcontext(ctx: Context | None = ...) -> _ContextManager: ... class Decimal(object): - def __new__(cls: Type[_DecimalT], value: _DecimalNew = ..., context: Context | None = ...) -> _DecimalT: ... + def __new__(cls: type[Self], value: _DecimalNew = ..., context: Context | None = ...) -> Self: ... @classmethod def from_float(cls, __f: float) -> Decimal: ... def __nonzero__(self) -> bool: ... @@ -54,7 +54,7 @@ class Decimal(object): def to_eng_string(self, context: Context | None = ...) -> str: ... def __abs__(self, round: bool = ..., context: Context | None = ...) -> Decimal: ... def __add__(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... - def __divmod__(self, other: _Decimal, context: Context | None = ...) -> Tuple[Decimal, Decimal]: ... + def __divmod__(self, other: _Decimal, context: Context | None = ...) -> tuple[Decimal, Decimal]: ... def __eq__(self, other: object, context: Context | None = ...) -> bool: ... def __floordiv__(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... def __ge__(self, other: _ComparableNum, context: Context | None = ...) -> bool: ... @@ -67,7 +67,7 @@ class Decimal(object): def __pos__(self, context: Context | None = ...) -> Decimal: ... def __pow__(self, other: _Decimal, modulo: _Decimal | None = ..., context: Context | None = ...) -> Decimal: ... def __radd__(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... - def __rdivmod__(self, other: _Decimal, context: Context | None = ...) -> Tuple[Decimal, Decimal]: ... + def __rdivmod__(self, other: _Decimal, context: Context | None = ...) -> tuple[Decimal, Decimal]: ... def __rfloordiv__(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... def __rmod__(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... def __rmul__(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... @@ -136,7 +136,7 @@ class Decimal(object): def rotate(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... def scaleb(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... def shift(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... - def __reduce__(self) -> Tuple[Type[Decimal], Tuple[str]]: ... + def __reduce__(self) -> tuple[type[Decimal], tuple[str]]: ... def __copy__(self) -> Decimal: ... def __deepcopy__(self, memo: Any) -> Decimal: ... def __format__(self, specifier: str, context: Context | None = ...) -> str: ... @@ -146,9 +146,9 @@ class _ContextManager(object): saved_context: Context def __init__(self, new_context: Context) -> None: ... def __enter__(self) -> Context: ... - def __exit__(self, t: Type[BaseException] | None, v: BaseException | None, tb: TracebackType | None) -> None: ... + def __exit__(self, t: type[BaseException] | None, v: BaseException | None, tb: TracebackType | None) -> None: ... -_TrapType = Type[DecimalException] +_TrapType = type[DecimalException] class Context(object): prec: int @@ -157,19 +157,19 @@ class Context(object): Emax: int capitals: int _clamp: int - traps: Dict[_TrapType, bool] - flags: Dict[_TrapType, bool] + traps: dict[_TrapType, bool] + flags: dict[_TrapType, bool] def __init__( self, prec: int | None = ..., rounding: str | None = ..., - traps: None | Dict[_TrapType, bool] | Container[_TrapType] = ..., - flags: None | Dict[_TrapType, bool] | Container[_TrapType] = ..., + traps: None | dict[_TrapType, bool] | Container[_TrapType] = ..., + flags: None | dict[_TrapType, bool] | Container[_TrapType] = ..., Emin: int | None = ..., Emax: int | None = ..., capitals: int | None = ..., _clamp: int | None = ..., - _ignored_flags: List[_TrapType] | None = ..., + _ignored_flags: list[_TrapType] | None = ..., ) -> None: ... def clear_flags(self) -> None: ... def copy(self) -> Context: ... @@ -192,7 +192,7 @@ class Context(object): def copy_sign(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... def divide(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... def divide_int(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... - def divmod(self, __x: _Decimal, __y: _Decimal) -> Tuple[Decimal, Decimal]: ... + def divmod(self, __x: _Decimal, __y: _Decimal) -> tuple[Decimal, Decimal]: ... def exp(self, __x: _Decimal) -> Decimal: ... def fma(self, __x: _Decimal, __y: _Decimal, __z: _Decimal) -> Decimal: ... def is_canonical(self, __x: _Decimal) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/difflib.pyi b/mypy/typeshed/stdlib/@python2/difflib.pyi index 41ffc6a286d10..f4214cec2260f 100644 --- a/mypy/typeshed/stdlib/@python2/difflib.pyi +++ b/mypy/typeshed/stdlib/@python2/difflib.pyi @@ -1,26 +1,11 @@ -from typing import ( - Any, - AnyStr, - Callable, - Generic, - Iterable, - Iterator, - List, - NamedTuple, - Sequence, - Text, - Tuple, - TypeVar, - Union, - overload, -) +from typing import Any, AnyStr, Callable, Generic, Iterable, Iterator, NamedTuple, Sequence, Text, TypeVar, overload _T = TypeVar("_T") # Aliases can't point to type vars, so we need to redeclare AnyStr _StrType = TypeVar("_StrType", Text, bytes) -_JunkCallback = Union[Callable[[Text], bool], Callable[[str], bool]] +_JunkCallback = Callable[[Text], bool] | Callable[[str], bool] class Match(NamedTuple): a: int @@ -35,22 +20,20 @@ class SequenceMatcher(Generic[_T]): def set_seq1(self, a: Sequence[_T]) -> None: ... def set_seq2(self, b: Sequence[_T]) -> None: ... def find_longest_match(self, alo: int, ahi: int, blo: int, bhi: int) -> Match: ... - def get_matching_blocks(self) -> List[Match]: ... - def get_opcodes(self) -> List[Tuple[str, int, int, int, int]]: ... - def get_grouped_opcodes(self, n: int = ...) -> Iterable[List[Tuple[str, int, int, int, int]]]: ... + def get_matching_blocks(self) -> list[Match]: ... + def get_opcodes(self) -> list[tuple[str, int, int, int, int]]: ... + def get_grouped_opcodes(self, n: int = ...) -> Iterable[list[tuple[str, int, int, int, int]]]: ... def ratio(self) -> float: ... def quick_ratio(self) -> float: ... def real_quick_ratio(self) -> float: ... # mypy thinks the signatures of the overloads overlap, but the types still work fine @overload -def get_close_matches( # type: ignore - word: AnyStr, possibilities: Iterable[AnyStr], n: int = ..., cutoff: float = ... -) -> List[AnyStr]: ... +def get_close_matches(word: AnyStr, possibilities: Iterable[AnyStr], n: int = ..., cutoff: float = ...) -> list[AnyStr]: ... # type: ignore[misc] @overload def get_close_matches( word: Sequence[_T], possibilities: Iterable[Sequence[_T]], n: int = ..., cutoff: float = ... -) -> List[Sequence[_T]]: ... +) -> list[Sequence[_T]]: ... class Differ: def __init__(self, linejunk: _JunkCallback | None = ..., charjunk: _JunkCallback | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/dircache.pyi b/mypy/typeshed/stdlib/@python2/dircache.pyi index 366909d871339..dc1e129648e8b 100644 --- a/mypy/typeshed/stdlib/@python2/dircache.pyi +++ b/mypy/typeshed/stdlib/@python2/dircache.pyi @@ -1,7 +1,7 @@ -from typing import List, MutableSequence, Text +from typing import MutableSequence, Text def reset() -> None: ... -def listdir(path: Text) -> List[str]: ... +def listdir(path: Text) -> list[str]: ... opendir = listdir diff --git a/mypy/typeshed/stdlib/@python2/dis.pyi b/mypy/typeshed/stdlib/@python2/dis.pyi index 1d6537667a60a..79cc30a68a0ab 100644 --- a/mypy/typeshed/stdlib/@python2/dis.pyi +++ b/mypy/typeshed/stdlib/@python2/dis.pyi @@ -13,17 +13,17 @@ from opcode import ( opmap as opmap, opname as opname, ) -from typing import Any, Callable, Dict, Iterator, List, Tuple, Union +from typing import Any, Callable, Iterator # Strictly this should not have to include Callable, but mypy doesn't use FunctionType # for functions (python/mypy#3171) -_have_code = Union[types.MethodType, types.FunctionType, types.CodeType, type, Callable[..., Any]] -_have_code_or_string = Union[_have_code, str, bytes] +_have_code = types.MethodType | types.FunctionType | types.CodeType | type | Callable[..., Any] +_have_code_or_string = _have_code | str | bytes -COMPILER_FLAG_NAMES: Dict[int, str] +COMPILER_FLAG_NAMES: dict[int, str] -def findlabels(code: _have_code) -> List[int]: ... -def findlinestarts(code: _have_code) -> Iterator[Tuple[int, int]]: ... +def findlabels(code: _have_code) -> list[int]: ... +def findlinestarts(code: _have_code) -> Iterator[tuple[int, int]]: ... def dis(x: _have_code_or_string = ...) -> None: ... def distb(tb: types.TracebackType = ...) -> None: ... def disassemble(co: _have_code, lasti: int = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/ccompiler.pyi b/mypy/typeshed/stdlib/@python2/distutils/ccompiler.pyi index b0539bf9e5dcc..4cdc62ce3bae4 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/ccompiler.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/ccompiler.pyi @@ -1,11 +1,11 @@ -from typing import Any, Callable, List, Optional, Tuple, Union +from typing import Any, Callable, Union -_Macro = Union[Tuple[str], Tuple[str, Optional[str]]] +_Macro = Union[tuple[str], tuple[str, str | None]] def gen_lib_options( - compiler: CCompiler, library_dirs: List[str], runtime_library_dirs: List[str], libraries: List[str] -) -> List[str]: ... -def gen_preprocess_options(macros: List[_Macro], include_dirs: List[str]) -> List[str]: ... + compiler: CCompiler, library_dirs: list[str], runtime_library_dirs: list[str], libraries: list[str] +) -> list[str]: ... +def gen_preprocess_options(macros: list[_Macro], include_dirs: list[str]) -> list[str]: ... def get_default_compiler(osname: str | None = ..., platform: str | None = ...) -> str: ... def new_compiler( plat: str | None = ..., compiler: str | None = ..., verbose: int = ..., dry_run: int = ..., force: int = ... @@ -17,34 +17,34 @@ class CCompiler: force: bool verbose: bool output_dir: str | None - macros: List[_Macro] - include_dirs: List[str] - libraries: List[str] - library_dirs: List[str] - runtime_library_dirs: List[str] - objects: List[str] + macros: list[_Macro] + include_dirs: list[str] + libraries: list[str] + library_dirs: list[str] + runtime_library_dirs: list[str] + objects: list[str] def __init__(self, verbose: int = ..., dry_run: int = ..., force: int = ...) -> None: ... def add_include_dir(self, dir: str) -> None: ... - def set_include_dirs(self, dirs: List[str]) -> None: ... + def set_include_dirs(self, dirs: list[str]) -> None: ... def add_library(self, libname: str) -> None: ... - def set_libraries(self, libnames: List[str]) -> None: ... + def set_libraries(self, libnames: list[str]) -> None: ... def add_library_dir(self, dir: str) -> None: ... - def set_library_dirs(self, dirs: List[str]) -> None: ... + def set_library_dirs(self, dirs: list[str]) -> None: ... def add_runtime_library_dir(self, dir: str) -> None: ... - def set_runtime_library_dirs(self, dirs: List[str]) -> None: ... + def set_runtime_library_dirs(self, dirs: list[str]) -> None: ... def define_macro(self, name: str, value: str | None = ...) -> None: ... def undefine_macro(self, name: str) -> None: ... def add_link_object(self, object: str) -> None: ... - def set_link_objects(self, objects: List[str]) -> None: ... - def detect_language(self, sources: str | List[str]) -> str | None: ... - def find_library_file(self, dirs: List[str], lib: str, debug: bool = ...) -> str | None: ... + def set_link_objects(self, objects: list[str]) -> None: ... + def detect_language(self, sources: str | list[str]) -> str | None: ... + def find_library_file(self, dirs: list[str], lib: str, debug: bool = ...) -> str | None: ... def has_function( self, funcname: str, - includes: List[str] | None = ..., - include_dirs: List[str] | None = ..., - libraries: List[str] | None = ..., - library_dirs: List[str] | None = ..., + includes: list[str] | None = ..., + include_dirs: list[str] | None = ..., + libraries: list[str] | None = ..., + library_dirs: list[str] | None = ..., ) -> bool: ... def library_dir_option(self, dir: str) -> str: ... def library_option(self, lib: str) -> str: ... @@ -52,18 +52,18 @@ class CCompiler: def set_executables(self, **args: str) -> None: ... def compile( self, - sources: List[str], + sources: list[str], output_dir: str | None = ..., macros: _Macro | None = ..., - include_dirs: List[str] | None = ..., + include_dirs: list[str] | None = ..., debug: bool = ..., - extra_preargs: List[str] | None = ..., - extra_postargs: List[str] | None = ..., - depends: List[str] | None = ..., - ) -> List[str]: ... + extra_preargs: list[str] | None = ..., + extra_postargs: list[str] | None = ..., + depends: list[str] | None = ..., + ) -> list[str]: ... def create_static_lib( self, - objects: List[str], + objects: list[str], output_libname: str, output_dir: str | None = ..., debug: bool = ..., @@ -72,59 +72,59 @@ class CCompiler: def link( self, target_desc: str, - objects: List[str], + objects: list[str], output_filename: str, output_dir: str | None = ..., - libraries: List[str] | None = ..., - library_dirs: List[str] | None = ..., - runtime_library_dirs: List[str] | None = ..., - export_symbols: List[str] | None = ..., + libraries: list[str] | None = ..., + library_dirs: list[str] | None = ..., + runtime_library_dirs: list[str] | None = ..., + export_symbols: list[str] | None = ..., debug: bool = ..., - extra_preargs: List[str] | None = ..., - extra_postargs: List[str] | None = ..., + extra_preargs: list[str] | None = ..., + extra_postargs: list[str] | None = ..., build_temp: str | None = ..., target_lang: str | None = ..., ) -> None: ... def link_executable( self, - objects: List[str], + objects: list[str], output_progname: str, output_dir: str | None = ..., - libraries: List[str] | None = ..., - library_dirs: List[str] | None = ..., - runtime_library_dirs: List[str] | None = ..., + libraries: list[str] | None = ..., + library_dirs: list[str] | None = ..., + runtime_library_dirs: list[str] | None = ..., debug: bool = ..., - extra_preargs: List[str] | None = ..., - extra_postargs: List[str] | None = ..., + extra_preargs: list[str] | None = ..., + extra_postargs: list[str] | None = ..., target_lang: str | None = ..., ) -> None: ... def link_shared_lib( self, - objects: List[str], + objects: list[str], output_libname: str, output_dir: str | None = ..., - libraries: List[str] | None = ..., - library_dirs: List[str] | None = ..., - runtime_library_dirs: List[str] | None = ..., - export_symbols: List[str] | None = ..., + libraries: list[str] | None = ..., + library_dirs: list[str] | None = ..., + runtime_library_dirs: list[str] | None = ..., + export_symbols: list[str] | None = ..., debug: bool = ..., - extra_preargs: List[str] | None = ..., - extra_postargs: List[str] | None = ..., + extra_preargs: list[str] | None = ..., + extra_postargs: list[str] | None = ..., build_temp: str | None = ..., target_lang: str | None = ..., ) -> None: ... def link_shared_object( self, - objects: List[str], + objects: list[str], output_filename: str, output_dir: str | None = ..., - libraries: List[str] | None = ..., - library_dirs: List[str] | None = ..., - runtime_library_dirs: List[str] | None = ..., - export_symbols: List[str] | None = ..., + libraries: list[str] | None = ..., + library_dirs: list[str] | None = ..., + runtime_library_dirs: list[str] | None = ..., + export_symbols: list[str] | None = ..., debug: bool = ..., - extra_preargs: List[str] | None = ..., - extra_postargs: List[str] | None = ..., + extra_preargs: list[str] | None = ..., + extra_postargs: list[str] | None = ..., build_temp: str | None = ..., target_lang: str | None = ..., ) -> None: ... @@ -132,17 +132,17 @@ class CCompiler: self, source: str, output_file: str | None = ..., - macros: List[_Macro] | None = ..., - include_dirs: List[str] | None = ..., - extra_preargs: List[str] | None = ..., - extra_postargs: List[str] | None = ..., + macros: list[_Macro] | None = ..., + include_dirs: list[str] | None = ..., + extra_preargs: list[str] | None = ..., + extra_postargs: list[str] | None = ..., ) -> None: ... def executable_filename(self, basename: str, strip_dir: int = ..., output_dir: str = ...) -> str: ... def library_filename(self, libname: str, lib_type: str = ..., strip_dir: int = ..., output_dir: str = ...) -> str: ... - def object_filenames(self, source_filenames: List[str], strip_dir: int = ..., output_dir: str = ...) -> List[str]: ... + def object_filenames(self, source_filenames: list[str], strip_dir: int = ..., output_dir: str = ...) -> list[str]: ... def shared_object_filename(self, basename: str, strip_dir: int = ..., output_dir: str = ...) -> str: ... - def execute(self, func: Callable[..., None], args: Tuple[Any, ...], msg: str | None = ..., level: int = ...) -> None: ... - def spawn(self, cmd: List[str]) -> None: ... + def execute(self, func: Callable[..., None], args: tuple[Any, ...], msg: str | None = ..., level: int = ...) -> None: ... + def spawn(self, cmd: list[str]) -> None: ... def mkpath(self, name: str, mode: int = ...) -> None: ... def move_file(self, src: str, dst: str) -> str: ... def announce(self, msg: str, level: int = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/cmd.pyi b/mypy/typeshed/stdlib/@python2/distutils/cmd.pyi index d4e90bf699705..096414713f7f9 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/cmd.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/cmd.pyi @@ -1,9 +1,9 @@ from abc import abstractmethod from distutils.dist import Distribution -from typing import Any, Callable, Iterable, List, Text, Tuple +from typing import Any, Callable, Iterable, Text class Command: - sub_commands: List[Tuple[str, Callable[[Command], bool] | None]] + sub_commands: list[tuple[str, Callable[[Command], bool] | None]] def __init__(self, dist: Distribution) -> None: ... @abstractmethod def initialize_options(self) -> None: ... @@ -14,15 +14,15 @@ class Command: def announce(self, msg: Text, level: int = ...) -> None: ... def debug_print(self, msg: Text) -> None: ... def ensure_string(self, option: str, default: str | None = ...) -> None: ... - def ensure_string_list(self, option: str | List[str]) -> None: ... + def ensure_string_list(self, option: str | list[str]) -> None: ... def ensure_filename(self, option: str) -> None: ... def ensure_dirname(self, option: str) -> None: ... def get_command_name(self) -> str: ... - def set_undefined_options(self, src_cmd: Text, *option_pairs: Tuple[str, str]) -> None: ... + def set_undefined_options(self, src_cmd: Text, *option_pairs: tuple[str, str]) -> None: ... def get_finalized_command(self, command: Text, create: int = ...) -> Command: ... def reinitialize_command(self, command: Command | Text, reinit_subcommands: int = ...) -> Command: ... def run_command(self, command: Text) -> None: ... - def get_sub_commands(self) -> List[str]: ... + def get_sub_commands(self) -> list[str]: ... def warn(self, msg: Text) -> None: ... def execute(self, func: Callable[..., Any], args: Iterable[Any], msg: Text | None = ..., level: int = ...) -> None: ... def mkpath(self, name: str, mode: int = ...) -> None: ... @@ -34,7 +34,7 @@ class Command: preserve_times: int = ..., link: str | None = ..., level: Any = ..., - ) -> Tuple[str, bool]: ... # level is not used + ) -> tuple[str, bool]: ... # level is not used def copy_tree( self, infile: str, @@ -43,7 +43,7 @@ class Command: preserve_times: int = ..., preserve_symlinks: int = ..., level: Any = ..., - ) -> List[str]: ... # level is not used + ) -> list[str]: ... # level is not used def move_file(self, src: str, dst: str, level: Any = ...) -> str: ... # level is not used def spawn(self, cmd: Iterable[str], search_path: int = ..., level: Any = ...) -> None: ... # level is not used def make_archive( @@ -57,10 +57,10 @@ class Command: ) -> str: ... def make_file( self, - infiles: str | List[str] | Tuple[str], + infiles: str | list[str] | tuple[str, ...], outfile: str, func: Callable[..., Any], - args: List[Any], + args: list[Any], exec_msg: str | None = ..., skip_msg: str | None = ..., level: Any = ..., diff --git a/mypy/typeshed/stdlib/@python2/distutils/command/bdist_msi.pyi b/mypy/typeshed/stdlib/@python2/distutils/command/bdist_msi.pyi index 150229fb01c91..09351d29a6734 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/command/bdist_msi.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/command/bdist_msi.pyi @@ -2,6 +2,7 @@ import sys if sys.platform == "win32": from distutils.cmd import Command + class bdist_msi(Command): def initialize_options(self) -> None: ... def finalize_options(self) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/command/config.pyi b/mypy/typeshed/stdlib/@python2/distutils/command/config.pyi index d0fd762e83b27..790a8b485a56f 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/command/config.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/command/config.pyi @@ -3,14 +3,14 @@ from distutils.ccompiler import CCompiler from distutils.core import Command as Command from distutils.errors import DistutilsExecError as DistutilsExecError from distutils.sysconfig import customize_compiler as customize_compiler -from typing import Dict, List, Pattern, Sequence, Tuple +from typing import Pattern, Sequence -LANG_EXT: Dict[str, str] +LANG_EXT: dict[str, str] class config(Command): description: str = ... # Tuple is full name, short name, description - user_options: Sequence[Tuple[str, str | None, str]] = ... + user_options: Sequence[tuple[str, str | None, str]] = ... compiler: str | CCompiler | None = ... cc: str | None = ... include_dirs: Sequence[str] | None = ... @@ -74,7 +74,7 @@ class config(Command): library_dirs: Sequence[str] | None = ..., headers: Sequence[str] | None = ..., include_dirs: Sequence[str] | None = ..., - other_libraries: List[str] = ..., + other_libraries: list[str] = ..., ) -> bool: ... def check_header( self, header: str, include_dirs: Sequence[str] | None = ..., library_dirs: Sequence[str] | None = ..., lang: str = ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/command/install_egg_info.pyi b/mypy/typeshed/stdlib/@python2/distutils/command/install_egg_info.pyi index bf3d0737f2444..1bee1ed07e453 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/command/install_egg_info.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/command/install_egg_info.pyi @@ -1,10 +1,10 @@ from distutils.cmd import Command -from typing import ClassVar, List, Tuple +from typing import ClassVar class install_egg_info(Command): description: ClassVar[str] - user_options: ClassVar[List[Tuple[str, str | None, str]]] + user_options: ClassVar[list[tuple[str, str | None, str]]] def initialize_options(self) -> None: ... def finalize_options(self) -> None: ... def run(self) -> None: ... - def get_outputs(self) -> List[str]: ... + def get_outputs(self) -> list[str]: ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/command/upload.pyi b/mypy/typeshed/stdlib/@python2/distutils/command/upload.pyi index 3835d9fd6ec61..005db872b0bf8 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/command/upload.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/command/upload.pyi @@ -1,8 +1,8 @@ from distutils.config import PyPIRCCommand -from typing import ClassVar, List, Tuple +from typing import ClassVar class upload(PyPIRCCommand): description: ClassVar[str] - boolean_options: ClassVar[List[str]] + boolean_options: ClassVar[list[str]] def run(self) -> None: ... def upload_file(self, command, pyversion, filename) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/config.pyi b/mypy/typeshed/stdlib/@python2/distutils/config.pyi index bcd626c81d483..5814a82841cc9 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/config.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/config.pyi @@ -1,6 +1,6 @@ from abc import abstractmethod from distutils.cmd import Command -from typing import ClassVar, List, Tuple +from typing import ClassVar DEFAULT_PYPIRC: str @@ -9,8 +9,8 @@ class PyPIRCCommand(Command): DEFAULT_REALM: ClassVar[str] repository: None realm: None - user_options: ClassVar[List[Tuple[str, str | None, str]]] - boolean_options: ClassVar[List[str]] + user_options: ClassVar[list[tuple[str, str | None, str]]] + boolean_options: ClassVar[list[str]] def initialize_options(self) -> None: ... def finalize_options(self) -> None: ... @abstractmethod diff --git a/mypy/typeshed/stdlib/@python2/distutils/core.pyi b/mypy/typeshed/stdlib/@python2/distutils/core.pyi index 48bd7b5018bc6..6564c9a86ded8 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/core.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/core.pyi @@ -1,7 +1,7 @@ from distutils.cmd import Command as Command from distutils.dist import Distribution as Distribution from distutils.extension import Extension as Extension -from typing import Any, List, Mapping, Tuple, Type +from typing import Any, Mapping def setup( *, @@ -15,34 +15,34 @@ def setup( maintainer_email: str = ..., url: str = ..., download_url: str = ..., - packages: List[str] = ..., - py_modules: List[str] = ..., - scripts: List[str] = ..., - ext_modules: List[Extension] = ..., - classifiers: List[str] = ..., - distclass: Type[Distribution] = ..., + packages: list[str] = ..., + py_modules: list[str] = ..., + scripts: list[str] = ..., + ext_modules: list[Extension] = ..., + classifiers: list[str] = ..., + distclass: type[Distribution] = ..., script_name: str = ..., - script_args: List[str] = ..., + script_args: list[str] = ..., options: Mapping[str, Any] = ..., license: str = ..., - keywords: List[str] | str = ..., - platforms: List[str] | str = ..., - cmdclass: Mapping[str, Type[Command]] = ..., - data_files: List[Tuple[str, List[str]]] = ..., + keywords: list[str] | str = ..., + platforms: list[str] | str = ..., + cmdclass: Mapping[str, type[Command]] = ..., + data_files: list[tuple[str, list[str]]] = ..., package_dir: Mapping[str, str] = ..., - obsoletes: List[str] = ..., - provides: List[str] = ..., - requires: List[str] = ..., - command_packages: List[str] = ..., - command_options: Mapping[str, Mapping[str, Tuple[Any, Any]]] = ..., - package_data: Mapping[str, List[str]] = ..., + obsoletes: list[str] = ..., + provides: list[str] = ..., + requires: list[str] = ..., + command_packages: list[str] = ..., + command_options: Mapping[str, Mapping[str, tuple[Any, Any]]] = ..., + package_data: Mapping[str, list[str]] = ..., include_package_data: bool = ..., - libraries: List[str] = ..., - headers: List[str] = ..., + libraries: list[str] = ..., + headers: list[str] = ..., ext_package: str = ..., - include_dirs: List[str] = ..., + include_dirs: list[str] = ..., password: str = ..., fullname: str = ..., **attrs: Any, ) -> None: ... -def run_setup(script_name: str, script_args: List[str] | None = ..., stop_after: str = ...) -> Distribution: ... +def run_setup(script_name: str, script_args: list[str] | None = ..., stop_after: str = ...) -> Distribution: ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/dep_util.pyi b/mypy/typeshed/stdlib/@python2/distutils/dep_util.pyi index 6f779d540e5e9..929d6ffd0c81b 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/dep_util.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/dep_util.pyi @@ -1,5 +1,3 @@ -from typing import List, Tuple - def newer(source: str, target: str) -> bool: ... -def newer_pairwise(sources: List[str], targets: List[str]) -> List[Tuple[str, str]]: ... -def newer_group(sources: List[str], target: str, missing: str = ...) -> bool: ... +def newer_pairwise(sources: list[str], targets: list[str]) -> list[tuple[str, str]]: ... +def newer_group(sources: list[str], target: str, missing: str = ...) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/dir_util.pyi b/mypy/typeshed/stdlib/@python2/distutils/dir_util.pyi index 4c4a221025589..ffe5ff1cfbd43 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/dir_util.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/dir_util.pyi @@ -1,7 +1,5 @@ -from typing import List - -def mkpath(name: str, mode: int = ..., verbose: int = ..., dry_run: int = ...) -> List[str]: ... -def create_tree(base_dir: str, files: List[str], mode: int = ..., verbose: int = ..., dry_run: int = ...) -> None: ... +def mkpath(name: str, mode: int = ..., verbose: int = ..., dry_run: int = ...) -> list[str]: ... +def create_tree(base_dir: str, files: list[str], mode: int = ..., verbose: int = ..., dry_run: int = ...) -> None: ... def copy_tree( src: str, dst: str, @@ -11,5 +9,5 @@ def copy_tree( update: int = ..., verbose: int = ..., dry_run: int = ..., -) -> List[str]: ... +) -> list[str]: ... def remove_tree(directory: str, verbose: int = ..., dry_run: int = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/dist.pyi b/mypy/typeshed/stdlib/@python2/distutils/dist.pyi index adba8f0935696..8e6eeafc15b38 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/dist.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/dist.pyi @@ -1,9 +1,9 @@ from distutils.cmd import Command -from typing import Any, Dict, Iterable, Mapping, Text, Tuple, Type +from typing import Any, Iterable, Mapping, Text class Distribution: - cmdclass: Dict[str, Type[Command]] + cmdclass: dict[str, type[Command]] def __init__(self, attrs: Mapping[str, Any] | None = ...) -> None: ... - def get_option_dict(self, command: str) -> Dict[str, Tuple[str, Text]]: ... + def get_option_dict(self, command: str) -> dict[str, tuple[str, Text]]: ... def parse_config_files(self, filenames: Iterable[Text] | None = ...) -> None: ... def get_command_obj(self, command: str, create: bool = ...) -> Command | None: ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/extension.pyi b/mypy/typeshed/stdlib/@python2/distutils/extension.pyi index 9335fad86418d..cff84ef59b6b8 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/extension.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/extension.pyi @@ -1,21 +1,19 @@ -from typing import List, Tuple - class Extension: def __init__( self, name: str, - sources: List[str], - include_dirs: List[str] = ..., - define_macros: List[Tuple[str, str | None]] = ..., - undef_macros: List[str] = ..., - library_dirs: List[str] = ..., - libraries: List[str] = ..., - runtime_library_dirs: List[str] = ..., - extra_objects: List[str] = ..., - extra_compile_args: List[str] = ..., - extra_link_args: List[str] = ..., - export_symbols: List[str] = ..., + sources: list[str], + include_dirs: list[str] = ..., + define_macros: list[tuple[str, str | None]] = ..., + undef_macros: list[str] = ..., + library_dirs: list[str] = ..., + libraries: list[str] = ..., + runtime_library_dirs: list[str] = ..., + extra_objects: list[str] = ..., + extra_compile_args: list[str] = ..., + extra_link_args: list[str] = ..., + export_symbols: list[str] = ..., swig_opts: str | None = ..., # undocumented - depends: List[str] = ..., + depends: list[str] = ..., language: str = ..., ) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/fancy_getopt.pyi b/mypy/typeshed/stdlib/@python2/distutils/fancy_getopt.pyi index d0e3309c2d77c..bf3754aab8ea2 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/fancy_getopt.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/fancy_getopt.pyi @@ -1,21 +1,21 @@ -from typing import Any, List, Mapping, Optional, Tuple, overload +from typing import Any, Mapping, overload -_Option = Tuple[str, Optional[str], str] -_GR = Tuple[List[str], OptionDummy] +_Option = tuple[str, str | None, str] +_GR = tuple[list[str], OptionDummy] def fancy_getopt( - options: List[_Option], negative_opt: Mapping[_Option, _Option], object: Any, args: List[str] | None -) -> List[str] | _GR: ... -def wrap_text(text: str, width: int) -> List[str]: ... + options: list[_Option], negative_opt: Mapping[_Option, _Option], object: Any, args: list[str] | None +) -> list[str] | _GR: ... +def wrap_text(text: str, width: int) -> list[str]: ... class FancyGetopt: - def __init__(self, option_table: List[_Option] | None = ...) -> None: ... + def __init__(self, option_table: list[_Option] | None = ...) -> None: ... # TODO kinda wrong, `getopt(object=object())` is invalid @overload - def getopt(self, args: List[str] | None = ...) -> _GR: ... + def getopt(self, args: list[str] | None = ...) -> _GR: ... @overload - def getopt(self, args: List[str] | None, object: Any) -> List[str]: ... - def get_option_order(self) -> List[Tuple[str, str]]: ... - def generate_help(self, header: str | None = ...) -> List[str]: ... + def getopt(self, args: list[str] | None, object: Any) -> list[str]: ... + def get_option_order(self) -> list[tuple[str, str]]: ... + def generate_help(self, header: str | None = ...) -> list[str]: ... class OptionDummy: ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/file_util.pyi b/mypy/typeshed/stdlib/@python2/distutils/file_util.pyi index cfe840e710403..a7f24105a6788 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/file_util.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/file_util.pyi @@ -1,4 +1,4 @@ -from typing import Sequence, Tuple +from typing import Sequence def copy_file( src: str, @@ -9,6 +9,6 @@ def copy_file( link: str | None = ..., verbose: bool = ..., dry_run: bool = ..., -) -> Tuple[str, str]: ... +) -> tuple[str, str]: ... def move_file(src: str, dst: str, verbose: bool = ..., dry_run: bool = ...) -> str: ... def write_file(filename: str, contents: Sequence[str]) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/spawn.pyi b/mypy/typeshed/stdlib/@python2/distutils/spawn.pyi index 0fffc5402c62c..dda05ad7e85a7 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/spawn.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/spawn.pyi @@ -1,4 +1,2 @@ -from typing import List - -def spawn(cmd: List[str], search_path: bool = ..., verbose: bool = ..., dry_run: bool = ...) -> None: ... +def spawn(cmd: list[str], search_path: bool = ..., verbose: bool = ..., dry_run: bool = ...) -> None: ... def find_executable(executable: str, path: str | None = ...) -> str | None: ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/text_file.pyi b/mypy/typeshed/stdlib/@python2/distutils/text_file.pyi index 26ba5a6fabb69..364bcf9ff1543 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/text_file.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/text_file.pyi @@ -1,4 +1,4 @@ -from typing import IO, List, Tuple +from typing import IO class TextFile: def __init__( @@ -15,7 +15,7 @@ class TextFile: ) -> None: ... def open(self, filename: str) -> None: ... def close(self) -> None: ... - def warn(self, msg: str, line: List[int] | Tuple[int, int] | int = ...) -> None: ... + def warn(self, msg: str, line: list[int] | tuple[int, int] | int = ...) -> None: ... def readline(self) -> str | None: ... - def readlines(self) -> List[str]: ... + def readlines(self) -> list[str]: ... def unreadline(self, line: str) -> str: ... diff --git a/mypy/typeshed/stdlib/@python2/distutils/util.pyi b/mypy/typeshed/stdlib/@python2/distutils/util.pyi index c0882d1dd1cbf..935a695e58dbc 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/util.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/util.pyi @@ -1,17 +1,18 @@ -from typing import Any, Callable, List, Mapping, Tuple +from typing import Any, Callable, Mapping +from typing_extensions import Literal def get_platform() -> str: ... def convert_path(pathname: str) -> str: ... def change_root(new_root: str, pathname: str) -> str: ... def check_environ() -> None: ... def subst_vars(s: str, local_vars: Mapping[str, str]) -> None: ... -def split_quoted(s: str) -> List[str]: ... +def split_quoted(s: str) -> list[str]: ... def execute( - func: Callable[..., None], args: Tuple[Any, ...], msg: str | None = ..., verbose: bool = ..., dry_run: bool = ... + func: Callable[..., None], args: tuple[Any, ...], msg: str | None = ..., verbose: bool = ..., dry_run: bool = ... ) -> None: ... -def strtobool(val: str) -> bool: ... +def strtobool(val: str) -> Literal[0, 1]: ... def byte_compile( - py_files: List[str], + py_files: list[str], optimize: int = ..., force: bool = ..., prefix: str | None = ..., diff --git a/mypy/typeshed/stdlib/@python2/distutils/version.pyi b/mypy/typeshed/stdlib/@python2/distutils/version.pyi index dd0969b8635f0..0e37a3a1a90cc 100644 --- a/mypy/typeshed/stdlib/@python2/distutils/version.pyi +++ b/mypy/typeshed/stdlib/@python2/distutils/version.pyi @@ -1,14 +1,14 @@ +from _typeshed import Self from abc import abstractmethod -from typing import Pattern, Text, Tuple, TypeVar +from typing import Pattern, Text, TypeVar _T = TypeVar("_T", bound=Version) class Version: - def __repr__(self) -> str: ... @abstractmethod def __init__(self, vstring: Text | None = ...) -> None: ... @abstractmethod - def parse(self: _T, vstring: Text) -> _T: ... + def parse(self: Self, vstring: Text) -> Self: ... @abstractmethod def __str__(self) -> str: ... @abstractmethod @@ -16,18 +16,18 @@ class Version: class StrictVersion(Version): version_re: Pattern[str] - version: Tuple[int, int, int] - prerelease: Tuple[Text, int] | None + version: tuple[int, int, int] + prerelease: tuple[Text, int] | None def __init__(self, vstring: Text | None = ...) -> None: ... - def parse(self: _T, vstring: Text) -> _T: ... - def __str__(self) -> str: ... + def parse(self: Self, vstring: Text) -> Self: ... + def __str__(self) -> str: ... # noqa: Y029 def __cmp__(self: _T, other: _T | str) -> bool: ... class LooseVersion(Version): component_re: Pattern[str] vstring: Text - version: Tuple[Text | int, ...] + version: tuple[Text | int, ...] def __init__(self, vstring: Text | None = ...) -> None: ... - def parse(self: _T, vstring: Text) -> _T: ... - def __str__(self) -> str: ... + def parse(self: Self, vstring: Text) -> Self: ... + def __str__(self) -> str: ... # noqa: Y029 def __cmp__(self: _T, other: _T | str) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/doctest.pyi b/mypy/typeshed/stdlib/@python2/doctest.pyi index 6c3b922244f4a..9f95d122eea51 100644 --- a/mypy/typeshed/stdlib/@python2/doctest.pyi +++ b/mypy/typeshed/stdlib/@python2/doctest.pyi @@ -1,12 +1,12 @@ import types import unittest -from typing import Any, Callable, Dict, List, NamedTuple, Tuple, Type +from typing import Any, Callable, NamedTuple class TestResults(NamedTuple): failed: int attempted: int -OPTIONFLAGS_BY_NAME: Dict[str, int] +OPTIONFLAGS_BY_NAME: dict[str, int] def register_optionflag(name: str) -> int: ... @@ -34,7 +34,7 @@ class Example: exc_msg: str | None lineno: int indent: int - options: Dict[int, bool] + options: dict[int, bool] def __init__( self, source: str, @@ -42,21 +42,21 @@ class Example: exc_msg: str | None = ..., lineno: int = ..., indent: int = ..., - options: Dict[int, bool] | None = ..., + options: dict[int, bool] | None = ..., ) -> None: ... def __hash__(self) -> int: ... class DocTest: - examples: List[Example] - globs: Dict[str, Any] + examples: list[Example] + globs: dict[str, Any] name: str filename: str | None lineno: int | None docstring: str | None def __init__( self, - examples: List[Example], - globs: Dict[str, Any], + examples: list[Example], + globs: dict[str, Any], name: str, filename: str | None, lineno: int | None, @@ -66,9 +66,9 @@ class DocTest: def __lt__(self, other: DocTest) -> bool: ... class DocTestParser: - def parse(self, string: str, name: str = ...) -> List[str | Example]: ... - def get_doctest(self, string: str, globs: Dict[str, Any], name: str, filename: str | None, lineno: int | None) -> DocTest: ... - def get_examples(self, string: str, name: str = ...) -> List[Example]: ... + def parse(self, string: str, name: str = ...) -> list[str | Example]: ... + def get_doctest(self, string: str, globs: dict[str, Any], name: str, filename: str | None, lineno: int | None) -> DocTest: ... + def get_examples(self, string: str, name: str = ...) -> list[Example]: ... class DocTestFinder: def __init__( @@ -79,12 +79,12 @@ class DocTestFinder: obj: object, name: str | None = ..., module: None | bool | types.ModuleType = ..., - globs: Dict[str, Any] | None = ..., - extraglobs: Dict[str, Any] | None = ..., - ) -> List[DocTest]: ... + globs: dict[str, Any] | None = ..., + extraglobs: dict[str, Any] | None = ..., + ) -> list[DocTest]: ... _Out = Callable[[str], Any] -_ExcInfo = Tuple[Type[BaseException], BaseException, types.TracebackType] +_ExcInfo = tuple[type[BaseException], BaseException, types.TracebackType] class DocTestRunner: DIVIDER: str @@ -127,11 +127,11 @@ master: DocTestRunner | None def testmod( m: types.ModuleType | None = ..., name: str | None = ..., - globs: Dict[str, Any] | None = ..., + globs: dict[str, Any] | None = ..., verbose: bool | None = ..., report: bool = ..., optionflags: int = ..., - extraglobs: Dict[str, Any] | None = ..., + extraglobs: dict[str, Any] | None = ..., raise_on_error: bool = ..., exclude_empty: bool = ..., ) -> TestResults: ... @@ -140,17 +140,17 @@ def testfile( module_relative: bool = ..., name: str | None = ..., package: None | str | types.ModuleType = ..., - globs: Dict[str, Any] | None = ..., + globs: dict[str, Any] | None = ..., verbose: bool | None = ..., report: bool = ..., optionflags: int = ..., - extraglobs: Dict[str, Any] | None = ..., + extraglobs: dict[str, Any] | None = ..., raise_on_error: bool = ..., parser: DocTestParser = ..., encoding: str | None = ..., ) -> TestResults: ... def run_docstring_examples( - f: object, globs: Dict[str, Any], verbose: bool = ..., name: str = ..., compileflags: int | None = ..., optionflags: int = ... + f: object, globs: dict[str, Any], verbose: bool = ..., name: str = ..., compileflags: int | None = ..., optionflags: int = ... ) -> None: ... def set_unittest_reportflags(flags: int) -> int: ... @@ -182,8 +182,8 @@ _DocTestSuite = unittest.TestSuite def DocTestSuite( module: None | str | types.ModuleType = ..., - globs: Dict[str, Any] | None = ..., - extraglobs: Dict[str, Any] | None = ..., + globs: dict[str, Any] | None = ..., + extraglobs: dict[str, Any] | None = ..., test_finder: DocTestFinder | None = ..., **options: Any, ) -> _DocTestSuite: ... @@ -196,7 +196,7 @@ def DocFileTest( path: str, module_relative: bool = ..., package: None | str | types.ModuleType = ..., - globs: Dict[str, Any] | None = ..., + globs: dict[str, Any] | None = ..., parser: DocTestParser = ..., encoding: str | None = ..., **options: Any, @@ -204,6 +204,6 @@ def DocFileTest( def DocFileSuite(*paths: str, **kw: Any) -> _DocTestSuite: ... def script_from_examples(s: str) -> str: ... def testsource(module: None | str | types.ModuleType, name: str) -> str: ... -def debug_src(src: str, pm: bool = ..., globs: Dict[str, Any] | None = ...) -> None: ... -def debug_script(src: str, pm: bool = ..., globs: Dict[str, Any] | None = ...) -> None: ... +def debug_src(src: str, pm: bool = ..., globs: dict[str, Any] | None = ...) -> None: ... +def debug_script(src: str, pm: bool = ..., globs: dict[str, Any] | None = ...) -> None: ... def debug(module: None | str | types.ModuleType, name: str, pm: bool = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/dummy_thread.pyi b/mypy/typeshed/stdlib/@python2/dummy_thread.pyi index 0a28b3aaeeb9e..1bd324b7eaaf9 100644 --- a/mypy/typeshed/stdlib/@python2/dummy_thread.pyi +++ b/mypy/typeshed/stdlib/@python2/dummy_thread.pyi @@ -1,9 +1,9 @@ -from typing import Any, Callable, Dict, NoReturn, Tuple +from typing import Any, Callable, NoReturn class error(Exception): def __init__(self, *args: Any) -> None: ... -def start_new_thread(function: Callable[..., Any], args: Tuple[Any, ...], kwargs: Dict[str, Any] = ...) -> None: ... +def start_new_thread(function: Callable[..., Any], args: tuple[Any, ...], kwargs: dict[str, Any] = ...) -> None: ... def exit() -> NoReturn: ... def get_ident() -> int: ... def allocate_lock() -> LockType: ... diff --git a/mypy/typeshed/stdlib/@python2/email/mime/application.pyi b/mypy/typeshed/stdlib/@python2/email/mime/application.pyi index 4245e3e0f9804..cb8c281261fe2 100644 --- a/mypy/typeshed/stdlib/@python2/email/mime/application.pyi +++ b/mypy/typeshed/stdlib/@python2/email/mime/application.pyi @@ -1,7 +1,7 @@ from email.mime.nonmultipart import MIMENonMultipart -from typing import Callable, Optional, Tuple, Union +from typing import Callable, Union -_ParamsType = Union[str, None, Tuple[str, Optional[str], str]] +_ParamsType = Union[str, None, tuple[str, str | None, str]] class MIMEApplication(MIMENonMultipart): def __init__( diff --git a/mypy/typeshed/stdlib/@python2/encodings/utf_8.pyi b/mypy/typeshed/stdlib/@python2/encodings/utf_8.pyi index d38bd58d0e43c..349b61432eab3 100644 --- a/mypy/typeshed/stdlib/@python2/encodings/utf_8.pyi +++ b/mypy/typeshed/stdlib/@python2/encodings/utf_8.pyi @@ -1,11 +1,11 @@ import codecs -from typing import Text, Tuple +from typing import Text class IncrementalEncoder(codecs.IncrementalEncoder): def encode(self, input: Text, final: bool = ...) -> bytes: ... class IncrementalDecoder(codecs.BufferedIncrementalDecoder): - def _buffer_decode(self, input: bytes, errors: str, final: bool) -> Tuple[Text, int]: ... + def _buffer_decode(self, input: bytes, errors: str, final: bool) -> tuple[Text, int]: ... class StreamWriter(codecs.StreamWriter): ... class StreamReader(codecs.StreamReader): ... diff --git a/mypy/typeshed/stdlib/@python2/filecmp.pyi b/mypy/typeshed/stdlib/@python2/filecmp.pyi index 0be5596c2bdb2..c50faedf2fa14 100644 --- a/mypy/typeshed/stdlib/@python2/filecmp.pyi +++ b/mypy/typeshed/stdlib/@python2/filecmp.pyi @@ -1,11 +1,11 @@ -from typing import AnyStr, Callable, Dict, Generic, Iterable, List, Sequence, Text, Tuple +from typing import AnyStr, Callable, Generic, Iterable, Sequence, Text -DEFAULT_IGNORES: List[str] +DEFAULT_IGNORES: list[str] def cmp(f1: bytes | Text, f2: bytes | Text, shallow: int | bool = ...) -> bool: ... def cmpfiles( a: AnyStr, b: AnyStr, common: Iterable[AnyStr], shallow: int | bool = ... -) -> Tuple[List[AnyStr], List[AnyStr], List[AnyStr]]: ... +) -> tuple[list[AnyStr], list[AnyStr], list[AnyStr]]: ... class dircmp(Generic[AnyStr]): def __init__( @@ -16,22 +16,22 @@ class dircmp(Generic[AnyStr]): hide: Sequence[AnyStr] ignore: Sequence[AnyStr] # These properties are created at runtime by __getattr__ - subdirs: Dict[AnyStr, dircmp[AnyStr]] - same_files: List[AnyStr] - diff_files: List[AnyStr] - funny_files: List[AnyStr] - common_dirs: List[AnyStr] - common_files: List[AnyStr] - common_funny: List[AnyStr] - common: List[AnyStr] - left_only: List[AnyStr] - right_only: List[AnyStr] - left_list: List[AnyStr] - right_list: List[AnyStr] + subdirs: dict[AnyStr, dircmp[AnyStr]] + same_files: list[AnyStr] + diff_files: list[AnyStr] + funny_files: list[AnyStr] + common_dirs: list[AnyStr] + common_files: list[AnyStr] + common_funny: list[AnyStr] + common: list[AnyStr] + left_only: list[AnyStr] + right_only: list[AnyStr] + left_list: list[AnyStr] + right_list: list[AnyStr] def report(self) -> None: ... def report_partial_closure(self) -> None: ... def report_full_closure(self) -> None: ... - methodmap: Dict[str, Callable[[], None]] + methodmap: dict[str, Callable[[], None]] def phase0(self) -> None: ... def phase1(self) -> None: ... def phase2(self) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/fnmatch.pyi b/mypy/typeshed/stdlib/@python2/fnmatch.pyi index e933b7b2cb623..942a52bbac9a2 100644 --- a/mypy/typeshed/stdlib/@python2/fnmatch.pyi +++ b/mypy/typeshed/stdlib/@python2/fnmatch.pyi @@ -1,8 +1,8 @@ -from typing import AnyStr, Iterable, List, Union +from typing import AnyStr, Iterable -_EitherStr = Union[str, unicode] +_EitherStr = str | unicode def fnmatch(filename: _EitherStr, pattern: _EitherStr) -> bool: ... def fnmatchcase(filename: _EitherStr, pattern: _EitherStr) -> bool: ... -def filter(names: Iterable[AnyStr], pattern: _EitherStr) -> List[AnyStr]: ... +def filter(names: Iterable[AnyStr], pattern: _EitherStr) -> list[AnyStr]: ... def translate(pattern: AnyStr) -> AnyStr: ... diff --git a/mypy/typeshed/stdlib/@python2/formatter.pyi b/mypy/typeshed/stdlib/@python2/formatter.pyi index da165f2d55e34..f5d8348d08a1d 100644 --- a/mypy/typeshed/stdlib/@python2/formatter.pyi +++ b/mypy/typeshed/stdlib/@python2/formatter.pyi @@ -1,8 +1,8 @@ -from typing import IO, Any, Iterable, List, Tuple +from typing import IO, Any, Iterable AS_IS: None -_FontType = Tuple[str, bool, bool, bool] -_StylesType = Tuple[Any, ...] +_FontType = tuple[str, bool, bool, bool] +_StylesType = tuple[Any, ...] class NullFormatter: writer: NullWriter | None @@ -28,9 +28,9 @@ class NullFormatter: class AbstractFormatter: writer: NullWriter align: str | None - align_stack: List[str | None] - font_stack: List[_FontType] - margin_stack: List[int] + align_stack: list[str | None] + font_stack: list[_FontType] + margin_stack: list[int] spacing: str | None style_stack: Any nospace: int @@ -68,7 +68,7 @@ class NullWriter: def new_font(self, font: _FontType) -> None: ... def new_margin(self, margin: int, level: int) -> None: ... def new_spacing(self, spacing: str | None) -> None: ... - def new_styles(self, styles: Tuple[Any, ...]) -> None: ... + def new_styles(self, styles: tuple[Any, ...]) -> None: ... def send_paragraph(self, blankline: int) -> None: ... def send_line_break(self) -> None: ... def send_hor_rule(self, *args: Any, **kw: Any) -> None: ... @@ -81,7 +81,7 @@ class AbstractWriter(NullWriter): def new_font(self, font: _FontType) -> None: ... def new_margin(self, margin: int, level: int) -> None: ... def new_spacing(self, spacing: str | None) -> None: ... - def new_styles(self, styles: Tuple[Any, ...]) -> None: ... + def new_styles(self, styles: tuple[Any, ...]) -> None: ... def send_paragraph(self, blankline: int) -> None: ... def send_line_break(self) -> None: ... def send_hor_rule(self, *args: Any, **kw: Any) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/fractions.pyi b/mypy/typeshed/stdlib/@python2/fractions.pyi index 872e20ede6887..27de79248c03d 100644 --- a/mypy/typeshed/stdlib/@python2/fractions.pyi +++ b/mypy/typeshed/stdlib/@python2/fractions.pyi @@ -1,10 +1,10 @@ +from _typeshed import Self from decimal import Decimal from numbers import Integral, Rational, Real -from typing import Tuple, Type, TypeVar, Union, overload +from typing import overload from typing_extensions import Literal -_ComparableNum = Union[int, float, Decimal, Real] -_T = TypeVar("_T") +_ComparableNum = int | float | Decimal | Real @overload def gcd(a: int, b: int) -> int: ... @@ -18,10 +18,10 @@ def gcd(a: Integral, b: Integral) -> Integral: ... class Fraction(Rational): @overload def __new__( - cls: Type[_T], numerator: int | Rational = ..., denominator: int | Rational | None = ..., *, _normalize: bool = ... - ) -> _T: ... + cls: type[Self], numerator: int | Rational = ..., denominator: int | Rational | None = ..., *, _normalize: bool = ... + ) -> Self: ... @overload - def __new__(cls: Type[_T], __value: float | Decimal | str, *, _normalize: bool = ...) -> _T: ... + def __new__(cls: type[Self], __value: float | Decimal | str, *, _normalize: bool = ...) -> Self: ... @classmethod def from_float(cls, f: float) -> Fraction: ... @classmethod @@ -108,13 +108,13 @@ class Fraction(Rational): @overload def __rmod__(self, other: float) -> float: ... @overload - def __divmod__(self, other: int | Fraction) -> Tuple[int, Fraction]: ... + def __divmod__(self, other: int | Fraction) -> tuple[int, Fraction]: ... @overload - def __divmod__(self, other: float) -> Tuple[float, Fraction]: ... + def __divmod__(self, other: float) -> tuple[float, Fraction]: ... @overload - def __rdivmod__(self, other: int | Fraction) -> Tuple[int, Fraction]: ... + def __rdivmod__(self, other: int | Fraction) -> tuple[int, Fraction]: ... @overload - def __rdivmod__(self, other: float) -> Tuple[float, Fraction]: ... + def __rdivmod__(self, other: float) -> tuple[float, Fraction]: ... @overload def __pow__(self, other: int) -> Fraction: ... @overload diff --git a/mypy/typeshed/stdlib/@python2/ftplib.pyi b/mypy/typeshed/stdlib/@python2/ftplib.pyi index 0931a9d171cdb..870d00d804cea 100644 --- a/mypy/typeshed/stdlib/@python2/ftplib.pyi +++ b/mypy/typeshed/stdlib/@python2/ftplib.pyi @@ -1,11 +1,10 @@ from _typeshed import SupportsRead, SupportsReadline from socket import socket from ssl import SSLContext -from typing import Any, BinaryIO, Callable, List, Text, Tuple, Type, TypeVar, Union +from typing import Any, BinaryIO, Callable, Text from typing_extensions import Literal -_T = TypeVar("_T") -_IntOrStr = Union[int, Text] +_IntOrStr = int | Text MSG_OOB: int FTP_PORT: int @@ -18,7 +17,7 @@ class error_temp(Error): ... class error_perm(Error): ... class error_proto(Error): ... -all_errors: Tuple[Type[Exception], ...] +all_errors: tuple[type[Exception], ...] class FTP: debugging: int @@ -58,10 +57,10 @@ class FTP: def sendport(self, host: Text, port: int) -> str: ... def sendeprt(self, host: Text, port: int) -> str: ... def makeport(self) -> socket: ... - def makepasv(self) -> Tuple[str, int]: ... + def makepasv(self) -> tuple[str, int]: ... def login(self, user: Text = ..., passwd: Text = ..., acct: Text = ...) -> str: ... # In practice, `rest` rest can actually be anything whose str() is an integer sequence, so to make it simple we allow integers. - def ntransfercmd(self, cmd: Text, rest: _IntOrStr | None = ...) -> Tuple[socket, int]: ... + def ntransfercmd(self, cmd: Text, rest: _IntOrStr | None = ...) -> tuple[socket, int]: ... def transfercmd(self, cmd: Text, rest: _IntOrStr | None = ...) -> socket: ... def retrbinary( self, cmd: Text, callback: Callable[[bytes], Any], blocksize: int = ..., rest: _IntOrStr | None = ... @@ -77,7 +76,7 @@ class FTP: def retrlines(self, cmd: Text, callback: Callable[[str], Any] | None = ...) -> str: ... def storlines(self, cmd: Text, fp: SupportsReadline[bytes], callback: Callable[[bytes], Any] | None = ...) -> str: ... def acct(self, password: Text) -> str: ... - def nlst(self, *args: Text) -> List[str]: ... + def nlst(self, *args: Text) -> list[str]: ... # Technically only the last arg can be a Callable but ... def dir(self, *args: str | Callable[[str], None]) -> None: ... def rename(self, fromname: Text, toname: Text) -> str: ... @@ -101,7 +100,7 @@ class FTP_TLS(FTP): certfile: str | None = ..., context: SSLContext | None = ..., timeout: float = ..., - source_address: Tuple[str, int] | None = ..., + source_address: tuple[str, int] | None = ..., ) -> None: ... ssl_version: int keyfile: str | None @@ -114,14 +113,14 @@ class FTP_TLS(FTP): class Netrc: def __init__(self, filename: Text | None = ...) -> None: ... - def get_hosts(self) -> List[str]: ... - def get_account(self, host: Text) -> Tuple[str | None, str | None, str | None]: ... - def get_macros(self) -> List[str]: ... - def get_macro(self, macro: Text) -> Tuple[str, ...]: ... + def get_hosts(self) -> list[str]: ... + def get_account(self, host: Text) -> tuple[str | None, str | None, str | None]: ... + def get_macros(self) -> list[str]: ... + def get_macro(self, macro: Text) -> tuple[str, ...]: ... def parse150(resp: str) -> int | None: ... # undocumented -def parse227(resp: str) -> Tuple[str, int]: ... # undocumented -def parse229(resp: str, peer: Any) -> Tuple[str, int]: ... # undocumented +def parse227(resp: str) -> tuple[str, int]: ... # undocumented +def parse229(resp: str, peer: Any) -> tuple[str, int]: ... # undocumented def parse257(resp: str) -> str: ... # undocumented def ftpcp( source: FTP, sourcename: str, target: FTP, targetname: str = ..., type: Literal["A", "I"] = ... diff --git a/mypy/typeshed/stdlib/@python2/functools.pyi b/mypy/typeshed/stdlib/@python2/functools.pyi index dd873708fea4e..026a74faf6ff1 100644 --- a/mypy/typeshed/stdlib/@python2/functools.pyi +++ b/mypy/typeshed/stdlib/@python2/functools.pyi @@ -1,4 +1,4 @@ -from typing import Any, Callable, Dict, Generic, Iterable, Sequence, Tuple, Type, TypeVar, overload +from typing import Any, Callable, Generic, Iterable, Sequence, TypeVar, overload _AnyCallable = Callable[..., Any] @@ -19,12 +19,12 @@ def update_wrapper( def wraps( wrapped: _AnyCallable, assigned: Sequence[str] = ..., updated: Sequence[str] = ... ) -> Callable[[_AnyCallable], _AnyCallable]: ... -def total_ordering(cls: Type[_T]) -> Type[_T]: ... +def total_ordering(cls: type[_T]) -> type[_T]: ... def cmp_to_key(mycmp: Callable[[_T, _T], int]) -> Callable[[_T], Any]: ... class partial(Generic[_T]): func = ... # Callable[..., _T] - args: Tuple[Any, ...] - keywords: Dict[str, Any] + args: tuple[Any, ...] + keywords: dict[str, Any] def __init__(self, func: Callable[..., _T], *args: Any, **kwargs: Any) -> None: ... def __call__(self, *args: Any, **kwargs: Any) -> _T: ... diff --git a/mypy/typeshed/stdlib/@python2/gc.pyi b/mypy/typeshed/stdlib/@python2/gc.pyi index b1fb1acc07d28..0ee05387a5a8d 100644 --- a/mypy/typeshed/stdlib/@python2/gc.pyi +++ b/mypy/typeshed/stdlib/@python2/gc.pyi @@ -1,4 +1,4 @@ -from typing import Any, List, Tuple +from typing import Any def enable() -> None: ... def disable() -> None: ... @@ -6,15 +6,15 @@ def isenabled() -> bool: ... def collect(generation: int = ...) -> int: ... def set_debug(flags: int) -> None: ... def get_debug() -> int: ... -def get_objects() -> List[Any]: ... +def get_objects() -> list[Any]: ... def set_threshold(threshold0: int, threshold1: int = ..., threshold2: int = ...) -> None: ... -def get_count() -> Tuple[int, int, int]: ... -def get_threshold() -> Tuple[int, int, int]: ... -def get_referrers(*objs: Any) -> List[Any]: ... -def get_referents(*objs: Any) -> List[Any]: ... +def get_count() -> tuple[int, int, int]: ... +def get_threshold() -> tuple[int, int, int]: ... +def get_referrers(*objs: Any) -> list[Any]: ... +def get_referents(*objs: Any) -> list[Any]: ... def is_tracked(obj: Any) -> bool: ... -garbage: List[Any] +garbage: list[Any] DEBUG_STATS: int DEBUG_COLLECTABLE: int diff --git a/mypy/typeshed/stdlib/@python2/genericpath.pyi b/mypy/typeshed/stdlib/@python2/genericpath.pyi index ba29db4692bbc..7ff27a62f9590 100644 --- a/mypy/typeshed/stdlib/@python2/genericpath.pyi +++ b/mypy/typeshed/stdlib/@python2/genericpath.pyi @@ -1,18 +1,18 @@ from _typeshed import SupportsLessThanT -from typing import List, Sequence, Text, Tuple, Union, overload +from typing import Sequence, Text, overload from typing_extensions import Literal # All overloads can return empty string. Ideally, Literal[""] would be a valid # Iterable[T], so that Union[List[T], Literal[""]] could be used as a return # type. But because this only works when T is str, we need Sequence[T] instead. @overload -def commonprefix(m: Sequence[str]) -> str | Literal[""]: ... # type: ignore +def commonprefix(m: Sequence[str]) -> str | Literal[""]: ... # type: ignore[misc] @overload -def commonprefix(m: Sequence[Text]) -> Text: ... # type: ignore +def commonprefix(m: Sequence[Text]) -> Text: ... @overload -def commonprefix(m: Sequence[List[SupportsLessThanT]]) -> Sequence[SupportsLessThanT]: ... +def commonprefix(m: Sequence[list[SupportsLessThanT]]) -> Sequence[SupportsLessThanT]: ... @overload -def commonprefix(m: Sequence[Tuple[SupportsLessThanT, ...]]) -> Sequence[SupportsLessThanT]: ... +def commonprefix(m: Sequence[tuple[SupportsLessThanT, ...]]) -> Sequence[SupportsLessThanT]: ... def exists(path: Text) -> bool: ... def getsize(filename: Text) -> int: ... def isfile(path: Text) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/getopt.pyi b/mypy/typeshed/stdlib/@python2/getopt.pyi index 370d4d5c1cba6..b1e90a6c5a675 100644 --- a/mypy/typeshed/stdlib/@python2/getopt.pyi +++ b/mypy/typeshed/stdlib/@python2/getopt.pyi @@ -1,12 +1,9 @@ -from typing import List, Tuple - class GetoptError(Exception): opt: str msg: str def __init__(self, msg: str, opt: str = ...) -> None: ... - def __str__(self) -> str: ... error = GetoptError -def getopt(args: List[str], shortopts: str, longopts: List[str] = ...) -> Tuple[List[Tuple[str, str]], List[str]]: ... -def gnu_getopt(args: List[str], shortopts: str, longopts: List[str] = ...) -> Tuple[List[Tuple[str, str]], List[str]]: ... +def getopt(args: list[str], shortopts: str, longopts: list[str] = ...) -> tuple[list[tuple[str, str]], list[str]]: ... +def gnu_getopt(args: list[str], shortopts: str, longopts: list[str] = ...) -> tuple[list[tuple[str, str]], list[str]]: ... diff --git a/mypy/typeshed/stdlib/@python2/gettext.pyi b/mypy/typeshed/stdlib/@python2/gettext.pyi index a91234f6b2d3c..02e306978160e 100644 --- a/mypy/typeshed/stdlib/@python2/gettext.pyi +++ b/mypy/typeshed/stdlib/@python2/gettext.pyi @@ -1,4 +1,4 @@ -from typing import IO, Any, Container, Dict, List, Sequence, Type +from typing import IO, Any, Container, Sequence def bindtextdomain(domain: str, localedir: str = ...) -> str: ... def bind_textdomain_codeset(domain: str, codeset: str = ...) -> str: ... @@ -22,7 +22,7 @@ class NullTranslations(object): def ngettext(self, singular: str, plural: str, n: int) -> str: ... def lngettext(self, singular: str, plural: str, n: int) -> str: ... def ungettext(self, singular: str | unicode, plural: str | unicode, n: int) -> unicode: ... - def info(self) -> Dict[str, str]: ... + def info(self) -> dict[str, str]: ... def charset(self) -> str | None: ... def output_charset(self) -> str | None: ... def set_output_charset(self, charset: str | None) -> None: ... @@ -34,12 +34,12 @@ class GNUTranslations(NullTranslations): def find( domain: str, localedir: str | None = ..., languages: Sequence[str] | None = ..., all: Any = ... -) -> str | List[str] | None: ... +) -> str | list[str] | None: ... def translation( domain: str, localedir: str | None = ..., languages: Sequence[str] | None = ..., - class_: Type[NullTranslations] | None = ..., + class_: type[NullTranslations] | None = ..., fallback: bool = ..., codeset: str | None = ..., ) -> NullTranslations: ... diff --git a/mypy/typeshed/stdlib/@python2/glob.pyi b/mypy/typeshed/stdlib/@python2/glob.pyi index f5a389a0ddfae..2fc01a03a48b2 100644 --- a/mypy/typeshed/stdlib/@python2/glob.pyi +++ b/mypy/typeshed/stdlib/@python2/glob.pyi @@ -1,7 +1,7 @@ -from typing import AnyStr, Iterator, List +from typing import AnyStr, Iterator -def glob(pathname: AnyStr) -> List[AnyStr]: ... +def glob(pathname: AnyStr) -> list[AnyStr]: ... def iglob(pathname: AnyStr) -> Iterator[AnyStr]: ... -def glob1(dirname: str | unicode, pattern: AnyStr) -> List[AnyStr]: ... -def glob0(dirname: str | unicode, basename: AnyStr) -> List[AnyStr]: ... +def glob1(dirname: str | unicode, pattern: AnyStr) -> list[AnyStr]: ... +def glob0(dirname: str | unicode, basename: AnyStr) -> list[AnyStr]: ... def has_magic(s: str | unicode) -> bool: ... # undocumented diff --git a/mypy/typeshed/stdlib/@python2/grp.pyi b/mypy/typeshed/stdlib/@python2/grp.pyi index 6e937ec0f2629..1651663eb2425 100644 --- a/mypy/typeshed/stdlib/@python2/grp.pyi +++ b/mypy/typeshed/stdlib/@python2/grp.pyi @@ -1,12 +1,12 @@ import sys -from typing import List, NamedTuple +from typing import NamedTuple if sys.platform != "win32": class struct_group(NamedTuple): gr_name: str gr_passwd: str | None gr_gid: int - gr_mem: List[str] - def getgrall() -> List[struct_group]: ... + gr_mem: list[str] + def getgrall() -> list[struct_group]: ... def getgrgid(id: int) -> struct_group: ... def getgrnam(name: str) -> struct_group: ... diff --git a/mypy/typeshed/stdlib/@python2/hashlib.pyi b/mypy/typeshed/stdlib/@python2/hashlib.pyi index 9c53d2b6b30d9..86e6c21159a62 100644 --- a/mypy/typeshed/stdlib/@python2/hashlib.pyi +++ b/mypy/typeshed/stdlib/@python2/hashlib.pyi @@ -1,6 +1,4 @@ -from typing import Tuple, Union - -_DataType = Union[str, unicode, bytearray, buffer, memoryview] +_DataType = str | unicode | bytearray | buffer | memoryview class _hash(object): # This is not actually in the module namespace. @property @@ -25,8 +23,8 @@ def sha256(s: _DataType = ...) -> _hash: ... def sha384(s: _DataType = ...) -> _hash: ... def sha512(s: _DataType = ...) -> _hash: ... -algorithms: Tuple[str, ...] -algorithms_guaranteed: Tuple[str, ...] -algorithms_available: Tuple[str, ...] +algorithms: tuple[str, ...] +algorithms_guaranteed: tuple[str, ...] +algorithms_available: tuple[str, ...] def pbkdf2_hmac(name: str, password: str, salt: str, rounds: int, dklen: int = ...) -> str: ... diff --git a/mypy/typeshed/stdlib/@python2/heapq.pyi b/mypy/typeshed/stdlib/@python2/heapq.pyi index 78ce6fd039286..5c393436d3c27 100644 --- a/mypy/typeshed/stdlib/@python2/heapq.pyi +++ b/mypy/typeshed/stdlib/@python2/heapq.pyi @@ -1,15 +1,15 @@ from _typeshed import SupportsLessThan -from typing import Callable, Iterable, List, TypeVar +from typing import Callable, Iterable, TypeVar _T = TypeVar("_T") def cmp_lt(x, y) -> bool: ... -def heappush(heap: List[_T], item: _T) -> None: ... -def heappop(heap: List[_T]) -> _T: ... -def heappushpop(heap: List[_T], item: _T) -> _T: ... -def heapify(x: List[_T]) -> None: ... -def heapreplace(heap: List[_T], item: _T) -> _T: ... +def heappush(heap: list[_T], item: _T) -> None: ... +def heappop(heap: list[_T]) -> _T: ... +def heappushpop(heap: list[_T], item: _T) -> _T: ... +def heapify(x: list[_T]) -> None: ... +def heapreplace(heap: list[_T], item: _T) -> _T: ... def merge(*iterables: Iterable[_T]) -> Iterable[_T]: ... -def nlargest(n: int, iterable: Iterable[_T], key: Callable[[_T], SupportsLessThan] | None = ...) -> List[_T]: ... -def nsmallest(n: int, iterable: Iterable[_T], key: Callable[[_T], SupportsLessThan] | None = ...) -> List[_T]: ... -def _heapify_max(__x: List[_T]) -> None: ... # undocumented +def nlargest(n: int, iterable: Iterable[_T], key: Callable[[_T], SupportsLessThan] | None = ...) -> list[_T]: ... +def nsmallest(n: int, iterable: Iterable[_T], key: Callable[[_T], SupportsLessThan] | None = ...) -> list[_T]: ... +def _heapify_max(__x: list[_T]) -> None: ... # undocumented diff --git a/mypy/typeshed/stdlib/@python2/hmac.pyi b/mypy/typeshed/stdlib/@python2/hmac.pyi index cc39d8c65c8f4..a244f4112e875 100644 --- a/mypy/typeshed/stdlib/@python2/hmac.pyi +++ b/mypy/typeshed/stdlib/@python2/hmac.pyi @@ -1,10 +1,10 @@ from _typeshed import ReadableBuffer from types import ModuleType -from typing import Any, AnyStr, Callable, Union, overload +from typing import Any, AnyStr, Callable, overload # TODO more precise type for object of hashlib _Hash = Any -_DigestMod = Union[str, Callable[[], _Hash], ModuleType] +_DigestMod = str | Callable[[], _Hash] | ModuleType digest_size: None diff --git a/mypy/typeshed/stdlib/@python2/htmlentitydefs.pyi b/mypy/typeshed/stdlib/@python2/htmlentitydefs.pyi index 749b3039dfc38..3fcc4be2d5a08 100644 --- a/mypy/typeshed/stdlib/@python2/htmlentitydefs.pyi +++ b/mypy/typeshed/stdlib/@python2/htmlentitydefs.pyi @@ -1,5 +1,3 @@ -from typing import Dict - -name2codepoint: Dict[str, int] -codepoint2name: Dict[int, str] -entitydefs: Dict[str, str] +name2codepoint: dict[str, int] +codepoint2name: dict[int, str] +entitydefs: dict[str, str] diff --git a/mypy/typeshed/stdlib/@python2/httplib.pyi b/mypy/typeshed/stdlib/@python2/httplib.pyi index f2163818fae49..b72423fc8ea98 100644 --- a/mypy/typeshed/stdlib/@python2/httplib.pyi +++ b/mypy/typeshed/stdlib/@python2/httplib.pyi @@ -1,9 +1,9 @@ import mimetools -from typing import Any, Dict, Protocol +from typing import Any, Protocol class HTTPMessage(mimetools.Message): def addcontinue(self, key: str, more: str) -> None: ... - dict: Dict[str, str] + dict: dict[str, str] def addheader(self, key: str, value: str) -> None: ... unixfrom: str headers: Any @@ -151,7 +151,7 @@ class LineAndFileWrapper: # Constants -responses: Dict[int, str] +responses: dict[int, str] HTTP_PORT: int HTTPS_PORT: int diff --git a/mypy/typeshed/stdlib/@python2/imaplib.pyi b/mypy/typeshed/stdlib/@python2/imaplib.pyi index c4346851bdac7..72003eb482339 100644 --- a/mypy/typeshed/stdlib/@python2/imaplib.pyi +++ b/mypy/typeshed/stdlib/@python2/imaplib.pyi @@ -1,33 +1,34 @@ import subprocess import time +from builtins import list as List # alias to avoid name clashes with `IMAP4.list` from socket import socket as _socket from ssl import SSLSocket -from typing import IO, Any, Callable, Dict, List, Pattern, Text, Tuple, Type, Union +from typing import IO, Any, Callable, Pattern, Text from typing_extensions import Literal # TODO: Commands should use their actual return types, not this type alias. -# E.g. Tuple[Literal["OK"], List[bytes]] -_CommandResults = Tuple[str, List[Any]] +# E.g. tuple[Literal["OK"], list[bytes]] +_CommandResults = tuple[str, list[Any]] -_AnyResponseData = Union[List[None], List[Union[bytes, Tuple[bytes, bytes]]]] +_AnyResponseData = list[None] | list[bytes | tuple[bytes, bytes]] class IMAP4: - error: Type[Exception] = ... - abort: Type[Exception] = ... - readonly: Type[Exception] = ... + error: type[Exception] = ... + abort: type[Exception] = ... + readonly: type[Exception] = ... mustquote: Pattern[Text] = ... debug: int = ... state: str = ... literal: Text | None = ... - tagged_commands: Dict[bytes, List[bytes] | None] - untagged_responses: Dict[str, List[bytes | Tuple[bytes, bytes]]] + tagged_commands: dict[bytes, List[bytes] | None] + untagged_responses: dict[str, List[bytes | tuple[bytes, bytes]]] continuation_response: str = ... is_readonly: bool = ... tagnum: int = ... tagpre: str = ... tagre: Pattern[Text] = ... welcome: bytes = ... - capabilities: Tuple[str] = ... + capabilities: tuple[str, ...] = ... PROTOCOL_VERSION: str = ... def __init__(self, host: str = ..., port: int = ...) -> None: ... def open(self, host: str = ..., port: int = ...) -> None: ... @@ -44,7 +45,7 @@ class IMAP4: def recent(self) -> _CommandResults: ... def response(self, code: str) -> _CommandResults: ... def append(self, mailbox: str, flags: str, date_time: str, message: str) -> str: ... - def authenticate(self, mechanism: str, authobject: Callable[[bytes], bytes | None]) -> Tuple[str, str]: ... + def authenticate(self, mechanism: str, authobject: Callable[[bytes], bytes | None]) -> tuple[str, str]: ... def capability(self) -> _CommandResults: ... def check(self) -> _CommandResults: ... def close(self) -> _CommandResults: ... @@ -53,24 +54,24 @@ class IMAP4: def delete(self, mailbox: str) -> _CommandResults: ... def deleteacl(self, mailbox: str, who: str) -> _CommandResults: ... def expunge(self) -> _CommandResults: ... - def fetch(self, message_set: str, message_parts: str) -> Tuple[str, _AnyResponseData]: ... + def fetch(self, message_set: str, message_parts: str) -> tuple[str, _AnyResponseData]: ... def getacl(self, mailbox: str) -> _CommandResults: ... def getannotation(self, mailbox: str, entry: str, attribute: str) -> _CommandResults: ... def getquota(self, root: str) -> _CommandResults: ... def getquotaroot(self, mailbox: str) -> _CommandResults: ... - def list(self, directory: str = ..., pattern: str = ...) -> Tuple[str, _AnyResponseData]: ... - def login(self, user: str, password: str) -> Tuple[Literal["OK"], List[bytes]]: ... + def list(self, directory: str = ..., pattern: str = ...) -> tuple[str, _AnyResponseData]: ... + def login(self, user: str, password: str) -> tuple[Literal["OK"], List[bytes]]: ... def login_cram_md5(self, user: str, password: str) -> _CommandResults: ... - def logout(self) -> Tuple[str, _AnyResponseData]: ... + def logout(self) -> tuple[str, _AnyResponseData]: ... def lsub(self, directory: str = ..., pattern: str = ...) -> _CommandResults: ... def myrights(self, mailbox: str) -> _CommandResults: ... def namespace(self) -> _CommandResults: ... - def noop(self) -> Tuple[str, List[bytes]]: ... + def noop(self) -> tuple[str, List[bytes]]: ... def partial(self, message_num: str, message_part: str, start: str, length: str) -> _CommandResults: ... def proxyauth(self, user: str) -> _CommandResults: ... def rename(self, oldmailbox: str, newmailbox: str) -> _CommandResults: ... def search(self, charset: str | None, *criteria: str) -> _CommandResults: ... - def select(self, mailbox: str = ..., readonly: bool = ...) -> Tuple[str, List[bytes | None]]: ... + def select(self, mailbox: str = ..., readonly: bool = ...) -> tuple[str, List[bytes | None]]: ... def setacl(self, mailbox: str, who: str, what: str) -> _CommandResults: ... def setannotation(self, *args: str) -> _CommandResults: ... def setquota(self, root: str, limits: str) -> _CommandResults: ... @@ -126,5 +127,5 @@ class _Authenticator: def Internaldate2tuple(resp: str) -> time.struct_time: ... def Int2AP(num: int) -> str: ... -def ParseFlags(resp: str) -> Tuple[str]: ... +def ParseFlags(resp: str) -> tuple[str, ...]: ... def Time2Internaldate(date_time: float | time.struct_time | str) -> str: ... diff --git a/mypy/typeshed/stdlib/@python2/imghdr.pyi b/mypy/typeshed/stdlib/@python2/imghdr.pyi index d60cafa4c78ff..36db49902983b 100644 --- a/mypy/typeshed/stdlib/@python2/imghdr.pyi +++ b/mypy/typeshed/stdlib/@python2/imghdr.pyi @@ -1,15 +1,15 @@ -from typing import Any, BinaryIO, Callable, List, Protocol, Text, Union, overload +from typing import Any, BinaryIO, Callable, Protocol, Text, overload class _ReadableBinary(Protocol): def tell(self) -> int: ... def read(self, size: int) -> bytes: ... def seek(self, offset: int) -> Any: ... -_File = Union[Text, _ReadableBinary] +_File = Text | _ReadableBinary @overload def what(file: _File, h: None = ...) -> str | None: ... @overload def what(file: Any, h: bytes) -> str | None: ... -tests: List[Callable[[bytes, BinaryIO | None], str | None]] +tests: list[Callable[[bytes, BinaryIO | None], str | None]] diff --git a/mypy/typeshed/stdlib/@python2/imp.pyi b/mypy/typeshed/stdlib/@python2/imp.pyi index 128bd900e996e..15d689249563a 100644 --- a/mypy/typeshed/stdlib/@python2/imp.pyi +++ b/mypy/typeshed/stdlib/@python2/imp.pyi @@ -1,5 +1,5 @@ import types -from typing import IO, Any, Iterable, List, Tuple +from typing import IO, Any, Iterable C_BUILTIN: int C_EXTENSION: int @@ -13,16 +13,16 @@ PY_SOURCE: int SEARCH_ERROR: int def acquire_lock() -> None: ... -def find_module(name: str, path: Iterable[str] = ...) -> Tuple[IO[Any], str, Tuple[str, str, int]] | None: ... +def find_module(name: str, path: Iterable[str] = ...) -> tuple[IO[Any], str, tuple[str, str, int]] | None: ... def get_magic() -> str: ... -def get_suffixes() -> List[Tuple[str, str, int]]: ... +def get_suffixes() -> list[tuple[str, str, int]]: ... def init_builtin(name: str) -> types.ModuleType: ... def init_frozen(name: str) -> types.ModuleType: ... def is_builtin(name: str) -> int: ... def is_frozen(name: str) -> bool: ... def load_compiled(name: str, pathname: str, file: IO[Any] = ...) -> types.ModuleType: ... def load_dynamic(name: str, pathname: str, file: IO[Any] = ...) -> types.ModuleType: ... -def load_module(name: str, file: str, pathname: str, description: Tuple[str, str, int]) -> types.ModuleType: ... +def load_module(name: str, file: str, pathname: str, description: tuple[str, str, int]) -> types.ModuleType: ... def load_source(name: str, pathname: str, file: IO[Any] = ...) -> types.ModuleType: ... def lock_held() -> bool: ... def new_module(name: str) -> types.ModuleType: ... diff --git a/mypy/typeshed/stdlib/@python2/inspect.pyi b/mypy/typeshed/stdlib/@python2/inspect.pyi index c6118ea8aebb6..8ffcc3edcb872 100644 --- a/mypy/typeshed/stdlib/@python2/inspect.pyi +++ b/mypy/typeshed/stdlib/@python2/inspect.pyi @@ -1,5 +1,5 @@ from types import CodeType, FrameType, FunctionType, MethodType, ModuleType, TracebackType -from typing import Any, AnyStr, Callable, Dict, List, NamedTuple, Optional, Sequence, Tuple, Type, Union +from typing import Any, AnyStr, Callable, NamedTuple, Sequence, Union # Types and members class EndOfBlock(Exception): ... @@ -11,7 +11,7 @@ class BlockFinder: passline: bool last: int def tokeneater( - self, type: int, token: AnyStr, srow_scol: Tuple[int, int], erow_ecol: Tuple[int, int], line: AnyStr + self, type: int, token: AnyStr, srow_scol: tuple[int, int], erow_ecol: tuple[int, int], line: AnyStr ) -> None: ... CO_GENERATOR: int @@ -29,7 +29,7 @@ class ModuleInfo(NamedTuple): mode: str module_type: int -def getmembers(object: object, predicate: Callable[[Any], bool] | None = ...) -> List[Tuple[str, Any]]: ... +def getmembers(object: object, predicate: Callable[[Any], bool] | None = ...) -> list[tuple[str, Any]]: ... def getmoduleinfo(path: str | unicode) -> ModuleInfo | None: ... def getmodulename(path: AnyStr) -> AnyStr | None: ... def ismodule(object: object) -> bool: ... @@ -50,9 +50,9 @@ def isgetsetdescriptor(object: object) -> bool: ... def ismemberdescriptor(object: object) -> bool: ... # Retrieving source code -_SourceObjectType = Union[ModuleType, Type[Any], MethodType, FunctionType, TracebackType, FrameType, CodeType, Callable[..., Any]] +_SourceObjectType = Union[ModuleType, type[Any], MethodType, FunctionType, TracebackType, FrameType, CodeType, Callable[..., Any]] -def findsource(object: _SourceObjectType) -> Tuple[List[str], int]: ... +def findsource(object: _SourceObjectType) -> tuple[list[str], int]: ... def getabsfile(object: _SourceObjectType) -> str: ... def getblock(lines: Sequence[AnyStr]) -> Sequence[AnyStr]: ... def getdoc(object: object) -> str | None: ... @@ -60,28 +60,28 @@ def getcomments(object: object) -> str | None: ... def getfile(object: _SourceObjectType) -> str: ... def getmodule(object: object) -> ModuleType | None: ... def getsourcefile(object: _SourceObjectType) -> str | None: ... -def getsourcelines(object: _SourceObjectType) -> Tuple[List[str], int]: ... +def getsourcelines(object: _SourceObjectType) -> tuple[list[str], int]: ... def getsource(object: _SourceObjectType) -> str: ... def cleandoc(doc: AnyStr) -> AnyStr: ... def indentsize(line: str | unicode) -> int: ... # Classes and functions -def getclasstree(classes: List[type], unique: bool = ...) -> List[Tuple[type, Tuple[type, ...]] | List[Any]]: ... +def getclasstree(classes: list[type], unique: bool = ...) -> list[tuple[type, tuple[type, ...]] | list[Any]]: ... class ArgSpec(NamedTuple): - args: List[str] + args: list[str] varargs: str | None keywords: str | None - defaults: Tuple[Any, ...] + defaults: tuple[Any, ...] class ArgInfo(NamedTuple): - args: List[str] + args: list[str] varargs: str | None keywords: str | None - locals: Dict[str, Any] + locals: dict[str, Any] class Arguments(NamedTuple): - args: List[str | List[Any]] + args: list[str | list[Any]] varargs: str | None keywords: str | None @@ -94,8 +94,8 @@ def formatargspec( def formatargvalues( args, varargs=..., varkw=..., defaults=..., formatarg=..., formatvarargs=..., formatvarkw=..., formatvalue=..., join=... ) -> str: ... -def getmro(cls: type) -> Tuple[type, ...]: ... -def getcallargs(func, *args, **kwds) -> Dict[str, Any]: ... +def getmro(cls: type) -> tuple[type, ...]: ... +def getcallargs(func, *args, **kwds) -> dict[str, Any]: ... # The interpreter stack @@ -103,18 +103,18 @@ class Traceback(NamedTuple): filename: str lineno: int function: str - code_context: List[str] | None - index: int | None # type: ignore + code_context: list[str] | None + index: int | None # type: ignore[assignment] -_FrameInfo = Tuple[FrameType, str, int, str, Optional[List[str]], Optional[int]] +_FrameInfo = tuple[FrameType, str, int, str, list[str] | None, int | None] -def getouterframes(frame: FrameType, context: int = ...) -> List[_FrameInfo]: ... +def getouterframes(frame: FrameType, context: int = ...) -> list[_FrameInfo]: ... def getframeinfo(frame: FrameType | TracebackType, context: int = ...) -> Traceback: ... -def getinnerframes(traceback: TracebackType, context: int = ...) -> List[_FrameInfo]: ... +def getinnerframes(traceback: TracebackType, context: int = ...) -> list[_FrameInfo]: ... def getlineno(frame: FrameType) -> int: ... def currentframe(depth: int = ...) -> FrameType: ... -def stack(context: int = ...) -> List[_FrameInfo]: ... -def trace(context: int = ...) -> List[_FrameInfo]: ... +def stack(context: int = ...) -> list[_FrameInfo]: ... +def trace(context: int = ...) -> list[_FrameInfo]: ... # Create private type alias to avoid conflict with symbol of same # name created in Attribute class. @@ -126,4 +126,4 @@ class Attribute(NamedTuple): defining_class: type object: _Object -def classify_class_attrs(cls: type) -> List[Attribute]: ... +def classify_class_attrs(cls: type) -> list[Attribute]: ... diff --git a/mypy/typeshed/stdlib/@python2/itertools.pyi b/mypy/typeshed/stdlib/@python2/itertools.pyi index 12996d44628b8..6509213e16255 100644 --- a/mypy/typeshed/stdlib/@python2/itertools.pyi +++ b/mypy/typeshed/stdlib/@python2/itertools.pyi @@ -1,4 +1,5 @@ -from typing import Any, Callable, Generic, Iterable, Iterator, Sequence, Tuple, TypeVar, overload +from _typeshed import Self +from typing import Any, Callable, Generic, Iterable, Iterator, Sequence, TypeVar, overload _T = TypeVar("_T") _S = TypeVar("_S") @@ -8,14 +9,14 @@ def count(start: int = ..., step: int = ...) -> Iterator[int]: ... # more gener class cycle(Iterator[_T], Generic[_T]): def __init__(self, iterable: Iterable[_T]) -> None: ... def next(self) -> _T: ... - def __iter__(self) -> Iterator[_T]: ... + def __iter__(self: Self) -> Self: ... def repeat(object: _T, times: int = ...) -> Iterator[_T]: ... class chain(Iterator[_T], Generic[_T]): def __init__(self, *iterables: Iterable[_T]) -> None: ... def next(self) -> _T: ... - def __iter__(self) -> Iterator[_T]: ... + def __iter__(self: Self) -> Self: ... @staticmethod def from_iterable(iterable: Iterable[Iterable[_S]]) -> Iterator[_S]: ... @@ -24,9 +25,9 @@ def dropwhile(predicate: Callable[[_T], Any], iterable: Iterable[_T]) -> Iterato def ifilter(predicate: Callable[[_T], Any] | None, iterable: Iterable[_T]) -> Iterator[_T]: ... def ifilterfalse(predicate: Callable[[_T], Any] | None, iterable: Iterable[_T]) -> Iterator[_T]: ... @overload -def groupby(iterable: Iterable[_T], key: None = ...) -> Iterator[Tuple[_T, Iterator[_T]]]: ... +def groupby(iterable: Iterable[_T], key: None = ...) -> Iterator[tuple[_T, Iterator[_T]]]: ... @overload -def groupby(iterable: Iterable[_T], key: Callable[[_T], _S]) -> Iterator[Tuple[_S, Iterator[_T]]]: ... +def groupby(iterable: Iterable[_T], key: Callable[[_T], _S]) -> Iterator[tuple[_S, Iterator[_T]]]: ... @overload def islice(iterable: Iterable[_T], stop: int | None) -> Iterator[_T]: ... @overload @@ -88,21 +89,21 @@ def imap( ) -> Iterator[_S]: ... def starmap(func: Any, iterable: Iterable[Any]) -> Iterator[Any]: ... def takewhile(predicate: Callable[[_T], Any], iterable: Iterable[_T]) -> Iterator[_T]: ... -def tee(iterable: Iterable[_T], n: int = ...) -> Tuple[Iterator[_T], ...]: ... +def tee(iterable: Iterable[_T], n: int = ...) -> tuple[Iterator[_T], ...]: ... @overload -def izip(iter1: Iterable[_T1]) -> Iterator[Tuple[_T1]]: ... +def izip(iter1: Iterable[_T1]) -> Iterator[tuple[_T1]]: ... @overload -def izip(iter1: Iterable[_T1], iter2: Iterable[_T2]) -> Iterator[Tuple[_T1, _T2]]: ... +def izip(iter1: Iterable[_T1], iter2: Iterable[_T2]) -> Iterator[tuple[_T1, _T2]]: ... @overload -def izip(iter1: Iterable[_T1], iter2: Iterable[_T2], iter3: Iterable[_T3]) -> Iterator[Tuple[_T1, _T2, _T3]]: ... +def izip(iter1: Iterable[_T1], iter2: Iterable[_T2], iter3: Iterable[_T3]) -> Iterator[tuple[_T1, _T2, _T3]]: ... @overload def izip( iter1: Iterable[_T1], iter2: Iterable[_T2], iter3: Iterable[_T3], iter4: Iterable[_T4] -) -> Iterator[Tuple[_T1, _T2, _T3, _T4]]: ... +) -> Iterator[tuple[_T1, _T2, _T3, _T4]]: ... @overload def izip( iter1: Iterable[_T1], iter2: Iterable[_T2], iter3: Iterable[_T3], iter4: Iterable[_T4], iter5: Iterable[_T5] -) -> Iterator[Tuple[_T1, _T2, _T3, _T4, _T5]]: ... +) -> Iterator[tuple[_T1, _T2, _T3, _T4, _T5]]: ... @overload def izip( iter1: Iterable[_T1], @@ -111,7 +112,7 @@ def izip( iter4: Iterable[_T4], iter5: Iterable[_T5], iter6: Iterable[_T6], -) -> Iterator[Tuple[_T1, _T2, _T3, _T4, _T5, _T6]]: ... +) -> Iterator[tuple[_T1, _T2, _T3, _T4, _T5, _T6]]: ... @overload def izip( iter1: Iterable[Any], @@ -122,22 +123,22 @@ def izip( iter6: Iterable[Any], iter7: Iterable[Any], *iterables: Iterable[Any], -) -> Iterator[Tuple[Any, ...]]: ... +) -> Iterator[tuple[Any, ...]]: ... def izip_longest(*p: Iterable[Any], fillvalue: Any = ...) -> Iterator[Any]: ... @overload -def product(iter1: Iterable[_T1]) -> Iterator[Tuple[_T1]]: ... +def product(iter1: Iterable[_T1]) -> Iterator[tuple[_T1]]: ... @overload -def product(iter1: Iterable[_T1], iter2: Iterable[_T2]) -> Iterator[Tuple[_T1, _T2]]: ... +def product(iter1: Iterable[_T1], iter2: Iterable[_T2]) -> Iterator[tuple[_T1, _T2]]: ... @overload -def product(iter1: Iterable[_T1], iter2: Iterable[_T2], iter3: Iterable[_T3]) -> Iterator[Tuple[_T1, _T2, _T3]]: ... +def product(iter1: Iterable[_T1], iter2: Iterable[_T2], iter3: Iterable[_T3]) -> Iterator[tuple[_T1, _T2, _T3]]: ... @overload def product( iter1: Iterable[_T1], iter2: Iterable[_T2], iter3: Iterable[_T3], iter4: Iterable[_T4] -) -> Iterator[Tuple[_T1, _T2, _T3, _T4]]: ... +) -> Iterator[tuple[_T1, _T2, _T3, _T4]]: ... @overload def product( iter1: Iterable[_T1], iter2: Iterable[_T2], iter3: Iterable[_T3], iter4: Iterable[_T4], iter5: Iterable[_T5] -) -> Iterator[Tuple[_T1, _T2, _T3, _T4, _T5]]: ... +) -> Iterator[tuple[_T1, _T2, _T3, _T4, _T5]]: ... @overload def product( iter1: Iterable[_T1], @@ -146,7 +147,7 @@ def product( iter4: Iterable[_T4], iter5: Iterable[_T5], iter6: Iterable[_T6], -) -> Iterator[Tuple[_T1, _T2, _T3, _T4, _T5, _T6]]: ... +) -> Iterator[tuple[_T1, _T2, _T3, _T4, _T5, _T6]]: ... @overload def product( iter1: Iterable[Any], @@ -157,9 +158,9 @@ def product( iter6: Iterable[Any], iter7: Iterable[Any], *iterables: Iterable[Any], -) -> Iterator[Tuple[Any, ...]]: ... +) -> Iterator[tuple[Any, ...]]: ... @overload -def product(*iterables: Iterable[Any], repeat: int) -> Iterator[Tuple[Any, ...]]: ... +def product(*iterables: Iterable[Any], repeat: int) -> Iterator[tuple[Any, ...]]: ... def permutations(iterable: Iterable[_T], r: int = ...) -> Iterator[Sequence[_T]]: ... def combinations(iterable: Iterable[_T], r: int) -> Iterator[Sequence[_T]]: ... def combinations_with_replacement(iterable: Iterable[_T], r: int) -> Iterator[Sequence[_T]]: ... diff --git a/mypy/typeshed/stdlib/@python2/json.pyi b/mypy/typeshed/stdlib/@python2/json.pyi index bfbddb2a68356..fa6fdc49b9a9e 100644 --- a/mypy/typeshed/stdlib/@python2/json.pyi +++ b/mypy/typeshed/stdlib/@python2/json.pyi @@ -1,5 +1,5 @@ from _typeshed import SupportsRead -from typing import IO, Any, Callable, Dict, List, Text, Tuple, Type +from typing import IO, Any, Callable, Text def dumps( obj: Any, @@ -7,9 +7,9 @@ def dumps( ensure_ascii: bool = ..., check_circular: bool = ..., allow_nan: bool = ..., - cls: Type[JSONEncoder] | None = ..., + cls: type[JSONEncoder] | None = ..., indent: int | None = ..., - separators: Tuple[str, str] | None = ..., + separators: tuple[str, str] | None = ..., encoding: str = ..., default: Callable[[Any], Any] | None = ..., sort_keys: bool = ..., @@ -22,9 +22,9 @@ def dump( ensure_ascii: bool = ..., check_circular: bool = ..., allow_nan: bool = ..., - cls: Type[JSONEncoder] | None = ..., + cls: type[JSONEncoder] | None = ..., indent: int | None = ..., - separators: Tuple[str, str] | None = ..., + separators: tuple[str, str] | None = ..., encoding: str = ..., default: Callable[[Any], Any] | None = ..., sort_keys: bool = ..., @@ -33,23 +33,23 @@ def dump( def loads( s: Text | bytes, encoding: Any = ..., - cls: Type[JSONDecoder] | None = ..., - object_hook: Callable[[Dict[Any, Any]], Any] | None = ..., + cls: type[JSONDecoder] | None = ..., + object_hook: Callable[[dict[Any, Any]], Any] | None = ..., parse_float: Callable[[str], Any] | None = ..., parse_int: Callable[[str], Any] | None = ..., parse_constant: Callable[[str], Any] | None = ..., - object_pairs_hook: Callable[[List[Tuple[Any, Any]]], Any] | None = ..., + object_pairs_hook: Callable[[list[tuple[Any, Any]]], Any] | None = ..., **kwds: Any, ) -> Any: ... def load( fp: SupportsRead[Text | bytes], encoding: str | None = ..., - cls: Type[JSONDecoder] | None = ..., - object_hook: Callable[[Dict[Any, Any]], Any] | None = ..., + cls: type[JSONDecoder] | None = ..., + object_hook: Callable[[dict[Any, Any]], Any] | None = ..., parse_float: Callable[[str], Any] | None = ..., parse_int: Callable[[str], Any] | None = ..., parse_constant: Callable[[str], Any] | None = ..., - object_pairs_hook: Callable[[List[Tuple[Any, Any]]], Any] | None = ..., + object_pairs_hook: Callable[[list[tuple[Any, Any]]], Any] | None = ..., **kwds: Any, ) -> Any: ... @@ -65,7 +65,7 @@ class JSONDecoder(object): object_pairs_hook: Callable[..., Any] = ..., ) -> None: ... def decode(self, s: Text | bytes, _w: Any = ...) -> Any: ... - def raw_decode(self, s: Text | bytes, idx: int = ...) -> Tuple[Any, Any]: ... + def raw_decode(self, s: Text | bytes, idx: int = ...) -> tuple[Any, Any]: ... class JSONEncoder(object): item_separator: str @@ -84,7 +84,7 @@ class JSONEncoder(object): allow_nan: bool = ..., sort_keys: bool = ..., indent: int | None = ..., - separators: Tuple[Text | bytes, Text | bytes] = ..., + separators: tuple[Text | bytes, Text | bytes] = ..., encoding: Text | bytes = ..., default: Callable[..., Any] = ..., ) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/grammar.pyi b/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/grammar.pyi index 6ec97ce849d2d..9d05082fc30c0 100644 --- a/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/grammar.pyi +++ b/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/grammar.pyi @@ -1,26 +1,25 @@ -from _typeshed import StrPath -from typing import Dict, List, Optional, Text, Tuple, TypeVar +from _typeshed import Self, StrPath +from typing import Text -_P = TypeVar("_P") -_Label = Tuple[int, Optional[Text]] -_DFA = List[List[Tuple[int, int]]] -_DFAS = Tuple[_DFA, Dict[int, int]] +_Label = tuple[int, Text | None] +_DFA = list[list[tuple[int, int]]] +_DFAS = tuple[_DFA, dict[int, int]] class Grammar: - symbol2number: Dict[Text, int] - number2symbol: Dict[int, Text] - states: List[_DFA] - dfas: Dict[int, _DFAS] - labels: List[_Label] - keywords: Dict[Text, int] - tokens: Dict[int, int] - symbol2label: Dict[Text, int] + symbol2number: dict[Text, int] + number2symbol: dict[int, Text] + states: list[_DFA] + dfas: dict[int, _DFAS] + labels: list[_Label] + keywords: dict[Text, int] + tokens: dict[int, int] + symbol2label: dict[Text, int] start: int def __init__(self) -> None: ... def dump(self, filename: StrPath) -> None: ... def load(self, filename: StrPath) -> None: ... - def copy(self: _P) -> _P: ... + def copy(self: Self) -> Self: ... def report(self) -> None: ... opmap_raw: Text -opmap: Dict[Text, Text] +opmap: dict[Text, Text] diff --git a/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/literals.pyi b/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/literals.pyi index 160d6fd76f76d..c7a219b5f9af7 100644 --- a/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/literals.pyi +++ b/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/literals.pyi @@ -1,6 +1,6 @@ -from typing import Dict, Match, Text +from typing import Match, Text -simple_escapes: Dict[Text, Text] +simple_escapes: dict[Text, Text] def escape(m: Match[str]) -> Text: ... def evalString(s: Text) -> Text: ... diff --git a/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/parse.pyi b/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/parse.pyi index eed165db551c4..be66a8e21e7ea 100644 --- a/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/parse.pyi +++ b/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/parse.pyi @@ -1,6 +1,6 @@ from lib2to3.pgen2.grammar import _DFAS, Grammar from lib2to3.pytree import _NL, _Convert, _RawNode -from typing import Any, List, Sequence, Set, Text, Tuple +from typing import Any, Sequence, Text _Context = Sequence[Any] @@ -14,9 +14,9 @@ class ParseError(Exception): class Parser: grammar: Grammar convert: _Convert - stack: List[Tuple[_DFAS, int, _RawNode]] + stack: list[tuple[_DFAS, int, _RawNode]] rootnode: _NL | None - used_names: Set[Text] + used_names: set[Text] def __init__(self, grammar: Grammar, convert: _Convert | None = ...) -> None: ... def setup(self, start: int | None = ...) -> None: ... def addtoken(self, type: int, value: Text | None, context: _Context) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/pgen.pyi b/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/pgen.pyi index 67dbbccdd4a6a..daddcf0cf113e 100644 --- a/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/pgen.pyi +++ b/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/pgen.pyi @@ -1,7 +1,7 @@ from _typeshed import StrPath from lib2to3.pgen2 import grammar from lib2to3.pgen2.tokenize import _TokenInfo -from typing import IO, Any, Dict, Iterable, Iterator, List, NoReturn, Text, Tuple +from typing import IO, Any, Iterable, Iterator, NoReturn, Text class PgenGrammar(grammar.Grammar): ... @@ -9,38 +9,38 @@ class ParserGenerator: filename: StrPath stream: IO[Text] generator: Iterator[_TokenInfo] - first: Dict[Text, Dict[Text, int]] + first: dict[Text, dict[Text, int]] def __init__(self, filename: StrPath, stream: IO[Text] | None = ...) -> None: ... def make_grammar(self) -> PgenGrammar: ... - def make_first(self, c: PgenGrammar, name: Text) -> Dict[int, int]: ... + def make_first(self, c: PgenGrammar, name: Text) -> dict[int, int]: ... def make_label(self, c: PgenGrammar, label: Text) -> int: ... def addfirstsets(self) -> None: ... def calcfirst(self, name: Text) -> None: ... - def parse(self) -> Tuple[Dict[Text, List[DFAState]], Text]: ... - def make_dfa(self, start: NFAState, finish: NFAState) -> List[DFAState]: ... - def dump_nfa(self, name: Text, start: NFAState, finish: NFAState) -> List[DFAState]: ... + def parse(self) -> tuple[dict[Text, list[DFAState]], Text]: ... + def make_dfa(self, start: NFAState, finish: NFAState) -> list[DFAState]: ... + def dump_nfa(self, name: Text, start: NFAState, finish: NFAState) -> list[DFAState]: ... def dump_dfa(self, name: Text, dfa: Iterable[DFAState]) -> None: ... - def simplify_dfa(self, dfa: List[DFAState]) -> None: ... - def parse_rhs(self) -> Tuple[NFAState, NFAState]: ... - def parse_alt(self) -> Tuple[NFAState, NFAState]: ... - def parse_item(self) -> Tuple[NFAState, NFAState]: ... - def parse_atom(self) -> Tuple[NFAState, NFAState]: ... + def simplify_dfa(self, dfa: list[DFAState]) -> None: ... + def parse_rhs(self) -> tuple[NFAState, NFAState]: ... + def parse_alt(self) -> tuple[NFAState, NFAState]: ... + def parse_item(self) -> tuple[NFAState, NFAState]: ... + def parse_atom(self) -> tuple[NFAState, NFAState]: ... def expect(self, type: int, value: Any | None = ...) -> Text: ... def gettoken(self) -> None: ... def raise_error(self, msg: str, *args: Any) -> NoReturn: ... class NFAState: - arcs: List[Tuple[Text | None, NFAState]] + arcs: list[tuple[Text | None, NFAState]] def __init__(self) -> None: ... def addarc(self, next: NFAState, label: Text | None = ...) -> None: ... class DFAState: - nfaset: Dict[NFAState, Any] + nfaset: dict[NFAState, Any] isfinal: bool - arcs: Dict[Text, DFAState] - def __init__(self, nfaset: Dict[NFAState, Any], final: NFAState) -> None: ... + arcs: dict[Text, DFAState] + def __init__(self, nfaset: dict[NFAState, Any], final: NFAState) -> None: ... def addarc(self, next: DFAState, label: Text) -> None: ... def unifystate(self, old: DFAState, new: DFAState) -> None: ... - def __eq__(self, other: Any) -> bool: ... + def __eq__(self, other: DFAState) -> bool: ... # type: ignore[override] def generate_grammar(filename: StrPath = ...) -> PgenGrammar: ... diff --git a/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/token.pyi b/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/token.pyi index 3f4e41d49bd5d..967c4df5d7210 100644 --- a/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/token.pyi +++ b/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/token.pyi @@ -1,4 +1,4 @@ -from typing import Dict, Text +from typing import Text ENDMARKER: int NAME: int @@ -56,7 +56,7 @@ NL: int ERRORTOKEN: int N_TOKENS: int NT_OFFSET: int -tok_name: Dict[int, Text] +tok_name: dict[int, Text] def ISTERMINAL(x: int) -> bool: ... def ISNONTERMINAL(x: int) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/tokenize.pyi b/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/tokenize.pyi index 477341c1a54e0..d93d3f4827667 100644 --- a/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/tokenize.pyi +++ b/mypy/typeshed/stdlib/@python2/lib2to3/pgen2/tokenize.pyi @@ -1,9 +1,9 @@ from lib2to3.pgen2.token import * # noqa -from typing import Callable, Iterable, Iterator, List, Text, Tuple +from typing import Callable, Iterable, Iterator, Text -_Coord = Tuple[int, int] +_Coord = tuple[int, int] _TokenEater = Callable[[int, Text, _Coord, _Coord, Text], None] -_TokenInfo = Tuple[int, Text, _Coord, _Coord, Text] +_TokenInfo = tuple[int, Text, _Coord, _Coord, Text] class TokenError(Exception): ... class StopTokenizing(Exception): ... @@ -11,13 +11,13 @@ class StopTokenizing(Exception): ... def tokenize(readline: Callable[[], Text], tokeneater: _TokenEater = ...) -> None: ... class Untokenizer: - tokens: List[Text] + tokens: list[Text] prev_row: int prev_col: int def __init__(self) -> None: ... def add_whitespace(self, start: _Coord) -> None: ... def untokenize(self, iterable: Iterable[_TokenInfo]) -> Text: ... - def compat(self, token: Tuple[int, Text], iterable: Iterable[_TokenInfo]) -> None: ... + def compat(self, token: tuple[int, Text], iterable: Iterable[_TokenInfo]) -> None: ... def untokenize(iterable: Iterable[_TokenInfo]) -> Text: ... def generate_tokens(readline: Callable[[], Text]) -> Iterator[_TokenInfo]: ... diff --git a/mypy/typeshed/stdlib/@python2/lib2to3/pytree.pyi b/mypy/typeshed/stdlib/@python2/lib2to3/pytree.pyi index 27c64853329e7..a3969e60d95eb 100644 --- a/mypy/typeshed/stdlib/@python2/lib2to3/pytree.pyi +++ b/mypy/typeshed/stdlib/@python2/lib2to3/pytree.pyi @@ -1,11 +1,12 @@ +from _typeshed import Self from lib2to3.pgen2.grammar import Grammar -from typing import Any, Callable, Dict, Iterator, List, Optional, Text, Tuple, TypeVar, Union +from typing import Any, Callable, Iterator, Text, TypeVar _P = TypeVar("_P") -_NL = Union[Node, Leaf] -_Context = Tuple[Text, int, int] -_Results = Dict[Text, _NL] -_RawNode = Tuple[int, Text, _Context, Optional[List[_NL]]] +_NL = Node | Leaf +_Context = tuple[Text, int, int] +_Results = dict[Text, _NL] +_RawNode = tuple[int, Text, _Context, list[_NL] | None] _Convert = Callable[[Grammar, _RawNode], Any] HUGE: int @@ -16,15 +17,15 @@ class Base: type: int parent: Node | None prefix: Text - children: List[_NL] + children: list[_NL] was_changed: bool was_checked: bool - def __eq__(self, other: Any) -> bool: ... + def __eq__(self, other: object) -> bool: ... def _eq(self: _P, other: _P) -> bool: ... - def clone(self: _P) -> _P: ... + def clone(self: Self) -> Self: ... def post_order(self) -> Iterator[_NL]: ... def pre_order(self) -> Iterator[_NL]: ... - def replace(self, new: _NL | List[_NL]) -> None: ... + def replace(self, new: _NL | list[_NL]) -> None: ... def get_lineno(self) -> int: ... def changed(self) -> None: ... def remove(self) -> int | None: ... @@ -39,14 +40,14 @@ class Base: def set_prefix(self, prefix: Text) -> None: ... class Node(Base): - fixers_applied: List[Any] + fixers_applied: list[Any] def __init__( self, type: int, - children: List[_NL], + children: list[_NL], context: Any | None = ..., prefix: Text | None = ..., - fixers_applied: List[Any] | None = ..., + fixers_applied: list[Any] | None = ..., ) -> None: ... def set_child(self, i: int, child: _NL) -> None: ... def insert_child(self, i: int, child: _NL) -> None: ... @@ -56,9 +57,9 @@ class Leaf(Base): lineno: int column: int value: Text - fixers_applied: List[Any] + fixers_applied: list[Any] def __init__( - self, type: int, value: Text, context: _Context | None = ..., prefix: Text | None = ..., fixers_applied: List[Any] = ... + self, type: int, value: Text, context: _Context | None = ..., prefix: Text | None = ..., fixers_applied: list[Any] = ... ) -> None: ... def convert(gr: Grammar, raw_node: _RawNode) -> _NL: ... @@ -69,8 +70,8 @@ class BasePattern: name: Text | None def optimize(self) -> BasePattern: ... # sic, subclasses are free to optimize themselves into different patterns def match(self, node: _NL, results: _Results | None = ...) -> bool: ... - def match_seq(self, nodes: List[_NL], results: _Results | None = ...) -> bool: ... - def generate_matches(self, nodes: List[_NL]) -> Iterator[Tuple[int, _Results]]: ... + def match_seq(self, nodes: list[_NL], results: _Results | None = ...) -> bool: ... + def generate_matches(self, nodes: list[_NL]) -> Iterator[tuple[int, _Results]]: ... class LeafPattern(BasePattern): def __init__(self, type: int | None = ..., content: Text | None = ..., name: Text | None = ...) -> None: ... @@ -87,4 +88,4 @@ class WildcardPattern(BasePattern): class NegatedPattern(BasePattern): def __init__(self, content: Text | None = ...) -> None: ... -def generate_matches(patterns: List[BasePattern], nodes: List[_NL]) -> Iterator[Tuple[int, _Results]]: ... +def generate_matches(patterns: list[BasePattern], nodes: list[_NL]) -> Iterator[tuple[int, _Results]]: ... diff --git a/mypy/typeshed/stdlib/@python2/linecache.pyi b/mypy/typeshed/stdlib/@python2/linecache.pyi index 8628a0c58adc3..68c9074998670 100644 --- a/mypy/typeshed/stdlib/@python2/linecache.pyi +++ b/mypy/typeshed/stdlib/@python2/linecache.pyi @@ -1,9 +1,9 @@ -from typing import Any, Dict, List, Text +from typing import Any, Text -_ModuleGlobals = Dict[str, Any] +_ModuleGlobals = dict[str, Any] def getline(filename: Text, lineno: int, module_globals: _ModuleGlobals | None = ...) -> str: ... def clearcache() -> None: ... -def getlines(filename: Text, module_globals: _ModuleGlobals | None = ...) -> List[str]: ... +def getlines(filename: Text, module_globals: _ModuleGlobals | None = ...) -> list[str]: ... def checkcache(filename: Text | None = ...) -> None: ... -def updatecache(filename: Text, module_globals: _ModuleGlobals | None = ...) -> List[str]: ... +def updatecache(filename: Text, module_globals: _ModuleGlobals | None = ...) -> list[str]: ... diff --git a/mypy/typeshed/stdlib/@python2/locale.pyi b/mypy/typeshed/stdlib/@python2/locale.pyi index 21a7da166e29d..c75d865b87463 100644 --- a/mypy/typeshed/stdlib/@python2/locale.pyi +++ b/mypy/typeshed/stdlib/@python2/locale.pyi @@ -1,7 +1,7 @@ # workaround for mypy#2010 from __builtin__ import str as _str from decimal import Decimal -from typing import Any, Callable, Dict, Iterable, List, Mapping, Sequence, Tuple +from typing import Any, Callable, Iterable, Mapping, Sequence CODESET: int D_T_FMT: int @@ -75,9 +75,9 @@ CHAR_MAX: int class Error(Exception): ... def setlocale(category: int, locale: _str | Iterable[_str] | None = ...) -> _str: ... -def localeconv() -> Mapping[_str, int | _str | List[int]]: ... +def localeconv() -> Mapping[_str, int | _str | list[int]]: ... def nl_langinfo(__key: int) -> _str: ... -def getdefaultlocale(envvars: Tuple[_str, ...] = ...) -> Tuple[_str | None, _str | None]: ... +def getdefaultlocale(envvars: tuple[_str, ...] = ...) -> tuple[_str | None, _str | None]: ... def getlocale(category: int = ...) -> Sequence[_str]: ... def getpreferredencoding(do_setlocale: bool = ...) -> _str: ... def normalize(localename: _str) -> _str: ... @@ -91,6 +91,6 @@ def atof(string: _str, func: Callable[[_str], float] = ...) -> float: ... def atoi(string: _str) -> int: ... def str(val: float) -> _str: ... -locale_alias: Dict[_str, _str] # undocumented -locale_encoding_alias: Dict[_str, _str] # undocumented -windows_locale: Dict[int, _str] # undocumented +locale_alias: dict[_str, _str] # undocumented +locale_encoding_alias: dict[_str, _str] # undocumented +windows_locale: dict[int, _str] # undocumented diff --git a/mypy/typeshed/stdlib/@python2/logging/__init__.pyi b/mypy/typeshed/stdlib/@python2/logging/__init__.pyi index f981e24006240..059906d139eea 100644 --- a/mypy/typeshed/stdlib/@python2/logging/__init__.pyi +++ b/mypy/typeshed/stdlib/@python2/logging/__init__.pyi @@ -2,29 +2,13 @@ import threading from _typeshed import StrPath, SupportsWrite from time import struct_time from types import FrameType, TracebackType -from typing import ( - IO, - Any, - Callable, - Dict, - Generic, - List, - Mapping, - MutableMapping, - Optional, - Sequence, - Text, - Tuple, - TypeVar, - Union, - overload, -) +from typing import IO, Any, Callable, Generic, Mapping, MutableMapping, Sequence, Text, TypeVar, Union, overload -_SysExcInfoType = Union[Tuple[type, BaseException, Optional[TracebackType]], Tuple[None, None, None]] -_ExcInfoType = Union[None, bool, _SysExcInfoType] -_ArgsType = Union[Tuple[Any, ...], Mapping[str, Any]] -_FilterType = Union[Filter, Callable[[LogRecord], int]] -_Level = Union[int, Text] +_SysExcInfoType = Union[tuple[type, BaseException, TracebackType | None], tuple[None, None, None]] +_ExcInfoType = None | bool | _SysExcInfoType +_ArgsType = Union[tuple[Any, ...], Mapping[str, Any]] +_FilterType = Filter | Callable[[LogRecord], int] +_Level = int | Text raiseExceptions: bool logThreads: bool @@ -34,10 +18,10 @@ _srcfile: str | None def currentframe() -> FrameType: ... -_levelNames: Dict[int | str, str | int] # Union[int:str, str:int] +_levelNames: dict[int | str, str | int] # Union[int:str, str:int] class Filterer(object): - filters: List[Filter] + filters: list[Filter] def __init__(self) -> None: ... def addFilter(self, filter: _FilterType) -> None: ... def removeFilter(self, filter: _FilterType) -> None: ... @@ -48,7 +32,7 @@ class Logger(Filterer): level: int parent: Logger | PlaceHolder propagate: bool - handlers: List[Handler] + handlers: list[Handler] disabled: int def __init__(self, name: str, level: _Level = ...) -> None: ... def setLevel(self, level: _Level) -> None: ... @@ -56,35 +40,35 @@ class Logger(Filterer): def getEffectiveLevel(self) -> int: ... def getChild(self, suffix: str) -> Logger: ... def debug( - self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any + self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: dict[str, Any] | None = ..., **kwargs: Any ) -> None: ... def info( - self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any + self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: dict[str, Any] | None = ..., **kwargs: Any ) -> None: ... def warning( - self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any + self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: dict[str, Any] | None = ..., **kwargs: Any ) -> None: ... warn = warning def error( - self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any + self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: dict[str, Any] | None = ..., **kwargs: Any ) -> None: ... def critical( - self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any + self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: dict[str, Any] | None = ..., **kwargs: Any ) -> None: ... fatal = critical def log( - self, level: int, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any + self, level: int, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: dict[str, Any] | None = ..., **kwargs: Any ) -> None: ... def exception( - self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any + self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: dict[str, Any] | None = ..., **kwargs: Any ) -> None: ... def _log( - self, level: int, msg: Any, args: _ArgsType, exc_info: _ExcInfoType | None = ..., extra: Dict[str, Any] | None = ... + self, level: int, msg: Any, args: _ArgsType, exc_info: _ExcInfoType | None = ..., extra: dict[str, Any] | None = ... ) -> None: ... # undocumented def filter(self, record: LogRecord) -> bool: ... def addHandler(self, hdlr: Handler) -> None: ... def removeHandler(self, hdlr: Handler) -> None: ... - def findCaller(self) -> Tuple[str, int, str]: ... + def findCaller(self) -> tuple[str, int, str]: ... def handle(self, record: LogRecord) -> None: ... def makeRecord( self, @@ -181,27 +165,27 @@ class LoggerAdapter(Generic[_L]): logger: _L extra: Mapping[str, Any] def __init__(self, logger: _L, extra: Mapping[str, Any]) -> None: ... - def process(self, msg: Any, kwargs: MutableMapping[str, Any]) -> Tuple[Any, MutableMapping[str, Any]]: ... + def process(self, msg: Any, kwargs: MutableMapping[str, Any]) -> tuple[Any, MutableMapping[str, Any]]: ... def debug( - self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any + self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: dict[str, Any] | None = ..., **kwargs: Any ) -> None: ... def info( - self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any + self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: dict[str, Any] | None = ..., **kwargs: Any ) -> None: ... def warning( - self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any + self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: dict[str, Any] | None = ..., **kwargs: Any ) -> None: ... def error( - self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any + self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: dict[str, Any] | None = ..., **kwargs: Any ) -> None: ... def exception( - self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any + self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: dict[str, Any] | None = ..., **kwargs: Any ) -> None: ... def critical( - self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any + self, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: dict[str, Any] | None = ..., **kwargs: Any ) -> None: ... def log( - self, level: int, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any + self, level: int, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: dict[str, Any] | None = ..., **kwargs: Any ) -> None: ... def isEnabledFor(self, level: int) -> bool: ... @@ -210,17 +194,17 @@ def getLogger() -> Logger: ... @overload def getLogger(name: Text | str) -> Logger: ... def getLoggerClass() -> type: ... -def debug(msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any) -> None: ... -def info(msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any) -> None: ... -def warning(msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any) -> None: ... +def debug(msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: dict[str, Any] | None = ..., **kwargs: Any) -> None: ... +def info(msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: dict[str, Any] | None = ..., **kwargs: Any) -> None: ... +def warning(msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: dict[str, Any] | None = ..., **kwargs: Any) -> None: ... warn = warning -def error(msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any) -> None: ... -def critical(msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any) -> None: ... -def exception(msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any) -> None: ... +def error(msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: dict[str, Any] | None = ..., **kwargs: Any) -> None: ... +def critical(msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: dict[str, Any] | None = ..., **kwargs: Any) -> None: ... +def exception(msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: dict[str, Any] | None = ..., **kwargs: Any) -> None: ... def log( - level: int, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: Dict[str, Any] | None = ..., **kwargs: Any + level: int, msg: Any, *args: Any, exc_info: _ExcInfoType = ..., extra: dict[str, Any] | None = ..., **kwargs: Any ) -> None: ... fatal = critical diff --git a/mypy/typeshed/stdlib/@python2/logging/config.pyi b/mypy/typeshed/stdlib/@python2/logging/config.pyi index 03707bb98f55e..5597347d09616 100644 --- a/mypy/typeshed/stdlib/@python2/logging/config.pyi +++ b/mypy/typeshed/stdlib/@python2/logging/config.pyi @@ -1,10 +1,10 @@ from _typeshed import StrPath from threading import Thread -from typing import IO, Any, Dict +from typing import IO, Any _Path = StrPath -def dictConfig(config: Dict[str, Any]) -> None: ... -def fileConfig(fname: str | IO[str], defaults: Dict[str, str] | None = ..., disable_existing_loggers: bool = ...) -> None: ... +def dictConfig(config: dict[str, Any]) -> None: ... +def fileConfig(fname: str | IO[str], defaults: dict[str, str] | None = ..., disable_existing_loggers: bool = ...) -> None: ... def listen(port: int = ...) -> Thread: ... def stopListening() -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/logging/handlers.pyi b/mypy/typeshed/stdlib/@python2/logging/handlers.pyi index d18d57e77af46..212980e32ac63 100644 --- a/mypy/typeshed/stdlib/@python2/logging/handlers.pyi +++ b/mypy/typeshed/stdlib/@python2/logging/handlers.pyi @@ -1,7 +1,7 @@ from _typeshed import StrPath from logging import FileHandler, Handler, LogRecord from socket import SocketKind, SocketType -from typing import Any, ClassVar, Dict, List, Tuple +from typing import Any, ClassVar DEFAULT_TCP_LOGGING_PORT: int DEFAULT_UDP_LOGGING_PORT: int @@ -52,7 +52,7 @@ class SocketHandler(Handler): def createSocket(self) -> None: ... class DatagramHandler(SocketHandler): - def makeSocket(self) -> SocketType: ... # type: ignore + def makeSocket(self) -> SocketType: ... # type: ignore[override] class SysLogHandler(Handler): LOG_EMERG: int @@ -84,14 +84,14 @@ class SysLogHandler(Handler): LOG_LOCAL5: int LOG_LOCAL6: int LOG_LOCAL7: int - address: Tuple[str, int] | str # undocumented + address: tuple[str, int] | str # undocumented unixsocket: bool # undocumented socktype: SocketKind # undocumented facility: int # undocumented - priority_names: ClassVar[Dict[str, int]] # undocumented - facility_names: ClassVar[Dict[str, int]] # undocumented - priority_map: ClassVar[Dict[str, str]] # undocumented - def __init__(self, address: Tuple[str, int] | str = ..., facility: int = ..., socktype: SocketKind | None = ...) -> None: ... + priority_names: ClassVar[dict[str, int]] # undocumented + facility_names: ClassVar[dict[str, int]] # undocumented + priority_map: ClassVar[dict[str, str]] # undocumented + def __init__(self, address: tuple[str, int] | str = ..., facility: int = ..., socktype: SocketKind | None = ...) -> None: ... def encodePriority(self, facility: int | str, priority: int | str) -> int: ... def mapPriority(self, levelName: str) -> str: ... @@ -106,17 +106,17 @@ class SMTPHandler(Handler): # TODO `secure` can also be an empty tuple def __init__( self, - mailhost: str | Tuple[str, int], + mailhost: str | tuple[str, int], fromaddr: str, - toaddrs: List[str], + toaddrs: list[str], subject: str, - credentials: Tuple[str, str] | None = ..., - secure: Tuple[str] | Tuple[str, str] | None = ..., + credentials: tuple[str, str] | None = ..., + secure: tuple[str] | tuple[str, str] | None = ..., ) -> None: ... def getSubject(self, record: LogRecord) -> str: ... class BufferingHandler(Handler): - buffer: List[LogRecord] + buffer: list[LogRecord] def __init__(self, capacity: int) -> None: ... def shouldFlush(self, record: LogRecord) -> bool: ... @@ -126,4 +126,4 @@ class MemoryHandler(BufferingHandler): class HTTPHandler(Handler): def __init__(self, host: str, url: str, method: str = ...) -> None: ... - def mapLogRecord(self, record: LogRecord) -> Dict[str, Any]: ... + def mapLogRecord(self, record: LogRecord) -> dict[str, Any]: ... diff --git a/mypy/typeshed/stdlib/@python2/macpath.pyi b/mypy/typeshed/stdlib/@python2/macpath.pyi index bcb882e23eefb..73d55b15328f5 100644 --- a/mypy/typeshed/stdlib/@python2/macpath.pyi +++ b/mypy/typeshed/stdlib/@python2/macpath.pyi @@ -27,7 +27,7 @@ from posixpath import ( splitext as splitext, supports_unicode_filenames as supports_unicode_filenames, ) -from typing import AnyStr, Text, Tuple, overload +from typing import AnyStr, Text, overload altsep: str | None @@ -52,4 +52,4 @@ def join(__p1: bytes, __p2: bytes, __p3: Text, *p: Text) -> Text: ... def join(__p1: bytes, __p2: Text, *p: Text) -> Text: ... @overload def join(__p1: Text, *p: Text) -> Text: ... -def split(s: AnyStr) -> Tuple[AnyStr, AnyStr]: ... +def split(s: AnyStr) -> tuple[AnyStr, AnyStr]: ... diff --git a/mypy/typeshed/stdlib/@python2/mailbox.pyi b/mypy/typeshed/stdlib/@python2/mailbox.pyi index 18a66fa964c47..9d3f4d866aba3 100644 --- a/mypy/typeshed/stdlib/@python2/mailbox.pyi +++ b/mypy/typeshed/stdlib/@python2/mailbox.pyi @@ -1,36 +1,17 @@ import email.message from types import TracebackType -from typing import ( - IO, - Any, - AnyStr, - Callable, - Dict, - Generic, - Iterable, - Iterator, - List, - Mapping, - Protocol, - Sequence, - Text, - Tuple, - Type, - TypeVar, - Union, - overload, -) +from typing import IO, Any, AnyStr, Callable, Generic, Iterable, Iterator, Mapping, Protocol, Sequence, Text, TypeVar, overload from typing_extensions import Literal _T = TypeVar("_T") _MessageT = TypeVar("_MessageT", bound=Message) -_MessageData = Union[email.message.Message, bytes, str, IO[str], IO[bytes]] +_MessageData = email.message.Message | bytes | str | IO[str] | IO[bytes] class _HasIteritems(Protocol): - def iteritems(self) -> Iterator[Tuple[str, _MessageData]]: ... + def iteritems(self) -> Iterator[tuple[str, _MessageData]]: ... class _HasItems(Protocol): - def items(self) -> Iterator[Tuple[str, _MessageData]]: ... + def items(self) -> Iterator[tuple[str, _MessageData]]: ... linesep: bytes @@ -55,12 +36,12 @@ class Mailbox(Generic[_MessageT]): # As '_ProxyFile' doesn't implement the full IO spec, and BytesIO is incompatible with it, get_file return is Any here def get_file(self, key: str) -> Any: ... def iterkeys(self) -> Iterator[str]: ... - def keys(self) -> List[str]: ... + def keys(self) -> list[str]: ... def itervalues(self) -> Iterator[_MessageT]: ... def __iter__(self) -> Iterator[_MessageT]: ... - def values(self) -> List[_MessageT]: ... - def iteritems(self) -> Iterator[Tuple[str, _MessageT]]: ... - def items(self) -> List[Tuple[str, _MessageT]]: ... + def values(self) -> list[_MessageT]: ... + def iteritems(self) -> Iterator[tuple[str, _MessageT]]: ... + def items(self) -> list[tuple[str, _MessageT]]: ... def __contains__(self, key: str) -> bool: ... def __len__(self) -> int: ... def clear(self) -> None: ... @@ -68,8 +49,8 @@ class Mailbox(Generic[_MessageT]): def pop(self, key: str, default: None = ...) -> _MessageT | None: ... @overload def pop(self, key: str, default: _T = ...) -> _MessageT | _T: ... - def popitem(self) -> Tuple[str, _MessageT]: ... - def update(self, arg: _HasIteritems | _HasItems | Iterable[Tuple[str, _MessageData]] | None = ...) -> None: ... + def popitem(self) -> tuple[str, _MessageT]: ... + def update(self, arg: _HasIteritems | _HasItems | Iterable[tuple[str, _MessageData]] | None = ...) -> None: ... def flush(self) -> None: ... def lock(self) -> None: ... def unlock(self) -> None: ... @@ -80,7 +61,7 @@ class Maildir(Mailbox[MaildirMessage]): colon: str def __init__(self, dirname: Text, factory: Callable[[IO[Any]], MaildirMessage] | None = ..., create: bool = ...) -> None: ... def get_file(self, key: str) -> _ProxyFile[bytes]: ... - def list_folders(self) -> List[str]: ... + def list_folders(self) -> list[str]: ... def get_folder(self, folder: Text) -> Maildir: ... def add_folder(self, folder: Text) -> Maildir: ... def remove_folder(self, folder: Text) -> None: ... @@ -103,18 +84,18 @@ class MMDF(_mboxMMDF[MMDFMessage]): class MH(Mailbox[MHMessage]): def __init__(self, path: Text, factory: Callable[[IO[Any]], MHMessage] | None = ..., create: bool = ...) -> None: ... def get_file(self, key: str) -> _ProxyFile[bytes]: ... - def list_folders(self) -> List[str]: ... + def list_folders(self) -> list[str]: ... def get_folder(self, folder: Text) -> MH: ... def add_folder(self, folder: Text) -> MH: ... def remove_folder(self, folder: Text) -> None: ... - def get_sequences(self) -> Dict[str, List[int]]: ... + def get_sequences(self) -> dict[str, list[int]]: ... def set_sequences(self, sequences: Mapping[str, Sequence[int]]) -> None: ... def pack(self) -> None: ... class Babyl(_singlefileMailbox[BabylMessage]): def __init__(self, path: Text, factory: Callable[[IO[Any]], BabylMessage] | None = ..., create: bool = ...) -> None: ... def get_file(self, key: str) -> IO[bytes]: ... - def get_labels(self) -> List[str]: ... + def get_labels(self) -> list[str]: ... class Message(email.message.Message): def __init__(self, message: _MessageData | None = ...) -> None: ... @@ -133,7 +114,7 @@ class MaildirMessage(Message): class _mboxMMDFMessage(Message): def get_from(self) -> str: ... - def set_from(self, from_: str, time_: bool | Tuple[int, int, int, int, int, int, int, int, int] | None = ...) -> None: ... + def set_from(self, from_: str, time_: bool | tuple[int, int, int, int, int, int, int, int, int] | None = ...) -> None: ... def get_flags(self) -> str: ... def set_flags(self, flags: Iterable[str]) -> None: ... def add_flag(self, flag: str) -> None: ... @@ -142,13 +123,13 @@ class _mboxMMDFMessage(Message): class mboxMessage(_mboxMMDFMessage): ... class MHMessage(Message): - def get_sequences(self) -> List[str]: ... + def get_sequences(self) -> list[str]: ... def set_sequences(self, sequences: Iterable[str]) -> None: ... def add_sequence(self, sequence: str) -> None: ... def remove_sequence(self, sequence: str) -> None: ... class BabylMessage(Message): - def get_labels(self) -> List[str]: ... + def get_labels(self) -> list[str]: ... def set_labels(self, labels: Iterable[str]) -> None: ... def add_label(self, label: str) -> None: ... def remove_label(self, label: str) -> None: ... @@ -163,13 +144,13 @@ class _ProxyFile(Generic[AnyStr]): def read(self, size: int | None = ...) -> AnyStr: ... def read1(self, size: int | None = ...) -> AnyStr: ... def readline(self, size: int | None = ...) -> AnyStr: ... - def readlines(self, sizehint: int | None = ...) -> List[AnyStr]: ... + def readlines(self, sizehint: int | None = ...) -> list[AnyStr]: ... def __iter__(self) -> Iterator[AnyStr]: ... def tell(self) -> int: ... def seek(self, offset: int, whence: int = ...) -> None: ... def close(self) -> None: ... def __enter__(self) -> _ProxyFile[AnyStr]: ... - def __exit__(self, exc_type: Type[BaseException] | None, exc: BaseException | None, tb: TracebackType | None) -> None: ... + def __exit__(self, exc_type: type[BaseException] | None, exc: BaseException | None, tb: TracebackType | None) -> None: ... def readable(self) -> bool: ... def writable(self) -> bool: ... def seekable(self) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/mailcap.pyi b/mypy/typeshed/stdlib/@python2/mailcap.pyi index b29854f3c7445..6e0c918280ad3 100644 --- a/mypy/typeshed/stdlib/@python2/mailcap.pyi +++ b/mypy/typeshed/stdlib/@python2/mailcap.pyi @@ -1,8 +1,8 @@ -from typing import Dict, List, Mapping, Sequence, Tuple, Union +from typing import Mapping, Sequence -_Cap = Dict[str, Union[str, int]] +_Cap = dict[str, str | int] def findmatch( - caps: Mapping[str, List[_Cap]], MIMEtype: str, key: str = ..., filename: str = ..., plist: Sequence[str] = ... -) -> Tuple[str | None, _Cap | None]: ... -def getcaps() -> Dict[str, List[_Cap]]: ... + caps: Mapping[str, list[_Cap]], MIMEtype: str, key: str = ..., filename: str = ..., plist: Sequence[str] = ... +) -> tuple[str | None, _Cap | None]: ... +def getcaps() -> dict[str, list[_Cap]]: ... diff --git a/mypy/typeshed/stdlib/@python2/markupbase.pyi b/mypy/typeshed/stdlib/@python2/markupbase.pyi index 727daaacf25ea..869c341b66aab 100644 --- a/mypy/typeshed/stdlib/@python2/markupbase.pyi +++ b/mypy/typeshed/stdlib/@python2/markupbase.pyi @@ -1,8 +1,6 @@ -from typing import Tuple - class ParserBase(object): def __init__(self) -> None: ... def error(self, message: str) -> None: ... def reset(self) -> None: ... - def getpos(self) -> Tuple[int, int]: ... + def getpos(self) -> tuple[int, int]: ... def unknown_decl(self, data: str) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/math.pyi b/mypy/typeshed/stdlib/@python2/math.pyi index caddcedd864be..643242a73fa90 100644 --- a/mypy/typeshed/stdlib/@python2/math.pyi +++ b/mypy/typeshed/stdlib/@python2/math.pyi @@ -1,4 +1,4 @@ -from typing import Iterable, SupportsFloat, SupportsInt, Tuple +from typing import Iterable, SupportsFloat, SupportsInt e: float pi: float @@ -23,7 +23,7 @@ def fabs(__x: SupportsFloat) -> float: ... def factorial(__x: SupportsInt) -> int: ... def floor(__x: SupportsFloat) -> float: ... def fmod(__x: SupportsFloat, __y: SupportsFloat) -> float: ... -def frexp(__x: SupportsFloat) -> Tuple[float, int]: ... +def frexp(__x: SupportsFloat) -> tuple[float, int]: ... def fsum(__seq: Iterable[float]) -> float: ... def gamma(__x: SupportsFloat) -> float: ... def hypot(__x: SupportsFloat, __y: SupportsFloat) -> float: ... @@ -34,7 +34,7 @@ def lgamma(__x: SupportsFloat) -> float: ... def log(x: SupportsFloat, base: SupportsFloat = ...) -> float: ... def log10(__x: SupportsFloat) -> float: ... def log1p(__x: SupportsFloat) -> float: ... -def modf(__x: SupportsFloat) -> Tuple[float, float]: ... +def modf(__x: SupportsFloat) -> tuple[float, float]: ... def pow(__x: SupportsFloat, __y: SupportsFloat) -> float: ... def radians(__x: SupportsFloat) -> float: ... def sin(__x: SupportsFloat) -> float: ... diff --git a/mypy/typeshed/stdlib/@python2/mimetypes.pyi b/mypy/typeshed/stdlib/@python2/mimetypes.pyi index a9661dab56ad8..a7cddca65921f 100644 --- a/mypy/typeshed/stdlib/@python2/mimetypes.pyi +++ b/mypy/typeshed/stdlib/@python2/mimetypes.pyi @@ -1,29 +1,29 @@ import sys -from typing import IO, Dict, List, Sequence, Text, Tuple +from typing import IO, Sequence, Text -def guess_type(url: Text, strict: bool = ...) -> Tuple[str | None, str | None]: ... -def guess_all_extensions(type: str, strict: bool = ...) -> List[str]: ... +def guess_type(url: Text, strict: bool = ...) -> tuple[str | None, str | None]: ... +def guess_all_extensions(type: str, strict: bool = ...) -> list[str]: ... def guess_extension(type: str, strict: bool = ...) -> str | None: ... def init(files: Sequence[str] | None = ...) -> None: ... -def read_mime_types(file: str) -> Dict[str, str] | None: ... +def read_mime_types(file: str) -> dict[str, str] | None: ... def add_type(type: str, ext: str, strict: bool = ...) -> None: ... inited: bool -knownfiles: List[str] -suffix_map: Dict[str, str] -encodings_map: Dict[str, str] -types_map: Dict[str, str] -common_types: Dict[str, str] +knownfiles: list[str] +suffix_map: dict[str, str] +encodings_map: dict[str, str] +types_map: dict[str, str] +common_types: dict[str, str] class MimeTypes: - suffix_map: Dict[str, str] - encodings_map: Dict[str, str] - types_map: Tuple[Dict[str, str], Dict[str, str]] - types_map_inv: Tuple[Dict[str, str], Dict[str, str]] - def __init__(self, filenames: Tuple[str, ...] = ..., strict: bool = ...) -> None: ... + suffix_map: dict[str, str] + encodings_map: dict[str, str] + types_map: tuple[dict[str, str], dict[str, str]] + types_map_inv: tuple[dict[str, str], dict[str, str]] + def __init__(self, filenames: tuple[str, ...] = ..., strict: bool = ...) -> None: ... def guess_extension(self, type: str, strict: bool = ...) -> str | None: ... - def guess_type(self, url: str, strict: bool = ...) -> Tuple[str | None, str | None]: ... - def guess_all_extensions(self, type: str, strict: bool = ...) -> List[str]: ... + def guess_type(self, url: str, strict: bool = ...) -> tuple[str | None, str | None]: ... + def guess_all_extensions(self, type: str, strict: bool = ...) -> list[str]: ... def read(self, filename: str, strict: bool = ...) -> None: ... def readfp(self, fp: IO[str], strict: bool = ...) -> None: ... if sys.platform == "win32": diff --git a/mypy/typeshed/stdlib/@python2/mmap.pyi b/mypy/typeshed/stdlib/@python2/mmap.pyi index 44369e6c051d1..4e08bc28c28a5 100644 --- a/mypy/typeshed/stdlib/@python2/mmap.pyi +++ b/mypy/typeshed/stdlib/@python2/mmap.pyi @@ -30,6 +30,7 @@ class mmap(Sequence[bytes]): def __init__( self, fileno: int, length: int, flags: int = ..., prot: int = ..., access: int = ..., offset: int = ... ) -> None: ... + def close(self) -> None: ... def flush(self, offset: int = ..., size: int = ...) -> int: ... def move(self, dest: int, src: int, count: int) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/modulefinder.pyi b/mypy/typeshed/stdlib/@python2/modulefinder.pyi index 76fd014daf6e0..458b037723f39 100644 --- a/mypy/typeshed/stdlib/@python2/modulefinder.pyi +++ b/mypy/typeshed/stdlib/@python2/modulefinder.pyi @@ -1,40 +1,39 @@ from types import CodeType -from typing import IO, Any, Container, Dict, Iterable, List, Sequence, Tuple +from typing import IO, Any, Container, Iterable, Sequence LOAD_CONST: int # undocumented IMPORT_NAME: int # undocumented STORE_NAME: int # undocumented STORE_GLOBAL: int # undocumented -STORE_OPS: Tuple[int, int] # undocumented +STORE_OPS: tuple[int, int] # undocumented EXTENDED_ARG: int # undocumented -packagePathMap: Dict[str, List[str]] # undocumented +packagePathMap: dict[str, list[str]] # undocumented def AddPackagePath(packagename: str, path: str) -> None: ... -replacePackageMap: Dict[str, str] # undocumented +replacePackageMap: dict[str, str] # undocumented def ReplacePackage(oldname: str, newname: str) -> None: ... class Module: # undocumented def __init__(self, name: str, file: str | None = ..., path: str | None = ...) -> None: ... - def __repr__(self) -> str: ... class ModuleFinder: - modules: Dict[str, Module] - path: List[str] # undocumented - badmodules: Dict[str, Dict[str, int]] # undocumented + modules: dict[str, Module] + path: list[str] # undocumented + badmodules: dict[str, dict[str, int]] # undocumented debug: int # undocumented indent: int # undocumented excludes: Container[str] # undocumented - replace_paths: Sequence[Tuple[str, str]] # undocumented + replace_paths: Sequence[tuple[str, str]] # undocumented def __init__( self, - path: List[str] | None = ..., + path: list[str] | None = ..., debug: int = ..., excludes: Container[str] = ..., - replace_paths: Sequence[Tuple[str, str]] = ..., + replace_paths: Sequence[tuple[str, str]] = ..., ) -> None: ... def msg(self, level: int, str: str, *args: Any) -> None: ... # undocumented def msgin(self, *args: Any) -> None: ... # undocumented @@ -42,22 +41,22 @@ class ModuleFinder: def run_script(self, pathname: str) -> None: ... def load_file(self, pathname: str) -> None: ... # undocumented def import_hook( - self, name: str, caller: Module | None = ..., fromlist: List[str] | None = ..., level: int = ... + self, name: str, caller: Module | None = ..., fromlist: list[str] | None = ..., level: int = ... ) -> Module | None: ... # undocumented def determine_parent(self, caller: Module | None, level: int = ...) -> Module | None: ... # undocumented - def find_head_package(self, parent: Module, name: str) -> Tuple[Module, str]: ... # undocumented + def find_head_package(self, parent: Module, name: str) -> tuple[Module, str]: ... # undocumented def load_tail(self, q: Module, tail: str) -> Module: ... # undocumented def ensure_fromlist(self, m: Module, fromlist: Iterable[str], recursive: int = ...) -> None: ... # undocumented def find_all_submodules(self, m: Module) -> Iterable[str]: ... # undocumented def import_module(self, partname: str, fqname: str, parent: Module) -> Module | None: ... # undocumented - def load_module(self, fqname: str, fp: IO[str], pathname: str, file_info: Tuple[str, str, str]) -> Module: ... # undocumented + def load_module(self, fqname: str, fp: IO[str], pathname: str, file_info: tuple[str, str, str]) -> Module: ... # undocumented def scan_code(self, co: CodeType, m: Module) -> None: ... # undocumented def load_package(self, fqname: str, pathname: str) -> Module: ... # undocumented def add_module(self, fqname: str) -> Module: ... # undocumented def find_module( self, name: str, path: str | None, parent: Module | None = ... - ) -> Tuple[IO[Any] | None, str | None, Tuple[str, str, int]]: ... # undocumented + ) -> tuple[IO[Any] | None, str | None, tuple[str, str, int]]: ... # undocumented def report(self) -> None: ... - def any_missing(self) -> List[str]: ... # undocumented - def any_missing_maybe(self) -> Tuple[List[str], List[str]]: ... # undocumented + def any_missing(self) -> list[str]: ... # undocumented + def any_missing_maybe(self) -> tuple[list[str], list[str]]: ... # undocumented def replace_paths_in_code(self, co: CodeType) -> CodeType: ... # undocumented diff --git a/mypy/typeshed/stdlib/@python2/msilib/__init__.pyi b/mypy/typeshed/stdlib/@python2/msilib/__init__.pyi index fa67576968455..a49f37f0de1d8 100644 --- a/mypy/typeshed/stdlib/@python2/msilib/__init__.pyi +++ b/mypy/typeshed/stdlib/@python2/msilib/__init__.pyi @@ -1,6 +1,6 @@ import sys from types import ModuleType -from typing import Any, Container, Dict, Iterable, List, Sequence, Set, Tuple, Type +from typing import Any, Container, Iterable, Sequence from typing_extensions import Literal if sys.platform == "win32": @@ -21,22 +21,25 @@ if sys.platform == "win32": type_nullable: Literal[0x1000] type_key: Literal[0x2000] knownbits: Literal[0x3FFF] + class Table: name: str - fields: List[Tuple[int, str, int]] + fields: list[tuple[int, str, int]] def __init__(self, name: str) -> None: ... def add_field(self, index: int, name: str, type: int) -> None: ... def sql(self) -> str: ... def create(self, db: _Database) -> None: ... + class _Unspecified: ... + def change_sequence( - seq: Sequence[Tuple[str, str | None, int]], + seq: Sequence[tuple[str, str | None, int]], action: str, - seqno: int | Type[_Unspecified] = ..., - cond: str | Type[_Unspecified] = ..., + seqno: int | type[_Unspecified] = ..., + cond: str | type[_Unspecified] = ..., ) -> None: ... - def add_data(db: _Database, table: str, values: Iterable[Tuple[Any, ...]]) -> None: ... + def add_data(db: _Database, table: str, values: Iterable[tuple[Any, ...]]) -> None: ... def add_stream(db: _Database, name: str, path: str) -> None: ... def init_database( name: str, schema: ModuleType, ProductName: str, ProductCode: str, ProductVersion: str, Manufacturer: str @@ -44,17 +47,19 @@ if sys.platform == "win32": def add_tables(db: _Database, module: ModuleType) -> None: ... def make_id(str: str) -> str: ... def gen_uuid() -> str: ... + class CAB: name: str - files: List[Tuple[str, str]] - filenames: Set[str] + files: list[tuple[str, str]] + filenames: set[str] index: int def __init__(self, name: str) -> None: ... def gen_id(self, file: str) -> str: ... - def append(self, full: str, file: str, logical: str) -> Tuple[int, str]: ... + def append(self, full: str, file: str, logical: str) -> tuple[int, str]: ... def commit(self, db: _Database) -> None: ... - _directories: Set[str] + _directories: set[str] + class Directory: db: _Database @@ -63,9 +68,9 @@ if sys.platform == "win32": physical: str logical: str component: str | None - short_names: Set[str] - ids: Set[str] - keyfiles: Dict[str, str] + short_names: set[str] + ids: set[str] + keyfiles: dict[str, str] componentflags: int | None absolute: str def __init__( @@ -88,13 +93,14 @@ if sys.platform == "win32": ) -> None: ... def make_short(self, file: str) -> str: ... def add_file(self, file: str, src: str | None = ..., version: str | None = ..., language: str | None = ...) -> str: ... - def glob(self, pattern: str, exclude: Container[str] | None = ...) -> List[str]: ... + def glob(self, pattern: str, exclude: Container[str] | None = ...) -> list[str]: ... def remove_pyc(self) -> None: ... + class Binary: name: str def __init__(self, fname: str) -> None: ... - def __repr__(self) -> str: ... + class Feature: id: str @@ -111,6 +117,7 @@ if sys.platform == "win32": attributes: int = ..., ) -> None: ... def set_current(self) -> None: ... + class Control: dlg: Dialog @@ -119,12 +126,14 @@ if sys.platform == "win32": def event(self, event: str, argument: str, condition: str = ..., ordering: int | None = ...) -> None: ... def mapping(self, event: str, attribute: str) -> None: ... def condition(self, action: str, condition: str) -> None: ... + class RadioButtonGroup(Control): property: str index: int def __init__(self, dlg: Dialog, name: str, property: str) -> None: ... def add(self, name: str, x: int, y: int, w: int, h: int, text: str, value: str | None = ...) -> None: ... + class Dialog: db: _Database diff --git a/mypy/typeshed/stdlib/@python2/msilib/schema.pyi b/mypy/typeshed/stdlib/@python2/msilib/schema.pyi index d59e9767c3de0..4ad9a1783fcd0 100644 --- a/mypy/typeshed/stdlib/@python2/msilib/schema.pyi +++ b/mypy/typeshed/stdlib/@python2/msilib/schema.pyi @@ -1,5 +1,4 @@ import sys -from typing import List, Tuple if sys.platform == "win32": from . import Table @@ -90,6 +89,6 @@ if sys.platform == "win32": Upgrade: Table Verb: Table - tables: List[Table] + tables: list[Table] - _Validation_records: List[Tuple[str, str, str, int | None, int | None, str | None, int | None, str | None, str | None, str]] + _Validation_records: list[tuple[str, str, str, int | None, int | None, str | None, int | None, str | None, str | None, str]] diff --git a/mypy/typeshed/stdlib/@python2/msilib/sequence.pyi b/mypy/typeshed/stdlib/@python2/msilib/sequence.pyi index e4f400d33233e..30346aba33673 100644 --- a/mypy/typeshed/stdlib/@python2/msilib/sequence.pyi +++ b/mypy/typeshed/stdlib/@python2/msilib/sequence.pyi @@ -1,9 +1,8 @@ import sys -from typing import List, Optional, Tuple if sys.platform == "win32": - _SequenceType = List[Tuple[str, Optional[str], int]] + _SequenceType = list[tuple[str, str | None, int]] AdminExecuteSequence: _SequenceType AdminUISequence: _SequenceType @@ -11,4 +10,4 @@ if sys.platform == "win32": InstallExecuteSequence: _SequenceType InstallUISequence: _SequenceType - tables: List[str] + tables: list[str] diff --git a/mypy/typeshed/stdlib/@python2/msilib/text.pyi b/mypy/typeshed/stdlib/@python2/msilib/text.pyi index 4ae8ee68184b4..879429ecea85f 100644 --- a/mypy/typeshed/stdlib/@python2/msilib/text.pyi +++ b/mypy/typeshed/stdlib/@python2/msilib/text.pyi @@ -1,9 +1,8 @@ import sys -from typing import List, Tuple if sys.platform == "win32": - ActionText: List[Tuple[str, str, str | None]] - UIText: List[Tuple[str, str | None]] + ActionText: list[tuple[str, str, str | None]] + UIText: list[tuple[str, str | None]] - tables: List[str] + tables: list[str] diff --git a/mypy/typeshed/stdlib/@python2/multiprocessing/dummy/__init__.pyi b/mypy/typeshed/stdlib/@python2/multiprocessing/dummy/__init__.pyi index 80a1456d1be88..a5381ed3839c8 100644 --- a/mypy/typeshed/stdlib/@python2/multiprocessing/dummy/__init__.pyi +++ b/mypy/typeshed/stdlib/@python2/multiprocessing/dummy/__init__.pyi @@ -2,7 +2,7 @@ import array import threading import weakref from Queue import Queue -from typing import Any, List +from typing import Any class DummyProcess(threading.Thread): _children: weakref.WeakKeyDictionary[Any, Any] @@ -35,7 +35,7 @@ JoinableQueue = Queue def Array(typecode, sequence, lock=...) -> array.array[Any]: ... def Manager() -> Any: ... def Pool(processes=..., initializer=..., initargs=...) -> Any: ... -def active_children() -> List[Any]: ... +def active_children() -> list[Any]: ... def current_process() -> threading.Thread: ... def freeze_support() -> None: ... def shutdown() -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/multiprocessing/dummy/connection.pyi b/mypy/typeshed/stdlib/@python2/multiprocessing/dummy/connection.pyi index ae5e05e9ccdda..f01b3f8cd6609 100644 --- a/mypy/typeshed/stdlib/@python2/multiprocessing/dummy/connection.pyi +++ b/mypy/typeshed/stdlib/@python2/multiprocessing/dummy/connection.pyi @@ -1,7 +1,7 @@ from Queue import Queue -from typing import Any, List, Tuple +from typing import Any -families: List[None] +families: list[None] class Connection(object): _in: Any @@ -22,4 +22,4 @@ class Listener(object): def close(self) -> None: ... def Client(address) -> Connection: ... -def Pipe(duplex=...) -> Tuple[Connection, Connection]: ... +def Pipe(duplex=...) -> tuple[Connection, Connection]: ... diff --git a/mypy/typeshed/stdlib/@python2/multiprocessing/pool.pyi b/mypy/typeshed/stdlib/@python2/multiprocessing/pool.pyi index be9747e89c2fc..440b5e83c5006 100644 --- a/mypy/typeshed/stdlib/@python2/multiprocessing/pool.pyi +++ b/mypy/typeshed/stdlib/@python2/multiprocessing/pool.pyi @@ -1,6 +1,5 @@ -from typing import Any, Callable, Dict, Iterable, Iterator, List, TypeVar - -_T = TypeVar("_T", bound=Pool) +from _typeshed import Self +from typing import Any, Callable, Iterable, Iterator class AsyncResult: def get(self, timeout: float | None = ...) -> Any: ... @@ -9,7 +8,7 @@ class AsyncResult: def successful(self) -> bool: ... class IMapIterator(Iterator[Any]): - def __iter__(self) -> Iterator[Any]: ... + def __iter__(self: Self) -> Self: ... def next(self, timeout: float | None = ...) -> Any: ... class IMapUnorderedIterator(IMapIterator): ... @@ -22,15 +21,15 @@ class Pool(object): initargs: Iterable[Any] = ..., maxtasksperchild: int | None = ..., ) -> None: ... - def apply(self, func: Callable[..., Any], args: Iterable[Any] = ..., kwds: Dict[str, Any] = ...) -> Any: ... + def apply(self, func: Callable[..., Any], args: Iterable[Any] = ..., kwds: dict[str, Any] = ...) -> Any: ... def apply_async( self, func: Callable[..., Any], args: Iterable[Any] = ..., - kwds: Dict[str, Any] = ..., + kwds: dict[str, Any] = ..., callback: Callable[..., None] | None = ..., ) -> AsyncResult: ... - def map(self, func: Callable[..., Any], iterable: Iterable[Any] = ..., chunksize: int | None = ...) -> List[Any]: ... + def map(self, func: Callable[..., Any], iterable: Iterable[Any] = ..., chunksize: int | None = ...) -> list[Any]: ... def map_async( self, func: Callable[..., Any], diff --git a/mypy/typeshed/stdlib/@python2/mutex.pyi b/mypy/typeshed/stdlib/@python2/mutex.pyi index e0931dc1188a9..fd5363de73e5c 100644 --- a/mypy/typeshed/stdlib/@python2/mutex.pyi +++ b/mypy/typeshed/stdlib/@python2/mutex.pyi @@ -1,10 +1,11 @@ -from typing import Any, Callable, Deque, TypeVar +from collections import deque +from typing import Any, Callable, TypeVar _T = TypeVar("_T") class mutex: locked: bool - queue: Deque[Any] + queue: deque[Any] def __init__(self) -> None: ... def test(self) -> bool: ... def testandset(self) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/netrc.pyi b/mypy/typeshed/stdlib/@python2/netrc.pyi index 3033c2f78955a..fc5fababa7e79 100644 --- a/mypy/typeshed/stdlib/@python2/netrc.pyi +++ b/mypy/typeshed/stdlib/@python2/netrc.pyi @@ -1,4 +1,4 @@ -from typing import Dict, List, Optional, Text, Tuple +from typing import Text class NetrcParseError(Exception): filename: str | None @@ -7,10 +7,10 @@ class NetrcParseError(Exception): def __init__(self, msg: str, filename: Text | None = ..., lineno: int | None = ...) -> None: ... # (login, account, password) tuple -_NetrcTuple = Tuple[str, Optional[str], Optional[str]] +_NetrcTuple = tuple[str, str | None, str | None] class netrc: - hosts: Dict[str, _NetrcTuple] - macros: Dict[str, List[str]] + hosts: dict[str, _NetrcTuple] + macros: dict[str, list[str]] def __init__(self, file: Text | None = ...) -> None: ... def authenticators(self, host: str) -> _NetrcTuple | None: ... diff --git a/mypy/typeshed/stdlib/@python2/nis.pyi b/mypy/typeshed/stdlib/@python2/nis.pyi index bc6c2bc072566..10eef2336a834 100644 --- a/mypy/typeshed/stdlib/@python2/nis.pyi +++ b/mypy/typeshed/stdlib/@python2/nis.pyi @@ -1,9 +1,9 @@ import sys -from typing import Dict, List if sys.platform != "win32": - def cat(map: str, domain: str = ...) -> Dict[str, str]: ... + def cat(map: str, domain: str = ...) -> dict[str, str]: ... def get_default_domain() -> str: ... - def maps(domain: str = ...) -> List[str]: ... + def maps(domain: str = ...) -> list[str]: ... def match(key: str, map: str, domain: str = ...) -> str: ... + class error(Exception): ... diff --git a/mypy/typeshed/stdlib/@python2/nntplib.pyi b/mypy/typeshed/stdlib/@python2/nntplib.pyi index 56545d3b88b4c..7cacb07bdb774 100644 --- a/mypy/typeshed/stdlib/@python2/nntplib.pyi +++ b/mypy/typeshed/stdlib/@python2/nntplib.pyi @@ -1,10 +1,11 @@ import datetime import socket import ssl -from typing import IO, Any, Dict, Iterable, List, NamedTuple, Tuple, TypeVar, Union +from _typeshed import Self +from builtins import list as List # alias to avoid a name clash with a method named `list` in `_NNTPBase` +from typing import IO, Any, Iterable, NamedTuple -_SelfT = TypeVar("_SelfT", bound=_NNTPBase) -_File = Union[IO[bytes], bytes, str, None] +_File = IO[bytes] | bytes | str | None class NNTPError(Exception): response: str @@ -27,7 +28,7 @@ class GroupInfo(NamedTuple): class ArticleInfo(NamedTuple): number: int message_id: str - lines: List[bytes] + lines: list[bytes] def decode_header(header_str: str) -> str: ... @@ -45,35 +46,35 @@ class _NNTPBase: nntp_implementation: str nntp_version: int def __init__(self, file: IO[bytes], host: str, readermode: bool | None = ..., timeout: float = ...) -> None: ... - def __enter__(self: _SelfT) -> _SelfT: ... + def __enter__(self: Self) -> Self: ... def __exit__(self, *args: Any) -> None: ... def getwelcome(self) -> str: ... - def getcapabilities(self) -> Dict[str, List[str]]: ... + def getcapabilities(self) -> dict[str, List[str]]: ... def set_debuglevel(self, level: int) -> None: ... def debug(self, level: int) -> None: ... - def capabilities(self) -> Tuple[str, Dict[str, List[str]]]: ... - def newgroups(self, date: datetime.date | datetime.datetime, *, file: _File = ...) -> Tuple[str, List[str]]: ... - def newnews(self, group: str, date: datetime.date | datetime.datetime, *, file: _File = ...) -> Tuple[str, List[str]]: ... - def list(self, group_pattern: str | None = ..., *, file: _File = ...) -> Tuple[str, List[str]]: ... + def capabilities(self) -> tuple[str, dict[str, List[str]]]: ... + def newgroups(self, date: datetime.date | datetime.datetime, *, file: _File = ...) -> tuple[str, List[str]]: ... + def newnews(self, group: str, date: datetime.date | datetime.datetime, *, file: _File = ...) -> tuple[str, List[str]]: ... + def list(self, group_pattern: str | None = ..., *, file: _File = ...) -> tuple[str, List[str]]: ... def description(self, group: str) -> str: ... - def descriptions(self, group_pattern: str) -> Tuple[str, Dict[str, str]]: ... - def group(self, name: str) -> Tuple[str, int, int, int, str]: ... - def help(self, *, file: _File = ...) -> Tuple[str, List[str]]: ... - def stat(self, message_spec: Any = ...) -> Tuple[str, int, str]: ... - def next(self) -> Tuple[str, int, str]: ... - def last(self) -> Tuple[str, int, str]: ... - def head(self, message_spec: Any = ..., *, file: _File = ...) -> Tuple[str, ArticleInfo]: ... - def body(self, message_spec: Any = ..., *, file: _File = ...) -> Tuple[str, ArticleInfo]: ... - def article(self, message_spec: Any = ..., *, file: _File = ...) -> Tuple[str, ArticleInfo]: ... + def descriptions(self, group_pattern: str) -> tuple[str, dict[str, str]]: ... + def group(self, name: str) -> tuple[str, int, int, int, str]: ... + def help(self, *, file: _File = ...) -> tuple[str, List[str]]: ... + def stat(self, message_spec: Any = ...) -> tuple[str, int, str]: ... + def next(self) -> tuple[str, int, str]: ... + def last(self) -> tuple[str, int, str]: ... + def head(self, message_spec: Any = ..., *, file: _File = ...) -> tuple[str, ArticleInfo]: ... + def body(self, message_spec: Any = ..., *, file: _File = ...) -> tuple[str, ArticleInfo]: ... + def article(self, message_spec: Any = ..., *, file: _File = ...) -> tuple[str, ArticleInfo]: ... def slave(self) -> str: ... - def xhdr(self, hdr: str, str: Any, *, file: _File = ...) -> Tuple[str, List[str]]: ... - def xover(self, start: int, end: int, *, file: _File = ...) -> Tuple[str, List[Tuple[int, Dict[str, str]]]]: ... + def xhdr(self, hdr: str, str: Any, *, file: _File = ...) -> tuple[str, List[str]]: ... + def xover(self, start: int, end: int, *, file: _File = ...) -> tuple[str, List[tuple[int, dict[str, str]]]]: ... def over( - self, message_spec: None | str | List[Any] | Tuple[Any, ...], *, file: _File = ... - ) -> Tuple[str, List[Tuple[int, Dict[str, str]]]]: ... - def xgtitle(self, group: str, *, file: _File = ...) -> Tuple[str, List[Tuple[str, str]]]: ... - def xpath(self, id: Any) -> Tuple[str, str]: ... - def date(self) -> Tuple[str, datetime.datetime]: ... + self, message_spec: None | str | List[Any] | tuple[Any, ...], *, file: _File = ... + ) -> tuple[str, List[tuple[int, dict[str, str]]]]: ... + def xgtitle(self, group: str, *, file: _File = ...) -> tuple[str, List[tuple[str, str]]]: ... + def xpath(self, id: Any) -> tuple[str, str]: ... + def date(self) -> tuple[str, datetime.datetime]: ... def post(self, data: bytes | Iterable[bytes]) -> str: ... def ihave(self, message_id: Any, data: bytes | Iterable[bytes]) -> str: ... def quit(self) -> str: ... diff --git a/mypy/typeshed/stdlib/@python2/ntpath.pyi b/mypy/typeshed/stdlib/@python2/ntpath.pyi index 514db760886f1..33732903cb4cf 100644 --- a/mypy/typeshed/stdlib/@python2/ntpath.pyi +++ b/mypy/typeshed/stdlib/@python2/ntpath.pyi @@ -1,7 +1,7 @@ import os import sys from genericpath import exists as exists -from typing import Any, AnyStr, Callable, List, Sequence, Text, Tuple, TypeVar, overload +from typing import Any, AnyStr, Callable, Sequence, Text, TypeVar, overload _T = TypeVar("_T") @@ -74,11 +74,11 @@ def relpath(path: Text, start: Text | None = ...) -> Text: ... def samefile(f1: Text, f2: Text) -> bool: ... def sameopenfile(fp1: int, fp2: int) -> bool: ... def samestat(s1: os.stat_result, s2: os.stat_result) -> bool: ... -def split(p: AnyStr) -> Tuple[AnyStr, AnyStr]: ... -def splitdrive(p: AnyStr) -> Tuple[AnyStr, AnyStr]: ... -def splitext(p: AnyStr) -> Tuple[AnyStr, AnyStr]: ... +def split(p: AnyStr) -> tuple[AnyStr, AnyStr]: ... +def splitdrive(p: AnyStr) -> tuple[AnyStr, AnyStr]: ... +def splitext(p: AnyStr) -> tuple[AnyStr, AnyStr]: ... if sys.platform == "win32": - def splitunc(p: AnyStr) -> Tuple[AnyStr, AnyStr]: ... # deprecated + def splitunc(p: AnyStr) -> tuple[AnyStr, AnyStr]: ... # deprecated -def walk(path: AnyStr, visit: Callable[[_T, AnyStr, List[AnyStr]], Any], arg: _T) -> None: ... +def walk(path: AnyStr, visit: Callable[[_T, AnyStr, list[AnyStr]], Any], arg: _T) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/numbers.pyi b/mypy/typeshed/stdlib/@python2/numbers.pyi index fb88e076d4462..73384a30803cb 100644 --- a/mypy/typeshed/stdlib/@python2/numbers.pyi +++ b/mypy/typeshed/stdlib/@python2/numbers.pyi @@ -46,8 +46,8 @@ class Complex(Number): def __rpow__(self, base: Any) -> Any: ... def __abs__(self) -> Real: ... def conjugate(self) -> Any: ... - def __eq__(self, other: Any) -> bool: ... - def __ne__(self, other: Any) -> bool: ... + def __eq__(self, other: object) -> bool: ... + def __ne__(self, other: object) -> bool: ... class Real(Complex, SupportsFloat): @abstractmethod diff --git a/mypy/typeshed/stdlib/@python2/opcode.pyi b/mypy/typeshed/stdlib/@python2/opcode.pyi index 893dd7c7df9c5..be162da4e4969 100644 --- a/mypy/typeshed/stdlib/@python2/opcode.pyi +++ b/mypy/typeshed/stdlib/@python2/opcode.pyi @@ -1,15 +1,15 @@ -from typing import Dict, List, Sequence +from typing import Sequence cmp_op: Sequence[str] -hasconst: List[int] -hasname: List[int] -hasjrel: List[int] -hasjabs: List[int] -haslocal: List[int] -hascompare: List[int] -hasfree: List[int] -opname: List[str] +hasconst: list[int] +hasname: list[int] +hasjrel: list[int] +hasjabs: list[int] +haslocal: list[int] +hascompare: list[int] +hasfree: list[int] +opname: list[str] -opmap: Dict[str, int] +opmap: dict[str, int] HAVE_ARGUMENT: int EXTENDED_ARG: int diff --git a/mypy/typeshed/stdlib/@python2/operator.pyi b/mypy/typeshed/stdlib/@python2/operator.pyi index 76a8a9b6bee4e..cff20b85898bb 100644 --- a/mypy/typeshed/stdlib/@python2/operator.pyi +++ b/mypy/typeshed/stdlib/@python2/operator.pyi @@ -1,16 +1,4 @@ -from typing import ( - Any, - Container, - Generic, - Mapping, - MutableMapping, - MutableSequence, - Sequence, - SupportsAbs, - Tuple, - TypeVar, - overload, -) +from typing import Any, Container, Generic, Mapping, MutableMapping, MutableSequence, Sequence, SupportsAbs, TypeVar, overload _T = TypeVar("_T") _T_co = TypeVar("_T_co", covariant=True) @@ -128,26 +116,26 @@ class attrgetter(Generic[_T_co]): @overload def __new__(cls, attr: str) -> attrgetter[Any]: ... @overload - def __new__(cls, attr: str, __attr2: str) -> attrgetter[Tuple[Any, Any]]: ... + def __new__(cls, attr: str, __attr2: str) -> attrgetter[tuple[Any, Any]]: ... @overload - def __new__(cls, attr: str, __attr2: str, __attr3: str) -> attrgetter[Tuple[Any, Any, Any]]: ... + def __new__(cls, attr: str, __attr2: str, __attr3: str) -> attrgetter[tuple[Any, Any, Any]]: ... @overload - def __new__(cls, attr: str, __attr2: str, __attr3: str, __attr4: str) -> attrgetter[Tuple[Any, Any, Any, Any]]: ... + def __new__(cls, attr: str, __attr2: str, __attr3: str, __attr4: str) -> attrgetter[tuple[Any, Any, Any, Any]]: ... @overload - def __new__(cls, attr: str, *attrs: str) -> attrgetter[Tuple[Any, ...]]: ... + def __new__(cls, attr: str, *attrs: str) -> attrgetter[tuple[Any, ...]]: ... def __call__(self, obj: Any) -> _T_co: ... class itemgetter(Generic[_T_co]): @overload def __new__(cls, item: Any) -> itemgetter[Any]: ... @overload - def __new__(cls, item: Any, __item2: Any) -> itemgetter[Tuple[Any, Any]]: ... + def __new__(cls, item: Any, __item2: Any) -> itemgetter[tuple[Any, Any]]: ... @overload - def __new__(cls, item: Any, __item2: Any, __item3: Any) -> itemgetter[Tuple[Any, Any, Any]]: ... + def __new__(cls, item: Any, __item2: Any, __item3: Any) -> itemgetter[tuple[Any, Any, Any]]: ... @overload - def __new__(cls, item: Any, __item2: Any, __item3: Any, __item4: Any) -> itemgetter[Tuple[Any, Any, Any, Any]]: ... + def __new__(cls, item: Any, __item2: Any, __item3: Any, __item4: Any) -> itemgetter[tuple[Any, Any, Any, Any]]: ... @overload - def __new__(cls, item: Any, *items: Any) -> itemgetter[Tuple[Any, ...]]: ... + def __new__(cls, item: Any, *items: Any) -> itemgetter[tuple[Any, ...]]: ... def __call__(self, obj: Any) -> _T_co: ... class methodcaller: diff --git a/mypy/typeshed/stdlib/@python2/optparse.pyi b/mypy/typeshed/stdlib/@python2/optparse.pyi index 08a926e301b3b..d033cb9a6da69 100644 --- a/mypy/typeshed/stdlib/@python2/optparse.pyi +++ b/mypy/typeshed/stdlib/@python2/optparse.pyi @@ -1,9 +1,9 @@ -from typing import IO, Any, AnyStr, Callable, Dict, Iterable, List, Mapping, Sequence, Tuple, Type, Union, overload +from typing import IO, Any, AnyStr, Callable, Iterable, Mapping, Sequence, overload # See https://groups.google.com/forum/#!topic/python-ideas/gA1gdj3RZ5g -_Text = Union[str, unicode] +_Text = str | unicode -NO_DEFAULT: Tuple[_Text, ...] +NO_DEFAULT: tuple[_Text, ...] SUPPRESS_HELP: _Text SUPPRESS_USAGE: _Text @@ -42,7 +42,7 @@ class HelpFormatter: indent_increment: int level: int max_help_position: int - option_strings: Dict[Option, _Text] + option_strings: dict[Option, _Text] parser: OptionParser short_first: Any width: int @@ -76,25 +76,25 @@ class TitledHelpFormatter(HelpFormatter): def format_usage(self, usage: _Text) -> _Text: ... class Option: - ACTIONS: Tuple[_Text, ...] - ALWAYS_TYPED_ACTIONS: Tuple[_Text, ...] - ATTRS: List[_Text] - CHECK_METHODS: List[Callable[..., Any]] | None - CONST_ACTIONS: Tuple[_Text, ...] - STORE_ACTIONS: Tuple[_Text, ...] - TYPED_ACTIONS: Tuple[_Text, ...] - TYPES: Tuple[_Text, ...] - TYPE_CHECKER: Dict[_Text, Callable[..., Any]] - _long_opts: List[_Text] - _short_opts: List[_Text] + ACTIONS: tuple[_Text, ...] + ALWAYS_TYPED_ACTIONS: tuple[_Text, ...] + ATTRS: list[_Text] + CHECK_METHODS: list[Callable[..., Any]] | None + CONST_ACTIONS: tuple[_Text, ...] + STORE_ACTIONS: tuple[_Text, ...] + TYPED_ACTIONS: tuple[_Text, ...] + TYPES: tuple[_Text, ...] + TYPE_CHECKER: dict[_Text, Callable[..., Any]] + _long_opts: list[_Text] + _short_opts: list[_Text] action: _Text dest: _Text | None default: Any nargs: int type: Any callback: Callable[..., Any] | None - callback_args: Tuple[Any, ...] | None - callback_kwargs: Dict[_Text, Any] | None + callback_args: tuple[Any, ...] | None + callback_kwargs: dict[_Text, Any] | None help: _Text | None metavar: _Text | None def __init__(self, *opts: _Text | None, **attrs: Any) -> None: ... @@ -104,9 +104,9 @@ class Option: def _check_const(self) -> None: ... def _check_dest(self) -> None: ... def _check_nargs(self) -> None: ... - def _check_opt_strings(self, opts: Iterable[_Text | None]) -> List[_Text]: ... + def _check_opt_strings(self, opts: Iterable[_Text | None]) -> list[_Text]: ... def _check_type(self) -> None: ... - def _set_attrs(self, attrs: Dict[_Text, Any]) -> None: ... + def _set_attrs(self, attrs: dict[_Text, Any]) -> None: ... def _set_opt_strings(self, opts: Iterable[_Text]) -> None: ... def check_value(self, opt: _Text, value: Any) -> Any: ... def convert_value(self, opt: _Text, value: Any) -> Any: ... @@ -118,13 +118,13 @@ class Option: make_option = Option class OptionContainer: - _long_opt: Dict[_Text, Option] - _short_opt: Dict[_Text, Option] + _long_opt: dict[_Text, Option] + _short_opt: dict[_Text, Option] conflict_handler: _Text - defaults: Dict[_Text, Any] + defaults: dict[_Text, Any] description: Any - option_class: Type[Option] - def __init__(self, option_class: Type[Option], conflict_handler: Any, description: Any) -> None: ... + option_class: type[Option] + def __init__(self, option_class: type[Option], conflict_handler: Any, description: Any) -> None: ... def _check_conflict(self, option: Any) -> None: ... def _create_option_mappings(self) -> None: ... def _share_option_mappings(self, parser: OptionParser) -> None: ... @@ -145,7 +145,7 @@ class OptionContainer: def set_description(self, description: Any) -> None: ... class OptionGroup(OptionContainer): - option_list: List[Option] + option_list: list[Option] parser: OptionParser title: _Text def __init__(self, parser: OptionParser, title: _Text, description: _Text | None = ...) -> None: ... @@ -167,13 +167,13 @@ class OptionParser(OptionContainer): allow_interspersed_args: bool epilog: _Text | None formatter: HelpFormatter - largs: List[_Text] | None - option_groups: List[OptionGroup] - option_list: List[Option] + largs: list[_Text] | None + option_groups: list[OptionGroup] + option_list: list[Option] process_default_values: Any prog: _Text | None - rargs: List[Any] | None - standard_option_list: List[Option] + rargs: list[Any] | None + standard_option_list: list[Option] usage: _Text | None values: Values | None version: _Text @@ -181,7 +181,7 @@ class OptionParser(OptionContainer): self, usage: _Text | None = ..., option_list: Iterable[Option] | None = ..., - option_class: Type[Option] = ..., + option_class: type[Option] = ..., version: _Text | None = ..., conflict_handler: _Text = ..., description: _Text | None = ..., @@ -193,19 +193,19 @@ class OptionParser(OptionContainer): def _add_help_option(self) -> None: ... def _add_version_option(self) -> None: ... def _create_option_list(self) -> None: ... - def _get_all_options(self) -> List[Option]: ... - def _get_args(self, args: Iterable[Any]) -> List[Any]: ... + def _get_all_options(self) -> list[Option]: ... + def _get_args(self, args: Iterable[Any]) -> list[Any]: ... def _init_parsing_state(self) -> None: ... def _match_long_opt(self, opt: _Text) -> _Text: ... def _populate_option_list(self, option_list: Iterable[Option], add_help: bool = ...) -> None: ... - def _process_args(self, largs: List[Any], rargs: List[Any], values: Values) -> None: ... - def _process_long_opt(self, rargs: List[Any], values: Any) -> None: ... - def _process_short_opts(self, rargs: List[Any], values: Any) -> None: ... + def _process_args(self, largs: list[Any], rargs: list[Any], values: Values) -> None: ... + def _process_long_opt(self, rargs: list[Any], values: Any) -> None: ... + def _process_short_opts(self, rargs: list[Any], values: Any) -> None: ... @overload def add_option_group(self, __opt_group: OptionGroup) -> OptionGroup: ... @overload def add_option_group(self, *args: Any, **kwargs: Any) -> OptionGroup: ... - def check_values(self, values: Values, args: List[_Text]) -> Tuple[Values, List[_Text]]: ... + def check_values(self, values: Values, args: list[_Text]) -> tuple[Values, list[_Text]]: ... def disable_interspersed_args(self) -> None: ... def enable_interspersed_args(self) -> None: ... def error(self, msg: _Text) -> None: ... @@ -219,7 +219,7 @@ class OptionParser(OptionContainer): def get_prog_name(self) -> _Text: ... def get_usage(self) -> _Text: ... def get_version(self) -> _Text: ... - def parse_args(self, args: Sequence[AnyStr] | None = ..., values: Values | None = ...) -> Tuple[Values, List[AnyStr]]: ... + def parse_args(self, args: Sequence[AnyStr] | None = ..., values: Values | None = ...) -> tuple[Values, list[AnyStr]]: ... def print_usage(self, file: IO[str] | None = ...) -> None: ... def print_help(self, file: IO[str] | None = ...) -> None: ... def print_version(self, file: IO[str] | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/os/__init__.pyi b/mypy/typeshed/stdlib/@python2/os/__init__.pyi index 1955c07020de3..c2e806ff0fb6a 100644 --- a/mypy/typeshed/stdlib/@python2/os/__init__.pyi +++ b/mypy/typeshed/stdlib/@python2/os/__init__.pyi @@ -7,19 +7,15 @@ from typing import ( Any, AnyStr, Callable, - Dict, Generic, Iterator, - List, Mapping, MutableMapping, NamedTuple, NoReturn, Sequence, Text, - Tuple, TypeVar, - Union, overload, ) @@ -90,7 +86,7 @@ W_OK: int X_OK: int class _Environ(MutableMapping[AnyStr, AnyStr], Generic[AnyStr]): - def copy(self) -> Dict[AnyStr, AnyStr]: ... + def copy(self) -> dict[AnyStr, AnyStr]: ... def __delitem__(self, key: AnyStr) -> None: ... def __getitem__(self, key: AnyStr) -> AnyStr: ... def __setitem__(self, key: AnyStr, value: AnyStr) -> None: ... @@ -100,9 +96,9 @@ class _Environ(MutableMapping[AnyStr, AnyStr], Generic[AnyStr]): environ: _Environ[str] if sys.platform != "win32": # Unix only - confstr_names: Dict[str, int] - pathconf_names: Dict[str, int] - sysconf_names: Dict[str, int] + confstr_names: dict[str, int] + pathconf_names: dict[str, int] + sysconf_names: dict[str, int] EX_OK: int EX_USAGE: int @@ -161,12 +157,12 @@ if sys.platform != "win32": def getegid() -> int: ... def geteuid() -> int: ... def getgid() -> int: ... - def getgroups() -> List[int]: ... # Unix only, behaves differently on Mac + def getgroups() -> list[int]: ... # Unix only, behaves differently on Mac def initgroups(username: str, gid: int) -> None: ... def getpgid(pid: int) -> int: ... def getpgrp() -> int: ... - def getresuid() -> Tuple[int, int, int]: ... - def getresgid() -> Tuple[int, int, int]: ... + def getresuid() -> tuple[int, int, int]: ... + def getresgid() -> tuple[int, int, int]: ... def getuid() -> int: ... def setegid(egid: int) -> None: ... def seteuid(euid: int) -> None: ... @@ -181,7 +177,7 @@ if sys.platform != "win32": def getsid(pid: int) -> int: ... def setsid() -> None: ... def setuid(uid: int) -> None: ... - def uname() -> Tuple[str, str, str, str, str]: ... + def uname() -> tuple[str, str, str, str, str]: ... @overload def getenv(key: Text) -> str | None: ... @@ -198,7 +194,7 @@ def fstat(fd: int) -> Any: ... def fsync(fd: FileDescriptorLike) -> None: ... def lseek(fd: int, pos: int, how: int) -> int: ... def open(file: Text, flags: int, mode: int = ...) -> int: ... -def pipe() -> Tuple[int, int]: ... +def pipe() -> tuple[int, int]: ... def read(fd: int, n: int) -> bytes: ... def write(fd: int, string: bytes | buffer) -> int: ... def access(path: Text, mode: int) -> bool: ... @@ -230,7 +226,7 @@ def symlink(source: Text, link_name: Text) -> None: ... def unlink(path: Text) -> None: ... # TODO: add ns, dir_fd, follow_symlinks argument -def utime(path: Text, times: Tuple[float, float] | None) -> None: ... +def utime(path: Text, times: tuple[float, float] | None) -> None: ... if sys.platform != "win32": # Unix only @@ -238,11 +234,12 @@ if sys.platform != "win32": def fchown(fd: int, uid: int, gid: int) -> None: ... if sys.platform != "darwin": def fdatasync(fd: FileDescriptorLike) -> None: ... # Unix only, not Mac + def fpathconf(fd: int, name: str | int) -> int: ... def fstatvfs(fd: int) -> _StatVFS: ... def ftruncate(fd: int, length: int) -> None: ... def isatty(fd: int) -> bool: ... - def openpty() -> Tuple[int, int]: ... # some flavors of Unix + def openpty() -> tuple[int, int]: ... # some flavors of Unix def tcgetpgrp(fd: int) -> int: ... def tcsetpgrp(fd: int, pg: int) -> None: ... def ttyname(fd: int) -> str: ... @@ -258,7 +255,7 @@ if sys.platform != "win32": def walk( top: AnyStr, topdown: bool = ..., onerror: Callable[[OSError], Any] | None = ..., followlinks: bool = ... -) -> Iterator[Tuple[AnyStr, List[AnyStr], List[AnyStr]]]: ... +) -> Iterator[tuple[AnyStr, list[AnyStr], list[AnyStr]]]: ... def abort() -> NoReturn: ... # These are defined as execl(file, *args) but the first *arg is mandatory. @@ -271,7 +268,7 @@ def execlpe(file: Text, __arg0: bytes | Text, *args: Any) -> NoReturn: ... # The docs say `args: tuple or list of strings` # The implementation enforces tuple or list so we can't use Sequence. -_ExecVArgs = Union[Tuple[Union[bytes, Text], ...], List[bytes], List[Text], List[Union[bytes, Text]]] +_ExecVArgs = tuple[bytes | Text, ...] | list[bytes] | list[Text] | list[bytes | Text] def execv(path: Text, args: _ExecVArgs) -> NoReturn: ... def execve(path: Text, args: _ExecVArgs, env: Mapping[str, str]) -> NoReturn: ... @@ -283,22 +280,22 @@ def kill(pid: int, sig: int) -> None: ... if sys.platform != "win32": # Unix only def fork() -> int: ... - def forkpty() -> Tuple[int, int]: ... # some flavors of Unix + def forkpty() -> tuple[int, int]: ... # some flavors of Unix def killpg(__pgid: int, __signal: int) -> None: ... def nice(increment: int) -> int: ... def plock(op: int) -> None: ... # ???op is int? def popen(command: str, *args, **kwargs) -> IO[Any]: ... -def popen2(cmd: str, *args, **kwargs) -> Tuple[IO[Any], IO[Any]]: ... -def popen3(cmd: str, *args, **kwargs) -> Tuple[IO[Any], IO[Any], IO[Any]]: ... -def popen4(cmd: str, *args, **kwargs) -> Tuple[IO[Any], IO[Any]]: ... +def popen2(cmd: str, *args, **kwargs) -> tuple[IO[Any], IO[Any]]: ... +def popen3(cmd: str, *args, **kwargs) -> tuple[IO[Any], IO[Any], IO[Any]]: ... +def popen4(cmd: str, *args, **kwargs) -> tuple[IO[Any], IO[Any]]: ... def spawnl(mode: int, path: Text, arg0: bytes | Text, *args: bytes | Text) -> int: ... def spawnle(mode: int, path: Text, arg0: bytes | Text, *args: Any) -> int: ... # Imprecise sig -def spawnv(mode: int, path: Text, args: List[bytes | Text]) -> int: ... -def spawnve(mode: int, path: Text, args: List[bytes | Text], env: Mapping[str, str]) -> int: ... +def spawnv(mode: int, path: Text, args: list[bytes | Text]) -> int: ... +def spawnve(mode: int, path: Text, args: list[bytes | Text], env: Mapping[str, str]) -> int: ... def system(command: Text) -> int: ... -def times() -> Tuple[float, float, float, float, float]: ... -def waitpid(pid: int, options: int) -> Tuple[int, int]: ... +def times() -> tuple[float, float, float, float, float]: ... +def waitpid(pid: int, options: int) -> tuple[int, int]: ... def urandom(n: int) -> bytes: ... if sys.platform == "win32": @@ -308,11 +305,11 @@ else: # Unix only def spawnlp(mode: int, file: Text, arg0: bytes | Text, *args: bytes | Text) -> int: ... def spawnlpe(mode: int, file: Text, arg0: bytes | Text, *args: Any) -> int: ... # Imprecise signature - def spawnvp(mode: int, file: Text, args: List[bytes | Text]) -> int: ... - def spawnvpe(mode: int, file: Text, args: List[bytes | Text], env: Mapping[str, str]) -> int: ... - def wait() -> Tuple[int, int]: ... - def wait3(options: int) -> Tuple[int, int, Any]: ... - def wait4(pid: int, options: int) -> Tuple[int, int, Any]: ... + def spawnvp(mode: int, file: Text, args: list[bytes | Text]) -> int: ... + def spawnvpe(mode: int, file: Text, args: list[bytes | Text], env: Mapping[str, str]) -> int: ... + def wait() -> tuple[int, int]: ... + def wait3(options: int) -> tuple[int, int, Any]: ... + def wait4(pid: int, options: int) -> tuple[int, int, Any]: ... def WCOREDUMP(status: int) -> bool: ... def WIFCONTINUED(status: int) -> bool: ... def WIFSTOPPED(status: int) -> bool: ... @@ -322,7 +319,7 @@ else: def WSTOPSIG(status: int) -> int: ... def WTERMSIG(status: int) -> int: ... def confstr(name: str | int) -> str | None: ... - def getloadavg() -> Tuple[float, float, float]: ... + def getloadavg() -> tuple[float, float, float]: ... def sysconf(name: str | int) -> int: ... def tmpfile() -> IO[Any]: ... diff --git a/mypy/typeshed/stdlib/@python2/os/path.pyi b/mypy/typeshed/stdlib/@python2/os/path.pyi index 2ce2f592f0e29..4e484ce8a0969 100644 --- a/mypy/typeshed/stdlib/@python2/os/path.pyi +++ b/mypy/typeshed/stdlib/@python2/os/path.pyi @@ -1,6 +1,6 @@ import os import sys -from typing import Any, AnyStr, Callable, List, Sequence, Text, Tuple, TypeVar, overload +from typing import Any, AnyStr, Callable, Sequence, Text, TypeVar, overload _T = TypeVar("_T") @@ -74,11 +74,11 @@ def relpath(path: Text, start: Text | None = ...) -> Text: ... def samefile(f1: Text, f2: Text) -> bool: ... def sameopenfile(fp1: int, fp2: int) -> bool: ... def samestat(s1: os.stat_result, s2: os.stat_result) -> bool: ... -def split(p: AnyStr) -> Tuple[AnyStr, AnyStr]: ... -def splitdrive(p: AnyStr) -> Tuple[AnyStr, AnyStr]: ... -def splitext(p: AnyStr) -> Tuple[AnyStr, AnyStr]: ... +def split(p: AnyStr) -> tuple[AnyStr, AnyStr]: ... +def splitdrive(p: AnyStr) -> tuple[AnyStr, AnyStr]: ... +def splitext(p: AnyStr) -> tuple[AnyStr, AnyStr]: ... if sys.platform == "win32": - def splitunc(p: AnyStr) -> Tuple[AnyStr, AnyStr]: ... # deprecated + def splitunc(p: AnyStr) -> tuple[AnyStr, AnyStr]: ... # deprecated -def walk(path: AnyStr, visit: Callable[[_T, AnyStr, List[AnyStr]], Any], arg: _T) -> None: ... +def walk(path: AnyStr, visit: Callable[[_T, AnyStr, list[AnyStr]], Any], arg: _T) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/os2emxpath.pyi b/mypy/typeshed/stdlib/@python2/os2emxpath.pyi index 514db760886f1..33732903cb4cf 100644 --- a/mypy/typeshed/stdlib/@python2/os2emxpath.pyi +++ b/mypy/typeshed/stdlib/@python2/os2emxpath.pyi @@ -1,7 +1,7 @@ import os import sys from genericpath import exists as exists -from typing import Any, AnyStr, Callable, List, Sequence, Text, Tuple, TypeVar, overload +from typing import Any, AnyStr, Callable, Sequence, Text, TypeVar, overload _T = TypeVar("_T") @@ -74,11 +74,11 @@ def relpath(path: Text, start: Text | None = ...) -> Text: ... def samefile(f1: Text, f2: Text) -> bool: ... def sameopenfile(fp1: int, fp2: int) -> bool: ... def samestat(s1: os.stat_result, s2: os.stat_result) -> bool: ... -def split(p: AnyStr) -> Tuple[AnyStr, AnyStr]: ... -def splitdrive(p: AnyStr) -> Tuple[AnyStr, AnyStr]: ... -def splitext(p: AnyStr) -> Tuple[AnyStr, AnyStr]: ... +def split(p: AnyStr) -> tuple[AnyStr, AnyStr]: ... +def splitdrive(p: AnyStr) -> tuple[AnyStr, AnyStr]: ... +def splitext(p: AnyStr) -> tuple[AnyStr, AnyStr]: ... if sys.platform == "win32": - def splitunc(p: AnyStr) -> Tuple[AnyStr, AnyStr]: ... # deprecated + def splitunc(p: AnyStr) -> tuple[AnyStr, AnyStr]: ... # deprecated -def walk(path: AnyStr, visit: Callable[[_T, AnyStr, List[AnyStr]], Any], arg: _T) -> None: ... +def walk(path: AnyStr, visit: Callable[[_T, AnyStr, list[AnyStr]], Any], arg: _T) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/ossaudiodev.pyi b/mypy/typeshed/stdlib/@python2/ossaudiodev.pyi index af3e2c210930b..d956a89729fd1 100644 --- a/mypy/typeshed/stdlib/@python2/ossaudiodev.pyi +++ b/mypy/typeshed/stdlib/@python2/ossaudiodev.pyi @@ -1,131 +1,132 @@ -from typing import Any, List, overload +import sys +from typing import Any, overload from typing_extensions import Literal -AFMT_AC3: int -AFMT_A_LAW: int -AFMT_IMA_ADPCM: int -AFMT_MPEG: int -AFMT_MU_LAW: int -AFMT_QUERY: int -AFMT_S16_BE: int -AFMT_S16_LE: int -AFMT_S16_NE: int -AFMT_S8: int -AFMT_U16_BE: int -AFMT_U16_LE: int -AFMT_U8: int -SNDCTL_COPR_HALT: int -SNDCTL_COPR_LOAD: int -SNDCTL_COPR_RCODE: int -SNDCTL_COPR_RCVMSG: int -SNDCTL_COPR_RDATA: int -SNDCTL_COPR_RESET: int -SNDCTL_COPR_RUN: int -SNDCTL_COPR_SENDMSG: int -SNDCTL_COPR_WCODE: int -SNDCTL_COPR_WDATA: int -SNDCTL_DSP_BIND_CHANNEL: int -SNDCTL_DSP_CHANNELS: int -SNDCTL_DSP_GETBLKSIZE: int -SNDCTL_DSP_GETCAPS: int -SNDCTL_DSP_GETCHANNELMASK: int -SNDCTL_DSP_GETFMTS: int -SNDCTL_DSP_GETIPTR: int -SNDCTL_DSP_GETISPACE: int -SNDCTL_DSP_GETODELAY: int -SNDCTL_DSP_GETOPTR: int -SNDCTL_DSP_GETOSPACE: int -SNDCTL_DSP_GETSPDIF: int -SNDCTL_DSP_GETTRIGGER: int -SNDCTL_DSP_MAPINBUF: int -SNDCTL_DSP_MAPOUTBUF: int -SNDCTL_DSP_NONBLOCK: int -SNDCTL_DSP_POST: int -SNDCTL_DSP_PROFILE: int -SNDCTL_DSP_RESET: int -SNDCTL_DSP_SAMPLESIZE: int -SNDCTL_DSP_SETDUPLEX: int -SNDCTL_DSP_SETFMT: int -SNDCTL_DSP_SETFRAGMENT: int -SNDCTL_DSP_SETSPDIF: int -SNDCTL_DSP_SETSYNCRO: int -SNDCTL_DSP_SETTRIGGER: int -SNDCTL_DSP_SPEED: int -SNDCTL_DSP_STEREO: int -SNDCTL_DSP_SUBDIVIDE: int -SNDCTL_DSP_SYNC: int -SNDCTL_FM_4OP_ENABLE: int -SNDCTL_FM_LOAD_INSTR: int -SNDCTL_MIDI_INFO: int -SNDCTL_MIDI_MPUCMD: int -SNDCTL_MIDI_MPUMODE: int -SNDCTL_MIDI_PRETIME: int -SNDCTL_SEQ_CTRLRATE: int -SNDCTL_SEQ_GETINCOUNT: int -SNDCTL_SEQ_GETOUTCOUNT: int -SNDCTL_SEQ_GETTIME: int -SNDCTL_SEQ_NRMIDIS: int -SNDCTL_SEQ_NRSYNTHS: int -SNDCTL_SEQ_OUTOFBAND: int -SNDCTL_SEQ_PANIC: int -SNDCTL_SEQ_PERCMODE: int -SNDCTL_SEQ_RESET: int -SNDCTL_SEQ_RESETSAMPLES: int -SNDCTL_SEQ_SYNC: int -SNDCTL_SEQ_TESTMIDI: int -SNDCTL_SEQ_THRESHOLD: int -SNDCTL_SYNTH_CONTROL: int -SNDCTL_SYNTH_ID: int -SNDCTL_SYNTH_INFO: int -SNDCTL_SYNTH_MEMAVL: int -SNDCTL_SYNTH_REMOVESAMPLE: int -SNDCTL_TMR_CONTINUE: int -SNDCTL_TMR_METRONOME: int -SNDCTL_TMR_SELECT: int -SNDCTL_TMR_SOURCE: int -SNDCTL_TMR_START: int -SNDCTL_TMR_STOP: int -SNDCTL_TMR_TEMPO: int -SNDCTL_TMR_TIMEBASE: int -SOUND_MIXER_ALTPCM: int -SOUND_MIXER_BASS: int -SOUND_MIXER_CD: int -SOUND_MIXER_DIGITAL1: int -SOUND_MIXER_DIGITAL2: int -SOUND_MIXER_DIGITAL3: int -SOUND_MIXER_IGAIN: int -SOUND_MIXER_IMIX: int -SOUND_MIXER_LINE: int -SOUND_MIXER_LINE1: int -SOUND_MIXER_LINE2: int -SOUND_MIXER_LINE3: int -SOUND_MIXER_MIC: int -SOUND_MIXER_MONITOR: int -SOUND_MIXER_NRDEVICES: int -SOUND_MIXER_OGAIN: int -SOUND_MIXER_PCM: int -SOUND_MIXER_PHONEIN: int -SOUND_MIXER_PHONEOUT: int -SOUND_MIXER_RADIO: int -SOUND_MIXER_RECLEV: int -SOUND_MIXER_SPEAKER: int -SOUND_MIXER_SYNTH: int -SOUND_MIXER_TREBLE: int -SOUND_MIXER_VIDEO: int -SOUND_MIXER_VOLUME: int +if sys.platform != "win32" and sys.platform != "darwin": + AFMT_AC3: int + AFMT_A_LAW: int + AFMT_IMA_ADPCM: int + AFMT_MPEG: int + AFMT_MU_LAW: int + AFMT_QUERY: int + AFMT_S16_BE: int + AFMT_S16_LE: int + AFMT_S16_NE: int + AFMT_S8: int + AFMT_U16_BE: int + AFMT_U16_LE: int + AFMT_U8: int + SNDCTL_COPR_HALT: int + SNDCTL_COPR_LOAD: int + SNDCTL_COPR_RCODE: int + SNDCTL_COPR_RCVMSG: int + SNDCTL_COPR_RDATA: int + SNDCTL_COPR_RESET: int + SNDCTL_COPR_RUN: int + SNDCTL_COPR_SENDMSG: int + SNDCTL_COPR_WCODE: int + SNDCTL_COPR_WDATA: int + SNDCTL_DSP_BIND_CHANNEL: int + SNDCTL_DSP_CHANNELS: int + SNDCTL_DSP_GETBLKSIZE: int + SNDCTL_DSP_GETCAPS: int + SNDCTL_DSP_GETCHANNELMASK: int + SNDCTL_DSP_GETFMTS: int + SNDCTL_DSP_GETIPTR: int + SNDCTL_DSP_GETISPACE: int + SNDCTL_DSP_GETODELAY: int + SNDCTL_DSP_GETOPTR: int + SNDCTL_DSP_GETOSPACE: int + SNDCTL_DSP_GETSPDIF: int + SNDCTL_DSP_GETTRIGGER: int + SNDCTL_DSP_MAPINBUF: int + SNDCTL_DSP_MAPOUTBUF: int + SNDCTL_DSP_NONBLOCK: int + SNDCTL_DSP_POST: int + SNDCTL_DSP_PROFILE: int + SNDCTL_DSP_RESET: int + SNDCTL_DSP_SAMPLESIZE: int + SNDCTL_DSP_SETDUPLEX: int + SNDCTL_DSP_SETFMT: int + SNDCTL_DSP_SETFRAGMENT: int + SNDCTL_DSP_SETSPDIF: int + SNDCTL_DSP_SETSYNCRO: int + SNDCTL_DSP_SETTRIGGER: int + SNDCTL_DSP_SPEED: int + SNDCTL_DSP_STEREO: int + SNDCTL_DSP_SUBDIVIDE: int + SNDCTL_DSP_SYNC: int + SNDCTL_FM_4OP_ENABLE: int + SNDCTL_FM_LOAD_INSTR: int + SNDCTL_MIDI_INFO: int + SNDCTL_MIDI_MPUCMD: int + SNDCTL_MIDI_MPUMODE: int + SNDCTL_MIDI_PRETIME: int + SNDCTL_SEQ_CTRLRATE: int + SNDCTL_SEQ_GETINCOUNT: int + SNDCTL_SEQ_GETOUTCOUNT: int + SNDCTL_SEQ_GETTIME: int + SNDCTL_SEQ_NRMIDIS: int + SNDCTL_SEQ_NRSYNTHS: int + SNDCTL_SEQ_OUTOFBAND: int + SNDCTL_SEQ_PANIC: int + SNDCTL_SEQ_PERCMODE: int + SNDCTL_SEQ_RESET: int + SNDCTL_SEQ_RESETSAMPLES: int + SNDCTL_SEQ_SYNC: int + SNDCTL_SEQ_TESTMIDI: int + SNDCTL_SEQ_THRESHOLD: int + SNDCTL_SYNTH_CONTROL: int + SNDCTL_SYNTH_ID: int + SNDCTL_SYNTH_INFO: int + SNDCTL_SYNTH_MEMAVL: int + SNDCTL_SYNTH_REMOVESAMPLE: int + SNDCTL_TMR_CONTINUE: int + SNDCTL_TMR_METRONOME: int + SNDCTL_TMR_SELECT: int + SNDCTL_TMR_SOURCE: int + SNDCTL_TMR_START: int + SNDCTL_TMR_STOP: int + SNDCTL_TMR_TEMPO: int + SNDCTL_TMR_TIMEBASE: int + SOUND_MIXER_ALTPCM: int + SOUND_MIXER_BASS: int + SOUND_MIXER_CD: int + SOUND_MIXER_DIGITAL1: int + SOUND_MIXER_DIGITAL2: int + SOUND_MIXER_DIGITAL3: int + SOUND_MIXER_IGAIN: int + SOUND_MIXER_IMIX: int + SOUND_MIXER_LINE: int + SOUND_MIXER_LINE1: int + SOUND_MIXER_LINE2: int + SOUND_MIXER_LINE3: int + SOUND_MIXER_MIC: int + SOUND_MIXER_MONITOR: int + SOUND_MIXER_NRDEVICES: int + SOUND_MIXER_OGAIN: int + SOUND_MIXER_PCM: int + SOUND_MIXER_PHONEIN: int + SOUND_MIXER_PHONEOUT: int + SOUND_MIXER_RADIO: int + SOUND_MIXER_RECLEV: int + SOUND_MIXER_SPEAKER: int + SOUND_MIXER_SYNTH: int + SOUND_MIXER_TREBLE: int + SOUND_MIXER_VIDEO: int + SOUND_MIXER_VOLUME: int -control_labels: List[str] -control_names: List[str] + control_labels: list[str] + control_names: list[str] -# TODO: oss_audio_device return type -@overload -def open(mode: Literal["r", "w", "rw"]) -> Any: ... -@overload -def open(device: str, mode: Literal["r", "w", "rw"]) -> Any: ... + # TODO: oss_audio_device return type + @overload + def open(mode: Literal["r", "w", "rw"]) -> Any: ... + @overload + def open(device: str, mode: Literal["r", "w", "rw"]) -> Any: ... -# TODO: oss_mixer_device return type -def openmixer(device: str = ...) -> Any: ... + # TODO: oss_mixer_device return type + def openmixer(device: str = ...) -> Any: ... -class OSSAudioError(Exception): ... - -error = OSSAudioError + class OSSAudioError(Exception): ... + error = OSSAudioError diff --git a/mypy/typeshed/stdlib/@python2/parser.pyi b/mypy/typeshed/stdlib/@python2/parser.pyi index ff8bf039ee800..de88bc0ba056a 100644 --- a/mypy/typeshed/stdlib/@python2/parser.pyi +++ b/mypy/typeshed/stdlib/@python2/parser.pyi @@ -1,12 +1,12 @@ from types import CodeType -from typing import Any, List, Sequence, Text, Tuple +from typing import Any, Sequence, Text def expr(source: Text) -> STType: ... def suite(source: Text) -> STType: ... def sequence2st(sequence: Sequence[Any]) -> STType: ... def tuple2st(sequence: Sequence[Any]) -> STType: ... -def st2list(st: STType, line_info: bool = ..., col_info: bool = ...) -> List[Any]: ... -def st2tuple(st: STType, line_info: bool = ..., col_info: bool = ...) -> Tuple[Any]: ... +def st2list(st: STType, line_info: bool = ..., col_info: bool = ...) -> list[Any]: ... +def st2tuple(st: STType, line_info: bool = ..., col_info: bool = ...) -> tuple[Any, ...]: ... def compilest(st: STType, filename: Text = ...) -> CodeType: ... def isexpr(st: STType) -> bool: ... def issuite(st: STType) -> bool: ... @@ -17,5 +17,5 @@ class STType: def compile(self, filename: Text = ...) -> CodeType: ... def isexpr(self) -> bool: ... def issuite(self) -> bool: ... - def tolist(self, line_info: bool = ..., col_info: bool = ...) -> List[Any]: ... - def totuple(self, line_info: bool = ..., col_info: bool = ...) -> Tuple[Any]: ... + def tolist(self, line_info: bool = ..., col_info: bool = ...) -> list[Any]: ... + def totuple(self, line_info: bool = ..., col_info: bool = ...) -> tuple[Any, ...]: ... diff --git a/mypy/typeshed/stdlib/@python2/pdb.pyi b/mypy/typeshed/stdlib/@python2/pdb.pyi index 6d3a6d5c59037..4600b5818eb3c 100644 --- a/mypy/typeshed/stdlib/@python2/pdb.pyi +++ b/mypy/typeshed/stdlib/@python2/pdb.pyi @@ -1,18 +1,20 @@ from bdb import Bdb from cmd import Cmd from types import FrameType, TracebackType -from typing import IO, Any, Callable, ClassVar, Dict, Iterable, List, Mapping, Tuple, TypeVar +from typing import IO, Any, Callable, ClassVar, Iterable, Mapping, TypeVar +from typing_extensions import ParamSpec _T = TypeVar("_T") +_P = ParamSpec("_P") line_prefix: str # undocumented class Restart(Exception): ... -def run(statement: str, globals: Dict[str, Any] | None = ..., locals: Mapping[str, Any] | None = ...) -> None: ... -def runeval(expression: str, globals: Dict[str, Any] | None = ..., locals: Mapping[str, Any] | None = ...) -> Any: ... -def runctx(statement: str, globals: Dict[str, Any], locals: Mapping[str, Any]) -> None: ... -def runcall(func: Callable[..., _T], *args: Any, **kwds: Any) -> _T | None: ... +def run(statement: str, globals: dict[str, Any] | None = ..., locals: Mapping[str, Any] | None = ...) -> None: ... +def runeval(expression: str, globals: dict[str, Any] | None = ..., locals: Mapping[str, Any] | None = ...) -> Any: ... +def runctx(statement: str, globals: dict[str, Any], locals: Mapping[str, Any]) -> None: ... +def runcall(func: Callable[_P, _T], *args: _P.args, **kwds: _P.kwargs) -> _T | None: ... def set_trace() -> None: ... def post_mortem(t: TracebackType | None = ...) -> None: ... def pm() -> None: ... @@ -20,19 +22,19 @@ def pm() -> None: ... class Pdb(Bdb, Cmd): # Everything here is undocumented, except for __init__ - commands_resuming: ClassVar[List[str]] + commands_resuming: ClassVar[list[str]] - aliases: Dict[str, str] + aliases: dict[str, str] mainpyfile: str _wait_for_mainpyfile: bool - rcLines: List[str] - commands: Dict[int, List[str]] - commands_doprompt: Dict[int, bool] - commands_silent: Dict[int, bool] + rcLines: list[str] + commands: dict[int, list[str]] + commands_doprompt: dict[int, bool] + commands_silent: dict[int, bool] commands_defining: bool commands_bnum: int | None lineno: int | None - stack: List[Tuple[FrameType, int]] + stack: list[tuple[FrameType, int]] curindex: int curframe: FrameType | None curframe_locals: Mapping[str, Any] @@ -47,11 +49,11 @@ class Pdb(Bdb, Cmd): def displayhook(self, obj: object) -> None: ... def handle_command_def(self, line: str) -> bool: ... def defaultFile(self) -> str: ... - def lineinfo(self, identifier: str) -> Tuple[None, None, None] | Tuple[str, str, int]: ... + def lineinfo(self, identifier: str) -> tuple[None, None, None] | tuple[str, str, int]: ... def checkline(self, filename: str, lineno: int) -> int: ... def _getval(self, arg: str) -> object: ... def print_stack_trace(self) -> None: ... - def print_stack_entry(self, frame_lineno: Tuple[FrameType, int], prompt_prefix: str = ...) -> None: ... + def print_stack_entry(self, frame_lineno: tuple[FrameType, int], prompt_prefix: str = ...) -> None: ... def lookupmodule(self, filename: str) -> str | None: ... def _runscript(self, filename: str) -> None: ... def do_commands(self, arg: str) -> bool | None: ... @@ -157,7 +159,7 @@ class Pdb(Bdb, Cmd): # undocumented -def find_function(funcname: str, filename: str) -> Tuple[str, str, int] | None: ... +def find_function(funcname: str, filename: str) -> tuple[str, str, int] | None: ... def main() -> None: ... def help() -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/pickle.pyi b/mypy/typeshed/stdlib/@python2/pickle.pyi index 07e32e64b4495..c3052f5c31135 100644 --- a/mypy/typeshed/stdlib/@python2/pickle.pyi +++ b/mypy/typeshed/stdlib/@python2/pickle.pyi @@ -1,7 +1,7 @@ -from typing import IO, Any, Callable, Iterator, Optional, Tuple, Type, Union +from typing import IO, Any, Callable, Iterator, Union HIGHEST_PROTOCOL: int -bytes_types: Tuple[Type[Any], ...] # undocumented +bytes_types: tuple[type[Any], ...] # undocumented def dump(obj: Any, file: IO[bytes], protocol: int | None = ...) -> None: ... def dumps(obj: Any, protocol: int | None = ...) -> bytes: ... @@ -14,10 +14,10 @@ class UnpicklingError(PickleError): ... _reducedtype = Union[ str, - Tuple[Callable[..., Any], Tuple[Any, ...]], - Tuple[Callable[..., Any], Tuple[Any, ...], Any], - Tuple[Callable[..., Any], Tuple[Any, ...], Any, Optional[Iterator[Any]]], - Tuple[Callable[..., Any], Tuple[Any, ...], Any, Optional[Iterator[Any]], Optional[Iterator[Any]]], + tuple[Callable[..., Any], tuple[Any, ...]], + tuple[Callable[..., Any], tuple[Any, ...], Any], + tuple[Callable[..., Any], tuple[Any, ...], Any, Iterator[Any] | None], + tuple[Callable[..., Any], tuple[Any, ...], Any, Iterator[Any] | None, Iterator[Any] | None], ] class Pickler: diff --git a/mypy/typeshed/stdlib/@python2/pickletools.pyi b/mypy/typeshed/stdlib/@python2/pickletools.pyi index 14ec0fdff03a7..915b700dc8e53 100644 --- a/mypy/typeshed/stdlib/@python2/pickletools.pyi +++ b/mypy/typeshed/stdlib/@python2/pickletools.pyi @@ -1,4 +1,4 @@ -from typing import IO, Any, Callable, Iterator, List, MutableMapping, Text, Tuple, Type +from typing import IO, Any, Callable, Iterator, MutableMapping, Text _Reader = Callable[[IO[bytes]], Any] @@ -77,9 +77,9 @@ long4: ArgumentDescriptor class StackObject(object): name: str - obtype: Type[Any] | Tuple[Type[Any], ...] + obtype: type[Any] | tuple[type[Any], ...] doc: str - def __init__(self, name: str, obtype: Type[Any] | Tuple[Type[Any], ...], doc: str) -> None: ... + def __init__(self, name: str, obtype: type[Any] | tuple[type[Any], ...], doc: str) -> None: ... pyint: StackObject pylong: StackObject @@ -100,8 +100,8 @@ class OpcodeInfo(object): name: str code: str arg: ArgumentDescriptor | None - stack_before: List[StackObject] - stack_after: List[StackObject] + stack_before: list[StackObject] + stack_after: list[StackObject] proto: int doc: str def __init__( @@ -109,15 +109,15 @@ class OpcodeInfo(object): name: str, code: str, arg: ArgumentDescriptor | None, - stack_before: List[StackObject], - stack_after: List[StackObject], + stack_before: list[StackObject], + stack_after: list[StackObject], proto: int, doc: str, ) -> None: ... -opcodes: List[OpcodeInfo] +opcodes: list[OpcodeInfo] -def genops(pickle: bytes | IO[bytes]) -> Iterator[Tuple[OpcodeInfo, Any | None, int | None]]: ... +def genops(pickle: bytes | IO[bytes]) -> Iterator[tuple[OpcodeInfo, Any | None, int | None]]: ... def optimize(p: bytes | IO[bytes]) -> bytes: ... def dis( pickle: bytes | IO[bytes], out: IO[str] | None = ..., memo: MutableMapping[int, Any] | None = ..., indentlevel: int = ... diff --git a/mypy/typeshed/stdlib/@python2/pkgutil.pyi b/mypy/typeshed/stdlib/@python2/pkgutil.pyi index fd42af916cfe2..aa220bc3ae61a 100644 --- a/mypy/typeshed/stdlib/@python2/pkgutil.pyi +++ b/mypy/typeshed/stdlib/@python2/pkgutil.pyi @@ -1,19 +1,20 @@ from _typeshed import SupportsRead -from typing import IO, Any, Callable, Iterable, Iterator, List, Tuple, Union +from typing import IO, Any, Callable, Iterable, Iterator, TypeVar Loader = Any MetaPathFinder = Any PathEntryFinder = Any -_ModuleInfoLike = Tuple[Union[MetaPathFinder, PathEntryFinder], str, bool] +_PathT = TypeVar("_PathT", bound=Iterable[str]) +_ModuleInfoLike = tuple[MetaPathFinder | PathEntryFinder, str, bool] -def extend_path(path: List[str], name: str) -> List[str]: ... +def extend_path(path: _PathT, name: str) -> _PathT: ... class ImpImporter: def __init__(self, path: str | None = ...) -> None: ... class ImpLoader: - def __init__(self, fullname: str, file: IO[str], filename: str, etc: Tuple[str, str, int]) -> None: ... + def __init__(self, fullname: str, file: IO[str], filename: str, etc: tuple[str, str, int]) -> None: ... def find_loader(fullname: str) -> Loader | None: ... def get_importer(path_item: str) -> PathEntryFinder | None: ... diff --git a/mypy/typeshed/stdlib/@python2/platform.pyi b/mypy/typeshed/stdlib/@python2/platform.pyi index b984a2b2d3d5d..7d71ee943da15 100644 --- a/mypy/typeshed/stdlib/@python2/platform.pyi +++ b/mypy/typeshed/stdlib/@python2/platform.pyi @@ -1,4 +1,4 @@ -from typing import Any, Tuple +from typing import Any __copyright__: Any DEV_NULL: Any @@ -19,16 +19,16 @@ class _popen: __del__: Any def popen(cmd, mode=..., bufsize: Any | None = ...): ... -def win32_ver(release: str = ..., version: str = ..., csd: str = ..., ptype: str = ...) -> Tuple[str, str, str, str]: ... +def win32_ver(release: str = ..., version: str = ..., csd: str = ..., ptype: str = ...) -> tuple[str, str, str, str]: ... def mac_ver( - release: str = ..., versioninfo: Tuple[str, str, str] = ..., machine: str = ... -) -> Tuple[str, Tuple[str, str, str], str]: ... + release: str = ..., versioninfo: tuple[str, str, str] = ..., machine: str = ... +) -> tuple[str, tuple[str, str, str], str]: ... def java_ver( - release: str = ..., vendor: str = ..., vminfo: Tuple[str, str, str] = ..., osinfo: Tuple[str, str, str] = ... -) -> Tuple[str, str, Tuple[str, str, str], Tuple[str, str, str]]: ... + release: str = ..., vendor: str = ..., vminfo: tuple[str, str, str] = ..., osinfo: tuple[str, str, str] = ... +) -> tuple[str, str, tuple[str, str, str], tuple[str, str, str]]: ... def system_alias(system, release, version): ... -def architecture(executable=..., bits=..., linkage=...) -> Tuple[str, str]: ... -def uname() -> Tuple[str, str, str, str, str, str]: ... +def architecture(executable=..., bits=..., linkage=...) -> tuple[str, str]: ... +def uname() -> tuple[str, str, str, str, str, str]: ... def system() -> str: ... def node() -> str: ... def release() -> str: ... @@ -37,9 +37,9 @@ def machine() -> str: ... def processor() -> str: ... def python_implementation() -> str: ... def python_version() -> str: ... -def python_version_tuple() -> Tuple[str, str, str]: ... +def python_version_tuple() -> tuple[str, str, str]: ... def python_branch() -> str: ... def python_revision() -> str: ... -def python_build() -> Tuple[str, str]: ... +def python_build() -> tuple[str, str]: ... def python_compiler() -> str: ... def platform(aliased: int = ..., terse: int = ...) -> str: ... diff --git a/mypy/typeshed/stdlib/@python2/plistlib.pyi b/mypy/typeshed/stdlib/@python2/plistlib.pyi index d815e3c35404d..488757b4c81ea 100644 --- a/mypy/typeshed/stdlib/@python2/plistlib.pyi +++ b/mypy/typeshed/stdlib/@python2/plistlib.pyi @@ -1,6 +1,6 @@ -from typing import IO, Any, Dict as DictT, Mapping, Text, Union +from typing import IO, Any, Mapping, Text -_Path = Union[str, Text] +_Path = str | Text def readPlist(pathOrFile: _Path | IO[bytes]) -> Any: ... def writePlist(value: Mapping[str, Any], pathOrFile: _Path | IO[bytes]) -> None: ... @@ -11,7 +11,7 @@ def writePlistToResource(rootObject: Mapping[str, Any], path: _Path, restype: st def readPlistFromString(data: str) -> Any: ... def writePlistToString(rootObject: Mapping[str, Any]) -> str: ... -class Dict(DictT[str, Any]): +class Dict(dict[str, Any]): def __getattr__(self, attr: str) -> Any: ... def __setattr__(self, attr: str, value: Any) -> None: ... def __delattr__(self, attr: str) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/popen2.pyi b/mypy/typeshed/stdlib/@python2/popen2.pyi index 0efee4e6d271c..43f6804e06594 100644 --- a/mypy/typeshed/stdlib/@python2/popen2.pyi +++ b/mypy/typeshed/stdlib/@python2/popen2.pyi @@ -1,4 +1,4 @@ -from typing import Any, Iterable, TextIO, Tuple, TypeVar +from typing import Any, Iterable, TextIO, TypeVar _T = TypeVar("_T") @@ -22,6 +22,6 @@ class Popen4(Popen3): fromchild: TextIO def __init__(self, cmd: Iterable[Any] = ..., bufsize: int = ...) -> None: ... -def popen2(cmd: Iterable[Any] = ..., bufsize: int = ..., mode: str = ...) -> Tuple[TextIO, TextIO]: ... -def popen3(cmd: Iterable[Any] = ..., bufsize: int = ..., mode: str = ...) -> Tuple[TextIO, TextIO, TextIO]: ... -def popen4(cmd: Iterable[Any] = ..., bufsize: int = ..., mode: str = ...) -> Tuple[TextIO, TextIO]: ... +def popen2(cmd: Iterable[Any] = ..., bufsize: int = ..., mode: str = ...) -> tuple[TextIO, TextIO]: ... +def popen3(cmd: Iterable[Any] = ..., bufsize: int = ..., mode: str = ...) -> tuple[TextIO, TextIO, TextIO]: ... +def popen4(cmd: Iterable[Any] = ..., bufsize: int = ..., mode: str = ...) -> tuple[TextIO, TextIO]: ... diff --git a/mypy/typeshed/stdlib/@python2/poplib.pyi b/mypy/typeshed/stdlib/@python2/poplib.pyi index 7a71f9850dfe3..4525cac1e687a 100644 --- a/mypy/typeshed/stdlib/@python2/poplib.pyi +++ b/mypy/typeshed/stdlib/@python2/poplib.pyi @@ -1,7 +1,7 @@ import socket -from typing import Any, BinaryIO, List, Pattern, Text, Tuple, overload +from typing import Any, BinaryIO, Pattern, Text, overload -_LongResp = Tuple[bytes, List[bytes], int] +_LongResp = tuple[bytes, list[bytes], int] class error_proto(Exception): ... @@ -22,7 +22,7 @@ class POP3: def set_debuglevel(self, level: int) -> None: ... def user(self, user: Text) -> bytes: ... def pass_(self, pswd: Text) -> bytes: ... - def stat(self) -> Tuple[int, int]: ... + def stat(self) -> tuple[int, int]: ... def list(self, which: Any | None = ...) -> _LongResp: ... def retr(self, which: Any) -> _LongResp: ... def dele(self, which: Any) -> bytes: ... diff --git a/mypy/typeshed/stdlib/@python2/posix.pyi b/mypy/typeshed/stdlib/@python2/posix.pyi index c39ce325289b4..7ea9c0015ab02 100644 --- a/mypy/typeshed/stdlib/@python2/posix.pyi +++ b/mypy/typeshed/stdlib/@python2/posix.pyi @@ -1,12 +1,12 @@ from _typeshed import FileDescriptorLike -from typing import IO, AnyStr, Dict, List, Mapping, NamedTuple, Sequence, Tuple, TypeVar +from typing import IO, AnyStr, Mapping, NamedTuple, Sequence, TypeVar error = OSError -confstr_names: Dict[str, int] -environ: Dict[str, str] -pathconf_names: Dict[str, int] -sysconf_names: Dict[str, int] +confstr_names: dict[str, int] +environ: dict[str, str] +pathconf_names: dict[str, int] +sysconf_names: dict[str, int] _T = TypeVar("_T") @@ -112,7 +112,7 @@ def fchown(fd: int, uid: int, gid: int) -> None: ... def fdatasync(fd: FileDescriptorLike) -> None: ... def fdopen(fd: int, mode: str = ..., bufsize: int = ...) -> IO[str]: ... def fork() -> int: ... -def forkpty() -> Tuple[int, int]: ... +def forkpty() -> tuple[int, int]: ... def fpathconf(fd: int, name: str) -> None: ... def fstat(fd: int) -> stat_result: ... def fstatvfs(fd: int) -> statvfs_result: ... @@ -123,15 +123,15 @@ def getcwdu() -> unicode: ... def getegid() -> int: ... def geteuid() -> int: ... def getgid() -> int: ... -def getgroups() -> List[int]: ... -def getloadavg() -> Tuple[float, float, float]: ... +def getgroups() -> list[int]: ... +def getloadavg() -> tuple[float, float, float]: ... def getlogin() -> str: ... def getpgid(pid: int) -> int: ... def getpgrp() -> int: ... def getpid() -> int: ... def getppid() -> int: ... -def getresgid() -> Tuple[int, int, int]: ... -def getresuid() -> Tuple[int, int, int]: ... +def getresgid() -> tuple[int, int, int]: ... +def getresuid() -> tuple[int, int, int]: ... def getsid(pid: int) -> int: ... def getuid() -> int: ... def initgroups(username: str, gid: int) -> None: ... @@ -140,7 +140,7 @@ def kill(pid: int, sig: int) -> None: ... def killpg(pgid: int, sig: int) -> None: ... def lchown(path: unicode, uid: int, gid: int) -> None: ... def link(source: unicode, link_name: str) -> None: ... -def listdir(path: AnyStr) -> List[AnyStr]: ... +def listdir(path: AnyStr) -> list[AnyStr]: ... def lseek(fd: int, pos: int, how: int) -> None: ... def lstat(path: unicode) -> stat_result: ... def major(device: int) -> int: ... @@ -151,9 +151,9 @@ def mkfifo(path: unicode, mode: int = ...) -> None: ... def mknod(filename: unicode, mode: int = ..., device: int = ...) -> None: ... def nice(increment: int) -> int: ... def open(file: unicode, flags: int, mode: int = ...) -> int: ... -def openpty() -> Tuple[int, int]: ... +def openpty() -> tuple[int, int]: ... def pathconf(path: unicode, name: str) -> str: ... -def pipe() -> Tuple[int, int]: ... +def pipe() -> tuple[int, int]: ... def popen(command: str, mode: str = ..., bufsize: int = ...) -> IO[str]: ... def putenv(varname: str, value: str) -> None: ... def read(fd: int, n: int) -> str: ... @@ -182,20 +182,20 @@ def sysconf(name: str | int) -> int: ... def system(command: unicode) -> int: ... def tcgetpgrp(fd: int) -> int: ... def tcsetpgrp(fd: int, pg: int) -> None: ... -def times() -> Tuple[float, float, float, float, float]: ... +def times() -> tuple[float, float, float, float, float]: ... def tmpfile() -> IO[str]: ... def ttyname(fd: int) -> str: ... def umask(mask: int) -> int: ... -def uname() -> Tuple[str, str, str, str, str]: ... +def uname() -> tuple[str, str, str, str, str]: ... def unlink(path: unicode) -> None: ... def unsetenv(varname: str) -> None: ... def urandom(n: int) -> str: ... -def utime(path: unicode, times: Tuple[int, int] | None) -> None: ... +def utime(path: unicode, times: tuple[int, int] | None) -> None: ... def wait() -> int: ... -_r = Tuple[float, float, int, int, int, int, int, int, int, int, int, int, int, int, int, int] +_r = tuple[float, float, int, int, int, int, int, int, int, int, int, int, int, int, int, int] -def wait3(options: int) -> Tuple[int, int, _r]: ... -def wait4(pid: int, options: int) -> Tuple[int, int, _r]: ... +def wait3(options: int) -> tuple[int, int, _r]: ... +def wait4(pid: int, options: int) -> tuple[int, int, _r]: ... def waitpid(pid: int, options: int) -> int: ... def write(fd: int, str: str) -> int: ... diff --git a/mypy/typeshed/stdlib/@python2/posixpath.pyi b/mypy/typeshed/stdlib/@python2/posixpath.pyi index 514db760886f1..33732903cb4cf 100644 --- a/mypy/typeshed/stdlib/@python2/posixpath.pyi +++ b/mypy/typeshed/stdlib/@python2/posixpath.pyi @@ -1,7 +1,7 @@ import os import sys from genericpath import exists as exists -from typing import Any, AnyStr, Callable, List, Sequence, Text, Tuple, TypeVar, overload +from typing import Any, AnyStr, Callable, Sequence, Text, TypeVar, overload _T = TypeVar("_T") @@ -74,11 +74,11 @@ def relpath(path: Text, start: Text | None = ...) -> Text: ... def samefile(f1: Text, f2: Text) -> bool: ... def sameopenfile(fp1: int, fp2: int) -> bool: ... def samestat(s1: os.stat_result, s2: os.stat_result) -> bool: ... -def split(p: AnyStr) -> Tuple[AnyStr, AnyStr]: ... -def splitdrive(p: AnyStr) -> Tuple[AnyStr, AnyStr]: ... -def splitext(p: AnyStr) -> Tuple[AnyStr, AnyStr]: ... +def split(p: AnyStr) -> tuple[AnyStr, AnyStr]: ... +def splitdrive(p: AnyStr) -> tuple[AnyStr, AnyStr]: ... +def splitext(p: AnyStr) -> tuple[AnyStr, AnyStr]: ... if sys.platform == "win32": - def splitunc(p: AnyStr) -> Tuple[AnyStr, AnyStr]: ... # deprecated + def splitunc(p: AnyStr) -> tuple[AnyStr, AnyStr]: ... # deprecated -def walk(path: AnyStr, visit: Callable[[_T, AnyStr, List[AnyStr]], Any], arg: _T) -> None: ... +def walk(path: AnyStr, visit: Callable[[_T, AnyStr, list[AnyStr]], Any], arg: _T) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/pprint.pyi b/mypy/typeshed/stdlib/@python2/pprint.pyi index 407a9afb8e477..e22c4464eb4d0 100644 --- a/mypy/typeshed/stdlib/@python2/pprint.pyi +++ b/mypy/typeshed/stdlib/@python2/pprint.pyi @@ -1,4 +1,4 @@ -from typing import IO, Any, Dict, Tuple +from typing import IO, Any def pformat(object: object, indent: int = ..., width: int = ..., depth: int | None = ...) -> str: ... def pprint( @@ -14,4 +14,4 @@ class PrettyPrinter: def pprint(self, object: object) -> None: ... def isreadable(self, object: object) -> bool: ... def isrecursive(self, object: object) -> bool: ... - def format(self, object: object, context: Dict[int, Any], maxlevels: int, level: int) -> Tuple[str, bool, bool]: ... + def format(self, object: object, context: dict[int, Any], maxlevels: int, level: int) -> tuple[str, bool, bool]: ... diff --git a/mypy/typeshed/stdlib/@python2/profile.pyi b/mypy/typeshed/stdlib/@python2/profile.pyi index 08e9b906dd0dd..d9884038e0e09 100644 --- a/mypy/typeshed/stdlib/@python2/profile.pyi +++ b/mypy/typeshed/stdlib/@python2/profile.pyi @@ -1,13 +1,15 @@ -from typing import Any, Callable, Dict, Text, Tuple, TypeVar +from _typeshed import Self +from typing import Any, Callable, Text, TypeVar +from typing_extensions import ParamSpec def run(statement: str, filename: str | None = ..., sort: str | int = ...) -> None: ... def runctx( - statement: str, globals: Dict[str, Any], locals: Dict[str, Any], filename: str | None = ..., sort: str | int = ... + statement: str, globals: dict[str, Any], locals: dict[str, Any], filename: str | None = ..., sort: str | int = ... ) -> None: ... -_SelfT = TypeVar("_SelfT", bound=Profile) _T = TypeVar("_T") -_Label = Tuple[str, int, str] +_P = ParamSpec("_P") +_Label = tuple[str, int, str] class Profile: bias: int @@ -20,7 +22,7 @@ class Profile: def dump_stats(self, file: Text) -> None: ... def create_stats(self) -> None: ... def snapshot_stats(self) -> None: ... - def run(self: _SelfT, cmd: str) -> _SelfT: ... - def runctx(self: _SelfT, cmd: str, globals: Dict[str, Any], locals: Dict[str, Any]) -> _SelfT: ... - def runcall(self, __func: Callable[..., _T], *args: Any, **kw: Any) -> _T: ... + def run(self: Self, cmd: str) -> Self: ... + def runctx(self: Self, cmd: str, globals: dict[str, Any], locals: dict[str, Any]) -> Self: ... + def runcall(self, __func: Callable[_P, _T], *args: _P.args, **kw: _P.kwargs) -> _T: ... def calibrate(self, m: int, verbose: int = ...) -> float: ... diff --git a/mypy/typeshed/stdlib/@python2/pstats.pyi b/mypy/typeshed/stdlib/@python2/pstats.pyi index cecd1e84e3053..6b956764efa99 100644 --- a/mypy/typeshed/stdlib/@python2/pstats.pyi +++ b/mypy/typeshed/stdlib/@python2/pstats.pyi @@ -1,12 +1,13 @@ +from _typeshed import Self from cProfile import Profile as _cProfile from profile import Profile -from typing import IO, Any, Dict, Iterable, List, Text, Tuple, TypeVar, Union, overload +from typing import IO, Any, Iterable, Text, TypeVar, overload -_Selector = Union[str, float, int] +_Selector = str | float | int _T = TypeVar("_T", bound=Stats) class Stats: - sort_arg_dict_default: Dict[str, Tuple[Any, str]] + sort_arg_dict_default: dict[str, tuple[Any, str]] def __init__( self: _T, __arg: None | str | Text | Profile | _cProfile = ..., @@ -16,22 +17,22 @@ class Stats: def init(self, arg: None | str | Text | Profile | _cProfile) -> None: ... def load_stats(self, arg: None | str | Text | Profile | _cProfile) -> None: ... def get_top_level_stats(self) -> None: ... - def add(self: _T, *arg_list: None | str | Text | Profile | _cProfile | _T) -> _T: ... + def add(self: Self, *arg_list: None | str | Text | Profile | _cProfile | Self) -> Self: ... def dump_stats(self, filename: Text) -> None: ... - def get_sort_arg_defs(self) -> Dict[str, Tuple[Tuple[Tuple[int, int], ...], str]]: ... + def get_sort_arg_defs(self) -> dict[str, tuple[tuple[tuple[int, int], ...], str]]: ... @overload - def sort_stats(self: _T, field: int) -> _T: ... + def sort_stats(self: Self, field: int) -> Self: ... @overload - def sort_stats(self: _T, *field: str) -> _T: ... - def reverse_order(self: _T) -> _T: ... - def strip_dirs(self: _T) -> _T: ... + def sort_stats(self: Self, *field: str) -> Self: ... + def reverse_order(self: Self) -> Self: ... + def strip_dirs(self: Self) -> Self: ... def calc_callees(self) -> None: ... - def eval_print_amount(self, sel: _Selector, list: List[str], msg: str) -> Tuple[List[str], str]: ... - def get_print_list(self, sel_list: Iterable[_Selector]) -> Tuple[int, List[str]]: ... - def print_stats(self: _T, *amount: _Selector) -> _T: ... - def print_callees(self: _T, *amount: _Selector) -> _T: ... - def print_callers(self: _T, *amount: _Selector) -> _T: ... + def eval_print_amount(self, sel: _Selector, list: list[str], msg: str) -> tuple[list[str], str]: ... + def get_print_list(self, sel_list: Iterable[_Selector]) -> tuple[int, list[str]]: ... + def print_stats(self: Self, *amount: _Selector) -> Self: ... + def print_callees(self: Self, *amount: _Selector) -> Self: ... + def print_callers(self: Self, *amount: _Selector) -> Self: ... def print_call_heading(self, name_size: int, column_title: str) -> None: ... - def print_call_line(self, name_size: int, source: str, call_dict: Dict[str, Any], arrow: str = ...) -> None: ... + def print_call_line(self, name_size: int, source: str, call_dict: dict[str, Any], arrow: str = ...) -> None: ... def print_title(self) -> None: ... def print_line(self, func: str) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/pty.pyi b/mypy/typeshed/stdlib/@python2/pty.pyi index d9d9fd98e41be..2c90faf18aa30 100644 --- a/mypy/typeshed/stdlib/@python2/pty.pyi +++ b/mypy/typeshed/stdlib/@python2/pty.pyi @@ -1,5 +1,5 @@ import sys -from typing import Callable, Iterable, Tuple +from typing import Callable, Iterable if sys.platform != "win32": _Reader = Callable[[int], bytes] @@ -9,8 +9,8 @@ if sys.platform != "win32": STDERR_FILENO: int CHILD: int - def openpty() -> Tuple[int, int]: ... - def master_open() -> Tuple[int, str]: ... + def openpty() -> tuple[int, int]: ... + def master_open() -> tuple[int, str]: ... def slave_open(tty_name: str) -> int: ... - def fork() -> Tuple[int, int]: ... + def fork() -> tuple[int, int]: ... def spawn(argv: str | Iterable[str], master_read: _Reader = ..., stdin_read: _Reader = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/pwd.pyi b/mypy/typeshed/stdlib/@python2/pwd.pyi index 583999fd84b7f..e64cbf6a1ac3b 100644 --- a/mypy/typeshed/stdlib/@python2/pwd.pyi +++ b/mypy/typeshed/stdlib/@python2/pwd.pyi @@ -1,8 +1,7 @@ import sys -from typing import List, Tuple if sys.platform != "win32": - class struct_passwd(Tuple[str, str, int, int, str, str, str]): + class struct_passwd(tuple[str, str, int, int, str, str, str]): pw_name: str pw_passwd: str pw_uid: int @@ -10,6 +9,6 @@ if sys.platform != "win32": pw_gecos: str pw_dir: str pw_shell: str - def getpwall() -> List[struct_passwd]: ... + def getpwall() -> list[struct_passwd]: ... def getpwuid(__uid: int) -> struct_passwd: ... def getpwnam(__name: str) -> struct_passwd: ... diff --git a/mypy/typeshed/stdlib/@python2/py_compile.pyi b/mypy/typeshed/stdlib/@python2/py_compile.pyi index 44905b43da33f..ccd05029fe0ec 100644 --- a/mypy/typeshed/stdlib/@python2/py_compile.pyi +++ b/mypy/typeshed/stdlib/@python2/py_compile.pyi @@ -1,13 +1,13 @@ -from typing import List, Text, Type, Union +from typing import Text -_EitherStr = Union[bytes, Text] +_EitherStr = bytes | Text class PyCompileError(Exception): exc_type_name: str exc_value: BaseException file: str msg: str - def __init__(self, exc_type: Type[BaseException], exc_value: BaseException, file: str, msg: str = ...) -> None: ... + def __init__(self, exc_type: type[BaseException], exc_value: BaseException, file: str, msg: str = ...) -> None: ... def compile(file: _EitherStr, cfile: _EitherStr | None = ..., dfile: _EitherStr | None = ..., doraise: bool = ...) -> None: ... -def main(args: List[Text] | None = ...) -> int: ... +def main(args: list[Text] | None = ...) -> int: ... diff --git a/mypy/typeshed/stdlib/@python2/pyclbr.pyi b/mypy/typeshed/stdlib/@python2/pyclbr.pyi index 893079901665e..317e934694c57 100644 --- a/mypy/typeshed/stdlib/@python2/pyclbr.pyi +++ b/mypy/typeshed/stdlib/@python2/pyclbr.pyi @@ -1,13 +1,13 @@ -from typing import Dict, List, Sequence +from typing import Sequence class Class: module: str name: str - super: List[Class | str] | None - methods: Dict[str, int] + super: list[Class | str] | None + methods: dict[str, int] file: int lineno: int - def __init__(self, module: str, name: str, super: List[Class | str] | None, file: str, lineno: int) -> None: ... + def __init__(self, module: str, name: str, super: list[Class | str] | None, file: str, lineno: int) -> None: ... class Function: module: str @@ -16,5 +16,5 @@ class Function: lineno: int def __init__(self, module: str, name: str, file: str, lineno: int) -> None: ... -def readmodule(module: str, path: Sequence[str] | None = ...) -> Dict[str, Class]: ... -def readmodule_ex(module: str, path: Sequence[str] | None = ...) -> Dict[str, Class | Function | List[str]]: ... +def readmodule(module: str, path: Sequence[str] | None = ...) -> dict[str, Class]: ... +def readmodule_ex(module: str, path: Sequence[str] | None = ...) -> dict[str, Class | Function | list[str]]: ... diff --git a/mypy/typeshed/stdlib/@python2/pydoc.pyi b/mypy/typeshed/stdlib/@python2/pydoc.pyi index dee0c4710b399..a43b7333c7b0d 100644 --- a/mypy/typeshed/stdlib/@python2/pydoc.pyi +++ b/mypy/typeshed/stdlib/@python2/pydoc.pyi @@ -1,35 +1,20 @@ from _typeshed import SupportsWrite from types import MethodType, ModuleType, TracebackType -from typing import ( - IO, - Any, - AnyStr, - Callable, - Container, - Dict, - List, - Mapping, - MutableMapping, - NoReturn, - Optional, - Text, - Tuple, - Type, -) +from typing import IO, Any, AnyStr, Callable, Container, Mapping, MutableMapping, NoReturn, Optional, Text from repr import Repr # the return type of sys.exc_info(), used by ErrorDuringImport.__init__ -_Exc_Info = Tuple[Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType]] +_Exc_Info = tuple[Optional[type[BaseException]], Optional[BaseException], Optional[TracebackType]] __author__: str __date__: str __version__: str __credits__: str -def pathdirs() -> List[str]: ... +def pathdirs() -> list[str]: ... def getdoc(object: object) -> Text: ... -def splitdoc(doc: AnyStr) -> Tuple[AnyStr, AnyStr]: ... +def splitdoc(doc: AnyStr) -> tuple[AnyStr, AnyStr]: ... def classname(object: object, modname: str) -> str: ... def isdata(object: object) -> bool: ... def replace(text: AnyStr, *pairs: AnyStr) -> AnyStr: ... @@ -37,14 +22,14 @@ def cram(text: str, maxlen: int) -> str: ... def stripid(text: str) -> str: ... def allmethods(cl: type) -> MutableMapping[str, MethodType]: ... def visiblename(name: str, all: Container[str] | None = ..., obj: object | None = ...) -> bool: ... -def classify_class_attrs(object: object) -> List[Tuple[str, str, type, str]]: ... +def classify_class_attrs(object: object) -> list[tuple[str, str, type, str]]: ... def ispackage(path: str) -> bool: ... def source_synopsis(file: IO[AnyStr]) -> AnyStr | None: ... -def synopsis(filename: str, cache: MutableMapping[str, Tuple[int, str]] = ...) -> str | None: ... +def synopsis(filename: str, cache: MutableMapping[str, tuple[int, str]] = ...) -> str | None: ... class ErrorDuringImport(Exception): filename: str - exc: Type[BaseException] | None + exc: type[BaseException] | None value: BaseException | None tb: TracebackType | None def __init__(self, filename: str, exc_info: _Exc_Info) -> None: ... @@ -97,12 +82,12 @@ class HTMLDoc(Doc): ) -> str: ... def bigsection(self, title: str, *args: Any) -> str: ... def preformat(self, text: str) -> str: ... - def multicolumn(self, list: List[Any], format: Callable[[Any], str], cols: int = ...) -> str: ... + def multicolumn(self, list: list[Any], format: Callable[[Any], str], cols: int = ...) -> str: ... def grey(self, text: str) -> str: ... def namelink(self, name: str, *dicts: MutableMapping[str, str]) -> str: ... def classlink(self, object: object, modname: str) -> str: ... def modulelink(self, object: object) -> str: ... - def modpkglink(self, modpkginfo: Tuple[str, str, bool, bool]) -> str: ... + def modpkglink(self, modpkginfo: tuple[str, str, bool, bool]) -> str: ... def markup( self, text: str, @@ -112,7 +97,7 @@ class HTMLDoc(Doc): methods: Mapping[str, str] = ..., ) -> str: ... def formattree( - self, tree: List[Tuple[type, Tuple[type, ...]] | List[Any]], modname: str, parent: type | None = ... + self, tree: list[tuple[type, tuple[type, ...]] | list[Any]], modname: str, parent: type | None = ... ) -> str: ... def docmodule(self, object: object, name: str | None = ..., mod: str | None = ..., *ignored: Any) -> str: ... def docclass( @@ -164,7 +149,7 @@ class TextDoc(Doc): def indent(self, text: str, prefix: str = ...) -> str: ... def section(self, title: str, contents: str) -> str: ... def formattree( - self, tree: List[Tuple[type, Tuple[type, ...]] | List[Any]], modname: str, parent: type | None = ..., prefix: str = ... + self, tree: list[tuple[type, tuple[type, ...]] | list[Any]], modname: str, parent: type | None = ..., prefix: str = ... ) -> str: ... def docmodule(self, object: object, name: str | None = ..., mod: Any | None = ..., *ignored: Any) -> str: ... def docclass(self, object: object, name: str | None = ..., mod: str | None = ..., *ignored: Any) -> str: ... @@ -204,16 +189,16 @@ html: HTMLDoc class _OldStyleClass: ... -def resolve(thing: str | object, forceload: bool = ...) -> Tuple[object, str] | None: ... +def resolve(thing: str | object, forceload: bool = ...) -> tuple[object, str] | None: ... def render_doc(thing: str | object, title: str = ..., forceload: bool = ..., renderer: Doc | None = ...) -> str: ... def doc(thing: str | object, title: str = ..., forceload: bool = ..., output: SupportsWrite[str] | None = ...) -> None: ... def writedoc(thing: str | object, forceload: bool = ...) -> None: ... def writedocs(dir: str, pkgpath: str = ..., done: Any | None = ...) -> None: ... class Helper: - keywords: Dict[str, str | Tuple[str, str]] - symbols: Dict[str, str] - topics: Dict[str, str | Tuple[str, ...]] + keywords: dict[str, str | tuple[str, str]] + symbols: dict[str, str] + topics: dict[str, str | tuple[str, ...]] def __init__(self, input: IO[str] | None = ..., output: IO[str] | None = ...) -> None: ... input: IO[str] output: IO[str] @@ -222,7 +207,7 @@ class Helper: def getline(self, prompt: str) -> str: ... def help(self, request: Any) -> None: ... def intro(self) -> None: ... - def list(self, items: List[str], columns: int = ..., width: int = ...) -> None: ... + def list(self, items: list[str], columns: int = ..., width: int = ...) -> None: ... def listkeywords(self) -> None: ... def listsymbols(self) -> None: ... def listtopics(self) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/pydoc_data/topics.pyi b/mypy/typeshed/stdlib/@python2/pydoc_data/topics.pyi index 1c48f4022fd62..091d34300106e 100644 --- a/mypy/typeshed/stdlib/@python2/pydoc_data/topics.pyi +++ b/mypy/typeshed/stdlib/@python2/pydoc_data/topics.pyi @@ -1,3 +1 @@ -from typing import Dict - -topics: Dict[str, str] +topics: dict[str, str] diff --git a/mypy/typeshed/stdlib/@python2/pyexpat/__init__.pyi b/mypy/typeshed/stdlib/@python2/pyexpat/__init__.pyi index bd73f850b5591..5c58a0a1fe73e 100644 --- a/mypy/typeshed/stdlib/@python2/pyexpat/__init__.pyi +++ b/mypy/typeshed/stdlib/@python2/pyexpat/__init__.pyi @@ -1,12 +1,12 @@ import pyexpat.errors as errors import pyexpat.model as model from _typeshed import SupportsRead -from typing import Any, Callable, Dict, List, Optional, Text, Tuple +from typing import Any, Callable, Text EXPAT_VERSION: str # undocumented -version_info: Tuple[int, int, int] # undocumented +version_info: tuple[int, int, int] # undocumented native_encoding: str # undocumented -features: List[Tuple[str, int]] # undocumented +features: list[tuple[str, int]] # undocumented class ExpatError(Exception): code: int @@ -19,7 +19,7 @@ XML_PARAM_ENTITY_PARSING_NEVER: int XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE: int XML_PARAM_ENTITY_PARSING_ALWAYS: int -_Model = Tuple[int, int, Optional[str], Tuple[Any, ...]] +_Model = tuple[int, int, str | None, tuple[Any, ...]] class XMLParserType(object): def Parse(self, __data: Text | bytes, __isfinal: bool = ...) -> int: ... @@ -48,8 +48,8 @@ class XMLParserType(object): EndDoctypeDeclHandler: Callable[[], Any] | None ElementDeclHandler: Callable[[str, _Model], Any] | None AttlistDeclHandler: Callable[[str, str, str, str | None, bool], Any] | None - StartElementHandler: Callable[[str, Dict[str, str]], Any] | Callable[[str, List[str]], Any] | Callable[ - [str, Dict[str, str], List[str]], Any + StartElementHandler: Callable[[str, dict[str, str]], Any] | Callable[[str, list[str]], Any] | Callable[ + [str, dict[str, str], list[str]], Any ] | None EndElementHandler: Callable[[str], Any] | None ProcessingInstructionHandler: Callable[[str, str], Any] | None @@ -71,5 +71,5 @@ def ErrorString(__code: int) -> str: ... # intern is undocumented def ParserCreate( - encoding: Text | None = ..., namespace_separator: Text | None = ..., intern: Dict[str, Any] | None = ... + encoding: Text | None = ..., namespace_separator: Text | None = ..., intern: dict[str, Any] | None = ... ) -> XMLParserType: ... diff --git a/mypy/typeshed/stdlib/@python2/random.pyi b/mypy/typeshed/stdlib/@python2/random.pyi index 6fb5d602067cb..df279a03c24a3 100644 --- a/mypy/typeshed/stdlib/@python2/random.pyi +++ b/mypy/typeshed/stdlib/@python2/random.pyi @@ -1,5 +1,5 @@ import _random -from typing import Any, Callable, Iterator, List, MutableSequence, Protocol, Sequence, TypeVar, overload +from typing import Any, Callable, Iterator, MutableSequence, Protocol, Sequence, TypeVar, overload _T = TypeVar("_T") _T_co = TypeVar("_T_co", covariant=True) @@ -22,7 +22,7 @@ class Random(_random.Random): def randint(self, a: int, b: int) -> int: ... def choice(self, seq: Sequence[_T]) -> _T: ... def shuffle(self, x: MutableSequence[Any], random: Callable[[], None] = ...) -> None: ... - def sample(self, population: _Sampleable[_T], k: int) -> List[_T]: ... + def sample(self, population: _Sampleable[_T], k: int) -> list[_T]: ... def random(self) -> float: ... def uniform(self, a: float, b: float) -> float: ... def triangular(self, low: float = ..., high: float = ..., mode: float = ...) -> float: ... @@ -52,7 +52,7 @@ def randrange(start: int, stop: int, step: int = ...) -> int: ... def randint(a: int, b: int) -> int: ... def choice(seq: Sequence[_T]) -> _T: ... def shuffle(x: MutableSequence[Any], random: Callable[[], float] = ...) -> None: ... -def sample(population: _Sampleable[_T], k: int) -> List[_T]: ... +def sample(population: _Sampleable[_T], k: int) -> list[_T]: ... def random() -> float: ... def uniform(a: float, b: float) -> float: ... def triangular(low: float = ..., high: float = ..., mode: float = ...) -> float: ... diff --git a/mypy/typeshed/stdlib/@python2/re.pyi b/mypy/typeshed/stdlib/@python2/re.pyi index fbe021ce67be7..ba555968ad4b8 100644 --- a/mypy/typeshed/stdlib/@python2/re.pyi +++ b/mypy/typeshed/stdlib/@python2/re.pyi @@ -1,4 +1,4 @@ -from typing import Any, AnyStr, Callable, Iterator, List, Match, Pattern, Tuple, overload +from typing import Any, AnyStr, Callable, Iterator, Match, Pattern, overload # ----- re variables and constants ----- DEBUG: int @@ -32,13 +32,13 @@ def match(pattern: str | unicode, string: AnyStr, flags: int = ...) -> Match[Any @overload def match(pattern: Pattern[str] | Pattern[unicode], string: AnyStr, flags: int = ...) -> Match[AnyStr] | None: ... @overload -def split(pattern: str | unicode, string: AnyStr, maxsplit: int = ..., flags: int = ...) -> List[AnyStr]: ... +def split(pattern: str | unicode, string: AnyStr, maxsplit: int = ..., flags: int = ...) -> list[AnyStr]: ... @overload -def split(pattern: Pattern[str] | Pattern[unicode], string: AnyStr, maxsplit: int = ..., flags: int = ...) -> List[AnyStr]: ... +def split(pattern: Pattern[str] | Pattern[unicode], string: AnyStr, maxsplit: int = ..., flags: int = ...) -> list[AnyStr]: ... @overload -def findall(pattern: str | unicode, string: AnyStr, flags: int = ...) -> List[Any]: ... +def findall(pattern: str | unicode, string: AnyStr, flags: int = ...) -> list[Any]: ... @overload -def findall(pattern: Pattern[str] | Pattern[unicode], string: AnyStr, flags: int = ...) -> List[Any]: ... +def findall(pattern: Pattern[str] | Pattern[unicode], string: AnyStr, flags: int = ...) -> list[Any]: ... # Return an iterator yielding match objects over all non-overlapping matches # for the RE pattern in string. The string is scanned left-to-right, and @@ -65,15 +65,15 @@ def sub( flags: int = ..., ) -> AnyStr: ... @overload -def subn(pattern: str | unicode, repl: AnyStr, string: AnyStr, count: int = ..., flags: int = ...) -> Tuple[AnyStr, int]: ... +def subn(pattern: str | unicode, repl: AnyStr, string: AnyStr, count: int = ..., flags: int = ...) -> tuple[AnyStr, int]: ... @overload def subn( pattern: str | unicode, repl: Callable[[Match[AnyStr]], AnyStr], string: AnyStr, count: int = ..., flags: int = ... -) -> Tuple[AnyStr, int]: ... +) -> tuple[AnyStr, int]: ... @overload def subn( pattern: Pattern[str] | Pattern[unicode], repl: AnyStr, string: AnyStr, count: int = ..., flags: int = ... -) -> Tuple[AnyStr, int]: ... +) -> tuple[AnyStr, int]: ... @overload def subn( pattern: Pattern[str] | Pattern[unicode], @@ -81,7 +81,7 @@ def subn( string: AnyStr, count: int = ..., flags: int = ..., -) -> Tuple[AnyStr, int]: ... +) -> tuple[AnyStr, int]: ... def escape(string: AnyStr) -> AnyStr: ... def purge() -> None: ... def template(pattern: AnyStr | Pattern[AnyStr], flags: int = ...) -> Pattern[AnyStr]: ... diff --git a/mypy/typeshed/stdlib/@python2/readline.pyi b/mypy/typeshed/stdlib/@python2/readline.pyi index 9b82d9bae6362..af642410b0075 100644 --- a/mypy/typeshed/stdlib/@python2/readline.pyi +++ b/mypy/typeshed/stdlib/@python2/readline.pyi @@ -2,8 +2,8 @@ import sys from typing import Callable, Optional, Sequence, Text if sys.platform != "win32": - _CompleterT = Optional[Callable[[str, int], Optional[str]]] - _CompDispT = Optional[Callable[[str, Sequence[str], int], None]] + _CompleterT = Optional[Callable[[str, int], str | None]] + _CompDispT = Callable[[str, Sequence[str], int], None] | None def parse_and_bind(__string: str) -> None: ... def read_init_file(__filename: Text | None = ...) -> None: ... def get_line_buffer() -> str: ... diff --git a/mypy/typeshed/stdlib/@python2/repr.pyi b/mypy/typeshed/stdlib/@python2/repr.pyi index bdb8822ac77d0..6b6f5ea9325ec 100644 --- a/mypy/typeshed/stdlib/@python2/repr.pyi +++ b/mypy/typeshed/stdlib/@python2/repr.pyi @@ -1,4 +1,4 @@ -from typing import Any, List +from typing import Any class Repr: maxarray: int @@ -27,7 +27,7 @@ class Repr: def repr_str(self, x, level: complex) -> str: ... def repr_tuple(self, x, level: complex) -> str: ... -def _possibly_sorted(x) -> List[Any]: ... +def _possibly_sorted(x) -> list[Any]: ... aRepr: Repr diff --git a/mypy/typeshed/stdlib/@python2/resource.pyi b/mypy/typeshed/stdlib/@python2/resource.pyi index 476438d536744..8deec4f67f516 100644 --- a/mypy/typeshed/stdlib/@python2/resource.pyi +++ b/mypy/typeshed/stdlib/@python2/resource.pyi @@ -1,11 +1,11 @@ import sys -from typing import NamedTuple, Tuple +from typing import NamedTuple if sys.platform != "win32": class error(Exception): ... RLIM_INFINITY: int - def getrlimit(resource: int) -> Tuple[int, int]: ... - def setrlimit(resource: int, limits: Tuple[int, int]) -> None: ... + def getrlimit(resource: int) -> tuple[int, int]: ... + def setrlimit(resource: int, limits: tuple[int, int]) -> None: ... RLIMIT_CORE: int RLIMIT_CPU: int RLIMIT_FSIZE: int @@ -18,6 +18,7 @@ if sys.platform != "win32": RLIMIT_MEMLOCK: int RLIMIT_VMEM: int RLIMIT_AS: int + class _RUsage(NamedTuple): ru_utime: float ru_stime: float diff --git a/mypy/typeshed/stdlib/@python2/rlcompleter.pyi b/mypy/typeshed/stdlib/@python2/rlcompleter.pyi index a61c61eb24f21..6cf58fbf20cff 100644 --- a/mypy/typeshed/stdlib/@python2/rlcompleter.pyi +++ b/mypy/typeshed/stdlib/@python2/rlcompleter.pyi @@ -1,7 +1,9 @@ -from typing import Any, Dict, Union +from typing import Any -_Text = Union[str, unicode] +_Text = str | unicode class Completer: - def __init__(self, namespace: Dict[str, Any] | None = ...) -> None: ... + def __init__(self, namespace: dict[str, Any] | None = ...) -> None: ... def complete(self, text: _Text, state: int) -> str | None: ... + def attr_matches(self, text: _Text) -> list[str]: ... + def global_matches(self, text: _Text) -> list[str]: ... diff --git a/mypy/typeshed/stdlib/@python2/sched.pyi b/mypy/typeshed/stdlib/@python2/sched.pyi index f718dd7a57bdb..9247a95da974a 100644 --- a/mypy/typeshed/stdlib/@python2/sched.pyi +++ b/mypy/typeshed/stdlib/@python2/sched.pyi @@ -1,18 +1,18 @@ -from typing import Any, Callable, Dict, List, NamedTuple, Text, Tuple +from typing import Any, Callable, NamedTuple, Text class Event(NamedTuple): time: float priority: Any action: Callable[..., Any] - argument: Tuple[Any, ...] - kwargs: Dict[Text, Any] + argument: tuple[Any, ...] + kwargs: dict[Text, Any] class scheduler: def __init__(self, timefunc: Callable[[], float], delayfunc: Callable[[float], None]) -> None: ... - def enterabs(self, time: float, priority: Any, action: Callable[..., Any], argument: Tuple[Any, ...]) -> Event: ... - def enter(self, delay: float, priority: Any, action: Callable[..., Any], argument: Tuple[Any, ...]) -> Event: ... + def enterabs(self, time: float, priority: Any, action: Callable[..., Any], argument: tuple[Any, ...]) -> Event: ... + def enter(self, delay: float, priority: Any, action: Callable[..., Any], argument: tuple[Any, ...]) -> Event: ... def run(self) -> None: ... def cancel(self, event: Event) -> None: ... def empty(self) -> bool: ... @property - def queue(self) -> List[Event]: ... + def queue(self) -> list[Event]: ... diff --git a/mypy/typeshed/stdlib/@python2/select.pyi b/mypy/typeshed/stdlib/@python2/select.pyi index b960fd4e24b51..cd799d75b5b1f 100644 --- a/mypy/typeshed/stdlib/@python2/select.pyi +++ b/mypy/typeshed/stdlib/@python2/select.pyi @@ -1,6 +1,6 @@ import sys from _typeshed import FileDescriptorLike -from typing import Any, Iterable, List, Tuple +from typing import Any, Iterable if sys.platform != "win32": PIPE_BUF: int @@ -21,11 +21,11 @@ class poll: def register(self, fd: FileDescriptorLike, eventmask: int = ...) -> None: ... def modify(self, fd: FileDescriptorLike, eventmask: int) -> None: ... def unregister(self, fd: FileDescriptorLike) -> None: ... - def poll(self, timeout: float | None = ...) -> List[Tuple[int, int]]: ... + def poll(self, timeout: float | None = ...) -> list[tuple[int, int]]: ... def select( __rlist: Iterable[Any], __wlist: Iterable[Any], __xlist: Iterable[Any], __timeout: float | None = ... -) -> Tuple[List[Any], List[Any], List[Any]]: ... +) -> tuple[list[Any], list[Any], list[Any]]: ... class error(Exception): ... @@ -54,7 +54,7 @@ if sys.platform != "linux" and sys.platform != "win32": def close(self) -> None: ... def control( self, __changelist: Iterable[kevent] | None, __maxevents: int, __timeout: float | None = ... - ) -> List[kevent]: ... + ) -> list[kevent]: ... def fileno(self) -> int: ... @classmethod def fromfd(cls, __fd: FileDescriptorLike) -> kqueue: ... @@ -106,7 +106,7 @@ if sys.platform == "linux": def register(self, fd: FileDescriptorLike, eventmask: int = ...) -> None: ... def modify(self, fd: FileDescriptorLike, eventmask: int) -> None: ... def unregister(self, fd: FileDescriptorLike) -> None: ... - def poll(self, timeout: float | None = ..., maxevents: int = ...) -> List[Tuple[int, int]]: ... + def poll(self, timeout: float | None = ..., maxevents: int = ...) -> list[tuple[int, int]]: ... @classmethod def fromfd(cls, __fd: FileDescriptorLike) -> epoll: ... EPOLLERR: int diff --git a/mypy/typeshed/stdlib/@python2/sets.pyi b/mypy/typeshed/stdlib/@python2/sets.pyi index d2b94ea44bbce..637bc879fa748 100644 --- a/mypy/typeshed/stdlib/@python2/sets.pyi +++ b/mypy/typeshed/stdlib/@python2/sets.pyi @@ -1,29 +1,27 @@ -from typing import Any, Hashable, Iterable, Iterator, MutableMapping, TypeVar, Union +from _typeshed import Self +from typing import Any, Hashable, Iterable, Iterator, MutableMapping, TypeVar _T = TypeVar("_T") -_Setlike = Union[BaseSet[_T], Iterable[_T]] -_SelfT = TypeVar("_SelfT") +_Setlike = BaseSet[_T] | Iterable[_T] class BaseSet(Iterable[_T]): def __init__(self) -> None: ... def __len__(self) -> int: ... - def __repr__(self) -> str: ... - def __str__(self) -> str: ... def __iter__(self) -> Iterator[_T]: ... def __cmp__(self, other: Any) -> int: ... - def __eq__(self, other: Any) -> bool: ... - def __ne__(self, other: Any) -> bool: ... - def copy(self: _SelfT) -> _SelfT: ... - def __copy__(self: _SelfT) -> _SelfT: ... - def __deepcopy__(self: _SelfT, memo: MutableMapping[int, BaseSet[_T]]) -> _SelfT: ... - def __or__(self: _SelfT, other: BaseSet[_T]) -> _SelfT: ... - def union(self: _SelfT, other: _Setlike[_T]) -> _SelfT: ... - def __and__(self: _SelfT, other: BaseSet[_T]) -> _SelfT: ... - def intersection(self: _SelfT, other: _Setlike[Any]) -> _SelfT: ... - def __xor__(self: _SelfT, other: BaseSet[_T]) -> _SelfT: ... - def symmetric_difference(self: _SelfT, other: _Setlike[_T]) -> _SelfT: ... - def __sub__(self: _SelfT, other: BaseSet[_T]) -> _SelfT: ... - def difference(self: _SelfT, other: _Setlike[Any]) -> _SelfT: ... + def __eq__(self, other: object) -> bool: ... + def __ne__(self, other: object) -> bool: ... + def copy(self: Self) -> Self: ... + def __copy__(self: Self) -> Self: ... + def __deepcopy__(self: Self, memo: MutableMapping[int, BaseSet[_T]]) -> Self: ... + def __or__(self: Self, other: BaseSet[_T]) -> Self: ... + def union(self: Self, other: _Setlike[_T]) -> Self: ... + def __and__(self: Self, other: BaseSet[_T]) -> Self: ... + def intersection(self: Self, other: _Setlike[Any]) -> Self: ... + def __xor__(self: Self, other: BaseSet[_T]) -> Self: ... + def symmetric_difference(self: Self, other: _Setlike[_T]) -> Self: ... + def __sub__(self: Self, other: BaseSet[_T]) -> Self: ... + def difference(self: Self, other: _Setlike[Any]) -> Self: ... def __contains__(self, element: Any) -> bool: ... def issubset(self, other: BaseSet[_T]) -> bool: ... def issuperset(self, other: BaseSet[_T]) -> bool: ... @@ -38,13 +36,13 @@ class ImmutableSet(BaseSet[_T], Hashable): class Set(BaseSet[_T]): def __init__(self, iterable: _Setlike[_T] | None = ...) -> None: ... - def __ior__(self: _SelfT, other: BaseSet[_T]) -> _SelfT: ... + def __ior__(self: Self, other: BaseSet[_T]) -> Self: ... def union_update(self, other: _Setlike[_T]) -> None: ... - def __iand__(self: _SelfT, other: BaseSet[_T]) -> _SelfT: ... + def __iand__(self: Self, other: BaseSet[_T]) -> Self: ... def intersection_update(self, other: _Setlike[Any]) -> None: ... - def __ixor__(self: _SelfT, other: BaseSet[_T]) -> _SelfT: ... + def __ixor__(self: Self, other: BaseSet[_T]) -> Self: ... def symmetric_difference_update(self, other: _Setlike[_T]) -> None: ... - def __isub__(self: _SelfT, other: BaseSet[_T]) -> _SelfT: ... + def __isub__(self: Self, other: BaseSet[_T]) -> Self: ... def difference_update(self, other: _Setlike[Any]) -> None: ... def update(self, iterable: _Setlike[_T]) -> None: ... def clear(self) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/shelve.pyi b/mypy/typeshed/stdlib/@python2/shelve.pyi index d9b1a00e58dfd..011159792e607 100644 --- a/mypy/typeshed/stdlib/@python2/shelve.pyi +++ b/mypy/typeshed/stdlib/@python2/shelve.pyi @@ -1,12 +1,13 @@ import collections -from typing import Any, Dict, Iterator, List, Tuple +from _typeshed import Self +from typing import Any, Iterator class Shelf(collections.MutableMapping[Any, Any]): def __init__( - self, dict: Dict[Any, Any], protocol: int | None = ..., writeback: bool = ..., keyencoding: str = ... + self, dict: dict[Any, Any], protocol: int | None = ..., writeback: bool = ..., keyencoding: str = ... ) -> None: ... def __iter__(self) -> Iterator[str]: ... - def keys(self) -> List[Any]: ... + def keys(self) -> list[Any]: ... def __len__(self) -> int: ... def has_key(self, key: Any) -> bool: ... def __contains__(self, key: Any) -> bool: ... @@ -14,7 +15,7 @@ class Shelf(collections.MutableMapping[Any, Any]): def __getitem__(self, key: Any) -> Any: ... def __setitem__(self, key: Any, value: Any) -> None: ... def __delitem__(self, key: Any) -> None: ... - def __enter__(self) -> Shelf: ... + def __enter__(self: Self) -> Self: ... def __exit__(self, type: Any, value: Any, traceback: Any) -> None: ... def close(self) -> None: ... def __del__(self) -> None: ... @@ -22,13 +23,13 @@ class Shelf(collections.MutableMapping[Any, Any]): class BsdDbShelf(Shelf): def __init__( - self, dict: Dict[Any, Any], protocol: int | None = ..., writeback: bool = ..., keyencoding: str = ... + self, dict: dict[Any, Any], protocol: int | None = ..., writeback: bool = ..., keyencoding: str = ... ) -> None: ... - def set_location(self, key: Any) -> Tuple[str, Any]: ... - def next(self) -> Tuple[str, Any]: ... - def previous(self) -> Tuple[str, Any]: ... - def first(self) -> Tuple[str, Any]: ... - def last(self) -> Tuple[str, Any]: ... + def set_location(self, key: Any) -> tuple[str, Any]: ... + def next(self) -> tuple[str, Any]: ... + def previous(self) -> tuple[str, Any]: ... + def first(self) -> tuple[str, Any]: ... + def last(self) -> tuple[str, Any]: ... class DbfilenameShelf(Shelf): def __init__(self, filename: str, flag: str = ..., protocol: int | None = ..., writeback: bool = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/shlex.pyi b/mypy/typeshed/stdlib/@python2/shlex.pyi index 89c28fc9be7f9..6c4557a980367 100644 --- a/mypy/typeshed/stdlib/@python2/shlex.pyi +++ b/mypy/typeshed/stdlib/@python2/shlex.pyi @@ -1,12 +1,11 @@ -from typing import IO, Any, List, Text, TypeVar +from _typeshed import Self +from typing import IO, Any, Text -def split(s: str | None, comments: bool = ..., posix: bool = ...) -> List[str]: ... - -_SLT = TypeVar("_SLT", bound=shlex) +def split(s: str | None, comments: bool = ..., posix: bool = ...) -> list[str]: ... class shlex: def __init__(self, instream: IO[Any] | Text = ..., infile: IO[Any] = ..., posix: bool = ...) -> None: ... - def __iter__(self: _SLT) -> _SLT: ... + def __iter__(self: Self) -> Self: ... def next(self) -> str: ... def get_token(self) -> str | None: ... def push_token(self, _str: str) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/shutil.pyi b/mypy/typeshed/stdlib/@python2/shutil.pyi index 4805c8e4cdb72..173ce9c284af5 100644 --- a/mypy/typeshed/stdlib/@python2/shutil.pyi +++ b/mypy/typeshed/stdlib/@python2/shutil.pyi @@ -1,9 +1,9 @@ from _typeshed import SupportsRead, SupportsWrite -from typing import Any, AnyStr, Callable, Iterable, List, Sequence, Set, Text, Tuple, Type, TypeVar, Union +from typing import Any, AnyStr, Callable, Iterable, Sequence, Text, TypeVar _AnyStr = TypeVar("_AnyStr", str, unicode) _AnyPath = TypeVar("_AnyPath", str, unicode) -_PathReturn = Type[None] +_PathReturn = type[None] class Error(EnvironmentError): ... class SpecialFileError(EnvironmentError): ... @@ -15,13 +15,13 @@ def copymode(src: Text, dst: Text) -> None: ... def copystat(src: Text, dst: Text) -> None: ... def copy(src: Text, dst: Text) -> _PathReturn: ... def copy2(src: Text, dst: Text) -> _PathReturn: ... -def ignore_patterns(*patterns: Text) -> Callable[[Any, List[_AnyStr]], Set[_AnyStr]]: ... +def ignore_patterns(*patterns: Text) -> Callable[[Any, list[_AnyStr]], set[_AnyStr]]: ... def copytree( - src: AnyStr, dst: AnyStr, symlinks: bool = ..., ignore: None | Callable[[AnyStr, List[AnyStr]], Iterable[AnyStr]] = ... + src: AnyStr, dst: AnyStr, symlinks: bool = ..., ignore: None | Callable[[AnyStr, list[AnyStr]], Iterable[AnyStr]] = ... ) -> _PathReturn: ... def rmtree(path: _AnyPath, ignore_errors: bool = ..., onerror: Callable[[Any, _AnyPath, Any], Any] | None = ...) -> None: ... -_CopyFn = Union[Callable[[str, str], None], Callable[[Text, Text], None]] +_CopyFn = Callable[[str, str], None] | Callable[[Text, Text], None] def move(src: Text, dst: Text) -> _PathReturn: ... def make_archive( @@ -35,11 +35,11 @@ def make_archive( group: str | None = ..., logger: Any | None = ..., ) -> _AnyStr: ... -def get_archive_formats() -> List[Tuple[str, str]]: ... +def get_archive_formats() -> list[tuple[str, str]]: ... def register_archive_format( name: str, function: Callable[..., Any], - extra_args: Sequence[Tuple[str, Any] | List[Any]] | None = ..., + extra_args: Sequence[tuple[str, Any] | list[Any]] | None = ..., description: str = ..., ) -> None: ... def unregister_archive_format(name: str) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/signal.pyi b/mypy/typeshed/stdlib/@python2/signal.pyi index 16a8f2d1cb8b1..f39f38c41c8fd 100644 --- a/mypy/typeshed/stdlib/@python2/signal.pyi +++ b/mypy/typeshed/stdlib/@python2/signal.pyi @@ -1,67 +1,67 @@ from types import FrameType -from typing import Callable, Tuple, Union +from typing import Callable -SIG_DFL: int = ... -SIG_IGN: int = ... +SIG_DFL: int +SIG_IGN: int -ITIMER_REAL: int = ... -ITIMER_VIRTUAL: int = ... -ITIMER_PROF: int = ... +ITIMER_REAL: int +ITIMER_VIRTUAL: int +ITIMER_PROF: int -NSIG: int = ... +NSIG: int -SIGABRT: int = ... -SIGALRM: int = ... -SIGBREAK: int = ... # Windows -SIGBUS: int = ... -SIGCHLD: int = ... -SIGCLD: int = ... -SIGCONT: int = ... -SIGEMT: int = ... -SIGFPE: int = ... -SIGHUP: int = ... -SIGILL: int = ... -SIGINFO: int = ... -SIGINT: int = ... -SIGIO: int = ... -SIGIOT: int = ... -SIGKILL: int = ... -SIGPIPE: int = ... -SIGPOLL: int = ... -SIGPROF: int = ... -SIGPWR: int = ... -SIGQUIT: int = ... -SIGRTMAX: int = ... -SIGRTMIN: int = ... -SIGSEGV: int = ... -SIGSTOP: int = ... -SIGSYS: int = ... -SIGTERM: int = ... -SIGTRAP: int = ... -SIGTSTP: int = ... -SIGTTIN: int = ... -SIGTTOU: int = ... -SIGURG: int = ... -SIGUSR1: int = ... -SIGUSR2: int = ... -SIGVTALRM: int = ... -SIGWINCH: int = ... -SIGXCPU: int = ... -SIGXFSZ: int = ... +SIGABRT: int +SIGALRM: int +SIGBREAK: int # Windows +SIGBUS: int +SIGCHLD: int +SIGCLD: int +SIGCONT: int +SIGEMT: int +SIGFPE: int +SIGHUP: int +SIGILL: int +SIGINFO: int +SIGINT: int +SIGIO: int +SIGIOT: int +SIGKILL: int +SIGPIPE: int +SIGPOLL: int +SIGPROF: int +SIGPWR: int +SIGQUIT: int +SIGRTMAX: int +SIGRTMIN: int +SIGSEGV: int +SIGSTOP: int +SIGSYS: int +SIGTERM: int +SIGTRAP: int +SIGTSTP: int +SIGTTIN: int +SIGTTOU: int +SIGURG: int +SIGUSR1: int +SIGUSR2: int +SIGVTALRM: int +SIGWINCH: int +SIGXCPU: int +SIGXFSZ: int # Windows -CTRL_C_EVENT: int = ... -CTRL_BREAK_EVENT: int = ... +CTRL_C_EVENT: int +CTRL_BREAK_EVENT: int class ItimerError(IOError): ... -_HANDLER = Union[Callable[[int, FrameType], None], int, None] +_HANDLER = Callable[[int, FrameType], None] | int | None def alarm(time: int) -> int: ... def getsignal(signalnum: int) -> _HANDLER: ... def pause() -> None: ... -def setitimer(which: int, seconds: float, interval: float = ...) -> Tuple[float, float]: ... -def getitimer(which: int) -> Tuple[float, float]: ... +def setitimer(which: int, seconds: float, interval: float = ...) -> tuple[float, float]: ... +def getitimer(which: int) -> tuple[float, float]: ... def set_wakeup_fd(fd: int) -> int: ... def siginterrupt(signalnum: int, flag: bool) -> None: ... def signal(signalnum: int, handler: _HANDLER) -> _HANDLER: ... diff --git a/mypy/typeshed/stdlib/@python2/site.pyi b/mypy/typeshed/stdlib/@python2/site.pyi index c77c9397f6123..fc331c113163c 100644 --- a/mypy/typeshed/stdlib/@python2/site.pyi +++ b/mypy/typeshed/stdlib/@python2/site.pyi @@ -1,12 +1,12 @@ -from typing import Iterable, List +from typing import Iterable -PREFIXES: List[str] +PREFIXES: list[str] ENABLE_USER_SITE: bool | None USER_SITE: str | None USER_BASE: str | None def main() -> None: ... def addsitedir(sitedir: str, known_paths: Iterable[str] | None = ...) -> None: ... -def getsitepackages(prefixes: Iterable[str] | None = ...) -> List[str]: ... +def getsitepackages(prefixes: Iterable[str] | None = ...) -> list[str]: ... def getuserbase() -> str: ... def getusersitepackages() -> str: ... diff --git a/mypy/typeshed/stdlib/@python2/smtpd.pyi b/mypy/typeshed/stdlib/@python2/smtpd.pyi index 1c17b82d8ab51..c7741d1834154 100644 --- a/mypy/typeshed/stdlib/@python2/smtpd.pyi +++ b/mypy/typeshed/stdlib/@python2/smtpd.pyi @@ -1,16 +1,15 @@ import asynchat import asyncore import socket -from typing import Any, List, Text, Tuple, Type +from typing import Any, Text -_Address = Tuple[str, int] # (host, port) +_Address = tuple[str, int] # (host, port) class SMTPChannel(asynchat.async_chat): COMMAND: int DATA: int def __init__(self, server: SMTPServer, conn: socket.socket, addr: Any, data_size_limit: int = ...) -> None: ... - # base asynchat.async_chat.push() accepts bytes - def push(self, msg: Text) -> None: ... # type: ignore + def push(self, msg: Text) -> None: ... def collect_incoming_data(self, data: bytes) -> None: ... def found_terminator(self) -> None: ... def smtp_HELO(self, arg: str) -> None: ... @@ -22,24 +21,20 @@ class SMTPChannel(asynchat.async_chat): def smtp_DATA(self, arg: str) -> None: ... class SMTPServer(asyncore.dispatcher): - channel_class: Type[SMTPChannel] + channel_class: type[SMTPChannel] data_size_limit: int enable_SMTPUTF8: bool def __init__(self, localaddr: _Address, remoteaddr: _Address, data_size_limit: int = ...) -> None: ... def handle_accepted(self, conn: socket.socket, addr: Any) -> None: ... def process_message( - self, peer: _Address, mailfrom: str, rcpttos: List[Text], data: bytes | str, **kwargs: Any + self, peer: _Address, mailfrom: str, rcpttos: list[Text], data: bytes | str, **kwargs: Any ) -> str | None: ... class DebuggingServer(SMTPServer): ... class PureProxy(SMTPServer): - def process_message( # type: ignore - self, peer: _Address, mailfrom: str, rcpttos: List[Text], data: bytes | str - ) -> str | None: ... + def process_message(self, peer: _Address, mailfrom: str, rcpttos: list[Text], data: bytes | str) -> str | None: ... # type: ignore[override] class MailmanProxy(PureProxy): - def process_message( # type: ignore - self, peer: _Address, mailfrom: str, rcpttos: List[Text], data: bytes | str - ) -> str | None: ... + def process_message(self, peer: _Address, mailfrom: str, rcpttos: list[Text], data: bytes | str) -> str | None: ... # type: ignore[override] diff --git a/mypy/typeshed/stdlib/@python2/sndhdr.pyi b/mypy/typeshed/stdlib/@python2/sndhdr.pyi index 189529fd21d66..fea65b28899cb 100644 --- a/mypy/typeshed/stdlib/@python2/sndhdr.pyi +++ b/mypy/typeshed/stdlib/@python2/sndhdr.pyi @@ -1,6 +1,6 @@ -from typing import Text, Tuple, Union +from typing import Text -_SndHeaders = Tuple[str, int, int, int, Union[int, str]] +_SndHeaders = tuple[str, int, int, int, int | str] def what(filename: Text) -> _SndHeaders | None: ... def whathdr(filename: Text) -> _SndHeaders | None: ... diff --git a/mypy/typeshed/stdlib/@python2/socket.pyi b/mypy/typeshed/stdlib/@python2/socket.pyi index 2bf719dd9faa3..296a9fa5e5a53 100644 --- a/mypy/typeshed/stdlib/@python2/socket.pyi +++ b/mypy/typeshed/stdlib/@python2/socket.pyi @@ -1,5 +1,5 @@ import sys -from typing import Any, BinaryIO, Iterable, List, Text, Tuple, TypeVar, Union, overload +from typing import Any, BinaryIO, Iterable, Text, overload # ----- Constants ----- # Some socket families are listed in the "Socket families" section of the docs, @@ -373,14 +373,13 @@ class timeout(error): # Addresses can be either tuples of varying lengths (AF_INET, AF_INET6, # AF_NETLINK, AF_TIPC) or strings (AF_UNIX). -_Address = Union[Tuple[Any, ...], str] +_Address = tuple[Any, ...] | str _RetAddress = Any # TODO Most methods allow bytes as address objects -_WriteBuffer = Union[bytearray, memoryview] +_WriteBuffer = bytearray | memoryview -_CMSG = Tuple[int, int, bytes] -_SelfT = TypeVar("_SelfT", bound=socket) +_CMSG = tuple[int, int, bytes] class socket: family: int @@ -388,7 +387,7 @@ class socket: proto: int def __init__(self, family: int = ..., type: int = ..., proto: int = ...) -> None: ... # --- methods --- - def accept(self) -> Tuple[socket, _RetAddress]: ... + def accept(self) -> tuple[socket, _RetAddress]: ... def bind(self, address: _Address | bytes) -> None: ... def close(self) -> None: ... def connect(self, address: _Address | bytes) -> None: ... @@ -404,13 +403,14 @@ class socket: def getsockopt(self, level: int, optname: int, buflen: int) -> bytes: ... def gettimeout(self) -> float | None: ... if sys.platform == "win32": - def ioctl(self, control: int, option: int | Tuple[int, int, int]) -> None: ... + def ioctl(self, control: int, option: int | tuple[int, int, int]) -> None: ... + def listen(self, __backlog: int) -> None: ... # Note that the makefile's documented windows-specific behavior is not represented def makefile(self, mode: unicode = ..., buffering: int = ...) -> BinaryIO: ... def recv(self, bufsize: int, flags: int = ...) -> bytes: ... - def recvfrom(self, bufsize: int, flags: int = ...) -> Tuple[bytes, _RetAddress]: ... - def recvfrom_into(self, buffer: _WriteBuffer, nbytes: int = ..., flags: int = ...) -> Tuple[int, _RetAddress]: ... + def recvfrom(self, bufsize: int, flags: int = ...) -> tuple[bytes, _RetAddress]: ... + def recvfrom_into(self, buffer: _WriteBuffer, nbytes: int = ..., flags: int = ...) -> tuple[int, _RetAddress]: ... def recv_into(self, buffer: _WriteBuffer, nbytes: int = ..., flags: int = ...) -> int: ... def send(self, data: bytes, flags: int = ...) -> int: ... def sendall(self, data: bytes, flags: int = ...) -> None: ... # return type: None on success @@ -423,14 +423,15 @@ class socket: def setsockopt(self, level: int, optname: int, value: int | bytes) -> None: ... if sys.platform == "win32": def share(self, process_id: int) -> bytes: ... + def shutdown(self, how: int) -> None: ... # ----- Functions ----- def create_connection( - address: Tuple[str | None, int], + address: tuple[str | None, int], timeout: float | None = ..., - source_address: Tuple[bytearray | bytes | Text, int] | None = ..., + source_address: tuple[bytearray | bytes | Text, int] | None = ..., ) -> socket: ... def fromfd(fd: int, family: int, type: int, proto: int = ...) -> socket: ... @@ -442,22 +443,22 @@ def getaddrinfo( socktype: int = ..., proto: int = ..., flags: int = ..., -) -> List[Tuple[AddressFamily, SocketKind, int, str, Tuple[Any, ...]]]: ... +) -> list[tuple[AddressFamily, SocketKind, int, str, tuple[Any, ...]]]: ... def getfqdn(name: str = ...) -> str: ... def gethostbyname(hostname: str) -> str: ... -def gethostbyname_ex(hostname: str) -> Tuple[str, List[str], List[str]]: ... +def gethostbyname_ex(hostname: str) -> tuple[str, list[str], list[str]]: ... def gethostname() -> str: ... -def gethostbyaddr(ip_address: str) -> Tuple[str, List[str], List[str]]: ... -def getnameinfo(sockaddr: Tuple[str, int] | Tuple[str, int, int, int], flags: int) -> Tuple[str, str]: ... +def gethostbyaddr(ip_address: str) -> tuple[str, list[str], list[str]]: ... +def getnameinfo(sockaddr: tuple[str, int] | tuple[str, int, int, int], flags: int) -> tuple[str, str]: ... def getprotobyname(protocolname: str) -> int: ... def getservbyname(servicename: str, protocolname: str = ...) -> int: ... def getservbyport(port: int, protocolname: str = ...) -> str: ... if sys.platform == "win32": - def socketpair(family: int = ..., type: int = ..., proto: int = ...) -> Tuple[socket, socket]: ... + def socketpair(family: int = ..., type: int = ..., proto: int = ...) -> tuple[socket, socket]: ... else: - def socketpair(family: int | None = ..., type: int = ..., proto: int = ...) -> Tuple[socket, socket]: ... + def socketpair(family: int | None = ..., type: int = ..., proto: int = ...) -> tuple[socket, socket]: ... def ntohl(x: int) -> int: ... # param & ret val are 32-bit ints def ntohs(x: int) -> int: ... # param & ret val are 16-bit ints diff --git a/mypy/typeshed/stdlib/@python2/spwd.pyi b/mypy/typeshed/stdlib/@python2/spwd.pyi index 95122ce43d1ea..b21242fc49e4f 100644 --- a/mypy/typeshed/stdlib/@python2/spwd.pyi +++ b/mypy/typeshed/stdlib/@python2/spwd.pyi @@ -1,5 +1,5 @@ import sys -from typing import List, NamedTuple +from typing import NamedTuple if sys.platform != "win32": class struct_spwd(NamedTuple): @@ -12,5 +12,5 @@ if sys.platform != "win32": sp_inact: int sp_expire: int sp_flag: int - def getspall() -> List[struct_spwd]: ... + def getspall() -> list[struct_spwd]: ... def getspnam(name: str) -> struct_spwd: ... diff --git a/mypy/typeshed/stdlib/@python2/sqlite3/__init__.pyi b/mypy/typeshed/stdlib/@python2/sqlite3/__init__.pyi index d5d20d67b58ea..d747be90fd0a5 100644 --- a/mypy/typeshed/stdlib/@python2/sqlite3/__init__.pyi +++ b/mypy/typeshed/stdlib/@python2/sqlite3/__init__.pyi @@ -1 +1 @@ -from sqlite3.dbapi2 import * # noqa: F403 +from sqlite3.dbapi2 import * diff --git a/mypy/typeshed/stdlib/@python2/sqlite3/dbapi2.pyi b/mypy/typeshed/stdlib/@python2/sqlite3/dbapi2.pyi index 023a0506f4aac..90740bcf90a18 100644 --- a/mypy/typeshed/stdlib/@python2/sqlite3/dbapi2.pyi +++ b/mypy/typeshed/stdlib/@python2/sqlite3/dbapi2.pyi @@ -1,5 +1,6 @@ +from _typeshed import Self from datetime import date, datetime, time -from typing import Any, Callable, Generator, Iterable, Iterator, List, Protocol, Text, Tuple, Type, TypeVar +from typing import Any, Callable, Generator, Iterable, Iterator, Protocol, Text, TypeVar _T = TypeVar("_T") @@ -14,8 +15,8 @@ def DateFromTicks(ticks: float) -> Date: ... def TimeFromTicks(ticks: float) -> Time: ... def TimestampFromTicks(ticks: float) -> Timestamp: ... -version_info: Tuple[int, int, int] -sqlite_version_info: Tuple[int, int, int] +version_info: tuple[int, int, int] +sqlite_version_info: tuple[int, int, int] Binary = buffer # The remaining definitions are imported from _sqlite3. @@ -67,12 +68,12 @@ def connect( detect_types: int = ..., isolation_level: str | None = ..., check_same_thread: bool = ..., - factory: Type[Connection] | None = ..., + factory: type[Connection] | None = ..., cached_statements: int = ..., ) -> Connection: ... def enable_callback_tracebacks(__enable: bool) -> None: ... def enable_shared_cache(enable: int) -> None: ... -def register_adapter(__type: Type[_T], __caster: Callable[[_T], int | float | str | bytes]) -> None: ... +def register_adapter(__type: type[_T], __caster: Callable[[_T], int | float | str | bytes]) -> None: ... def register_converter(__name: str, __converter: Callable[[bytes], Any]) -> None: ... class Cache(object): @@ -126,7 +127,7 @@ class Connection(object): def enable_load_extension(self, enabled: bool) -> None: ... def load_extension(self, path: str) -> None: ... def __call__(self, *args: Any, **kwargs: Any) -> Any: ... - def __enter__(self) -> Connection: ... + def __enter__(self: Self) -> Self: ... def __exit__(self, t: type | None, exc: BaseException | None, tb: Any | None) -> None: ... class Cursor(Iterator[Any]): @@ -144,8 +145,8 @@ class Cursor(Iterator[Any]): def execute(self, __sql: str, __parameters: Iterable[Any] = ...) -> Cursor: ... def executemany(self, __sql: str, __seq_of_parameters: Iterable[Iterable[Any]]) -> Cursor: ... def executescript(self, __sql_script: bytes | Text) -> Cursor: ... - def fetchall(self) -> List[Any]: ... - def fetchmany(self, size: int | None = ...) -> List[Any]: ... + def fetchall(self) -> list[Any]: ... + def fetchmany(self, size: int | None = ...) -> list[Any]: ... def fetchone(self) -> Any: ... def setinputsizes(self, *args: Any, **kwargs: Any) -> None: ... def setoutputsize(self, *args: Any, **kwargs: Any) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/sre_compile.pyi b/mypy/typeshed/stdlib/@python2/sre_compile.pyi index efc3e568a07c7..30b4d2cb628c4 100644 --- a/mypy/typeshed/stdlib/@python2/sre_compile.pyi +++ b/mypy/typeshed/stdlib/@python2/sre_compile.pyi @@ -12,10 +12,10 @@ from sre_constants import ( SRE_INFO_PREFIX as SRE_INFO_PREFIX, ) from sre_parse import SubPattern -from typing import Any, List, Pattern, Tuple, Type +from typing import Any, Pattern MAXCODE: int -STRING_TYPES: Tuple[Type[str], Type[unicode]] +STRING_TYPES: tuple[type[str], type[unicode]] _IsStringType = int def isstring(obj: Any) -> _IsStringType: ... diff --git a/mypy/typeshed/stdlib/@python2/sre_constants.pyi b/mypy/typeshed/stdlib/@python2/sre_constants.pyi index bc15754d6fa1b..09280512a7f4a 100644 --- a/mypy/typeshed/stdlib/@python2/sre_constants.pyi +++ b/mypy/typeshed/stdlib/@python2/sre_constants.pyi @@ -1,4 +1,4 @@ -from typing import Dict, List, TypeVar +from typing import TypeVar MAGIC: int MAXREPEAT: int @@ -72,14 +72,14 @@ CATEGORY_UNI_NOT_LINEBREAK: str _T = TypeVar("_T") -def makedict(list: List[_T]) -> Dict[_T, int]: ... +def makedict(list: list[_T]) -> dict[_T, int]: ... -OP_IGNORE: Dict[str, str] -AT_MULTILINE: Dict[str, str] -AT_LOCALE: Dict[str, str] -AT_UNICODE: Dict[str, str] -CH_LOCALE: Dict[str, str] -CH_UNICODE: Dict[str, str] +OP_IGNORE: dict[str, str] +AT_MULTILINE: dict[str, str] +AT_LOCALE: dict[str, str] +AT_UNICODE: dict[str, str] +CH_LOCALE: dict[str, str] +CH_UNICODE: dict[str, str] SRE_FLAG_TEMPLATE: int SRE_FLAG_IGNORECASE: int SRE_FLAG_LOCALE: int diff --git a/mypy/typeshed/stdlib/@python2/sre_parse.pyi b/mypy/typeshed/stdlib/@python2/sre_parse.pyi index 35f6d4d32ae25..9929b804126e5 100644 --- a/mypy/typeshed/stdlib/@python2/sre_parse.pyi +++ b/mypy/typeshed/stdlib/@python2/sre_parse.pyi @@ -1,38 +1,38 @@ -from typing import Any, Dict, Iterable, List, Match, Optional, Pattern as _Pattern, Set, Tuple, Union +from typing import Any, Iterable, Match, Pattern as _Pattern SPECIAL_CHARS: str REPEAT_CHARS: str -DIGITS: Set[Any] -OCTDIGITS: Set[Any] -HEXDIGITS: Set[Any] -WHITESPACE: Set[Any] -ESCAPES: Dict[str, Tuple[str, int]] -CATEGORIES: Dict[str, Tuple[str, str] | Tuple[str, List[Tuple[str, str]]]] -FLAGS: Dict[str, int] +DIGITS: set[Any] +OCTDIGITS: set[Any] +HEXDIGITS: set[Any] +WHITESPACE: set[Any] +ESCAPES: dict[str, tuple[str, int]] +CATEGORIES: dict[str, tuple[str, str] | tuple[str, list[tuple[str, str]]]] +FLAGS: dict[str, int] class Pattern: flags: int - open: List[int] + open: list[int] groups: int - groupdict: Dict[str, int] + groupdict: dict[str, int] lookbehind: int def __init__(self) -> None: ... def opengroup(self, name: str = ...) -> int: ... def closegroup(self, gid: int) -> None: ... def checkgroup(self, gid: int) -> bool: ... -_OpSubpatternType = Tuple[Optional[int], int, int, SubPattern] -_OpGroupRefExistsType = Tuple[int, SubPattern, SubPattern] -_OpInType = List[Tuple[str, int]] -_OpBranchType = Tuple[None, List[SubPattern]] -_AvType = Union[_OpInType, _OpBranchType, Iterable[SubPattern], _OpGroupRefExistsType, _OpSubpatternType] -_CodeType = Union[str, _AvType] +_OpSubpatternType = tuple[int | None, int, int, SubPattern] +_OpGroupRefExistsType = tuple[int, SubPattern, SubPattern] +_OpInType = list[tuple[str, int]] +_OpBranchType = tuple[None, list[SubPattern]] +_AvType = _OpInType | _OpBranchType | Iterable[SubPattern] | _OpGroupRefExistsType | _OpSubpatternType +_CodeType = str | _AvType class SubPattern: pattern: str - data: List[_CodeType] + data: list[_CodeType] width: int | None - def __init__(self, pattern, data: List[_CodeType] = ...) -> None: ... + def __init__(self, pattern, data: list[_CodeType] = ...) -> None: ... def dump(self, level: int = ...) -> None: ... def __len__(self) -> int: ... def __delitem__(self, index: int | slice) -> None: ... @@ -48,7 +48,7 @@ class Tokenizer: def __init__(self, string: str) -> None: ... def match(self, char: str, skip: int = ...) -> int: ... def get(self) -> str | None: ... - def tell(self) -> Tuple[int, str | None]: ... + def tell(self) -> tuple[int, str | None]: ... def seek(self, index: int) -> None: ... def isident(char: str) -> bool: ... @@ -56,7 +56,7 @@ def isdigit(char: str) -> bool: ... def isname(name: str) -> bool: ... def parse(str: str, flags: int = ..., pattern: Pattern = ...) -> SubPattern: ... -_Template = Tuple[List[Tuple[int, int]], List[Optional[int]]] +_Template = tuple[list[tuple[int, int]], list[int | None]] def parse_template(source: str, pattern: _Pattern[Any]) -> _Template: ... def expand_template(template: _Template, match: Match[Any]) -> str: ... diff --git a/mypy/typeshed/stdlib/@python2/ssl.pyi b/mypy/typeshed/stdlib/@python2/ssl.pyi index aabecaaba87ab..2c6b325672496 100644 --- a/mypy/typeshed/stdlib/@python2/ssl.pyi +++ b/mypy/typeshed/stdlib/@python2/ssl.pyi @@ -1,18 +1,18 @@ import socket import sys -from _typeshed import StrPath -from typing import Any, Callable, ClassVar, Dict, Iterable, List, NamedTuple, Optional, Set, Text, Tuple, Union, overload +from _typeshed import Self, StrPath +from typing import Any, Callable, ClassVar, Iterable, NamedTuple, Text, Union, overload from typing_extensions import Literal -_PCTRTT = Tuple[Tuple[str, str], ...] -_PCTRTTT = Tuple[_PCTRTT, ...] -_PeerCertRetDictType = Dict[str, Union[str, _PCTRTTT, _PCTRTT]] -_PeerCertRetType = Union[_PeerCertRetDictType, bytes, None] -_EnumRetType = List[Tuple[bytes, str, Union[Set[str], bool]]] -_PasswordType = Union[Callable[[], Union[str, bytes]], str, bytes] +_PCTRTT = tuple[tuple[str, str], ...] +_PCTRTTT = tuple[_PCTRTT, ...] +_PeerCertRetDictType = dict[str, str | _PCTRTTT | _PCTRTT] +_PeerCertRetType = _PeerCertRetDictType | bytes | None +_EnumRetType = list[tuple[bytes, str, Union[set[str], bool]]] +_PasswordType = Union[Callable[[], str | bytes], str, bytes] _SC1ArgT = SSLSocket -_SrvnmeCbType = Callable[[_SC1ArgT, Optional[str], SSLSocket], Optional[int]] +_SrvnmeCbType = Callable[[_SC1ArgT, str | None, SSLSocket], int | None] class SSLError(OSError): library: str @@ -60,7 +60,7 @@ def RAND_egd(path: str) -> None: ... def RAND_add(__s: bytes, __entropy: float) -> None: ... def match_hostname(cert: _PeerCertRetType, hostname: str) -> None: ... def cert_time_to_seconds(cert_time: str) -> int: ... -def get_server_certificate(addr: Tuple[str, int], ssl_version: int = ..., ca_certs: str | None = ...) -> str: ... +def get_server_certificate(addr: tuple[str, int], ssl_version: int = ..., ca_certs: str | None = ...) -> str: ... def DER_cert_to_PEM_cert(der_cert_bytes: bytes) -> str: ... def PEM_cert_to_DER_cert(pem_cert_string: str) -> bytes: ... @@ -110,10 +110,10 @@ HAS_ALPN: bool HAS_ECDH: bool HAS_SNI: bool HAS_NPN: bool -CHANNEL_BINDING_TYPES: List[str] +CHANNEL_BINDING_TYPES: list[str] OPENSSL_VERSION: str -OPENSSL_VERSION_INFO: Tuple[int, int, int, int, int] +OPENSSL_VERSION_INFO: tuple[int, int, int, int, int] OPENSSL_VERSION_NUMBER: int ALERT_DESCRIPTION_HANDSHAKE_FAILURE: int @@ -200,12 +200,12 @@ class SSLSocket(socket.socket): def getpeercert(self, binary_form: Literal[True]) -> bytes | None: ... @overload def getpeercert(self, binary_form: bool) -> _PeerCertRetType: ... - def cipher(self) -> Tuple[str, str, int] | None: ... + def cipher(self) -> tuple[str, str, int] | None: ... def compression(self) -> str | None: ... def get_channel_binding(self, cb_type: str = ...) -> bytes | None: ... def selected_alpn_protocol(self) -> str | None: ... def selected_npn_protocol(self) -> str | None: ... - def accept(self) -> Tuple[SSLSocket, socket._RetAddress]: ... + def accept(self) -> tuple[SSLSocket, socket._RetAddress]: ... def unwrap(self) -> socket.socket: ... def version(self) -> str | None: ... def pending(self) -> int: ... @@ -213,19 +213,19 @@ class SSLSocket(socket.socket): class SSLContext: check_hostname: bool options: int - def __new__(cls, protocol: int, *args: Any, **kwargs: Any) -> SSLContext: ... + def __new__(cls: type[Self], protocol: int, *args: Any, **kwargs: Any) -> Self: ... @property def protocol(self) -> int: ... verify_flags: int verify_mode: int def __init__(self, protocol: int) -> None: ... - def cert_store_stats(self) -> Dict[str, int]: ... + def cert_store_stats(self) -> dict[str, int]: ... def load_cert_chain(self, certfile: StrPath, keyfile: StrPath | None = ..., password: _PasswordType | None = ...) -> None: ... def load_default_certs(self, purpose: Purpose = ...) -> None: ... def load_verify_locations( self, cafile: StrPath | None = ..., capath: StrPath | None = ..., cadata: Text | bytes | None = ... ) -> None: ... - def get_ca_certs(self, binary_form: bool = ...) -> List[_PeerCertRetDictType] | List[bytes]: ... + def get_ca_certs(self, binary_form: bool = ...) -> list[_PeerCertRetDictType] | list[bytes]: ... def set_default_verify_paths(self) -> None: ... def set_ciphers(self, __cipherlist: str) -> None: ... def set_alpn_protocols(self, alpn_protocols: Iterable[str]) -> None: ... @@ -241,7 +241,7 @@ class SSLContext: suppress_ragged_eofs: bool = ..., server_hostname: str | None = ..., ) -> SSLSocket: ... - def session_stats(self) -> Dict[str, int]: ... + def session_stats(self) -> dict[str, int]: ... # TODO below documented in cpython but not in docs.python.org # taken from python 3.4 diff --git a/mypy/typeshed/stdlib/@python2/string.pyi b/mypy/typeshed/stdlib/@python2/string.pyi index fe028dab39bde..79fce4f893c79 100644 --- a/mypy/typeshed/stdlib/@python2/string.pyi +++ b/mypy/typeshed/stdlib/@python2/string.pyi @@ -1,4 +1,4 @@ -from typing import Any, AnyStr, Iterable, List, Mapping, Sequence, Text, Tuple, overload +from typing import Any, AnyStr, Iterable, Mapping, Sequence, Text, overload ascii_letters: str ascii_lowercase: str @@ -27,9 +27,9 @@ def index(s: unicode, sub: unicode, start: int = ..., end: int = ...) -> int: .. def rindex(s: unicode, sub: unicode, start: int = ..., end: int = ...) -> int: ... def count(s: unicode, sub: unicode, start: int = ..., end: int = ...) -> int: ... def lower(s: AnyStr) -> AnyStr: ... -def split(s: AnyStr, sep: AnyStr = ..., maxsplit: int = ...) -> List[AnyStr]: ... -def rsplit(s: AnyStr, sep: AnyStr = ..., maxsplit: int = ...) -> List[AnyStr]: ... -def splitfields(s: AnyStr, sep: AnyStr = ..., maxsplit: int = ...) -> List[AnyStr]: ... +def split(s: AnyStr, sep: AnyStr = ..., maxsplit: int = ...) -> list[AnyStr]: ... +def rsplit(s: AnyStr, sep: AnyStr = ..., maxsplit: int = ...) -> list[AnyStr]: ... +def splitfields(s: AnyStr, sep: AnyStr = ..., maxsplit: int = ...) -> list[AnyStr]: ... def join(words: Iterable[AnyStr], sep: AnyStr = ...) -> AnyStr: ... def joinfields(word: Iterable[AnyStr], sep: AnyStr = ...) -> AnyStr: ... def lstrip(s: AnyStr, chars: AnyStr = ...) -> AnyStr: ... @@ -60,7 +60,7 @@ class Template: class Formatter(object): def format(self, format_string: str, *args, **kwargs) -> str: ... def vformat(self, format_string: str, args: Sequence[Any], kwargs: Mapping[str, Any]) -> str: ... - def parse(self, format_string: str) -> Iterable[Tuple[str, str, str, str]]: ... + def parse(self, format_string: str) -> Iterable[tuple[str, str, str, str]]: ... def get_field(self, field_name: str, args: Sequence[Any], kwargs: Mapping[str, Any]) -> Any: ... def get_value(self, key: int | str, args: Sequence[Any], kwargs: Mapping[str, Any]) -> Any: ... def check_unused_args(self, used_args: Sequence[int | str], args: Sequence[Any], kwargs: Mapping[str, Any]) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/stringold.pyi b/mypy/typeshed/stdlib/@python2/stringold.pyi index d221547f1c07e..80402b0069e36 100644 --- a/mypy/typeshed/stdlib/@python2/stringold.pyi +++ b/mypy/typeshed/stdlib/@python2/stringold.pyi @@ -1,4 +1,4 @@ -from typing import AnyStr, Iterable, List +from typing import AnyStr, Iterable whitespace: str lowercase: str @@ -8,7 +8,7 @@ digits: str hexdigits: str octdigits: str _idmap: str -_idmapL: List[str] | None +_idmapL: list[str] | None index_error = ValueError atoi_error = ValueError atof_error = ValueError @@ -20,8 +20,8 @@ def swapcase(s: AnyStr) -> AnyStr: ... def strip(s: AnyStr) -> AnyStr: ... def lstrip(s: AnyStr) -> AnyStr: ... def rstrip(s: AnyStr) -> AnyStr: ... -def split(s: AnyStr, sep: AnyStr = ..., maxsplit: int = ...) -> List[AnyStr]: ... -def splitfields(s: AnyStr, sep: AnyStr = ..., maxsplit: int = ...) -> List[AnyStr]: ... +def split(s: AnyStr, sep: AnyStr = ..., maxsplit: int = ...) -> list[AnyStr]: ... +def splitfields(s: AnyStr, sep: AnyStr = ..., maxsplit: int = ...) -> list[AnyStr]: ... def join(words: Iterable[AnyStr], sep: AnyStr = ...) -> AnyStr: ... def joinfields(words: Iterable[AnyStr], sep: AnyStr = ...) -> AnyStr: ... def index(s: unicode, sub: unicode, start: int = ..., end: int = ...) -> int: ... diff --git a/mypy/typeshed/stdlib/@python2/strop.pyi b/mypy/typeshed/stdlib/@python2/strop.pyi index 81035eaabe792..9321bbe5bf5ec 100644 --- a/mypy/typeshed/stdlib/@python2/strop.pyi +++ b/mypy/typeshed/stdlib/@python2/strop.pyi @@ -1,4 +1,4 @@ -from typing import List, Sequence +from typing import Sequence lowercase: str uppercase: str @@ -19,8 +19,8 @@ def maketrans(frm: str, to: str) -> str: ... def replace(s: str, old: str, new: str, maxsplit: int = ...) -> str: ... def rfind(s: str, sub: str, start: int = ..., end: int = ...) -> int: ... def rstrip(s: str) -> str: ... -def split(s: str, sep: str, maxsplit: int = ...) -> List[str]: ... -def splitfields(s: str, sep: str, maxsplit: int = ...) -> List[str]: ... +def split(s: str, sep: str, maxsplit: int = ...) -> list[str]: ... +def splitfields(s: str, sep: str, maxsplit: int = ...) -> list[str]: ... def strip(s: str) -> str: ... def swapcase(s: str) -> str: ... def translate(s: str, table: str, deletechars: str = ...) -> str: ... diff --git a/mypy/typeshed/stdlib/@python2/struct.pyi b/mypy/typeshed/stdlib/@python2/struct.pyi index bf27d12783daa..0296c737089a8 100644 --- a/mypy/typeshed/stdlib/@python2/struct.pyi +++ b/mypy/typeshed/stdlib/@python2/struct.pyi @@ -1,17 +1,17 @@ from array import array from mmap import mmap -from typing import Any, Text, Tuple, Union +from typing import Any, Text class error(Exception): ... -_FmtType = Union[bytes, Text] -_BufferType = Union[array[int], bytes, bytearray, buffer, memoryview, mmap] -_WriteBufferType = Union[array[Any], bytearray, buffer, memoryview, mmap] +_FmtType = bytes | Text +_BufferType = array[int] | bytes | bytearray | buffer | memoryview | mmap +_WriteBufferType = array[Any] | bytearray | buffer | memoryview | mmap def pack(fmt: _FmtType, *v: Any) -> bytes: ... def pack_into(fmt: _FmtType, buffer: _WriteBufferType, offset: int, *v: Any) -> None: ... -def unpack(__format: _FmtType, __buffer: _BufferType) -> Tuple[Any, ...]: ... -def unpack_from(__format: _FmtType, buffer: _BufferType, offset: int = ...) -> Tuple[Any, ...]: ... +def unpack(__format: _FmtType, __buffer: _BufferType) -> tuple[Any, ...]: ... +def unpack_from(__format: _FmtType, buffer: _BufferType, offset: int = ...) -> tuple[Any, ...]: ... def calcsize(__format: _FmtType) -> int: ... class Struct: @@ -20,5 +20,5 @@ class Struct: def __init__(self, format: _FmtType) -> None: ... def pack(self, *v: Any) -> bytes: ... def pack_into(self, buffer: _WriteBufferType, offset: int, *v: Any) -> None: ... - def unpack(self, __buffer: _BufferType) -> Tuple[Any, ...]: ... - def unpack_from(self, buffer: _BufferType, offset: int = ...) -> Tuple[Any, ...]: ... + def unpack(self, __buffer: _BufferType) -> tuple[Any, ...]: ... + def unpack_from(self, buffer: _BufferType, offset: int = ...) -> tuple[Any, ...]: ... diff --git a/mypy/typeshed/stdlib/@python2/subprocess.pyi b/mypy/typeshed/stdlib/@python2/subprocess.pyi index 8c101272322a4..e6ab3dfcbb734 100644 --- a/mypy/typeshed/stdlib/@python2/subprocess.pyi +++ b/mypy/typeshed/stdlib/@python2/subprocess.pyi @@ -1,9 +1,9 @@ -from typing import IO, Any, Callable, Generic, Mapping, Optional, Sequence, Text, Tuple, TypeVar, Union +from typing import IO, Any, Callable, Generic, Mapping, Sequence, Text, TypeVar -_FILE = Union[None, int, IO[Any]] -_TXT = Union[bytes, Text] -_CMD = Union[_TXT, Sequence[_TXT]] -_ENV = Union[Mapping[bytes, _TXT], Mapping[Text, _TXT]] +_FILE = None | int | IO[Any] +_TXT = bytes | Text +_CMD = _TXT | Sequence[_TXT] +_ENV = Mapping[bytes, _TXT] | Mapping[Text, _TXT] # Same args as Popen.__init__ def call( @@ -96,7 +96,7 @@ class Popen(Generic[_T]): def poll(self) -> int | None: ... def wait(self) -> int: ... # morally: -> Tuple[Optional[bytes], Optional[bytes]] - def communicate(self, input: _TXT | None = ...) -> Tuple[bytes, bytes]: ... + def communicate(self, input: _TXT | None = ...) -> tuple[bytes, bytes]: ... def send_signal(self, signal: int) -> None: ... def terminate(self) -> None: ... def kill(self) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/sunau.pyi b/mypy/typeshed/stdlib/@python2/sunau.pyi index 3ee4b9651346a..85b4d12b4d8a8 100644 --- a/mypy/typeshed/stdlib/@python2/sunau.pyi +++ b/mypy/typeshed/stdlib/@python2/sunau.pyi @@ -1,6 +1,6 @@ -from typing import IO, Any, NoReturn, Text, Tuple, Union +from typing import IO, Any, NoReturn, Text -_File = Union[Text, IO[bytes]] +_File = Text | IO[bytes] class Error(Exception): ... @@ -19,7 +19,7 @@ AUDIO_FILE_ENCODING_ADPCM_G723_5: int AUDIO_FILE_ENCODING_ALAW_8: int AUDIO_UNKNOWN_SIZE: int -_sunau_params = Tuple[int, int, int, int, str, str] +_sunau_params = tuple[int, int, int, int, str, str] class Au_read: def __init__(self, f: _File) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/symbol.pyi b/mypy/typeshed/stdlib/@python2/symbol.pyi index a3561fe6b26f2..052e3f1f8f423 100644 --- a/mypy/typeshed/stdlib/@python2/symbol.pyi +++ b/mypy/typeshed/stdlib/@python2/symbol.pyi @@ -1,5 +1,3 @@ -from typing import Dict - single_input: int file_input: int eval_input: int @@ -86,4 +84,4 @@ testlist1: int encoding_decl: int yield_expr: int -sym_name: Dict[int, str] +sym_name: dict[int, str] diff --git a/mypy/typeshed/stdlib/@python2/symtable.pyi b/mypy/typeshed/stdlib/@python2/symtable.pyi index bd3f25c7cb637..c0b701cc1df5f 100644 --- a/mypy/typeshed/stdlib/@python2/symtable.pyi +++ b/mypy/typeshed/stdlib/@python2/symtable.pyi @@ -1,4 +1,4 @@ -from typing import Any, List, Sequence, Text, Tuple +from typing import Any, Sequence, Text def symtable(code: Text, filename: Text, compile_type: Text) -> SymbolTable: ... @@ -15,17 +15,17 @@ class SymbolTable(object): def has_import_star(self) -> bool: ... def get_identifiers(self) -> Sequence[str]: ... def lookup(self, name: str) -> Symbol: ... - def get_symbols(self) -> List[Symbol]: ... - def get_children(self) -> List[SymbolTable]: ... + def get_symbols(self) -> list[Symbol]: ... + def get_children(self) -> list[SymbolTable]: ... class Function(SymbolTable): - def get_parameters(self) -> Tuple[str, ...]: ... - def get_locals(self) -> Tuple[str, ...]: ... - def get_globals(self) -> Tuple[str, ...]: ... - def get_frees(self) -> Tuple[str, ...]: ... + def get_parameters(self) -> tuple[str, ...]: ... + def get_locals(self) -> tuple[str, ...]: ... + def get_globals(self) -> tuple[str, ...]: ... + def get_frees(self) -> tuple[str, ...]: ... class Class(SymbolTable): - def get_methods(self) -> Tuple[str, ...]: ... + def get_methods(self) -> tuple[str, ...]: ... class Symbol(object): def __init__(self, name: str, flags: int, namespaces: Sequence[SymbolTable] | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/sys.pyi b/mypy/typeshed/stdlib/@python2/sys.pyi index d4858ec251fa4..409b776cdcb01 100644 --- a/mypy/typeshed/stdlib/@python2/sys.pyi +++ b/mypy/typeshed/stdlib/@python2/sys.pyi @@ -1,9 +1,9 @@ from types import ClassType, FrameType, TracebackType -from typing import IO, Any, Callable, Dict, List, NoReturn, Text, Tuple, Type, Union +from typing import IO, Any, Callable, NoReturn, Text, Union # The following type alias are stub-only and do not exist during runtime -_ExcInfo = Tuple[Type[BaseException], BaseException, TracebackType] -_OptExcInfo = Union[_ExcInfo, Tuple[None, None, None]] +_ExcInfo = tuple[type[BaseException], BaseException, TracebackType] +_OptExcInfo = Union[_ExcInfo, tuple[None, None, None]] class _flags: bytes_warning: int @@ -36,17 +36,17 @@ class _float_info: radix: int rounds: int -class _version_info(Tuple[int, int, int, str, int]): +class _version_info(tuple[int, int, int, str, int]): major: int minor: int micro: int releaselevel: str serial: int -_mercurial: Tuple[str, str, str] +_mercurial: tuple[str, str, str] api_version: int -argv: List[str] -builtin_module_names: Tuple[str, ...] +argv: list[str] +builtin_module_names: tuple[str, ...] byteorder: str copyright: str dont_write_bytecode: bool @@ -59,8 +59,8 @@ long_info: object maxint: int maxsize: int maxunicode: int -modules: Dict[str, Any] -path: List[str] +modules: dict[str, Any] +path: list[str] platform: str prefix: str py3kwarning: bool @@ -70,7 +70,7 @@ __stdout__: IO[str] stderr: IO[str] stdin: IO[str] stdout: IO[str] -subversion: Tuple[str, str, str] +subversion: tuple[str, str, str] version: str warnoptions: object float_info: _float_info @@ -81,11 +81,11 @@ last_type: type last_value: BaseException last_traceback: TracebackType # TODO precise types -meta_path: List[Any] -path_hooks: List[Any] -path_importer_cache: Dict[str, Any] +meta_path: list[Any] +path_hooks: list[Any] +path_importer_cache: dict[str, Any] displayhook: Callable[[object], Any] -excepthook: Callable[[Type[BaseException], BaseException, TracebackType], Any] +excepthook: Callable[[type[BaseException], BaseException, TracebackType], Any] exc_type: type | None exc_value: BaseException | ClassType exc_traceback: TracebackType @@ -103,7 +103,7 @@ class _WindowsVersionType: def getwindowsversion() -> _WindowsVersionType: ... def _clear_type_cache() -> None: ... -def _current_frames() -> Dict[int, FrameType]: ... +def _current_frames() -> dict[int, FrameType]: ... def _getframe(depth: int = ...) -> FrameType: ... def call_tracing(fn: Any, args: Any) -> Any: ... def __displayhook__(value: object) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/sysconfig.pyi b/mypy/typeshed/stdlib/@python2/sysconfig.pyi index 2bef9e467bc93..17077144f6e98 100644 --- a/mypy/typeshed/stdlib/@python2/sysconfig.pyi +++ b/mypy/typeshed/stdlib/@python2/sysconfig.pyi @@ -1,17 +1,17 @@ -from typing import IO, Any, Dict, List, Tuple, overload +from typing import IO, Any, overload def get_config_var(name: str) -> str | None: ... @overload -def get_config_vars() -> Dict[str, Any]: ... +def get_config_vars() -> dict[str, Any]: ... @overload -def get_config_vars(arg: str, *args: str) -> List[Any]: ... -def get_scheme_names() -> Tuple[str, ...]: ... -def get_path_names() -> Tuple[str, ...]: ... -def get_path(name: str, scheme: str = ..., vars: Dict[str, Any] | None = ..., expand: bool = ...) -> str: ... -def get_paths(scheme: str = ..., vars: Dict[str, Any] | None = ..., expand: bool = ...) -> Dict[str, str]: ... +def get_config_vars(arg: str, *args: str) -> list[Any]: ... +def get_scheme_names() -> tuple[str, ...]: ... +def get_path_names() -> tuple[str, ...]: ... +def get_path(name: str, scheme: str = ..., vars: dict[str, Any] | None = ..., expand: bool = ...) -> str: ... +def get_paths(scheme: str = ..., vars: dict[str, Any] | None = ..., expand: bool = ...) -> dict[str, str]: ... def get_python_version() -> str: ... def get_platform() -> str: ... def is_python_build(check_home: bool = ...) -> bool: ... -def parse_config_h(fp: IO[Any], vars: Dict[str, Any] | None = ...) -> Dict[str, Any]: ... +def parse_config_h(fp: IO[Any], vars: dict[str, Any] | None = ...) -> dict[str, Any]: ... def get_config_h_filename() -> str: ... def get_makefile_filename() -> str: ... diff --git a/mypy/typeshed/stdlib/@python2/tabnanny.pyi b/mypy/typeshed/stdlib/@python2/tabnanny.pyi index 95873761ee757..cf6eefc2e15f9 100644 --- a/mypy/typeshed/stdlib/@python2/tabnanny.pyi +++ b/mypy/typeshed/stdlib/@python2/tabnanny.pyi @@ -1,4 +1,4 @@ -from typing import Iterable, Text, Tuple +from typing import Iterable, Text verbose: int filename_only: int @@ -10,4 +10,4 @@ class NannyNag(Exception): def get_line(self) -> str: ... def check(file: Text) -> None: ... -def process_tokens(tokens: Iterable[Tuple[int, str, Tuple[int, int], Tuple[int, int], str]]) -> None: ... +def process_tokens(tokens: Iterable[tuple[int, str, tuple[int, int], tuple[int, int], str]]) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/tarfile.pyi b/mypy/typeshed/stdlib/@python2/tarfile.pyi index c08c96b6f0d5e..571bb19632a88 100644 --- a/mypy/typeshed/stdlib/@python2/tarfile.pyi +++ b/mypy/typeshed/stdlib/@python2/tarfile.pyi @@ -1,6 +1,7 @@ import io +from _typeshed import Self from types import TracebackType -from typing import IO, Callable, Dict, Iterable, Iterator, List, Mapping, Text, Tuple, Type +from typing import IO, Callable, Iterable, Iterator, Mapping, Text # tar constants NUL: bytes @@ -38,11 +39,11 @@ DEFAULT_FORMAT: int # tarfile constants -SUPPORTED_TYPES: Tuple[bytes, ...] -REGULAR_TYPES: Tuple[bytes, ...] -GNU_TYPES: Tuple[bytes, ...] -PAX_FIELDS: Tuple[str, ...] -PAX_NUMBER_FIELDS: Dict[str, type] +SUPPORTED_TYPES: tuple[bytes, ...] +REGULAR_TYPES: tuple[bytes, ...] +GNU_TYPES: tuple[bytes, ...] +PAX_FIELDS: tuple[str, ...] +PAX_NUMBER_FIELDS: dict[str, type] ENCODING: str @@ -56,7 +57,7 @@ def open( bufsize: int = ..., *, format: int | None = ..., - tarinfo: Type[TarInfo] | None = ..., + tarinfo: type[TarInfo] | None = ..., dereference: bool | None = ..., ignore_zeros: bool | None = ..., encoding: str | None = ..., @@ -76,12 +77,12 @@ class TarFile(Iterable[TarInfo]): mode: str fileobj: IO[bytes] | None format: int | None - tarinfo: Type[TarInfo] + tarinfo: type[TarInfo] dereference: bool | None ignore_zeros: bool | None encoding: str | None errors: str - fileobject: Type[ExFileObject] + fileobject: type[ExFileObject] pax_headers: Mapping[str, str] | None debug: int | None errorlevel: int | None @@ -93,7 +94,7 @@ class TarFile(Iterable[TarInfo]): mode: str = ..., fileobj: IO[bytes] | None = ..., format: int | None = ..., - tarinfo: Type[TarInfo] | None = ..., + tarinfo: type[TarInfo] | None = ..., dereference: bool | None = ..., ignore_zeros: bool | None = ..., encoding: str | None = ..., @@ -103,9 +104,9 @@ class TarFile(Iterable[TarInfo]): errorlevel: int | None = ..., copybufsize: int | None = ..., # undocumented ) -> None: ... - def __enter__(self) -> TarFile: ... + def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> None: ... def __iter__(self) -> Iterator[TarInfo]: ... @classmethod @@ -117,7 +118,7 @@ class TarFile(Iterable[TarInfo]): bufsize: int = ..., *, format: int | None = ..., - tarinfo: Type[TarInfo] | None = ..., + tarinfo: type[TarInfo] | None = ..., dereference: bool | None = ..., ignore_zeros: bool | None = ..., encoding: str | None = ..., @@ -135,7 +136,7 @@ class TarFile(Iterable[TarInfo]): *, compresslevel: int = ..., format: int | None = ..., - tarinfo: Type[TarInfo] | None = ..., + tarinfo: type[TarInfo] | None = ..., dereference: bool | None = ..., ignore_zeros: bool | None = ..., encoding: str | None = ..., @@ -152,7 +153,7 @@ class TarFile(Iterable[TarInfo]): compresslevel: int = ..., *, format: int | None = ..., - tarinfo: Type[TarInfo] | None = ..., + tarinfo: type[TarInfo] | None = ..., dereference: bool | None = ..., ignore_zeros: bool | None = ..., encoding: str | None = ..., @@ -169,7 +170,7 @@ class TarFile(Iterable[TarInfo]): compresslevel: int = ..., *, format: int | None = ..., - tarinfo: Type[TarInfo] | None = ..., + tarinfo: type[TarInfo] | None = ..., dereference: bool | None = ..., ignore_zeros: bool | None = ..., encoding: str | None = ..., @@ -186,7 +187,7 @@ class TarFile(Iterable[TarInfo]): preset: int | None = ..., *, format: int | None = ..., - tarinfo: Type[TarInfo] | None = ..., + tarinfo: type[TarInfo] | None = ..., dereference: bool | None = ..., ignore_zeros: bool | None = ..., encoding: str | None = ..., @@ -195,8 +196,8 @@ class TarFile(Iterable[TarInfo]): errorlevel: int | None = ..., ) -> TarFile: ... def getmember(self, name: str) -> TarInfo: ... - def getmembers(self) -> List[TarInfo]: ... - def getnames(self) -> List[str]: ... + def getmembers(self) -> list[TarInfo]: ... + def getnames(self) -> list[str]: ... def list(self, verbose: bool = ...) -> None: ... def next(self) -> TarInfo | None: ... def extractall(self, path: Text = ..., members: Iterable[TarInfo] | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/telnetlib.pyi b/mypy/typeshed/stdlib/@python2/telnetlib.pyi index dfb01f26398ea..5cd47e28a95c2 100644 --- a/mypy/typeshed/stdlib/@python2/telnetlib.pyi +++ b/mypy/typeshed/stdlib/@python2/telnetlib.pyi @@ -1,5 +1,5 @@ import socket -from typing import Any, Callable, Match, Pattern, Sequence, Tuple +from typing import Any, Callable, Match, Pattern, Sequence DEBUGLEVEL: int TELNET_PORT: int @@ -108,4 +108,4 @@ class Telnet: def listener(self) -> None: ... def expect( self, list: Sequence[Pattern[bytes] | bytes], timeout: float | None = ... - ) -> Tuple[int, Match[bytes] | None, bytes]: ... + ) -> tuple[int, Match[bytes] | None, bytes]: ... diff --git a/mypy/typeshed/stdlib/@python2/tempfile.pyi b/mypy/typeshed/stdlib/@python2/tempfile.pyi index c5f67d243ac87..3d94bdefeb74a 100644 --- a/mypy/typeshed/stdlib/@python2/tempfile.pyi +++ b/mypy/typeshed/stdlib/@python2/tempfile.pyi @@ -1,6 +1,7 @@ +from _typeshed import Self from random import Random from thread import LockType -from typing import IO, Any, AnyStr, Iterable, Iterator, List, Text, Tuple, overload +from typing import IO, Any, AnyStr, Iterable, Iterator, Text, overload TMP_MAX: int tempdir: str @@ -23,7 +24,7 @@ class _TemporaryFileWrapper(IO[str]): name: Any def __init__(self, file: IO[str], name: Any, delete: bool = ...) -> None: ... def __del__(self) -> None: ... - def __enter__(self) -> _TemporaryFileWrapper: ... + def __enter__(self: Self) -> Self: ... def __exit__(self, exc, value, tb) -> bool | None: ... def __getattr__(self, name: unicode) -> Any: ... def close(self) -> None: ... @@ -39,7 +40,7 @@ class _TemporaryFileWrapper(IO[str]): def read(self, n: int = ...) -> str: ... def readable(self) -> bool: ... def readline(self, limit: int = ...) -> str: ... - def readlines(self, hint: int = ...) -> List[str]: ... + def readlines(self, hint: int = ...) -> list[str]: ... def seek(self, offset: int, whence: int = ...) -> int: ... def seekable(self) -> bool: ... def tell(self) -> int: ... @@ -82,9 +83,9 @@ class TemporaryDirectory: def __exit__(self, type, value, traceback) -> None: ... @overload -def mkstemp() -> Tuple[int, str]: ... +def mkstemp() -> tuple[int, str]: ... @overload -def mkstemp(suffix: AnyStr = ..., prefix: AnyStr = ..., dir: AnyStr | None = ..., text: bool = ...) -> Tuple[int, AnyStr]: ... +def mkstemp(suffix: AnyStr = ..., prefix: AnyStr = ..., dir: AnyStr | None = ..., text: bool = ...) -> tuple[int, AnyStr]: ... @overload def mkdtemp() -> str: ... @overload @@ -95,6 +96,6 @@ def mktemp() -> str: ... def mktemp(suffix: AnyStr = ..., prefix: AnyStr = ..., dir: AnyStr | None = ...) -> AnyStr: ... def gettempdir() -> str: ... def gettempprefix() -> str: ... -def _candidate_tempdir_list() -> List[str]: ... +def _candidate_tempdir_list() -> list[str]: ... def _get_candidate_names() -> _RandomNameSequence | None: ... def _get_default_tempdir() -> str: ... diff --git a/mypy/typeshed/stdlib/@python2/termios.pyi b/mypy/typeshed/stdlib/@python2/termios.pyi index cee6b85f9ba57..c6a90df31b591 100644 --- a/mypy/typeshed/stdlib/@python2/termios.pyi +++ b/mypy/typeshed/stdlib/@python2/termios.pyi @@ -1,9 +1,9 @@ import sys from _typeshed import FileDescriptorLike -from typing import Any, List, Union +from typing import Any if sys.platform != "win32": - _Attr = List[Union[int, List[Union[bytes, int]]]] + _Attr = list[int | list[bytes | int]] # TODO constants not really documented B0: int @@ -237,10 +237,11 @@ if sys.platform != "win32": VWERASE: int XCASE: int XTABS: int - def tcgetattr(__fd: FileDescriptorLike) -> List[Any]: ... + def tcgetattr(__fd: FileDescriptorLike) -> list[Any]: ... def tcsetattr(__fd: FileDescriptorLike, __when: int, __attributes: _Attr) -> None: ... def tcsendbreak(__fd: FileDescriptorLike, __duration: int) -> None: ... def tcdrain(__fd: FileDescriptorLike) -> None: ... def tcflush(__fd: FileDescriptorLike, __queue: int) -> None: ... def tcflow(__fd: FileDescriptorLike, __action: int) -> None: ... + class error(Exception): ... diff --git a/mypy/typeshed/stdlib/@python2/textwrap.pyi b/mypy/typeshed/stdlib/@python2/textwrap.pyi index c4147b4bd5387..cb9c034cc4ba6 100644 --- a/mypy/typeshed/stdlib/@python2/textwrap.pyi +++ b/mypy/typeshed/stdlib/@python2/textwrap.pyi @@ -1,4 +1,4 @@ -from typing import AnyStr, Dict, List, Pattern +from typing import AnyStr, Pattern class TextWrapper(object): width: int = ... @@ -16,7 +16,7 @@ class TextWrapper(object): wordsep_re: Pattern[str] = ... wordsep_simple_re: Pattern[str] = ... whitespace_trans: str = ... - unicode_whitespace_trans: Dict[int, int] = ... + unicode_whitespace_trans: dict[int, int] = ... uspace: int = ... x: int = ... def __init__( @@ -31,7 +31,7 @@ class TextWrapper(object): drop_whitespace: bool = ..., break_on_hyphens: bool = ..., ) -> None: ... - def wrap(self, text: AnyStr) -> List[AnyStr]: ... + def wrap(self, text: AnyStr) -> list[AnyStr]: ... def fill(self, text: AnyStr) -> AnyStr: ... def wrap( @@ -45,7 +45,7 @@ def wrap( break_long_words: bool = ..., drop_whitespace: bool = ..., break_on_hyphens: bool = ..., -) -> List[AnyStr]: ... +) -> list[AnyStr]: ... def fill( text: AnyStr, width: int = ..., diff --git a/mypy/typeshed/stdlib/@python2/this.pyi b/mypy/typeshed/stdlib/@python2/this.pyi index 0687a6675ccad..8de996b04aeca 100644 --- a/mypy/typeshed/stdlib/@python2/this.pyi +++ b/mypy/typeshed/stdlib/@python2/this.pyi @@ -1,4 +1,2 @@ -from typing import Dict - s: str -d: Dict[str, str] +d: dict[str, str] diff --git a/mypy/typeshed/stdlib/@python2/thread.pyi b/mypy/typeshed/stdlib/@python2/thread.pyi index b3ba062a498e0..9823dddcbfd7d 100644 --- a/mypy/typeshed/stdlib/@python2/thread.pyi +++ b/mypy/typeshed/stdlib/@python2/thread.pyi @@ -1,9 +1,11 @@ from typing import Any, Callable +from typing_extensions import final def _count() -> int: ... class error(Exception): ... +@final class LockType: def acquire(self, waitflag: int = ...) -> bool: ... def acquire_lock(self, waitflag: int = ...) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/threading.pyi b/mypy/typeshed/stdlib/@python2/threading.pyi index e45a1b5c4a894..b62b3a121b802 100644 --- a/mypy/typeshed/stdlib/@python2/threading.pyi +++ b/mypy/typeshed/stdlib/@python2/threading.pyi @@ -1,19 +1,36 @@ from types import FrameType, TracebackType -from typing import Any, Callable, Iterable, List, Mapping, Optional, Text, Type, TypeVar +from typing import Any, Callable, Iterable, Mapping, Text, TypeVar # TODO recursive type -_TF = Callable[[FrameType, str, Any], Optional[Callable[..., Any]]] +_TF = Callable[[FrameType, str, Any], Callable[..., Any] | None] _PF = Callable[[FrameType, str, Any], None] -_T = TypeVar("_T") -__all__: List[str] +__all__ = [ + "activeCount", + "active_count", + "Condition", + "currentThread", + "current_thread", + "enumerate", + "Event", + "Lock", + "RLock", + "Semaphore", + "BoundedSemaphore", + "Thread", + "Timer", + "setprofile", + "settrace", + "local", + "stack_size", +] def active_count() -> int: ... def activeCount() -> int: ... def current_thread() -> Thread: ... def currentThread() -> Thread: ... -def enumerate() -> List[Thread]: ... +def enumerate() -> list[Thread]: ... def settrace(func: _TF) -> None: ... def setprofile(func: _PF | None) -> None: ... def stack_size(size: int = ...) -> int: ... @@ -53,7 +70,7 @@ class Lock: def __init__(self) -> None: ... def __enter__(self) -> bool: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> bool | None: ... def acquire(self, blocking: bool = ...) -> bool: ... def release(self) -> None: ... @@ -63,7 +80,7 @@ class _RLock: def __init__(self) -> None: ... def __enter__(self) -> bool: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> bool | None: ... def acquire(self, blocking: bool = ...) -> bool: ... def release(self) -> None: ... @@ -74,7 +91,7 @@ class Condition: def __init__(self, lock: Lock | _RLock | None = ...) -> None: ... def __enter__(self) -> bool: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> bool | None: ... def acquire(self, blocking: bool = ...) -> bool: ... def release(self) -> None: ... @@ -86,7 +103,7 @@ class Condition: class Semaphore: def __init__(self, value: int = ...) -> None: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> bool | None: ... def acquire(self, blocking: bool = ...) -> bool: ... def __enter__(self, blocking: bool = ...) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/time.pyi b/mypy/typeshed/stdlib/@python2/time.pyi index 48ae9da9c65ef..93cdafa7cafa8 100644 --- a/mypy/typeshed/stdlib/@python2/time.pyi +++ b/mypy/typeshed/stdlib/@python2/time.pyi @@ -1,13 +1,14 @@ import sys -from typing import Any, NamedTuple, Tuple +from typing import Any, NamedTuple +from typing_extensions import final -_TimeTuple = Tuple[int, int, int, int, int, int, int, int, int] +_TimeTuple = tuple[int, int, int, int, int, int, int, int, int] accept2dyear: bool altzone: int daylight: int timezone: int -tzname: Tuple[str, str] +tzname: tuple[str, str] class _struct_time(NamedTuple): tm_year: int @@ -26,6 +27,7 @@ class _struct_time(NamedTuple): @property def n_unnamed_fields(self) -> int: ... +@final class struct_time(_struct_time): def __init__(self, o: _TimeTuple, _arg: Any = ...) -> None: ... def __new__(cls, o: _TimeTuple, _arg: Any = ...) -> struct_time: ... diff --git a/mypy/typeshed/stdlib/@python2/timeit.pyi b/mypy/typeshed/stdlib/@python2/timeit.pyi index ecb528725a9c1..b95c89fa312df 100644 --- a/mypy/typeshed/stdlib/@python2/timeit.pyi +++ b/mypy/typeshed/stdlib/@python2/timeit.pyi @@ -1,8 +1,8 @@ -from typing import IO, Any, Callable, List, Sequence, Text, Union +from typing import IO, Any, Callable, Sequence, Text -_str = Union[str, Text] +_str = str | Text _Timer = Callable[[], float] -_stmt = Union[_str, Callable[[], Any]] +_stmt = _str | Callable[[], Any] default_timer: _Timer @@ -10,10 +10,10 @@ class Timer: def __init__(self, stmt: _stmt = ..., setup: _stmt = ..., timer: _Timer = ...) -> None: ... def print_exc(self, file: IO[str] | None = ...) -> None: ... def timeit(self, number: int = ...) -> float: ... - def repeat(self, repeat: int = ..., number: int = ...) -> List[float]: ... + def repeat(self, repeat: int = ..., number: int = ...) -> list[float]: ... def timeit(stmt: _stmt = ..., setup: _stmt = ..., timer: _Timer = ..., number: int = ...) -> float: ... -def repeat(stmt: _stmt = ..., setup: _stmt = ..., timer: _Timer = ..., repeat: int = ..., number: int = ...) -> List[float]: ... +def repeat(stmt: _stmt = ..., setup: _stmt = ..., timer: _Timer = ..., repeat: int = ..., number: int = ...) -> list[float]: ... _timerFunc = Callable[[], float] diff --git a/mypy/typeshed/stdlib/@python2/toaiff.pyi b/mypy/typeshed/stdlib/@python2/toaiff.pyi index b70e026d6d8ef..d4b86f9bb7566 100644 --- a/mypy/typeshed/stdlib/@python2/toaiff.pyi +++ b/mypy/typeshed/stdlib/@python2/toaiff.pyi @@ -1,11 +1,10 @@ from pipes import Template -from typing import Dict, List -table: Dict[str, Template] +table: dict[str, Template] t: Template uncompress: Template class error(Exception): ... def toaiff(filename: str) -> str: ... -def _toaiff(filename: str, temps: List[str]) -> str: ... +def _toaiff(filename: str, temps: list[str]) -> str: ... diff --git a/mypy/typeshed/stdlib/@python2/token.pyi b/mypy/typeshed/stdlib/@python2/token.pyi index 4ba7104706245..d88aba8678a06 100644 --- a/mypy/typeshed/stdlib/@python2/token.pyi +++ b/mypy/typeshed/stdlib/@python2/token.pyi @@ -1,5 +1,3 @@ -from typing import Dict - ENDMARKER: int NAME: int NUMBER: int @@ -55,7 +53,7 @@ OP: int ERRORTOKEN: int N_TOKENS: int NT_OFFSET: int -tok_name: Dict[int, str] +tok_name: dict[int, str] def ISTERMINAL(x: int) -> bool: ... def ISNONTERMINAL(x: int) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/tokenize.pyi b/mypy/typeshed/stdlib/@python2/tokenize.pyi index 98ec01a6cb75a..f045f76cc39ee 100644 --- a/mypy/typeshed/stdlib/@python2/tokenize.pyi +++ b/mypy/typeshed/stdlib/@python2/tokenize.pyi @@ -1,4 +1,4 @@ -from typing import Any, Callable, Dict, Generator, Iterable, Iterator, List, Tuple +from typing import Any, Callable, Generator, Iterable, Iterator __author__: str __credits__: str @@ -97,27 +97,27 @@ VBAREQUAL: int Whitespace: str chain: type double3prog: type -endprogs: Dict[str, Any] +endprogs: dict[str, Any] pseudoprog: type single3prog: type -single_quoted: Dict[str, str] +single_quoted: dict[str, str] t: str tabsize: int -tok_name: Dict[int, str] +tok_name: dict[int, str] tokenprog: type -triple_quoted: Dict[str, str] +triple_quoted: dict[str, str] x: str -_Pos = Tuple[int, int] -_TokenType = Tuple[int, str, _Pos, _Pos, str] +_Pos = tuple[int, int] +_TokenType = tuple[int, str, _Pos, _Pos, str] def any(*args, **kwargs) -> str: ... def generate_tokens(readline: Callable[[], str]) -> Generator[_TokenType, None, None]: ... def group(*args: str) -> str: ... def maybe(*args: str) -> str: ... def printtoken(type: int, token: str, srow_scol: _Pos, erow_ecol: _Pos, line: str) -> None: ... -def tokenize(readline: Callable[[], str], tokeneater: Callable[[Tuple[int, str, _Pos, _Pos, str]], None]) -> None: ... -def tokenize_loop(readline: Callable[[], str], tokeneater: Callable[[Tuple[int, str, _Pos, _Pos, str]], None]) -> None: ... +def tokenize(readline: Callable[[], str], tokeneater: Callable[[tuple[int, str, _Pos, _Pos, str]], None]) -> None: ... +def tokenize_loop(readline: Callable[[], str], tokeneater: Callable[[tuple[int, str, _Pos, _Pos, str]], None]) -> None: ... def untokenize(iterable: Iterable[_TokenType]) -> str: ... class StopTokenizing(Exception): ... @@ -126,8 +126,8 @@ class TokenError(Exception): ... class Untokenizer: prev_col: int prev_row: int - tokens: List[str] + tokens: list[str] def __init__(self) -> None: ... def add_whitespace(self, _Pos) -> None: ... - def compat(self, token: Tuple[int, Any], iterable: Iterator[_TokenType]) -> None: ... + def compat(self, token: tuple[int, Any], iterable: Iterator[_TokenType]) -> None: ... def untokenize(self, iterable: Iterable[_TokenType]) -> str: ... diff --git a/mypy/typeshed/stdlib/@python2/trace.pyi b/mypy/typeshed/stdlib/@python2/trace.pyi index 62f228673a554..ea9dfba5bb834 100644 --- a/mypy/typeshed/stdlib/@python2/trace.pyi +++ b/mypy/typeshed/stdlib/@python2/trace.pyi @@ -1,25 +1,27 @@ import types from _typeshed import StrPath -from typing import Any, Callable, Dict, Mapping, Optional, Sequence, Tuple, TypeVar +from typing import Any, Callable, Mapping, Sequence, TypeVar +from typing_extensions import ParamSpec _T = TypeVar("_T") +_P = ParamSpec("_P") _localtrace = Callable[[types.FrameType, str, Any], Callable[..., Any]] -_fileModuleFunction = Tuple[str, Optional[str], str] +_fileModuleFunction = tuple[str, str | None, str] class CoverageResults: def __init__( self, - counts: Dict[Tuple[str, int], int] | None = ..., - calledfuncs: Dict[_fileModuleFunction, int] | None = ..., + counts: dict[tuple[str, int], int] | None = ..., + calledfuncs: dict[_fileModuleFunction, int] | None = ..., infile: StrPath | None = ..., - callers: Dict[Tuple[_fileModuleFunction, _fileModuleFunction], int] | None = ..., + callers: dict[tuple[_fileModuleFunction, _fileModuleFunction], int] | None = ..., outfile: StrPath | None = ..., ) -> None: ... # undocumented def update(self, other: CoverageResults) -> None: ... def write_results(self, show_missing: bool = ..., summary: bool = ..., coverdir: StrPath | None = ...) -> None: ... def write_results_file( self, path: StrPath, lines: Sequence[str], lnotab: Any, lines_hit: Mapping[int, int], encoding: str | None = ... - ) -> Tuple[int, int]: ... + ) -> tuple[int, int]: ... class Trace: def __init__( @@ -38,7 +40,7 @@ class Trace: def runctx( self, cmd: str | types.CodeType, globals: Mapping[str, Any] | None = ..., locals: Mapping[str, Any] | None = ... ) -> None: ... - def runfunc(self, func: Callable[..., _T], *args: Any, **kw: Any) -> _T: ... + def runfunc(self, func: Callable[_P, _T], *args: _P.args, **kw: _P.kwargs) -> _T: ... def file_module_function_of(self, frame: types.FrameType) -> _fileModuleFunction: ... def globaltrace_trackcallers(self, frame: types.FrameType, why: str, arg: Any) -> None: ... def globaltrace_countfuncs(self, frame: types.FrameType, why: str, arg: Any) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/traceback.pyi b/mypy/typeshed/stdlib/@python2/traceback.pyi index 2152ab2559423..34fc00ed7daad 100644 --- a/mypy/typeshed/stdlib/@python2/traceback.pyi +++ b/mypy/typeshed/stdlib/@python2/traceback.pyi @@ -1,11 +1,11 @@ from types import FrameType, TracebackType -from typing import IO, List, Optional, Tuple, Type +from typing import IO -_PT = Tuple[str, int, str, Optional[str]] +_PT = tuple[str, int, str, str | None] def print_tb(tb: TracebackType | None, limit: int | None = ..., file: IO[str] | None = ...) -> None: ... def print_exception( - etype: Type[BaseException] | None, + etype: type[BaseException] | None, value: BaseException | None, tb: TracebackType | None, limit: int | None = ..., @@ -14,14 +14,14 @@ def print_exception( def print_exc(limit: int | None = ..., file: IO[str] | None = ...) -> None: ... def print_last(limit: int | None = ..., file: IO[str] | None = ...) -> None: ... def print_stack(f: FrameType | None = ..., limit: int | None = ..., file: IO[str] | None = ...) -> None: ... -def extract_tb(tb: TracebackType | None, limit: int | None = ...) -> List[_PT]: ... -def extract_stack(f: FrameType | None = ..., limit: int | None = ...) -> List[_PT]: ... -def format_list(extracted_list: List[_PT]) -> List[str]: ... -def format_exception_only(etype: Type[BaseException] | None, value: BaseException | None) -> List[str]: ... +def extract_tb(tb: TracebackType | None, limit: int | None = ...) -> list[_PT]: ... +def extract_stack(f: FrameType | None = ..., limit: int | None = ...) -> list[_PT]: ... +def format_list(extracted_list: list[_PT]) -> list[str]: ... +def format_exception_only(etype: type[BaseException] | None, value: BaseException | None) -> list[str]: ... def format_exception( - etype: Type[BaseException] | None, value: BaseException | None, tb: TracebackType | None, limit: int | None = ... -) -> List[str]: ... + etype: type[BaseException] | None, value: BaseException | None, tb: TracebackType | None, limit: int | None = ... +) -> list[str]: ... def format_exc(limit: int | None = ...) -> str: ... -def format_tb(tb: TracebackType | None, limit: int | None = ...) -> List[str]: ... -def format_stack(f: FrameType | None = ..., limit: int | None = ...) -> List[str]: ... +def format_tb(tb: TracebackType | None, limit: int | None = ...) -> list[str]: ... +def format_stack(f: FrameType | None = ..., limit: int | None = ...) -> list[str]: ... def tb_lineno(tb: TracebackType) -> int: ... diff --git a/mypy/typeshed/stdlib/@python2/tty.pyi b/mypy/typeshed/stdlib/@python2/tty.pyi index 56e85108c75ee..fc7e90bc0ff9d 100644 --- a/mypy/typeshed/stdlib/@python2/tty.pyi +++ b/mypy/typeshed/stdlib/@python2/tty.pyi @@ -1,7 +1,7 @@ import sys -from typing import IO, Union +from typing import IO -_FD = Union[int, IO[str]] +_FD = int | IO[str] if sys.platform != "win32": # XXX: Undocumented integer constants diff --git a/mypy/typeshed/stdlib/@python2/turtle.pyi b/mypy/typeshed/stdlib/@python2/turtle.pyi index 659dfd31b1616..037b9851381f6 100644 --- a/mypy/typeshed/stdlib/@python2/turtle.pyi +++ b/mypy/typeshed/stdlib/@python2/turtle.pyi @@ -1,4 +1,5 @@ -from typing import Any, Callable, Dict, List, Sequence, Text, Tuple, TypeVar, Union, overload +from _typeshed import Self +from typing import Any, Callable, Sequence, Text, Union, overload # TODO: Replace these aliases once we have Python 2 stubs for the Tkinter module. Canvas = Any @@ -8,18 +9,18 @@ PhotoImage = Any # alias we use for return types. Really, these two aliases should be the # same, but as per the "no union returns" typeshed policy, we'll return # Any instead. -_Color = Union[Text, Tuple[float, float, float]] +_Color = Union[Text, tuple[float, float, float]] _AnyColor = Any # TODO: Replace this with a TypedDict once it becomes standardized. -_PenState = Dict[str, Any] +_PenState = dict[str, Any] -_Speed = Union[str, float] -_PolygonCoords = Sequence[Tuple[float, float]] +_Speed = str | float +_PolygonCoords = Sequence[tuple[float, float]] # TODO: Type this more accurately # Vec2D is actually a custom subclass of 'tuple'. -Vec2D = Tuple[float, float] +Vec2D = tuple[float, float] class TurtleScreenBase(object): cv: Canvas = ... @@ -50,7 +51,7 @@ class TurtleScreen(TurtleScreenBase): @overload def colormode(self, cmode: float) -> None: ... def reset(self) -> None: ... - def turtles(self) -> List[Turtle]: ... + def turtles(self) -> list[Turtle]: ... @overload def bgcolor(self) -> _AnyColor: ... @overload @@ -69,7 +70,7 @@ class TurtleScreen(TurtleScreenBase): def window_width(self) -> int: ... def window_height(self) -> int: ... def getcanvas(self) -> Canvas: ... - def getshapes(self) -> List[str]: ... + def getshapes(self) -> list[str]: ... def onclick(self, fun: Callable[[float, float], Any], btn: int = ..., add: Any | None = ...) -> None: ... def onkey(self, fun: Callable[[], Any], key: str) -> None: ... def listen(self, xdummy: float | None = ..., ydummy: float | None = ...) -> None: ... @@ -79,7 +80,7 @@ class TurtleScreen(TurtleScreenBase): @overload def bgpic(self, picname: str) -> None: ... @overload - def screensize(self, canvwidth: None = ..., canvheight: None = ..., bg: None = ...) -> Tuple[int, int]: ... + def screensize(self, canvwidth: None = ..., canvheight: None = ..., bg: None = ...) -> tuple[int, int]: ... # Looks like if self.cv is not a ScrolledCanvas, this could return a tuple as well @overload def screensize(self, canvwidth: int, canvheight: int, bg: _Color | None = ...) -> None: ... @@ -89,7 +90,7 @@ class TurtleScreen(TurtleScreenBase): addshape = register_shape class TNavigator(object): - START_ORIENTATION: Dict[str, Vec2D] = ... + START_ORIENTATION: dict[str, Vec2D] = ... DEFAULT_MODE: str = ... DEFAULT_ANGLEOFFSET: int = ... DEFAULT_ANGLEORIENT: int = ... @@ -105,18 +106,18 @@ class TNavigator(object): def xcor(self) -> float: ... def ycor(self) -> float: ... @overload - def goto(self, x: Tuple[float, float], y: None = ...) -> None: ... + def goto(self, x: tuple[float, float], y: None = ...) -> None: ... @overload def goto(self, x: float, y: float) -> None: ... def home(self) -> None: ... def setx(self, x: float) -> None: ... def sety(self, y: float) -> None: ... @overload - def distance(self, x: TNavigator | Tuple[float, float], y: None = ...) -> float: ... + def distance(self, x: TNavigator | tuple[float, float], y: None = ...) -> float: ... @overload def distance(self, x: float, y: float) -> float: ... @overload - def towards(self, x: TNavigator | Tuple[float, float], y: None = ...) -> float: ... + def towards(self, x: TNavigator | tuple[float, float], y: None = ...) -> float: ... @overload def towards(self, x: float, y: float) -> float: ... def heading(self) -> float: ... @@ -162,7 +163,7 @@ class TPen(object): @overload def fillcolor(self, r: float, g: float, b: float) -> None: ... @overload - def color(self) -> Tuple[_AnyColor, _AnyColor]: ... + def color(self) -> tuple[_AnyColor, _AnyColor]: ... @overload def color(self, color: _Color) -> None: ... @overload @@ -174,7 +175,7 @@ class TPen(object): def isvisible(self) -> bool: ... # Note: signatures 1 and 2 overlap unsafely when no arguments are provided @overload - def pen(self) -> _PenState: ... # type: ignore + def pen(self) -> _PenState: ... # type: ignore[misc] @overload def pen( self, @@ -187,7 +188,7 @@ class TPen(object): pensize: int = ..., speed: int = ..., resizemode: str = ..., - stretchfactor: Tuple[float, float] = ..., + stretchfactor: tuple[float, float] = ..., outline: int = ..., tilt: float = ..., ) -> None: ... @@ -199,8 +200,6 @@ class TPen(object): st = showturtle ht = hideturtle -_T = TypeVar("_T") - class RawTurtle(TPen, TNavigator): def __init__( self, canvas: Canvas | TurtleScreen | None = ..., shape: str = ..., undobuffersize: int = ..., visible: bool = ... @@ -209,14 +208,14 @@ class RawTurtle(TPen, TNavigator): def setundobuffer(self, size: int | None) -> None: ... def undobufferentries(self) -> int: ... def clear(self) -> None: ... - def clone(self: _T) -> _T: ... + def clone(self: Self) -> Self: ... @overload def shape(self, name: None = ...) -> str: ... @overload def shape(self, name: str) -> None: ... # Unsafely overlaps when no arguments are provided @overload - def shapesize(self) -> Tuple[float, float, float]: ... # type: ignore + def shapesize(self) -> tuple[float, float, float]: ... # type: ignore[misc] @overload def shapesize( self, stretch_wid: float | None = ..., stretch_len: float | None = ..., outline: float | None = ... @@ -231,18 +230,18 @@ class RawTurtle(TPen, TNavigator): # a compound stamp or not. So, as per the "no Union return" policy, # we return Any. def stamp(self) -> Any: ... - def clearstamp(self, stampid: int | Tuple[int, ...]) -> None: ... + def clearstamp(self, stampid: int | tuple[int, ...]) -> None: ... def clearstamps(self, n: int | None = ...) -> None: ... def filling(self) -> bool: ... def begin_fill(self) -> None: ... def end_fill(self) -> None: ... def dot(self, size: int | None = ..., *color: _Color) -> None: ... - def write(self, arg: object, move: bool = ..., align: str = ..., font: Tuple[str, int, str] = ...) -> None: ... + def write(self, arg: object, move: bool = ..., align: str = ..., font: tuple[str, int, str] = ...) -> None: ... def begin_poly(self) -> None: ... def end_poly(self) -> None: ... def get_poly(self) -> _PolygonCoords | None: ... def getscreen(self) -> TurtleScreen: ... - def getturtle(self: _T) -> _T: ... + def getturtle(self: Self) -> Self: ... getpen = getturtle def onclick(self, fun: Callable[[float, float], Any], btn: int = ..., add: bool | None = ...) -> None: ... def onrelease(self, fun: Callable[[float, float], Any], btn: int = ..., add: bool | None = ...) -> None: ... @@ -297,7 +296,7 @@ def colormode(cmode: None = ...) -> float: ... @overload def colormode(cmode: float) -> None: ... def reset() -> None: ... -def turtles() -> List[Turtle]: ... +def turtles() -> list[Turtle]: ... @overload def bgcolor() -> _AnyColor: ... @overload @@ -316,7 +315,7 @@ def update() -> None: ... def window_width() -> int: ... def window_height() -> int: ... def getcanvas() -> Canvas: ... -def getshapes() -> List[str]: ... +def getshapes() -> list[str]: ... def onclick(fun: Callable[[float, float], Any], btn: int = ..., add: Any | None = ...) -> None: ... def onkey(fun: Callable[[], Any], key: str) -> None: ... def listen(xdummy: float | None = ..., ydummy: float | None = ...) -> None: ... @@ -326,7 +325,7 @@ def bgpic(picname: None = ...) -> str: ... @overload def bgpic(picname: str) -> None: ... @overload -def screensize(canvwidth: None = ..., canvheight: None = ..., bg: None = ...) -> Tuple[int, int]: ... +def screensize(canvwidth: None = ..., canvheight: None = ..., bg: None = ...) -> tuple[int, int]: ... @overload def screensize(canvwidth: int, canvheight: int, bg: _Color | None = ...) -> None: ... @@ -354,18 +353,18 @@ def pos() -> Vec2D: ... def xcor() -> float: ... def ycor() -> float: ... @overload -def goto(x: Tuple[float, float], y: None = ...) -> None: ... +def goto(x: tuple[float, float], y: None = ...) -> None: ... @overload def goto(x: float, y: float) -> None: ... def home() -> None: ... def setx(x: float) -> None: ... def sety(y: float) -> None: ... @overload -def distance(x: TNavigator | Tuple[float, float], y: None = ...) -> float: ... +def distance(x: TNavigator | tuple[float, float], y: None = ...) -> float: ... @overload def distance(x: float, y: float) -> float: ... @overload -def towards(x: TNavigator | Tuple[float, float], y: None = ...) -> float: ... +def towards(x: TNavigator | tuple[float, float], y: None = ...) -> float: ... @overload def towards(x: float, y: float) -> float: ... def heading() -> float: ... @@ -411,7 +410,7 @@ def fillcolor(color: _Color) -> None: ... @overload def fillcolor(r: float, g: float, b: float) -> None: ... @overload -def color() -> Tuple[_AnyColor, _AnyColor]: ... +def color() -> tuple[_AnyColor, _AnyColor]: ... @overload def color(color: _Color) -> None: ... @overload @@ -424,7 +423,7 @@ def isvisible() -> bool: ... # Note: signatures 1 and 2 overlap unsafely when no arguments are provided @overload -def pen() -> _PenState: ... # type: ignore +def pen() -> _PenState: ... # type: ignore[misc] @overload def pen( pen: _PenState | None = ..., @@ -436,7 +435,7 @@ def pen( pensize: int = ..., speed: int = ..., resizemode: str = ..., - stretchfactor: Tuple[float, float] = ..., + stretchfactor: tuple[float, float] = ..., outline: int = ..., tilt: float = ..., ) -> None: ... @@ -460,7 +459,7 @@ def shape(name: str) -> None: ... # Unsafely overlaps when no arguments are provided @overload -def shapesize() -> Tuple[float, float, float]: ... # type: ignore +def shapesize() -> tuple[float, float, float]: ... # type: ignore[misc] @overload def shapesize(stretch_wid: float | None = ..., stretch_len: float | None = ..., outline: float | None = ...) -> None: ... def settiltangle(angle: float) -> None: ... @@ -474,13 +473,13 @@ def tilt(angle: float) -> None: ... # a compound stamp or not. So, as per the "no Union return" policy, # we return Any. def stamp() -> Any: ... -def clearstamp(stampid: int | Tuple[int, ...]) -> None: ... +def clearstamp(stampid: int | tuple[int, ...]) -> None: ... def clearstamps(n: int | None = ...) -> None: ... def filling() -> bool: ... def begin_fill() -> None: ... def end_fill() -> None: ... def dot(size: int | None = ..., *color: _Color) -> None: ... -def write(arg: object, move: bool = ..., align: str = ..., font: Tuple[str, int, str] = ...) -> None: ... +def write(arg: object, move: bool = ..., align: str = ..., font: tuple[str, int, str] = ...) -> None: ... def begin_poly() -> None: ... def end_poly() -> None: ... def get_poly() -> _PolygonCoords | None: ... diff --git a/mypy/typeshed/stdlib/@python2/types.pyi b/mypy/typeshed/stdlib/@python2/types.pyi index 0feee45305869..d2194296aa172 100644 --- a/mypy/typeshed/stdlib/@python2/types.pyi +++ b/mypy/typeshed/stdlib/@python2/types.pyi @@ -1,4 +1,4 @@ -from typing import Any, Callable, Dict, Iterable, Iterator, List, Tuple, Type, TypeVar, overload +from typing import Any, Callable, Iterable, Iterator, TypeVar, overload _T = TypeVar("_T") @@ -16,7 +16,7 @@ BooleanType = bool ComplexType = complex StringType = str UnicodeType = unicode -StringTypes: Tuple[Type[StringType], Type[UnicodeType]] +StringTypes: tuple[type[StringType], type[UnicodeType]] BufferType = buffer TupleType = tuple ListType = list @@ -27,12 +27,12 @@ class _Cell: cell_contents: Any class FunctionType: - func_closure: Tuple[_Cell, ...] | None = ... + func_closure: tuple[_Cell, ...] | None = ... func_code: CodeType = ... - func_defaults: Tuple[Any, ...] | None = ... - func_dict: Dict[str, Any] = ... + func_defaults: tuple[Any, ...] | None = ... + func_dict: dict[str, Any] = ... func_doc: str | None = ... - func_globals: Dict[str, Any] = ... + func_globals: dict[str, Any] = ... func_name: str = ... __closure__ = func_closure __code__ = func_code @@ -43,10 +43,10 @@ class FunctionType: def __init__( self, code: CodeType, - globals: Dict[str, Any], + globals: dict[str, Any], name: str | None = ..., - argdefs: Tuple[object, ...] | None = ..., - closure: Tuple[_Cell, ...] | None = ..., + argdefs: tuple[object, ...] | None = ..., + closure: tuple[_Cell, ...] | None = ..., ) -> None: ... def __call__(self, *args: Any, **kwargs: Any) -> Any: ... def __get__(self, obj: object | None, type: type | None) -> UnboundMethodType: ... @@ -55,19 +55,19 @@ LambdaType = FunctionType class CodeType: co_argcount: int - co_cellvars: Tuple[str, ...] + co_cellvars: tuple[str, ...] co_code: str - co_consts: Tuple[Any, ...] + co_consts: tuple[Any, ...] co_filename: str co_firstlineno: int co_flags: int - co_freevars: Tuple[str, ...] + co_freevars: tuple[str, ...] co_lnotab: str co_name: str - co_names: Tuple[str, ...] + co_names: tuple[str, ...] co_nlocals: int co_stacksize: int - co_varnames: Tuple[str, ...] + co_varnames: tuple[str, ...] def __init__( self, argcount: int, @@ -75,15 +75,15 @@ class CodeType: stacksize: int, flags: int, codestring: str, - constants: Tuple[Any, ...], - names: Tuple[str, ...], - varnames: Tuple[str, ...], + constants: tuple[Any, ...], + names: tuple[str, ...], + varnames: tuple[str, ...], filename: str, name: str, firstlineno: int, lnotab: str, - freevars: Tuple[str, ...] = ..., - cellvars: Tuple[str, ...] = ..., + freevars: tuple[str, ...] = ..., + cellvars: tuple[str, ...] = ..., ) -> None: ... class GeneratorType: @@ -95,7 +95,7 @@ class GeneratorType: def next(self) -> Any: ... def send(self, __arg: Any) -> Any: ... @overload - def throw(self, __typ: Type[BaseException], __val: BaseException | object = ..., __tb: TracebackType | None = ...) -> Any: ... + def throw(self, __typ: type[BaseException], __val: BaseException | object = ..., __tb: TracebackType | None = ...) -> Any: ... @overload def throw(self, __typ: BaseException, __val: None = ..., __tb: TracebackType | None = ...) -> Any: ... @@ -127,7 +127,7 @@ class ModuleType: __name__: str __package__: str | None __path__: Iterable[str] | None - __dict__: Dict[str, Any] + __dict__: dict[str, Any] def __init__(self, name: str, doc: str | None = ...) -> None: ... FileType = file @@ -141,15 +141,15 @@ class TracebackType: class FrameType: f_back: FrameType - f_builtins: Dict[str, Any] + f_builtins: dict[str, Any] f_code: CodeType f_exc_type: None f_exc_value: None f_exc_traceback: None - f_globals: Dict[str, Any] + f_globals: dict[str, Any] f_lasti: int f_lineno: int | None - f_locals: Dict[str, Any] + f_locals: dict[str, Any] f_restricted: bool f_trace: Callable[[], None] def clear(self) -> None: ... @@ -161,15 +161,15 @@ class EllipsisType: ... class DictProxyType: # TODO is it possible to have non-string keys? # no __init__ - def copy(self) -> Dict[Any, Any]: ... + def copy(self) -> dict[Any, Any]: ... def get(self, key: str, default: _T = ...) -> Any | _T: ... def has_key(self, key: str) -> bool: ... - def items(self) -> List[Tuple[str, Any]]: ... - def iteritems(self) -> Iterator[Tuple[str, Any]]: ... + def items(self) -> list[tuple[str, Any]]: ... + def iteritems(self) -> Iterator[tuple[str, Any]]: ... def iterkeys(self) -> Iterator[str]: ... def itervalues(self) -> Iterator[Any]: ... - def keys(self) -> List[str]: ... - def values(self) -> List[Any]: ... + def keys(self) -> list[str]: ... + def values(self) -> list[Any]: ... def __contains__(self, key: str) -> bool: ... def __getitem__(self, key: str) -> Any: ... def __iter__(self) -> Iterator[str]: ... diff --git a/mypy/typeshed/stdlib/@python2/typing.pyi b/mypy/typeshed/stdlib/@python2/typing.pyi index a1b02e81990c9..affa82c825a21 100644 --- a/mypy/typeshed/stdlib/@python2/typing.pyi +++ b/mypy/typeshed/stdlib/@python2/typing.pyi @@ -1,4 +1,5 @@ import collections # Needed by aliases like DefaultDict, see mypy issue 2986 +from _typeshed import Self from abc import ABCMeta, abstractmethod from types import CodeType, FrameType, TracebackType @@ -9,36 +10,44 @@ Any = object() class TypeVar: __name__: str - __bound__: Type[Any] | None - __constraints__: Tuple[Type[Any], ...] + __bound__: type[Any] | None + __constraints__: tuple[type[Any], ...] __covariant__: bool __contravariant__: bool def __init__( - self, name: str, *constraints: Type[Any], bound: Type[Any] | None = ..., covariant: bool = ..., contravariant: bool = ... + self, name: str, *constraints: type[Any], bound: type[Any] | None = ..., covariant: bool = ..., contravariant: bool = ... ) -> None: ... _promote = object() +# N.B. Keep this definition in sync with typing_extensions._SpecialForm class _SpecialForm(object): def __getitem__(self, typeargs: Any) -> object: ... -Union: _SpecialForm = ... -Optional: _SpecialForm = ... -Tuple: _SpecialForm = ... +# Unlike the vast majority module-level objects in stub files, +# these `_SpecialForm` objects in typing need the default value `= ...`, +# due to the fact that they are used elswhere in the same file. +# Otherwise, flake8 erroneously flags them as undefined. +# `_SpecialForm` objects in typing.py that are not used elswhere in the same file +# do not need the default value assignment. Generic: _SpecialForm = ... Protocol: _SpecialForm = ... Callable: _SpecialForm = ... -Type: _SpecialForm = ... -ClassVar: _SpecialForm = ... -Final: _SpecialForm = ... +Union: _SpecialForm = ... + +Optional: _SpecialForm +Tuple: _SpecialForm +Type: _SpecialForm +ClassVar: _SpecialForm +Final: _SpecialForm _F = TypeVar("_F", bound=Callable[..., Any]) def final(f: _F) -> _F: ... def overload(f: _F) -> _F: ... -Literal: _SpecialForm = ... +Literal: _SpecialForm # TypedDict is a (non-subscriptable) special form. -TypedDict: object = ... +TypedDict: object class GenericMeta(type): ... @@ -49,7 +58,6 @@ NoReturn = Union[None] # These type variables are used by the container types. _T = TypeVar("_T") -_S = TypeVar("_S") _KT = TypeVar("_KT") # Key type. _VT = TypeVar("_VT") # Value type. _T_co = TypeVar("_T_co", covariant=True) # Any type covariant containers. @@ -57,7 +65,7 @@ _V_co = TypeVar("_V_co", covariant=True) # Any type covariant containers. _KT_co = TypeVar("_KT_co", covariant=True) # Key type covariant containers. _VT_co = TypeVar("_VT_co", covariant=True) # Value type covariant containers. _T_contra = TypeVar("_T_contra", contravariant=True) # Ditto contravariant. -_TC = TypeVar("_TC", bound=Type[object]) +_TC = TypeVar("_TC", bound=type[object]) def no_type_check(f: _F) -> _F: ... def no_type_check_decorator(decorator: _F) -> _F: ... @@ -77,7 +85,7 @@ Counter = _Alias() Deque = _Alias() # Predefined type variables. -AnyStr = TypeVar("AnyStr", str, unicode) +AnyStr = TypeVar("AnyStr", str, unicode) # noqa: Y001 # Abstract base classes. @@ -139,7 +147,7 @@ class Generator(Iterator[_T_co], Generic[_T_co, _T_contra, _V_co]): @overload @abstractmethod def throw( - self, __typ: Type[BaseException], __val: BaseException | object = ..., __tb: TracebackType | None = ... + self, __typ: type[BaseException], __val: BaseException | object = ..., __tb: TracebackType | None = ... ) -> _T_co: ... @overload @abstractmethod @@ -202,7 +210,7 @@ class MutableSequence(Sequence[_T], Generic[_T]): def reverse(self) -> None: ... def pop(self, index: int = ...) -> _T: ... def remove(self, object: _T) -> None: ... - def __iadd__(self, x: Iterable[_T]) -> MutableSequence[_T]: ... + def __iadd__(self: Self, x: Iterable[_T]) -> Self: ... class AbstractSet(Iterable[_T_co], Container[_T_co], Generic[_T_co]): @abstractmethod @@ -231,18 +239,18 @@ class MutableSet(AbstractSet[_T], Generic[_T]): def clear(self) -> None: ... def pop(self) -> _T: ... def remove(self, element: _T) -> None: ... - def __ior__(self, s: AbstractSet[_S]) -> MutableSet[_T | _S]: ... - def __iand__(self, s: AbstractSet[Any]) -> MutableSet[_T]: ... - def __ixor__(self, s: AbstractSet[_S]) -> MutableSet[_T | _S]: ... - def __isub__(self, s: AbstractSet[Any]) -> MutableSet[_T]: ... + def __ior__(self: Self, s: AbstractSet[_T]) -> Self: ... + def __iand__(self: Self, s: AbstractSet[Any]) -> Self: ... + def __ixor__(self: Self, s: AbstractSet[_T]) -> Self: ... + def __isub__(self: Self, s: AbstractSet[Any]) -> Self: ... class MappingView(object): def __len__(self) -> int: ... -class ItemsView(MappingView, AbstractSet[Tuple[_KT_co, _VT_co]], Generic[_KT_co, _VT_co]): +class ItemsView(MappingView, AbstractSet[tuple[_KT_co, _VT_co]], Generic[_KT_co, _VT_co]): def __init__(self, mapping: Mapping[_KT_co, _VT_co]) -> None: ... def __contains__(self, o: object) -> bool: ... - def __iter__(self) -> Iterator[Tuple[_KT_co, _VT_co]]: ... + def __iter__(self) -> Iterator[tuple[_KT_co, _VT_co]]: ... class KeysView(MappingView, AbstractSet[_KT_co], Generic[_KT_co]): def __init__(self, mapping: Mapping[_KT_co, _VT_co]) -> None: ... @@ -258,7 +266,7 @@ class ValuesView(MappingView, Iterable[_VT_co], Generic[_VT_co]): class ContextManager(Protocol[_T_co]): def __enter__(self) -> _T_co: ... def __exit__( - self, __exc_type: Type[BaseException] | None, __exc_value: BaseException | None, __traceback: TracebackType | None + self, __exc_type: type[BaseException] | None, __exc_value: BaseException | None, __traceback: TracebackType | None ) -> bool | None: ... class Mapping(Iterable[_KT], Container[_KT], Generic[_KT, _VT_co]): @@ -273,10 +281,10 @@ class Mapping(Iterable[_KT], Container[_KT], Generic[_KT, _VT_co]): def get(self, k: _KT, default: _VT_co | _T) -> _VT_co | _T: ... def keys(self) -> list[_KT]: ... def values(self) -> list[_VT_co]: ... - def items(self) -> list[Tuple[_KT, _VT_co]]: ... + def items(self) -> list[tuple[_KT, _VT_co]]: ... def iterkeys(self) -> Iterator[_KT]: ... def itervalues(self) -> Iterator[_VT_co]: ... - def iteritems(self) -> Iterator[Tuple[_KT, _VT_co]]: ... + def iteritems(self) -> Iterator[tuple[_KT, _VT_co]]: ... def __contains__(self, o: object) -> bool: ... # Implement Sized (but don't have it as a base class). @abstractmethod @@ -292,18 +300,18 @@ class MutableMapping(Mapping[_KT, _VT], Generic[_KT, _VT]): def pop(self, k: _KT) -> _VT: ... @overload def pop(self, k: _KT, default: _VT | _T = ...) -> _VT | _T: ... - def popitem(self) -> Tuple[_KT, _VT]: ... + def popitem(self) -> tuple[_KT, _VT]: ... def setdefault(self, k: _KT, default: _VT = ...) -> _VT: ... @overload def update(self, __m: Mapping[_KT, _VT], **kwargs: _VT) -> None: ... @overload - def update(self, __m: Iterable[Tuple[_KT, _VT]], **kwargs: _VT) -> None: ... + def update(self, __m: Iterable[tuple[_KT, _VT]], **kwargs: _VT) -> None: ... @overload def update(self, **kwargs: _VT) -> None: ... Text = unicode -TYPE_CHECKING = True +TYPE_CHECKING: bool class IO(Iterator[AnyStr], Generic[AnyStr]): # TODO detach @@ -354,7 +362,7 @@ class IO(Iterator[AnyStr], Generic[AnyStr]): def __enter__(self) -> IO[AnyStr]: ... @abstractmethod def __exit__( - self, t: Type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None + self, t: type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None ) -> bool | None: ... class BinaryIO(IO[str]): @@ -403,16 +411,16 @@ class Match(Generic[AnyStr]): @overload def group(self, group1: str) -> AnyStr: ... @overload - def group(self, group1: int, group2: int, *groups: int) -> Tuple[AnyStr, ...]: ... + def group(self, group1: int, group2: int, *groups: int) -> tuple[AnyStr, ...]: ... @overload - def group(self, group1: str, group2: str, *groups: str) -> Tuple[AnyStr, ...]: ... - def groups(self, default: AnyStr = ...) -> Tuple[AnyStr, ...]: ... + def group(self, group1: str, group2: str, *groups: str) -> tuple[AnyStr, ...]: ... + def groups(self, default: AnyStr = ...) -> tuple[AnyStr, ...]: ... def groupdict(self, default: AnyStr = ...) -> Dict[str, AnyStr]: ... def start(self, __group: int | str = ...) -> int: ... def end(self, __group: int | str = ...) -> int: ... - def span(self, __group: int | str = ...) -> Tuple[int, int]: ... + def span(self, __group: int | str = ...) -> tuple[int, int]: ... @property - def regs(self) -> Tuple[Tuple[int, int], ...]: ... # undocumented + def regs(self) -> tuple[tuple[int, int], ...]: ... # undocumented # We need a second TypeVar with the same definition as AnyStr, because # Pattern is generic over AnyStr (determining the type of its .pattern @@ -437,9 +445,9 @@ class Pattern(Generic[AnyStr]): @overload def sub(self, repl: Callable[[Match[_AnyStr2]], _AnyStr2], string: _AnyStr2, count: int = ...) -> _AnyStr2: ... @overload - def subn(self, repl: _AnyStr2, string: _AnyStr2, count: int = ...) -> Tuple[_AnyStr2, int]: ... + def subn(self, repl: _AnyStr2, string: _AnyStr2, count: int = ...) -> tuple[_AnyStr2, int]: ... @overload - def subn(self, repl: Callable[[Match[_AnyStr2]], _AnyStr2], string: _AnyStr2, count: int = ...) -> Tuple[_AnyStr2, int]: ... + def subn(self, repl: Callable[[Match[_AnyStr2]], _AnyStr2], string: _AnyStr2, count: int = ...) -> tuple[_AnyStr2, int]: ... # Functions @@ -447,7 +455,7 @@ def get_type_hints( obj: Callable[..., Any], globalns: Dict[Text, Any] | None = ..., localns: Dict[Text, Any] | None = ... ) -> None: ... @overload -def cast(tp: Type[_T], obj: Any) -> _T: ... +def cast(tp: type[_T], obj: Any) -> _T: ... @overload def cast(tp: str, obj: Any) -> Any: ... @overload @@ -456,17 +464,17 @@ def cast(tp: object, obj: Any) -> Any: ... # Type constructors # NamedTuple is special-cased in the type checker -class NamedTuple(Tuple[Any, ...]): - _fields: Tuple[str, ...] - def __init__(self, typename: Text, fields: Iterable[Tuple[Text, Any]] = ..., **kwargs: Any) -> None: ... +class NamedTuple(tuple[Any, ...]): + _fields: tuple[str, ...] + def __init__(self, typename: Text, fields: Iterable[tuple[Text, Any]] = ..., **kwargs: Any) -> None: ... @classmethod - def _make(cls: Type[_T], iterable: Iterable[Any]) -> _T: ... + def _make(cls: type[Self], iterable: Iterable[Any]) -> Self: ... def _asdict(self) -> Dict[str, Any]: ... - def _replace(self: _T, **kwargs: Any) -> _T: ... + def _replace(self: Self, **kwargs: Any) -> Self: ... # Internal mypy fallback type for all typed dicts (does not exist at runtime) class _TypedDict(Mapping[str, object], metaclass=ABCMeta): - def copy(self: _T) -> _T: ... + def copy(self: Self) -> Self: ... # Using NoReturn so that only calls using mypy plugin hook that specialize the signature # can go through. def setdefault(self, k: NoReturn, default: object) -> object: ... @@ -479,7 +487,7 @@ class _TypedDict(Mapping[str, object], metaclass=ABCMeta): def viewvalues(self) -> ValuesView[object]: ... def __delitem__(self, k: NoReturn) -> None: ... -def NewType(name: str, tp: Type[_T]) -> Type[_T]: ... +def NewType(name: str, tp: type[_T]) -> type[_T]: ... # This itself is only available during type checking def type_check_only(func_or_cls: _F) -> _F: ... diff --git a/mypy/typeshed/stdlib/@python2/typing_extensions.pyi b/mypy/typeshed/stdlib/@python2/typing_extensions.pyi index d946cc278d32a..62ef6f7b787cc 100644 --- a/mypy/typeshed/stdlib/@python2/typing_extensions.pyi +++ b/mypy/typeshed/stdlib/@python2/typing_extensions.pyi @@ -1,5 +1,6 @@ import abc -from typing import ( +from _typeshed import Self +from typing import ( # noqa: Y022 TYPE_CHECKING as TYPE_CHECKING, Any, Callable, @@ -8,49 +9,45 @@ from typing import ( Counter as Counter, DefaultDict as DefaultDict, Deque as Deque, - Dict, ItemsView, KeysView, Mapping, NewType as NewType, NoReturn as NoReturn, + Protocol as Protocol, Text as Text, - Tuple, Type as Type, TypeVar, ValuesView, _Alias, overload as overload, + runtime_checkable as runtime_checkable, ) _T = TypeVar("_T") _F = TypeVar("_F", bound=Callable[..., Any]) -_TC = TypeVar("_TC", bound=Type[object]) +# unfortunately we have to duplicate this class definition from typing.pyi or we break pytype class _SpecialForm: - def __getitem__(self, typeargs: Any) -> Any: ... - -def runtime_checkable(cls: _TC) -> _TC: ... + def __getitem__(self, typeargs: Any) -> object: ... # This alias for above is kept here for backwards compatibility. runtime = runtime_checkable -Protocol: _SpecialForm = ... -Final: _SpecialForm = ... +Final: _SpecialForm def final(f: _F) -> _F: ... -Literal: _SpecialForm = ... +Literal: _SpecialForm def IntVar(name: str) -> Any: ... # returns a new TypeVar # Internal mypy fallback type for all typed dicts (does not exist at runtime) class _TypedDict(Mapping[str, object], metaclass=abc.ABCMeta): - def copy(self: _T) -> _T: ... + def copy(self: Self) -> Self: ... # Using NoReturn so that only calls using mypy plugin hook that specialize the signature # can go through. def setdefault(self, k: NoReturn, default: object) -> object: ... - # Mypy plugin hook for 'pop' expects that 'default' has a type variable type. - def pop(self, k: NoReturn, default: _T = ...) -> object: ... # type: ignore + def pop(self, k: NoReturn, default: _T = ...) -> object: ... def update(self: _T, __m: _T) -> None: ... def has_key(self, k: str) -> bool: ... def viewitems(self) -> ItemsView[str, object]: ... @@ -59,19 +56,19 @@ class _TypedDict(Mapping[str, object], metaclass=abc.ABCMeta): def __delitem__(self, k: NoReturn) -> None: ... # TypedDict is a (non-subscriptable) special form. -TypedDict: object = ... +TypedDict: object OrderedDict = _Alias() def get_type_hints( obj: Callable[..., Any], - globalns: Dict[str, Any] | None = ..., - localns: Dict[str, Any] | None = ..., + globalns: dict[str, Any] | None = ..., + localns: dict[str, Any] | None = ..., include_extras: bool = ..., -) -> Dict[str, Any]: ... +) -> dict[str, Any]: ... -Annotated: _SpecialForm = ... -_AnnotatedAlias: Any = ... # undocumented +Annotated: _SpecialForm +_AnnotatedAlias: Any # undocumented @runtime_checkable class SupportsIndex(Protocol, metaclass=abc.ABCMeta): @@ -89,17 +86,17 @@ class ParamSpecKwargs: class ParamSpec: __name__: str - __bound__: Type[Any] | None + __bound__: type[Any] | None __covariant__: bool __contravariant__: bool def __init__( - self, name: str, *, bound: None | Type[Any] | str = ..., contravariant: bool = ..., covariant: bool = ... + self, name: str, *, bound: None | type[Any] | str = ..., contravariant: bool = ..., covariant: bool = ... ) -> None: ... @property def args(self) -> ParamSpecArgs: ... @property def kwargs(self) -> ParamSpecKwargs: ... -Concatenate: _SpecialForm = ... -TypeAlias: _SpecialForm = ... -TypeGuard: _SpecialForm = ... +Concatenate: _SpecialForm +TypeAlias: _SpecialForm +TypeGuard: _SpecialForm diff --git a/mypy/typeshed/stdlib/@python2/unittest.pyi b/mypy/typeshed/stdlib/@python2/unittest.pyi index 65a5a7878de66..887e7055207d9 100644 --- a/mypy/typeshed/stdlib/@python2/unittest.pyi +++ b/mypy/typeshed/stdlib/@python2/unittest.pyi @@ -1,35 +1,18 @@ import datetime import types +from _typeshed import Self from abc import ABCMeta, abstractmethod -from typing import ( - Any, - Callable, - Dict, - FrozenSet, - Iterable, - Iterator, - List, - Mapping, - NoReturn, - Pattern, - Sequence, - Set, - Text, - TextIO, - Tuple, - Type, - TypeVar, - Union, - overload, -) +from typing import Any, Callable, Iterable, Iterator, Mapping, NoReturn, Pattern, Sequence, Text, TextIO, TypeVar, Union, overload +from typing_extensions import ParamSpec _T = TypeVar("_T") _FT = TypeVar("_FT") +_P = ParamSpec("_P") -_ExceptionType = Union[Type[BaseException], Tuple[Type[BaseException], ...]] -_Regexp = Union[Text, Pattern[Text]] +_ExceptionType = Union[type[BaseException], tuple[type[BaseException], ...]] +_Regexp = Text | Pattern[Text] -_SysExcInfoType = Union[Tuple[Type[BaseException], BaseException, types.TracebackType], Tuple[None, None, None]] +_SysExcInfoType = Union[tuple[type[BaseException], BaseException, types.TracebackType], tuple[None, None, None]] class Testable(metaclass=ABCMeta): @abstractmethod @@ -42,11 +25,11 @@ class Testable(metaclass=ABCMeta): # TODO ABC for test runners? class TestResult: - errors: List[Tuple[TestCase, str]] - failures: List[Tuple[TestCase, str]] - skipped: List[Tuple[TestCase, str]] - expectedFailures: List[Tuple[TestCase, str]] - unexpectedSuccesses: List[TestCase] + errors: list[tuple[TestCase, str]] + failures: list[tuple[TestCase, str]] + skipped: list[tuple[TestCase, str]] + expectedFailures: list[tuple[TestCase, str]] + unexpectedSuccesses: list[TestCase] shouldStop: bool testsRun: int buffer: bool @@ -66,17 +49,17 @@ class TestResult: class _AssertRaisesBaseContext: expected: Any - failureException: Type[BaseException] + failureException: type[BaseException] obj_name: str expected_regex: Pattern[str] class _AssertRaisesContext(_AssertRaisesBaseContext): exception: Any - def __enter__(self) -> _AssertRaisesContext: ... + def __enter__(self: Self) -> Self: ... def __exit__(self, exc_type, exc_value, tb) -> bool: ... class TestCase(Testable): - failureException: Type[BaseException] + failureException: type[BaseException] longMessage: bool maxDiff: int | None # undocumented @@ -141,10 +124,10 @@ class TestCase(Testable): def assertSequenceEqual( self, first: Sequence[Any], second: Sequence[Any], msg: object = ..., seq_type: type = ... ) -> None: ... - def assertListEqual(self, first: List[Any], second: List[Any], msg: object = ...) -> None: ... - def assertTupleEqual(self, first: Tuple[Any, ...], second: Tuple[Any, ...], msg: object = ...) -> None: ... - def assertSetEqual(self, first: Set[Any] | FrozenSet[Any], second: Set[Any] | FrozenSet[Any], msg: object = ...) -> None: ... - def assertDictEqual(self, first: Dict[Any, Any], second: Dict[Any, Any], msg: object = ...) -> None: ... + def assertListEqual(self, first: list[Any], second: list[Any], msg: object = ...) -> None: ... + def assertTupleEqual(self, first: tuple[Any, ...], second: tuple[Any, ...], msg: object = ...) -> None: ... + def assertSetEqual(self, first: set[Any] | frozenset[Any], second: set[Any] | frozenset[Any], msg: object = ...) -> None: ... + def assertDictEqual(self, first: dict[Any, Any], second: dict[Any, Any], msg: object = ...) -> None: ... def assertLess(self, first: Any, second: Any, msg: object = ...) -> None: ... def assertLessEqual(self, first: Any, second: Any, msg: object = ...) -> None: ... @overload @@ -174,8 +157,8 @@ class TestCase(Testable): def assertIsNotNone(self, expr: Any, msg: object = ...) -> None: ... def assertIn(self, first: _T, second: Iterable[_T], msg: object = ...) -> None: ... def assertNotIn(self, first: _T, second: Iterable[_T], msg: object = ...) -> None: ... - def assertIsInstance(self, obj: Any, cls: type | Tuple[type, ...], msg: object = ...) -> None: ... - def assertNotIsInstance(self, obj: Any, cls: type | Tuple[type, ...], msg: object = ...) -> None: ... + def assertIsInstance(self, obj: Any, cls: type | tuple[type, ...], msg: object = ...) -> None: ... + def assertNotIsInstance(self, obj: Any, cls: type | tuple[type, ...], msg: object = ...) -> None: ... def fail(self, msg: object = ...) -> NoReturn: ... def countTestCases(self) -> int: ... def defaultTestResult(self) -> TestResult: ... @@ -210,13 +193,13 @@ class TestSuite(Testable): class TestLoader: testMethodPrefix: str sortTestMethodsUsing: Callable[[str, str], int] | None - suiteClass: Callable[[List[TestCase]], TestSuite] - def loadTestsFromTestCase(self, testCaseClass: Type[TestCase]) -> TestSuite: ... + suiteClass: Callable[[list[TestCase]], TestSuite] + def loadTestsFromTestCase(self, testCaseClass: type[TestCase]) -> TestSuite: ... def loadTestsFromModule(self, module: types.ModuleType = ..., use_load_tests: bool = ...) -> TestSuite: ... def loadTestsFromName(self, name: str = ..., module: types.ModuleType | None = ...) -> TestSuite: ... - def loadTestsFromNames(self, names: List[str] = ..., module: types.ModuleType | None = ...) -> TestSuite: ... + def loadTestsFromNames(self, names: list[str] = ..., module: types.ModuleType | None = ...) -> TestSuite: ... def discover(self, start_dir: str, pattern: str = ..., top_level_dir: str | None = ...) -> TestSuite: ... - def getTestCaseNames(self, testCaseClass: Type[TestCase] = ...) -> List[str]: ... + def getTestCaseNames(self, testCaseClass: type[TestCase] = ...) -> list[str]: ... defaultTestLoader: TestLoader @@ -224,7 +207,7 @@ class TextTestResult(TestResult): def __init__(self, stream: TextIO, descriptions: bool, verbosity: int) -> None: ... def getDescription(self, test: TestCase) -> str: ... # undocumented def printErrors(self) -> None: ... # undocumented - def printErrorList(self, flavour: str, errors: List[Tuple[TestCase, str]]) -> None: ... # undocumented + def printErrorList(self, flavour: str, errors: list[tuple[TestCase, str]]) -> None: ... # undocumented class TextTestRunner: def __init__( @@ -234,7 +217,7 @@ class TextTestRunner: verbosity: int = ..., failfast: bool = ..., buffer: bool = ..., - resultclass: Type[TestResult] | None = ..., + resultclass: type[TestResult] | None = ..., ) -> None: ... def _makeResult(self) -> TestResult: ... def run(self, test: Testable) -> TestResult: ... # undocumented @@ -256,7 +239,7 @@ def main( module: None | Text | types.ModuleType = ..., defaultTest: str | None = ..., argv: Sequence[str] | None = ..., - testRunner: Type[TextTestRunner] | TextTestRunner | None = ..., + testRunner: type[TextTestRunner] | TextTestRunner | None = ..., testLoader: TestLoader = ..., exit: bool = ..., verbosity: int = ..., @@ -271,7 +254,7 @@ def removeResult(result: TestResult) -> bool: ... @overload def removeHandler() -> None: ... @overload -def removeHandler(function: Callable[..., Any]) -> Callable[..., Any]: ... +def removeHandler(function: Callable[_P, _T]) -> Callable[_P, _T]: ... # private but occasionally used util: types.ModuleType diff --git a/mypy/typeshed/stdlib/@python2/urllib.pyi b/mypy/typeshed/stdlib/@python2/urllib.pyi index f6bb555b95810..56a75af74bb32 100644 --- a/mypy/typeshed/stdlib/@python2/urllib.pyi +++ b/mypy/typeshed/stdlib/@python2/urllib.pyi @@ -1,4 +1,5 @@ -from typing import IO, Any, AnyStr, List, Mapping, Sequence, Text, Tuple, TypeVar +from _typeshed import Self +from typing import IO, Any, AnyStr, Mapping, Sequence, Text def url2pathname(pathname: AnyStr) -> AnyStr: ... def pathname2url(pathname: AnyStr) -> AnyStr: ... @@ -77,15 +78,13 @@ class ftpwrapper: def file_close(self): ... def real_close(self): ... -_AIUT = TypeVar("_AIUT", bound=addbase) - class addbase: fp: Any def read(self, n: int = ...) -> bytes: ... def readline(self, limit: int = ...) -> bytes: ... - def readlines(self, hint: int = ...) -> List[bytes]: ... + def readlines(self, hint: int = ...) -> list[bytes]: ... def fileno(self) -> int: ... # Optional[int], but that is rare - def __iter__(self: _AIUT) -> _AIUT: ... + def __iter__(self: Self) -> Self: ... def next(self) -> bytes: ... def __init__(self, fp) -> None: ... def close(self) -> None: ... @@ -125,7 +124,7 @@ def unquote(s: AnyStr) -> AnyStr: ... def unquote_plus(s: AnyStr) -> AnyStr: ... def quote(s: AnyStr, safe: Text = ...) -> AnyStr: ... def quote_plus(s: AnyStr, safe: Text = ...) -> AnyStr: ... -def urlencode(query: Sequence[Tuple[Any, Any]] | Mapping[Any, Any], doseq=...) -> str: ... +def urlencode(query: Sequence[tuple[Any, Any]] | Mapping[Any, Any], doseq=...) -> str: ... def getproxies() -> Mapping[str, str]: ... def proxy_bypass(host: str) -> Any: ... # undocumented diff --git a/mypy/typeshed/stdlib/@python2/urllib2.pyi b/mypy/typeshed/stdlib/@python2/urllib2.pyi index bf6157b8428b3..1ea1bce28db1f 100644 --- a/mypy/typeshed/stdlib/@python2/urllib2.pyi +++ b/mypy/typeshed/stdlib/@python2/urllib2.pyi @@ -1,9 +1,9 @@ import ssl from httplib import HTTPConnectionProtocol, HTTPResponse -from typing import Any, AnyStr, Callable, Dict, List, Mapping, Sequence, Text, Tuple, Type, Union +from typing import Any, AnyStr, Callable, Mapping, Sequence, Text from urllib import addinfourl -_string = Union[str, unicode] +_string = str | unicode class URLError(IOError): reason: str | BaseException @@ -17,17 +17,17 @@ class Request(object): host: str port: str data: str - headers: Dict[str, str] + headers: dict[str, str] unverifiable: bool type: str | None origin_req_host = ... - unredirected_hdrs: Dict[str, str] + unredirected_hdrs: dict[str, str] timeout: float | None # Undocumented, only set after __init__() by OpenerDirector.open() def __init__( self, url: str, data: str | None = ..., - headers: Dict[str, str] = ..., + headers: dict[str, str] = ..., origin_req_host: str | None = ..., unverifiable: bool = ..., ) -> None: ... @@ -51,7 +51,7 @@ class Request(object): def header_items(self): ... class OpenerDirector(object): - addheaders: List[Tuple[str, str]] + addheaders: list[tuple[str, str]] def add_handler(self, handler: BaseHandler) -> None: ... def open(self, fullurl: Request | _string, data: _string | None = ..., timeout: float | None = ...) -> addinfourl | None: ... def error(self, proto: _string, *args: Any): ... @@ -68,7 +68,7 @@ def urlopen( context: ssl.SSLContext | None = ..., ) -> addinfourl: ... def install_opener(opener: OpenerDirector) -> None: ... -def build_opener(*handlers: BaseHandler | Type[BaseHandler]) -> OpenerDirector: ... +def build_opener(*handlers: BaseHandler | type[BaseHandler]) -> OpenerDirector: ... class BaseHandler: handler_order: int @@ -101,8 +101,8 @@ class ProxyHandler(BaseHandler): class HTTPPasswordMgr: def __init__(self) -> None: ... def add_password(self, realm: Text | None, uri: Text | Sequence[Text], user: Text, passwd: Text) -> None: ... - def find_user_password(self, realm: Text | None, authuri: Text) -> Tuple[Any, Any]: ... - def reduce_uri(self, uri: _string, default_port: bool = ...) -> Tuple[Any, Any]: ... + def find_user_password(self, realm: Text | None, authuri: Text) -> tuple[Any, Any]: ... + def reduce_uri(self, uri: _string, default_port: bool = ...) -> tuple[Any, Any]: ... def is_suburi(self, base: _string, test: _string) -> bool: ... class HTTPPasswordMgrWithDefaultRealm(HTTPPasswordMgr): ... @@ -129,7 +129,7 @@ class AbstractDigestAuthHandler: def retry_http_digest_auth(self, req: Request, auth: str) -> HTTPResponse | None: ... def get_cnonce(self, nonce: str) -> str: ... def get_authorization(self, req: Request, chal: Mapping[str, str]) -> str: ... - def get_algorithm_impls(self, algorithm: str) -> Tuple[Callable[[str], str], Callable[[str, str], str]]: ... + def get_algorithm_impls(self, algorithm: str) -> tuple[Callable[[str], str], Callable[[str, str], str]]: ... def get_entity_digest(self, data: bytes | None, chal: Mapping[str, str]) -> str | None: ... class HTTPDigestAuthHandler(BaseHandler, AbstractDigestAuthHandler): @@ -181,5 +181,5 @@ class CacheFTPHandler(FTPHandler): def check_cache(self): ... def clear_cache(self): ... -def parse_http_list(s: AnyStr) -> List[AnyStr]: ... -def parse_keqv_list(l: List[AnyStr]) -> Dict[AnyStr, AnyStr]: ... +def parse_http_list(s: AnyStr) -> list[AnyStr]: ... +def parse_keqv_list(l: list[AnyStr]) -> dict[AnyStr, AnyStr]: ... diff --git a/mypy/typeshed/stdlib/@python2/urlparse.pyi b/mypy/typeshed/stdlib/@python2/urlparse.pyi index 6668c743373a4..16c32753c7c5c 100644 --- a/mypy/typeshed/stdlib/@python2/urlparse.pyi +++ b/mypy/typeshed/stdlib/@python2/urlparse.pyi @@ -1,13 +1,13 @@ -from typing import AnyStr, Dict, List, NamedTuple, Sequence, Tuple, Union, overload +from typing import AnyStr, NamedTuple, Sequence, overload -_String = Union[str, unicode] +_String = str | unicode -uses_relative: List[str] -uses_netloc: List[str] -uses_params: List[str] -non_hierarchical: List[str] -uses_query: List[str] -uses_fragment: List[str] +uses_relative: list[str] +uses_netloc: list[str] +uses_params: list[str] +non_hierarchical: list[str] +uses_query: list[str] +uses_fragment: list[str] scheme_chars: str MAX_CACHE_SIZE: int @@ -47,15 +47,15 @@ class ParseResult(_ParseResult, ResultMixin): def urlparse(url: _String, scheme: _String = ..., allow_fragments: bool = ...) -> ParseResult: ... def urlsplit(url: _String, scheme: _String = ..., allow_fragments: bool = ...) -> SplitResult: ... @overload -def urlunparse(data: Tuple[AnyStr, AnyStr, AnyStr, AnyStr, AnyStr, AnyStr]) -> AnyStr: ... +def urlunparse(data: tuple[AnyStr, AnyStr, AnyStr, AnyStr, AnyStr, AnyStr]) -> AnyStr: ... @overload def urlunparse(data: Sequence[AnyStr]) -> AnyStr: ... @overload -def urlunsplit(data: Tuple[AnyStr, AnyStr, AnyStr, AnyStr, AnyStr]) -> AnyStr: ... +def urlunsplit(data: tuple[AnyStr, AnyStr, AnyStr, AnyStr, AnyStr]) -> AnyStr: ... @overload def urlunsplit(data: Sequence[AnyStr]) -> AnyStr: ... def urljoin(base: AnyStr, url: AnyStr, allow_fragments: bool = ...) -> AnyStr: ... -def urldefrag(url: AnyStr) -> Tuple[AnyStr, AnyStr]: ... +def urldefrag(url: AnyStr) -> tuple[AnyStr, AnyStr]: ... def unquote(s: AnyStr) -> AnyStr: ... -def parse_qs(qs: AnyStr, keep_blank_values: bool = ..., strict_parsing: bool = ...) -> Dict[AnyStr, List[AnyStr]]: ... -def parse_qsl(qs: AnyStr, keep_blank_values: int = ..., strict_parsing: bool = ...) -> List[Tuple[AnyStr, AnyStr]]: ... +def parse_qs(qs: AnyStr, keep_blank_values: bool = ..., strict_parsing: bool = ...) -> dict[AnyStr, list[AnyStr]]: ... +def parse_qsl(qs: AnyStr, keep_blank_values: int = ..., strict_parsing: bool = ...) -> list[tuple[AnyStr, AnyStr]]: ... diff --git a/mypy/typeshed/stdlib/@python2/uu.pyi b/mypy/typeshed/stdlib/@python2/uu.pyi index e8717aecbe365..a9585bac60a1b 100644 --- a/mypy/typeshed/stdlib/@python2/uu.pyi +++ b/mypy/typeshed/stdlib/@python2/uu.pyi @@ -1,6 +1,6 @@ -from typing import BinaryIO, Text, Union +from typing import BinaryIO, Text -_File = Union[Text, BinaryIO] +_File = Text | BinaryIO class Error(Exception): ... diff --git a/mypy/typeshed/stdlib/@python2/uuid.pyi b/mypy/typeshed/stdlib/@python2/uuid.pyi index 2c8a9fb1c0972..8ba2d7e5aa247 100644 --- a/mypy/typeshed/stdlib/@python2/uuid.pyi +++ b/mypy/typeshed/stdlib/@python2/uuid.pyi @@ -1,9 +1,9 @@ -from typing import Any, Text, Tuple +from typing import Any, Text # Because UUID has properties called int and bytes we need to rename these temporarily. _Int = int _Bytes = bytes -_FieldsType = Tuple[int, int, int, int, int, int] +_FieldsType = tuple[int, int, int, int, int, int] class UUID: def __init__( diff --git a/mypy/typeshed/stdlib/@python2/warnings.pyi b/mypy/typeshed/stdlib/@python2/warnings.pyi index 0d187bf70c339..2e872a4fb28ec 100644 --- a/mypy/typeshed/stdlib/@python2/warnings.pyi +++ b/mypy/typeshed/stdlib/@python2/warnings.pyi @@ -1,23 +1,23 @@ from _warnings import warn as warn, warn_explicit as warn_explicit from types import ModuleType, TracebackType -from typing import List, TextIO, Type, overload +from typing import TextIO, overload from typing_extensions import Literal def showwarning( - message: Warning | str, category: Type[Warning], filename: str, lineno: int, file: TextIO | None = ..., line: str | None = ... + message: Warning | str, category: type[Warning], filename: str, lineno: int, file: TextIO | None = ..., line: str | None = ... ) -> None: ... -def formatwarning(message: Warning | str, category: Type[Warning], filename: str, lineno: int, line: str | None = ...) -> str: ... +def formatwarning(message: Warning | str, category: type[Warning], filename: str, lineno: int, line: str | None = ...) -> str: ... def filterwarnings( - action: str, message: str = ..., category: Type[Warning] = ..., module: str = ..., lineno: int = ..., append: bool = ... + action: str, message: str = ..., category: type[Warning] = ..., module: str = ..., lineno: int = ..., append: bool = ... ) -> None: ... -def simplefilter(action: str, category: Type[Warning] = ..., lineno: int = ..., append: bool = ...) -> None: ... +def simplefilter(action: str, category: type[Warning] = ..., lineno: int = ..., append: bool = ...) -> None: ... def resetwarnings() -> None: ... class _OptionError(Exception): ... class WarningMessage: message: Warning | str - category: Type[Warning] + category: type[Warning] filename: str lineno: int file: TextIO | None @@ -25,7 +25,7 @@ class WarningMessage: def __init__( self, message: Warning | str, - category: Type[Warning], + category: type[Warning], filename: str, lineno: int, file: TextIO | None = ..., @@ -39,13 +39,13 @@ class catch_warnings: def __new__(cls, *, record: Literal[True], module: ModuleType | None = ...) -> _catch_warnings_with_records: ... @overload def __new__(cls, *, record: bool, module: ModuleType | None = ...) -> catch_warnings: ... - def __enter__(self) -> List[WarningMessage] | None: ... + def __enter__(self) -> list[WarningMessage] | None: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> None: ... class _catch_warnings_without_records(catch_warnings): def __enter__(self) -> None: ... class _catch_warnings_with_records(catch_warnings): - def __enter__(self) -> List[WarningMessage]: ... + def __enter__(self) -> list[WarningMessage]: ... diff --git a/mypy/typeshed/stdlib/@python2/wave.pyi b/mypy/typeshed/stdlib/@python2/wave.pyi index 0e9fe612cd24b..d13f74664f430 100644 --- a/mypy/typeshed/stdlib/@python2/wave.pyi +++ b/mypy/typeshed/stdlib/@python2/wave.pyi @@ -1,12 +1,12 @@ -from typing import IO, Any, BinaryIO, NoReturn, Text, Tuple, Union +from typing import IO, Any, BinaryIO, NoReturn, Text -_File = Union[Text, IO[bytes]] +_File = Text | IO[bytes] class Error(Exception): ... WAVE_FORMAT_PCM: int -_wave_params = Tuple[int, int, int, int, str, str] +_wave_params = tuple[int, int, int, int, str, str] class Wave_read: def __init__(self, f: _File) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/weakref.pyi b/mypy/typeshed/stdlib/@python2/weakref.pyi index 6467f3a7517ff..959c3e1b9d1e9 100644 --- a/mypy/typeshed/stdlib/@python2/weakref.pyi +++ b/mypy/typeshed/stdlib/@python2/weakref.pyi @@ -1,5 +1,5 @@ from _weakrefset import WeakSet as WeakSet -from typing import Any, Callable, Generic, Iterable, Iterator, List, Mapping, MutableMapping, Tuple, Type, TypeVar, overload +from typing import Any, Callable, Generic, Iterable, Iterator, Mapping, MutableMapping, TypeVar, overload from _weakref import ( CallableProxyType as CallableProxyType, @@ -12,18 +12,17 @@ from _weakref import ( ) from exceptions import ReferenceError as ReferenceError -_S = TypeVar("_S") _T = TypeVar("_T") _KT = TypeVar("_KT") _VT = TypeVar("_VT") -ProxyTypes: Tuple[Type[Any], ...] +ProxyTypes: tuple[type[Any], ...] class WeakValueDictionary(MutableMapping[_KT, _VT]): @overload def __init__(self) -> None: ... @overload - def __init__(self, __other: Mapping[_KT, _VT] | Iterable[Tuple[_KT, _VT]], **kwargs: _VT) -> None: ... + def __init__(self, __other: Mapping[_KT, _VT] | Iterable[tuple[_KT, _VT]], **kwargs: _VT) -> None: ... def __len__(self) -> int: ... def __getitem__(self, k: _KT) -> _VT: ... def __setitem__(self, k: _KT, v: _VT) -> None: ... @@ -31,28 +30,27 @@ class WeakValueDictionary(MutableMapping[_KT, _VT]): def has_key(self, key: object) -> bool: ... def __contains__(self, o: object) -> bool: ... def __iter__(self) -> Iterator[_KT]: ... - def __str__(self) -> str: ... def copy(self) -> WeakValueDictionary[_KT, _VT]: ... - def keys(self) -> List[_KT]: ... - def values(self) -> List[_VT]: ... - def items(self) -> List[Tuple[_KT, _VT]]: ... + def keys(self) -> list[_KT]: ... + def values(self) -> list[_VT]: ... + def items(self) -> list[tuple[_KT, _VT]]: ... def iterkeys(self) -> Iterator[_KT]: ... def itervalues(self) -> Iterator[_VT]: ... - def iteritems(self) -> Iterator[Tuple[_KT, _VT]]: ... + def iteritems(self) -> Iterator[tuple[_KT, _VT]]: ... def itervaluerefs(self) -> Iterator[KeyedRef[_KT, _VT]]: ... - def valuerefs(self) -> List[KeyedRef[_KT, _VT]]: ... + def valuerefs(self) -> list[KeyedRef[_KT, _VT]]: ... class KeyedRef(ref[_T], Generic[_KT, _T]): key: _KT # This __new__ method uses a non-standard name for the "cls" parameter - def __new__(type, ob: _T, callback: Callable[[_T], Any], key: _KT) -> KeyedRef[_KT, _T]: ... # type: ignore + def __new__(type, ob: _T, callback: Callable[[_T], Any], key: _KT) -> KeyedRef[_KT, _T]: ... def __init__(self, ob: _T, callback: Callable[[_T], Any], key: _KT) -> None: ... class WeakKeyDictionary(MutableMapping[_KT, _VT]): @overload def __init__(self, dict: None = ...) -> None: ... @overload - def __init__(self, dict: Mapping[_KT, _VT] | Iterable[Tuple[_KT, _VT]]) -> None: ... + def __init__(self, dict: Mapping[_KT, _VT] | Iterable[tuple[_KT, _VT]]) -> None: ... def __len__(self) -> int: ... def __getitem__(self, k: _KT) -> _VT: ... def __setitem__(self, k: _KT, v: _VT) -> None: ... @@ -60,13 +58,12 @@ class WeakKeyDictionary(MutableMapping[_KT, _VT]): def has_key(self, key: object) -> bool: ... def __contains__(self, o: object) -> bool: ... def __iter__(self) -> Iterator[_KT]: ... - def __str__(self) -> str: ... def copy(self) -> WeakKeyDictionary[_KT, _VT]: ... - def keys(self) -> List[_KT]: ... - def values(self) -> List[_VT]: ... - def items(self) -> List[Tuple[_KT, _VT]]: ... + def keys(self) -> list[_KT]: ... + def values(self) -> list[_VT]: ... + def items(self) -> list[tuple[_KT, _VT]]: ... def iterkeys(self) -> Iterator[_KT]: ... def itervalues(self) -> Iterator[_VT]: ... - def iteritems(self) -> Iterator[Tuple[_KT, _VT]]: ... + def iteritems(self) -> Iterator[tuple[_KT, _VT]]: ... def iterkeyrefs(self) -> Iterator[ref[_KT]]: ... - def keyrefs(self) -> List[ref[_KT]]: ... + def keyrefs(self) -> list[ref[_KT]]: ... diff --git a/mypy/typeshed/stdlib/@python2/webbrowser.pyi b/mypy/typeshed/stdlib/@python2/webbrowser.pyi index f634bc11ca7dd..33600fe3255d7 100644 --- a/mypy/typeshed/stdlib/@python2/webbrowser.pyi +++ b/mypy/typeshed/stdlib/@python2/webbrowser.pyi @@ -1,5 +1,5 @@ import sys -from typing import Callable, List, Sequence, Text +from typing import Callable, Sequence, Text class Error(Exception): ... @@ -12,7 +12,7 @@ def open_new(url: Text) -> bool: ... def open_new_tab(url: Text) -> bool: ... class BaseBrowser: - args: List[str] + args: list[str] name: str basename: str def __init__(self, name: Text = ...) -> None: ... @@ -21,7 +21,7 @@ class BaseBrowser: def open_new_tab(self, url: Text) -> bool: ... class GenericBrowser(BaseBrowser): - args: List[str] + args: list[str] name: str basename: str def __init__(self, name: Text | Sequence[Text]) -> None: ... @@ -31,45 +31,45 @@ class BackgroundBrowser(GenericBrowser): def open(self, url: Text, new: int = ..., autoraise: bool = ...) -> bool: ... class UnixBrowser(BaseBrowser): - raise_opts: List[str] | None + raise_opts: list[str] | None background: bool redirect_stdout: bool - remote_args: List[str] + remote_args: list[str] remote_action: str remote_action_newwin: str remote_action_newtab: str def open(self, url: Text, new: int = ..., autoraise: bool = ...) -> bool: ... class Mozilla(UnixBrowser): - remote_args: List[str] + remote_args: list[str] remote_action: str remote_action_newwin: str remote_action_newtab: str background: bool class Galeon(UnixBrowser): - raise_opts: List[str] - remote_args: List[str] + raise_opts: list[str] + remote_args: list[str] remote_action: str remote_action_newwin: str background: bool class Chrome(UnixBrowser): - remote_args: List[str] + remote_args: list[str] remote_action: str remote_action_newwin: str remote_action_newtab: str background: bool class Opera(UnixBrowser): - remote_args: List[str] + remote_args: list[str] remote_action: str remote_action_newwin: str remote_action_newtab: str background: bool class Elinks(UnixBrowser): - remote_args: List[str] + remote_args: list[str] remote_action: str remote_action_newwin: str remote_action_newtab: str @@ -91,6 +91,7 @@ if sys.platform == "darwin": name: str def __init__(self, name: Text) -> None: ... def open(self, url: Text, new: int = ..., autoraise: bool = ...) -> bool: ... + class MacOSXOSAScript(BaseBrowser): def __init__(self, name: Text) -> None: ... def open(self, url: Text, new: int = ..., autoraise: bool = ...) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/wsgiref/handlers.pyi b/mypy/typeshed/stdlib/@python2/wsgiref/handlers.pyi index d7e35ba8aff63..4dd63ac75035f 100644 --- a/mypy/typeshed/stdlib/@python2/wsgiref/handlers.pyi +++ b/mypy/typeshed/stdlib/@python2/wsgiref/handlers.pyi @@ -1,17 +1,17 @@ from abc import abstractmethod from types import TracebackType -from typing import IO, Callable, List, MutableMapping, Optional, Text, Tuple, Type +from typing import IO, Callable, MutableMapping, Optional, Text from .headers import Headers from .types import ErrorStream, InputStream, StartResponse, WSGIApplication, WSGIEnvironment from .util import FileWrapper -_exc_info = Tuple[Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType]] +_exc_info = tuple[Optional[type[BaseException]], Optional[BaseException], Optional[TracebackType]] def format_date_time(timestamp: float | None) -> str: ... # undocumented class BaseHandler: - wsgi_version: Tuple[int, int] # undocumented + wsgi_version: tuple[int, int] # undocumented wsgi_multithread: bool wsgi_multiprocess: bool wsgi_run_once: bool @@ -22,12 +22,12 @@ class BaseHandler: os_environ: MutableMapping[str, str] - wsgi_file_wrapper: Type[FileWrapper] | None - headers_class: Type[Headers] # undocumented + wsgi_file_wrapper: type[FileWrapper] | None + headers_class: type[Headers] # undocumented traceback_limit: int | None error_status: str - error_headers: List[Tuple[Text, Text]] + error_headers: list[tuple[Text, Text]] error_body: bytes def run(self, application: WSGIApplication) -> None: ... def setup_environ(self) -> None: ... @@ -36,7 +36,7 @@ class BaseHandler: def set_content_length(self) -> None: ... def cleanup_headers(self) -> None: ... def start_response( - self, status: Text, headers: List[Tuple[Text, Text]], exc_info: _exc_info | None = ... + self, status: Text, headers: list[tuple[Text, Text]], exc_info: _exc_info | None = ... ) -> Callable[[bytes], None]: ... def send_preamble(self) -> None: ... def write(self, data: bytes) -> None: ... @@ -48,7 +48,7 @@ class BaseHandler: def client_is_modern(self) -> bool: ... def log_exception(self, exc_info: _exc_info) -> None: ... def handle_error(self) -> None: ... - def error_output(self, environ: WSGIEnvironment, start_response: StartResponse) -> List[bytes]: ... + def error_output(self, environ: WSGIEnvironment, start_response: StartResponse) -> list[bytes]: ... @abstractmethod def _write(self, data: bytes) -> None: ... @abstractmethod diff --git a/mypy/typeshed/stdlib/@python2/wsgiref/headers.pyi b/mypy/typeshed/stdlib/@python2/wsgiref/headers.pyi index 08061fee76641..5c939a3425104 100644 --- a/mypy/typeshed/stdlib/@python2/wsgiref/headers.pyi +++ b/mypy/typeshed/stdlib/@python2/wsgiref/headers.pyi @@ -1,6 +1,6 @@ -from typing import List, Pattern, Tuple, overload +from typing import Pattern, overload -_HeaderList = List[Tuple[str, str]] +_HeaderList = list[tuple[str, str]] tspecials: Pattern[str] # undocumented @@ -12,13 +12,13 @@ class Headers: def __getitem__(self, name: str) -> str | None: ... def has_key(self, name: str) -> bool: ... def __contains__(self, name: str) -> bool: ... - def get_all(self, name: str) -> List[str]: ... + def get_all(self, name: str) -> list[str]: ... @overload def get(self, name: str, default: str) -> str: ... @overload def get(self, name: str, default: str | None = ...) -> str | None: ... - def keys(self) -> List[str]: ... - def values(self) -> List[str]: ... + def keys(self) -> list[str]: ... + def values(self) -> list[str]: ... def items(self) -> _HeaderList: ... def setdefault(self, name: str, value: str) -> str: ... def add_header(self, _name: str, _value: str | None, **_params: str | None) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/wsgiref/simple_server.pyi b/mypy/typeshed/stdlib/@python2/wsgiref/simple_server.pyi index a74a26fed9350..6faba328f9355 100644 --- a/mypy/typeshed/stdlib/@python2/wsgiref/simple_server.pyi +++ b/mypy/typeshed/stdlib/@python2/wsgiref/simple_server.pyi @@ -1,5 +1,5 @@ from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer -from typing import List, Type, TypeVar, overload +from typing import TypeVar, overload from .handlers import SimpleHandler from .types import ErrorStream, StartResponse, WSGIApplication, WSGIEnvironment @@ -25,13 +25,13 @@ class WSGIRequestHandler(BaseHTTPRequestHandler): def get_stderr(self) -> ErrorStream: ... def handle(self) -> None: ... -def demo_app(environ: WSGIEnvironment, start_response: StartResponse) -> List[bytes]: ... +def demo_app(environ: WSGIEnvironment, start_response: StartResponse) -> list[bytes]: ... _S = TypeVar("_S", bound=WSGIServer) @overload -def make_server(host: str, port: int, app: WSGIApplication, *, handler_class: Type[WSGIRequestHandler] = ...) -> WSGIServer: ... +def make_server(host: str, port: int, app: WSGIApplication, *, handler_class: type[WSGIRequestHandler] = ...) -> WSGIServer: ... @overload def make_server( - host: str, port: int, app: WSGIApplication, server_class: Type[_S], handler_class: Type[WSGIRequestHandler] = ... + host: str, port: int, app: WSGIApplication, server_class: type[_S], handler_class: type[WSGIRequestHandler] = ... ) -> _S: ... diff --git a/mypy/typeshed/stdlib/@python2/xdrlib.pyi b/mypy/typeshed/stdlib/@python2/xdrlib.pyi index 378504c372279..f59843f8ee9d9 100644 --- a/mypy/typeshed/stdlib/@python2/xdrlib.pyi +++ b/mypy/typeshed/stdlib/@python2/xdrlib.pyi @@ -1,4 +1,4 @@ -from typing import Callable, List, Sequence, TypeVar +from typing import Callable, Sequence, TypeVar _T = TypeVar("_T") @@ -50,6 +50,6 @@ class Unpacker: def unpack_string(self) -> bytes: ... def unpack_opaque(self) -> bytes: ... def unpack_bytes(self) -> bytes: ... - def unpack_list(self, unpack_item: Callable[[], _T]) -> List[_T]: ... - def unpack_farray(self, n: int, unpack_item: Callable[[], _T]) -> List[_T]: ... - def unpack_array(self, unpack_item: Callable[[], _T]) -> List[_T]: ... + def unpack_list(self, unpack_item: Callable[[], _T]) -> list[_T]: ... + def unpack_farray(self, n: int, unpack_item: Callable[[], _T]) -> list[_T]: ... + def unpack_array(self, unpack_item: Callable[[], _T]) -> list[_T]: ... diff --git a/mypy/typeshed/stdlib/@python2/xml/dom/domreg.pyi b/mypy/typeshed/stdlib/@python2/xml/dom/domreg.pyi index 2496b3884ea12..b9e2dd9eb2631 100644 --- a/mypy/typeshed/stdlib/@python2/xml/dom/domreg.pyi +++ b/mypy/typeshed/stdlib/@python2/xml/dom/domreg.pyi @@ -1,8 +1,8 @@ from _typeshed.xml import DOMImplementation -from typing import Callable, Dict, Iterable, Tuple +from typing import Callable, Iterable -well_known_implementations: Dict[str, str] -registered: Dict[str, Callable[[], DOMImplementation]] +well_known_implementations: dict[str, str] +registered: dict[str, Callable[[], DOMImplementation]] def registerDOMImplementation(name: str, factory: Callable[[], DOMImplementation]) -> None: ... -def getDOMImplementation(name: str | None = ..., features: str | Iterable[Tuple[str, str | None]] = ...) -> DOMImplementation: ... +def getDOMImplementation(name: str | None = ..., features: str | Iterable[tuple[str, str | None]] = ...) -> DOMImplementation: ... diff --git a/mypy/typeshed/stdlib/@python2/xml/dom/minicompat.pyi b/mypy/typeshed/stdlib/@python2/xml/dom/minicompat.pyi index e9b0395ab50df..e37b7cd891762 100644 --- a/mypy/typeshed/stdlib/@python2/xml/dom/minicompat.pyi +++ b/mypy/typeshed/stdlib/@python2/xml/dom/minicompat.pyi @@ -1,17 +1,17 @@ -from typing import Any, Iterable, List, Tuple, Type, TypeVar +from typing import Any, Iterable, TypeVar _T = TypeVar("_T") -StringTypes: Tuple[Type[str]] +StringTypes: tuple[type[str]] -class NodeList(List[_T]): +class NodeList(list[_T]): length: int def item(self, index: int) -> _T | None: ... -class EmptyNodeList(Tuple[Any, ...]): +class EmptyNodeList(tuple[Any, ...]): length: int def item(self, index: int) -> None: ... - def __add__(self, other: Iterable[_T]) -> NodeList[_T]: ... # type: ignore + def __add__(self, other: Iterable[_T]) -> NodeList[_T]: ... # type: ignore[override] def __radd__(self, other: Iterable[_T]) -> NodeList[_T]: ... -def defproperty(klass: Type[Any], name: str, doc: str) -> None: ... +def defproperty(klass: type[Any], name: str, doc: str) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/xml/dom/minidom.pyi b/mypy/typeshed/stdlib/@python2/xml/dom/minidom.pyi index ed46ac4561ece..b09d1a503b441 100644 --- a/mypy/typeshed/stdlib/@python2/xml/dom/minidom.pyi +++ b/mypy/typeshed/stdlib/@python2/xml/dom/minidom.pyi @@ -1,10 +1,9 @@ import xml.dom -from typing import IO, Any, Text as _Text, TypeVar +from _typeshed import Self +from typing import IO, Any, Text as _Text from xml.dom.xmlbuilder import DocumentLS, DOMImplementationLS from xml.sax.xmlreader import XMLReader -_T = TypeVar("_T") - def parse(file: str | IO[Any], parser: XMLReader | None = ..., bufsize: int | None = ...): ... def parseString(string: bytes | _Text, parser: XMLReader | None = ...): ... def getDOMImplementation(features=...): ... @@ -32,7 +31,7 @@ class Node(xml.dom.Node): def setUserData(self, key, data, handler): ... childNodes: Any def unlink(self) -> None: ... - def __enter__(self: _T) -> _T: ... + def __enter__(self: Self) -> Self: ... def __exit__(self, et, ev, tb) -> None: ... class DocumentFragment(Node): @@ -72,7 +71,7 @@ class NamedNodeMap: def values(self): ... def get(self, name, value: Any | None = ...): ... def __len__(self) -> int: ... - def __eq__(self, other: Any) -> bool: ... + def __eq__(self, other: object) -> bool: ... def __ge__(self, other: Any) -> bool: ... def __gt__(self, other: Any) -> bool: ... def __le__(self, other: Any) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/xml/dom/xmlbuilder.pyi b/mypy/typeshed/stdlib/@python2/xml/dom/xmlbuilder.pyi index d8936bdc2ab4e..a77c99790fdac 100644 --- a/mypy/typeshed/stdlib/@python2/xml/dom/xmlbuilder.pyi +++ b/mypy/typeshed/stdlib/@python2/xml/dom/xmlbuilder.pyi @@ -2,5 +2,5 @@ from typing import Any def __getattr__(name: str) -> Any: ... # incomplete -class DocumentLS(Any): ... # type: ignore -class DOMImplementationLS(Any): ... # type: ignore +class DocumentLS(Any): ... +class DOMImplementationLS(Any): ... diff --git a/mypy/typeshed/stdlib/@python2/xml/etree/ElementPath.pyi b/mypy/typeshed/stdlib/@python2/xml/etree/ElementPath.pyi index 02fe845675433..5a2dd69c1beea 100644 --- a/mypy/typeshed/stdlib/@python2/xml/etree/ElementPath.pyi +++ b/mypy/typeshed/stdlib/@python2/xml/etree/ElementPath.pyi @@ -1,14 +1,14 @@ -from typing import Callable, Dict, Generator, List, Pattern, Tuple, TypeVar +from typing import Callable, Generator, Pattern, TypeVar from xml.etree.ElementTree import Element xpath_tokenizer_re: Pattern[str] -_token = Tuple[str, str] +_token = tuple[str, str] _next = Callable[[], _token] -_callback = Callable[[_SelectorContext, List[Element]], Generator[Element, None, None]] +_callback = Callable[[_SelectorContext, list[Element]], Generator[Element, None, None]] -def xpath_tokenizer(pattern: str, namespaces: Dict[str, str] | None = ...) -> Generator[_token, None, None]: ... -def get_parent_map(context: _SelectorContext) -> Dict[Element, Element]: ... +def xpath_tokenizer(pattern: str, namespaces: dict[str, str] | None = ...) -> Generator[_token, None, None]: ... +def get_parent_map(context: _SelectorContext) -> dict[Element, Element]: ... def prepare_child(next: _next, token: _token) -> _callback: ... def prepare_star(next: _next, token: _token) -> _callback: ... def prepare_self(next: _next, token: _token) -> _callback: ... @@ -16,16 +16,16 @@ def prepare_descendant(next: _next, token: _token) -> _callback: ... def prepare_parent(next: _next, token: _token) -> _callback: ... def prepare_predicate(next: _next, token: _token) -> _callback: ... -ops: Dict[str, Callable[[_next, _token], _callback]] +ops: dict[str, Callable[[_next, _token], _callback]] class _SelectorContext: - parent_map: Dict[Element, Element] | None + parent_map: dict[Element, Element] | None root: Element def __init__(self, root: Element) -> None: ... _T = TypeVar("_T") -def iterfind(elem: Element, path: str, namespaces: Dict[str, str] | None = ...) -> Generator[Element, None, None]: ... -def find(elem: Element, path: str, namespaces: Dict[str, str] | None = ...) -> Element | None: ... -def findall(elem: Element, path: str, namespaces: Dict[str, str] | None = ...) -> List[Element]: ... -def findtext(elem: Element, path: str, default: _T | None = ..., namespaces: Dict[str, str] | None = ...) -> _T | str: ... +def iterfind(elem: Element, path: str, namespaces: dict[str, str] | None = ...) -> Generator[Element, None, None]: ... +def find(elem: Element, path: str, namespaces: dict[str, str] | None = ...) -> Element | None: ... +def findall(elem: Element, path: str, namespaces: dict[str, str] | None = ...) -> list[Element]: ... +def findtext(elem: Element, path: str, default: _T | None = ..., namespaces: dict[str, str] | None = ...) -> _T | str: ... diff --git a/mypy/typeshed/stdlib/@python2/xml/etree/ElementTree.pyi b/mypy/typeshed/stdlib/@python2/xml/etree/ElementTree.pyi index a7a0a1c65f463..f17ae52112522 100644 --- a/mypy/typeshed/stdlib/@python2/xml/etree/ElementTree.pyi +++ b/mypy/typeshed/stdlib/@python2/xml/etree/ElementTree.pyi @@ -3,19 +3,15 @@ from typing import ( IO, Any, Callable, - Dict, Generator, ItemsView, Iterable, Iterator, KeysView, - List, MutableSequence, Sequence, Text, - Tuple, TypeVar, - Union, overload, ) @@ -23,7 +19,7 @@ VERSION: str class ParseError(SyntaxError): code: int - position: Tuple[int, int] + position: tuple[int, int] def iselement(element: object) -> bool: ... @@ -32,7 +28,7 @@ _T = TypeVar("_T") # Type for parser inputs. Parser will accept any unicode/str/bytes and coerce, # and this is true in py2 and py3 (even fromstringlist() in python3 can be # called with a heterogeneous list) -_parser_input_type = Union[bytes, Text] +_parser_input_type = bytes | Text # Type for individual tag/attr/ns/text values in args to most functions. # In py2, the library accepts str or unicode everywhere and coerces @@ -41,7 +37,7 @@ _parser_input_type = Union[bytes, Text] # so we exclude it. (why? the parser never produces bytes when it parses XML, # so e.g., element.get(b'name') will always return None for parsed XML, even if # there is a 'name' attribute.) -_str_argument_type = Union[str, Text] +_str_argument_type = str | Text # Type for return values from individual tag/attr/text values # in python2, if the tag/attribute/text wasn't decode-able as ascii, it @@ -49,35 +45,35 @@ _str_argument_type = Union[str, Text] # _fixtext function in the source). Client code knows best: _str_result_type = Any -_file_or_filename = Union[Text, FileDescriptor, IO[Any]] +_file_or_filename = Text | FileDescriptor | IO[Any] class Element(MutableSequence[Element]): tag: _str_result_type - attrib: Dict[_str_result_type, _str_result_type] + attrib: dict[_str_result_type, _str_result_type] text: _str_result_type | None tail: _str_result_type | None def __init__( self, tag: _str_argument_type | Callable[..., Element], - attrib: Dict[_str_argument_type, _str_argument_type] = ..., + attrib: dict[_str_argument_type, _str_argument_type] = ..., **extra: _str_argument_type, ) -> None: ... def append(self, __subelement: Element) -> None: ... def clear(self) -> None: ... def extend(self, __elements: Iterable[Element]) -> None: ... def find( - self, path: _str_argument_type, namespaces: Dict[_str_argument_type, _str_argument_type] | None = ... + self, path: _str_argument_type, namespaces: dict[_str_argument_type, _str_argument_type] | None = ... ) -> Element | None: ... def findall( - self, path: _str_argument_type, namespaces: Dict[_str_argument_type, _str_argument_type] | None = ... - ) -> List[Element]: ... + self, path: _str_argument_type, namespaces: dict[_str_argument_type, _str_argument_type] | None = ... + ) -> list[Element]: ... @overload def findtext( - self, path: _str_argument_type, default: None = ..., namespaces: Dict[_str_argument_type, _str_argument_type] | None = ... + self, path: _str_argument_type, default: None = ..., namespaces: dict[_str_argument_type, _str_argument_type] | None = ... ) -> _str_result_type | None: ... @overload def findtext( - self, path: _str_argument_type, default: _T, namespaces: Dict[_str_argument_type, _str_argument_type] | None = ... + self, path: _str_argument_type, default: _T, namespaces: dict[_str_argument_type, _str_argument_type] | None = ... ) -> _T | _str_result_type: ... @overload def get(self, key: _str_argument_type, default: None = ...) -> _str_result_type | None: ... @@ -87,11 +83,11 @@ class Element(MutableSequence[Element]): def items(self) -> ItemsView[_str_result_type, _str_result_type]: ... def iter(self, tag: _str_argument_type | None = ...) -> Generator[Element, None, None]: ... def iterfind( - self, path: _str_argument_type, namespaces: Dict[_str_argument_type, _str_argument_type] | None = ... + self, path: _str_argument_type, namespaces: dict[_str_argument_type, _str_argument_type] | None = ... ) -> Generator[Element, None, None]: ... def itertext(self) -> Generator[_str_result_type, None, None]: ... def keys(self) -> KeysView[_str_result_type]: ... - def makeelement(self, __tag: _str_argument_type, __attrib: Dict[_str_argument_type, _str_argument_type]) -> Element: ... + def makeelement(self, __tag: _str_argument_type, __attrib: dict[_str_argument_type, _str_argument_type]) -> Element: ... def remove(self, __subelement: Element) -> None: ... def set(self, __key: _str_argument_type, __value: _str_argument_type) -> None: ... def __delitem__(self, i: int | slice) -> None: ... @@ -104,13 +100,13 @@ class Element(MutableSequence[Element]): def __setitem__(self, i: int, o: Element) -> None: ... @overload def __setitem__(self, s: slice, o: Iterable[Element]) -> None: ... - def getchildren(self) -> List[Element]: ... - def getiterator(self, tag: _str_argument_type | None = ...) -> List[Element]: ... + def getchildren(self) -> list[Element]: ... + def getiterator(self, tag: _str_argument_type | None = ...) -> list[Element]: ... def SubElement( parent: Element, tag: _str_argument_type, - attrib: Dict[_str_argument_type, _str_argument_type] = ..., + attrib: dict[_str_argument_type, _str_argument_type] = ..., **extra: _str_argument_type, ) -> Element: ... def Comment(text: _str_argument_type | None = ...) -> Element: ... @@ -127,23 +123,23 @@ class ElementTree: def getroot(self) -> Element: ... def parse(self, source: _file_or_filename, parser: XMLParser | None = ...) -> Element: ... def iter(self, tag: _str_argument_type | None = ...) -> Generator[Element, None, None]: ... - def getiterator(self, tag: _str_argument_type | None = ...) -> List[Element]: ... + def getiterator(self, tag: _str_argument_type | None = ...) -> list[Element]: ... def find( - self, path: _str_argument_type, namespaces: Dict[_str_argument_type, _str_argument_type] | None = ... + self, path: _str_argument_type, namespaces: dict[_str_argument_type, _str_argument_type] | None = ... ) -> Element | None: ... @overload def findtext( - self, path: _str_argument_type, default: None = ..., namespaces: Dict[_str_argument_type, _str_argument_type] | None = ... + self, path: _str_argument_type, default: None = ..., namespaces: dict[_str_argument_type, _str_argument_type] | None = ... ) -> _str_result_type | None: ... @overload def findtext( - self, path: _str_argument_type, default: _T, namespaces: Dict[_str_argument_type, _str_argument_type] | None = ... + self, path: _str_argument_type, default: _T, namespaces: dict[_str_argument_type, _str_argument_type] | None = ... ) -> _T | _str_result_type: ... def findall( - self, path: _str_argument_type, namespaces: Dict[_str_argument_type, _str_argument_type] | None = ... - ) -> List[Element]: ... + self, path: _str_argument_type, namespaces: dict[_str_argument_type, _str_argument_type] | None = ... + ) -> list[Element]: ... def iterfind( - self, path: _str_argument_type, namespaces: Dict[_str_argument_type, _str_argument_type] | None = ... + self, path: _str_argument_type, namespaces: dict[_str_argument_type, _str_argument_type] | None = ... ) -> Generator[Element, None, None]: ... def write( self, @@ -157,14 +153,14 @@ class ElementTree: def register_namespace(prefix: _str_argument_type, uri: _str_argument_type) -> None: ... def tostring(element: Element, encoding: str | None = ..., method: str | None = ...) -> bytes: ... -def tostringlist(element: Element, encoding: str | None = ..., method: str | None = ...) -> List[bytes]: ... +def tostringlist(element: Element, encoding: str | None = ..., method: str | None = ...) -> list[bytes]: ... def dump(elem: Element) -> None: ... def parse(source: _file_or_filename, parser: XMLParser | None = ...) -> ElementTree: ... def iterparse( source: _file_or_filename, events: Sequence[str] | None = ..., parser: XMLParser | None = ... -) -> Iterator[Tuple[str, Any]]: ... +) -> Iterator[tuple[str, Any]]: ... def XML(text: _parser_input_type, parser: XMLParser | None = ...) -> Element: ... -def XMLID(text: _parser_input_type, parser: XMLParser | None = ...) -> Tuple[Element, Dict[_str_result_type, Element]]: ... +def XMLID(text: _parser_input_type, parser: XMLParser | None = ...) -> tuple[Element, dict[_str_result_type, Element]]: ... # This is aliased to XML in the source. fromstring = XML @@ -180,13 +176,13 @@ def fromstringlist(sequence: Sequence[_parser_input_type], parser: XMLParser | N # TreeBuilder is called by client code (they could pass strs, bytes or whatever); # but we don't want to use a too-broad type, or it would be too hard to write # elementfactories. -_ElementFactory = Callable[[Any, Dict[Any, Any]], Element] +_ElementFactory = Callable[[Any, dict[Any, Any]], Element] class TreeBuilder: def __init__(self, element_factory: _ElementFactory | None = ...) -> None: ... def close(self) -> Element: ... def data(self, __data: _parser_input_type) -> None: ... - def start(self, __tag: _parser_input_type, __attrs: Dict[_parser_input_type, _parser_input_type]) -> Element: ... + def start(self, __tag: _parser_input_type, __attrs: dict[_parser_input_type, _parser_input_type]) -> Element: ... def end(self, __tag: _parser_input_type) -> Element: ... class XMLParser: diff --git a/mypy/typeshed/stdlib/@python2/xml/etree/cElementTree.pyi b/mypy/typeshed/stdlib/@python2/xml/etree/cElementTree.pyi index c41e2bee0eb15..02272d803c185 100644 --- a/mypy/typeshed/stdlib/@python2/xml/etree/cElementTree.pyi +++ b/mypy/typeshed/stdlib/@python2/xml/etree/cElementTree.pyi @@ -1 +1 @@ -from xml.etree.ElementTree import * # noqa: F403 +from xml.etree.ElementTree import * diff --git a/mypy/typeshed/stdlib/@python2/xml/sax/__init__.pyi b/mypy/typeshed/stdlib/@python2/xml/sax/__init__.pyi index 0c6da9a87d13c..7a35805f9f16b 100644 --- a/mypy/typeshed/stdlib/@python2/xml/sax/__init__.pyi +++ b/mypy/typeshed/stdlib/@python2/xml/sax/__init__.pyi @@ -1,4 +1,4 @@ -from typing import IO, Any, List, NoReturn, Text +from typing import IO, Any, NoReturn, Text from xml.sax.handler import ContentHandler, ErrorHandler from xml.sax.xmlreader import Locator, XMLReader @@ -19,9 +19,9 @@ class SAXNotRecognizedException(SAXException): ... class SAXNotSupportedException(SAXException): ... class SAXReaderNotAvailable(SAXNotSupportedException): ... -default_parser_list: List[str] +default_parser_list: list[str] -def make_parser(parser_list: List[str] = ...) -> XMLReader: ... +def make_parser(parser_list: list[str] = ...) -> XMLReader: ... def parse(source: str | IO[str] | IO[bytes], handler: ContentHandler, errorHandler: ErrorHandler = ...) -> None: ... def parseString(string: bytes | Text, handler: ContentHandler, errorHandler: ErrorHandler | None = ...) -> None: ... def _create_parser(parser_name: str) -> XMLReader: ... diff --git a/mypy/typeshed/stdlib/@python2/xml/sax/xmlreader.pyi b/mypy/typeshed/stdlib/@python2/xml/sax/xmlreader.pyi index 8afc566b16a10..684e9cef1f421 100644 --- a/mypy/typeshed/stdlib/@python2/xml/sax/xmlreader.pyi +++ b/mypy/typeshed/stdlib/@python2/xml/sax/xmlreader.pyi @@ -1,4 +1,4 @@ -from typing import Mapping, Tuple +from typing import Mapping class XMLReader: def __init__(self) -> None: ... @@ -64,7 +64,7 @@ class AttributesImpl: def values(self): ... class AttributesNSImpl(AttributesImpl): - def __init__(self, attrs: Mapping[Tuple[str, str], str], qnames: Mapping[Tuple[str, str], str]) -> None: ... + def __init__(self, attrs: Mapping[tuple[str, str], str], qnames: Mapping[tuple[str, str], str]) -> None: ... def getValueByQName(self, name): ... def getNameByQName(self, name): ... def getQNameByName(self, name): ... diff --git a/mypy/typeshed/stdlib/@python2/xmlrpclib.pyi b/mypy/typeshed/stdlib/@python2/xmlrpclib.pyi index 5a7d0fc34f0e4..2365bcf90cd1c 100644 --- a/mypy/typeshed/stdlib/@python2/xmlrpclib.pyi +++ b/mypy/typeshed/stdlib/@python2/xmlrpclib.pyi @@ -5,14 +5,14 @@ from ssl import SSLContext from StringIO import StringIO from time import struct_time from types import InstanceType -from typing import IO, Any, AnyStr, Callable, Iterable, List, Mapping, MutableMapping, Tuple, Type, Union +from typing import IO, Any, AnyStr, Callable, Iterable, Mapping, MutableMapping, Union _Unmarshaller = Any -_timeTuple = Tuple[int, int, int, int, int, int, int, int, int] +_timeTuple = tuple[int, int, int, int, int, int, int, int, int] # Represents types that can be compared against a DateTime object -_dateTimeComp = Union[unicode, DateTime, datetime] +_dateTimeComp = unicode | DateTime | datetime # A "host description" used by Transport factories -_hostDesc = Union[str, Tuple[str, Mapping[Any, Any]]] +_hostDesc = Union[str, tuple[str, Mapping[Any, Any]]] def escape(s: AnyStr, replace: Callable[[AnyStr, AnyStr, AnyStr], AnyStr] = ...) -> AnyStr: ... @@ -47,19 +47,19 @@ class Fault(Error): faultString: str def __init__(self, faultCode: Any, faultString: str, **extra: Any) -> None: ... -boolean: Type[bool] -Boolean: Type[bool] +boolean: type[bool] +Boolean: type[bool] class DateTime: value: str def __init__(self, value: str | unicode | datetime | float | int | _timeTuple | struct_time = ...) -> None: ... - def make_comparable(self, other: _dateTimeComp) -> Tuple[unicode, unicode]: ... + def make_comparable(self, other: _dateTimeComp) -> tuple[unicode, unicode]: ... def __lt__(self, other: _dateTimeComp) -> bool: ... def __le__(self, other: _dateTimeComp) -> bool: ... def __gt__(self, other: _dateTimeComp) -> bool: ... def __ge__(self, other: _dateTimeComp) -> bool: ... - def __eq__(self, other: _dateTimeComp) -> bool: ... # type: ignore - def __ne__(self, other: _dateTimeComp) -> bool: ... # type: ignore + def __eq__(self, other: _dateTimeComp) -> bool: ... # type: ignore[override] + def __ne__(self, other: _dateTimeComp) -> bool: ... # type: ignore[override] def timetuple(self) -> struct_time: ... def __cmp__(self, other: _dateTimeComp) -> int: ... def decode(self, data: Any) -> None: ... @@ -72,7 +72,7 @@ class Binary: def decode(self, data: str) -> None: ... def encode(self, out: IO[str]) -> None: ... -WRAPPERS: Tuple[Type[Any], ...] +WRAPPERS: tuple[type[Any], ...] # Still part of the public API, but see http://bugs.python.org/issue1773632 FastParser: None @@ -112,8 +112,8 @@ class Marshaller: | float | str | unicode - | List[Any] - | Tuple[Any, ...] + | list[Any] + | tuple[Any, ...] | Mapping[Any, Any] | datetime | InstanceType @@ -150,7 +150,7 @@ class Marshaller: class Unmarshaller: def append(self, object: Any) -> None: ... def __init__(self, use_datetime: bool = ...) -> None: ... - def close(self) -> Tuple[Any, ...]: ... + def close(self) -> tuple[Any, ...]: ... def getmethodname(self) -> str | None: ... def xml(self, encoding: str, standalone: bool) -> None: ... def start(self, tag: str, attrs: Any) -> None: ... @@ -173,25 +173,25 @@ class Unmarshaller: def end_methodName(self, data: str) -> None: ... class _MultiCallMethod: - def __init__(self, call_list: List[Tuple[str, Tuple[Any, ...]]], name: str) -> None: ... + def __init__(self, call_list: list[tuple[str, tuple[Any, ...]]], name: str) -> None: ... class MultiCallIterator: - def __init__(self, results: List[Any]) -> None: ... + def __init__(self, results: list[Any]) -> None: ... class MultiCall: def __init__(self, server: ServerProxy) -> None: ... def __getattr__(self, name: str) -> _MultiCallMethod: ... def __call__(self) -> MultiCallIterator: ... -def getparser(use_datetime: bool = ...) -> Tuple[ExpatParser | SlowParser, Unmarshaller]: ... +def getparser(use_datetime: bool = ...) -> tuple[ExpatParser | SlowParser, Unmarshaller]: ... def dumps( - params: Tuple[Any, ...] | Fault, + params: tuple[Any, ...] | Fault, methodname: str | None = ..., methodresponse: bool | None = ..., encoding: str | None = ..., allow_none: bool = ..., ) -> str: ... -def loads(data: str, use_datetime: bool = ...) -> Tuple[Tuple[Any, ...], str | None]: ... +def loads(data: str, use_datetime: bool = ...) -> tuple[tuple[Any, ...], str | None]: ... def gzip_encode(data: str) -> str: ... def gzip_decode(data: str, max_decode: int = ...) -> str: ... @@ -201,7 +201,7 @@ class GzipDecodedResponse(GzipFile): def close(self): ... class _Method: - def __init__(self, send: Callable[[str, Tuple[Any, ...]], Any], name: str) -> None: ... + def __init__(self, send: Callable[[str, tuple[Any, ...]], Any], name: str) -> None: ... def __getattr__(self, name: str) -> _Method: ... def __call__(self, *args: Any) -> Any: ... @@ -210,18 +210,18 @@ class Transport: accept_gzip_encoding: bool encode_threshold: int | None def __init__(self, use_datetime: bool = ...) -> None: ... - def request(self, host: _hostDesc, handler: str, request_body: str, verbose: bool = ...) -> Tuple[Any, ...]: ... + def request(self, host: _hostDesc, handler: str, request_body: str, verbose: bool = ...) -> tuple[Any, ...]: ... verbose: bool - def single_request(self, host: _hostDesc, handler: str, request_body: str, verbose: bool = ...) -> Tuple[Any, ...]: ... - def getparser(self) -> Tuple[ExpatParser | SlowParser, Unmarshaller]: ... - def get_host_info(self, host: _hostDesc) -> Tuple[str, List[Tuple[str, str]] | None, Mapping[Any, Any] | None]: ... + def single_request(self, host: _hostDesc, handler: str, request_body: str, verbose: bool = ...) -> tuple[Any, ...]: ... + def getparser(self) -> tuple[ExpatParser | SlowParser, Unmarshaller]: ... + def get_host_info(self, host: _hostDesc) -> tuple[str, list[tuple[str, str]] | None, Mapping[Any, Any] | None]: ... def make_connection(self, host: _hostDesc) -> HTTPConnection: ... def close(self) -> None: ... def send_request(self, connection: HTTPConnection, handler: str, request_body: str) -> None: ... def send_host(self, connection: HTTPConnection, host: str) -> None: ... def send_user_agent(self, connection: HTTPConnection) -> None: ... def send_content(self, connection: HTTPConnection, request_body: str) -> None: ... - def parse_response(self, response: HTTPResponse) -> Tuple[Any, ...]: ... + def parse_response(self, response: HTTPResponse) -> tuple[Any, ...]: ... class SafeTransport(Transport): def __init__(self, use_datetime: bool = ..., context: SSLContext | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/@python2/zipfile.pyi b/mypy/typeshed/stdlib/@python2/zipfile.pyi index 5a0879492a886..63c93b4828554 100644 --- a/mypy/typeshed/stdlib/@python2/zipfile.pyi +++ b/mypy/typeshed/stdlib/@python2/zipfile.pyi @@ -1,10 +1,10 @@ import io -from _typeshed import StrPath +from _typeshed import Self, StrPath from types import TracebackType -from typing import IO, Any, Callable, Dict, Iterable, List, Pattern, Protocol, Sequence, Text, Tuple, Type, Union +from typing import IO, Any, Callable, Iterable, Pattern, Protocol, Sequence, Text -_SZI = Union[Text, ZipInfo] -_DT = Tuple[int, int, int, int, int, int] +_SZI = Text | ZipInfo +_DT = tuple[int, int, int, int, int, int] class BadZipfile(Exception): ... @@ -18,7 +18,7 @@ class ZipExtFile(io.BufferedIOBase): PATTERN: Pattern[str] = ... - newlines: List[bytes] | None + newlines: list[bytes] | None mode: str name: str def __init__( @@ -30,10 +30,9 @@ class ZipExtFile(io.BufferedIOBase): close_fileobj: bool = ..., ) -> None: ... def read(self, n: int | None = ...) -> bytes: ... - def readline(self, limit: int = ...) -> bytes: ... # type: ignore - def __repr__(self) -> str: ... + def readline(self, limit: int = ...) -> bytes: ... # type: ignore[override] def peek(self, n: int = ...) -> bytes: ... - def read1(self, n: int | None) -> bytes: ... # type: ignore + def read1(self, n: int | None) -> bytes: ... class _Writer(Protocol): def write(self, __s: str) -> Any: ... @@ -42,19 +41,19 @@ class ZipFile: filename: Text | None debug: int comment: bytes - filelist: List[ZipInfo] + filelist: list[ZipInfo] fp: IO[bytes] | None - NameToInfo: Dict[Text, ZipInfo] + NameToInfo: dict[Text, ZipInfo] start_dir: int # undocumented def __init__(self, file: StrPath | IO[bytes], mode: Text = ..., compression: int = ..., allowZip64: bool = ...) -> None: ... - def __enter__(self) -> ZipFile: ... + def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> None: ... def close(self) -> None: ... def getinfo(self, name: Text) -> ZipInfo: ... - def infolist(self) -> List[ZipInfo]: ... - def namelist(self) -> List[Text]: ... + def infolist(self) -> list[ZipInfo]: ... + def namelist(self) -> list[Text]: ... def open(self, name: _SZI, mode: Text = ..., pwd: bytes | None = ..., *, force_zip64: bool = ...) -> IO[bytes]: ... def extract(self, member: _SZI, path: StrPath | None = ..., pwd: bytes | None = ...) -> str: ... def extractall(self, path: StrPath | None = ..., members: Iterable[Text] | None = ..., pwd: bytes | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/VERSIONS b/mypy/typeshed/stdlib/VERSIONS index e82161d97cb64..d3ba459dd9e36 100644 --- a/mypy/typeshed/stdlib/VERSIONS +++ b/mypy/typeshed/stdlib/VERSIONS @@ -62,6 +62,15 @@ array: 2.7- ast: 2.7- asynchat: 2.7- asyncio: 3.4- +asyncio.mixins: 3.10- +asyncio.compat: 3.4-3.6 +asyncio.exceptions: 3.8- +asyncio.format_helpers: 3.7- +asyncio.runners: 3.7- +asyncio.staggered: 3.8- +asyncio.taskgroups: 3.11- +asyncio.threads: 3.9- +asyncio.trsock: 3.8- asyncore: 2.7- atexit: 2.7- audioop: 2.7- @@ -104,6 +113,7 @@ difflib: 2.7- dis: 2.7- distutils: 2.7- distutils.command.bdist_msi: 2.7-3.10 +distutils.command.bdist_wininst: 2.7-3.9 doctest: 2.7- dummy_threading: 2.7-3.8 email: 2.7- @@ -164,6 +174,7 @@ modulefinder: 2.7- msilib: 2.7- msvcrt: 2.7- multiprocessing: 2.7- +multiprocessing.shared_memory: 3.8- netrc: 2.7- nis: 2.7- nntplib: 2.7- @@ -251,6 +262,7 @@ timeit: 2.7- tkinter: 3.0- token: 2.7- tokenize: 2.7- +tomllib: 3.11- trace: 2.7- traceback: 2.7- tracemalloc: 3.4- @@ -262,6 +274,7 @@ typing_extensions: 2.7- unicodedata: 2.7- unittest: 2.7- unittest._log: 3.9- +unittest.async_case: 3.8- urllib: 2.7- uu: 2.7- uuid: 2.7- diff --git a/mypy/typeshed/stdlib/_ast.pyi b/mypy/typeshed/stdlib/_ast.pyi index 08725cfc0b778..f801b5deb0d97 100644 --- a/mypy/typeshed/stdlib/_ast.pyi +++ b/mypy/typeshed/stdlib/_ast.pyi @@ -1,18 +1,19 @@ import sys -import typing from typing import Any, ClassVar from typing_extensions import Literal -PyCF_ONLY_AST: int +PyCF_ONLY_AST: Literal[1024] if sys.version_info >= (3, 8): - PyCF_TYPE_COMMENTS: int - PyCF_ALLOW_TOP_LEVEL_AWAIT: int + PyCF_TYPE_COMMENTS: Literal[4096] + PyCF_ALLOW_TOP_LEVEL_AWAIT: Literal[8192] _identifier = str class AST: - _attributes: ClassVar[typing.Tuple[str, ...]] - _fields: ClassVar[typing.Tuple[str, ...]] + if sys.version_info >= (3, 10): + __match_args__ = () + _attributes: ClassVar[tuple[str, ...]] + _fields: ClassVar[tuple[str, ...]] def __init__(self, *args: Any, **kwargs: Any) -> None: ... # TODO: Not all nodes have all of the following attributes lineno: int @@ -26,26 +27,40 @@ class mod(AST): ... if sys.version_info >= (3, 8): class type_ignore(AST): ... + class TypeIgnore(type_ignore): + if sys.version_info >= (3, 10): + __match_args__ = ("lineno", "tag") tag: str + class FunctionType(mod): + if sys.version_info >= (3, 10): + __match_args__ = ("argtypes", "returns") argtypes: list[expr] returns: expr class Module(mod): + if sys.version_info >= (3, 10): + __match_args__ = ("body", "type_ignores") body: list[stmt] if sys.version_info >= (3, 8): type_ignores: list[TypeIgnore] class Interactive(mod): + if sys.version_info >= (3, 10): + __match_args__ = ("body",) body: list[stmt] class Expression(mod): + if sys.version_info >= (3, 10): + __match_args__ = ("body",) body: expr class stmt(AST): ... class FunctionDef(stmt): + if sys.version_info >= (3, 10): + __match_args__ = ("name", "args", "body", "decorator_list", "returns", "type_comment") name: _identifier args: arguments body: list[stmt] @@ -53,6 +68,8 @@ class FunctionDef(stmt): returns: expr | None class AsyncFunctionDef(stmt): + if sys.version_info >= (3, 10): + __match_args__ = ("name", "args", "body", "decorator_list", "returns", "type_comment") name: _identifier args: arguments body: list[stmt] @@ -60,6 +77,8 @@ class AsyncFunctionDef(stmt): returns: expr | None class ClassDef(stmt): + if sys.version_info >= (3, 10): + __match_args__ = ("name", "bases", "keywords", "body", "decorator_list") name: _identifier bases: list[expr] keywords: list[keyword] @@ -67,85 +86,123 @@ class ClassDef(stmt): decorator_list: list[expr] class Return(stmt): + if sys.version_info >= (3, 10): + __match_args__ = ("value",) value: expr | None class Delete(stmt): + if sys.version_info >= (3, 10): + __match_args__ = ("targets",) targets: list[expr] class Assign(stmt): + if sys.version_info >= (3, 10): + __match_args__ = ("targets", "value", "type_comment") targets: list[expr] value: expr class AugAssign(stmt): + if sys.version_info >= (3, 10): + __match_args__ = ("target", "op", "value") target: expr op: operator value: expr class AnnAssign(stmt): + if sys.version_info >= (3, 10): + __match_args__ = ("target", "annotation", "value", "simple") target: expr annotation: expr value: expr | None simple: int class For(stmt): + if sys.version_info >= (3, 10): + __match_args__ = ("target", "iter", "body", "orelse", "type_comment") target: expr iter: expr body: list[stmt] orelse: list[stmt] class AsyncFor(stmt): + if sys.version_info >= (3, 10): + __match_args__ = ("target", "iter", "body", "orelse", "type_comment") target: expr iter: expr body: list[stmt] orelse: list[stmt] class While(stmt): + if sys.version_info >= (3, 10): + __match_args__ = ("test", "body", "orelse") test: expr body: list[stmt] orelse: list[stmt] class If(stmt): + if sys.version_info >= (3, 10): + __match_args__ = ("test", "body", "orelse") test: expr body: list[stmt] orelse: list[stmt] class With(stmt): + if sys.version_info >= (3, 10): + __match_args__ = ("items", "body", "type_comment") items: list[withitem] body: list[stmt] class AsyncWith(stmt): + if sys.version_info >= (3, 10): + __match_args__ = ("items", "body", "type_comment") items: list[withitem] body: list[stmt] class Raise(stmt): + if sys.version_info >= (3, 10): + __match_args__ = ("exc", "cause") exc: expr | None cause: expr | None class Try(stmt): + if sys.version_info >= (3, 10): + __match_args__ = ("body", "handlers", "orelse", "finalbody") body: list[stmt] handlers: list[ExceptHandler] orelse: list[stmt] finalbody: list[stmt] class Assert(stmt): + if sys.version_info >= (3, 10): + __match_args__ = ("test", "msg") test: expr msg: expr | None class Import(stmt): + if sys.version_info >= (3, 10): + __match_args__ = ("names",) names: list[alias] class ImportFrom(stmt): + if sys.version_info >= (3, 10): + __match_args__ = ("module", "names", "level") module: _identifier | None names: list[alias] level: int class Global(stmt): + if sys.version_info >= (3, 10): + __match_args__ = ("names",) names: list[_identifier] class Nonlocal(stmt): + if sys.version_info >= (3, 10): + __match_args__ = ("names",) names: list[_identifier] class Expr(stmt): + if sys.version_info >= (3, 10): + __match_args__ = ("value",) value: expr class Pass(stmt): ... @@ -154,90 +211,132 @@ class Continue(stmt): ... class expr(AST): ... class BoolOp(expr): + if sys.version_info >= (3, 10): + __match_args__ = ("op", "values") op: boolop values: list[expr] class BinOp(expr): + if sys.version_info >= (3, 10): + __match_args__ = ("left", "op", "right") left: expr op: operator right: expr class UnaryOp(expr): + if sys.version_info >= (3, 10): + __match_args__ = ("op", "operand") op: unaryop operand: expr class Lambda(expr): + if sys.version_info >= (3, 10): + __match_args__ = ("args", "body") args: arguments body: expr class IfExp(expr): + if sys.version_info >= (3, 10): + __match_args__ = ("test", "body", "orelse") test: expr body: expr orelse: expr class Dict(expr): + if sys.version_info >= (3, 10): + __match_args__ = ("keys", "values") keys: list[expr | None] values: list[expr] class Set(expr): + if sys.version_info >= (3, 10): + __match_args__ = ("elts",) elts: list[expr] class ListComp(expr): + if sys.version_info >= (3, 10): + __match_args__ = ("elt", "generators") elt: expr generators: list[comprehension] class SetComp(expr): + if sys.version_info >= (3, 10): + __match_args__ = ("elt", "generators") elt: expr generators: list[comprehension] class DictComp(expr): + if sys.version_info >= (3, 10): + __match_args__ = ("key", "value", "generators") key: expr value: expr generators: list[comprehension] class GeneratorExp(expr): + if sys.version_info >= (3, 10): + __match_args__ = ("elt", "generators") elt: expr generators: list[comprehension] class Await(expr): + if sys.version_info >= (3, 10): + __match_args__ = ("value",) value: expr class Yield(expr): + if sys.version_info >= (3, 10): + __match_args__ = ("value",) value: expr | None class YieldFrom(expr): + if sys.version_info >= (3, 10): + __match_args__ = ("value",) value: expr class Compare(expr): + if sys.version_info >= (3, 10): + __match_args__ = ("left", "ops", "comparators") left: expr ops: list[cmpop] comparators: list[expr] class Call(expr): + if sys.version_info >= (3, 10): + __match_args__ = ("func", "args", "keywords") func: expr args: list[expr] keywords: list[keyword] class FormattedValue(expr): + if sys.version_info >= (3, 10): + __match_args__ = ("value", "conversion", "format_spec") value: expr conversion: int | None format_spec: expr | None class JoinedStr(expr): + if sys.version_info >= (3, 10): + __match_args__ = ("values",) values: list[expr] if sys.version_info < (3, 8): class Num(expr): # Deprecated in 3.8; use Constant n: complex + class Str(expr): # Deprecated in 3.8; use Constant s: str + class Bytes(expr): # Deprecated in 3.8; use Constant s: bytes + class NameConstant(expr): # Deprecated in 3.8; use Constant value: Any + class Ellipsis(expr): ... # Deprecated in 3.8; use Constant class Constant(expr): + if sys.version_info >= (3, 10): + __match_args__ = ("value", "kind") value: Any # None, str, bytes, bool, int, float, complex, Ellipsis kind: str | None # Aliases for value, for backwards compatibility @@ -246,10 +345,14 @@ class Constant(expr): if sys.version_info >= (3, 8): class NamedExpr(expr): + if sys.version_info >= (3, 10): + __match_args__ = ("target", "value") target: expr value: expr class Attribute(expr): + if sys.version_info >= (3, 10): + __match_args__ = ("value", "attr", "ctx") value: expr attr: _identifier ctx: expr_context @@ -261,6 +364,8 @@ else: _SliceT = slice class Slice(_SliceT): + if sys.version_info >= (3, 10): + __match_args__ = ("lower", "upper", "step") lower: expr | None upper: expr | None step: expr | None @@ -268,27 +373,38 @@ class Slice(_SliceT): if sys.version_info < (3, 9): class ExtSlice(slice): dims: list[slice] + class Index(slice): value: expr class Subscript(expr): + if sys.version_info >= (3, 10): + __match_args__ = ("value", "slice", "ctx") value: expr slice: _SliceT ctx: expr_context class Starred(expr): + if sys.version_info >= (3, 10): + __match_args__ = ("value", "ctx") value: expr ctx: expr_context class Name(expr): + if sys.version_info >= (3, 10): + __match_args__ = ("id", "ctx") id: _identifier ctx: expr_context class List(expr): + if sys.version_info >= (3, 10): + __match_args__ = ("elts", "ctx") elts: list[expr] ctx: expr_context class Tuple(expr): + if sys.version_info >= (3, 10): + __match_args__ = ("elts", "ctx") elts: list[expr] ctx: expr_context @@ -298,6 +414,7 @@ if sys.version_info < (3, 9): class AugLoad(expr_context): ... class AugStore(expr_context): ... class Param(expr_context): ... + class Suite(mod): body: list[stmt] @@ -339,6 +456,8 @@ class NotEq(cmpop): ... class NotIn(cmpop): ... class comprehension(AST): + if sys.version_info >= (3, 10): + __match_args__ = ("target", "iter", "ifs", "is_async") target: expr iter: expr ifs: list[expr] @@ -347,11 +466,15 @@ class comprehension(AST): class excepthandler(AST): ... class ExceptHandler(excepthandler): + if sys.version_info >= (3, 10): + __match_args__ = ("type", "name", "body") type: expr | None name: _identifier | None body: list[stmt] class arguments(AST): + if sys.version_info >= (3, 10): + __match_args__ = ("posonlyargs", "args", "vararg", "kwonlyargs", "kw_defaults", "kwarg", "defaults") if sys.version_info >= (3, 8): posonlyargs: list[arg] args: list[arg] @@ -362,51 +485,79 @@ class arguments(AST): defaults: list[expr] class arg(AST): + if sys.version_info >= (3, 10): + __match_args__ = ("arg", "annotation", "type_comment") arg: _identifier annotation: expr | None class keyword(AST): + if sys.version_info >= (3, 10): + __match_args__ = ("arg", "value") arg: _identifier | None value: expr class alias(AST): + if sys.version_info >= (3, 10): + __match_args__ = ("name", "asname") name: _identifier asname: _identifier | None class withitem(AST): + if sys.version_info >= (3, 10): + __match_args__ = ("context_expr", "optional_vars") context_expr: expr optional_vars: expr | None if sys.version_info >= (3, 10): class Match(stmt): + __match_args__ = ("subject", "cases") subject: expr cases: list[match_case] + class pattern(AST): ... # Without the alias, Pyright complains variables named pattern are recursively defined _pattern = pattern + class match_case(AST): + __match_args__ = ("pattern", "guard", "body") pattern: _pattern guard: expr | None body: list[stmt] + class MatchValue(pattern): + __match_args__ = ("value",) value: expr + class MatchSingleton(pattern): + __match_args__ = ("value",) value: Literal[True, False, None] + class MatchSequence(pattern): + __match_args__ = ("patterns",) patterns: list[pattern] + class MatchStar(pattern): + __match_args__ = ("name",) name: _identifier | None + class MatchMapping(pattern): + __match_args__ = ("keys", "patterns", "rest") keys: list[expr] patterns: list[pattern] rest: _identifier | None + class MatchClass(pattern): + __match_args__ = ("cls", "patterns", "kwd_attrs", "kwd_patterns") cls: expr patterns: list[pattern] kwd_attrs: list[_identifier] kwd_patterns: list[pattern] + class MatchAs(pattern): + __match_args__ = ("pattern", "name") pattern: _pattern | None name: _identifier | None + class MatchOr(pattern): + __match_args__ = ("patterns",) patterns: list[pattern] diff --git a/mypy/typeshed/stdlib/_bisect.pyi b/mypy/typeshed/stdlib/_bisect.pyi index 1f67dadd89a00..5608094ccbd6b 100644 --- a/mypy/typeshed/stdlib/_bisect.pyi +++ b/mypy/typeshed/stdlib/_bisect.pyi @@ -1,35 +1,73 @@ import sys -from _typeshed import SupportsRichComparison -from typing import Callable, MutableSequence, Sequence, TypeVar +from _typeshed import SupportsRichComparisonT +from typing import Callable, MutableSequence, Sequence, TypeVar, overload _T = TypeVar("_T") if sys.version_info >= (3, 10): + @overload def bisect_left( - a: Sequence[_T], x: _T, lo: int = ..., hi: int | None = ..., *, key: Callable[[_T], SupportsRichComparison] | None = ... + a: Sequence[SupportsRichComparisonT], x: SupportsRichComparisonT, lo: int = ..., hi: int | None = ..., *, key: None = ... ) -> int: ... + @overload + def bisect_left( + a: Sequence[_T], + x: SupportsRichComparisonT, + lo: int = ..., + hi: int | None = ..., + *, + key: Callable[[_T], SupportsRichComparisonT] = ..., + ) -> int: ... + @overload def bisect_right( - a: Sequence[_T], x: _T, lo: int = ..., hi: int | None = ..., *, key: Callable[[_T], SupportsRichComparison] | None = ... + a: Sequence[SupportsRichComparisonT], x: SupportsRichComparisonT, lo: int = ..., hi: int | None = ..., *, key: None = ... ) -> int: ... + @overload + def bisect_right( + a: Sequence[_T], + x: SupportsRichComparisonT, + lo: int = ..., + hi: int | None = ..., + *, + key: Callable[[_T], SupportsRichComparisonT] = ..., + ) -> int: ... + @overload def insort_left( - a: MutableSequence[_T], - x: _T, + a: MutableSequence[SupportsRichComparisonT], + x: SupportsRichComparisonT, lo: int = ..., hi: int | None = ..., *, - key: Callable[[_T], SupportsRichComparison] | None = ..., + key: None = ..., + ) -> None: ... + @overload + def insort_left( + a: MutableSequence[_T], x: _T, lo: int = ..., hi: int | None = ..., *, key: Callable[[_T], SupportsRichComparisonT] = ... ) -> None: ... + @overload def insort_right( - a: MutableSequence[_T], - x: _T, + a: MutableSequence[SupportsRichComparisonT], + x: SupportsRichComparisonT, lo: int = ..., hi: int | None = ..., *, - key: Callable[[_T], SupportsRichComparison] | None = ..., + key: None = ..., + ) -> None: ... + @overload + def insort_right( + a: MutableSequence[_T], x: _T, lo: int = ..., hi: int | None = ..., *, key: Callable[[_T], SupportsRichComparisonT] = ... ) -> None: ... else: - def bisect_left(a: Sequence[_T], x: _T, lo: int = ..., hi: int | None = ...) -> int: ... - def bisect_right(a: Sequence[_T], x: _T, lo: int = ..., hi: int | None = ...) -> int: ... - def insort_left(a: MutableSequence[_T], x: _T, lo: int = ..., hi: int | None = ...) -> None: ... - def insort_right(a: MutableSequence[_T], x: _T, lo: int = ..., hi: int | None = ...) -> None: ... + def bisect_left( + a: Sequence[SupportsRichComparisonT], x: SupportsRichComparisonT, lo: int = ..., hi: int | None = ... + ) -> int: ... + def bisect_right( + a: Sequence[SupportsRichComparisonT], x: SupportsRichComparisonT, lo: int = ..., hi: int | None = ... + ) -> int: ... + def insort_left( + a: MutableSequence[SupportsRichComparisonT], x: SupportsRichComparisonT, lo: int = ..., hi: int | None = ... + ) -> None: ... + def insort_right( + a: MutableSequence[SupportsRichComparisonT], x: SupportsRichComparisonT, lo: int = ..., hi: int | None = ... + ) -> None: ... diff --git a/mypy/typeshed/stdlib/_codecs.pyi b/mypy/typeshed/stdlib/_codecs.pyi index 470722a293a3e..1781a2418ca05 100644 --- a/mypy/typeshed/stdlib/_codecs.pyi +++ b/mypy/typeshed/stdlib/_codecs.pyi @@ -1,12 +1,12 @@ import codecs import sys -from typing import Any, Callable, Union +from typing import Any, Callable # This type is not exposed; it is defined in unicodeobject.c class _EncodingMap: def size(self) -> int: ... -_MapT = Union[dict[int, int], _EncodingMap] +_MapT = dict[int, int] | _EncodingMap _Handler = Callable[[Exception], tuple[str, int]] def register(__search_function: Callable[[str], Any]) -> None: ... diff --git a/mypy/typeshed/stdlib/_collections_abc.pyi b/mypy/typeshed/stdlib/_collections_abc.pyi index 223b5fb8d62ea..bd8d35641b375 100644 --- a/mypy/typeshed/stdlib/_collections_abc.pyi +++ b/mypy/typeshed/stdlib/_collections_abc.pyi @@ -65,14 +65,17 @@ _VT_co = TypeVar("_VT_co", covariant=True) # Value type covariant containers. @final class dict_keys(KeysView[_KT_co], Generic[_KT_co, _VT_co]): # undocumented if sys.version_info >= (3, 10): - mapping: MappingProxyType[_KT_co, _VT_co] + @property + def mapping(self) -> MappingProxyType[_KT_co, _VT_co]: ... @final class dict_values(ValuesView[_VT_co], Generic[_KT_co, _VT_co]): # undocumented if sys.version_info >= (3, 10): - mapping: MappingProxyType[_KT_co, _VT_co] + @property + def mapping(self) -> MappingProxyType[_KT_co, _VT_co]: ... @final class dict_items(ItemsView[_KT_co, _VT_co], Generic[_KT_co, _VT_co]): # undocumented if sys.version_info >= (3, 10): - mapping: MappingProxyType[_KT_co, _VT_co] + @property + def mapping(self) -> MappingProxyType[_KT_co, _VT_co]: ... diff --git a/mypy/typeshed/stdlib/_compression.pyi b/mypy/typeshed/stdlib/_compression.pyi index 31940e3eb15b2..e71f7d14bd2b0 100644 --- a/mypy/typeshed/stdlib/_compression.pyi +++ b/mypy/typeshed/stdlib/_compression.pyi @@ -1,8 +1,8 @@ from _typeshed import WriteableBuffer -from io import BufferedIOBase, RawIOBase -from typing import Any, Callable, Protocol, Type +from io import DEFAULT_BUFFER_SIZE, BufferedIOBase, RawIOBase +from typing import Any, Callable, Protocol -BUFFER_SIZE: Any +BUFFER_SIZE = DEFAULT_BUFFER_SIZE class _Reader(Protocol): def read(self, __n: int) -> bytes: ... @@ -16,7 +16,7 @@ class DecompressReader(RawIOBase): self, fp: _Reader, decomp_factory: Callable[..., object], - trailing_error: Type[Exception] | tuple[Type[Exception], ...] = ..., + trailing_error: type[Exception] | tuple[type[Exception], ...] = ..., **decomp_args: Any, ) -> None: ... def readable(self) -> bool: ... diff --git a/mypy/typeshed/stdlib/_csv.pyi b/mypy/typeshed/stdlib/_csv.pyi index 54e9099bbdcd3..161a89778de8d 100644 --- a/mypy/typeshed/stdlib/_csv.pyi +++ b/mypy/typeshed/stdlib/_csv.pyi @@ -1,9 +1,12 @@ -from typing import Any, Iterable, Iterator, Protocol, Type, Union +from typing import Any, Iterable, Iterator, Protocol, Union +from typing_extensions import Literal -QUOTE_ALL: int -QUOTE_MINIMAL: int -QUOTE_NONE: int -QUOTE_NONNUMERIC: int +__version__: str + +QUOTE_ALL: Literal[1] +QUOTE_MINIMAL: Literal[0] +QUOTE_NONE: Literal[3] +QUOTE_NONNUMERIC: Literal[2] class Error(Exception): ... @@ -18,7 +21,7 @@ class Dialect: strict: int def __init__(self) -> None: ... -_DialectLike = Union[str, Dialect, Type[Dialect]] +_DialectLike = Union[str, Dialect, type[Dialect]] class _reader(Iterator[list[str]]): dialect: Dialect diff --git a/mypy/typeshed/stdlib/_curses.pyi b/mypy/typeshed/stdlib/_curses.pyi index 9f23eeb1c6dc6..e193759bdc6eb 100644 --- a/mypy/typeshed/stdlib/_curses.pyi +++ b/mypy/typeshed/stdlib/_curses.pyi @@ -1,9 +1,10 @@ import sys from _typeshed import SupportsRead -from typing import IO, Any, NamedTuple, Union, overload +from typing import IO, Any, NamedTuple, overload +from typing_extensions import final if sys.platform != "win32": - _chtype = Union[str, bytes, int] + _chtype = str | bytes | int # ACS codes are only initialized after initscr is called ACS_BBSS: int @@ -280,6 +281,7 @@ if sys.platform != "win32": def color_pair(pair_number: int) -> int: ... else: def color_pair(__color_number: int) -> int: ... + def curs_set(__visibility: int) -> int: ... def def_prog_mode() -> None: ... def def_shell_mode() -> None: ... @@ -294,6 +296,7 @@ if sys.platform != "win32": if sys.version_info >= (3, 9): def get_escdelay() -> int: ... def get_tabsize() -> int: ... + def getmouse() -> tuple[int, int, int, int, int]: ... def getsyx() -> tuple[int, int]: ... def getwin(__file: SupportsRead[bytes]) -> _CursesWindow: ... @@ -301,6 +304,7 @@ if sys.platform != "win32": def has_colors() -> bool: ... if sys.version_info >= (3, 10): def has_extended_color_support() -> bool: ... + def has_ic() -> bool: ... def has_il() -> bool: ... def has_key(__key: int) -> bool: ... @@ -339,6 +343,7 @@ if sys.platform != "win32": if sys.version_info >= (3, 9): def set_escdelay(__ms: int) -> None: ... def set_tabsize(__size: int) -> None: ... + def setsyx(__y: int, __x: int) -> None: ... def setupterm(term: str | None = ..., fd: int = ...) -> None: ... def start_color() -> None: ... @@ -367,7 +372,10 @@ if sys.platform != "win32": def update_lines_cols() -> None: ... def use_default_colors() -> None: ... def use_env(__flag: bool) -> None: ... + class error(Exception): ... + + @final class _CursesWindow: encoding: str @overload diff --git a/mypy/typeshed/stdlib/_decimal.pyi b/mypy/typeshed/stdlib/_decimal.pyi index e58805855b138..de49a787283d6 100644 --- a/mypy/typeshed/stdlib/_decimal.pyi +++ b/mypy/typeshed/stdlib/_decimal.pyi @@ -1 +1,3 @@ from decimal import * + +__libmpdec_version__: str diff --git a/mypy/typeshed/stdlib/_dummy_thread.pyi b/mypy/typeshed/stdlib/_dummy_thread.pyi index 6e936726a48fe..97ba17ae497d4 100644 --- a/mypy/typeshed/stdlib/_dummy_thread.pyi +++ b/mypy/typeshed/stdlib/_dummy_thread.pyi @@ -1,3 +1,4 @@ +from types import TracebackType from typing import Any, Callable, NoReturn TIMEOUT_MAX: int @@ -14,7 +15,7 @@ class LockType: def __init__(self) -> None: ... def acquire(self, waitflag: bool | None = ..., timeout: int = ...) -> bool: ... def __enter__(self, waitflag: bool | None = ..., timeout: int = ...) -> bool: ... - def __exit__(self, typ: Any, val: Any, tb: Any) -> None: ... + def __exit__(self, typ: type[BaseException] | None, val: BaseException | None, tb: TracebackType | None) -> None: ... def release(self) -> bool: ... def locked(self) -> bool: ... diff --git a/mypy/typeshed/stdlib/_dummy_threading.pyi b/mypy/typeshed/stdlib/_dummy_threading.pyi index 075ea4637f73f..1cbb8f1ee8c8a 100644 --- a/mypy/typeshed/stdlib/_dummy_threading.pyi +++ b/mypy/typeshed/stdlib/_dummy_threading.pyi @@ -1,14 +1,63 @@ import sys from types import FrameType, TracebackType -from typing import Any, Callable, Iterable, Mapping, Optional, Type, TypeVar +from typing import Any, Callable, Iterable, Mapping, TypeVar # TODO recursive type -_TF = Callable[[FrameType, str, Any], Optional[Callable[..., Any]]] +_TF = Callable[[FrameType, str, Any], Callable[..., Any] | None] _PF = Callable[[FrameType, str, Any], None] _T = TypeVar("_T") -__all__: list[str] +if sys.version_info >= (3, 8): + __all__ = [ + "get_ident", + "active_count", + "Condition", + "current_thread", + "enumerate", + "main_thread", + "TIMEOUT_MAX", + "Event", + "Lock", + "RLock", + "Semaphore", + "BoundedSemaphore", + "Thread", + "Barrier", + "BrokenBarrierError", + "Timer", + "ThreadError", + "setprofile", + "settrace", + "local", + "stack_size", + "excepthook", + "ExceptHookArgs", + ] +else: + __all__ = [ + "get_ident", + "active_count", + "Condition", + "current_thread", + "enumerate", + "main_thread", + "TIMEOUT_MAX", + "Event", + "Lock", + "RLock", + "Semaphore", + "BoundedSemaphore", + "Thread", + "Barrier", + "BrokenBarrierError", + "Timer", + "ThreadError", + "setprofile", + "settrace", + "local", + "stack_size", + ] def active_count() -> int: ... def current_thread() -> Thread: ... @@ -16,10 +65,6 @@ def currentThread() -> Thread: ... def get_ident() -> int: ... def enumerate() -> list[Thread]: ... def main_thread() -> Thread: ... - -if sys.version_info >= (3, 8): - from _thread import get_native_id as get_native_id - def settrace(func: _TF) -> None: ... def setprofile(func: _PF | None) -> None: ... def stack_size(size: int = ...) -> int: ... @@ -35,8 +80,9 @@ class local: class Thread: name: str - ident: int | None daemon: bool + @property + def ident(self) -> int | None: ... def __init__( self, group: None = ..., @@ -55,9 +101,11 @@ class Thread: if sys.version_info >= (3, 8): @property def native_id(self) -> int | None: ... # only available on some platforms + def is_alive(self) -> bool: ... if sys.version_info < (3, 9): def isAlive(self) -> bool: ... + def isDaemon(self) -> bool: ... def setDaemon(self, daemonic: bool) -> None: ... @@ -67,7 +115,7 @@ class Lock: def __init__(self) -> None: ... def __enter__(self) -> bool: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> bool | None: ... def acquire(self, blocking: bool = ..., timeout: float = ...) -> bool: ... def release(self) -> None: ... @@ -77,7 +125,7 @@ class _RLock: def __init__(self) -> None: ... def __enter__(self) -> bool: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> bool | None: ... def acquire(self, blocking: bool = ..., timeout: float = ...) -> bool: ... def release(self) -> None: ... @@ -88,7 +136,7 @@ class Condition: def __init__(self, lock: Lock | _RLock | None = ...) -> None: ... def __enter__(self) -> bool: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> bool | None: ... def acquire(self, blocking: bool = ..., timeout: float = ...) -> bool: ... def release(self) -> None: ... @@ -101,7 +149,7 @@ class Condition: class Semaphore: def __init__(self, value: int = ...) -> None: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> bool | None: ... def acquire(self, blocking: bool = ..., timeout: float | None = ...) -> bool: ... def __enter__(self, blocking: bool = ..., timeout: float | None = ...) -> bool: ... @@ -136,9 +184,12 @@ class Timer(Thread): def cancel(self) -> None: ... class Barrier: - parties: int - n_waiting: int - broken: bool + @property + def parties(self) -> int: ... + @property + def n_waiting(self) -> int: ... + @property + def broken(self) -> bool: ... def __init__(self, parties: int, action: Callable[[], None] | None = ..., timeout: float | None = ...) -> None: ... def wait(self, timeout: float | None = ...) -> int: ... def reset(self) -> None: ... diff --git a/mypy/typeshed/stdlib/_heapq.pyi b/mypy/typeshed/stdlib/_heapq.pyi index 87e0fe0fa777b..90dc28deb71f3 100644 --- a/mypy/typeshed/stdlib/_heapq.pyi +++ b/mypy/typeshed/stdlib/_heapq.pyi @@ -2,6 +2,8 @@ from typing import Any, TypeVar _T = TypeVar("_T") +__about__: str + def heapify(__heap: list[Any]) -> None: ... def heappop(__heap: list[_T]) -> _T: ... def heappush(__heap: list[_T], __item: _T) -> None: ... diff --git a/mypy/typeshed/stdlib/_imp.pyi b/mypy/typeshed/stdlib/_imp.pyi index 23272591df4ce..e2bbb9385ceb0 100644 --- a/mypy/typeshed/stdlib/_imp.pyi +++ b/mypy/typeshed/stdlib/_imp.pyi @@ -7,7 +7,7 @@ if sys.version_info >= (3, 7): check_hash_based_pycs: str def create_builtin(__spec: ModuleSpec) -> types.ModuleType: ... -def create_dynamic(__spec: ModuleSpec, __file: Any = ...) -> None: ... +def create_dynamic(__spec: ModuleSpec, __file: Any = ...) -> types.ModuleType: ... def acquire_lock() -> None: ... def exec_builtin(__mod: types.ModuleType) -> int: ... def exec_dynamic(__mod: types.ModuleType) -> int: ... diff --git a/mypy/typeshed/stdlib/_json.pyi b/mypy/typeshed/stdlib/_json.pyi index 7395288afdbc3..962fa9ec257ad 100644 --- a/mypy/typeshed/stdlib/_json.pyi +++ b/mypy/typeshed/stdlib/_json.pyi @@ -1,14 +1,24 @@ from typing import Any, Callable +from typing_extensions import final +@final class make_encoder: - sort_keys: Any - skipkeys: Any - key_separator: Any - indent: Any - markers: Any - default: Any - encoder: Any - item_separator: Any + @property + def sort_keys(self) -> bool: ... + @property + def skipkeys(self) -> bool: ... + @property + def key_separator(self) -> str: ... + @property + def indent(self) -> int | None: ... + @property + def markers(self) -> dict[int, Any] | None: ... + @property + def default(self) -> Callable[[Any], Any]: ... + @property + def encoder(self) -> Callable[[str], str]: ... + @property + def item_separator(self) -> str: ... def __init__( self, markers: dict[int, Any] | None, @@ -23,6 +33,7 @@ class make_encoder: ) -> None: ... def __call__(self, obj: object, _current_indent_level: int) -> Any: ... +@final class make_scanner: object_hook: Any object_pairs_hook: Any diff --git a/mypy/typeshed/stdlib/_msi.pyi b/mypy/typeshed/stdlib/_msi.pyi index b7e852f38ae9c..ffe53c819e539 100644 --- a/mypy/typeshed/stdlib/_msi.pyi +++ b/mypy/typeshed/stdlib/_msi.pyi @@ -43,6 +43,6 @@ if sys.platform == "win32": __new__: None # type: ignore[assignment] __init__: None # type: ignore[assignment] def UuidCreate() -> str: ... - def FCICreate(cabname: str, files: list[str]) -> None: ... - def OpenDatabase(name: str, flags: int) -> _Database: ... - def CreateRecord(count: int) -> _Record: ... + def FCICreate(__cabname: str, __files: list[str]) -> None: ... + def OpenDatabase(__path: str, __persist: int) -> _Database: ... + def CreateRecord(__count: int) -> _Record: ... diff --git a/mypy/typeshed/stdlib/_operator.pyi b/mypy/typeshed/stdlib/_operator.pyi index 77a88d4fa141b..375d8e4ddfbfb 100644 --- a/mypy/typeshed/stdlib/_operator.pyi +++ b/mypy/typeshed/stdlib/_operator.pyi @@ -1,5 +1,4 @@ import sys -from _typeshed import SupportsAnyComparison from typing import ( Any, AnyStr, @@ -25,6 +24,24 @@ _K = TypeVar("_K") _V = TypeVar("_V") _P = ParamSpec("_P") +# The following protocols return "Any" instead of bool, since the comparison +# operators can be overloaded to return an arbitrary object. For example, +# the numpy.array comparison dunders return another numpy.array. + +class _SupportsDunderLT(Protocol): + def __lt__(self, __other: Any) -> Any: ... + +class _SupportsDunderGT(Protocol): + def __gt__(self, __other: Any) -> Any: ... + +class _SupportsDunderLE(Protocol): + def __le__(self, __other: Any) -> Any: ... + +class _SupportsDunderGE(Protocol): + def __ge__(self, __other: Any) -> Any: ... + +_SupportsComparison = _SupportsDunderLE | _SupportsDunderGE | _SupportsDunderGT | _SupportsDunderLT + class _SupportsInversion(Protocol[_T_co]): def __invert__(self) -> _T_co: ... @@ -35,12 +52,12 @@ class _SupportsPos(Protocol[_T_co]): def __pos__(self) -> _T_co: ... # All four comparison functions must have the same signature, or we get false-positive errors -def lt(__a: SupportsAnyComparison, __b: SupportsAnyComparison) -> Any: ... -def le(__a: SupportsAnyComparison, __b: SupportsAnyComparison) -> Any: ... +def lt(__a: _SupportsComparison, __b: _SupportsComparison) -> Any: ... +def le(__a: _SupportsComparison, __b: _SupportsComparison) -> Any: ... def eq(__a: object, __b: object) -> Any: ... def ne(__a: object, __b: object) -> Any: ... -def ge(__a: SupportsAnyComparison, __b: SupportsAnyComparison) -> Any: ... -def gt(__a: SupportsAnyComparison, __b: SupportsAnyComparison) -> Any: ... +def ge(__a: _SupportsComparison, __b: _SupportsComparison) -> Any: ... +def gt(__a: _SupportsComparison, __b: _SupportsComparison) -> Any: ... def not_(__a: object) -> bool: ... def truth(__a: object) -> bool: ... def is_(__a: object, __b: object) -> bool: ... diff --git a/mypy/typeshed/stdlib/_osx_support.pyi b/mypy/typeshed/stdlib/_osx_support.pyi index ffb25d5a2c0ed..cb43fa93bb808 100644 --- a/mypy/typeshed/stdlib/_osx_support.pyi +++ b/mypy/typeshed/stdlib/_osx_support.pyi @@ -5,7 +5,7 @@ _T = TypeVar("_T") _K = TypeVar("_K") _V = TypeVar("_V") -__all__: list[str] +__all__ = ["compiler_fixup", "customize_config_vars", "customize_compiler", "get_platform_osx"] _UNIVERSAL_CONFIG_VARS: tuple[str, ...] # undocumented _COMPILER_CONFIG_VARS: tuple[str, ...] # undocumented diff --git a/mypy/typeshed/stdlib/_py_abc.pyi b/mypy/typeshed/stdlib/_py_abc.pyi index 697a7f17111a2..ddf04364a2380 100644 --- a/mypy/typeshed/stdlib/_py_abc.pyi +++ b/mypy/typeshed/stdlib/_py_abc.pyi @@ -1,10 +1,12 @@ -from typing import Any, Type, TypeVar +from _typeshed import Self +from typing import Any, NewType, TypeVar _T = TypeVar("_T") -# TODO: Change the return into a NewType bound to int after pytype/#597 -def get_cache_token() -> object: ... +_CacheToken = NewType("_CacheToken", int) + +def get_cache_token() -> _CacheToken: ... class ABCMeta(type): - def __new__(__mcls, __name: str, __bases: tuple[Type[Any], ...], __namespace: dict[str, Any]) -> ABCMeta: ... - def register(cls, subclass: Type[_T]) -> Type[_T]: ... + def __new__(__mcls: type[Self], __name: str, __bases: tuple[type[Any], ...], __namespace: dict[str, Any]) -> Self: ... + def register(cls, subclass: type[_T]) -> type[_T]: ... diff --git a/mypy/typeshed/stdlib/_socket.pyi b/mypy/typeshed/stdlib/_socket.pyi index d7d7f73ea37d1..a8cf16823d4e2 100644 --- a/mypy/typeshed/stdlib/_socket.pyi +++ b/mypy/typeshed/stdlib/_socket.pyi @@ -1,7 +1,7 @@ import sys from _typeshed import ReadableBuffer, WriteableBuffer from collections.abc import Iterable -from typing import Any, SupportsInt, Union, overload +from typing import Any, SupportsInt, overload if sys.version_info >= (3, 8): from typing import SupportsIndex @@ -15,7 +15,7 @@ _CMSGArg = tuple[int, int, ReadableBuffer] # Addresses can be either tuples of varying lengths (AF_INET, AF_INET6, # AF_NETLINK, AF_TIPC) or strings (AF_UNIX). -_Address = Union[tuple[Any, ...], str] +_Address = tuple[Any, ...] | str _RetAddress = Any # TODO Most methods allow bytes as address objects @@ -356,6 +356,9 @@ if sys.platform == "linux" and sys.version_info >= (3, 9): J1939_FILTER_MAX: int +if sys.platform == "linux" and sys.version_info >= (3, 10): + IPPROTO_MPTCP: int + if sys.platform == "linux": AF_PACKET: int PF_PACKET: int @@ -524,9 +527,12 @@ else: # ----- Classes ----- class socket: - family: int - type: int - proto: int + @property + def family(self) -> int: ... + @property + def type(self) -> int: ... + @property + def proto(self) -> int: ... @property def timeout(self) -> float | None: ... def __init__(self, family: int = ..., type: int = ..., proto: int = ..., fileno: _FD | None = ...) -> None: ... @@ -544,9 +550,11 @@ class socket: def getsockopt(self, __level: int, __optname: int, __buflen: int) -> bytes: ... if sys.version_info >= (3, 7): def getblocking(self) -> bool: ... + def gettimeout(self) -> float | None: ... if sys.platform == "win32": def ioctl(self, __control: int, __option: int | tuple[int, int, int] | bool) -> None: ... + def listen(self, __backlog: int = ...) -> None: ... def recv(self, __bufsize: int, __flags: int = ...) -> bytes: ... def recvfrom(self, __bufsize: int, __flags: int = ...) -> tuple[bytes, _RetAddress]: ... @@ -555,6 +563,7 @@ class socket: def recvmsg_into( self, __buffers: Iterable[WriteableBuffer], __ancbufsize: int = ..., __flags: int = ... ) -> tuple[int, list[_CMSG], int, Any]: ... + def recvfrom_into(self, buffer: WriteableBuffer, nbytes: int = ..., flags: int = ...) -> tuple[int, _RetAddress]: ... def recv_into(self, buffer: WriteableBuffer, nbytes: int = ..., flags: int = ...) -> int: ... def send(self, __data: ReadableBuffer, __flags: int = ...) -> int: ... @@ -575,6 +584,7 @@ class socket: def sendmsg_afalg( self, msg: Iterable[ReadableBuffer] = ..., *, op: int, iv: Any = ..., assoclen: int = ..., flags: int = ... ) -> int: ... + def setblocking(self, __flag: bool) -> None: ... def settimeout(self, __value: float | None) -> None: ... @overload @@ -583,6 +593,7 @@ class socket: def setsockopt(self, __level: int, __optname: int, __value: None, __optlen: int) -> None: ... if sys.platform == "win32": def share(self, __process_id: int) -> bytes: ... + def shutdown(self, __how: int) -> None: ... SocketType = socket diff --git a/mypy/typeshed/stdlib/_thread.pyi b/mypy/typeshed/stdlib/_thread.pyi index 03318a0b2d413..04abf8dc869cd 100644 --- a/mypy/typeshed/stdlib/_thread.pyi +++ b/mypy/typeshed/stdlib/_thread.pyi @@ -2,8 +2,8 @@ import sys from _typeshed import structseq from threading import Thread from types import TracebackType -from typing import Any, Callable, NoReturn, Optional, Type -from typing_extensions import final +from typing import Any, Callable, NoReturn +from typing_extensions import Final, final error = RuntimeError @@ -18,7 +18,7 @@ class LockType: def locked(self) -> bool: ... def __enter__(self) -> bool: ... def __exit__( - self, type: Type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None + self, type: type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None ) -> None: ... def start_new_thread(function: Callable[..., Any], args: tuple[Any, ...], kwargs: dict[str, Any] = ...) -> int: ... @@ -33,11 +33,11 @@ TIMEOUT_MAX: float if sys.version_info >= (3, 8): def get_native_id() -> int: ... # only available on some platforms @final - class _ExceptHookArgs( - structseq[Any], tuple[Type[BaseException], Optional[BaseException], Optional[TracebackType], Optional[Thread]] - ): + class _ExceptHookArgs(structseq[Any], tuple[type[BaseException], BaseException | None, TracebackType | None, Thread | None]): + if sys.version_info >= (3, 10): + __match_args__: Final = ("exc_type", "exc_value", "exc_traceback", "thread") @property - def exc_type(self) -> Type[BaseException]: ... + def exc_type(self) -> type[BaseException]: ... @property def exc_value(self) -> BaseException | None: ... @property diff --git a/mypy/typeshed/stdlib/_threading_local.pyi b/mypy/typeshed/stdlib/_threading_local.pyi index 9e1e3f48d2868..2ad77a177c371 100644 --- a/mypy/typeshed/stdlib/_threading_local.pyi +++ b/mypy/typeshed/stdlib/_threading_local.pyi @@ -1,6 +1,7 @@ from typing import Any from weakref import ReferenceType +__all__ = ["local"] localdict = dict[Any, Any] class _localimpl: diff --git a/mypy/typeshed/stdlib/_tkinter.pyi b/mypy/typeshed/stdlib/_tkinter.pyi index b6c8ccd1c3807..c2cf55505afb5 100644 --- a/mypy/typeshed/stdlib/_tkinter.pyi +++ b/mypy/typeshed/stdlib/_tkinter.pyi @@ -1,5 +1,5 @@ import sys -from typing import Any +from typing import Any, ClassVar from typing_extensions import Literal, final # _tkinter is meant to be only used internally by tkinter, but some tkinter @@ -17,8 +17,15 @@ from typing_extensions import Literal, final # (, ) @final class Tcl_Obj: - string: str # str(tclobj) returns this + string: str | bytes typename: str + __hash__: ClassVar[None] # type: ignore[assignment] + def __eq__(self, __other): ... + def __ge__(self, __other): ... + def __gt__(self, __other): ... + def __le__(self, __other): ... + def __lt__(self, __other): ... + def __ne__(self, __other): ... class TclError(Exception): ... @@ -42,39 +49,42 @@ class TclError(Exception): ... @final class TkappType: # Please keep in sync with tkinter.Tk + def adderrorinfo(self, __msg): ... def call(self, __command: Any, *args: Any) -> Any: ... + def createcommand(self, __name, __func): ... + if sys.platform != "win32": + def createfilehandler(self, __file, __mask, __func): ... + def deletefilehandler(self, __file): ... + + def createtimerhandler(self, __milliseconds, __func): ... + def deletecommand(self, __name): ... + def dooneevent(self, __flags: int = ...): ... def eval(self, __script: str) -> str: ... - adderrorinfo: Any - createcommand: Any - createfilehandler: Any - createtimerhandler: Any - deletecommand: Any - deletefilehandler: Any - dooneevent: Any - evalfile: Any - exprboolean: Any - exprdouble: Any - exprlong: Any - exprstring: Any - getboolean: Any - getdouble: Any - getint: Any - getvar: Any - globalgetvar: Any - globalsetvar: Any - globalunsetvar: Any - interpaddr: Any - loadtk: Any - mainloop: Any - quit: Any - record: Any - setvar: Any + def evalfile(self, __fileName): ... + def exprboolean(self, __s): ... + def exprdouble(self, __s): ... + def exprlong(self, __s): ... + def exprstring(self, __s): ... + def getboolean(self, __arg): ... + def getdouble(self, __arg): ... + def getint(self, __arg): ... + def getvar(self, *args, **kwargs): ... + def globalgetvar(self, *args, **kwargs): ... + def globalsetvar(self, *args, **kwargs): ... + def globalunsetvar(self, *args, **kwargs): ... + def interpaddr(self): ... + def loadtk(self) -> None: ... + def mainloop(self, __threshold: int = ...): ... + def quit(self): ... + def record(self, __script): ... + def setvar(self, *ags, **kwargs): ... if sys.version_info < (3, 11): - split: Any - splitlist: Any - unsetvar: Any - wantobjects: Any - willdispatch: Any + def split(self, __arg): ... + + def splitlist(self, __arg): ... + def unsetvar(self, *args, **kwargs): ... + def wantobjects(self, *args, **kwargs): ... + def willdispatch(self): ... # These should be kept in sync with tkinter.tix constants, except ALL_EVENTS which doesn't match TCL_ALL_EVENTS ALL_EVENTS: Literal[-3] @@ -91,9 +101,19 @@ WRITABLE: Literal[4] TCL_VERSION: str TK_VERSION: str -# TODO: figure out what these are (with e.g. help()) and get rid of Any -TkttType: Any -_flatten: Any -create: Any -getbusywaitinterval: Any -setbusywaitinterval: Any +@final +class TkttType: + def deletetimerhandler(self): ... + +def create( + __screenName: str | None = ..., + __baseName: str | None = ..., + __className: str = ..., + __interactive: bool = ..., + __wantobjects: bool = ..., + __wantTk: bool = ..., + __sync: bool = ..., + __use: str | None = ..., +): ... +def getbusywaitinterval(): ... +def setbusywaitinterval(__new_val): ... diff --git a/mypy/typeshed/stdlib/_typeshed/__init__.pyi b/mypy/typeshed/stdlib/_typeshed/__init__.pyi index a7f8c51471039..b348a329522bc 100644 --- a/mypy/typeshed/stdlib/_typeshed/__init__.pyi +++ b/mypy/typeshed/stdlib/_typeshed/__init__.pyi @@ -7,8 +7,8 @@ import ctypes import mmap import sys from os import PathLike -from typing import AbstractSet, Any, Awaitable, ClassVar, Container, Generic, Iterable, Protocol, Type, TypeVar, Union -from typing_extensions import Literal, final +from typing import AbstractSet, Any, Awaitable, Container, Generic, Iterable, Protocol, TypeVar +from typing_extensions import Final, Literal, TypeAlias, final _KT = TypeVar("_KT") _KT_co = TypeVar("_KT_co", covariant=True) @@ -21,7 +21,14 @@ _T_contra = TypeVar("_T_contra", contravariant=True) # Use for "self" annotations: # def __enter__(self: Self) -> Self: ... -Self = TypeVar("Self") # noqa Y001 +Self = TypeVar("Self") # noqa: Y001 + +# For partially known annotations. Usually, fields where type annotations +# haven't been added are left unannotated, but in some situations this +# isn't possible or a type is already partially known. In cases like these, +# use Incomplete instead of Any as a marker. For example, use +# "Incomplete | None" instead of "Any | None". +Incomplete: TypeAlias = Any # stable class IdentityFunction(Protocol): @@ -38,22 +45,21 @@ class SupportsAnext(Protocol[_T_co]): # Comparison protocols class SupportsDunderLT(Protocol): - def __lt__(self, __other: Any) -> Any: ... + def __lt__(self, __other: Any) -> bool: ... class SupportsDunderGT(Protocol): - def __gt__(self, __other: Any) -> Any: ... + def __gt__(self, __other: Any) -> bool: ... class SupportsDunderLE(Protocol): - def __le__(self, __other: Any) -> Any: ... + def __le__(self, __other: Any) -> bool: ... class SupportsDunderGE(Protocol): - def __ge__(self, __other: Any) -> Any: ... + def __ge__(self, __other: Any) -> bool: ... class SupportsAllComparisons(SupportsDunderLT, SupportsDunderGT, SupportsDunderLE, SupportsDunderGE, Protocol): ... -SupportsRichComparison = Union[SupportsDunderLT, SupportsDunderGT] +SupportsRichComparison: TypeAlias = SupportsDunderLT | SupportsDunderGT SupportsRichComparisonT = TypeVar("SupportsRichComparisonT", bound=SupportsRichComparison) # noqa: Y001 -SupportsAnyComparison = Union[SupportsDunderLE, SupportsDunderGE, SupportsDunderGT, SupportsDunderLT] class SupportsDivMod(Protocol[_T_contra, _T_co]): def __divmod__(self, __other: _T_contra) -> _T_co: ... @@ -89,9 +95,9 @@ class SupportsItemAccess(SupportsGetItem[_KT_contra, _VT], Protocol[_KT_contra, def __delitem__(self, __v: _KT_contra) -> None: ... # These aliases are simple strings in Python 2. -StrPath = Union[str, PathLike[str]] # stable -BytesPath = Union[bytes, PathLike[bytes]] # stable -StrOrBytesPath = Union[str, bytes, PathLike[str], PathLike[bytes]] # stable +StrPath: TypeAlias = str | PathLike[str] # stable +BytesPath: TypeAlias = bytes | PathLike[bytes] # stable +StrOrBytesPath: TypeAlias = str | bytes | PathLike[str] | PathLike[bytes] # stable OpenTextModeUpdating = Literal[ "r+", @@ -127,10 +133,10 @@ OpenTextModeUpdating = Literal[ "t+x", "+tx", ] -OpenTextModeWriting = Literal["w", "wt", "tw", "a", "at", "ta", "x", "xt", "tx"] -OpenTextModeReading = Literal["r", "rt", "tr", "U", "rU", "Ur", "rtU", "rUt", "Urt", "trU", "tUr", "Utr"] -OpenTextMode = Union[OpenTextModeUpdating, OpenTextModeWriting, OpenTextModeReading] -OpenBinaryModeUpdating = Literal[ +OpenTextModeWriting: TypeAlias = Literal["w", "wt", "tw", "a", "at", "ta", "x", "xt", "tx"] +OpenTextModeReading: TypeAlias = Literal["r", "rt", "tr", "U", "rU", "Ur", "rtU", "rUt", "Urt", "trU", "tUr", "Utr"] +OpenTextMode: TypeAlias = OpenTextModeUpdating | OpenTextModeWriting | OpenTextModeReading +OpenBinaryModeUpdating: TypeAlias = Literal[ "rb+", "r+b", "+rb", @@ -156,16 +162,16 @@ OpenBinaryModeUpdating = Literal[ "b+x", "+bx", ] -OpenBinaryModeWriting = Literal["wb", "bw", "ab", "ba", "xb", "bx"] -OpenBinaryModeReading = Literal["rb", "br", "rbU", "rUb", "Urb", "brU", "bUr", "Ubr"] -OpenBinaryMode = Union[OpenBinaryModeUpdating, OpenBinaryModeReading, OpenBinaryModeWriting] +OpenBinaryModeWriting: TypeAlias = Literal["wb", "bw", "ab", "ba", "xb", "bx"] +OpenBinaryModeReading: TypeAlias = Literal["rb", "br", "rbU", "rUb", "Urb", "brU", "bUr", "Ubr"] +OpenBinaryMode: TypeAlias = OpenBinaryModeUpdating | OpenBinaryModeReading | OpenBinaryModeWriting # stable class HasFileno(Protocol): def fileno(self) -> int: ... -FileDescriptor = int # stable -FileDescriptorLike = Union[int, HasFileno] # stable +FileDescriptor: TypeAlias = int # stable +FileDescriptorLike: TypeAlias = int | HasFileno # stable # stable class SupportsRead(Protocol[_T_co]): @@ -181,15 +187,15 @@ class SupportsNoArgReadline(Protocol[_T_co]): # stable class SupportsWrite(Protocol[_T_contra]): - def write(self, __s: _T_contra) -> Any: ... + def write(self, __s: _T_contra) -> object: ... -ReadOnlyBuffer = bytes # stable +ReadOnlyBuffer: TypeAlias = bytes # stable # Anything that implements the read-write buffer interface. # The buffer interface is defined purely on the C level, so we cannot define a normal Protocol # for it. Instead we have to list the most common stdlib buffer classes in a Union. -WriteableBuffer = Union[bytearray, memoryview, array.array[Any], mmap.mmap, ctypes._CData] # stable +WriteableBuffer: TypeAlias = bytearray | memoryview | array.array[Any] | mmap.mmap | ctypes._CData # stable # Same as _WriteableBuffer, but also includes read-only buffer types (like bytes). -ReadableBuffer = Union[ReadOnlyBuffer, WriteableBuffer] # stable +ReadableBuffer: TypeAlias = ReadOnlyBuffer | WriteableBuffer # stable # stable if sys.version_info >= (3, 10): @@ -206,13 +212,13 @@ else: # See discussion at #6546 & #6560 # `structseq` classes are unsubclassable, so are all decorated with `@final`. class structseq(Generic[_T_co]): - n_fields: ClassVar[int] - n_unnamed_fields: ClassVar[int] - n_sequence_fields: ClassVar[int] + n_fields: Final[int] + n_unnamed_fields: Final[int] + n_sequence_fields: Final[int] # The first parameter will generally only take an iterable of a specific length. # E.g. `os.uname_result` takes any iterable of length exactly 5. # # The second parameter will accept a dict of any kind without raising an exception, # but only has any meaning if you supply it a dict where the keys are strings. # https://github.com/python/typeshed/pull/6560#discussion_r767149830 - def __new__(cls: Type[_T], sequence: Iterable[_T_co], dict: dict[str, Any] = ...) -> _T: ... + def __new__(cls: type[Self], sequence: Iterable[_T_co], dict: dict[str, Any] = ...) -> Self: ... diff --git a/mypy/typeshed/stdlib/_typeshed/dbapi.pyi b/mypy/typeshed/stdlib/_typeshed/dbapi.pyi index eee4fc03874e5..022e95996bb3c 100644 --- a/mypy/typeshed/stdlib/_typeshed/dbapi.pyi +++ b/mypy/typeshed/stdlib/_typeshed/dbapi.pyi @@ -3,11 +3,12 @@ from collections.abc import Mapping, Sequence from typing import Any, Protocol +from typing_extensions import TypeAlias -DBAPITypeCode = Any | None +DBAPITypeCode: TypeAlias = Any | None # Strictly speaking, this should be a Sequence, but the type system does # not support fixed-length sequences. -DBAPIColumnDescription = tuple[str, DBAPITypeCode, int | None, int | None, int | None, int | None, bool | None] +DBAPIColumnDescription: TypeAlias = tuple[str, DBAPITypeCode, int | None, int | None, int | None, int | None, bool | None] class DBAPIConnection(Protocol): def close(self) -> object: ... diff --git a/mypy/typeshed/stdlib/_typeshed/wsgi.pyi b/mypy/typeshed/stdlib/_typeshed/wsgi.pyi index 031d1472b6c5f..9f036d8f2d336 100644 --- a/mypy/typeshed/stdlib/_typeshed/wsgi.pyi +++ b/mypy/typeshed/stdlib/_typeshed/wsgi.pyi @@ -4,6 +4,7 @@ from sys import _OptExcInfo from typing import Any, Callable, Iterable, Protocol +from typing_extensions import TypeAlias # stable class StartResponse(Protocol): @@ -11,8 +12,8 @@ class StartResponse(Protocol): self, status: str, headers: list[tuple[str, str]], exc_info: _OptExcInfo | None = ... ) -> Callable[[bytes], Any]: ... -WSGIEnvironment = dict[str, Any] # stable -WSGIApplication = Callable[[WSGIEnvironment, StartResponse], Iterable[bytes]] # stable +WSGIEnvironment: TypeAlias = dict[str, Any] # stable +WSGIApplication: TypeAlias = Callable[[WSGIEnvironment, StartResponse], Iterable[bytes]] # stable # WSGI input streams per PEP 3333, stable class InputStream(Protocol): diff --git a/mypy/typeshed/stdlib/_warnings.pyi b/mypy/typeshed/stdlib/_warnings.pyi index e5b180b14fea2..2eb9ae478a5d2 100644 --- a/mypy/typeshed/stdlib/_warnings.pyi +++ b/mypy/typeshed/stdlib/_warnings.pyi @@ -1,21 +1,21 @@ -from typing import Any, Type, overload +from typing import Any, overload _defaultaction: str _onceregistry: dict[Any, Any] -filters: list[tuple[str, str | None, Type[Warning], str | None, int]] +filters: list[tuple[str, str | None, type[Warning], str | None, int]] @overload -def warn(message: str, category: Type[Warning] | None = ..., stacklevel: int = ..., source: Any | None = ...) -> None: ... +def warn(message: str, category: type[Warning] | None = ..., stacklevel: int = ..., source: Any | None = ...) -> None: ... @overload def warn(message: Warning, category: Any = ..., stacklevel: int = ..., source: Any | None = ...) -> None: ... @overload def warn_explicit( message: str, - category: Type[Warning], + category: type[Warning], filename: str, lineno: int, module: str | None = ..., - registry: dict[str | tuple[str, Type[Warning], int], int] | None = ..., + registry: dict[str | tuple[str, type[Warning], int], int] | None = ..., module_globals: dict[str, Any] | None = ..., source: Any | None = ..., ) -> None: ... @@ -26,7 +26,7 @@ def warn_explicit( filename: str, lineno: int, module: str | None = ..., - registry: dict[str | tuple[str, Type[Warning], int], int] | None = ..., + registry: dict[str | tuple[str, type[Warning], int], int] | None = ..., module_globals: dict[str, Any] | None = ..., source: Any | None = ..., ) -> None: ... diff --git a/mypy/typeshed/stdlib/_weakrefset.pyi b/mypy/typeshed/stdlib/_weakrefset.pyi index 1f0132f4c240a..b0c22a5ecc135 100644 --- a/mypy/typeshed/stdlib/_weakrefset.pyi +++ b/mypy/typeshed/stdlib/_weakrefset.pyi @@ -1,34 +1,36 @@ import sys +from _typeshed import Self from typing import Any, Generic, Iterable, Iterator, MutableSet, TypeVar if sys.version_info >= (3, 9): from types import GenericAlias +__all__ = ["WeakSet"] + _S = TypeVar("_S") _T = TypeVar("_T") -_SelfT = TypeVar("_SelfT", bound=WeakSet[Any]) class WeakSet(MutableSet[_T], Generic[_T]): def __init__(self, data: Iterable[_T] | None = ...) -> None: ... def add(self, item: _T) -> None: ... def clear(self) -> None: ... def discard(self, item: _T) -> None: ... - def copy(self: _SelfT) -> _SelfT: ... + def copy(self: Self) -> Self: ... def pop(self) -> _T: ... def remove(self, item: _T) -> None: ... def update(self, other: Iterable[_T]) -> None: ... def __contains__(self, item: object) -> bool: ... def __len__(self) -> int: ... def __iter__(self) -> Iterator[_T]: ... - def __ior__(self, other: Iterable[_S]) -> WeakSet[_S | _T]: ... - def difference(self: _SelfT, other: Iterable[_T]) -> _SelfT: ... - def __sub__(self: _SelfT, other: Iterable[_T]) -> _SelfT: ... - def difference_update(self, other: Iterable[_T]) -> None: ... - def __isub__(self: _SelfT, other: Iterable[_T]) -> _SelfT: ... - def intersection(self: _SelfT, other: Iterable[_T]) -> _SelfT: ... - def __and__(self: _SelfT, other: Iterable[_T]) -> _SelfT: ... - def intersection_update(self, other: Iterable[_T]) -> None: ... - def __iand__(self: _SelfT, other: Iterable[_T]) -> _SelfT: ... + def __ior__(self: Self, other: Iterable[_T]) -> Self: ... # type: ignore[override,misc] + def difference(self: Self, other: Iterable[_T]) -> Self: ... + def __sub__(self: Self, other: Iterable[Any]) -> Self: ... + def difference_update(self, other: Iterable[Any]) -> None: ... + def __isub__(self: Self, other: Iterable[Any]) -> Self: ... + def intersection(self: Self, other: Iterable[_T]) -> Self: ... + def __and__(self: Self, other: Iterable[Any]) -> Self: ... + def intersection_update(self, other: Iterable[Any]) -> None: ... + def __iand__(self: Self, other: Iterable[Any]) -> Self: ... def issubset(self, other: Iterable[_T]) -> bool: ... def __le__(self, other: Iterable[_T]) -> bool: ... def __lt__(self, other: Iterable[_T]) -> bool: ... @@ -38,8 +40,8 @@ class WeakSet(MutableSet[_T], Generic[_T]): def __eq__(self, other: object) -> bool: ... def symmetric_difference(self, other: Iterable[_S]) -> WeakSet[_S | _T]: ... def __xor__(self, other: Iterable[_S]) -> WeakSet[_S | _T]: ... - def symmetric_difference_update(self, other: Iterable[Any]) -> None: ... - def __ixor__(self, other: Iterable[_S]) -> WeakSet[_S | _T]: ... + def symmetric_difference_update(self, other: Iterable[_T]) -> None: ... + def __ixor__(self: Self, other: Iterable[_T]) -> Self: ... # type: ignore[override,misc] def union(self, other: Iterable[_S]) -> WeakSet[_S | _T]: ... def __or__(self, other: Iterable[_S]) -> WeakSet[_S | _T]: ... def isdisjoint(self, other: Iterable[_T]) -> bool: ... diff --git a/mypy/typeshed/stdlib/_winapi.pyi b/mypy/typeshed/stdlib/_winapi.pyi index eba236597840b..1e8c514770839 100644 --- a/mypy/typeshed/stdlib/_winapi.pyi +++ b/mypy/typeshed/stdlib/_winapi.pyi @@ -160,6 +160,7 @@ if sys.platform == "win32": if sys.version_info >= (3, 7): def GetACP() -> int: ... def GetFileType(handle: int) -> int: ... + def GetCurrentProcess() -> int: ... def GetExitCodeProcess(__process: int) -> int: ... def GetLastError() -> int: ... diff --git a/mypy/typeshed/stdlib/abc.pyi b/mypy/typeshed/stdlib/abc.pyi index 3c53692e1b36a..58985067b1259 100644 --- a/mypy/typeshed/stdlib/abc.pyi +++ b/mypy/typeshed/stdlib/abc.pyi @@ -1,8 +1,11 @@ import sys from _typeshed import SupportsWrite -from typing import Any, Callable, Type, TypeVar +from collections.abc import Callable +from typing import Any, Generic, TypeVar +from typing_extensions import Literal _T = TypeVar("_T") +_R_co = TypeVar("_R_co", covariant=True) _FuncT = TypeVar("_FuncT", bound=Callable[..., Any]) # These definitions have special processing in mypy @@ -12,19 +15,24 @@ class ABCMeta(type): def __instancecheck__(cls: ABCMeta, instance: Any) -> Any: ... def __subclasscheck__(cls: ABCMeta, subclass: Any) -> Any: ... def _dump_registry(cls: ABCMeta, file: SupportsWrite[str] | None = ...) -> None: ... - def register(cls: ABCMeta, subclass: Type[_T]) -> Type[_T]: ... + def register(cls: ABCMeta, subclass: type[_T]) -> type[_T]: ... def abstractmethod(funcobj: _FuncT) -> _FuncT: ... -class abstractproperty(property): ... +class abstractclassmethod(classmethod[_R_co], Generic[_R_co]): + __isabstractmethod__: Literal[True] + def __init__(self: abstractclassmethod[_R_co], callable: Callable[..., _R_co]) -> None: ... -# These two are deprecated and not supported by mypy -def abstractstaticmethod(callable: _FuncT) -> _FuncT: ... -def abstractclassmethod(callable: _FuncT) -> _FuncT: ... +class abstractstaticmethod(staticmethod[_R_co], Generic[_R_co]): + __isabstractmethod__: Literal[True] + def __init__(self, callable: Callable[..., _R_co]) -> None: ... + +class abstractproperty(property): + __isabstractmethod__: Literal[True] class ABC(metaclass=ABCMeta): ... def get_cache_token() -> object: ... if sys.version_info >= (3, 10): - def update_abstractmethods(cls: Type[_T]) -> Type[_T]: ... + def update_abstractmethods(cls: type[_T]) -> type[_T]: ... diff --git a/mypy/typeshed/stdlib/aifc.pyi b/mypy/typeshed/stdlib/aifc.pyi index e19bf2478bf31..db3d8d9910295 100644 --- a/mypy/typeshed/stdlib/aifc.pyi +++ b/mypy/typeshed/stdlib/aifc.pyi @@ -1,9 +1,14 @@ import sys from _typeshed import Self from types import TracebackType -from typing import IO, Any, NamedTuple, Type, Union, overload +from typing import IO, Any, NamedTuple, overload from typing_extensions import Literal +if sys.version_info >= (3, 9): + __all__ = ["Error", "open"] +else: + __all__ = ["Error", "open", "openfp"] + class Error(Exception): ... class _aifc_params(NamedTuple): @@ -14,14 +19,14 @@ class _aifc_params(NamedTuple): comptype: bytes compname: bytes -_File = Union[str, IO[bytes]] +_File = str | IO[bytes] _Marker = tuple[int, int, bytes] class Aifc_read: def __init__(self, f: _File) -> None: ... def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> None: ... def initfp(self, file: IO[bytes]) -> None: ... def getfp(self) -> IO[bytes]: ... @@ -45,7 +50,7 @@ class Aifc_write: def __del__(self) -> None: ... def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> None: ... def initfp(self, file: IO[bytes]) -> None: ... def aiff(self) -> None: ... diff --git a/mypy/typeshed/stdlib/argparse.pyi b/mypy/typeshed/stdlib/argparse.pyi index 51933dc66668e..ad54660cc45d4 100644 --- a/mypy/typeshed/stdlib/argparse.pyi +++ b/mypy/typeshed/stdlib/argparse.pyi @@ -1,17 +1,76 @@ import sys -from typing import IO, Any, Callable, Generator, Generic, Iterable, NoReturn, Pattern, Protocol, Sequence, Type, TypeVar, overload +from typing import ( + IO, + Any, + Callable, + Generator, + Generic, + Iterable, + NewType, + NoReturn, + Pattern, + Protocol, + Sequence, + TypeVar, + overload, +) +from typing_extensions import Literal + +if sys.version_info >= (3, 9): + __all__ = [ + "ArgumentParser", + "ArgumentError", + "ArgumentTypeError", + "BooleanOptionalAction", + "FileType", + "HelpFormatter", + "ArgumentDefaultsHelpFormatter", + "RawDescriptionHelpFormatter", + "RawTextHelpFormatter", + "MetavarTypeHelpFormatter", + "Namespace", + "Action", + "ONE_OR_MORE", + "OPTIONAL", + "PARSER", + "REMAINDER", + "SUPPRESS", + "ZERO_OR_MORE", + ] +else: + __all__ = [ + "ArgumentParser", + "ArgumentError", + "ArgumentTypeError", + "FileType", + "HelpFormatter", + "ArgumentDefaultsHelpFormatter", + "RawDescriptionHelpFormatter", + "RawTextHelpFormatter", + "MetavarTypeHelpFormatter", + "Namespace", + "Action", + "ONE_OR_MORE", + "OPTIONAL", + "PARSER", + "REMAINDER", + "SUPPRESS", + "ZERO_OR_MORE", + ] _T = TypeVar("_T") _ActionT = TypeVar("_ActionT", bound=Action) _ArgumentParserT = TypeVar("_ArgumentParserT", bound=ArgumentParser) _N = TypeVar("_N") -ONE_OR_MORE: str -OPTIONAL: str -PARSER: str -REMAINDER: str -SUPPRESS: str -ZERO_OR_MORE: str +ONE_OR_MORE: Literal["+"] +OPTIONAL: Literal["?"] +PARSER: Literal["A..."] +REMAINDER: Literal["..."] +_SUPPRESS_T = NewType("_SUPPRESS_T", str) +SUPPRESS: _SUPPRESS_T | str # not using Literal because argparse sometimes compares SUPPRESS with is +# the | str is there so that foo = argparse.SUPPRESS; foo = "test" checks out in mypy +ZERO_OR_MORE: Literal["*"] _UNRECOGNIZED_ARGS_ATTR: str # undocumented class ArgumentError(Exception): @@ -47,8 +106,11 @@ class _ActionsContainer: def add_argument( self, *name_or_flags: str, - action: str | Type[Action] = ..., - nargs: int | str = ..., + action: Literal[ + "store", "store_const", "store_true", "store_false", "append", "append_const", "count", "help", "version", "extend" + ] + | type[Action] = ..., + nargs: int | Literal["?", "*", "+", "...", "A...", "==SUPPRESS=="] | _SUPPRESS_T = ..., const: Any = ..., default: Any = ..., type: Callable[[str], _T] | FileType = ..., @@ -67,7 +129,7 @@ class _ActionsContainer: def _add_container_actions(self, container: _ActionsContainer) -> None: ... def _get_positional_kwargs(self, dest: str, **kwargs: Any) -> dict[str, Any]: ... def _get_optional_kwargs(self, *args: Any, **kwargs: Any) -> dict[str, Any]: ... - def _pop_action_class(self, kwargs: Any, default: Type[Action] | None = ...) -> Type[Action]: ... + def _pop_action_class(self, kwargs: Any, default: type[Action] | None = ...) -> type[Action]: ... def _get_handler(self) -> Callable[[Action, Iterable[tuple[str, Action]]], Any]: ... def _check_conflict(self, action: Action) -> None: ... def _handle_conflict_error(self, action: Action, conflicting_actions: Iterable[tuple[str, Action]]) -> NoReturn: ... @@ -143,7 +205,7 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): title: str = ..., description: str | None = ..., prog: str = ..., - action: Type[Action] = ..., + action: type[Action] = ..., option_string: str = ..., dest: str | None = ..., required: bool = ..., @@ -157,8 +219,8 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): title: str = ..., description: str | None = ..., prog: str = ..., - parser_class: Type[_ArgumentParserT] = ..., - action: Type[Action] = ..., + parser_class: type[_ArgumentParserT] = ..., + action: type[Action] = ..., option_string: str = ..., dest: str | None = ..., required: bool = ..., @@ -173,7 +235,7 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): title: str = ..., description: str | None = ..., prog: str = ..., - action: Type[Action] = ..., + action: type[Action] = ..., option_string: str = ..., dest: str | None = ..., help: str | None = ..., @@ -186,13 +248,14 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): title: str = ..., description: str | None = ..., prog: str = ..., - parser_class: Type[_ArgumentParserT] = ..., - action: Type[Action] = ..., + parser_class: type[_ArgumentParserT] = ..., + action: type[Action] = ..., option_string: str = ..., dest: str | None = ..., help: str | None = ..., metavar: str | None = ..., ) -> _SubParsersAction[_ArgumentParserT]: ... + def print_usage(self, file: IO[str] | None = ...) -> None: ... def print_help(self, file: IO[str] | None = ...) -> None: ... def format_usage(self) -> str: ... @@ -237,7 +300,7 @@ class HelpFormatter: _current_section: Any _whitespace_matcher: Pattern[str] _long_break_matcher: Pattern[str] - _Section: Type[Any] # Nested class + _Section: type[Any] # Nested class def __init__(self, prog: str, indent_increment: int = ..., max_help_position: int = ..., width: int | None = ...) -> None: ... def _indent(self) -> None: ... def _dedent(self) -> None: ... @@ -292,7 +355,7 @@ class Action(_AttributeHolder): nargs: int | str | None = ..., const: _T | None = ..., default: _T | str | None = ..., - type: Callable[[str], _T] | Callable[[str], _T] | FileType | None = ..., + type: Callable[[str], _T] | FileType | None = ..., choices: Iterable[_T] | None = ..., required: bool = ..., help: str | None = ..., @@ -311,7 +374,7 @@ if sys.version_info >= (3, 9): option_strings: Sequence[str], dest: str, default: _T | str | None = ..., - type: Callable[[str], _T] | Callable[[str], _T] | FileType | None = ..., + type: Callable[[str], _T] | FileType | None = ..., choices: Iterable[_T] | None = ..., required: bool = ..., help: str | None = ..., @@ -321,8 +384,9 @@ if sys.version_info >= (3, 9): class Namespace(_AttributeHolder): def __init__(self, **kwargs: Any) -> None: ... def __getattr__(self, name: str) -> Any: ... - def __setattr__(self, name: str, value: Any) -> None: ... + def __setattr__(self, __name: str, __value: Any) -> None: ... def __contains__(self, key: str) -> bool: ... + def __eq__(self, other: object) -> bool: ... class FileType: # undocumented @@ -410,9 +474,9 @@ class _VersionAction(Action): # undocumented class _SubParsersAction(Action, Generic[_ArgumentParserT]): - _ChoicesPseudoAction: Type[Any] # nested class + _ChoicesPseudoAction: type[Any] # nested class _prog_prefix: str - _parser_class: Type[_ArgumentParserT] + _parser_class: type[_ArgumentParserT] _name_parser_map: dict[str, _ArgumentParserT] choices: dict[str, _ArgumentParserT] _choices_actions: list[Action] @@ -421,7 +485,7 @@ class _SubParsersAction(Action, Generic[_ArgumentParserT]): self, option_strings: Sequence[str], prog: str, - parser_class: Type[_ArgumentParserT], + parser_class: type[_ArgumentParserT], dest: str = ..., required: bool = ..., help: str | None = ..., @@ -432,7 +496,7 @@ class _SubParsersAction(Action, Generic[_ArgumentParserT]): self, option_strings: Sequence[str], prog: str, - parser_class: Type[_ArgumentParserT], + parser_class: type[_ArgumentParserT], dest: str = ..., help: str | None = ..., metavar: str | tuple[str, ...] | None = ..., diff --git a/mypy/typeshed/stdlib/array.pyi b/mypy/typeshed/stdlib/array.pyi index f49eb2c916c28..69b4d35d9fe9e 100644 --- a/mypy/typeshed/stdlib/array.pyi +++ b/mypy/typeshed/stdlib/array.pyi @@ -1,19 +1,22 @@ import sys -from typing import Any, BinaryIO, Generic, Iterable, MutableSequence, TypeVar, Union, overload +from _typeshed import Self +from typing import Any, BinaryIO, Generic, Iterable, MutableSequence, TypeVar, overload from typing_extensions import Literal, SupportsIndex _IntTypeCode = Literal["b", "B", "h", "H", "i", "I", "l", "L", "q", "Q"] _FloatTypeCode = Literal["f", "d"] _UnicodeTypeCode = Literal["u"] -_TypeCode = Union[_IntTypeCode, _FloatTypeCode, _UnicodeTypeCode] +_TypeCode = _IntTypeCode | _FloatTypeCode | _UnicodeTypeCode _T = TypeVar("_T", int, float, str) typecodes: str class array(MutableSequence[_T], Generic[_T]): - typecode: _TypeCode - itemsize: int + @property + def typecode(self) -> _TypeCode: ... + @property + def itemsize(self) -> int: ... @overload def __init__(self: array[int], __typecode: _IntTypeCode, __initializer: bytes | Iterable[_T] = ...) -> None: ... @overload @@ -25,7 +28,7 @@ class array(MutableSequence[_T], Generic[_T]): def append(self, __v: _T) -> None: ... def buffer_info(self) -> tuple[int, int]: ... def byteswap(self) -> None: ... - def count(self, __v: Any) -> int: ... + def count(self, __v: _T) -> int: ... def extend(self, __bb: Iterable[_T]) -> None: ... def frombytes(self, __buffer: bytes) -> None: ... def fromfile(self, __f: BinaryIO, __n: int) -> None: ... @@ -34,10 +37,11 @@ class array(MutableSequence[_T], Generic[_T]): if sys.version_info >= (3, 10): def index(self, __v: _T, __start: int = ..., __stop: int = ...) -> int: ... else: - def index(self, __v: _T) -> int: ... # type: ignore # Overrides Sequence + def index(self, __v: _T) -> int: ... # type: ignore[override] + def insert(self, __i: int, __v: _T) -> None: ... def pop(self, __i: int = ...) -> _T: ... - def remove(self, __v: Any) -> None: ... + def remove(self, __v: _T) -> None: ... def reverse(self) -> None: ... def tobytes(self) -> bytes: ... def tofile(self, __f: BinaryIO) -> None: ... @@ -46,12 +50,14 @@ class array(MutableSequence[_T], Generic[_T]): if sys.version_info < (3, 9): def fromstring(self, __buffer: bytes) -> None: ... def tostring(self) -> bytes: ... + + def __contains__(self, __key: object) -> bool: ... def __len__(self) -> int: ... @overload def __getitem__(self, __i: SupportsIndex) -> _T: ... @overload def __getitem__(self, __s: slice) -> array[_T]: ... - @overload # type: ignore # Overrides MutableSequence + @overload # type: ignore[override] def __setitem__(self, __i: SupportsIndex, __o: _T) -> None: ... @overload def __setitem__(self, __s: slice, __o: array[_T]) -> None: ... @@ -59,11 +65,13 @@ class array(MutableSequence[_T], Generic[_T]): def __add__(self, __x: array[_T]) -> array[_T]: ... def __ge__(self, __other: array[_T]) -> bool: ... def __gt__(self, __other: array[_T]) -> bool: ... - def __iadd__(self, __x: array[_T]) -> array[_T]: ... # type: ignore # Overrides MutableSequence - def __imul__(self, __n: int) -> array[_T]: ... + def __iadd__(self: Self, __x: array[_T]) -> Self: ... # type: ignore[override] + def __imul__(self: Self, __n: int) -> Self: ... def __le__(self, __other: array[_T]) -> bool: ... def __lt__(self, __other: array[_T]) -> bool: ... def __mul__(self, __n: int) -> array[_T]: ... def __rmul__(self, __n: int) -> array[_T]: ... + def __copy__(self) -> array[_T]: ... + def __deepcopy__(self, __unused: Any) -> array[_T]: ... ArrayType = array diff --git a/mypy/typeshed/stdlib/ast.pyi b/mypy/typeshed/stdlib/ast.pyi index 8494a3a99126d..5a86d6888b2f9 100644 --- a/mypy/typeshed/stdlib/ast.pyi +++ b/mypy/typeshed/stdlib/ast.pyi @@ -15,14 +15,17 @@ from typing_extensions import Literal if sys.version_info >= (3, 8): class Num(Constant): value: complex + class Str(Constant): value: str # Aliases for value, for backwards compatibility s: str + class Bytes(Constant): value: bytes # Aliases for value, for backwards compatibility s: bytes + class NameConstant(Constant): ... class Ellipsis(Constant): ... @@ -88,6 +91,7 @@ class NodeVisitor: def visit_Constant(self, node: Constant) -> Any: ... if sys.version_info >= (3, 8): def visit_NamedExpr(self, node: NamedExpr) -> Any: ... + def visit_Attribute(self, node: Attribute) -> Any: ... def visit_Subscript(self, node: Subscript) -> Any: ... def visit_Starred(self, node: Starred) -> Any: ... diff --git a/mypy/typeshed/stdlib/asyncio/__init__.pyi b/mypy/typeshed/stdlib/asyncio/__init__.pyi index f2f7c6b0d1654..2f4823b22b244 100644 --- a/mypy/typeshed/stdlib/asyncio/__init__.pyi +++ b/mypy/typeshed/stdlib/asyncio/__init__.pyi @@ -1,125 +1,31 @@ import sys -from typing import Type -from .base_events import BaseEventLoop as BaseEventLoop -from .coroutines import iscoroutine as iscoroutine, iscoroutinefunction as iscoroutinefunction -from .events import ( - AbstractEventLoop as AbstractEventLoop, - AbstractEventLoopPolicy as AbstractEventLoopPolicy, - AbstractServer as AbstractServer, - Handle as Handle, - TimerHandle as TimerHandle, - _get_running_loop as _get_running_loop, - _set_running_loop as _set_running_loop, - get_child_watcher as get_child_watcher, - get_event_loop as get_event_loop, - get_event_loop_policy as get_event_loop_policy, - new_event_loop as new_event_loop, - set_child_watcher as set_child_watcher, - set_event_loop as set_event_loop, - set_event_loop_policy as set_event_loop_policy, -) -from .futures import Future as Future, isfuture as isfuture, wrap_future as wrap_future -from .locks import ( - BoundedSemaphore as BoundedSemaphore, - Condition as Condition, - Event as Event, - Lock as Lock, - Semaphore as Semaphore, -) -from .protocols import ( - BaseProtocol as BaseProtocol, - DatagramProtocol as DatagramProtocol, - Protocol as Protocol, - SubprocessProtocol as SubprocessProtocol, -) -from .queues import ( - LifoQueue as LifoQueue, - PriorityQueue as PriorityQueue, - Queue as Queue, - QueueEmpty as QueueEmpty, - QueueFull as QueueFull, -) -from .streams import ( - StreamReader as StreamReader, - StreamReaderProtocol as StreamReaderProtocol, - StreamWriter as StreamWriter, - open_connection as open_connection, - start_server as start_server, -) -from .subprocess import create_subprocess_exec as create_subprocess_exec, create_subprocess_shell as create_subprocess_shell -from .tasks import ( - ALL_COMPLETED as ALL_COMPLETED, - FIRST_COMPLETED as FIRST_COMPLETED, - FIRST_EXCEPTION as FIRST_EXCEPTION, - Task as Task, - as_completed as as_completed, - ensure_future as ensure_future, - gather as gather, - run_coroutine_threadsafe as run_coroutine_threadsafe, - shield as shield, - sleep as sleep, - wait as wait, - wait_for as wait_for, -) -from .transports import ( - BaseTransport as BaseTransport, - DatagramTransport as DatagramTransport, - ReadTransport as ReadTransport, - SubprocessTransport as SubprocessTransport, - Transport as Transport, - WriteTransport as WriteTransport, -) +# As at runtime, this depends on all submodules defining __all__ accurately. +from .base_events import * +from .coroutines import * +from .events import * +from .futures import * +from .locks import * +from .protocols import * +from .queues import * +from .streams import * +from .subprocess import * +from .tasks import * +from .transports import * -if sys.version_info < (3, 11): - from .coroutines import coroutine as coroutine - -if sys.version_info >= (3, 9): - from .threads import to_thread as to_thread - -if sys.version_info >= (3, 8): - from .exceptions import ( - CancelledError as CancelledError, - IncompleteReadError as IncompleteReadError, - InvalidStateError as InvalidStateError, - LimitOverrunError as LimitOverrunError, - TimeoutError as TimeoutError, - ) -else: - from .futures import CancelledError as CancelledError, InvalidStateError as InvalidStateError, TimeoutError as TimeoutError - from .streams import IncompleteReadError as IncompleteReadError, LimitOverrunError as LimitOverrunError +if sys.version_info >= (3, 7): + from .runners import * if sys.version_info >= (3, 8): - from .exceptions import SendfileNotAvailableError as SendfileNotAvailableError -elif sys.version_info >= (3, 7): - from .events import SendfileNotAvailableError as SendfileNotAvailableError + from .exceptions import * -if sys.version_info >= (3, 7): - from .events import get_running_loop as get_running_loop - from .protocols import BufferedProtocol as BufferedProtocol - from .runners import run as run - from .tasks import ( - _enter_task as _enter_task, - _leave_task as _leave_task, - _register_task as _register_task, - _unregister_task as _unregister_task, - all_tasks as all_tasks, - create_task as create_task, - current_task as current_task, - ) +if sys.version_info >= (3, 9): + from .threads import * -DefaultEventLoopPolicy: Type[AbstractEventLoopPolicy] +if sys.version_info >= (3, 11): + from .taskgroups import * if sys.platform == "win32": from .windows_events import * else: - from .streams import open_unix_connection as open_unix_connection, start_unix_server as start_unix_server - from .unix_events import ( - AbstractChildWatcher as AbstractChildWatcher, - FastChildWatcher as FastChildWatcher, - SafeChildWatcher as SafeChildWatcher, - SelectorEventLoop as SelectorEventLoop, - ) - - if sys.version_info >= (3, 8): - from .unix_events import MultiLoopChildWatcher as MultiLoopChildWatcher, ThreadedChildWatcher as ThreadedChildWatcher + from .unix_events import * diff --git a/mypy/typeshed/stdlib/asyncio/base_events.pyi b/mypy/typeshed/stdlib/asyncio/base_events.pyi index 674baf49ba05c..71e4487baf997 100644 --- a/mypy/typeshed/stdlib/asyncio/base_events.pyi +++ b/mypy/typeshed/stdlib/asyncio/base_events.pyi @@ -1,26 +1,32 @@ import ssl import sys from _typeshed import FileDescriptorLike -from abc import ABCMeta from asyncio.events import AbstractEventLoop, AbstractServer, Handle, TimerHandle from asyncio.futures import Future from asyncio.protocols import BaseProtocol from asyncio.tasks import Task -from asyncio.transports import BaseTransport +from asyncio.transports import BaseTransport, ReadTransport, SubprocessTransport, WriteTransport from collections.abc import Iterable from socket import AddressFamily, SocketKind, _Address, _RetAddress, socket -from typing import IO, Any, Awaitable, Callable, Generator, Sequence, TypeVar, Union, overload +from typing import IO, Any, Awaitable, Callable, Coroutine, Generator, Sequence, TypeVar, overload from typing_extensions import Literal if sys.version_info >= (3, 7): from contextvars import Context +if sys.version_info >= (3, 9): + __all__ = ("BaseEventLoop", "Server") +elif sys.version_info >= (3, 7): + __all__ = ("BaseEventLoop",) +else: + __all__ = ["BaseEventLoop"] + _T = TypeVar("_T") +_ProtocolT = TypeVar("_ProtocolT", bound=BaseProtocol) _Context = dict[str, Any] _ExceptionHandler = Callable[[AbstractEventLoop, _Context], Any] _ProtocolFactory = Callable[[], BaseProtocol] -_SSLContext = Union[bool, None, ssl.SSLContext] -_TransProtPair = tuple[BaseTransport, BaseProtocol] +_SSLContext = bool | None | ssl.SSLContext class Server(AbstractServer): if sys.version_info >= (3, 7): @@ -33,6 +39,10 @@ class Server(AbstractServer): backlog: int, ssl_handshake_timeout: float | None, ) -> None: ... + def get_loop(self) -> AbstractEventLoop: ... + def is_serving(self) -> bool: ... + async def start_serving(self) -> None: ... + async def serve_forever(self) -> None: ... else: def __init__(self, loop: AbstractEventLoop, sockets: list[socket]) -> None: ... if sys.version_info >= (3, 8): @@ -43,8 +53,10 @@ class Server(AbstractServer): def sockets(self) -> list[socket]: ... else: sockets: list[socket] | None + def close(self) -> None: ... + async def wait_closed(self) -> None: ... -class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): +class BaseEventLoop(AbstractEventLoop): def run_forever(self) -> None: ... # Can't use a union, see mypy issue # 1873. @overload @@ -69,14 +81,16 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): def call_soon(self, callback: Callable[..., Any], *args: Any) -> Handle: ... def call_later(self, delay: float, callback: Callable[..., Any], *args: Any) -> TimerHandle: ... def call_at(self, when: float, callback: Callable[..., Any], *args: Any) -> TimerHandle: ... + def time(self) -> float: ... # Future methods def create_future(self) -> Future[Any]: ... # Tasks methods if sys.version_info >= (3, 8): - def create_task(self, coro: Awaitable[_T] | Generator[Any, None, _T], *, name: object = ...) -> Task[_T]: ... + def create_task(self, coro: Coroutine[Any, Any, _T] | Generator[Any, None, _T], *, name: object = ...) -> Task[_T]: ... else: - def create_task(self, coro: Awaitable[_T] | Generator[Any, None, _T]) -> Task[_T]: ... + def create_task(self, coro: Coroutine[Any, Any, _T] | Generator[Any, None, _T]) -> Task[_T]: ... + def set_task_factory(self, factory: Callable[[AbstractEventLoop, Generator[Any, None, _T]], Future[_T]] | None) -> None: ... def get_task_factory(self) -> Callable[[AbstractEventLoop, Generator[Any, None, _T]], Future[_T]] | None: ... # Methods for interacting with threads @@ -84,18 +98,26 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): def call_soon_threadsafe(self, callback: Callable[..., Any], *args: Any, context: Context | None = ...) -> Handle: ... else: def call_soon_threadsafe(self, callback: Callable[..., Any], *args: Any) -> Handle: ... + def run_in_executor(self, executor: Any, func: Callable[..., _T], *args: Any) -> Future[_T]: ... def set_default_executor(self, executor: Any) -> None: ... # Network I/O methods returning Futures. async def getaddrinfo( - self, host: str | None, port: str | int | None, *, family: int = ..., type: int = ..., proto: int = ..., flags: int = ... + self, + host: bytes | str | None, + port: str | int | None, + *, + family: int = ..., + type: int = ..., + proto: int = ..., + flags: int = ..., ) -> list[tuple[AddressFamily, SocketKind, int, str, tuple[str, int] | tuple[str, int, int, int]]]: ... async def getnameinfo(self, sockaddr: tuple[str, int] | tuple[str, int, int, int], flags: int = ...) -> tuple[str, str]: ... if sys.version_info >= (3, 8): @overload async def create_connection( self, - protocol_factory: _ProtocolFactory, + protocol_factory: Callable[[], _ProtocolT], host: str = ..., port: int = ..., *, @@ -109,11 +131,11 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): ssl_handshake_timeout: float | None = ..., happy_eyeballs_delay: float | None = ..., interleave: int | None = ..., - ) -> _TransProtPair: ... + ) -> tuple[BaseTransport, _ProtocolT]: ... @overload async def create_connection( self, - protocol_factory: _ProtocolFactory, + protocol_factory: Callable[[], _ProtocolT], host: None = ..., port: None = ..., *, @@ -127,12 +149,12 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): ssl_handshake_timeout: float | None = ..., happy_eyeballs_delay: float | None = ..., interleave: int | None = ..., - ) -> _TransProtPair: ... + ) -> tuple[BaseTransport, _ProtocolT]: ... elif sys.version_info >= (3, 7): @overload async def create_connection( self, - protocol_factory: _ProtocolFactory, + protocol_factory: Callable[[], _ProtocolT], host: str = ..., port: int = ..., *, @@ -144,11 +166,11 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): local_addr: tuple[str, int] | None = ..., server_hostname: str | None = ..., ssl_handshake_timeout: float | None = ..., - ) -> _TransProtPair: ... + ) -> tuple[BaseTransport, _ProtocolT]: ... @overload async def create_connection( self, - protocol_factory: _ProtocolFactory, + protocol_factory: Callable[[], _ProtocolT], host: None = ..., port: None = ..., *, @@ -160,12 +182,12 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): local_addr: None = ..., server_hostname: str | None = ..., ssl_handshake_timeout: float | None = ..., - ) -> _TransProtPair: ... + ) -> tuple[BaseTransport, _ProtocolT]: ... else: @overload async def create_connection( self, - protocol_factory: _ProtocolFactory, + protocol_factory: Callable[[], _ProtocolT], host: str = ..., port: int = ..., *, @@ -176,11 +198,11 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): sock: None = ..., local_addr: tuple[str, int] | None = ..., server_hostname: str | None = ..., - ) -> _TransProtPair: ... + ) -> tuple[BaseTransport, _ProtocolT]: ... @overload async def create_connection( self, - protocol_factory: _ProtocolFactory, + protocol_factory: Callable[[], _ProtocolT], host: None = ..., port: None = ..., *, @@ -191,7 +213,7 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): sock: socket, local_addr: None = ..., server_hostname: str | None = ..., - ) -> _TransProtPair: ... + ) -> tuple[BaseTransport, _ProtocolT]: ... if sys.version_info >= (3, 7): async def sock_sendfile( self, sock: socket, file: IO[bytes], offset: int = ..., count: int | None = ..., *, fallback: bool | None = ... @@ -232,12 +254,12 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): ) -> Server: ... async def connect_accepted_socket( self, - protocol_factory: _ProtocolFactory, + protocol_factory: Callable[[], _ProtocolT], sock: socket, *, ssl: _SSLContext = ..., ssl_handshake_timeout: float | None = ..., - ) -> _TransProtPair: ... + ) -> tuple[BaseTransport, _ProtocolT]: ... async def sendfile( self, transport: BaseTransport, file: IO[bytes], offset: int = ..., count: int | None = ..., *, fallback: bool = ... ) -> int: ... @@ -283,12 +305,12 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): reuse_port: bool | None = ..., ) -> Server: ... async def connect_accepted_socket( - self, protocol_factory: _ProtocolFactory, sock: socket, *, ssl: _SSLContext = ... - ) -> _TransProtPair: ... + self, protocol_factory: Callable[[], _ProtocolT], sock: socket, *, ssl: _SSLContext = ... + ) -> tuple[BaseTransport, _ProtocolT]: ... if sys.version_info >= (3, 11): - async def create_datagram_endpoint( + async def create_datagram_endpoint( # type: ignore[override] self, - protocol_factory: _ProtocolFactory, + protocol_factory: Callable[[], _ProtocolT], local_addr: tuple[str, int] | None = ..., remote_addr: tuple[str, int] | None = ..., *, @@ -298,11 +320,11 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): reuse_port: bool | None = ..., allow_broadcast: bool | None = ..., sock: socket | None = ..., - ) -> _TransProtPair: ... + ) -> tuple[BaseTransport, _ProtocolT]: ... else: async def create_datagram_endpoint( self, - protocol_factory: _ProtocolFactory, + protocol_factory: Callable[[], _ProtocolT], local_addr: tuple[str, int] | None = ..., remote_addr: tuple[str, int] | None = ..., *, @@ -313,13 +335,17 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): reuse_port: bool | None = ..., allow_broadcast: bool | None = ..., sock: socket | None = ..., - ) -> _TransProtPair: ... + ) -> tuple[BaseTransport, _ProtocolT]: ... # Pipes and subprocesses. - async def connect_read_pipe(self, protocol_factory: _ProtocolFactory, pipe: Any) -> _TransProtPair: ... - async def connect_write_pipe(self, protocol_factory: _ProtocolFactory, pipe: Any) -> _TransProtPair: ... + async def connect_read_pipe( + self, protocol_factory: Callable[[], _ProtocolT], pipe: Any + ) -> tuple[ReadTransport, _ProtocolT]: ... + async def connect_write_pipe( + self, protocol_factory: Callable[[], _ProtocolT], pipe: Any + ) -> tuple[WriteTransport, _ProtocolT]: ... async def subprocess_shell( self, - protocol_factory: _ProtocolFactory, + protocol_factory: Callable[[], _ProtocolT], cmd: bytes | str, *, stdin: int | IO[Any] | None = ..., @@ -332,10 +358,10 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): errors: None = ..., text: Literal[False, None] = ..., **kwargs: Any, - ) -> _TransProtPair: ... + ) -> tuple[SubprocessTransport, _ProtocolT]: ... async def subprocess_exec( self, - protocol_factory: _ProtocolFactory, + protocol_factory: Callable[[], _ProtocolT], program: Any, *args: Any, stdin: int | IO[Any] | None = ..., @@ -347,11 +373,11 @@ class BaseEventLoop(AbstractEventLoop, metaclass=ABCMeta): encoding: None = ..., errors: None = ..., **kwargs: Any, - ) -> _TransProtPair: ... + ) -> tuple[SubprocessTransport, _ProtocolT]: ... def add_reader(self, fd: FileDescriptorLike, callback: Callable[..., Any], *args: Any) -> None: ... - def remove_reader(self, fd: FileDescriptorLike) -> None: ... + def remove_reader(self, fd: FileDescriptorLike) -> bool: ... def add_writer(self, fd: FileDescriptorLike, callback: Callable[..., Any], *args: Any) -> None: ... - def remove_writer(self, fd: FileDescriptorLike) -> None: ... + def remove_writer(self, fd: FileDescriptorLike) -> bool: ... # Completion based I/O methods returning Futures prior to 3.7 if sys.version_info >= (3, 7): async def sock_recv(self, sock: socket, nbytes: int) -> bytes: ... diff --git a/mypy/typeshed/stdlib/asyncio/base_futures.pyi b/mypy/typeshed/stdlib/asyncio/base_futures.pyi index 72ba6163e9d39..1b7fe4671ca82 100644 --- a/mypy/typeshed/stdlib/asyncio/base_futures.pyi +++ b/mypy/typeshed/stdlib/asyncio/base_futures.pyi @@ -7,12 +7,20 @@ if sys.version_info >= (3, 7): from . import futures +if sys.version_info >= (3, 7): + __all__ = () +else: + __all__: list[str] = [] + +# asyncio defines 'isfuture()' in base_futures.py and re-imports it in futures.py +# but it leads to circular import error in pytype tool. +# That's why the import order is reversed. +from .futures import isfuture as isfuture + _PENDING: Literal["PENDING"] # undocumented _CANCELLED: Literal["CANCELLED"] # undocumented _FINISHED: Literal["FINISHED"] # undocumented -def isfuture(obj: object) -> bool: ... - if sys.version_info >= (3, 7): def _format_callbacks(cb: Sequence[tuple[Callable[[futures.Future[Any]], None], Context]]) -> str: ... # undocumented diff --git a/mypy/typeshed/stdlib/asyncio/base_subprocess.pyi b/mypy/typeshed/stdlib/asyncio/base_subprocess.pyi index 94c7c01dd1bc7..21c56bde1eac7 100644 --- a/mypy/typeshed/stdlib/asyncio/base_subprocess.pyi +++ b/mypy/typeshed/stdlib/asyncio/base_subprocess.pyi @@ -1,10 +1,10 @@ import subprocess from collections import deque -from typing import IO, Any, Callable, Optional, Sequence, Union +from typing import IO, Any, Callable, Sequence from . import events, futures, protocols, transports -_File = Optional[Union[int, IO[Any]]] +_File = int | IO[Any] | None class BaseSubprocessTransport(transports.SubprocessTransport): diff --git a/mypy/typeshed/stdlib/asyncio/compat.pyi b/mypy/typeshed/stdlib/asyncio/compat.pyi index 1beeea9d6c3f7..f6f1bbca7faf6 100644 --- a/mypy/typeshed/stdlib/asyncio/compat.pyi +++ b/mypy/typeshed/stdlib/asyncio/compat.pyi @@ -1,7 +1,5 @@ -import sys +PY34: bool +PY35: bool +PY352: bool -if sys.version_info < (3, 7): - PY34: bool - PY35: bool - PY352: bool - def flatten_list_bytes(list_of_data: list[bytes]) -> bytes: ... +def flatten_list_bytes(list_of_data: list[bytes]) -> bytes: ... diff --git a/mypy/typeshed/stdlib/asyncio/coroutines.pyi b/mypy/typeshed/stdlib/asyncio/coroutines.pyi index 6c2d8179d1f14..6d4d507c6a4c2 100644 --- a/mypy/typeshed/stdlib/asyncio/coroutines.pyi +++ b/mypy/typeshed/stdlib/asyncio/coroutines.pyi @@ -4,6 +4,13 @@ from collections.abc import Coroutine from typing import Any from typing_extensions import TypeGuard +if sys.version_info >= (3, 11): + __all__ = ("iscoroutinefunction", "iscoroutine") +elif sys.version_info >= (3, 7): + __all__ = ("coroutine", "iscoroutinefunction", "iscoroutine") +else: + __all__ = ["coroutine", "iscoroutinefunction", "iscoroutine"] + if sys.version_info < (3, 11): from collections.abc import Callable from typing import TypeVar diff --git a/mypy/typeshed/stdlib/asyncio/events.pyi b/mypy/typeshed/stdlib/asyncio/events.pyi index 81b30b7e00651..cc0391f92bc4a 100644 --- a/mypy/typeshed/stdlib/asyncio/events.pyi +++ b/mypy/typeshed/stdlib/asyncio/events.pyi @@ -3,28 +3,85 @@ import sys from _typeshed import FileDescriptorLike, Self from abc import ABCMeta, abstractmethod from socket import AddressFamily, SocketKind, _Address, _RetAddress, socket -from typing import IO, Any, Awaitable, Callable, Generator, Sequence, TypeVar, Union, overload +from typing import IO, Any, Awaitable, Callable, Coroutine, Generator, Sequence, TypeVar, overload from typing_extensions import Literal from .base_events import Server from .futures import Future from .protocols import BaseProtocol from .tasks import Task -from .transports import BaseTransport +from .transports import BaseTransport, ReadTransport, SubprocessTransport, WriteTransport from .unix_events import AbstractChildWatcher if sys.version_info >= (3, 7): from contextvars import Context +if sys.version_info >= (3, 8): + __all__ = ( + "AbstractEventLoopPolicy", + "AbstractEventLoop", + "AbstractServer", + "Handle", + "TimerHandle", + "get_event_loop_policy", + "set_event_loop_policy", + "get_event_loop", + "set_event_loop", + "new_event_loop", + "get_child_watcher", + "set_child_watcher", + "_set_running_loop", + "get_running_loop", + "_get_running_loop", + ) + +elif sys.version_info >= (3, 7): + __all__ = ( + "AbstractEventLoopPolicy", + "AbstractEventLoop", + "AbstractServer", + "Handle", + "TimerHandle", + "SendfileNotAvailableError", + "get_event_loop_policy", + "set_event_loop_policy", + "get_event_loop", + "set_event_loop", + "new_event_loop", + "get_child_watcher", + "set_child_watcher", + "_set_running_loop", + "get_running_loop", + "_get_running_loop", + ) + +else: + __all__ = [ + "AbstractEventLoopPolicy", + "AbstractEventLoop", + "AbstractServer", + "Handle", + "TimerHandle", + "get_event_loop_policy", + "set_event_loop_policy", + "get_event_loop", + "set_event_loop", + "new_event_loop", + "get_child_watcher", + "set_child_watcher", + "_set_running_loop", + "_get_running_loop", + ] + _T = TypeVar("_T") +_ProtocolT = TypeVar("_ProtocolT", bound=BaseProtocol) _Context = dict[str, Any] _ExceptionHandler = Callable[[AbstractEventLoop, _Context], Any] _ProtocolFactory = Callable[[], BaseProtocol] -_SSLContext = Union[bool, None, ssl.SSLContext] -_TransProtPair = tuple[BaseTransport, BaseProtocol] +_SSLContext = bool | None | ssl.SSLContext class Handle: - _cancelled = False + _cancelled: bool _args: Sequence[Any] if sys.version_info >= (3, 7): def __init__( @@ -32,7 +89,7 @@ class Handle: ) -> None: ... else: def __init__(self, callback: Callable[..., Any], args: Sequence[Any], loop: AbstractEventLoop) -> None: ... - def __repr__(self) -> str: ... + def cancel(self) -> None: ... def _run(self) -> None: ... if sys.version_info >= (3, 7): @@ -50,22 +107,36 @@ class TimerHandle(Handle): ) -> None: ... else: def __init__(self, when: float, callback: Callable[..., Any], args: Sequence[Any], loop: AbstractEventLoop) -> None: ... + def __hash__(self) -> int: ... if sys.version_info >= (3, 7): def when(self) -> float: ... + def __lt__(self, other: TimerHandle) -> bool: ... + def __le__(self, other: TimerHandle) -> bool: ... + def __gt__(self, other: TimerHandle) -> bool: ... + def __ge__(self, other: TimerHandle) -> bool: ... + def __eq__(self, other: object) -> bool: ... + class AbstractServer: + @abstractmethod def close(self) -> None: ... if sys.version_info >= (3, 7): async def __aenter__(self: Self) -> Self: ... - async def __aexit__(self, *exc: Any) -> None: ... + async def __aexit__(self, *exc: object) -> None: ... + @abstractmethod def get_loop(self) -> AbstractEventLoop: ... + @abstractmethod def is_serving(self) -> bool: ... + @abstractmethod async def start_serving(self) -> None: ... + @abstractmethod async def serve_forever(self) -> None: ... + + @abstractmethod async def wait_closed(self) -> None: ... -class AbstractEventLoop(metaclass=ABCMeta): +class AbstractEventLoop: slow_callback_duration: float @abstractmethod def run_forever(self) -> None: ... @@ -87,12 +158,25 @@ class AbstractEventLoop(metaclass=ABCMeta): @abstractmethod async def shutdown_asyncgens(self) -> None: ... # Methods scheduling callbacks. All these return Handles. - @abstractmethod - def call_soon(self, callback: Callable[..., Any], *args: Any) -> Handle: ... - @abstractmethod - def call_later(self, delay: float, callback: Callable[..., Any], *args: Any) -> TimerHandle: ... - @abstractmethod - def call_at(self, when: float, callback: Callable[..., Any], *args: Any) -> TimerHandle: ... + if sys.version_info >= (3, 9): # "context" added in 3.9.10/3.10.2 + @abstractmethod + def call_soon(self, callback: Callable[..., Any], *args: Any, context: Context | None = ...) -> Handle: ... + @abstractmethod + def call_later( + self, delay: float, callback: Callable[..., Any], *args: Any, context: Context | None = ... + ) -> TimerHandle: ... + @abstractmethod + def call_at( + self, when: float, callback: Callable[..., Any], *args: Any, context: Context | None = ... + ) -> TimerHandle: ... + else: + @abstractmethod + def call_soon(self, callback: Callable[..., Any], *args: Any) -> Handle: ... + @abstractmethod + def call_later(self, delay: float, callback: Callable[..., Any], *args: Any) -> TimerHandle: ... + @abstractmethod + def call_at(self, when: float, callback: Callable[..., Any], *args: Any) -> TimerHandle: ... + @abstractmethod def time(self) -> float: ... # Future methods @@ -101,17 +185,25 @@ class AbstractEventLoop(metaclass=ABCMeta): # Tasks methods if sys.version_info >= (3, 8): @abstractmethod - def create_task(self, coro: Awaitable[_T] | Generator[Any, None, _T], *, name: str | None = ...) -> Task[_T]: ... + def create_task( + self, coro: Coroutine[Any, Any, _T] | Generator[Any, None, _T], *, name: str | None = ... + ) -> Task[_T]: ... else: @abstractmethod - def create_task(self, coro: Awaitable[_T] | Generator[Any, None, _T]) -> Task[_T]: ... + def create_task(self, coro: Coroutine[Any, Any, _T] | Generator[Any, None, _T]) -> Task[_T]: ... + @abstractmethod def set_task_factory(self, factory: Callable[[AbstractEventLoop, Generator[Any, None, _T]], Future[_T]] | None) -> None: ... @abstractmethod def get_task_factory(self) -> Callable[[AbstractEventLoop, Generator[Any, None, _T]], Future[_T]] | None: ... # Methods for interacting with threads - @abstractmethod - def call_soon_threadsafe(self, callback: Callable[..., Any], *args: Any) -> Handle: ... + if sys.version_info >= (3, 9): # "context" added in 3.9.10/3.10.2 + @abstractmethod + def call_soon_threadsafe(self, callback: Callable[..., Any], *args: Any, context: Context | None = ...) -> Handle: ... + else: + @abstractmethod + def call_soon_threadsafe(self, callback: Callable[..., Any], *args: Any) -> Handle: ... + @abstractmethod def run_in_executor(self, executor: Any, func: Callable[..., _T], *args: Any) -> Future[_T]: ... @abstractmethod @@ -119,7 +211,14 @@ class AbstractEventLoop(metaclass=ABCMeta): # Network I/O methods returning Futures. @abstractmethod async def getaddrinfo( - self, host: str | None, port: str | int | None, *, family: int = ..., type: int = ..., proto: int = ..., flags: int = ... + self, + host: bytes | str | None, + port: str | int | None, + *, + family: int = ..., + type: int = ..., + proto: int = ..., + flags: int = ..., ) -> list[tuple[AddressFamily, SocketKind, int, str, tuple[str, int] | tuple[str, int, int, int]]]: ... @abstractmethod async def getnameinfo(self, sockaddr: tuple[str, int] | tuple[str, int, int, int], flags: int = ...) -> tuple[str, str]: ... @@ -128,7 +227,7 @@ class AbstractEventLoop(metaclass=ABCMeta): @abstractmethod async def create_connection( self, - protocol_factory: _ProtocolFactory, + protocol_factory: Callable[[], _ProtocolT], host: str = ..., port: int = ..., *, @@ -142,12 +241,12 @@ class AbstractEventLoop(metaclass=ABCMeta): ssl_handshake_timeout: float | None = ..., happy_eyeballs_delay: float | None = ..., interleave: int | None = ..., - ) -> _TransProtPair: ... + ) -> tuple[BaseTransport, _ProtocolT]: ... @overload @abstractmethod async def create_connection( self, - protocol_factory: _ProtocolFactory, + protocol_factory: Callable[[], _ProtocolT], host: None = ..., port: None = ..., *, @@ -161,13 +260,13 @@ class AbstractEventLoop(metaclass=ABCMeta): ssl_handshake_timeout: float | None = ..., happy_eyeballs_delay: float | None = ..., interleave: int | None = ..., - ) -> _TransProtPair: ... + ) -> tuple[BaseTransport, _ProtocolT]: ... elif sys.version_info >= (3, 7): @overload @abstractmethod async def create_connection( self, - protocol_factory: _ProtocolFactory, + protocol_factory: Callable[[], _ProtocolT], host: str = ..., port: int = ..., *, @@ -179,12 +278,12 @@ class AbstractEventLoop(metaclass=ABCMeta): local_addr: tuple[str, int] | None = ..., server_hostname: str | None = ..., ssl_handshake_timeout: float | None = ..., - ) -> _TransProtPair: ... + ) -> tuple[BaseTransport, _ProtocolT]: ... @overload @abstractmethod async def create_connection( self, - protocol_factory: _ProtocolFactory, + protocol_factory: Callable[[], _ProtocolT], host: None = ..., port: None = ..., *, @@ -196,13 +295,13 @@ class AbstractEventLoop(metaclass=ABCMeta): local_addr: None = ..., server_hostname: str | None = ..., ssl_handshake_timeout: float | None = ..., - ) -> _TransProtPair: ... + ) -> tuple[BaseTransport, _ProtocolT]: ... else: @overload @abstractmethod async def create_connection( self, - protocol_factory: _ProtocolFactory, + protocol_factory: Callable[[], _ProtocolT], host: str = ..., port: int = ..., *, @@ -213,12 +312,12 @@ class AbstractEventLoop(metaclass=ABCMeta): sock: None = ..., local_addr: tuple[str, int] | None = ..., server_hostname: str | None = ..., - ) -> _TransProtPair: ... + ) -> tuple[BaseTransport, _ProtocolT]: ... @overload @abstractmethod async def create_connection( self, - protocol_factory: _ProtocolFactory, + protocol_factory: Callable[[], _ProtocolT], host: None = ..., port: None = ..., *, @@ -229,7 +328,7 @@ class AbstractEventLoop(metaclass=ABCMeta): sock: socket, local_addr: None = ..., server_hostname: str | None = ..., - ) -> _TransProtPair: ... + ) -> tuple[BaseTransport, _ProtocolT]: ... if sys.version_info >= (3, 7): @abstractmethod async def sock_sendfile( @@ -273,14 +372,14 @@ class AbstractEventLoop(metaclass=ABCMeta): ) -> Server: ... async def create_unix_connection( self, - protocol_factory: _ProtocolFactory, + protocol_factory: Callable[[], _ProtocolT], path: str | None = ..., *, ssl: _SSLContext = ..., sock: socket | None = ..., server_hostname: str | None = ..., ssl_handshake_timeout: float | None = ..., - ) -> _TransProtPair: ... + ) -> tuple[BaseTransport, _ProtocolT]: ... async def create_unix_server( self, protocol_factory: _ProtocolFactory, @@ -342,13 +441,13 @@ class AbstractEventLoop(metaclass=ABCMeta): ) -> Server: ... async def create_unix_connection( self, - protocol_factory: _ProtocolFactory, + protocol_factory: Callable[[], _ProtocolT], path: str, *, ssl: _SSLContext = ..., sock: socket | None = ..., server_hostname: str | None = ..., - ) -> _TransProtPair: ... + ) -> tuple[BaseTransport, _ProtocolT]: ... async def create_unix_server( self, protocol_factory: _ProtocolFactory, @@ -358,10 +457,11 @@ class AbstractEventLoop(metaclass=ABCMeta): backlog: int = ..., ssl: _SSLContext = ..., ) -> Server: ... + @abstractmethod async def create_datagram_endpoint( self, - protocol_factory: _ProtocolFactory, + protocol_factory: Callable[[], _ProtocolT], local_addr: tuple[str, int] | None = ..., remote_addr: tuple[str, int] | None = ..., *, @@ -372,16 +472,20 @@ class AbstractEventLoop(metaclass=ABCMeta): reuse_port: bool | None = ..., allow_broadcast: bool | None = ..., sock: socket | None = ..., - ) -> _TransProtPair: ... + ) -> tuple[BaseTransport, _ProtocolT]: ... # Pipes and subprocesses. @abstractmethod - async def connect_read_pipe(self, protocol_factory: _ProtocolFactory, pipe: Any) -> _TransProtPair: ... + async def connect_read_pipe( + self, protocol_factory: Callable[[], _ProtocolT], pipe: Any + ) -> tuple[ReadTransport, _ProtocolT]: ... @abstractmethod - async def connect_write_pipe(self, protocol_factory: _ProtocolFactory, pipe: Any) -> _TransProtPair: ... + async def connect_write_pipe( + self, protocol_factory: Callable[[], _ProtocolT], pipe: Any + ) -> tuple[WriteTransport, _ProtocolT]: ... @abstractmethod async def subprocess_shell( self, - protocol_factory: _ProtocolFactory, + protocol_factory: Callable[[], _ProtocolT], cmd: bytes | str, *, stdin: int | IO[Any] | None = ..., @@ -394,11 +498,11 @@ class AbstractEventLoop(metaclass=ABCMeta): errors: None = ..., text: Literal[False, None] = ..., **kwargs: Any, - ) -> _TransProtPair: ... + ) -> tuple[SubprocessTransport, _ProtocolT]: ... @abstractmethod async def subprocess_exec( self, - protocol_factory: _ProtocolFactory, + protocol_factory: Callable[[], _ProtocolT], program: Any, *args: Any, stdin: int | IO[Any] | None = ..., @@ -410,15 +514,15 @@ class AbstractEventLoop(metaclass=ABCMeta): encoding: None = ..., errors: None = ..., **kwargs: Any, - ) -> _TransProtPair: ... + ) -> tuple[SubprocessTransport, _ProtocolT]: ... @abstractmethod def add_reader(self, fd: FileDescriptorLike, callback: Callable[..., Any], *args: Any) -> None: ... @abstractmethod - def remove_reader(self, fd: FileDescriptorLike) -> None: ... + def remove_reader(self, fd: FileDescriptorLike) -> bool: ... @abstractmethod def add_writer(self, fd: FileDescriptorLike, callback: Callable[..., Any], *args: Any) -> None: ... @abstractmethod - def remove_writer(self, fd: FileDescriptorLike) -> None: ... + def remove_writer(self, fd: FileDescriptorLike) -> bool: ... # Completion based I/O methods returning Futures prior to 3.7 if sys.version_info >= (3, 7): @abstractmethod @@ -463,7 +567,7 @@ class AbstractEventLoop(metaclass=ABCMeta): @abstractmethod async def shutdown_default_executor(self) -> None: ... -class AbstractEventLoopPolicy(metaclass=ABCMeta): +class AbstractEventLoopPolicy: @abstractmethod def get_event_loop(self) -> AbstractEventLoop: ... @abstractmethod diff --git a/mypy/typeshed/stdlib/asyncio/exceptions.pyi b/mypy/typeshed/stdlib/asyncio/exceptions.pyi index 5b99966329ace..a1bc2c16ab1fc 100644 --- a/mypy/typeshed/stdlib/asyncio/exceptions.pyi +++ b/mypy/typeshed/stdlib/asyncio/exceptions.pyi @@ -1,14 +1,22 @@ -import sys +__all__ = ( + "CancelledError", + "InvalidStateError", + "TimeoutError", + "IncompleteReadError", + "LimitOverrunError", + "SendfileNotAvailableError", +) -if sys.version_info >= (3, 8): - class CancelledError(BaseException): ... - class TimeoutError(Exception): ... - class InvalidStateError(Exception): ... - class SendfileNotAvailableError(RuntimeError): ... - class IncompleteReadError(EOFError): - expected: int | None - partial: bytes - def __init__(self, partial: bytes, expected: int | None) -> None: ... - class LimitOverrunError(Exception): - consumed: int - def __init__(self, message: str, consumed: int) -> None: ... +class CancelledError(BaseException): ... +class TimeoutError(Exception): ... +class InvalidStateError(Exception): ... +class SendfileNotAvailableError(RuntimeError): ... + +class IncompleteReadError(EOFError): + expected: int | None + partial: bytes + def __init__(self, partial: bytes, expected: int | None) -> None: ... + +class LimitOverrunError(Exception): + consumed: int + def __init__(self, message: str, consumed: int) -> None: ... diff --git a/mypy/typeshed/stdlib/asyncio/format_helpers.pyi b/mypy/typeshed/stdlib/asyncio/format_helpers.pyi index be80efe266b10..5e483a578c3ee 100644 --- a/mypy/typeshed/stdlib/asyncio/format_helpers.pyi +++ b/mypy/typeshed/stdlib/asyncio/format_helpers.pyi @@ -1,20 +1,18 @@ import functools -import sys import traceback from types import FrameType, FunctionType -from typing import Any, Iterable, Union, overload +from typing import Any, Iterable, overload class _HasWrapper: __wrapper__: _HasWrapper | FunctionType -_FuncType = Union[FunctionType, _HasWrapper, functools.partial[Any], functools.partialmethod[Any]] +_FuncType = FunctionType | _HasWrapper | functools.partial[Any] | functools.partialmethod[Any] -if sys.version_info >= (3, 7): - @overload - def _get_function_source(func: _FuncType) -> tuple[str, int]: ... - @overload - def _get_function_source(func: object) -> tuple[str, int] | None: ... - def _format_callback_source(func: object, args: Iterable[Any]) -> str: ... - def _format_args_and_kwargs(args: Iterable[Any], kwargs: dict[str, Any]) -> str: ... - def _format_callback(func: object, args: Iterable[Any], kwargs: dict[str, Any], suffix: str = ...) -> str: ... - def extract_stack(f: FrameType | None = ..., limit: int | None = ...) -> traceback.StackSummary: ... +@overload +def _get_function_source(func: _FuncType) -> tuple[str, int]: ... +@overload +def _get_function_source(func: object) -> tuple[str, int] | None: ... +def _format_callback_source(func: object, args: Iterable[Any]) -> str: ... +def _format_args_and_kwargs(args: Iterable[Any], kwargs: dict[str, Any]) -> str: ... +def _format_callback(func: object, args: Iterable[Any], kwargs: dict[str, Any], suffix: str = ...) -> str: ... +def extract_stack(f: FrameType | None = ..., limit: int | None = ...) -> traceback.StackSummary: ... diff --git a/mypy/typeshed/stdlib/asyncio/futures.pyi b/mypy/typeshed/stdlib/asyncio/futures.pyi index 9788123f427ec..2b0b93a096383 100644 --- a/mypy/typeshed/stdlib/asyncio/futures.pyi +++ b/mypy/typeshed/stdlib/asyncio/futures.pyi @@ -1,11 +1,14 @@ import sys +from _typeshed import Self from concurrent.futures._base import Error, Future as _ConcurrentFuture from typing import Any, Awaitable, Callable, Generator, Iterable, TypeVar +from typing_extensions import Literal, TypeGuard from .events import AbstractEventLoop if sys.version_info < (3, 8): from concurrent.futures import CancelledError as CancelledError, TimeoutError as TimeoutError + class InvalidStateError(Error): ... if sys.version_info >= (3, 7): @@ -14,8 +17,19 @@ if sys.version_info >= (3, 7): if sys.version_info >= (3, 9): from types import GenericAlias +if sys.version_info >= (3, 8): + __all__ = ("Future", "wrap_future", "isfuture") +elif sys.version_info >= (3, 7): + __all__ = ("CancelledError", "TimeoutError", "InvalidStateError", "Future", "wrap_future", "isfuture") +else: + __all__ = ["CancelledError", "TimeoutError", "InvalidStateError", "Future", "wrap_future", "isfuture"] + _T = TypeVar("_T") -_S = TypeVar("_S") + +# asyncio defines 'isfuture()' in base_futures.py and re-imports it in futures.py +# but it leads to circular import error in pytype tool. +# That's why the import order is reversed. +def isfuture(obj: object) -> TypeGuard[Future[Any]]: ... if sys.version_info < (3, 7): class _TracebackLogger: @@ -26,33 +40,36 @@ if sys.version_info < (3, 7): def clear(self) -> None: ... def __del__(self) -> None: ... -def isfuture(obj: object) -> bool: ... - class Future(Awaitable[_T], Iterable[_T]): _state: str - _exception: BaseException - _blocking = False - _log_traceback = False + @property + def _exception(self) -> BaseException: ... + _blocking: bool + @property + def _log_traceback(self) -> bool: ... + @_log_traceback.setter + def _log_traceback(self, val: Literal[False]) -> None: ... + _asyncio_future_blocking: bool # is a part of duck-typing contract for `Future` def __init__(self, *, loop: AbstractEventLoop | None = ...) -> None: ... - def __repr__(self) -> str: ... def __del__(self) -> None: ... if sys.version_info >= (3, 7): def get_loop(self) -> AbstractEventLoop: ... - def _callbacks(self: _S) -> list[tuple[Callable[[_S], Any], Context]]: ... - def add_done_callback(self: _S, __fn: Callable[[_S], Any], *, context: Context | None = ...) -> None: ... + def _callbacks(self: Self) -> list[tuple[Callable[[Self], Any], Context]]: ... + def add_done_callback(self: Self, __fn: Callable[[Self], Any], *, context: Context | None = ...) -> None: ... else: @property - def _callbacks(self: _S) -> list[Callable[[_S], Any]]: ... - def add_done_callback(self: _S, __fn: Callable[[_S], Any]) -> None: ... + def _callbacks(self: Self) -> list[Callable[[Self], Any]]: ... + def add_done_callback(self: Self, __fn: Callable[[Self], Any]) -> None: ... if sys.version_info >= (3, 9): def cancel(self, msg: Any | None = ...) -> bool: ... else: def cancel(self) -> bool: ... + def cancelled(self) -> bool: ... def done(self) -> bool: ... def result(self) -> _T: ... def exception(self) -> BaseException | None: ... - def remove_done_callback(self: _S, __fn: Callable[[_S], Any]) -> int: ... + def remove_done_callback(self: Self, __fn: Callable[[Self], Any]) -> int: ... def set_result(self, __result: _T) -> None: ... def set_exception(self, __exception: type | BaseException) -> None: ... def __iter__(self) -> Generator[Any, None, _T]: ... diff --git a/mypy/typeshed/stdlib/asyncio/locks.pyi b/mypy/typeshed/stdlib/asyncio/locks.pyi index 7c4f40d9e4ca0..01b1c5b4591d6 100644 --- a/mypy/typeshed/stdlib/asyncio/locks.pyi +++ b/mypy/typeshed/stdlib/asyncio/locks.pyi @@ -1,42 +1,47 @@ import sys from collections import deque from types import TracebackType -from typing import Any, Awaitable, Callable, Generator, Type, TypeVar +from typing import Any, Callable, Generator, TypeVar +from typing_extensions import Literal from .events import AbstractEventLoop from .futures import Future +if sys.version_info >= (3, 7): + __all__ = ("Lock", "Event", "Condition", "Semaphore", "BoundedSemaphore") +else: + __all__ = ["Lock", "Event", "Condition", "Semaphore", "BoundedSemaphore"] + _T = TypeVar("_T") if sys.version_info >= (3, 9): class _ContextManagerMixin: - def __init__(self, lock: Lock | Semaphore) -> None: ... - def __aenter__(self) -> Awaitable[None]: ... - def __aexit__( - self, exc_type: Type[BaseException] | None, exc: BaseException | None, tb: TracebackType | None - ) -> Awaitable[None]: ... + async def __aenter__(self) -> None: ... + async def __aexit__( + self, exc_type: type[BaseException] | None, exc: BaseException | None, tb: TracebackType | None + ) -> None: ... else: class _ContextManager: def __init__(self, lock: Lock | Semaphore) -> None: ... - def __enter__(self) -> object: ... - def __exit__(self, *args: Any) -> None: ... + def __enter__(self) -> None: ... + def __exit__(self, *args: object) -> None: ... + class _ContextManagerMixin: - def __init__(self, lock: Lock | Semaphore) -> None: ... # Apparently this exists to *prohibit* use as a context manager. - def __enter__(self) -> object: ... - def __exit__(self, *args: Any) -> None: ... + # def __enter__(self) -> NoReturn: ... see: https://github.com/python/typing/issues/1043 + # def __exit__(self, *args: Any) -> None: ... def __iter__(self) -> Generator[Any, None, _ContextManager]: ... def __await__(self) -> Generator[Any, None, _ContextManager]: ... - def __aenter__(self) -> Awaitable[None]: ... - def __aexit__( - self, exc_type: Type[BaseException] | None, exc: BaseException | None, tb: TracebackType | None - ) -> Awaitable[None]: ... + async def __aenter__(self) -> None: ... + async def __aexit__( + self, exc_type: type[BaseException] | None, exc: BaseException | None, tb: TracebackType | None + ) -> None: ... class Lock(_ContextManagerMixin): def __init__(self, *, loop: AbstractEventLoop | None = ...) -> None: ... def locked(self) -> bool: ... - async def acquire(self) -> bool: ... + async def acquire(self) -> Literal[True]: ... def release(self) -> None: ... class Event: @@ -44,14 +49,14 @@ class Event: def is_set(self) -> bool: ... def set(self) -> None: ... def clear(self) -> None: ... - async def wait(self) -> bool: ... + async def wait(self) -> Literal[True]: ... class Condition(_ContextManagerMixin): def __init__(self, lock: Lock | None = ..., *, loop: AbstractEventLoop | None = ...) -> None: ... def locked(self) -> bool: ... - async def acquire(self) -> bool: ... + async def acquire(self) -> Literal[True]: ... def release(self) -> None: ... - async def wait(self) -> bool: ... + async def wait(self) -> Literal[True]: ... async def wait_for(self, predicate: Callable[[], _T]) -> _T: ... def notify(self, n: int = ...) -> None: ... def notify_all(self) -> None: ... @@ -61,7 +66,7 @@ class Semaphore(_ContextManagerMixin): _waiters: deque[Future[Any]] def __init__(self, value: int = ..., *, loop: AbstractEventLoop | None = ...) -> None: ... def locked(self) -> bool: ... - async def acquire(self) -> bool: ... + async def acquire(self) -> Literal[True]: ... def release(self) -> None: ... def _wake_up_next(self) -> None: ... diff --git a/mypy/typeshed/stdlib/asyncio/mixins.pyi b/mypy/typeshed/stdlib/asyncio/mixins.pyi new file mode 100644 index 0000000000000..4c11865c8968f --- /dev/null +++ b/mypy/typeshed/stdlib/asyncio/mixins.pyi @@ -0,0 +1,7 @@ +import threading +from typing import NoReturn + +_global_lock: threading.Lock + +class _LoopBoundMixin: + def __init__(self, *, loop: NoReturn = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/asyncio/proactor_events.pyi b/mypy/typeshed/stdlib/asyncio/proactor_events.pyi index 1e9cff1b1dd67..4ffb401604202 100644 --- a/mypy/typeshed/stdlib/asyncio/proactor_events.pyi +++ b/mypy/typeshed/stdlib/asyncio/proactor_events.pyi @@ -1,14 +1,19 @@ import sys from socket import socket -from typing import Any, Mapping, Protocol, Type +from typing import Any, Mapping, Protocol from typing_extensions import Literal from . import base_events, constants, events, futures, streams, transports +if sys.version_info >= (3, 7): + __all__ = ("BaseProactorEventLoop",) +else: + __all__ = ["BaseProactorEventLoop"] + if sys.version_info >= (3, 8): class _WarnCallbackProtocol(Protocol): def __call__( - self, message: str, category: Type[Warning] | None = ..., stacklevel: int = ..., source: Any | None = ... + self, message: str, category: type[Warning] | None = ..., stacklevel: int = ..., source: Any | None = ... ) -> None: ... class _ProactorBasePipeTransport(transports._FlowControlMixin, transports.BaseTransport): @@ -21,23 +26,35 @@ class _ProactorBasePipeTransport(transports._FlowControlMixin, transports.BaseTr extra: Mapping[Any, Any] | None = ..., server: events.AbstractServer | None = ..., ) -> None: ... - def __repr__(self) -> str: ... if sys.version_info >= (3, 8): def __del__(self, _warn: _WarnCallbackProtocol = ...) -> None: ... else: def __del__(self) -> None: ... + def get_write_buffer_size(self) -> int: ... class _ProactorReadPipeTransport(_ProactorBasePipeTransport, transports.ReadTransport): - def __init__( - self, - loop: events.AbstractEventLoop, - sock: socket, - protocol: streams.StreamReaderProtocol, - waiter: futures.Future[Any] | None = ..., - extra: Mapping[Any, Any] | None = ..., - server: events.AbstractServer | None = ..., - ) -> None: ... + if sys.version_info >= (3, 10): + def __init__( + self, + loop: events.AbstractEventLoop, + sock: socket, + protocol: streams.StreamReaderProtocol, + waiter: futures.Future[Any] | None = ..., + extra: Mapping[Any, Any] | None = ..., + server: events.AbstractServer | None = ..., + buffer_size: int = ..., + ) -> None: ... + else: + def __init__( + self, + loop: events.AbstractEventLoop, + sock: socket, + protocol: streams.StreamReaderProtocol, + waiter: futures.Future[Any] | None = ..., + extra: Mapping[Any, Any] | None = ..., + server: events.AbstractServer | None = ..., + ) -> None: ... class _ProactorBaseWritePipeTransport(_ProactorBasePipeTransport, transports.WriteTransport): def __init__( diff --git a/mypy/typeshed/stdlib/asyncio/protocols.pyi b/mypy/typeshed/stdlib/asyncio/protocols.pyi index 754f02c8bb4bf..7b5169702dbac 100644 --- a/mypy/typeshed/stdlib/asyncio/protocols.pyi +++ b/mypy/typeshed/stdlib/asyncio/protocols.pyi @@ -1,5 +1,11 @@ import sys from asyncio import transports +from typing import Any + +if sys.version_info >= (3, 7): + __all__ = ("BaseProtocol", "Protocol", "DatagramProtocol", "SubprocessProtocol", "BufferedProtocol") +else: + __all__ = ["BaseProtocol", "Protocol", "DatagramProtocol", "SubprocessProtocol"] class BaseProtocol: def connection_made(self, transport: transports.BaseTransport) -> None: ... @@ -15,10 +21,15 @@ if sys.version_info >= (3, 7): class BufferedProtocol(BaseProtocol): def get_buffer(self, sizehint: int) -> bytearray: ... def buffer_updated(self, nbytes: int) -> None: ... + def eof_received(self) -> bool | None: ... class DatagramProtocol(BaseProtocol): def connection_made(self, transport: transports.DatagramTransport) -> None: ... # type: ignore[override] - def datagram_received(self, data: bytes, addr: tuple[str, int]) -> None: ... + # addr can be a tuple[int, int] for some unusual protocols like socket.AF_NETLINK. + # Use tuple[str | Any, int] to not cause typechecking issues on most usual cases. + # This could be improved by using tuple[AnyOf[str, int], int] if the AnyOf feature is accepted. + # See https://github.com/python/typing/issues/566 + def datagram_received(self, data: bytes, addr: tuple[str | Any, int]) -> None: ... def error_received(self, exc: Exception) -> None: ... class SubprocessProtocol(BaseProtocol): diff --git a/mypy/typeshed/stdlib/asyncio/queues.pyi b/mypy/typeshed/stdlib/asyncio/queues.pyi index aff4af727b08a..93ea9d9fc6fec 100644 --- a/mypy/typeshed/stdlib/asyncio/queues.pyi +++ b/mypy/typeshed/stdlib/asyncio/queues.pyi @@ -5,6 +5,11 @@ from typing import Any, Generic, TypeVar if sys.version_info >= (3, 9): from types import GenericAlias +if sys.version_info >= (3, 7): + __all__ = ("Queue", "PriorityQueue", "LifoQueue", "QueueFull", "QueueEmpty") +else: + __all__ = ["Queue", "PriorityQueue", "LifoQueue", "QueueFull", "QueueEmpty"] + class QueueEmpty(Exception): ... class QueueFull(Exception): ... @@ -15,8 +20,6 @@ class Queue(Generic[_T]): def _init(self, maxsize: int) -> None: ... def _get(self) -> _T: ... def _put(self, item: _T) -> None: ... - def __repr__(self) -> str: ... - def __str__(self) -> str: ... def _format(self) -> str: ... def qsize(self) -> int: ... @property diff --git a/mypy/typeshed/stdlib/asyncio/runners.pyi b/mypy/typeshed/stdlib/asyncio/runners.pyi index 3f0f42eef48bb..7e799dd22fd8e 100644 --- a/mypy/typeshed/stdlib/asyncio/runners.pyi +++ b/mypy/typeshed/stdlib/asyncio/runners.pyi @@ -1,10 +1,10 @@ import sys +from typing import Awaitable, TypeVar -if sys.version_info >= (3, 7): - from typing import Awaitable, TypeVar +__all__ = ("run",) +_T = TypeVar("_T") +if sys.version_info >= (3, 8): + def run(main: Awaitable[_T], *, debug: bool | None = ...) -> _T: ... - _T = TypeVar("_T") - if sys.version_info >= (3, 8): - def run(main: Awaitable[_T], *, debug: bool | None = ...) -> _T: ... - else: - def run(main: Awaitable[_T], *, debug: bool = ...) -> _T: ... +else: + def run(main: Awaitable[_T], *, debug: bool = ...) -> _T: ... diff --git a/mypy/typeshed/stdlib/asyncio/selector_events.pyi b/mypy/typeshed/stdlib/asyncio/selector_events.pyi index bcbcd2fbe4b81..698bfef351a1c 100644 --- a/mypy/typeshed/stdlib/asyncio/selector_events.pyi +++ b/mypy/typeshed/stdlib/asyncio/selector_events.pyi @@ -1,6 +1,12 @@ import selectors +import sys from . import base_events +if sys.version_info >= (3, 7): + __all__ = ("BaseSelectorEventLoop",) +else: + __all__ = ["BaseSelectorEventLoop"] + class BaseSelectorEventLoop(base_events.BaseEventLoop): def __init__(self, selector: selectors.BaseSelector | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/asyncio/sslproto.pyi b/mypy/typeshed/stdlib/asyncio/sslproto.pyi index 082e96dc02331..4ecd7a11dd56f 100644 --- a/mypy/typeshed/stdlib/asyncio/sslproto.pyi +++ b/mypy/typeshed/stdlib/asyncio/sslproto.pyi @@ -57,6 +57,7 @@ class _SSLProtocolTransport(transports._FlowControlMixin, transports.Transport): def close(self) -> None: ... if sys.version_info >= (3, 7): def is_reading(self) -> bool: ... + def pause_reading(self) -> None: ... def resume_reading(self) -> None: ... def set_write_buffer_limits(self, high: int | None = ..., low: int | None = ...) -> None: ... @@ -64,6 +65,7 @@ class _SSLProtocolTransport(transports._FlowControlMixin, transports.Transport): if sys.version_info >= (3, 7): @property def _protocol_paused(self) -> bool: ... + def write(self, data: bytes) -> None: ... def can_write_eof(self) -> Literal[False]: ... def abort(self) -> None: ... @@ -114,6 +116,7 @@ class SSLProtocol(protocols.Protocol): ) -> None: ... if sys.version_info >= (3, 7): def _set_app_protocol(self, app_protocol: protocols.BaseProtocol) -> None: ... + def _wakeup_waiter(self, exc: BaseException | None = ...) -> None: ... def connection_made(self, transport: transports.BaseTransport) -> None: ... def connection_lost(self, exc: BaseException | None) -> None: ... @@ -127,6 +130,7 @@ class SSLProtocol(protocols.Protocol): def _start_handshake(self) -> None: ... if sys.version_info >= (3, 7): def _check_handshake_timeout(self) -> None: ... + def _on_handshake_complete(self, handshake_exc: BaseException | None) -> None: ... def _process_write_backlog(self) -> None: ... def _fatal_error(self, exc: BaseException, message: str = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/asyncio/staggered.pyi b/mypy/typeshed/stdlib/asyncio/staggered.pyi index 1d76d382555dc..fc4bfad769845 100644 --- a/mypy/typeshed/stdlib/asyncio/staggered.pyi +++ b/mypy/typeshed/stdlib/asyncio/staggered.pyi @@ -1,9 +1,9 @@ -import sys from typing import Any, Awaitable, Callable, Iterable from . import events -if sys.version_info >= (3, 8): - async def staggered_race( - coro_fns: Iterable[Callable[[], Awaitable[Any]]], delay: float | None, *, loop: events.AbstractEventLoop | None = ... - ) -> tuple[Any, int | None, list[Exception | None]]: ... +__all__ = ("staggered_race",) + +async def staggered_race( + coro_fns: Iterable[Callable[[], Awaitable[Any]]], delay: float | None, *, loop: events.AbstractEventLoop | None = ... +) -> tuple[Any, int | None, list[Exception | None]]: ... diff --git a/mypy/typeshed/stdlib/asyncio/streams.pyi b/mypy/typeshed/stdlib/asyncio/streams.pyi index 6dae893e3b974..98349222d5a29 100644 --- a/mypy/typeshed/stdlib/asyncio/streams.pyi +++ b/mypy/typeshed/stdlib/asyncio/streams.pyi @@ -1,17 +1,77 @@ import sys -from _typeshed import StrPath -from typing import Any, AsyncIterator, Awaitable, Callable, Iterable, Optional +from _typeshed import Self, StrPath +from typing import Any, AsyncIterator, Awaitable, Callable, Iterable, Sequence from . import events, protocols, transports from .base_events import Server -_ClientConnectedCallback = Callable[[StreamReader, StreamWriter], Optional[Awaitable[None]]] +if sys.platform == "win32": + if sys.version_info >= (3, 8): + __all__ = ("StreamReader", "StreamWriter", "StreamReaderProtocol", "open_connection", "start_server") + elif sys.version_info >= (3, 7): + __all__ = ( + "StreamReader", + "StreamWriter", + "StreamReaderProtocol", + "open_connection", + "start_server", + "IncompleteReadError", + "LimitOverrunError", + ) + else: + __all__ = [ + "StreamReader", + "StreamWriter", + "StreamReaderProtocol", + "open_connection", + "start_server", + "IncompleteReadError", + "LimitOverrunError", + ] +else: + if sys.version_info >= (3, 8): + __all__ = ( + "StreamReader", + "StreamWriter", + "StreamReaderProtocol", + "open_connection", + "start_server", + "open_unix_connection", + "start_unix_server", + ) + elif sys.version_info >= (3, 7): + __all__ = ( + "StreamReader", + "StreamWriter", + "StreamReaderProtocol", + "open_connection", + "start_server", + "IncompleteReadError", + "LimitOverrunError", + "open_unix_connection", + "start_unix_server", + ) + else: + __all__ = [ + "StreamReader", + "StreamWriter", + "StreamReaderProtocol", + "open_connection", + "start_server", + "IncompleteReadError", + "LimitOverrunError", + "open_unix_connection", + "start_unix_server", + ] + +_ClientConnectedCallback = Callable[[StreamReader, StreamWriter], Awaitable[None] | None] if sys.version_info < (3, 8): class IncompleteReadError(EOFError): expected: int | None partial: bytes def __init__(self, partial: bytes, expected: int | None) -> None: ... + class LimitOverrunError(Exception): consumed: int def __init__(self, message: str, consumed: int) -> None: ... @@ -27,7 +87,7 @@ if sys.version_info >= (3, 10): ) -> tuple[StreamReader, StreamWriter]: ... async def start_server( client_connected_cb: _ClientConnectedCallback, - host: str | None = ..., + host: str | Sequence[str] | None = ..., port: int | str | None = ..., *, limit: int = ..., @@ -114,10 +174,11 @@ class StreamWriter: if sys.version_info >= (3, 7): def is_closing(self) -> bool: ... async def wait_closed(self) -> None: ... + def get_extra_info(self, name: str, default: Any = ...) -> Any: ... async def drain(self) -> None: ... -class StreamReader: +class StreamReader(AsyncIterator[bytes]): def __init__(self, limit: int = ..., loop: events.AbstractEventLoop | None = ...) -> None: ... def exception(self) -> Exception: ... def set_exception(self, exc: Exception) -> None: ... @@ -129,5 +190,5 @@ class StreamReader: async def readuntil(self, separator: bytes = ...) -> bytes: ... async def read(self, n: int = ...) -> bytes: ... async def readexactly(self, n: int) -> bytes: ... - def __aiter__(self) -> AsyncIterator[bytes]: ... + def __aiter__(self: Self) -> Self: ... async def __anext__(self) -> bytes: ... diff --git a/mypy/typeshed/stdlib/asyncio/subprocess.pyi b/mypy/typeshed/stdlib/asyncio/subprocess.pyi index d835c12af3d8b..3a617d6fb6281 100644 --- a/mypy/typeshed/stdlib/asyncio/subprocess.pyi +++ b/mypy/typeshed/stdlib/asyncio/subprocess.pyi @@ -2,13 +2,18 @@ import subprocess import sys from _typeshed import StrOrBytesPath from asyncio import events, protocols, streams, transports -from typing import IO, Any, Callable, Union +from typing import IO, Any, Callable from typing_extensions import Literal +if sys.version_info >= (3, 7): + __all__ = ("create_subprocess_exec", "create_subprocess_shell") +else: + __all__ = ["create_subprocess_exec", "create_subprocess_shell"] + if sys.version_info >= (3, 8): _ExecArg = StrOrBytesPath else: - _ExecArg = Union[str, bytes] + _ExecArg = str | bytes PIPE: int STDOUT: int diff --git a/mypy/typeshed/stdlib/asyncio/taskgroups.pyi b/mypy/typeshed/stdlib/asyncio/taskgroups.pyi new file mode 100644 index 0000000000000..ef04614c3c15e --- /dev/null +++ b/mypy/typeshed/stdlib/asyncio/taskgroups.pyi @@ -0,0 +1,17 @@ +# This only exists in 3.11+. See VERSIONS. + +from _typeshed import Self +from types import TracebackType +from typing import Any, Coroutine, Generator, TypeVar + +from .tasks import Task + +__all__ = ["TaskGroup"] + +_T = TypeVar("_T") + +class TaskGroup: + def __init__(self) -> None: ... + async def __aenter__(self: Self) -> Self: ... + async def __aexit__(self, et: type[BaseException] | None, exc: BaseException | None, tb: TracebackType | None) -> None: ... + def create_task(self, coro: Generator[Any, None, _T] | Coroutine[Any, Any, _T], *, name: str | None = ...) -> Task[_T]: ... diff --git a/mypy/typeshed/stdlib/asyncio/tasks.pyi b/mypy/typeshed/stdlib/asyncio/tasks.pyi index 71f9741cb33b7..885688065ddc5 100644 --- a/mypy/typeshed/stdlib/asyncio/tasks.pyi +++ b/mypy/typeshed/stdlib/asyncio/tasks.pyi @@ -2,7 +2,7 @@ import concurrent.futures import sys from collections.abc import Awaitable, Generator, Iterable, Iterator from types import FrameType -from typing import Any, Generic, Optional, TextIO, TypeVar, Union, overload +from typing import Any, Coroutine, Generic, TextIO, TypeVar, overload from typing_extensions import Literal from .events import AbstractEventLoop @@ -11,6 +11,44 @@ from .futures import Future if sys.version_info >= (3, 9): from types import GenericAlias +if sys.version_info >= (3, 7): + __all__ = ( + "Task", + "create_task", + "FIRST_COMPLETED", + "FIRST_EXCEPTION", + "ALL_COMPLETED", + "wait", + "wait_for", + "as_completed", + "sleep", + "gather", + "shield", + "ensure_future", + "run_coroutine_threadsafe", + "current_task", + "all_tasks", + "_register_task", + "_unregister_task", + "_enter_task", + "_leave_task", + ) +else: + __all__ = [ + "Task", + "FIRST_COMPLETED", + "FIRST_EXCEPTION", + "ALL_COMPLETED", + "wait", + "wait_for", + "as_completed", + "sleep", + "gather", + "shield", + "ensure_future", + "run_coroutine_threadsafe", + ] + _T = TypeVar("_T") _T1 = TypeVar("_T1") _T2 = TypeVar("_T2") @@ -18,8 +56,8 @@ _T3 = TypeVar("_T3") _T4 = TypeVar("_T4") _T5 = TypeVar("_T5") _FT = TypeVar("_FT", bound=Future[Any]) -_FutureT = Union[Future[_T], Generator[Any, None, _T], Awaitable[_T]] -_TaskYieldType = Optional[Future[object]] +_FutureT = Future[_T] | Generator[Any, None, _T] | Awaitable[_T] +_TaskYieldType = Future[object] | None FIRST_COMPLETED = concurrent.futures.FIRST_COMPLETED FIRST_EXCEPTION = concurrent.futures.FIRST_EXCEPTION @@ -47,79 +85,79 @@ def ensure_future(coro_or_future: Awaitable[_T], *, loop: AbstractEventLoop | No # typing PR #1550 for discussion. if sys.version_info >= (3, 10): @overload - def gather(coro_or_future1: _FutureT[_T1], *, return_exceptions: Literal[False] = ...) -> Future[tuple[_T1]]: ... + def gather(__coro_or_future1: _FutureT[_T1], *, return_exceptions: Literal[False] = ...) -> Future[tuple[_T1]]: ... @overload def gather( - coro_or_future1: _FutureT[_T1], coro_or_future2: _FutureT[_T2], *, return_exceptions: Literal[False] = ... + __coro_or_future1: _FutureT[_T1], __coro_or_future2: _FutureT[_T2], *, return_exceptions: Literal[False] = ... ) -> Future[tuple[_T1, _T2]]: ... @overload def gather( - coro_or_future1: _FutureT[_T1], - coro_or_future2: _FutureT[_T2], - coro_or_future3: _FutureT[_T3], + __coro_or_future1: _FutureT[_T1], + __coro_or_future2: _FutureT[_T2], + __coro_or_future3: _FutureT[_T3], *, return_exceptions: Literal[False] = ..., ) -> Future[tuple[_T1, _T2, _T3]]: ... @overload def gather( - coro_or_future1: _FutureT[_T1], - coro_or_future2: _FutureT[_T2], - coro_or_future3: _FutureT[_T3], - coro_or_future4: _FutureT[_T4], + __coro_or_future1: _FutureT[_T1], + __coro_or_future2: _FutureT[_T2], + __coro_or_future3: _FutureT[_T3], + __coro_or_future4: _FutureT[_T4], *, return_exceptions: Literal[False] = ..., ) -> Future[tuple[_T1, _T2, _T3, _T4]]: ... @overload def gather( - coro_or_future1: _FutureT[_T1], - coro_or_future2: _FutureT[_T2], - coro_or_future3: _FutureT[_T3], - coro_or_future4: _FutureT[_T4], - coro_or_future5: _FutureT[_T5], + __coro_or_future1: _FutureT[_T1], + __coro_or_future2: _FutureT[_T2], + __coro_or_future3: _FutureT[_T3], + __coro_or_future4: _FutureT[_T4], + __coro_or_future5: _FutureT[_T5], *, return_exceptions: Literal[False] = ..., ) -> Future[tuple[_T1, _T2, _T3, _T4, _T5]]: ... @overload def gather( - coro_or_future1: _FutureT[Any], - coro_or_future2: _FutureT[Any], - coro_or_future3: _FutureT[Any], - coro_or_future4: _FutureT[Any], - coro_or_future5: _FutureT[Any], - coro_or_future6: _FutureT[Any], + __coro_or_future1: _FutureT[Any], + __coro_or_future2: _FutureT[Any], + __coro_or_future3: _FutureT[Any], + __coro_or_future4: _FutureT[Any], + __coro_or_future5: _FutureT[Any], + __coro_or_future6: _FutureT[Any], *coros_or_futures: _FutureT[Any], return_exceptions: bool = ..., ) -> Future[list[Any]]: ... @overload - def gather(coro_or_future1: _FutureT[_T1], *, return_exceptions: bool = ...) -> Future[tuple[_T1 | BaseException]]: ... + def gather(__coro_or_future1: _FutureT[_T1], *, return_exceptions: bool = ...) -> Future[tuple[_T1 | BaseException]]: ... @overload def gather( - coro_or_future1: _FutureT[_T1], coro_or_future2: _FutureT[_T2], *, return_exceptions: bool = ... + __coro_or_future1: _FutureT[_T1], __coro_or_future2: _FutureT[_T2], *, return_exceptions: bool = ... ) -> Future[tuple[_T1 | BaseException, _T2 | BaseException]]: ... @overload def gather( - coro_or_future1: _FutureT[_T1], - coro_or_future2: _FutureT[_T2], - coro_or_future3: _FutureT[_T3], + __coro_or_future1: _FutureT[_T1], + __coro_or_future2: _FutureT[_T2], + __coro_or_future3: _FutureT[_T3], *, return_exceptions: bool = ..., ) -> Future[tuple[_T1 | BaseException, _T2 | BaseException, _T3 | BaseException]]: ... @overload def gather( - coro_or_future1: _FutureT[_T1], - coro_or_future2: _FutureT[_T2], - coro_or_future3: _FutureT[_T3], - coro_or_future4: _FutureT[_T4], + __coro_or_future1: _FutureT[_T1], + __coro_or_future2: _FutureT[_T2], + __coro_or_future3: _FutureT[_T3], + __coro_or_future4: _FutureT[_T4], *, return_exceptions: bool = ..., ) -> Future[tuple[_T1 | BaseException, _T2 | BaseException, _T3 | BaseException, _T4 | BaseException]]: ... @overload def gather( - coro_or_future1: _FutureT[_T1], - coro_or_future2: _FutureT[_T2], - coro_or_future3: _FutureT[_T3], - coro_or_future4: _FutureT[_T4], - coro_or_future5: _FutureT[_T5], + __coro_or_future1: _FutureT[_T1], + __coro_or_future2: _FutureT[_T2], + __coro_or_future3: _FutureT[_T3], + __coro_or_future4: _FutureT[_T4], + __coro_or_future5: _FutureT[_T5], *, return_exceptions: bool = ..., ) -> Future[ @@ -129,96 +167,96 @@ if sys.version_info >= (3, 10): else: @overload def gather( - coro_or_future1: _FutureT[_T1], *, loop: AbstractEventLoop | None = ..., return_exceptions: Literal[False] = ... + __coro_or_future1: _FutureT[_T1], *, loop: AbstractEventLoop | None = ..., return_exceptions: Literal[False] = ... ) -> Future[tuple[_T1]]: ... @overload def gather( - coro_or_future1: _FutureT[_T1], - coro_or_future2: _FutureT[_T2], + __coro_or_future1: _FutureT[_T1], + __coro_or_future2: _FutureT[_T2], *, loop: AbstractEventLoop | None = ..., return_exceptions: Literal[False] = ..., ) -> Future[tuple[_T1, _T2]]: ... @overload def gather( - coro_or_future1: _FutureT[_T1], - coro_or_future2: _FutureT[_T2], - coro_or_future3: _FutureT[_T3], + __coro_or_future1: _FutureT[_T1], + __coro_or_future2: _FutureT[_T2], + __coro_or_future3: _FutureT[_T3], *, loop: AbstractEventLoop | None = ..., return_exceptions: Literal[False] = ..., ) -> Future[tuple[_T1, _T2, _T3]]: ... @overload def gather( - coro_or_future1: _FutureT[_T1], - coro_or_future2: _FutureT[_T2], - coro_or_future3: _FutureT[_T3], - coro_or_future4: _FutureT[_T4], + __coro_or_future1: _FutureT[_T1], + __coro_or_future2: _FutureT[_T2], + __coro_or_future3: _FutureT[_T3], + __coro_or_future4: _FutureT[_T4], *, loop: AbstractEventLoop | None = ..., return_exceptions: Literal[False] = ..., ) -> Future[tuple[_T1, _T2, _T3, _T4]]: ... @overload def gather( - coro_or_future1: _FutureT[_T1], - coro_or_future2: _FutureT[_T2], - coro_or_future3: _FutureT[_T3], - coro_or_future4: _FutureT[_T4], - coro_or_future5: _FutureT[_T5], + __coro_or_future1: _FutureT[_T1], + __coro_or_future2: _FutureT[_T2], + __coro_or_future3: _FutureT[_T3], + __coro_or_future4: _FutureT[_T4], + __coro_or_future5: _FutureT[_T5], *, loop: AbstractEventLoop | None = ..., return_exceptions: Literal[False] = ..., ) -> Future[tuple[_T1, _T2, _T3, _T4, _T5]]: ... @overload def gather( - coro_or_future1: _FutureT[Any], - coro_or_future2: _FutureT[Any], - coro_or_future3: _FutureT[Any], - coro_or_future4: _FutureT[Any], - coro_or_future5: _FutureT[Any], - coro_or_future6: _FutureT[Any], + __coro_or_future1: _FutureT[Any], + __coro_or_future2: _FutureT[Any], + __coro_or_future3: _FutureT[Any], + __coro_or_future4: _FutureT[Any], + __coro_or_future5: _FutureT[Any], + __coro_or_future6: _FutureT[Any], *coros_or_futures: _FutureT[Any], loop: AbstractEventLoop | None = ..., return_exceptions: bool = ..., ) -> Future[list[Any]]: ... @overload def gather( - coro_or_future1: _FutureT[_T1], *, loop: AbstractEventLoop | None = ..., return_exceptions: bool = ... + __coro_or_future1: _FutureT[_T1], *, loop: AbstractEventLoop | None = ..., return_exceptions: bool = ... ) -> Future[tuple[_T1 | BaseException]]: ... @overload def gather( - coro_or_future1: _FutureT[_T1], - coro_or_future2: _FutureT[_T2], + __coro_or_future1: _FutureT[_T1], + __coro_or_future2: _FutureT[_T2], *, loop: AbstractEventLoop | None = ..., return_exceptions: bool = ..., ) -> Future[tuple[_T1 | BaseException, _T2 | BaseException]]: ... @overload def gather( - coro_or_future1: _FutureT[_T1], - coro_or_future2: _FutureT[_T2], - coro_or_future3: _FutureT[_T3], + __coro_or_future1: _FutureT[_T1], + __coro_or_future2: _FutureT[_T2], + __coro_or_future3: _FutureT[_T3], *, loop: AbstractEventLoop | None = ..., return_exceptions: bool = ..., ) -> Future[tuple[_T1 | BaseException, _T2 | BaseException, _T3 | BaseException]]: ... @overload def gather( - coro_or_future1: _FutureT[_T1], - coro_or_future2: _FutureT[_T2], - coro_or_future3: _FutureT[_T3], - coro_or_future4: _FutureT[_T4], + __coro_or_future1: _FutureT[_T1], + __coro_or_future2: _FutureT[_T2], + __coro_or_future3: _FutureT[_T3], + __coro_or_future4: _FutureT[_T4], *, loop: AbstractEventLoop | None = ..., return_exceptions: bool = ..., ) -> Future[tuple[_T1 | BaseException, _T2 | BaseException, _T3 | BaseException, _T4 | BaseException]]: ... @overload def gather( - coro_or_future1: _FutureT[_T1], - coro_or_future2: _FutureT[_T2], - coro_or_future3: _FutureT[_T3], - coro_or_future4: _FutureT[_T4], - coro_or_future5: _FutureT[_T5], + __coro_or_future1: _FutureT[_T1], + __coro_or_future2: _FutureT[_T2], + __coro_or_future3: _FutureT[_T3], + __coro_or_future4: _FutureT[_T4], + __coro_or_future5: _FutureT[_T5], *, loop: AbstractEventLoop | None = ..., return_exceptions: bool = ..., @@ -265,17 +303,20 @@ class Task(Future[_T], Generic[_T]): def __init__( self, coro: Generator[_TaskYieldType, None, _T] | Awaitable[_T], *, loop: AbstractEventLoop = ... ) -> None: ... - def __repr__(self) -> str: ... if sys.version_info >= (3, 8): def get_coro(self) -> Generator[_TaskYieldType, None, _T] | Awaitable[_T]: ... def get_name(self) -> str: ... def set_name(self, __value: object) -> None: ... + def get_stack(self, *, limit: int | None = ...) -> list[FrameType]: ... def print_stack(self, *, limit: int | None = ..., file: TextIO | None = ...) -> None: ... if sys.version_info >= (3, 9): def cancel(self, msg: Any | None = ...) -> bool: ... else: def cancel(self) -> bool: ... + if sys.version_info >= (3, 11): + def cancelling(self) -> int: ... + def uncancel(self) -> int: ... if sys.version_info < (3, 9): @classmethod def current_task(cls, loop: AbstractEventLoop | None = ...) -> Task[Any] | None: ... @@ -289,9 +330,10 @@ class Task(Future[_T], Generic[_T]): if sys.version_info >= (3, 7): def all_tasks(loop: AbstractEventLoop | None = ...) -> set[Task[Any]]: ... if sys.version_info >= (3, 8): - def create_task(coro: Generator[_TaskYieldType, None, _T] | Awaitable[_T], *, name: str | None = ...) -> Task[_T]: ... + def create_task(coro: Generator[Any, None, _T] | Coroutine[Any, Any, _T], *, name: str | None = ...) -> Task[_T]: ... else: - def create_task(coro: Generator[_TaskYieldType, None, _T] | Awaitable[_T]) -> Task[_T]: ... + def create_task(coro: Generator[Any, None, _T] | Coroutine[Any, Any, _T]) -> Task[_T]: ... + def current_task(loop: AbstractEventLoop | None = ...) -> Task[Any] | None: ... def _enter_task(loop: AbstractEventLoop, task: Task[Any]) -> None: ... def _leave_task(loop: AbstractEventLoop, task: Task[Any]) -> None: ... diff --git a/mypy/typeshed/stdlib/asyncio/threads.pyi b/mypy/typeshed/stdlib/asyncio/threads.pyi index c13c0c6d11948..ac3a5c56b222d 100644 --- a/mypy/typeshed/stdlib/asyncio/threads.pyi +++ b/mypy/typeshed/stdlib/asyncio/threads.pyi @@ -1,9 +1,8 @@ -import sys from typing import Callable, TypeVar from typing_extensions import ParamSpec +__all__ = ("to_thread",) _P = ParamSpec("_P") _R = TypeVar("_R") -if sys.version_info >= (3, 9): - async def to_thread(__func: Callable[_P, _R], *args: _P.args, **kwargs: _P.kwargs) -> _R: ... +async def to_thread(__func: Callable[_P, _R], *args: _P.args, **kwargs: _P.kwargs) -> _R: ... diff --git a/mypy/typeshed/stdlib/asyncio/transports.pyi b/mypy/typeshed/stdlib/asyncio/transports.pyi index acca0e4c28b4e..c24ded49cfb86 100644 --- a/mypy/typeshed/stdlib/asyncio/transports.pyi +++ b/mypy/typeshed/stdlib/asyncio/transports.pyi @@ -4,6 +4,11 @@ from asyncio.protocols import BaseProtocol from socket import _Address from typing import Any, Mapping +if sys.version_info >= (3, 7): + __all__ = ("BaseTransport", "ReadTransport", "WriteTransport", "Transport", "DatagramTransport", "SubprocessTransport") +else: + __all__ = ["BaseTransport", "ReadTransport", "WriteTransport", "Transport", "DatagramTransport", "SubprocessTransport"] + class BaseTransport: def __init__(self, extra: Mapping[Any, Any] | None = ...) -> None: ... def get_extra_info(self, name: Any, default: Any = ...) -> Any: ... @@ -15,6 +20,7 @@ class BaseTransport: class ReadTransport(BaseTransport): if sys.version_info >= (3, 7): def is_reading(self) -> bool: ... + def pause_reading(self) -> None: ... def resume_reading(self) -> None: ... diff --git a/mypy/typeshed/stdlib/asyncio/trsock.pyi b/mypy/typeshed/stdlib/asyncio/trsock.pyi index 55147f4fddd52..3fe1e19d1311d 100644 --- a/mypy/typeshed/stdlib/asyncio/trsock.pyi +++ b/mypy/typeshed/stdlib/asyncio/trsock.pyi @@ -1,39 +1,44 @@ import socket import sys +from builtins import type as Type # alias to avoid name clashes with property named "type" from types import TracebackType -from typing import Any, BinaryIO, Iterable, NoReturn, Type, Union, overload +from typing import Any, BinaryIO, Iterable, NoReturn, overload -if sys.version_info >= (3, 8): - # These are based in socket, maybe move them out into _typeshed.pyi or such - _Address = Union[tuple[Any, ...], str] - _RetAddress = Any - _WriteBuffer = Union[bytearray, memoryview] - _CMSG = tuple[int, int, bytes] - class TransportSocket: - def __init__(self, sock: socket.socket) -> None: ... - def _na(self, what: str) -> None: ... - @property - def family(self) -> int: ... - @property - def type(self) -> int: ... - @property - def proto(self) -> int: ... - def __getstate__(self) -> NoReturn: ... - def fileno(self) -> int: ... - def dup(self) -> socket.socket: ... - def get_inheritable(self) -> bool: ... - def shutdown(self, how: int) -> None: ... - @overload - def getsockopt(self, level: int, optname: int) -> int: ... - @overload - def getsockopt(self, level: int, optname: int, buflen: int) -> bytes: ... - @overload - def setsockopt(self, level: int, optname: int, value: int | bytes) -> None: ... - @overload - def setsockopt(self, level: int, optname: int, value: None, optlen: int) -> None: ... - def getpeername(self) -> _RetAddress: ... - def getsockname(self) -> _RetAddress: ... - def getsockbyname(self) -> NoReturn: ... # This method doesn't exist on socket, yet is passed through? +# These are based in socket, maybe move them out into _typeshed.pyi or such +_Address = tuple[Any, ...] | str +_RetAddress = Any +_WriteBuffer = bytearray | memoryview +_CMSG = tuple[int, int, bytes] + +class TransportSocket: + def __init__(self, sock: socket.socket) -> None: ... + def _na(self, what: str) -> None: ... + @property + def family(self) -> int: ... + @property + def type(self) -> int: ... + @property + def proto(self) -> int: ... + def __getstate__(self) -> NoReturn: ... + def fileno(self) -> int: ... + def dup(self) -> socket.socket: ... + def get_inheritable(self) -> bool: ... + def shutdown(self, how: int) -> None: ... + @overload + def getsockopt(self, level: int, optname: int) -> int: ... + @overload + def getsockopt(self, level: int, optname: int, buflen: int) -> bytes: ... + @overload + def setsockopt(self, level: int, optname: int, value: int | bytes) -> None: ... + @overload + def setsockopt(self, level: int, optname: int, value: None, optlen: int) -> None: ... + def getpeername(self) -> _RetAddress: ... + def getsockname(self) -> _RetAddress: ... + def getsockbyname(self) -> NoReturn: ... # This method doesn't exist on socket, yet is passed through? + def settimeout(self, value: float | None) -> None: ... + def gettimeout(self) -> float | None: ... + def setblocking(self, flag: bool) -> None: ... + if sys.version_info < (3, 11): def accept(self) -> tuple[socket.socket, _RetAddress]: ... def connect(self, address: _Address | bytes) -> None: ... def connect_ex(self, address: _Address | bytes) -> int: ... @@ -42,6 +47,7 @@ if sys.version_info >= (3, 8): def ioctl(self, control: int, option: int | tuple[int, int, int] | bool) -> None: ... else: def ioctl(self, control: int, option: int | tuple[int, int, int] | bool) -> NoReturn: ... + def listen(self, __backlog: int = ...) -> None: ... def makefile(self) -> BinaryIO: ... def sendfile(self, file: BinaryIO, offset: int = ..., count: int | None = ...) -> int: ... @@ -55,6 +61,7 @@ if sys.version_info >= (3, 8): def sendmsg_afalg( self, msg: Iterable[bytes] = ..., *, op: int, iv: Any = ..., assoclen: int = ..., flags: int = ... ) -> NoReturn: ... + def sendmsg( self, __buffers: Iterable[bytes], __ancdata: Iterable[_CMSG] = ..., __flags: int = ..., __address: _Address = ... ) -> int: ... @@ -69,6 +76,7 @@ if sys.version_info >= (3, 8): def share(self, process_id: int) -> bytes: ... else: def share(self, process_id: int) -> NoReturn: ... + def recv_into(self, buffer: _WriteBuffer, nbytes: int = ..., flags: int = ...) -> int: ... def recvfrom_into(self, buffer: _WriteBuffer, nbytes: int = ..., flags: int = ...) -> tuple[int, _RetAddress]: ... def recvmsg_into( @@ -77,9 +85,6 @@ if sys.version_info >= (3, 8): def recvmsg(self, __bufsize: int, __ancbufsize: int = ..., __flags: int = ...) -> tuple[bytes, list[_CMSG], int, Any]: ... def recvfrom(self, bufsize: int, flags: int = ...) -> tuple[bytes, _RetAddress]: ... def recv(self, bufsize: int, flags: int = ...) -> bytes: ... - def settimeout(self, value: float | None) -> None: ... - def gettimeout(self) -> float | None: ... - def setblocking(self, flag: bool) -> None: ... def __enter__(self) -> socket.socket: ... def __exit__( self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None diff --git a/mypy/typeshed/stdlib/asyncio/unix_events.pyi b/mypy/typeshed/stdlib/asyncio/unix_events.pyi index de3b320a4e242..78d87dc4e9e94 100644 --- a/mypy/typeshed/stdlib/asyncio/unix_events.pyi +++ b/mypy/typeshed/stdlib/asyncio/unix_events.pyi @@ -1,33 +1,84 @@ import sys import types from _typeshed import Self +from abc import ABCMeta, abstractmethod from socket import socket -from typing import Any, Callable, Type +from typing import Any, Callable +from typing_extensions import Literal from .base_events import Server from .events import AbstractEventLoop, BaseDefaultEventLoopPolicy, _ProtocolFactory, _SSLContext from .selector_events import BaseSelectorEventLoop # This is also technically not available on Win, -# but other parts of typeshed need this defintion. +# but other parts of typeshed need this definition. # So, it is special cased. class AbstractChildWatcher: + @abstractmethod def add_child_handler(self, pid: int, callback: Callable[..., Any], *args: Any) -> None: ... + @abstractmethod def remove_child_handler(self, pid: int) -> bool: ... + @abstractmethod def attach_loop(self, loop: AbstractEventLoop | None) -> None: ... + @abstractmethod def close(self) -> None: ... + @abstractmethod def __enter__(self: Self) -> Self: ... - def __exit__(self, typ: Type[BaseException] | None, exc: BaseException | None, tb: types.TracebackType | None) -> None: ... + @abstractmethod + def __exit__(self, typ: type[BaseException] | None, exc: BaseException | None, tb: types.TracebackType | None) -> None: ... if sys.version_info >= (3, 8): + @abstractmethod def is_active(self) -> bool: ... if sys.platform != "win32": - class BaseChildWatcher(AbstractChildWatcher): + if sys.version_info >= (3, 9): + __all__ = ( + "SelectorEventLoop", + "AbstractChildWatcher", + "SafeChildWatcher", + "FastChildWatcher", + "PidfdChildWatcher", + "MultiLoopChildWatcher", + "ThreadedChildWatcher", + "DefaultEventLoopPolicy", + ) + elif sys.version_info >= (3, 8): + __all__ = ( + "SelectorEventLoop", + "AbstractChildWatcher", + "SafeChildWatcher", + "FastChildWatcher", + "MultiLoopChildWatcher", + "ThreadedChildWatcher", + "DefaultEventLoopPolicy", + ) + elif sys.version_info >= (3, 7): + __all__ = ("SelectorEventLoop", "AbstractChildWatcher", "SafeChildWatcher", "FastChildWatcher", "DefaultEventLoopPolicy") + else: + __all__ = ["SelectorEventLoop", "AbstractChildWatcher", "SafeChildWatcher", "FastChildWatcher", "DefaultEventLoopPolicy"] + + # Doesn't actually have ABCMeta metaclass at runtime, but mypy complains if we don't have it in the stub. + # See discussion in #7412 + class BaseChildWatcher(AbstractChildWatcher, metaclass=ABCMeta): def __init__(self) -> None: ... + def close(self) -> None: ... + if sys.version_info >= (3, 8): + def is_active(self) -> bool: ... + + def attach_loop(self, loop: AbstractEventLoop | None) -> None: ... + class SafeChildWatcher(BaseChildWatcher): def __enter__(self: Self) -> Self: ... + def __exit__(self, a: type[BaseException] | None, b: BaseException | None, c: types.TracebackType | None) -> None: ... + def add_child_handler(self, pid: int, callback: Callable[..., Any], *args: Any) -> None: ... + def remove_child_handler(self, pid: int) -> bool: ... + class FastChildWatcher(BaseChildWatcher): def __enter__(self: Self) -> Self: ... + def __exit__(self, a: type[BaseException] | None, b: BaseException | None, c: types.TracebackType | None) -> None: ... + def add_child_handler(self, pid: int, callback: Callable[..., Any], *args: Any) -> None: ... + def remove_child_handler(self, pid: int) -> bool: ... + class _UnixSelectorEventLoop(BaseSelectorEventLoop): if sys.version_info < (3, 7): async def create_unix_server( @@ -39,6 +90,7 @@ if sys.platform != "win32": backlog: int = ..., ssl: _SSLContext = ..., ) -> Server: ... + class _UnixDefaultEventLoopPolicy(BaseDefaultEventLoopPolicy): def get_child_watcher(self) -> AbstractChildWatcher: ... def set_child_watcher(self, watcher: AbstractChildWatcher | None) -> None: ... @@ -49,12 +101,46 @@ if sys.platform != "win32": if sys.version_info >= (3, 8): from typing import Protocol + class _Warn(Protocol): def __call__( - self, message: str, category: Type[Warning] | None = ..., stacklevel: int = ..., source: Any | None = ... + self, message: str, category: type[Warning] | None = ..., stacklevel: int = ..., source: Any | None = ... ) -> None: ... + class MultiLoopChildWatcher(AbstractChildWatcher): + def __init__(self) -> None: ... + def is_active(self) -> bool: ... + def close(self) -> None: ... def __enter__(self: Self) -> Self: ... + def __exit__( + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: types.TracebackType | None + ) -> None: ... + def add_child_handler(self, pid: int, callback: Callable[..., Any], *args: Any) -> None: ... + def remove_child_handler(self, pid: int) -> bool: ... + def attach_loop(self, loop: AbstractEventLoop | None) -> None: ... + class ThreadedChildWatcher(AbstractChildWatcher): + def __init__(self) -> None: ... + def is_active(self) -> Literal[True]: ... + def close(self) -> None: ... def __enter__(self: Self) -> Self: ... + def __exit__( + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: types.TracebackType | None + ) -> None: ... def __del__(self, _warn: _Warn = ...) -> None: ... + def add_child_handler(self, pid: int, callback: Callable[..., Any], *args: Any) -> None: ... + def remove_child_handler(self, pid: int) -> bool: ... + def attach_loop(self, loop: AbstractEventLoop | None) -> None: ... + + if sys.version_info >= (3, 9): + class PidfdChildWatcher(AbstractChildWatcher): + def __init__(self) -> None: ... + def __enter__(self: Self) -> Self: ... + def __exit__( + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: types.TracebackType | None + ) -> None: ... + def is_active(self) -> bool: ... + def close(self) -> None: ... + def attach_loop(self, loop: AbstractEventLoop | None) -> None: ... + def add_child_handler(self, pid: int, callback: Callable[..., Any], *args: Any) -> None: ... + def remove_child_handler(self, pid: int) -> bool: ... diff --git a/mypy/typeshed/stdlib/asyncio/windows_events.pyi b/mypy/typeshed/stdlib/asyncio/windows_events.pyi index d86b6af91a294..1e4d286386c87 100644 --- a/mypy/typeshed/stdlib/asyncio/windows_events.pyi +++ b/mypy/typeshed/stdlib/asyncio/windows_events.pyi @@ -1,7 +1,7 @@ import socket import sys from _typeshed import WriteableBuffer -from typing import IO, Any, Callable, ClassVar, NoReturn, Type +from typing import IO, Any, Callable, ClassVar, NoReturn from typing_extensions import Literal from . import events, futures, proactor_events, selector_events, streams, windows_utils @@ -25,12 +25,15 @@ if sys.platform == "win32": ERROR_CONNECTION_ABORTED: Literal[1236] CONNECT_PIPE_INIT_DELAY: float CONNECT_PIPE_MAX_DELAY: float + class PipeServer: def __init__(self, address: str) -> None: ... def __del__(self) -> None: ... def closed(self) -> bool: ... def close(self) -> None: ... + class _WindowsSelectorEventLoop(selector_events.BaseSelectorEventLoop): ... + class ProactorEventLoop(proactor_events.BaseProactorEventLoop): def __init__(self, proactor: IocpProactor | None = ...) -> None: ... async def create_pipe_connection( @@ -39,20 +42,22 @@ if sys.platform == "win32": async def start_serving_pipe( self, protocol_factory: Callable[[], streams.StreamReaderProtocol], address: str ) -> list[PipeServer]: ... + class IocpProactor: def __init__(self, concurrency: int = ...) -> None: ... - def __repr__(self) -> str: ... def __del__(self) -> None: ... def set_loop(self, loop: events.AbstractEventLoop) -> None: ... def select(self, timeout: int | None = ...) -> list[futures.Future[Any]]: ... def recv(self, conn: socket.socket, nbytes: int, flags: int = ...) -> futures.Future[bytes]: ... if sys.version_info >= (3, 7): def recv_into(self, conn: socket.socket, buf: WriteableBuffer, flags: int = ...) -> futures.Future[Any]: ... + def send(self, conn: socket.socket, buf: WriteableBuffer, flags: int = ...) -> futures.Future[Any]: ... def accept(self, listener: socket.socket) -> futures.Future[Any]: ... def connect(self, conn: socket.socket, address: bytes) -> futures.Future[Any]: ... if sys.version_info >= (3, 7): def sendfile(self, sock: socket.socket, file: IO[bytes], offset: int, count: int) -> futures.Future[Any]: ... + def accept_pipe(self, pipe: socket.socket) -> futures.Future[Any]: ... async def connect_pipe(self, address: bytes) -> windows_utils.PipeHandle: ... def wait_for_handle(self, handle: windows_utils.PipeHandle, timeout: int | None = ...) -> bool: ... @@ -61,17 +66,18 @@ if sys.platform == "win32": if sys.version_info >= (3, 7): class WindowsSelectorEventLoopPolicy(events.BaseDefaultEventLoopPolicy): - _loop_factory: ClassVar[Type[SelectorEventLoop]] + _loop_factory: ClassVar[type[SelectorEventLoop]] def get_child_watcher(self) -> NoReturn: ... def set_child_watcher(self, watcher: Any) -> NoReturn: ... + class WindowsProactorEventLoopPolicy(events.BaseDefaultEventLoopPolicy): - _loop_factory: ClassVar[Type[ProactorEventLoop]] + _loop_factory: ClassVar[type[ProactorEventLoop]] def get_child_watcher(self) -> NoReturn: ... def set_child_watcher(self, watcher: Any) -> NoReturn: ... DefaultEventLoopPolicy = WindowsSelectorEventLoopPolicy else: class _WindowsDefaultEventLoopPolicy(events.BaseDefaultEventLoopPolicy): - _loop_factory: ClassVar[Type[SelectorEventLoop]] + _loop_factory: ClassVar[type[SelectorEventLoop]] def get_child_watcher(self) -> NoReturn: ... def set_child_watcher(self, watcher: Any) -> NoReturn: ... DefaultEventLoopPolicy = _WindowsDefaultEventLoopPolicy diff --git a/mypy/typeshed/stdlib/asyncio/windows_utils.pyi b/mypy/typeshed/stdlib/asyncio/windows_utils.pyi index c387fc40f2118..1156f905659e8 100644 --- a/mypy/typeshed/stdlib/asyncio/windows_utils.pyi +++ b/mypy/typeshed/stdlib/asyncio/windows_utils.pyi @@ -2,28 +2,62 @@ import subprocess import sys from _typeshed import Self from types import TracebackType -from typing import Callable, Protocol, Type +from typing import Any, AnyStr, Callable, Protocol from typing_extensions import Literal if sys.platform == "win32": + if sys.version_info >= (3, 7): + __all__ = ("pipe", "Popen", "PIPE", "PipeHandle") + else: + __all__ = ["socketpair", "pipe", "Popen", "PIPE", "PipeHandle"] + import socket + + socketpair = socket.socketpair + class _WarnFunction(Protocol): def __call__( - self, message: str, category: Type[Warning] = ..., stacklevel: int = ..., source: PipeHandle = ... + self, message: str, category: type[Warning] = ..., stacklevel: int = ..., source: PipeHandle = ... ) -> None: ... BUFSIZE: Literal[8192] PIPE = subprocess.PIPE STDOUT = subprocess.STDOUT def pipe(*, duplex: bool = ..., overlapped: tuple[bool, bool] = ..., bufsize: int = ...) -> tuple[int, int]: ... + class PipeHandle: def __init__(self, handle: int) -> None: ... - def __repr__(self) -> str: ... if sys.version_info >= (3, 8): def __del__(self, _warn: _WarnFunction = ...) -> None: ... else: def __del__(self) -> None: ... + def __enter__(self: Self) -> Self: ... - def __exit__(self, t: type | None, v: BaseException | None, tb: TracebackType | None) -> None: ... + def __exit__(self, t: type[BaseException] | None, v: BaseException | None, tb: TracebackType | None) -> None: ... @property def handle(self) -> int: ... def fileno(self) -> int: ... def close(self, *, CloseHandle: Callable[[int], None] = ...) -> None: ... + + class Popen(subprocess.Popen[AnyStr]): + stdin: PipeHandle | None # type: ignore[assignment] + stdout: PipeHandle | None # type: ignore[assignment] + stderr: PipeHandle | None # type: ignore[assignment] + # For simplicity we omit the full overloaded __new__ signature of + # subprocess.Popen. The arguments are mostly the same, but + # subprocess.Popen takes other positional-or-keyword arguments before + # stdin. + def __new__( + cls: type[Self], + args: subprocess._CMD, + stdin: subprocess._FILE | None = ..., + stdout: subprocess._FILE | None = ..., + stderr: subprocess._FILE | None = ..., + **kwds: Any, + ) -> Self: ... + def __init__( + self, + args: subprocess._CMD, + stdin: subprocess._FILE | None = ..., + stdout: subprocess._FILE | None = ..., + stderr: subprocess._FILE | None = ..., + **kwds: Any, + ) -> None: ... diff --git a/mypy/typeshed/stdlib/asyncore.pyi b/mypy/typeshed/stdlib/asyncore.pyi index 123da2677a7e2..8f77e0e45c44f 100644 --- a/mypy/typeshed/stdlib/asyncore.pyi +++ b/mypy/typeshed/stdlib/asyncore.pyi @@ -85,6 +85,7 @@ if sys.platform != "win32": def write(self, data: bytes, flags: int = ...) -> int: ... def close(self) -> None: ... def fileno(self) -> int: ... + class file_dispatcher(dispatcher): def __init__(self, fd: FileDescriptorLike, map: _maptype | None = ...) -> None: ... def set_file(self, fd: int) -> None: ... diff --git a/mypy/typeshed/stdlib/base64.pyi b/mypy/typeshed/stdlib/base64.pyi index 8610eea17b52a..70fe642923280 100644 --- a/mypy/typeshed/stdlib/base64.pyi +++ b/mypy/typeshed/stdlib/base64.pyi @@ -1,6 +1,51 @@ import sys from typing import IO +if sys.version_info >= (3, 10): + __all__ = [ + "encode", + "decode", + "encodebytes", + "decodebytes", + "b64encode", + "b64decode", + "b32encode", + "b32decode", + "b32hexencode", + "b32hexdecode", + "b16encode", + "b16decode", + "b85encode", + "b85decode", + "a85encode", + "a85decode", + "standard_b64encode", + "standard_b64decode", + "urlsafe_b64encode", + "urlsafe_b64decode", + ] +else: + __all__ = [ + "encode", + "decode", + "encodebytes", + "decodebytes", + "b64encode", + "b64decode", + "b32encode", + "b32decode", + "b16encode", + "b16decode", + "b85encode", + "b85decode", + "a85encode", + "a85decode", + "standard_b64encode", + "standard_b64decode", + "urlsafe_b64encode", + "urlsafe_b64decode", + ] + def b64encode(s: bytes, altchars: bytes | None = ...) -> bytes: ... def b64decode(s: str | bytes, altchars: bytes | None = ..., validate: bool = ...) -> bytes: ... def standard_b64encode(s: bytes) -> bytes: ... diff --git a/mypy/typeshed/stdlib/bdb.pyi b/mypy/typeshed/stdlib/bdb.pyi index 3f6b6d3d8b7b7..8f61433e0cb88 100644 --- a/mypy/typeshed/stdlib/bdb.pyi +++ b/mypy/typeshed/stdlib/bdb.pyi @@ -1,11 +1,15 @@ from types import CodeType, FrameType, TracebackType -from typing import IO, Any, Callable, Iterable, Mapping, SupportsInt, Type, TypeVar +from typing import IO, Any, Callable, Iterable, Mapping, SupportsInt, TypeVar +from typing_extensions import Literal, ParamSpec + +__all__ = ["BdbQuit", "Bdb", "Breakpoint"] _T = TypeVar("_T") +_P = ParamSpec("_P") _TraceDispatch = Callable[[FrameType, str, Any], Any] # TODO: Recursive type -_ExcInfo = tuple[Type[BaseException], BaseException, FrameType] +_ExcInfo = tuple[type[BaseException], BaseException, FrameType] -GENERATOR_AND_COROUTINE_FLAGS: int +GENERATOR_AND_COROUTINE_FLAGS: Literal[672] class BdbQuit(Exception): ... @@ -61,7 +65,7 @@ class Bdb: def run(self, cmd: str | CodeType, globals: dict[str, Any] | None = ..., locals: Mapping[str, Any] | None = ...) -> None: ... def runeval(self, expr: str, globals: dict[str, Any] | None = ..., locals: Mapping[str, Any] | None = ...) -> None: ... def runctx(self, cmd: str | CodeType, globals: dict[str, Any] | None, locals: Mapping[str, Any] | None) -> None: ... - def runcall(self, __func: Callable[..., _T], *args: Any, **kwds: Any) -> _T | None: ... + def runcall(self, __func: Callable[_P, _T], *args: _P.args, **kwds: _P.kwargs) -> _T | None: ... class Breakpoint: @@ -87,7 +91,6 @@ class Breakpoint: def disable(self) -> None: ... def bpprint(self, out: IO[str] | None = ...) -> None: ... def bpformat(self) -> str: ... - def __str__(self) -> str: ... def checkfuncname(b: Breakpoint, frame: FrameType) -> bool: ... def effective(file: str, line: int, frame: FrameType) -> tuple[Breakpoint, bool] | tuple[None, None]: ... diff --git a/mypy/typeshed/stdlib/binhex.pyi b/mypy/typeshed/stdlib/binhex.pyi index 4e295b8ed9031..db002503c75fc 100644 --- a/mypy/typeshed/stdlib/binhex.pyi +++ b/mypy/typeshed/stdlib/binhex.pyi @@ -1,10 +1,13 @@ -from typing import IO, Any, Union +from typing import IO, Any +from typing_extensions import Literal + +__all__ = ["binhex", "hexbin", "Error"] class Error(Exception): ... -REASONABLY_LARGE: int -LINELEN: int -RUNCHAR: bytes +REASONABLY_LARGE: Literal[32768] +LINELEN: Literal[64] +RUNCHAR: Literal[b"\x90"] class FInfo: def __init__(self) -> None: ... @@ -13,7 +16,7 @@ class FInfo: Flags: int _FileInfoTuple = tuple[str, FInfo, int, int] -_FileHandleUnion = Union[str, IO[bytes]] +_FileHandleUnion = str | IO[bytes] def getfileinfo(name: str) -> _FileInfoTuple: ... diff --git a/mypy/typeshed/stdlib/builtins.pyi b/mypy/typeshed/stdlib/builtins.pyi index b38d645ef9fc4..ce2042bcac631 100644 --- a/mypy/typeshed/stdlib/builtins.pyi +++ b/mypy/typeshed/stdlib/builtins.pyi @@ -22,15 +22,17 @@ from _typeshed import ( SupportsTrunc, SupportsWrite, ) +from collections.abc import Callable from io import BufferedRandom, BufferedReader, BufferedWriter, FileIO, TextIOWrapper from types import CodeType, TracebackType, _Cell from typing import ( IO, AbstractSet, Any, + Awaitable, BinaryIO, ByteString, - Callable, + ClassVar, Generic, Iterable, Iterator, @@ -49,7 +51,6 @@ from typing import ( SupportsFloat, SupportsInt, SupportsRound, - Type, TypeVar, Union, overload, @@ -62,6 +63,7 @@ if sys.version_info >= (3, 9): _T = TypeVar("_T") _T_co = TypeVar("_T_co", covariant=True) _T_contra = TypeVar("_T_contra", contravariant=True) +_R_co = TypeVar("_R_co", covariant=True) _KT = TypeVar("_KT") _VT = TypeVar("_VT") _S = TypeVar("_S") @@ -70,11 +72,10 @@ _T2 = TypeVar("_T2") _T3 = TypeVar("_T3") _T4 = TypeVar("_T4") _T5 = TypeVar("_T5") -_TT = TypeVar("_TT", bound="type") -_TBE = TypeVar("_TBE", bound="BaseException") -_R = TypeVar("_R") # Return-type TypeVar _SupportsNextT = TypeVar("_SupportsNextT", bound=SupportsNext[Any], covariant=True) _SupportsAnextT = TypeVar("_SupportsAnextT", bound=SupportsAnext[Any], covariant=True) +_AwaitableT = TypeVar("_AwaitableT", bound=Awaitable[Any]) +_AwaitableT_co = TypeVar("_AwaitableT_co", bound=Awaitable[Any], covariant=True) class _SupportsIter(Protocol[_T_co]): def __iter__(self) -> _T_co: ... @@ -88,21 +89,23 @@ class object: __module__: str __annotations__: dict[str, Any] @property - def __class__(self: _T) -> Type[_T]: ... + def __class__(self: Self) -> type[Self]: ... # Ignore errors about type mismatch between property getter and setter @__class__.setter - def __class__(self, __type: Type[object]) -> None: ... # type: ignore # noqa: F811 + def __class__(self, __type: type[object]) -> None: ... # type: ignore # noqa: F811 def __init__(self) -> None: ... - def __new__(cls: Type[_T]) -> _T: ... + def __new__(cls: type[Self]) -> Self: ... + # N.B. `object.__setattr__` and `object.__delattr__` are heavily special-cased by type checkers. + # Overriding them in subclasses has different semantics, even if the override has an identical signature. def __setattr__(self, __name: str, __value: Any) -> None: ... + def __delattr__(self, __name: str) -> None: ... def __eq__(self, __o: object) -> bool: ... def __ne__(self, __o: object) -> bool: ... - def __str__(self) -> str: ... - def __repr__(self) -> str: ... + def __str__(self) -> str: ... # noqa: Y029 + def __repr__(self) -> str: ... # noqa: Y029 def __hash__(self) -> int: ... def __format__(self, __format_spec: str) -> str: ... def __getattribute__(self, __name: str) -> Any: ... - def __delattr__(self, __name: str) -> None: ... def __sizeof__(self) -> int: ... # return type of pickle methods is rather hard to express in the current type system # see #6661 and https://docs.python.org/3/library/pickle.html#object.__reduce__ @@ -111,46 +114,58 @@ class object: def __reduce_ex__(self, __protocol: SupportsIndex) -> str | tuple[Any, ...]: ... else: def __reduce_ex__(self, __protocol: int) -> str | tuple[Any, ...]: ... + def __dir__(self) -> Iterable[str]: ... def __init_subclass__(cls) -> None: ... -class staticmethod(Generic[_R]): # Special, only valid as a decorator. - __func__: Callable[..., _R] - __isabstractmethod__: bool - def __init__(self: staticmethod[_R], __f: Callable[..., _R]) -> None: ... - def __new__(cls: Type[_T], *args: Any, **kwargs: Any) -> _T: ... - def __get__(self, __obj: _T, __type: Type[_T] | None = ...) -> Callable[..., _R]: ... +class staticmethod(Generic[_R_co]): + @property + def __func__(self) -> Callable[..., _R_co]: ... + @property + def __isabstractmethod__(self) -> bool: ... + def __init__(self: staticmethod[_R_co], __f: Callable[..., _R_co]) -> None: ... + def __get__(self, __obj: _T, __type: type[_T] | None = ...) -> Callable[..., _R_co]: ... if sys.version_info >= (3, 10): __name__: str __qualname__: str - __wrapped__: Callable[..., _R] - def __call__(self, *args: Any, **kwargs: Any) -> _R: ... + __wrapped__: Callable[..., _R_co] + def __call__(self, *args: Any, **kwargs: Any) -> _R_co: ... -class classmethod(Generic[_R]): # Special, only valid as a decorator. - __func__: Callable[..., _R] - __isabstractmethod__: bool - def __init__(self: classmethod[_R], __f: Callable[..., _R]) -> None: ... - def __new__(cls: Type[_T], *args: Any, **kwargs: Any) -> _T: ... - def __get__(self, __obj: _T, __type: Type[_T] | None = ...) -> Callable[..., _R]: ... +class classmethod(Generic[_R_co]): + @property + def __func__(self) -> Callable[..., _R_co]: ... + @property + def __isabstractmethod__(self) -> bool: ... + def __init__(self: classmethod[_R_co], __f: Callable[..., _R_co]) -> None: ... + def __get__(self, __obj: _T, __type: type[_T] | None = ...) -> Callable[..., _R_co]: ... if sys.version_info >= (3, 10): __name__: str __qualname__: str - __wrapped__: Callable[..., _R] + __wrapped__: Callable[..., _R_co] class type: - __base__: type + @property + def __base__(self) -> type: ... __bases__: tuple[type, ...] - __basicsize__: int - __dict__: dict[str, Any] - __dictoffset__: int - __flags__: int - __itemsize__: int + @property + def __basicsize__(self) -> int: ... + @property + def __dict__(self) -> types.MappingProxyType[str, Any]: ... # type: ignore[override] + @property + def __dictoffset__(self) -> int: ... + @property + def __flags__(self) -> int: ... + @property + def __itemsize__(self) -> int: ... __module__: str - __mro__: tuple[type, ...] + @property + def __mro__(self) -> tuple[type, ...]: ... __name__: str __qualname__: str - __text_signature__: str | None - __weakrefoffset__: int + @property + def __text_signature__(self) -> str | None: ... + @property + def __weakrefoffset__(self) -> int: ... @overload def __init__(self, __o: object) -> None: ... @overload @@ -158,9 +173,9 @@ class type: @overload def __new__(cls, __o: object) -> type: ... @overload - def __new__(cls: Type[_TT], __name: str, __bases: tuple[type, ...], __namespace: dict[str, Any], **kwds: Any) -> _TT: ... + def __new__(cls: type[Self], __name: str, __bases: tuple[type, ...], __namespace: dict[str, Any], **kwds: Any) -> Self: ... def __call__(self, *args: Any, **kwds: Any) -> Any: ... - def __subclasses__(self: _TT) -> list[_TT]: ... + def __subclasses__(self: Self) -> list[Self]: ... # Note: the documentation doesn't specify what the return type is, the standard # implementation seems to be returning a list. def mro(self) -> list[type]: ... @@ -185,11 +200,12 @@ _NegativeInteger = Literal[-1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -1 class int: @overload - def __new__(cls: Type[_T], __x: str | bytes | SupportsInt | SupportsIndex | SupportsTrunc = ...) -> _T: ... + def __new__(cls: type[Self], __x: str | bytes | SupportsInt | SupportsIndex | SupportsTrunc = ...) -> Self: ... @overload - def __new__(cls: Type[_T], __x: str | bytes | bytearray, base: SupportsIndex) -> _T: ... + def __new__(cls: type[Self], __x: str | bytes | bytearray, base: SupportsIndex) -> Self: ... if sys.version_info >= (3, 8): def as_integer_ratio(self) -> tuple[int, Literal[1]]: ... + @property def real(self) -> int: ... @property @@ -202,11 +218,16 @@ class int: def bit_length(self) -> int: ... if sys.version_info >= (3, 10): def bit_count(self) -> int: ... + def to_bytes(self, length: SupportsIndex, byteorder: Literal["little", "big"], *, signed: bool = ...) -> bytes: ... @classmethod def from_bytes( - cls, bytes: Iterable[SupportsIndex] | SupportsBytes, byteorder: Literal["little", "big"], *, signed: bool = ... - ) -> int: ... # TODO buffer object argument + cls: type[Self], + bytes: Iterable[SupportsIndex] | SupportsBytes, # TODO buffer object argument + byteorder: Literal["little", "big"], + *, + signed: bool = ..., + ) -> Self: ... def __add__(self, __x: int) -> int: ... def __sub__(self, __x: int) -> int: ... def __mul__(self, __x: int) -> int: ... @@ -226,6 +247,8 @@ class int: @overload def __pow__(self, __x: int, __modulo: int) -> int: ... @overload + def __pow__(self, __x: Literal[0], __modulo: None = ...) -> Literal[1]: ... + @overload def __pow__(self, __x: _PositiveInteger, __modulo: None = ...) -> int: ... @overload def __pow__(self, __x: _NegativeInteger, __modulo: None = ...) -> float: ... @@ -258,7 +281,6 @@ class int: def __le__(self, __x: int) -> bool: ... def __gt__(self, __x: int) -> bool: ... def __ge__(self, __x: int) -> bool: ... - def __str__(self) -> str: ... def __float__(self) -> float: ... def __int__(self) -> int: ... def __abs__(self) -> int: ... @@ -267,12 +289,12 @@ class int: def __index__(self) -> int: ... class float: - def __new__(cls: Type[_T], x: SupportsFloat | SupportsIndex | str | bytes | bytearray = ...) -> _T: ... + def __new__(cls: type[Self], x: SupportsFloat | SupportsIndex | str | bytes | bytearray = ...) -> Self: ... def as_integer_ratio(self) -> tuple[int, int]: ... def hex(self) -> str: ... def is_integer(self) -> bool: ... @classmethod - def fromhex(cls, __s: str) -> float: ... + def fromhex(cls: type[Self], __s: str) -> Self: ... @property def real(self) -> float: ... @property @@ -298,12 +320,14 @@ class float: def __rtruediv__(self, __x: float) -> float: ... def __rmod__(self, __x: float) -> float: ... def __rdivmod__(self, __x: float) -> tuple[float, float]: ... - def __rpow__(self, __x: float, __mod: None = ...) -> float: ... + # Returns complex if the argument is negative. + def __rpow__(self, __x: float, __mod: None = ...) -> Any: ... def __getnewargs__(self) -> tuple[float]: ... def __trunc__(self) -> int: ... if sys.version_info >= (3, 9): def __ceil__(self) -> int: ... def __floor__(self) -> int: ... + @overload def __round__(self, __ndigits: None = ...) -> int: ... @overload @@ -316,7 +340,6 @@ class float: def __ge__(self, __x: float) -> bool: ... def __neg__(self) -> float: ... def __pos__(self) -> float: ... - def __str__(self) -> str: ... def __int__(self) -> int: ... def __float__(self) -> float: ... def __abs__(self) -> float: ... @@ -325,9 +348,9 @@ class float: class complex: @overload - def __new__(cls: Type[_T], real: float = ..., imag: float = ...) -> _T: ... + def __new__(cls: type[Self], real: float = ..., imag: float = ...) -> Self: ... @overload - def __new__(cls: Type[_T], real: str | SupportsComplex | SupportsIndex | complex) -> _T: ... + def __new__(cls: type[Self], real: str | SupportsComplex | SupportsIndex | complex) -> Self: ... @property def real(self) -> float: ... @property @@ -336,7 +359,7 @@ class complex: def __add__(self, __x: complex) -> complex: ... def __sub__(self, __x: complex) -> complex: ... def __mul__(self, __x: complex) -> complex: ... - def __pow__(self, __x: complex, mod: None = ...) -> complex: ... + def __pow__(self, __x: complex, __mod: None = ...) -> complex: ... def __truediv__(self, __x: complex) -> complex: ... def __radd__(self, __x: complex) -> complex: ... def __rsub__(self, __x: complex) -> complex: ... @@ -347,7 +370,6 @@ class complex: def __ne__(self, __x: object) -> bool: ... def __neg__(self) -> complex: ... def __pos__(self) -> complex: ... - def __str__(self) -> str: ... def __abs__(self) -> float: ... def __hash__(self) -> int: ... def __bool__(self) -> bool: ... @@ -359,9 +381,9 @@ class _FormatMapMapping(Protocol): class str(Sequence[str]): @overload - def __new__(cls: Type[_T], object: object = ...) -> _T: ... + def __new__(cls: type[Self], object: object = ...) -> Self: ... @overload - def __new__(cls: Type[_T], o: bytes, encoding: str = ..., errors: str = ...) -> _T: ... + def __new__(cls: type[Self], object: bytes, encoding: str = ..., errors: str = ...) -> Self: ... def capitalize(self) -> str: ... def casefold(self) -> str: ... def center(self, __width: SupportsIndex, __fillchar: str = ...) -> str: ... @@ -374,6 +396,7 @@ class str(Sequence[str]): def expandtabs(self, tabsize: SupportsIndex = ...) -> str: ... else: def expandtabs(self, tabsize: int = ...) -> str: ... + def find(self, __sub: str, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...) -> int: ... def format(self, *args: object, **kwargs: object) -> str: ... def format_map(self, map: _FormatMapMapping) -> str: ... @@ -382,6 +405,7 @@ class str(Sequence[str]): def isalpha(self) -> bool: ... if sys.version_info >= (3, 7): def isascii(self) -> bool: ... + def isdecimal(self) -> bool: ... def isdigit(self) -> bool: ... def isidentifier(self) -> bool: ... @@ -400,6 +424,7 @@ class str(Sequence[str]): if sys.version_info >= (3, 9): def removeprefix(self, __prefix: str) -> str: ... def removesuffix(self, __suffix: str) -> str: ... + def rfind(self, __sub: str, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...) -> int: ... def rindex(self, __sub: str, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...) -> int: ... def rjust(self, __width: SupportsIndex, __fillchar: str = ...) -> str: ... @@ -438,22 +463,20 @@ class str(Sequence[str]): def __mod__(self, __x: Any) -> str: ... def __mul__(self, __n: SupportsIndex) -> str: ... def __ne__(self, __x: object) -> bool: ... - def __repr__(self) -> str: ... - def __rmul__(self, n: SupportsIndex) -> str: ... - def __str__(self) -> str: ... + def __rmul__(self, __n: SupportsIndex) -> str: ... def __getnewargs__(self) -> tuple[str]: ... class bytes(ByteString): @overload - def __new__(cls: Type[_T], __ints: Iterable[SupportsIndex]) -> _T: ... + def __new__(cls: type[Self], __ints: Iterable[SupportsIndex]) -> Self: ... @overload - def __new__(cls: Type[_T], __string: str, encoding: str, errors: str = ...) -> _T: ... + def __new__(cls: type[Self], __string: str, encoding: str, errors: str = ...) -> Self: ... @overload - def __new__(cls: Type[_T], __length: SupportsIndex) -> _T: ... + def __new__(cls: type[Self], __length: SupportsIndex) -> Self: ... @overload - def __new__(cls: Type[_T]) -> _T: ... + def __new__(cls: type[Self]) -> Self: ... @overload - def __new__(cls: Type[_T], __o: SupportsBytes) -> _T: ... + def __new__(cls: type[Self], __o: SupportsBytes) -> Self: ... def capitalize(self) -> bytes: ... def center(self, __width: SupportsIndex, __fillchar: bytes = ...) -> bytes: ... def count( @@ -467,6 +490,7 @@ class bytes(ByteString): def expandtabs(self, tabsize: SupportsIndex = ...) -> bytes: ... else: def expandtabs(self, tabsize: int = ...) -> bytes: ... + def find( self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> int: ... @@ -474,6 +498,7 @@ class bytes(ByteString): def hex(self, sep: str | bytes = ..., bytes_per_sep: SupportsIndex = ...) -> str: ... else: def hex(self) -> str: ... + def index( self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> int: ... @@ -481,6 +506,7 @@ class bytes(ByteString): def isalpha(self) -> bool: ... if sys.version_info >= (3, 7): def isascii(self) -> bool: ... + def isdigit(self) -> bool: ... def islower(self) -> bool: ... def isspace(self) -> bool: ... @@ -495,6 +521,7 @@ class bytes(ByteString): if sys.version_info >= (3, 9): def removeprefix(self, __prefix: bytes) -> bytes: ... def removesuffix(self, __suffix: bytes) -> bytes: ... + def rfind( self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> int: ... @@ -517,13 +544,11 @@ class bytes(ByteString): def upper(self) -> bytes: ... def zfill(self, __width: SupportsIndex) -> bytes: ... @classmethod - def fromhex(cls: Type[_T], __s: str) -> _T: ... + def fromhex(cls: type[Self], __s: str) -> Self: ... @staticmethod def maketrans(__frm: bytes, __to: bytes) -> bytes: ... def __len__(self) -> int: ... def __iter__(self) -> Iterator[int]: ... - def __str__(self) -> str: ... - def __repr__(self) -> str: ... def __hash__(self) -> int: ... @overload def __getitem__(self, __i: SupportsIndex) -> int: ... @@ -569,6 +594,7 @@ class bytearray(MutableSequence[int], ByteString): def expandtabs(self, tabsize: SupportsIndex = ...) -> bytearray: ... else: def expandtabs(self, tabsize: int = ...) -> bytearray: ... + def extend(self, __iterable_of_ints: Iterable[SupportsIndex]) -> None: ... def find( self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... @@ -577,6 +603,7 @@ class bytearray(MutableSequence[int], ByteString): def hex(self, sep: str | bytes = ..., bytes_per_sep: SupportsIndex = ...) -> str: ... else: def hex(self) -> str: ... + def index( self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> int: ... @@ -585,6 +612,7 @@ class bytearray(MutableSequence[int], ByteString): def isalpha(self) -> bool: ... if sys.version_info >= (3, 7): def isascii(self) -> bool: ... + def isdigit(self) -> bool: ... def islower(self) -> bool: ... def isspace(self) -> bool: ... @@ -595,9 +623,12 @@ class bytearray(MutableSequence[int], ByteString): def lower(self) -> bytearray: ... def lstrip(self, __bytes: bytes | None = ...) -> bytearray: ... def partition(self, __sep: bytes) -> tuple[bytearray, bytearray, bytearray]: ... + def pop(self, __index: int = ...) -> int: ... + def remove(self, __value: int) -> None: ... if sys.version_info >= (3, 9): def removeprefix(self, __prefix: bytes) -> bytearray: ... def removesuffix(self, __suffix: bytes) -> bytearray: ... + def replace(self, __old: bytes, __new: bytes, __count: SupportsIndex = ...) -> bytearray: ... def rfind( self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... @@ -621,28 +652,26 @@ class bytearray(MutableSequence[int], ByteString): def upper(self) -> bytearray: ... def zfill(self, __width: SupportsIndex) -> bytearray: ... @classmethod - def fromhex(cls, __string: str) -> bytearray: ... + def fromhex(cls: type[Self], __string: str) -> Self: ... @staticmethod def maketrans(__frm: bytes, __to: bytes) -> bytes: ... def __len__(self) -> int: ... def __iter__(self) -> Iterator[int]: ... - def __str__(self) -> str: ... - def __repr__(self) -> str: ... - __hash__: None # type: ignore[assignment] + __hash__: ClassVar[None] # type: ignore[assignment] @overload def __getitem__(self, __i: SupportsIndex) -> int: ... @overload def __getitem__(self, __s: slice) -> bytearray: ... @overload - def __setitem__(self, __i: SupportsIndex, x: SupportsIndex) -> None: ... + def __setitem__(self, __i: SupportsIndex, __x: SupportsIndex) -> None: ... @overload def __setitem__(self, __s: slice, __x: Iterable[SupportsIndex] | bytes) -> None: ... def __delitem__(self, __i: SupportsIndex | slice) -> None: ... def __add__(self, __s: bytes) -> bytearray: ... - def __iadd__(self, __s: Iterable[int]) -> bytearray: ... + def __iadd__(self: Self, __s: Iterable[int]) -> Self: ... def __mul__(self, __n: SupportsIndex) -> bytearray: ... def __rmul__(self, __n: SupportsIndex) -> bytearray: ... - def __imul__(self, __n: SupportsIndex) -> bytearray: ... + def __imul__(self: Self, __n: SupportsIndex) -> Self: ... def __mod__(self, __value: Any) -> bytes: ... # Incompatible with Sequence.__contains__ def __contains__(self, __o: SupportsIndex | bytes) -> bool: ... # type: ignore[override] @@ -652,26 +681,38 @@ class bytearray(MutableSequence[int], ByteString): def __le__(self, __x: bytes) -> bool: ... def __gt__(self, __x: bytes) -> bool: ... def __ge__(self, __x: bytes) -> bool: ... + def __alloc__(self) -> int: ... @final class memoryview(Sized, Sequence[int]): - format: str - itemsize: int - shape: tuple[int, ...] | None - strides: tuple[int, ...] | None - suboffsets: tuple[int, ...] | None - readonly: bool - ndim: int - - obj: bytes | bytearray - c_contiguous: bool - f_contiguous: bool - contiguous: bool - nbytes: int + @property + def format(self) -> str: ... + @property + def itemsize(self) -> int: ... + @property + def shape(self) -> tuple[int, ...] | None: ... + @property + def strides(self) -> tuple[int, ...] | None: ... + @property + def suboffsets(self) -> tuple[int, ...] | None: ... + @property + def readonly(self) -> bool: ... + @property + def ndim(self) -> int: ... + @property + def obj(self) -> bytes | bytearray: ... + @property + def c_contiguous(self) -> bool: ... + @property + def f_contiguous(self) -> bool: ... + @property + def contiguous(self) -> bool: ... + @property + def nbytes(self) -> int: ... def __init__(self, obj: ReadableBuffer) -> None: ... def __enter__(self: Self) -> Self: ... def __exit__( - self, __exc_type: Type[BaseException] | None, __exc_val: BaseException | None, __exc_tb: TracebackType | None + self, __exc_type: type[BaseException] | None, __exc_val: BaseException | None, __exc_tb: TracebackType | None ) -> None: ... def cast(self, format: str, shape: list[int] | tuple[int, ...] = ...) -> memoryview: ... @overload @@ -689,9 +730,11 @@ class memoryview(Sized, Sequence[int]): def tobytes(self, order: Literal["C", "F", "A"] | None = ...) -> bytes: ... else: def tobytes(self) -> bytes: ... + def tolist(self) -> list[int]: ... if sys.version_info >= (3, 8): def toreadonly(self) -> memoryview: ... + def release(self) -> None: ... if sys.version_info >= (3, 8): def hex(self, sep: str | bytes = ..., bytes_per_sep: SupportsIndex = ...) -> str: ... @@ -700,7 +743,9 @@ class memoryview(Sized, Sequence[int]): @final class bool(int): - def __new__(cls: Type[_T], __o: object = ...) -> _T: ... + def __new__(cls: type[Self], __o: object = ...) -> Self: ... + # The following overloads could be represented more elegantly with a TypeVar("_B", bool, int), + # however mypy has a bug regarding TypeVar constraints (https://github.com/python/mypy/issues/11880). @overload def __and__(self, __x: bool) -> bool: ... @overload @@ -729,18 +774,21 @@ class bool(int): @final class slice: - start: Any - step: Any - stop: Any + @property + def start(self) -> Any: ... + @property + def step(self) -> Any: ... + @property + def stop(self) -> Any: ... @overload def __init__(self, __stop: Any) -> None: ... @overload def __init__(self, __start: Any, __stop: Any, __step: Any = ...) -> None: ... - __hash__: None # type: ignore[assignment] + __hash__: ClassVar[None] # type: ignore[assignment] def indices(self, __len: SupportsIndex) -> tuple[int, int, int]: ... class tuple(Sequence[_T_co], Generic[_T_co]): - def __new__(cls: Type[_T], __iterable: Iterable[_T_co] = ...) -> _T: ... + def __new__(cls: type[Self], __iterable: Iterable[_T_co] = ...) -> Self: ... def __len__(self) -> int: ... def __contains__(self, __x: object) -> bool: ... @overload @@ -767,15 +815,21 @@ class tuple(Sequence[_T_co], Generic[_T_co]): @final class function: # Make sure this class definition stays roughly in line with `types.FunctionType` - __closure__: tuple[_Cell, ...] | None + @property + def __closure__(self) -> tuple[_Cell, ...] | None: ... __code__: CodeType __defaults__: tuple[Any, ...] | None __dict__: dict[str, Any] - __globals__: dict[str, Any] + @property + def __globals__(self) -> dict[str, Any]: ... __name__: str __qualname__: str __annotations__: dict[str, Any] __kwdefaults__: dict[str, Any] + if sys.version_info >= (3, 10): + @property + def __builtins__(self) -> dict[str, Any]: ... + __module__: str # mypy uses `builtins.function.__get__` to represent methods, properties, and getset_descriptors so we type the return as Any. def __get__(self, obj: object | None, type: type | None = ...) -> Any: ... @@ -801,8 +855,7 @@ class list(MutableSequence[_T], Generic[_T]): def sort(self, *, key: Callable[[_T], SupportsRichComparison], reverse: bool = ...) -> None: ... def __len__(self) -> int: ... def __iter__(self) -> Iterator[_T]: ... - def __str__(self) -> str: ... - __hash__: None # type: ignore[assignment] + __hash__: ClassVar[None] # type: ignore[assignment] @overload def __getitem__(self, __i: SupportsIndex) -> _T: ... @overload @@ -813,10 +866,10 @@ class list(MutableSequence[_T], Generic[_T]): def __setitem__(self, __s: slice, __o: Iterable[_T]) -> None: ... def __delitem__(self, __i: SupportsIndex | slice) -> None: ... def __add__(self, __x: list[_T]) -> list[_T]: ... - def __iadd__(self: _S, __x: Iterable[_T]) -> _S: ... + def __iadd__(self: Self, __x: Iterable[_T]) -> Self: ... def __mul__(self, __n: SupportsIndex) -> list[_T]: ... def __rmul__(self, __n: SupportsIndex) -> list[_T]: ... - def __imul__(self: _S, __n: SupportsIndex) -> _S: ... + def __imul__(self: Self, __n: SupportsIndex) -> Self: ... def __contains__(self, __o: object) -> bool: ... def __reversed__(self) -> Iterator[_T]: ... def __gt__(self, __x: list[_T]) -> bool: ... @@ -840,13 +893,13 @@ class dict(MutableMapping[_KT, _VT], Generic[_KT, _VT]): # Cannot be Iterable[Sequence[_T]] or otherwise dict(["foo", "bar", "baz"]) is not an error @overload def __init__(self: dict[str, str], __iterable: Iterable[list[str]]) -> None: ... - def __new__(cls: Type[_T1], *args: Any, **kwargs: Any) -> _T1: ... + def __new__(cls: type[Self], *args: Any, **kwargs: Any) -> Self: ... def copy(self) -> dict[_KT, _VT]: ... def keys(self) -> dict_keys[_KT, _VT]: ... def values(self) -> dict_values[_KT, _VT]: ... def items(self) -> dict_items[_KT, _VT]: ... # Signature of `dict.fromkeys` should be kept identical to `fromkeys` methods of `OrderedDict`/`ChainMap`/`UserDict` in `collections` - # TODO: the true signature of `dict.fromkeys` is not expressable in the current type system. + # TODO: the true signature of `dict.fromkeys` is not expressible in the current type system. # See #3800 & https://github.com/python/typing/issues/548#issuecomment-683336963. @classmethod @overload @@ -854,20 +907,32 @@ class dict(MutableMapping[_KT, _VT], Generic[_KT, _VT]): @classmethod @overload def fromkeys(cls, __iterable: Iterable[_T], __value: _S) -> dict[_T, _S]: ... + # Positional-only in dict, but not in MutableMapping + @overload + def get(self, __key: _KT) -> _VT | None: ... + @overload + def get(self, __key: _KT, __default: _VT | _T) -> _VT | _T: ... + @overload + def pop(self, __key: _KT) -> _VT: ... + @overload + def pop(self, __key: _KT, __default: _VT | _T) -> _VT | _T: ... def __len__(self) -> int: ... def __getitem__(self, __k: _KT) -> _VT: ... - def __setitem__(self, __k: _KT, v: _VT) -> None: ... + def __setitem__(self, __k: _KT, __v: _VT) -> None: ... def __delitem__(self, __v: _KT) -> None: ... def __iter__(self) -> Iterator[_KT]: ... if sys.version_info >= (3, 8): def __reversed__(self) -> Iterator[_KT]: ... - def __str__(self) -> str: ... - __hash__: None # type: ignore[assignment] + __hash__: ClassVar[None] # type: ignore[assignment] if sys.version_info >= (3, 9): def __class_getitem__(cls, __item: Any) -> GenericAlias: ... def __or__(self, __value: Mapping[_T1, _T2]) -> dict[_KT | _T1, _VT | _T2]: ... def __ror__(self, __value: Mapping[_T1, _T2]) -> dict[_KT | _T1, _VT | _T2]: ... - def __ior__(self, __value: Mapping[_KT, _VT]) -> dict[_KT, _VT]: ... # type: ignore[misc] + # dict.__ior__ should be kept roughly in line with MutableMapping.update() + @overload # type: ignore[misc] + def __ior__(self: Self, __value: SupportsKeysAndGetItem[_KT, _VT]) -> Self: ... + @overload + def __ior__(self: Self, __value: Iterable[tuple[_KT, _VT]]) -> Self: ... class set(MutableSet[_T], Generic[_T]): def __init__(self, __iterable: Iterable[_T] = ...) -> None: ... @@ -889,20 +954,19 @@ class set(MutableSet[_T], Generic[_T]): def __len__(self) -> int: ... def __contains__(self, __o: object) -> bool: ... def __iter__(self) -> Iterator[_T]: ... - def __str__(self) -> str: ... def __and__(self, __s: AbstractSet[object]) -> set[_T]: ... - def __iand__(self, __s: AbstractSet[object]) -> set[_T]: ... + def __iand__(self: Self, __s: AbstractSet[object]) -> Self: ... def __or__(self, __s: AbstractSet[_S]) -> set[_T | _S]: ... - def __ior__(self, __s: AbstractSet[_S]) -> set[_T | _S]: ... + def __ior__(self: Self, __s: AbstractSet[_T]) -> Self: ... # type: ignore[override,misc] def __sub__(self, __s: AbstractSet[_T | None]) -> set[_T]: ... - def __isub__(self, __s: AbstractSet[_T | None]) -> set[_T]: ... + def __isub__(self: Self, __s: AbstractSet[object]) -> Self: ... def __xor__(self, __s: AbstractSet[_S]) -> set[_T | _S]: ... - def __ixor__(self, __s: AbstractSet[_S]) -> set[_T | _S]: ... + def __ixor__(self: Self, __s: AbstractSet[_T]) -> Self: ... # type: ignore[override,misc] def __le__(self, __s: AbstractSet[object]) -> bool: ... def __lt__(self, __s: AbstractSet[object]) -> bool: ... def __ge__(self, __s: AbstractSet[object]) -> bool: ... def __gt__(self, __s: AbstractSet[object]) -> bool: ... - __hash__: None # type: ignore[assignment] + __hash__: ClassVar[None] # type: ignore[assignment] if sys.version_info >= (3, 9): def __class_getitem__(cls, __item: Any) -> GenericAlias: ... @@ -919,7 +983,6 @@ class frozenset(AbstractSet[_T_co], Generic[_T_co]): def __len__(self) -> int: ... def __contains__(self, __o: object) -> bool: ... def __iter__(self) -> Iterator[_T_co]: ... - def __str__(self) -> str: ... def __and__(self, __s: AbstractSet[_T_co]) -> frozenset[_T_co]: ... def __or__(self, __s: AbstractSet[_S]) -> frozenset[_T_co | _S]: ... def __sub__(self, __s: AbstractSet[_T_co]) -> frozenset[_T_co]: ... @@ -933,16 +996,19 @@ class frozenset(AbstractSet[_T_co], Generic[_T_co]): class enumerate(Iterator[tuple[int, _T]], Generic[_T]): def __init__(self, iterable: Iterable[_T], start: int = ...) -> None: ... - def __iter__(self) -> Iterator[tuple[int, _T]]: ... + def __iter__(self: Self) -> Self: ... def __next__(self) -> tuple[int, _T]: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, __item: Any) -> GenericAlias: ... @final class range(Sequence[int]): - start: int - stop: int - step: int + @property + def start(self) -> int: ... + @property + def stop(self) -> int: ... + @property + def step(self) -> int: ... @overload def __init__(self, __stop: SupportsIndex) -> None: ... @overload @@ -956,13 +1022,13 @@ class range(Sequence[int]): def __getitem__(self, __i: SupportsIndex) -> int: ... @overload def __getitem__(self, __s: slice) -> range: ... - def __repr__(self) -> str: ... def __reversed__(self) -> Iterator[int]: ... class property: fget: Callable[[Any], Any] | None fset: Callable[[Any, Any], None] | None fdel: Callable[[Any], None] | None + __isabstractmethod__: bool def __init__( self, fget: Callable[[Any], Any] | None = ..., @@ -1006,8 +1072,15 @@ class _PathLike(Protocol[_AnyStr_co]): if sys.version_info >= (3, 10): def aiter(__async_iterable: _SupportsAiter[_SupportsAnextT]) -> _SupportsAnextT: ... + + class _SupportsSynchronousAnext(Protocol[_AwaitableT_co]): + def __anext__(self) -> _AwaitableT_co: ... + @overload - async def anext(__i: SupportsAnext[_T]) -> _T: ... + # `anext` is not, in fact, an async function. When default is not provided + # `anext` is just a passthrough for `obj.__anext__` + # See discussion in #7491 and pure-Python implementation of `anext` at https://github.com/python/cpython/blob/ea786a882b9ed4261eafabad6011bc7ef3b5bf94/Lib/test/test_asyncgen.py#L52-L80 + def anext(__i: _SupportsSynchronousAnext[_AwaitableT]) -> _AwaitableT: ... @overload async def anext(__i: SupportsAnext[_T], default: _VT) -> _T | _VT: ... @@ -1059,8 +1132,10 @@ class filter(Iterator[_T], Generic[_T]): @overload def __init__(self, __function: None, __iterable: Iterable[_T | None]) -> None: ... @overload + def __init__(self, __function: Callable[[_S], TypeGuard[_T]], __iterable: Iterable[_S]) -> None: ... + @overload def __init__(self, __function: Callable[[_T], Any], __iterable: Iterable[_T]) -> None: ... - def __iter__(self) -> Iterator[_T]: ... + def __iter__(self: Self) -> Self: ... def __next__(self) -> _T: ... def format(__value: object, __format_spec: str = ...) -> str: ... # TODO unicode @@ -1151,7 +1226,7 @@ class map(Iterator[_S], Generic[_S]): __iter6: Iterable[Any], *iterables: Iterable[Any], ) -> None: ... - def __iter__(self) -> Iterator[_S]: ... + def __iter__(self: Self) -> Self: ... def __next__(self) -> _S: ... @overload @@ -1188,7 +1263,7 @@ def next(__i: SupportsNext[_T]) -> _T: ... def next(__i: SupportsNext[_T], __default: _VT) -> _T | _VT: ... def oct(__number: int | SupportsIndex) -> str: ... -_OpenFile = Union[StrOrBytesPath, int] +_OpenFile = StrOrBytesPath | int _Opener = Callable[[str, int], int] # Text mode: always returns a TextIOWrapper @@ -1257,7 +1332,7 @@ def open( def open( file: _OpenFile, mode: OpenBinaryMode, - buffering: int, + buffering: int = ..., encoding: None = ..., errors: None = ..., newline: None = ..., @@ -1307,7 +1382,7 @@ class _SupportsPow3NoneOnly(Protocol[_E, _T_co]): class _SupportsPow3(Protocol[_E, _M, _T_co]): def __pow__(self, __other: _E, __modulo: _M) -> _T_co: ... -_SupportsSomeKindOfPow = Union[_SupportsPow2[Any, Any], _SupportsPow3NoneOnly[Any, Any], _SupportsPow3[Any, Any, Any]] +_SupportsSomeKindOfPow = _SupportsPow2[Any, Any] | _SupportsPow3NoneOnly[Any, Any] | _SupportsPow3[Any, Any, Any] if sys.version_info >= (3, 8): @overload @@ -1315,6 +1390,8 @@ if sys.version_info >= (3, 8): @overload def pow(base: int, exp: int, mod: int) -> int: ... @overload + def pow(base: int, exp: Literal[0], mod: None = ...) -> Literal[1]: ... # type: ignore[misc] + @overload def pow(base: int, exp: _PositiveInteger, mod: None = ...) -> int: ... # type: ignore[misc] @overload def pow(base: int, exp: _NegativeInteger, mod: None = ...) -> float: ... # type: ignore[misc] @@ -1348,6 +1425,8 @@ else: @overload def pow(__base: int, __exp: int, __mod: int) -> int: ... @overload + def pow(__base: int, __exp: Literal[0], __mod: None = ...) -> Literal[1]: ... # type: ignore[misc] + @overload def pow(__base: int, __exp: _PositiveInteger, __mod: None = ...) -> int: ... # type: ignore[misc] @overload def pow(__base: int, __exp: _NegativeInteger, __mod: None = ...) -> float: ... # type: ignore[misc] @@ -1377,8 +1456,9 @@ class reversed(Iterator[_T], Generic[_T]): def __init__(self, __sequence: Reversible[_T]) -> None: ... @overload def __init__(self, __sequence: SupportsLenAndGetItem[_T]) -> None: ... - def __iter__(self) -> Iterator[_T]: ... + def __iter__(self: Self) -> Self: ... def __next__(self) -> _T: ... + def __length_hint__(self) -> int: ... def repr(__obj: object) -> str: ... @overload @@ -1398,17 +1478,22 @@ def sorted( @overload def sorted(__iterable: Iterable[_T], *, key: Callable[[_T], SupportsRichComparison], reverse: bool = ...) -> list[_T]: ... +class _SupportsSum(Protocol): + def __add__(self, __x: Any) -> Any: ... + +_SumT = TypeVar("_SumT", bound=_SupportsSum) +_SumS = TypeVar("_SumS", bound=_SupportsSum) + +@overload +def sum(__iterable: Iterable[_SumT]) -> _SumT | Literal[0]: ... + if sys.version_info >= (3, 8): @overload - def sum(__iterable: Iterable[_T]) -> _T | Literal[0]: ... - @overload - def sum(__iterable: Iterable[_T], start: _S) -> _T | _S: ... + def sum(__iterable: Iterable[_SumT], start: _SumS) -> _SumT | _SumS: ... else: @overload - def sum(__iterable: Iterable[_T]) -> _T | Literal[0]: ... - @overload - def sum(__iterable: Iterable[_T], __start: _S) -> _T | _S: ... + def sum(__iterable: Iterable[_SumT], __start: _SumS) -> _SumT | _SumS: ... # The argument to `vars()` has to have a `__dict__` attribute, so can't be annotated with `object` # (A "SupportsDunderDict" protocol doesn't work) @@ -1488,7 +1573,8 @@ class zip(Iterator[_T_co], Generic[_T_co]): __iter6: Iterable[Any], *iterables: Iterable[Any], ) -> zip[tuple[Any, ...]]: ... - def __iter__(self) -> Iterator[_T_co]: ... + + def __iter__(self: Self) -> Self: ... def __next__(self) -> _T_co: ... # Signature of `builtins.__import__` should be kept identical to `importlib.__import__` @@ -1500,6 +1586,7 @@ def __import__( fromlist: Sequence[str] = ..., level: int = ..., ) -> types.ModuleType: ... +def __build_class__(__func: Callable[[], _Cell | Any], __name: str, *bases: Any, metaclass: Any = ..., **kwds: Any) -> Any: ... # Actually the type of Ellipsis is , but since it's # not exposed anywhere under that name, we make it private here. @@ -1517,9 +1604,7 @@ class BaseException: if sys.version_info >= (3, 11): __note__: str | None def __init__(self, *args: object) -> None: ... - def __str__(self) -> str: ... - def __repr__(self) -> str: ... - def with_traceback(self: _TBE, __tb: TracebackType | None) -> _TBE: ... + def with_traceback(self: Self, __tb: TracebackType | None) -> Self: ... class GeneratorExit(BaseException): ... class KeyboardInterrupt(BaseException): ... @@ -1662,17 +1747,19 @@ if sys.version_info >= (3, 10): class EncodingWarning(Warning): ... if sys.version_info >= (3, 11): - _SplitCondition = type[BaseException] | tuple[type[BaseException, ...]] | Callable[[BaseException], bool] + _SplitCondition = Union[type[BaseException], tuple[type[BaseException], ...], Callable[[BaseException], bool]] + class BaseExceptionGroup(BaseException): - def __new__(cls, __message: str, __exceptions: Sequence[BaseException]) -> BaseExceptionGroup | ExceptionGroup: ... + def __new__(cls: type[Self], __message: str, __exceptions: Sequence[BaseException]) -> Self: ... @property def message(self) -> str: ... @property - def exceptions(self) -> Sequence[BaseException]: ... + def exceptions(self) -> tuple[BaseException, ...]: ... def subgroup(self: Self, __condition: _SplitCondition) -> Self | None: ... def split(self: Self, __condition: _SplitCondition) -> tuple[Self | None, Self | None]: ... def derive(self: Self, __excs: Sequence[BaseException]) -> Self: ... + class ExceptionGroup(BaseExceptionGroup, Exception): - def __new__(cls, __message: str, exceptions: Sequence[Exception]) -> ExceptionGroup: ... + def __new__(cls: type[Self], __message: str, __exceptions: Sequence[Exception]) -> Self: ... @property - def exceptions(self) -> Sequence[Exception]: ... + def exceptions(self) -> tuple[Exception, ...]: ... diff --git a/mypy/typeshed/stdlib/bz2.pyi b/mypy/typeshed/stdlib/bz2.pyi index 6aeaa3da4c60d..f1467acadd103 100644 --- a/mypy/typeshed/stdlib/bz2.pyi +++ b/mypy/typeshed/stdlib/bz2.pyi @@ -2,9 +2,11 @@ import _compression import sys from _compression import BaseStream from _typeshed import ReadableBuffer, Self, StrOrBytesPath, WriteableBuffer -from typing import IO, Any, Iterable, Protocol, TextIO, TypeVar, overload +from typing import IO, Any, Iterable, Protocol, TextIO, overload from typing_extensions import Literal, SupportsIndex, final +__all__ = ["BZ2File", "BZ2Compressor", "BZ2Decompressor", "open", "compress", "decompress"] + # The following attributes and methods are optional: # def fileno(self) -> int: ... # def close(self) -> object: ... @@ -16,8 +18,6 @@ class _WritableFileobj(Protocol): # def fileno(self) -> int: ... # def close(self) -> object: ... -_T = TypeVar("_T") - def compress(data: bytes, compresslevel: int = ...) -> bytes: ... def decompress(data: bytes) -> bytes: ... @@ -118,6 +118,7 @@ class BZ2File(BaseStream, IO[bytes]): buffering: Any | None = ..., compresslevel: int = ..., ) -> None: ... + def read(self, size: int | None = ...) -> bytes: ... def read1(self, size: int = ...) -> bytes: ... def readline(self, size: SupportsIndex = ...) -> bytes: ... # type: ignore[override] diff --git a/mypy/typeshed/stdlib/cProfile.pyi b/mypy/typeshed/stdlib/cProfile.pyi index e79524aa793e4..6f15e461e007f 100644 --- a/mypy/typeshed/stdlib/cProfile.pyi +++ b/mypy/typeshed/stdlib/cProfile.pyi @@ -2,6 +2,9 @@ import sys from _typeshed import Self, StrOrBytesPath from types import CodeType from typing import Any, Callable, TypeVar +from typing_extensions import ParamSpec + +__all__ = ["run", "runctx", "Profile"] def run(statement: str, filename: str | None = ..., sort: str | int = ...) -> None: ... def runctx( @@ -9,6 +12,7 @@ def runctx( ) -> None: ... _T = TypeVar("_T") +_P = ParamSpec("_P") _Label = tuple[str, int, str] class Profile: @@ -24,9 +28,9 @@ class Profile: def snapshot_stats(self) -> None: ... def run(self: Self, cmd: str) -> Self: ... def runctx(self: Self, cmd: str, globals: dict[str, Any], locals: dict[str, Any]) -> Self: ... - def runcall(self, __func: Callable[..., _T], *args: Any, **kw: Any) -> _T: ... + def runcall(self, __func: Callable[_P, _T], *args: _P.args, **kw: _P.kwargs) -> _T: ... if sys.version_info >= (3, 8): def __enter__(self: Self) -> Self: ... - def __exit__(self, *exc_info: Any) -> None: ... + def __exit__(self, *exc_info: object) -> None: ... def label(code: str | CodeType) -> _Label: ... # undocumented diff --git a/mypy/typeshed/stdlib/calendar.pyi b/mypy/typeshed/stdlib/calendar.pyi index aa37928b87b12..05ceca4a3ae02 100644 --- a/mypy/typeshed/stdlib/calendar.pyi +++ b/mypy/typeshed/stdlib/calendar.pyi @@ -1,17 +1,43 @@ import datetime import sys +from collections.abc import Iterable, Sequence from time import struct_time -from typing import Any, Iterable, Optional, Sequence - -_LocaleType = tuple[Optional[str], Optional[str]] +from typing_extensions import Literal + +__all__ = [ + "IllegalMonthError", + "IllegalWeekdayError", + "setfirstweekday", + "firstweekday", + "isleap", + "leapdays", + "weekday", + "monthrange", + "monthcalendar", + "prmonth", + "month", + "prcal", + "calendar", + "timegm", + "month_name", + "month_abbr", + "day_name", + "day_abbr", + "Calendar", + "TextCalendar", + "HTMLCalendar", + "LocaleTextCalendar", + "LocaleHTMLCalendar", + "weekheader", +] + +_LocaleType = tuple[str | None, str | None] class IllegalMonthError(ValueError): def __init__(self, month: int) -> None: ... - def __str__(self) -> str: ... class IllegalWeekdayError(ValueError): def __init__(self, weekday: int) -> None: ... - def __str__(self) -> str: ... def isleap(year: int) -> bool: ... def leapdays(y1: int, y2: int) -> int: ... @@ -79,8 +105,8 @@ class HTMLCalendar(Calendar): class different_locale: def __init__(self, locale: _LocaleType) -> None: ... - def __enter__(self) -> _LocaleType: ... - def __exit__(self, *args: Any) -> None: ... + def __enter__(self) -> None: ... + def __exit__(self, *args: object) -> None: ... class LocaleTextCalendar(TextCalendar): def __init__(self, firstweekday: int = ..., locale: _LocaleType | None = ...) -> None: ... @@ -105,13 +131,12 @@ day_abbr: Sequence[str] month_name: Sequence[str] month_abbr: Sequence[str] -# Below constants are not in docs or __all__, but enough people have used them -# they are now effectively public. +MONDAY: Literal[0] +TUESDAY: Literal[1] +WEDNESDAY: Literal[2] +THURSDAY: Literal[3] +FRIDAY: Literal[4] +SATURDAY: Literal[5] +SUNDAY: Literal[6] -MONDAY: int -TUESDAY: int -WEDNESDAY: int -THURSDAY: int -FRIDAY: int -SATURDAY: int -SUNDAY: int +EPOCH: Literal[1970] diff --git a/mypy/typeshed/stdlib/cgi.pyi b/mypy/typeshed/stdlib/cgi.pyi index c2c3ac261010a..0bd4e515ce51b 100644 --- a/mypy/typeshed/stdlib/cgi.pyi +++ b/mypy/typeshed/stdlib/cgi.pyi @@ -1,10 +1,43 @@ import sys -from _typeshed import SupportsGetItem, SupportsItemAccess +from _typeshed import Self, SupportsGetItem, SupportsItemAccess from builtins import type as _type from collections.abc import Iterable, Iterator, Mapping -from typing import IO, Any, Protocol, TypeVar +from types import TracebackType +from typing import IO, Any, Protocol -_T = TypeVar("_T", bound=FieldStorage) +if sys.version_info >= (3, 8): + __all__ = [ + "MiniFieldStorage", + "FieldStorage", + "parse", + "parse_multipart", + "parse_header", + "test", + "print_exception", + "print_environ", + "print_form", + "print_directory", + "print_arguments", + "print_environ_usage", + ] +else: + __all__ = [ + "MiniFieldStorage", + "FieldStorage", + "parse", + "parse_qs", + "parse_qsl", + "parse_multipart", + "parse_header", + "test", + "print_exception", + "print_environ", + "print_form", + "print_directory", + "print_arguments", + "print_environ_usage", + "escape", + ] def parse( fp: IO[Any] | None = ..., @@ -53,7 +86,6 @@ class MiniFieldStorage: name: Any value: Any def __init__(self, name: Any, value: Any) -> None: ... - def __repr__(self) -> str: ... _list = list @@ -94,9 +126,8 @@ class FieldStorage: max_num_fields: int | None = ..., separator: str = ..., ) -> None: ... - def __enter__(self: _T) -> _T: ... - def __exit__(self, *args: Any) -> None: ... - def __repr__(self) -> str: ... + def __enter__(self: Self) -> Self: ... + def __exit__(self, *args: object) -> None: ... def __iter__(self) -> Iterator[str]: ... def __getitem__(self, key: str) -> Any: ... def getvalue(self, key: str, default: Any = ...) -> Any: ... @@ -108,3 +139,11 @@ class FieldStorage: def __bool__(self) -> bool: ... # In Python 3 it returns bytes or str IO depending on an internal flag def make_file(self) -> IO[Any]: ... + +def print_exception( + type: type[BaseException] | None = ..., + value: BaseException | None = ..., + tb: TracebackType | None = ..., + limit: int | None = ..., +) -> None: ... +def print_arguments() -> None: ... diff --git a/mypy/typeshed/stdlib/cgitb.pyi b/mypy/typeshed/stdlib/cgitb.pyi index a8f3912aa04cb..2db108ce75ec1 100644 --- a/mypy/typeshed/stdlib/cgitb.pyi +++ b/mypy/typeshed/stdlib/cgitb.pyi @@ -1,8 +1,10 @@ from _typeshed import StrOrBytesPath from types import FrameType, TracebackType -from typing import IO, Any, Callable, Optional, Type +from typing import IO, Any, Callable -_ExcInfo = tuple[Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType]] +_ExcInfo = tuple[type[BaseException] | None, BaseException | None, TracebackType | None] + +__UNDEF__: object # undocumented sentinel def reset() -> str: ... # undocumented def small(text: str) -> str: ... # undocumented @@ -24,7 +26,7 @@ class Hook: # undocumented file: IO[str] | None = ..., format: str = ..., ) -> None: ... - def __call__(self, etype: Type[BaseException] | None, evalue: BaseException | None, etb: TracebackType | None) -> None: ... + def __call__(self, etype: type[BaseException] | None, evalue: BaseException | None, etb: TracebackType | None) -> None: ... def handle(self, info: _ExcInfo | None = ...) -> None: ... def handler(info: _ExcInfo | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/cmath.pyi b/mypy/typeshed/stdlib/cmath.pyi index 04c2b632d411d..ee51861fdaa06 100644 --- a/mypy/typeshed/stdlib/cmath.pyi +++ b/mypy/typeshed/stdlib/cmath.pyi @@ -1,5 +1,5 @@ import sys -from typing import SupportsComplex, SupportsFloat, Union +from typing import SupportsComplex, SupportsFloat if sys.version_info >= (3, 8): from typing import SupportsIndex @@ -13,9 +13,9 @@ nanj: complex tau: float if sys.version_info >= (3, 8): - _C = Union[SupportsFloat, SupportsComplex, SupportsIndex, complex] + _C = SupportsFloat | SupportsComplex | SupportsIndex | complex else: - _C = Union[SupportsFloat, SupportsComplex, complex] + _C = SupportsFloat | SupportsComplex | complex def acos(__z: _C) -> complex: ... def acosh(__z: _C) -> complex: ... diff --git a/mypy/typeshed/stdlib/cmd.pyi b/mypy/typeshed/stdlib/cmd.pyi index f6d818591a4ea..d1166db0f507e 100644 --- a/mypy/typeshed/stdlib/cmd.pyi +++ b/mypy/typeshed/stdlib/cmd.pyi @@ -1,4 +1,10 @@ from typing import IO, Any, Callable +from typing_extensions import Literal + +__all__ = ["Cmd"] + +PROMPT: Literal["(Cmd) "] +IDENTCHARS: str # Too big to be `Literal` class Cmd: prompt: str @@ -26,7 +32,7 @@ class Cmd: def parseline(self, line: str) -> tuple[str | None, str | None, str]: ... def onecmd(self, line: str) -> bool: ... def emptyline(self) -> bool: ... - def default(self, line: str) -> bool: ... + def default(self, line: str) -> None: ... def completedefault(self, *ignored: Any) -> list[str]: ... def completenames(self, text: str, *ignored: Any) -> list[str]: ... completion_matches: list[str] | None diff --git a/mypy/typeshed/stdlib/code.pyi b/mypy/typeshed/stdlib/code.pyi index ed00eaf96a5cd..185c15853b826 100644 --- a/mypy/typeshed/stdlib/code.pyi +++ b/mypy/typeshed/stdlib/code.pyi @@ -2,6 +2,8 @@ from codeop import CommandCompiler from types import CodeType from typing import Any, Callable, Mapping +__all__ = ["InteractiveInterpreter", "InteractiveConsole", "interact", "compile_command"] + class InteractiveInterpreter: locals: Mapping[str, Any] # undocumented compile: CommandCompiler # undocumented diff --git a/mypy/typeshed/stdlib/codecs.pyi b/mypy/typeshed/stdlib/codecs.pyi index e08672e514284..8fa93961d9d09 100644 --- a/mypy/typeshed/stdlib/codecs.pyi +++ b/mypy/typeshed/stdlib/codecs.pyi @@ -2,13 +2,60 @@ import sys import types from _typeshed import Self from abc import abstractmethod -from typing import IO, Any, BinaryIO, Callable, Generator, Iterable, Iterator, Protocol, TextIO, Type, TypeVar, overload +from typing import IO, Any, BinaryIO, Callable, Generator, Iterable, Iterator, Protocol, TextIO, overload from typing_extensions import Literal -BOM32_BE: bytes -BOM32_LE: bytes -BOM64_BE: bytes -BOM64_LE: bytes +__all__ = [ + "register", + "lookup", + "open", + "EncodedFile", + "BOM", + "BOM_BE", + "BOM_LE", + "BOM32_BE", + "BOM32_LE", + "BOM64_BE", + "BOM64_LE", + "BOM_UTF8", + "BOM_UTF16", + "BOM_UTF16_LE", + "BOM_UTF16_BE", + "BOM_UTF32", + "BOM_UTF32_LE", + "BOM_UTF32_BE", + "CodecInfo", + "Codec", + "IncrementalEncoder", + "IncrementalDecoder", + "StreamReader", + "StreamWriter", + "StreamReaderWriter", + "StreamRecoder", + "getencoder", + "getdecoder", + "getincrementalencoder", + "getincrementaldecoder", + "getreader", + "getwriter", + "encode", + "decode", + "iterencode", + "iterdecode", + "strict_errors", + "ignore_errors", + "replace_errors", + "xmlcharrefreplace_errors", + "backslashreplace_errors", + "namereplace_errors", + "register_error", + "lookup_error", +] + +BOM32_BE: Literal[b"\xfe\xff"] +BOM32_LE: Literal[b"\xff\xfe"] +BOM64_BE: Literal[b"\x00\x00\xfe\xff"] +BOM64_LE: Literal[b"\xff\xfe\x00\x00"] # TODO: this only satisfies the most common interface, where # bytes is the raw form and str is the cooked form. @@ -35,8 +82,8 @@ class _IncrementalDecoder(Protocol): def __call__(self, errors: str = ...) -> IncrementalDecoder: ... # The type ignore on `encode` and `decode` is to avoid issues with overlapping overloads, for more details, see #300 -# mypy and pytype disagree about where the type ignore can and cannot go, so alias the long type -_BytesToBytesEncodingT = Literal[ +# https://docs.python.org/3/library/codecs.html#binary-transforms +_BytesToBytesEncoding = Literal[ "base64", "base_64", "base64_codec", @@ -54,17 +101,23 @@ _BytesToBytesEncodingT = Literal[ "zlib", "zlib_codec", ] +# https://docs.python.org/3/library/codecs.html#text-transforms +_StrToStrEncoding = Literal["rot13", "rot_13"] @overload -def encode(obj: bytes, encoding: _BytesToBytesEncodingT, errors: str = ...) -> bytes: ... +def encode(obj: bytes, encoding: _BytesToBytesEncoding, errors: str = ...) -> bytes: ... @overload -def encode(obj: str, encoding: Literal["rot13", "rot_13"] = ..., errors: str = ...) -> str: ... # type: ignore[misc] +def encode(obj: str, encoding: _StrToStrEncoding, errors: str = ...) -> str: ... # type: ignore[misc] @overload def encode(obj: str, encoding: str = ..., errors: str = ...) -> bytes: ... @overload -def decode(obj: bytes, encoding: _BytesToBytesEncodingT, errors: str = ...) -> bytes: ... # type: ignore[misc] +def decode(obj: bytes, encoding: _BytesToBytesEncoding, errors: str = ...) -> bytes: ... # type: ignore[misc] +@overload +def decode(obj: str, encoding: _StrToStrEncoding, errors: str = ...) -> str: ... + +# hex is officially documented as a bytes to bytes encoding, but it appears to also work with str @overload -def decode(obj: str, encoding: Literal["rot13", "rot_13"] = ..., errors: str = ...) -> str: ... +def decode(obj: str, encoding: Literal["hex", "hex_codec"], errors: str = ...) -> bytes: ... @overload def decode(obj: bytes, encoding: str = ..., errors: str = ...) -> str: ... def lookup(__encoding: str) -> CodecInfo: ... @@ -86,7 +139,7 @@ class CodecInfo(tuple[_Encoder, _Decoder, _StreamReader, _StreamWriter]): def incrementaldecoder(self) -> _IncrementalDecoder: ... name: str def __new__( - cls, + cls: type[Self], encode: _Encoder, decode: _Decoder, streamreader: _StreamReader | None = ..., @@ -96,7 +149,7 @@ class CodecInfo(tuple[_Encoder, _Decoder, _StreamReader, _StreamWriter]): name: str | None = ..., *, _is_text_encoding: bool | None = ..., - ) -> CodecInfo: ... + ) -> Self: ... def getencoder(encoding: str) -> _Encoder: ... def getdecoder(encoding: str) -> _Decoder: ... @@ -115,16 +168,16 @@ def iterdecode(iterator: Iterable[bytes], encoding: str, errors: str = ...) -> G if sys.version_info >= (3, 10): def unregister(__search_function: Callable[[str], CodecInfo | None]) -> None: ... -BOM: bytes -BOM_BE: bytes -BOM_LE: bytes -BOM_UTF8: bytes -BOM_UTF16: bytes -BOM_UTF16_BE: bytes -BOM_UTF16_LE: bytes -BOM_UTF32: bytes -BOM_UTF32_BE: bytes -BOM_UTF32_LE: bytes +BOM: Literal[b"\xff\xfe", b"\xfe\xff"] # depends on `sys.byteorder` +BOM_BE: Literal[b"\xfe\xff"] +BOM_LE: Literal[b"\xff\xfe"] +BOM_UTF8: Literal[b"\xef\xbb\xbf"] +BOM_UTF16: Literal[b"\xff\xfe", b"\xfe\xff"] # depends on `sys.byteorder` +BOM_UTF16_BE: Literal[b"\xfe\xff"] +BOM_UTF16_LE: Literal[b"\xff\xfe"] +BOM_UTF32: Literal[b"\xff\xfe\x00\x00", b"\x00\x00\xfe\xff"] # depends on `sys.byteorder` +BOM_UTF32_BE: Literal[b"\x00\x00\xfe\xff"] +BOM_UTF32_LE: Literal[b"\xff\xfe\x00\x00"] # It is expected that different actions be taken depending on which of the # three subclasses of `UnicodeError` is actually ...ed. However, the Union @@ -136,6 +189,7 @@ def replace_errors(exception: UnicodeError) -> tuple[str | bytes, int]: ... def ignore_errors(exception: UnicodeError) -> tuple[str | bytes, int]: ... def xmlcharrefreplace_errors(exception: UnicodeError) -> tuple[str | bytes, int]: ... def backslashreplace_errors(exception: UnicodeError) -> tuple[str | bytes, int]: ... +def namereplace_errors(exception: UnicodeError) -> tuple[str | bytes, int]: ... class Codec: # These are sort of @abstractmethod but sort of not. @@ -186,10 +240,10 @@ class StreamWriter(Codec): def writelines(self, list: Iterable[str]) -> None: ... def reset(self) -> None: ... def __enter__(self: Self) -> Self: ... - def __exit__(self, typ: Type[BaseException] | None, exc: BaseException | None, tb: types.TracebackType | None) -> None: ... + def __exit__(self, type: type[BaseException] | None, value: BaseException | None, tb: types.TracebackType | None) -> None: ... def __getattr__(self, name: str, getattr: Callable[[str], Any] = ...) -> Any: ... -class StreamReader(Codec): +class StreamReader(Codec, Iterator[str]): errors: str def __init__(self, stream: IO[bytes], errors: str = ...) -> None: ... def read(self, size: int = ..., chars: int = ..., firstline: bool = ...) -> str: ... @@ -197,12 +251,11 @@ class StreamReader(Codec): def readlines(self, sizehint: int | None = ..., keepends: bool = ...) -> list[str]: ... def reset(self) -> None: ... def __enter__(self: Self) -> Self: ... - def __exit__(self, typ: Type[BaseException] | None, exc: BaseException | None, tb: types.TracebackType | None) -> None: ... - def __iter__(self) -> Iterator[str]: ... + def __exit__(self, type: type[BaseException] | None, value: BaseException | None, tb: types.TracebackType | None) -> None: ... + def __iter__(self: Self) -> Self: ... + def __next__(self) -> str: ... def __getattr__(self, name: str, getattr: Callable[[str], Any] = ...) -> Any: ... -_T = TypeVar("_T", bound=StreamReaderWriter) - # Doesn't actually inherit from TextIO, but wraps a BinaryIO to provide text reading and writing # and delegates attributes to the underlying binary stream with __getattr__. class StreamReaderWriter(TextIO): @@ -211,15 +264,13 @@ class StreamReaderWriter(TextIO): def readline(self, size: int | None = ...) -> str: ... def readlines(self, sizehint: int | None = ...) -> list[str]: ... def __next__(self) -> str: ... - def __iter__(self: _T) -> _T: ... - # This actually returns None, but that's incompatible with the supertype - def write(self, data: str) -> int: ... + def __iter__(self: Self) -> Self: ... + def write(self, data: str) -> None: ... # type: ignore[override] def writelines(self, list: Iterable[str]) -> None: ... def reset(self) -> None: ... - # Same as write() - def seek(self, offset: int, whence: int = ...) -> int: ... + def seek(self, offset: int, whence: int = ...) -> None: ... # type: ignore[override] def __enter__(self: Self) -> Self: ... - def __exit__(self, typ: Type[BaseException] | None, exc: BaseException | None, tb: types.TracebackType | None) -> None: ... + def __exit__(self, type: type[BaseException] | None, value: BaseException | None, tb: types.TracebackType | None) -> None: ... def __getattr__(self, name: str) -> Any: ... # These methods don't actually exist directly, but they are needed to satisfy the TextIO # interface. At runtime, they are delegated through __getattr__. @@ -233,8 +284,6 @@ class StreamReaderWriter(TextIO): def tell(self) -> int: ... def writable(self) -> bool: ... -_SRT = TypeVar("_SRT", bound=StreamRecoder) - class StreamRecoder(BinaryIO): def __init__( self, @@ -249,16 +298,16 @@ class StreamRecoder(BinaryIO): def readline(self, size: int | None = ...) -> bytes: ... def readlines(self, sizehint: int | None = ...) -> list[bytes]: ... def __next__(self) -> bytes: ... - def __iter__(self: _SRT) -> _SRT: ... - def write(self, data: bytes) -> int: ... - def writelines(self, list: Iterable[bytes]) -> int: ... # type: ignore # it's supposed to return None + def __iter__(self: Self) -> Self: ... + def write(self, data: bytes) -> None: ... # type: ignore[override] + def writelines(self, list: Iterable[bytes]) -> None: ... def reset(self) -> None: ... def __getattr__(self, name: str) -> Any: ... def __enter__(self: Self) -> Self: ... - def __exit__(self, type: Type[BaseException] | None, value: BaseException | None, tb: types.TracebackType | None) -> None: ... + def __exit__(self, type: type[BaseException] | None, value: BaseException | None, tb: types.TracebackType | None) -> None: ... + def seek(self, offset: int, whence: int = ...) -> None: ... # type: ignore[override] # These methods don't actually exist directly, but they are needed to satisfy the BinaryIO # interface. At runtime, they are delegated through __getattr__. - def seek(self, offset: int, whence: int = ...) -> int: ... def close(self) -> None: ... def fileno(self) -> int: ... def flush(self) -> None: ... diff --git a/mypy/typeshed/stdlib/codeop.pyi b/mypy/typeshed/stdlib/codeop.pyi index 8ed5710c9891e..1c00e13fd5017 100644 --- a/mypy/typeshed/stdlib/codeop.pyi +++ b/mypy/typeshed/stdlib/codeop.pyi @@ -1,5 +1,7 @@ from types import CodeType +__all__ = ["compile_command", "Compile", "CommandCompiler"] + def compile_command(source: str, filename: str = ..., symbol: str = ...) -> CodeType | None: ... class Compile: diff --git a/mypy/typeshed/stdlib/collections/__init__.pyi b/mypy/typeshed/stdlib/collections/__init__.pyi index adcdf29fa6908..e534c13c026b5 100644 --- a/mypy/typeshed/stdlib/collections/__init__.pyi +++ b/mypy/typeshed/stdlib/collections/__init__.pyi @@ -1,7 +1,7 @@ import sys from _collections_abc import dict_items, dict_keys, dict_values from _typeshed import Self, SupportsKeysAndGetItem, SupportsRichComparison, SupportsRichComparisonT -from typing import Any, Generic, NoReturn, Type, TypeVar, overload +from typing import Any, Generic, NoReturn, TypeVar, overload from typing_extensions import SupportsIndex, final if sys.version_info >= (3, 9): @@ -12,8 +12,12 @@ if sys.version_info >= (3, 10): else: from _collections_abc import * +__all__ = ["ChainMap", "Counter", "OrderedDict", "UserDict", "UserList", "UserString", "defaultdict", "deque", "namedtuple"] + _S = TypeVar("_S") _T = TypeVar("_T") +_T1 = TypeVar("_T1") +_T2 = TypeVar("_T2") _KT = TypeVar("_KT") _VT = TypeVar("_VT") _KT_co = TypeVar("_KT_co", covariant=True) @@ -28,12 +32,12 @@ if sys.version_info >= (3, 7): rename: bool = ..., module: str | None = ..., defaults: Iterable[Any] | None = ..., - ) -> Type[tuple[Any, ...]]: ... + ) -> type[tuple[Any, ...]]: ... else: def namedtuple( typename: str, field_names: str | Iterable[str], *, verbose: bool = ..., rename: bool = ..., module: str | None = ... - ) -> Type[tuple[Any, ...]]: ... + ) -> type[tuple[Any, ...]]: ... class UserDict(MutableMapping[_KT, _VT], Generic[_KT, _VT]): data: dict[_KT, _VT] @@ -55,8 +59,11 @@ class UserDict(MutableMapping[_KT, _VT], Generic[_KT, _VT]): def __iter__(self) -> Iterator[_KT]: ... def __contains__(self, key: object) -> bool: ... def copy(self: Self) -> Self: ... + if sys.version_info >= (3, 7): + def __copy__(self: Self) -> Self: ... + # `UserDict.fromkeys` has the same semantics as `dict.fromkeys`, so should be kept in line with `dict.fromkeys`. - # TODO: Much like `dict.fromkeys`, the true signature of `UserDict.fromkeys` is inexpressable in the current type system. + # TODO: Much like `dict.fromkeys`, the true signature of `UserDict.fromkeys` is inexpressible in the current type system. # See #3800 & https://github.com/python/typing/issues/548#issuecomment-683336963. @classmethod @overload @@ -64,6 +71,14 @@ class UserDict(MutableMapping[_KT, _VT], Generic[_KT, _VT]): @classmethod @overload def fromkeys(cls, iterable: Iterable[_T], value: _S) -> UserDict[_T, _S]: ... + if sys.version_info >= (3, 9): + def __or__(self, other: UserDict[_T1, _T2] | dict[_T1, _T2]) -> UserDict[_KT | _T1, _VT | _T2]: ... + def __ror__(self, other: UserDict[_T1, _T2] | dict[_T1, _T2]) -> UserDict[_KT | _T1, _VT | _T2]: ... # type: ignore[misc] + # UserDict.__ior__ should be kept roughly in line with MutableMapping.update() + @overload # type: ignore[misc] + def __ior__(self: Self, other: SupportsKeysAndGetItem[_KT, _VT]) -> Self: ... + @overload + def __ior__(self: Self, other: Iterable[tuple[_KT, _VT]]) -> Self: ... class UserList(MutableSequence[_T]): data: list[_T] @@ -72,6 +87,7 @@ class UserList(MutableSequence[_T]): def __le__(self, other: list[_T] | UserList[_T]) -> bool: ... def __gt__(self, other: list[_T] | UserList[_T]) -> bool: ... def __ge__(self, other: list[_T] | UserList[_T]) -> bool: ... + def __eq__(self, other: object) -> bool: ... def __contains__(self, item: object) -> bool: ... def __len__(self) -> int: ... @overload @@ -79,19 +95,24 @@ class UserList(MutableSequence[_T]): @overload def __getitem__(self: Self, i: slice) -> Self: ... @overload - def __setitem__(self, i: SupportsIndex, o: _T) -> None: ... + def __setitem__(self, i: SupportsIndex, item: _T) -> None: ... @overload - def __setitem__(self, i: slice, o: Iterable[_T]) -> None: ... + def __setitem__(self, i: slice, item: Iterable[_T]) -> None: ... def __delitem__(self, i: SupportsIndex | slice) -> None: ... - def __add__(self: _S, other: Iterable[_T]) -> _S: ... - def __iadd__(self: _S, other: Iterable[_T]) -> _S: ... - def __mul__(self: _S, n: int) -> _S: ... - def __imul__(self: _S, n: int) -> _S: ... + def __add__(self: Self, other: Iterable[_T]) -> Self: ... + def __radd__(self: Self, other: Iterable[_T]) -> Self: ... + def __iadd__(self: Self, other: Iterable[_T]) -> Self: ... + def __mul__(self: Self, n: int) -> Self: ... + def __rmul__(self: Self, n: int) -> Self: ... + def __imul__(self: Self, n: int) -> Self: ... def append(self, item: _T) -> None: ... def insert(self, i: int, item: _T) -> None: ... def pop(self, i: int = ...) -> _T: ... def remove(self, item: _T) -> None: ... - def copy(self: _S) -> _S: ... + def copy(self: Self) -> Self: ... + if sys.version_info >= (3, 7): + def __copy__(self: Self) -> Self: ... + def count(self, item: _T) -> int: ... # All arguments are passed to `list.index` at runtime, so the signature should be kept in line with `list.index`. def index(self, item: _T, __start: SupportsIndex = ..., __stop: SupportsIndex = ...) -> int: ... @@ -102,9 +123,7 @@ class UserList(MutableSequence[_T]): def sort(self, *, key: Callable[[_T], SupportsRichComparison], reverse: bool = ...) -> None: ... def extend(self, other: Iterable[_T]) -> None: ... -_UserStringT = TypeVar("_UserStringT", bound=UserString) - -class UserString(Sequence[str]): +class UserString(Sequence[UserString]): data: str def __init__(self, seq: object) -> None: ... def __int__(self) -> int: ... @@ -115,25 +134,33 @@ class UserString(Sequence[str]): def __le__(self, string: str | UserString) -> bool: ... def __gt__(self, string: str | UserString) -> bool: ... def __ge__(self, string: str | UserString) -> bool: ... + def __eq__(self, string: object) -> bool: ... def __contains__(self, char: object) -> bool: ... def __len__(self) -> int: ... - # It should return a str to implement Sequence correctly, but it doesn't. - def __getitem__(self: _UserStringT, i: SupportsIndex | slice) -> _UserStringT: ... # type: ignore[override] - def __iter__(self: _UserStringT) -> Iterator[_UserStringT]: ... # type: ignore[override] - def __reversed__(self: _UserStringT) -> Iterator[_UserStringT]: ... # type: ignore[override] - def __add__(self: _UserStringT, other: object) -> _UserStringT: ... - def __mul__(self: _UserStringT, n: int) -> _UserStringT: ... - def __mod__(self: _UserStringT, args: Any) -> _UserStringT: ... - def capitalize(self: _UserStringT) -> _UserStringT: ... - def casefold(self: _UserStringT) -> _UserStringT: ... - def center(self: _UserStringT, width: int, *args: Any) -> _UserStringT: ... + def __getitem__(self: Self, index: SupportsIndex | slice) -> Self: ... + def __iter__(self: Self) -> Iterator[Self]: ... + def __reversed__(self: Self) -> Iterator[Self]: ... + def __add__(self: Self, other: object) -> Self: ... + def __radd__(self: Self, other: object) -> Self: ... + def __mul__(self: Self, n: int) -> Self: ... + def __rmul__(self: Self, n: int) -> Self: ... + def __mod__(self: Self, args: Any) -> Self: ... + if sys.version_info >= (3, 8): + def __rmod__(self: Self, template: object) -> Self: ... + else: + def __rmod__(self: Self, format: Any) -> Self: ... + + def capitalize(self: Self) -> Self: ... + def casefold(self: Self) -> Self: ... + def center(self: Self, width: int, *args: Any) -> Self: ... def count(self, sub: str | UserString, start: int = ..., end: int = ...) -> int: ... if sys.version_info >= (3, 8): def encode(self: UserString, encoding: str | None = ..., errors: str | None = ...) -> bytes: ... else: - def encode(self: _UserStringT, encoding: str | None = ..., errors: str | None = ...) -> _UserStringT: ... + def encode(self: Self, encoding: str | None = ..., errors: str | None = ...) -> Self: ... + def endswith(self, suffix: str | tuple[str, ...], start: int | None = ..., end: int | None = ...) -> bool: ... - def expandtabs(self: _UserStringT, tabsize: int = ...) -> _UserStringT: ... + def expandtabs(self: Self, tabsize: int = ...) -> Self: ... def find(self, sub: str | UserString, start: int = ..., end: int = ...) -> int: ... def format(self, *args: Any, **kwds: Any) -> str: ... def format_map(self, mapping: Mapping[str, Any]) -> str: ... @@ -151,10 +178,11 @@ class UserString(Sequence[str]): def isupper(self) -> bool: ... if sys.version_info >= (3, 7): def isascii(self) -> bool: ... + def join(self, seq: Iterable[str]) -> str: ... - def ljust(self: _UserStringT, width: int, *args: Any) -> _UserStringT: ... - def lower(self: _UserStringT) -> _UserStringT: ... - def lstrip(self: _UserStringT, chars: str | None = ...) -> _UserStringT: ... + def ljust(self: Self, width: int, *args: Any) -> Self: ... + def lower(self: Self) -> Self: ... + def lstrip(self: Self, chars: str | None = ...) -> Self: ... @staticmethod @overload def maketrans(x: dict[int, _T] | dict[str, _T] | dict[str | int, _T]) -> dict[int, _T]: ... @@ -163,24 +191,25 @@ class UserString(Sequence[str]): def maketrans(x: str, y: str, z: str = ...) -> dict[int, int | None]: ... def partition(self, sep: str) -> tuple[str, str, str]: ... if sys.version_info >= (3, 9): - def removeprefix(self: _UserStringT, __prefix: str | UserString) -> _UserStringT: ... - def removesuffix(self: _UserStringT, __suffix: str | UserString) -> _UserStringT: ... - def replace(self: _UserStringT, old: str | UserString, new: str | UserString, maxsplit: int = ...) -> _UserStringT: ... + def removeprefix(self: Self, __prefix: str | UserString) -> Self: ... + def removesuffix(self: Self, __suffix: str | UserString) -> Self: ... + + def replace(self: Self, old: str | UserString, new: str | UserString, maxsplit: int = ...) -> Self: ... def rfind(self, sub: str | UserString, start: int = ..., end: int = ...) -> int: ... def rindex(self, sub: str | UserString, start: int = ..., end: int = ...) -> int: ... - def rjust(self: _UserStringT, width: int, *args: Any) -> _UserStringT: ... + def rjust(self: Self, width: int, *args: Any) -> Self: ... def rpartition(self, sep: str) -> tuple[str, str, str]: ... - def rstrip(self: _UserStringT, chars: str | None = ...) -> _UserStringT: ... + def rstrip(self: Self, chars: str | None = ...) -> Self: ... def split(self, sep: str | None = ..., maxsplit: int = ...) -> list[str]: ... def rsplit(self, sep: str | None = ..., maxsplit: int = ...) -> list[str]: ... def splitlines(self, keepends: bool = ...) -> list[str]: ... def startswith(self, prefix: str | tuple[str, ...], start: int | None = ..., end: int | None = ...) -> bool: ... - def strip(self: _UserStringT, chars: str | None = ...) -> _UserStringT: ... - def swapcase(self: _UserStringT) -> _UserStringT: ... - def title(self: _UserStringT) -> _UserStringT: ... - def translate(self: _UserStringT, *args: Any) -> _UserStringT: ... - def upper(self: _UserStringT) -> _UserStringT: ... - def zfill(self: _UserStringT, width: int) -> _UserStringT: ... + def strip(self: Self, chars: str | None = ...) -> Self: ... + def swapcase(self: Self) -> Self: ... + def title(self: Self) -> Self: ... + def translate(self: Self, *args: Any) -> Self: ... + def upper(self: Self) -> Self: ... + def zfill(self: Self, width: int) -> Self: ... class deque(MutableSequence[_T], Generic[_T]): @property @@ -188,7 +217,7 @@ class deque(MutableSequence[_T], Generic[_T]): def __init__(self, iterable: Iterable[_T] = ..., maxlen: int | None = ...) -> None: ... def append(self, __x: _T) -> None: ... def appendleft(self, __x: _T) -> None: ... - def copy(self: _S) -> _S: ... + def copy(self: Self) -> Self: ... def count(self, __x: _T) -> int: ... def extend(self, __iterable: Iterable[_T]) -> None: ... def extendleft(self, __iterable: Iterable[_T]) -> None: ... @@ -198,25 +227,30 @@ class deque(MutableSequence[_T], Generic[_T]): def popleft(self) -> _T: ... def remove(self, __value: _T) -> None: ... def rotate(self, __n: int = ...) -> None: ... - def __copy__(self: _S) -> _S: ... + def __copy__(self: Self) -> Self: ... def __len__(self) -> int: ... - def __str__(self) -> str: ... # These methods of deque don't take slices, unlike MutableSequence, hence the type: ignores def __getitem__(self, __index: SupportsIndex) -> _T: ... # type: ignore[override] def __setitem__(self, __i: SupportsIndex, __x: _T) -> None: ... # type: ignore[override] def __delitem__(self, __i: SupportsIndex) -> None: ... # type: ignore[override] def __contains__(self, __o: object) -> bool: ... - def __reduce__(self: Self) -> tuple[Type[Self], tuple[()], None, Iterator[_T]]: ... - def __iadd__(self: _S, __iterable: Iterable[_T]) -> _S: ... - def __add__(self: _S, __other: _S) -> _S: ... - def __mul__(self: _S, __other: int) -> _S: ... - def __imul__(self: _S, __other: int) -> _S: ... + def __reduce__(self: Self) -> tuple[type[Self], tuple[()], None, Iterator[_T]]: ... + def __iadd__(self: Self, __iterable: Iterable[_T]) -> Self: ... + def __add__(self: Self, __other: Self) -> Self: ... + def __mul__(self: Self, __other: int) -> Self: ... + def __imul__(self: Self, __other: int) -> Self: ... + def __lt__(self, __other: deque[_T]) -> bool: ... + def __le__(self, __other: deque[_T]) -> bool: ... + def __gt__(self, __other: deque[_T]) -> bool: ... + def __ge__(self, __other: deque[_T]) -> bool: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, __item: Any) -> GenericAlias: ... class Counter(dict[_T, int], Generic[_T]): @overload - def __init__(self, __iterable: None = ..., **kwargs: int) -> None: ... + def __init__(self: Counter[_T], __iterable: None = ...) -> None: ... + @overload + def __init__(self: Counter[str], __iterable: None = ..., **kwargs: int) -> None: ... @overload def __init__(self, __mapping: SupportsKeysAndGetItem[_T, int]) -> None: ... @overload @@ -232,29 +266,41 @@ class Counter(dict[_T, int], Generic[_T]): def subtract(self, __mapping: Mapping[_T, int]) -> None: ... @overload def subtract(self, __iterable: Iterable[_T]) -> None: ... - # The Iterable[Tuple[...]] argument type is not actually desirable - # (the tuples will be added as keys, breaking type safety) but - # it's included so that the signature is compatible with - # Dict.update. Not sure if we should use '# type: ignore' instead - # and omit the type from the union. + # Unlike dict.update(), use Mapping instead of SupportsKeysAndGetItem for the first overload + # (source code does an `isinstance(other, Mapping)` check) + # + # The second overload is also deliberately different to dict.update() + # (if it were `Iterable[_T] | Iterable[tuple[_T, int]]`, + # the tuples would be added as keys, breaking type safety) + @overload # type: ignore[override] + def update(self, __m: Mapping[_T, int], **kwargs: int) -> None: ... @overload - def update(self, __m: SupportsKeysAndGetItem[_T, int], **kwargs: int) -> None: ... - @overload - def update(self, __m: Iterable[_T] | Iterable[tuple[_T, int]], **kwargs: int) -> None: ... + def update(self, __m: Iterable[_T], **kwargs: int) -> None: ... @overload def update(self, __m: None = ..., **kwargs: int) -> None: ... - def __add__(self, other: Counter[_T]) -> Counter[_T]: ... + def __missing__(self, key: _T) -> int: ... + def __delitem__(self, elem: object) -> None: ... + if sys.version_info >= (3, 10): + def __eq__(self, other: object) -> bool: ... + def __ne__(self, other: object) -> bool: ... + + def __add__(self, other: Counter[_S]) -> Counter[_T | _S]: ... def __sub__(self, other: Counter[_T]) -> Counter[_T]: ... def __and__(self, other: Counter[_T]) -> Counter[_T]: ... - def __or__(self, other: Counter[_T]) -> Counter[_T]: ... # type: ignore[override] + def __or__(self, other: Counter[_S]) -> Counter[_T | _S]: ... # type: ignore[override] def __pos__(self) -> Counter[_T]: ... def __neg__(self) -> Counter[_T]: ... - def __iadd__(self, other: Counter[_T]) -> Counter[_T]: ... - def __isub__(self, other: Counter[_T]) -> Counter[_T]: ... - def __iand__(self, other: Counter[_T]) -> Counter[_T]: ... - def __ior__(self, other: Counter[_T]) -> Counter[_T]: ... # type: ignore[override] + # several type: ignores because __iadd__ is supposedly incompatible with __add__, etc. + def __iadd__(self: Self, other: Counter[_T]) -> Self: ... # type: ignore[misc] + def __isub__(self: Self, other: Counter[_T]) -> Self: ... + def __iand__(self: Self, other: Counter[_T]) -> Self: ... + def __ior__(self: Self, other: Counter[_T]) -> Self: ... # type: ignore[override,misc] if sys.version_info >= (3, 10): def total(self) -> int: ... + def __le__(self, other: Counter[Any]) -> bool: ... + def __lt__(self, other: Counter[Any]) -> bool: ... + def __ge__(self, other: Counter[Any]) -> bool: ... + def __gt__(self, other: Counter[Any]) -> bool: ... @final class _OrderedDictKeysView(dict_keys[_KT_co, _VT_co], Reversible[_KT_co]): # type: ignore[misc] @@ -276,39 +322,52 @@ class OrderedDict(dict[_KT, _VT], Reversible[_KT], Generic[_KT, _VT]): def keys(self) -> _OrderedDictKeysView[_KT, _VT]: ... def items(self) -> _OrderedDictItemsView[_KT, _VT]: ... def values(self) -> _OrderedDictValuesView[_KT, _VT]: ... - # `fromkeys` is actually inherited from `dict` at runtime, so the signature should be kept in line with `dict.fromkeys`. - # Ideally we would not redefine it here, but the true signature of `dict.fromkeys` is not expressable in the current type system. + # The signature of OrderedDict.fromkeys should be kept in line with `dict.fromkeys`, modulo positional-only differences. + # Like dict.fromkeys, its true signature is not expressible in the current type system. # See #3800 & https://github.com/python/typing/issues/548#issuecomment-683336963. @classmethod @overload - def fromkeys(cls, __iterable: Iterable[_T], __value: None = ...) -> OrderedDict[_T, Any | None]: ... + def fromkeys(cls, iterable: Iterable[_T], value: None = ...) -> OrderedDict[_T, Any | None]: ... @classmethod @overload - def fromkeys(cls, __iterable: Iterable[_T], __value: _S) -> OrderedDict[_T, _S]: ... + def fromkeys(cls, iterable: Iterable[_T], value: _S) -> OrderedDict[_T, _S]: ... + # Keep OrderedDict.setdefault in line with MutableMapping.setdefault, modulo positional-only differences. + @overload + def setdefault(self: OrderedDict[_KT, _T | None], key: _KT) -> _T | None: ... + @overload + def setdefault(self, key: _KT, default: _VT) -> _VT: ... class defaultdict(dict[_KT, _VT], Generic[_KT, _VT]): default_factory: Callable[[], _VT] | None @overload - def __init__(self, **kwargs: _VT) -> None: ... + def __init__(self: defaultdict[_KT, _VT]) -> None: ... + @overload + def __init__(self: defaultdict[str, _VT], **kwargs: _VT) -> None: ... @overload def __init__(self, __default_factory: Callable[[], _VT] | None) -> None: ... @overload - def __init__(self, __default_factory: Callable[[], _VT] | None, **kwargs: _VT) -> None: ... + def __init__(self: defaultdict[str, _VT], __default_factory: Callable[[], _VT] | None, **kwargs: _VT) -> None: ... @overload def __init__(self, __default_factory: Callable[[], _VT] | None, __map: SupportsKeysAndGetItem[_KT, _VT]) -> None: ... @overload def __init__( - self, __default_factory: Callable[[], _VT] | None, __map: SupportsKeysAndGetItem[_KT, _VT], **kwargs: _VT + self: defaultdict[str, _VT], + __default_factory: Callable[[], _VT] | None, + __map: SupportsKeysAndGetItem[str, _VT], + **kwargs: _VT, ) -> None: ... @overload def __init__(self, __default_factory: Callable[[], _VT] | None, __iterable: Iterable[tuple[_KT, _VT]]) -> None: ... @overload def __init__( - self, __default_factory: Callable[[], _VT] | None, __iterable: Iterable[tuple[_KT, _VT]], **kwargs: _VT + self: defaultdict[str, _VT], + __default_factory: Callable[[], _VT] | None, + __iterable: Iterable[tuple[str, _VT]], + **kwargs: _VT, ) -> None: ... def __missing__(self, __key: _KT) -> _VT: ... - def __copy__(self: _S) -> _S: ... - def copy(self: _S) -> _S: ... + def __copy__(self: Self) -> Self: ... + def copy(self: Self) -> Self: ... class ChainMap(MutableMapping[_KT, _VT], Generic[_KT, _VT]): maps: list[MutableMapping[_KT, _VT]] @@ -316,18 +375,21 @@ class ChainMap(MutableMapping[_KT, _VT], Generic[_KT, _VT]): def new_child(self: Self, m: MutableMapping[_KT, _VT] | None = ...) -> Self: ... @property def parents(self: Self) -> Self: ... - def __setitem__(self, k: _KT, v: _VT) -> None: ... - def __delitem__(self, v: _KT) -> None: ... - def __getitem__(self, k: _KT) -> _VT: ... + def __setitem__(self, key: _KT, value: _VT) -> None: ... + def __delitem__(self, key: _KT) -> None: ... + def __getitem__(self, key: _KT) -> _VT: ... def __iter__(self) -> Iterator[_KT]: ... def __len__(self) -> int: ... + def __contains__(self, key: object) -> bool: ... def __missing__(self, key: _KT) -> _VT: ... # undocumented + def __bool__(self) -> bool: ... def setdefault(self, key: _KT, default: _VT = ...) -> _VT: ... @overload def pop(self, key: _KT) -> _VT: ... @overload def pop(self, key: _KT, default: _VT | _T = ...) -> _VT | _T: ... def copy(self: Self) -> Self: ... + __copy__ = copy # All arguments to `fromkeys` are passed to `dict.fromkeys` at runtime, so the signature should be kept in line with `dict.fromkeys`. @classmethod @overload @@ -335,3 +397,11 @@ class ChainMap(MutableMapping[_KT, _VT], Generic[_KT, _VT]): @classmethod @overload def fromkeys(cls, __iterable: Iterable[_T], __value: _S) -> ChainMap[_T, _S]: ... + if sys.version_info >= (3, 9): + def __or__(self, other: Mapping[_T1, _T2]) -> ChainMap[_KT | _T1, _VT | _T2]: ... + def __ror__(self, other: Mapping[_T1, _T2]) -> ChainMap[_KT | _T1, _VT | _T2]: ... + # ChainMap.__ior__ should be kept roughly in line with MutableMapping.update() + @overload # type: ignore[misc] + def __ior__(self: Self, other: SupportsKeysAndGetItem[_KT, _VT]) -> Self: ... + @overload + def __ior__(self: Self, other: Iterable[tuple[_KT, _VT]]) -> Self: ... diff --git a/mypy/typeshed/stdlib/colorsys.pyi b/mypy/typeshed/stdlib/colorsys.pyi index 00c5f9d22cb12..443ee828ebfe7 100644 --- a/mypy/typeshed/stdlib/colorsys.pyi +++ b/mypy/typeshed/stdlib/colorsys.pyi @@ -1,3 +1,5 @@ +__all__ = ["rgb_to_yiq", "yiq_to_rgb", "rgb_to_hls", "hls_to_rgb", "rgb_to_hsv", "hsv_to_rgb"] + def rgb_to_yiq(r: float, g: float, b: float) -> tuple[float, float, float]: ... def yiq_to_rgb(y: float, i: float, q: float) -> tuple[float, float, float]: ... def rgb_to_hls(r: float, g: float, b: float) -> tuple[float, float, float]: ... diff --git a/mypy/typeshed/stdlib/compileall.pyi b/mypy/typeshed/stdlib/compileall.pyi index 64b4dc2bc5f7a..7101fd05f717a 100644 --- a/mypy/typeshed/stdlib/compileall.pyi +++ b/mypy/typeshed/stdlib/compileall.pyi @@ -5,6 +5,8 @@ from typing import Any, Protocol if sys.version_info >= (3, 7): from py_compile import PycInvalidationMode +__all__ = ["compile_dir", "compile_file", "compile_path"] + class _SupportsSearch(Protocol): def search(self, string: str) -> Any: ... diff --git a/mypy/typeshed/stdlib/concurrent/futures/__init__.pyi b/mypy/typeshed/stdlib/concurrent/futures/__init__.pyi index f3b54e54228cc..dbf8ea3df8572 100644 --- a/mypy/typeshed/stdlib/concurrent/futures/__init__.pyi +++ b/mypy/typeshed/stdlib/concurrent/futures/__init__.pyi @@ -1,5 +1,21 @@ import sys +if sys.version_info >= (3, 7): + __all__ = ( + "FIRST_COMPLETED", + "FIRST_EXCEPTION", + "ALL_COMPLETED", + "CancelledError", + "TimeoutError", + "BrokenExecutor", + "Future", + "Executor", + "wait", + "as_completed", + "ProcessPoolExecutor", + "ThreadPoolExecutor", + ) + from ._base import ( ALL_COMPLETED as ALL_COMPLETED, FIRST_COMPLETED as FIRST_COMPLETED, diff --git a/mypy/typeshed/stdlib/concurrent/futures/_base.pyi b/mypy/typeshed/stdlib/concurrent/futures/_base.pyi index b55351aacc6f2..4967d01f90dc3 100644 --- a/mypy/typeshed/stdlib/concurrent/futures/_base.pyi +++ b/mypy/typeshed/stdlib/concurrent/futures/_base.pyi @@ -4,8 +4,9 @@ from _typeshed import Self from abc import abstractmethod from collections.abc import Container, Iterable, Iterator, Sequence from logging import Logger +from types import TracebackType from typing import Any, Callable, Generic, Protocol, TypeVar, overload -from typing_extensions import Literal, SupportsIndex +from typing_extensions import Literal, ParamSpec, SupportsIndex if sys.version_info >= (3, 9): from types import GenericAlias @@ -33,8 +34,8 @@ if sys.version_info >= (3, 7): class BrokenExecutor(RuntimeError): ... _T = TypeVar("_T") - _T_co = TypeVar("_T_co", covariant=True) +_P = ParamSpec("_P") # Copied over Collection implementation as it does not exist in Python 2 and <3.6. # Also to solve pytype issues with _Collection. @@ -60,9 +61,10 @@ class Future(Generic[_T]): class Executor: if sys.version_info >= (3, 9): - def submit(self, __fn: Callable[..., _T], *args: Any, **kwargs: Any) -> Future[_T]: ... + def submit(self, __fn: Callable[_P, _T], *args: _P.args, **kwargs: _P.kwargs) -> Future[_T]: ... else: - def submit(self, fn: Callable[..., _T], *args: Any, **kwargs: Any) -> Future[_T]: ... + def submit(self, fn: Callable[_P, _T], *args: _P.args, **kwargs: _P.kwargs) -> Future[_T]: ... + def map( self, fn: Callable[..., _T], *iterables: Iterable[Any], timeout: float | None = ..., chunksize: int = ... ) -> Iterator[_T]: ... @@ -70,21 +72,28 @@ class Executor: def shutdown(self, wait: bool = ..., *, cancel_futures: bool = ...) -> None: ... else: def shutdown(self, wait: bool = ...) -> None: ... + def __enter__(self: Self) -> Self: ... - def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> bool | None: ... + def __exit__( + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> bool | None: ... def as_completed(fs: Iterable[Future[_T]], timeout: float | None = ...) -> Iterator[Future[_T]]: ... # Ideally this would be a namedtuple, but mypy doesn't support generic tuple types. See #1976 class DoneAndNotDoneFutures(Sequence[set[Future[_T]]]): - done: set[Future[_T]] - not_done: set[Future[_T]] + if sys.version_info >= (3, 10): + __match_args__ = ("done", "not_done") + @property + def done(self) -> set[Future[_T]]: ... + @property + def not_done(self) -> set[Future[_T]]: ... def __new__(_cls, done: set[Future[_T]], not_done: set[Future[_T]]) -> DoneAndNotDoneFutures[_T]: ... def __len__(self) -> int: ... @overload - def __getitem__(self, i: SupportsIndex) -> set[Future[_T]]: ... + def __getitem__(self, __i: SupportsIndex) -> set[Future[_T]]: ... @overload - def __getitem__(self, s: slice) -> DoneAndNotDoneFutures[_T]: ... + def __getitem__(self, __s: slice) -> DoneAndNotDoneFutures[_T]: ... def wait(fs: Iterable[Future[_T]], timeout: float | None = ..., return_when: str = ...) -> DoneAndNotDoneFutures[_T]: ... @@ -121,4 +130,4 @@ class _AcquireFutures: futures: Iterable[Future[Any]] def __init__(self, futures: Iterable[Future[Any]]) -> None: ... def __enter__(self) -> None: ... - def __exit__(self, *args: Any) -> None: ... + def __exit__(self, *args: object) -> None: ... diff --git a/mypy/typeshed/stdlib/concurrent/futures/process.pyi b/mypy/typeshed/stdlib/concurrent/futures/process.pyi index 6435901a8f13c..0c6c403949adb 100644 --- a/mypy/typeshed/stdlib/concurrent/futures/process.pyi +++ b/mypy/typeshed/stdlib/concurrent/futures/process.pyi @@ -31,7 +31,6 @@ _MAX_WINDOWS_WORKERS: int class _RemoteTraceback(Exception): tb: str def __init__(self, tb: TracebackType) -> None: ... - def __str__(self) -> str: ... class _ExceptionWithTraceback: exc: BaseException @@ -82,6 +81,7 @@ if sys.version_info >= (3, 7): def __init__( self, max_size: int | None = ..., *, ctx: BaseContext, pending_work_items: dict[int, _WorkItem[Any]] ) -> None: ... + def _on_queue_feeder_error(self, e: Exception, obj: _CallItem) -> None: ... def _get_chunks(*iterables: Any, chunksize: int) -> Generator[tuple[Any, ...], None, None]: ... @@ -131,6 +131,7 @@ def _chain_from_iterable_of_lists(iterable: Iterable[MutableSequence[Any]]) -> A if sys.version_info >= (3, 7): from ._base import BrokenExecutor + class BrokenProcessPool(BrokenExecutor): ... else: @@ -164,4 +165,5 @@ class ProcessPoolExecutor(Executor): def __init__(self, max_workers: int | None = ...) -> None: ... if sys.version_info >= (3, 9): def _start_executor_manager_thread(self) -> None: ... + def _adjust_process_count(self) -> None: ... diff --git a/mypy/typeshed/stdlib/concurrent/futures/thread.pyi b/mypy/typeshed/stdlib/concurrent/futures/thread.pyi index f27c43c3403ca..46ca681c54fc6 100644 --- a/mypy/typeshed/stdlib/concurrent/futures/thread.pyi +++ b/mypy/typeshed/stdlib/concurrent/futures/thread.pyi @@ -41,6 +41,7 @@ else: if sys.version_info >= (3, 7): from ._base import BrokenExecutor + class BrokenThreadPool(BrokenExecutor): ... class ThreadPoolExecutor(Executor): @@ -67,6 +68,7 @@ class ThreadPoolExecutor(Executor): ) -> None: ... else: def __init__(self, max_workers: int | None = ..., thread_name_prefix: str = ...) -> None: ... + def _adjust_thread_count(self) -> None: ... if sys.version_info >= (3, 7): def _initializer_failed(self) -> None: ... diff --git a/mypy/typeshed/stdlib/configparser.pyi b/mypy/typeshed/stdlib/configparser.pyi index dc81cb78577a8..55df2ce58de70 100644 --- a/mypy/typeshed/stdlib/configparser.pyi +++ b/mypy/typeshed/stdlib/configparser.pyi @@ -1,9 +1,33 @@ import sys from _typeshed import StrOrBytesPath, StrPath, SupportsWrite from collections.abc import Callable, ItemsView, Iterable, Iterator, Mapping, MutableMapping, Sequence -from typing import Any, ClassVar, Optional, Pattern, Type, TypeVar, overload +from typing import Any, ClassVar, Pattern, TypeVar, overload from typing_extensions import Literal +__all__ = [ + "NoSectionError", + "DuplicateOptionError", + "DuplicateSectionError", + "NoOptionError", + "InterpolationError", + "InterpolationDepthError", + "InterpolationMissingOptionError", + "InterpolationSyntaxError", + "ParsingError", + "MissingSectionHeaderError", + "ConfigParser", + "SafeConfigParser", + "RawConfigParser", + "Interpolation", + "BasicInterpolation", + "ExtendedInterpolation", + "LegacyInterpolation", + "SectionProxy", + "ConverterMapping", + "DEFAULTSECT", + "MAX_INTERPOLATION_DEPTH", +] + # Internal type aliases _section = Mapping[str, str] _parser = MutableMapping[str, _section] @@ -16,8 +40,8 @@ if sys.version_info >= (3, 7): else: _Path = StrPath -DEFAULTSECT: str -MAX_INTERPOLATION_DEPTH: int +DEFAULTSECT: Literal["DEFAULT"] +MAX_INTERPOLATION_DEPTH: Literal[10] class Interpolation: def before_get(self, parser: _parser, section: str, option: str, value: str, defaults: _section) -> str: ... @@ -47,7 +71,7 @@ class RawConfigParser(_parser): def __init__( self, defaults: Mapping[str, str | None] | None = ..., - dict_type: Type[Mapping[str, str]] = ..., + dict_type: type[Mapping[str, str]] = ..., allow_no_value: Literal[True] = ..., *, delimiters: Sequence[str] = ..., @@ -63,7 +87,7 @@ class RawConfigParser(_parser): def __init__( self, defaults: _section | None = ..., - dict_type: Type[Mapping[str, str]] = ..., + dict_type: type[Mapping[str, str]] = ..., allow_no_value: bool = ..., *, delimiters: Sequence[str] = ..., @@ -76,10 +100,11 @@ class RawConfigParser(_parser): converters: _converters = ..., ) -> None: ... def __len__(self) -> int: ... - def __getitem__(self, section: str) -> SectionProxy: ... - def __setitem__(self, section: str, options: _section) -> None: ... - def __delitem__(self, section: str) -> None: ... + def __getitem__(self, key: str) -> SectionProxy: ... + def __setitem__(self, key: str, value: _section) -> None: ... + def __delitem__(self, key: str) -> None: ... def __iter__(self) -> Iterator[str]: ... + def __contains__(self, key: object) -> bool: ... def defaults(self) -> _section: ... def sections(self) -> list[str]: ... def add_section(self, section: str) -> None: ... @@ -138,8 +163,8 @@ class RawConfigParser(_parser): class ConfigParser(RawConfigParser): ... -if sys.version_info < (3, 11): - class SafeConfigParser(ConfigParser): ... +if sys.version_info < (3, 12): + class SafeConfigParser(ConfigParser): ... # deprecated alias class SectionProxy(MutableMapping[str, str]): def __init__(self, parser: RawConfigParser, name: str) -> None: ... @@ -180,7 +205,7 @@ class SectionProxy(MutableMapping[str, str]): # SectionProxy can have arbitrary attributes when custom converters are used def __getattr__(self, key: str) -> Callable[..., Any]: ... -class ConverterMapping(MutableMapping[str, Optional[_converter]]): +class ConverterMapping(MutableMapping[str, _converter | None]): GETTERCRE: Pattern[Any] def __init__(self, parser: RawConfigParser) -> None: ... def __getitem__(self, key: str) -> _converter: ... diff --git a/mypy/typeshed/stdlib/contextlib.pyi b/mypy/typeshed/stdlib/contextlib.pyi index b536c36678a26..a60f8811e0acc 100644 --- a/mypy/typeshed/stdlib/contextlib.pyi +++ b/mypy/typeshed/stdlib/contextlib.pyi @@ -1,7 +1,7 @@ import sys from _typeshed import Self, StrOrBytesPath from types import TracebackType -from typing import ( +from typing import ( # noqa: Y027 IO, Any, AsyncGenerator, @@ -12,27 +12,85 @@ from typing import ( Generator, Generic, Iterator, - Optional, Protocol, - Type, TypeVar, overload, ) from typing_extensions import ParamSpec +if sys.version_info >= (3, 11): + __all__ = [ + "asynccontextmanager", + "contextmanager", + "closing", + "nullcontext", + "AbstractContextManager", + "AbstractAsyncContextManager", + "AsyncExitStack", + "ContextDecorator", + "ExitStack", + "redirect_stdout", + "redirect_stderr", + "suppress", + "aclosing", + "chdir", + ] +elif sys.version_info >= (3, 10): + __all__ = [ + "asynccontextmanager", + "contextmanager", + "closing", + "nullcontext", + "AbstractContextManager", + "AbstractAsyncContextManager", + "AsyncExitStack", + "ContextDecorator", + "ExitStack", + "redirect_stdout", + "redirect_stderr", + "suppress", + "aclosing", + ] +elif sys.version_info >= (3, 7): + __all__ = [ + "asynccontextmanager", + "contextmanager", + "closing", + "nullcontext", + "AbstractContextManager", + "AbstractAsyncContextManager", + "AsyncExitStack", + "ContextDecorator", + "ExitStack", + "redirect_stdout", + "redirect_stderr", + "suppress", + ] +else: + __all__ = [ + "contextmanager", + "closing", + "AbstractContextManager", + "ContextDecorator", + "ExitStack", + "redirect_stdout", + "redirect_stderr", + "suppress", + ] + AbstractContextManager = ContextManager if sys.version_info >= (3, 7): - from typing import AsyncContextManager + from typing import AsyncContextManager # noqa: Y022 AbstractAsyncContextManager = AsyncContextManager _T = TypeVar("_T") _T_co = TypeVar("_T_co", covariant=True) -_T_io = TypeVar("_T_io", bound=Optional[IO[str]]) +_T_io = TypeVar("_T_io", bound=IO[str] | None) _F = TypeVar("_F", bound=Callable[..., Any]) _P = ParamSpec("_P") -_ExitFunc = Callable[[Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType]], bool] +_ExitFunc = Callable[[type[BaseException] | None, BaseException | None, TracebackType | None], bool | None] _CM_EF = TypeVar("_CM_EF", AbstractContextManager[Any], _ExitFunc) class ContextDecorator: @@ -47,13 +105,18 @@ class _GeneratorContextManager(AbstractContextManager[_T_co], ContextDecorator, func: Callable[..., Generator[_T_co, Any, Any]] args: tuple[Any, ...] kwds: dict[str, Any] + def __exit__( + self, typ: type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None + ) -> bool | None: ... def contextmanager(func: Callable[_P, Iterator[_T_co]]) -> Callable[_P, _GeneratorContextManager[_T_co]]: ... if sys.version_info >= (3, 10): _AF = TypeVar("_AF", bound=Callable[..., Awaitable[Any]]) + class AsyncContextDecorator: def __call__(self, func: _AF) -> _AF: ... + class _AsyncGeneratorContextManager(AbstractAsyncContextManager[_T_co], AsyncContextDecorator, Generic[_T_co]): # __init__ and these attributes are actually defined in the base class _GeneratorContextManagerBase, # which is more trouble than it's worth to include in the stub (see #6676) @@ -62,6 +125,9 @@ if sys.version_info >= (3, 10): func: Callable[..., AsyncGenerator[_T_co, Any]] args: tuple[Any, ...] kwds: dict[str, Any] + async def __aexit__( + self, typ: type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None + ) -> bool | None: ... elif sys.version_info >= (3, 7): class _AsyncGeneratorContextManager(AbstractAsyncContextManager[_T_co], Generic[_T_co]): @@ -70,6 +136,9 @@ elif sys.version_info >= (3, 7): func: Callable[..., AsyncGenerator[_T_co, Any]] args: tuple[Any, ...] kwds: dict[str, Any] + async def __aexit__( + self, typ: type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None + ) -> bool | None: ... if sys.version_info >= (3, 7): def asynccontextmanager(func: Callable[_P, AsyncIterator[_T_co]]) -> Callable[_P, _AsyncGeneratorContextManager[_T_co]]: ... @@ -81,56 +150,64 @@ _SupportsCloseT = TypeVar("_SupportsCloseT", bound=_SupportsClose) class closing(AbstractContextManager[_SupportsCloseT]): def __init__(self, thing: _SupportsCloseT) -> None: ... + def __exit__(self, *exc_info: object) -> None: ... if sys.version_info >= (3, 10): class _SupportsAclose(Protocol): def aclose(self) -> Awaitable[object]: ... _SupportsAcloseT = TypeVar("_SupportsAcloseT", bound=_SupportsAclose) + class aclosing(AbstractAsyncContextManager[_SupportsAcloseT]): def __init__(self, thing: _SupportsAcloseT) -> None: ... + async def __aexit__(self, *exc_info: object) -> None: ... class suppress(AbstractContextManager[None]): - def __init__(self, *exceptions: Type[BaseException]) -> None: ... + def __init__(self, *exceptions: type[BaseException]) -> None: ... def __exit__( - self, exctype: Type[BaseException] | None, excinst: BaseException | None, exctb: TracebackType | None + self, exctype: type[BaseException] | None, excinst: BaseException | None, exctb: TracebackType | None ) -> bool: ... -class redirect_stdout(AbstractContextManager[_T_io]): +class _RedirectStream(AbstractContextManager[_T_io]): def __init__(self, new_target: _T_io) -> None: ... + def __exit__( + self, exctype: type[BaseException] | None, excinst: BaseException | None, exctb: TracebackType | None + ) -> None: ... -class redirect_stderr(AbstractContextManager[_T_io]): - def __init__(self, new_target: _T_io) -> None: ... +class redirect_stdout(_RedirectStream[_T_io]): ... +class redirect_stderr(_RedirectStream[_T_io]): ... class ExitStack(AbstractContextManager[ExitStack]): def __init__(self) -> None: ... def enter_context(self, cm: AbstractContextManager[_T]) -> _T: ... def push(self, exit: _CM_EF) -> _CM_EF: ... - def callback(self, __callback: Callable[..., Any], *args: Any, **kwds: Any) -> Callable[..., Any]: ... + def callback(self, __callback: Callable[_P, _T], *args: _P.args, **kwds: _P.kwargs) -> Callable[_P, _T]: ... def pop_all(self: Self) -> Self: ... def close(self) -> None: ... def __enter__(self: Self) -> Self: ... def __exit__( - self, __exc_type: Type[BaseException] | None, __exc_value: BaseException | None, __traceback: TracebackType | None + self, __exc_type: type[BaseException] | None, __exc_value: BaseException | None, __traceback: TracebackType | None ) -> bool: ... if sys.version_info >= (3, 7): - _ExitCoroFunc = Callable[[Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType]], Awaitable[bool]] - _CallbackCoroFunc = Callable[..., Awaitable[Any]] + _ExitCoroFunc = Callable[[type[BaseException] | None, BaseException | None, TracebackType | None], Awaitable[bool]] _ACM_EF = TypeVar("_ACM_EF", AbstractAsyncContextManager[Any], _ExitCoroFunc) + class AsyncExitStack(AbstractAsyncContextManager[AsyncExitStack]): def __init__(self) -> None: ... def enter_context(self, cm: AbstractContextManager[_T]) -> _T: ... - def enter_async_context(self, cm: AbstractAsyncContextManager[_T]) -> Awaitable[_T]: ... + async def enter_async_context(self, cm: AbstractAsyncContextManager[_T]) -> _T: ... def push(self, exit: _CM_EF) -> _CM_EF: ... def push_async_exit(self, exit: _ACM_EF) -> _ACM_EF: ... - def callback(self, __callback: Callable[..., Any], *args: Any, **kwds: Any) -> Callable[..., Any]: ... - def push_async_callback(self, __callback: _CallbackCoroFunc, *args: Any, **kwds: Any) -> _CallbackCoroFunc: ... + def callback(self, __callback: Callable[_P, _T], *args: _P.args, **kwds: _P.kwargs) -> Callable[_P, _T]: ... + def push_async_callback( + self, __callback: Callable[_P, Awaitable[_T]], *args: _P.args, **kwds: _P.kwargs + ) -> Callable[_P, Awaitable[_T]]: ... def pop_all(self: Self) -> Self: ... - def aclose(self) -> Awaitable[None]: ... - def __aenter__(self: Self) -> Awaitable[Self]: ... - def __aexit__( - self, __exc_type: Type[BaseException] | None, __exc_value: BaseException | None, __traceback: TracebackType | None - ) -> Awaitable[bool]: ... + async def aclose(self) -> None: ... + async def __aenter__(self: Self) -> Self: ... + async def __aexit__( + self, __exc_type: type[BaseException] | None, __exc_value: BaseException | None, __traceback: TracebackType | None + ) -> bool: ... if sys.version_info >= (3, 10): class nullcontext(AbstractContextManager[_T], AbstractAsyncContextManager[_T]): @@ -140,9 +217,9 @@ if sys.version_info >= (3, 10): @overload def __init__(self: nullcontext[_T], enter_result: _T) -> None: ... def __enter__(self) -> _T: ... - def __exit__(self, *exctype: Any) -> None: ... + def __exit__(self, *exctype: object) -> None: ... async def __aenter__(self) -> _T: ... - async def __aexit__(self, *exctype: Any) -> None: ... + async def __aexit__(self, *exctype: object) -> None: ... elif sys.version_info >= (3, 7): class nullcontext(AbstractContextManager[_T]): @@ -152,10 +229,11 @@ elif sys.version_info >= (3, 7): @overload def __init__(self: nullcontext[_T], enter_result: _T) -> None: ... def __enter__(self) -> _T: ... - def __exit__(self, *exctype: Any) -> None: ... + def __exit__(self, *exctype: object) -> None: ... if sys.version_info >= (3, 11): _T_fd_or_any_path = TypeVar("_T_fd_or_any_path", bound=int | StrOrBytesPath) + class chdir(AbstractContextManager[None], Generic[_T_fd_or_any_path]): path: _T_fd_or_any_path def __init__(self, path: _T_fd_or_any_path) -> None: ... diff --git a/mypy/typeshed/stdlib/contextvars.pyi b/mypy/typeshed/stdlib/contextvars.pyi index e97f62188dcb3..6b5661dd69eb6 100644 --- a/mypy/typeshed/stdlib/contextvars.pyi +++ b/mypy/typeshed/stdlib/contextvars.pyi @@ -1,12 +1,17 @@ import sys from typing import Any, Callable, ClassVar, Generic, Iterator, Mapping, TypeVar, overload +from typing_extensions import ParamSpec, final if sys.version_info >= (3, 9): from types import GenericAlias +__all__ = ("Context", "ContextVar", "Token", "copy_context") + _T = TypeVar("_T") _D = TypeVar("_D") +_P = ParamSpec("_P") +@final class ContextVar(Generic[_T]): def __init__(self, name: str, *, default: _T = ...) -> None: ... @property @@ -15,11 +20,12 @@ class ContextVar(Generic[_T]): def get(self) -> _T: ... @overload def get(self, default: _D | _T) -> _D | _T: ... - def set(self, value: _T) -> Token[_T]: ... - def reset(self, token: Token[_T]) -> None: ... + def set(self, __value: _T) -> Token[_T]: ... + def reset(self, __token: Token[_T]) -> None: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... +@final class Token(Generic[_T]): @property def var(self) -> ContextVar[_T]: ... @@ -33,14 +39,15 @@ def copy_context() -> Context: ... # It doesn't make sense to make this generic, because for most Contexts each ContextVar will have # a different value. +@final class Context(Mapping[ContextVar[Any], Any]): def __init__(self) -> None: ... @overload - def get(self, __key: ContextVar[Any]) -> Any | None: ... + def get(self, __key: ContextVar[_T]) -> _T | None: ... @overload - def get(self, __key: ContextVar[Any], __default: Any | None) -> Any: ... - def run(self, callable: Callable[..., _T], *args: Any, **kwargs: Any) -> _T: ... + def get(self, __key: ContextVar[_T], __default: _D) -> _T | _D: ... + def run(self, callable: Callable[_P, _T], *args: _P.args, **kwargs: _P.kwargs) -> _T: ... def copy(self) -> Context: ... - def __getitem__(self, key: ContextVar[Any]) -> Any: ... + def __getitem__(self, __key: ContextVar[_T]) -> _T: ... def __iter__(self) -> Iterator[ContextVar[Any]]: ... def __len__(self) -> int: ... diff --git a/mypy/typeshed/stdlib/copy.pyi b/mypy/typeshed/stdlib/copy.pyi index a5f9420e3811a..b53f418b3930f 100644 --- a/mypy/typeshed/stdlib/copy.pyi +++ b/mypy/typeshed/stdlib/copy.pyi @@ -1,5 +1,7 @@ from typing import Any, TypeVar +__all__ = ["Error", "copy", "deepcopy"] + _T = TypeVar("_T") # None in CPython but non-None in Jython diff --git a/mypy/typeshed/stdlib/copyreg.pyi b/mypy/typeshed/stdlib/copyreg.pyi index 6097670833c0c..4844a8028c5c4 100644 --- a/mypy/typeshed/stdlib/copyreg.pyi +++ b/mypy/typeshed/stdlib/copyreg.pyi @@ -1,18 +1,19 @@ -from typing import Any, Callable, Hashable, Optional, SupportsInt, TypeVar, Union +from typing import Any, Callable, Hashable, SupportsInt, TypeVar, Union -_TypeT = TypeVar("_TypeT", bound=type) -_Reduce = Union[tuple[Callable[..., _TypeT], tuple[Any, ...]], tuple[Callable[..., _TypeT], tuple[Any, ...], Optional[Any]]] +_T = TypeVar("_T") +_Reduce = Union[tuple[Callable[..., _T], tuple[Any, ...]], tuple[Callable[..., _T], tuple[Any, ...], Any | None]] -__all__: list[str] +__all__ = ["pickle", "constructor", "add_extension", "remove_extension", "clear_extension_cache"] def pickle( - ob_type: _TypeT, - pickle_function: Callable[[_TypeT], str | _Reduce[_TypeT]], - constructor_ob: Callable[[_Reduce[_TypeT]], _TypeT] | None = ..., + ob_type: type[_T], + pickle_function: Callable[[_T], str | _Reduce[_T]], + constructor_ob: Callable[[_Reduce[_T]], _T] | None = ..., ) -> None: ... -def constructor(object: Callable[[_Reduce[_TypeT]], _TypeT]) -> None: ... +def constructor(object: Callable[[_Reduce[_T]], _T]) -> None: ... def add_extension(module: Hashable, name: Hashable, code: SupportsInt) -> None: ... def remove_extension(module: Hashable, name: Hashable, code: int) -> None: ... def clear_extension_cache() -> None: ... -dispatch_table: dict[type, Callable[[type], str | _Reduce[type]]] # undocumented +_DispatchTableType = dict[type, Callable[[Any], str | _Reduce[Any]]] # imported by multiprocessing.reduction +dispatch_table: _DispatchTableType # undocumented diff --git a/mypy/typeshed/stdlib/crypt.pyi b/mypy/typeshed/stdlib/crypt.pyi index a8342859e7700..5083f1eebeed3 100644 --- a/mypy/typeshed/stdlib/crypt.pyi +++ b/mypy/typeshed/stdlib/crypt.pyi @@ -15,4 +15,5 @@ if sys.platform != "win32": def mksalt(method: _Method | None = ..., *, rounds: int | None = ...) -> str: ... else: def mksalt(method: _Method | None = ...) -> str: ... + def crypt(word: str, salt: str | _Method | None = ...) -> str: ... diff --git a/mypy/typeshed/stdlib/csv.pyi b/mypy/typeshed/stdlib/csv.pyi index 63999be059f66..dcb3f19bebe18 100644 --- a/mypy/typeshed/stdlib/csv.pyi +++ b/mypy/typeshed/stdlib/csv.pyi @@ -6,6 +6,7 @@ from _csv import ( QUOTE_NONNUMERIC as QUOTE_NONNUMERIC, Dialect as Dialect, Error as Error, + __version__ as __version__, _DialectLike, _reader, _writer, @@ -17,14 +18,39 @@ from _csv import ( unregister_dialect as unregister_dialect, writer as writer, ) +from _typeshed import Self from collections.abc import Collection, Iterable, Iterator, Mapping, Sequence -from typing import Any, Generic, Type, TypeVar, overload +from typing import Any, Generic, TypeVar, overload if sys.version_info >= (3, 8): from builtins import dict as _DictReadMapping else: from collections import OrderedDict as _DictReadMapping +__all__ = [ + "QUOTE_MINIMAL", + "QUOTE_ALL", + "QUOTE_NONNUMERIC", + "QUOTE_NONE", + "Error", + "Dialect", + "__doc__", + "excel", + "excel_tab", + "field_size_limit", + "reader", + "writer", + "register_dialect", + "get_dialect", + "list_dialects", + "Sniffer", + "unregister_dialect", + "__version__", + "DictReader", + "DictWriter", + "unix_dialect", +] + _T = TypeVar("_T") class excel(Dialect): @@ -75,7 +101,7 @@ class DictReader(Generic[_T], Iterator[_DictReadMapping[_T, str]]): *args: Any, **kwds: Any, ) -> None: ... - def __iter__(self) -> DictReader[_T]: ... + def __iter__(self: Self) -> Self: ... def __next__(self) -> _DictReadMapping[_T, str]: ... class DictWriter(Generic[_T]): @@ -97,11 +123,12 @@ class DictWriter(Generic[_T]): def writeheader(self) -> Any: ... else: def writeheader(self) -> None: ... + def writerow(self, rowdict: Mapping[_T, Any]) -> Any: ... def writerows(self, rowdicts: Iterable[Mapping[_T, Any]]) -> None: ... class Sniffer: preferred: list[str] def __init__(self) -> None: ... - def sniff(self, sample: str, delimiters: str | None = ...) -> Type[Dialect]: ... + def sniff(self, sample: str, delimiters: str | None = ...) -> type[Dialect]: ... def has_header(self, sample: str) -> bool: ... diff --git a/mypy/typeshed/stdlib/ctypes/__init__.pyi b/mypy/typeshed/stdlib/ctypes/__init__.pyi index 7f2eba011d0fd..4a03886e8dd25 100644 --- a/mypy/typeshed/stdlib/ctypes/__init__.pyi +++ b/mypy/typeshed/stdlib/ctypes/__init__.pyi @@ -1,21 +1,7 @@ import sys -from _typeshed import ReadableBuffer, WriteableBuffer +from _typeshed import ReadableBuffer, Self, WriteableBuffer from abc import abstractmethod -from typing import ( - Any, - Callable, - ClassVar, - Generic, - Iterable, - Iterator, - Mapping, - Optional, - Sequence, - Type, - TypeVar, - Union as _UnionT, - overload, -) +from typing import Any, Callable, ClassVar, Generic, Iterable, Iterator, Mapping, Sequence, TypeVar, Union as _UnionT, overload if sys.version_info >= (3, 9): from types import GenericAlias @@ -33,7 +19,7 @@ class CDLL: _func_restype_: ClassVar[_CData] _name: str _handle: int - _FuncPtr: Type[_FuncPointer] + _FuncPtr: type[_FuncPointer] if sys.version_info >= (3, 8): def __init__( self, @@ -48,8 +34,9 @@ class CDLL: def __init__( self, name: str | None, mode: int = ..., handle: int | None = ..., use_errno: bool = ..., use_last_error: bool = ... ) -> None: ... + def __getattr__(self, name: str) -> _NamedFuncPointer: ... - def __getitem__(self, name: str) -> _NamedFuncPointer: ... + def __getitem__(self, name_or_ordinal: str) -> _NamedFuncPointer: ... if sys.platform == "win32": class OleDLL(CDLL): ... @@ -58,7 +45,7 @@ if sys.platform == "win32": class PyDLL(CDLL): ... class LibraryLoader(Generic[_DLLT]): - def __init__(self, dlltype: Type[_DLLT]) -> None: ... + def __init__(self, dlltype: type[_DLLT]) -> None: ... def __getattr__(self, name: str) -> _DLLT: ... def __getitem__(self, name: str) -> _DLLT: ... def LoadLibrary(self, name: str) -> _DLLT: ... @@ -76,33 +63,33 @@ class _CDataMeta(type): # By default mypy complains about the following two methods, because strictly speaking cls # might not be a Type[_CT]. However this can never actually happen, because the only class that # uses _CDataMeta as its metaclass is _CData. So it's safe to ignore the errors here. - def __mul__(cls: Type[_CT], other: int) -> Type[Array[_CT]]: ... # type: ignore[misc] - def __rmul__(cls: Type[_CT], other: int) -> Type[Array[_CT]]: ... # type: ignore[misc] + def __mul__(cls: type[_CT], other: int) -> type[Array[_CT]]: ... # type: ignore[misc] + def __rmul__(cls: type[_CT], other: int) -> type[Array[_CT]]: ... # type: ignore[misc] class _CData(metaclass=_CDataMeta): _b_base: int _b_needsfree_: bool _objects: Mapping[Any, int] | None @classmethod - def from_buffer(cls: Type[_CT], source: WriteableBuffer, offset: int = ...) -> _CT: ... + def from_buffer(cls: type[Self], source: WriteableBuffer, offset: int = ...) -> Self: ... @classmethod - def from_buffer_copy(cls: Type[_CT], source: ReadableBuffer, offset: int = ...) -> _CT: ... + def from_buffer_copy(cls: type[Self], source: ReadableBuffer, offset: int = ...) -> Self: ... @classmethod - def from_address(cls: Type[_CT], address: int) -> _CT: ... + def from_address(cls: type[Self], address: int) -> Self: ... @classmethod - def from_param(cls: Type[_CT], obj: Any) -> _CT | _CArgObject: ... + def from_param(cls: type[Self], obj: Any) -> Self | _CArgObject: ... @classmethod - def in_dll(cls: Type[_CT], library: CDLL, name: str) -> _CT: ... + def in_dll(cls: type[Self], library: CDLL, name: str) -> Self: ... class _CanCastTo(_CData): ... class _PointerLike(_CanCastTo): ... -_ECT = Callable[[Optional[Type[_CData]], _FuncPointer, tuple[_CData, ...]], _CData] +_ECT = Callable[[type[_CData] | None, _FuncPointer, tuple[_CData, ...]], _CData] _PF = _UnionT[tuple[int], tuple[int, str], tuple[int, str, Any]] class _FuncPointer(_PointerLike, _CData): - restype: Type[_CData] | Callable[[int], Any] | None - argtypes: Sequence[Type[_CData]] + restype: type[_CData] | Callable[[int], Any] | None + argtypes: Sequence[type[_CData]] errcheck: _ECT @overload def __init__(self, address: int) -> None: ... @@ -120,34 +107,34 @@ class _NamedFuncPointer(_FuncPointer): class ArgumentError(Exception): ... def CFUNCTYPE( - restype: Type[_CData] | None, *argtypes: Type[_CData], use_errno: bool = ..., use_last_error: bool = ... -) -> Type[_FuncPointer]: ... + restype: type[_CData] | None, *argtypes: type[_CData], use_errno: bool = ..., use_last_error: bool = ... +) -> type[_FuncPointer]: ... if sys.platform == "win32": def WINFUNCTYPE( - restype: Type[_CData] | None, *argtypes: Type[_CData], use_errno: bool = ..., use_last_error: bool = ... - ) -> Type[_FuncPointer]: ... + restype: type[_CData] | None, *argtypes: type[_CData], use_errno: bool = ..., use_last_error: bool = ... + ) -> type[_FuncPointer]: ... -def PYFUNCTYPE(restype: Type[_CData] | None, *argtypes: Type[_CData]) -> Type[_FuncPointer]: ... +def PYFUNCTYPE(restype: type[_CData] | None, *argtypes: type[_CData]) -> type[_FuncPointer]: ... class _CArgObject: ... # Any type that can be implicitly converted to c_void_p when passed as a C function argument. # (bytes is not included here, see below.) -_CVoidPLike = _UnionT[_PointerLike, Array[Any], _CArgObject, int] +_CVoidPLike = _PointerLike | Array[Any] | _CArgObject | int # Same as above, but including types known to be read-only (i. e. bytes). # This distinction is not strictly necessary (ctypes doesn't differentiate between const # and non-const pointers), but it catches errors like memmove(b'foo', buf, 4) # when memmove(buf, b'foo', 4) was intended. -_CVoidConstPLike = _UnionT[_CVoidPLike, bytes] +_CVoidConstPLike = _CVoidPLike | bytes def addressof(obj: _CData) -> int: ... -def alignment(obj_or_type: _CData | Type[_CData]) -> int: ... +def alignment(obj_or_type: _CData | type[_CData]) -> int: ... def byref(obj: _CData, offset: int = ...) -> _CArgObject: ... _CastT = TypeVar("_CastT", bound=_CanCastTo) -def cast(obj: _CData | _CArgObject | int, typ: Type[_CastT]) -> _CastT: ... +def cast(obj: _CData | _CArgObject | int, typ: type[_CastT]) -> _CastT: ... def create_string_buffer(init: int | bytes, size: int | None = ...) -> Array[c_char]: ... c_buffer = create_string_buffer @@ -165,25 +152,25 @@ def get_errno() -> int: ... if sys.platform == "win32": def get_last_error() -> int: ... -def memmove(dst: _CVoidPLike, src: _CVoidConstPLike, count: int) -> None: ... -def memset(dst: _CVoidPLike, c: int, count: int) -> None: ... -def POINTER(type: Type[_CT]) -> Type[pointer[_CT]]: ... +def memmove(dst: _CVoidPLike, src: _CVoidConstPLike, count: int) -> int: ... +def memset(dst: _CVoidPLike, c: int, count: int) -> int: ... +def POINTER(type: type[_CT]) -> type[pointer[_CT]]: ... # The real ctypes.pointer is a function, not a class. The stub version of pointer behaves like # ctypes._Pointer in that it is the base class for all pointer types. Unlike the real _Pointer, # it can be instantiated directly (to mimic the behavior of the real pointer function). class pointer(Generic[_CT], _PointerLike, _CData): - _type_: Type[_CT] + _type_: type[_CT] contents: _CT def __init__(self, arg: _CT = ...) -> None: ... @overload - def __getitem__(self, i: int) -> _CT: ... + def __getitem__(self, __i: int) -> _CT: ... @overload - def __getitem__(self, s: slice) -> list[_CT]: ... + def __getitem__(self, __s: slice) -> list[_CT]: ... @overload - def __setitem__(self, i: int, o: _CT) -> None: ... + def __setitem__(self, __i: int, __o: _CT) -> None: ... @overload - def __setitem__(self, s: slice, o: Iterable[_CT]) -> None: ... + def __setitem__(self, __s: slice, __o: Iterable[_CT]) -> None: ... def resize(obj: _CData, size: int) -> None: ... def set_errno(value: int) -> int: ... @@ -191,7 +178,7 @@ def set_errno(value: int) -> int: ... if sys.platform == "win32": def set_last_error(value: int) -> int: ... -def sizeof(obj_or_type: _CData | Type[_CData]) -> int: ... +def sizeof(obj_or_type: _CData | type[_CData]) -> int: ... def string_at(address: _CVoidConstPLike, size: int = ...) -> bytes: ... if sys.platform == "win32": @@ -208,7 +195,7 @@ class c_byte(_SimpleCData[int]): ... class c_char(_SimpleCData[bytes]): def __init__(self, value: int | bytes = ...) -> None: ... -class c_char_p(_PointerLike, _SimpleCData[Optional[bytes]]): +class c_char_p(_PointerLike, _SimpleCData[bytes | None]): def __init__(self, value: int | bytes | None = ...) -> None: ... class c_double(_SimpleCData[float]): ... @@ -233,10 +220,10 @@ class c_uint64(_SimpleCData[int]): ... class c_ulong(_SimpleCData[int]): ... class c_ulonglong(_SimpleCData[int]): ... class c_ushort(_SimpleCData[int]): ... -class c_void_p(_PointerLike, _SimpleCData[Optional[int]]): ... +class c_void_p(_PointerLike, _SimpleCData[int | None]): ... class c_wchar(_SimpleCData[str]): ... -class c_wchar_p(_PointerLike, _SimpleCData[Optional[str]]): +class c_wchar_p(_PointerLike, _SimpleCData[str | None]): def __init__(self, value: int | str | None = ...) -> None: ... class c_bool(_SimpleCData[bool]): @@ -252,7 +239,7 @@ class _CField: size: int class _StructUnionMeta(_CDataMeta): - _fields_: Sequence[tuple[str, Type[_CData]] | tuple[str, Type[_CData], int]] + _fields_: Sequence[tuple[str, type[_CData]] | tuple[str, type[_CData], int]] _pack_: int _anonymous_: Sequence[str] def __getattr__(self, name: str) -> _CField: ... @@ -275,9 +262,9 @@ class Array(Generic[_CT], _CData): def _length_(self, value: int) -> None: ... @property @abstractmethod - def _type_(self) -> Type[_CT]: ... + def _type_(self) -> type[_CT]: ... @_type_.setter - def _type_(self, value: Type[_CT]) -> None: ... + def _type_(self, value: type[_CT]) -> None: ... raw: bytes # Note: only available if _CT == c_char value: Any # Note: bytes if _CT == c_char, str if _CT == c_wchar, unavailable otherwise # TODO These methods cannot be annotated correctly at the moment. @@ -294,13 +281,13 @@ class Array(Generic[_CT], _CData): # the array element type would belong are annotated with Any instead. def __init__(self, *args: Any) -> None: ... @overload - def __getitem__(self, i: int) -> Any: ... + def __getitem__(self, __i: int) -> Any: ... @overload - def __getitem__(self, s: slice) -> list[Any]: ... + def __getitem__(self, __s: slice) -> list[Any]: ... @overload - def __setitem__(self, i: int, o: Any) -> None: ... + def __setitem__(self, __i: int, __o: Any) -> None: ... @overload - def __setitem__(self, s: slice, o: Iterable[Any]) -> None: ... + def __setitem__(self, __s: slice, __o: Iterable[Any]) -> None: ... def __iter__(self) -> Iterator[Any]: ... # Can't inherit from Sized because the metaclass conflict between # Sized and _CData prevents using _CDataMeta. diff --git a/mypy/typeshed/stdlib/curses/__init__.pyi b/mypy/typeshed/stdlib/curses/__init__.pyi index aef2d9b95ed5d..ee74c13b6b50f 100644 --- a/mypy/typeshed/stdlib/curses/__init__.pyi +++ b/mypy/typeshed/stdlib/curses/__init__.pyi @@ -2,7 +2,7 @@ import sys from typing import Any, Callable, TypeVar if sys.platform != "win32": - from _curses import * # noqa: F403 + from _curses import * from _curses import _CursesWindow as _CursesWindow _T = TypeVar("_T") @@ -14,4 +14,6 @@ if sys.platform != "win32": # available after calling `curses.start_color()` COLORS: int COLOR_PAIRS: int + # TODO: wait for `Concatenate` support + # def wrapper(__func: Callable[Concatenate[_CursesWindow, _P], _T], *arg: _P.args, **kwds: _P.kwargs) -> _T: ... def wrapper(__func: Callable[..., _T], *arg: Any, **kwds: Any) -> _T: ... diff --git a/mypy/typeshed/stdlib/curses/panel.pyi b/mypy/typeshed/stdlib/curses/panel.pyi index ed13a6e050e94..30803791f0391 100644 --- a/mypy/typeshed/stdlib/curses/panel.pyi +++ b/mypy/typeshed/stdlib/curses/panel.pyi @@ -4,6 +4,7 @@ if sys.platform != "win32": from _curses import _CursesWindow version: str + class _Curses_Panel: # type is (note the space in the class name) def above(self) -> _Curses_Panel: ... def below(self) -> _Curses_Panel: ... @@ -17,6 +18,7 @@ if sys.platform != "win32": def top(self) -> None: ... def userptr(self) -> object: ... def window(self) -> _CursesWindow: ... + def bottom_panel() -> _Curses_Panel: ... def new_panel(__win: _CursesWindow) -> _Curses_Panel: ... def top_panel() -> _Curses_Panel: ... diff --git a/mypy/typeshed/stdlib/curses/textpad.pyi b/mypy/typeshed/stdlib/curses/textpad.pyi index eb68796038537..b8a9c843f4021 100644 --- a/mypy/typeshed/stdlib/curses/textpad.pyi +++ b/mypy/typeshed/stdlib/curses/textpad.pyi @@ -4,6 +4,7 @@ from typing import Callable if sys.platform != "win32": from _curses import _CursesWindow def rectangle(win: _CursesWindow, uly: int, ulx: int, lry: int, lrx: int) -> None: ... + class Textbox: stripspaces: bool def __init__(self, win: _CursesWindow, insert_mode: bool = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/dataclasses.pyi b/mypy/typeshed/stdlib/dataclasses.pyi index 885facb9c0db0..d82e9a2bb5266 100644 --- a/mypy/typeshed/stdlib/dataclasses.pyi +++ b/mypy/typeshed/stdlib/dataclasses.pyi @@ -1,6 +1,9 @@ +import enum import sys import types -from typing import Any, Callable, Generic, Iterable, Mapping, Protocol, Type, TypeVar, overload +from builtins import type as Type # alias to avoid name clashes with fields named "type" +from typing import Any, Callable, Generic, Iterable, Mapping, Protocol, TypeVar, overload +from typing_extensions import Literal if sys.version_info >= (3, 9): from types import GenericAlias @@ -8,9 +11,47 @@ if sys.version_info >= (3, 9): _T = TypeVar("_T") _T_co = TypeVar("_T_co", covariant=True) -class _MISSING_TYPE: ... +if sys.version_info >= (3, 10): + __all__ = [ + "dataclass", + "field", + "Field", + "FrozenInstanceError", + "InitVar", + "KW_ONLY", + "MISSING", + "fields", + "asdict", + "astuple", + "make_dataclass", + "replace", + "is_dataclass", + ] +else: + __all__ = [ + "dataclass", + "field", + "Field", + "FrozenInstanceError", + "InitVar", + "MISSING", + "fields", + "asdict", + "astuple", + "make_dataclass", + "replace", + "is_dataclass", + ] + +# define _MISSING_TYPE as an enum within the type stubs, +# even though that is not really its type at runtime +# this allows us to use Literal[_MISSING_TYPE.MISSING] +# for background, see: +# https://github.com/python/typeshed/pull/5900#issuecomment-895513797 +class _MISSING_TYPE(enum.Enum): + MISSING = enum.auto() -MISSING: _MISSING_TYPE +MISSING = _MISSING_TYPE.MISSING if sys.version_info >= (3, 10): class KW_ONLY: ... @@ -24,11 +65,20 @@ def astuple(obj: Any) -> tuple[Any, ...]: ... @overload def astuple(obj: Any, *, tuple_factory: Callable[[list[Any]], _T]) -> _T: ... -if sys.version_info >= (3, 10): +if sys.version_info >= (3, 8): + # cls argument is now positional-only @overload - def dataclass(__cls: Type[_T]) -> Type[_T]: ... + def dataclass(__cls: type[_T]) -> type[_T]: ... @overload - def dataclass(__cls: None) -> Callable[[Type[_T]], Type[_T]]: ... + def dataclass(__cls: None) -> Callable[[type[_T]], type[_T]]: ... + +else: + @overload + def dataclass(_cls: type[_T]) -> type[_T]: ... + @overload + def dataclass(_cls: None) -> Callable[[type[_T]], type[_T]]: ... + +if sys.version_info >= (3, 10): @overload def dataclass( *, @@ -41,28 +91,13 @@ if sys.version_info >= (3, 10): match_args: bool = ..., kw_only: bool = ..., slots: bool = ..., - ) -> Callable[[Type[_T]], Type[_T]]: ... - -elif sys.version_info >= (3, 8): - # cls argument is now positional-only - @overload - def dataclass(__cls: Type[_T]) -> Type[_T]: ... - @overload - def dataclass(__cls: None) -> Callable[[Type[_T]], Type[_T]]: ... - @overload - def dataclass( - *, init: bool = ..., repr: bool = ..., eq: bool = ..., order: bool = ..., unsafe_hash: bool = ..., frozen: bool = ... - ) -> Callable[[Type[_T]], Type[_T]]: ... + ) -> Callable[[type[_T]], type[_T]]: ... else: - @overload - def dataclass(_cls: Type[_T]) -> Type[_T]: ... - @overload - def dataclass(_cls: None) -> Callable[[Type[_T]], Type[_T]]: ... @overload def dataclass( *, init: bool = ..., repr: bool = ..., eq: bool = ..., order: bool = ..., unsafe_hash: bool = ..., frozen: bool = ... - ) -> Callable[[Type[_T]], Type[_T]]: ... + ) -> Callable[[type[_T]], type[_T]]: ... # See https://github.com/python/mypy/issues/10750 class _DefaultFactory(Protocol[_T_co]): @@ -71,15 +106,15 @@ class _DefaultFactory(Protocol[_T_co]): class Field(Generic[_T]): name: str type: Type[_T] - default: _T - default_factory: _DefaultFactory[_T] + default: _T | Literal[_MISSING_TYPE.MISSING] + default_factory: _DefaultFactory[_T] | Literal[_MISSING_TYPE.MISSING] repr: bool hash: bool | None init: bool compare: bool metadata: types.MappingProxyType[Any, Any] if sys.version_info >= (3, 10): - kw_only: bool + kw_only: bool | Literal[_MISSING_TYPE.MISSING] def __init__( self, default: _T, @@ -102,6 +137,8 @@ class Field(Generic[_T]): compare: bool, metadata: Mapping[Any, Any], ) -> None: ... + + def __set_name__(self, owner: Type[Any], name: str) -> None: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... diff --git a/mypy/typeshed/stdlib/datetime.pyi b/mypy/typeshed/stdlib/datetime.pyi index e0ce085c29670..18a4d2dd28567 100644 --- a/mypy/typeshed/stdlib/datetime.pyi +++ b/mypy/typeshed/stdlib/datetime.pyi @@ -1,13 +1,16 @@ import sys +from _typeshed import Self from time import struct_time -from typing import ClassVar, NamedTuple, NoReturn, SupportsAbs, Type, TypeVar, overload -from typing_extensions import final +from typing import ClassVar, NamedTuple, NoReturn, SupportsAbs, TypeVar, overload +from typing_extensions import Literal, final + +if sys.version_info >= (3, 9): + __all__ = ("date", "datetime", "time", "timedelta", "timezone", "tzinfo", "MINYEAR", "MAXYEAR") -_S = TypeVar("_S") _D = TypeVar("_D", bound=date) -MINYEAR: int -MAXYEAR: int +MINYEAR: Literal[1] +MAXYEAR: Literal[9999] class tzinfo: def tzname(self, __dt: datetime | None) -> str | None: ... @@ -36,19 +39,20 @@ class date: min: ClassVar[date] max: ClassVar[date] resolution: ClassVar[timedelta] - def __new__(cls: Type[_S], year: int, month: int, day: int) -> _S: ... + def __new__(cls: type[Self], year: int, month: int, day: int) -> Self: ... @classmethod - def fromtimestamp(cls: Type[_S], __timestamp: float) -> _S: ... + def fromtimestamp(cls: type[Self], __timestamp: float) -> Self: ... @classmethod - def today(cls: Type[_S]) -> _S: ... + def today(cls: type[Self]) -> Self: ... @classmethod - def fromordinal(cls: Type[_S], __n: int) -> _S: ... + def fromordinal(cls: type[Self], __n: int) -> Self: ... if sys.version_info >= (3, 7): @classmethod - def fromisoformat(cls: Type[_S], __date_string: str) -> _S: ... + def fromisoformat(cls: type[Self], __date_string: str) -> Self: ... if sys.version_info >= (3, 8): @classmethod - def fromisocalendar(cls: Type[_S], year: int, week: int, day: int) -> _S: ... + def fromisocalendar(cls: type[Self], year: int, week: int, day: int) -> Self: ... + @property def year(self) -> int: ... @property @@ -61,16 +65,21 @@ class date: def isoformat(self) -> str: ... def timetuple(self) -> struct_time: ... def toordinal(self) -> int: ... - def replace(self, year: int = ..., month: int = ..., day: int = ...) -> date: ... + if sys.version_info >= (3, 6): + def replace(self: Self, year: int = ..., month: int = ..., day: int = ...) -> Self: ... + else: + # Prior to Python 3.6, the `replace` method always returned `date`, even in subclasses + def replace(self, year: int = ..., month: int = ..., day: int = ...) -> date: ... + def __le__(self, __other: date) -> bool: ... def __lt__(self, __other: date) -> bool: ... def __ge__(self, __other: date) -> bool: ... def __gt__(self, __other: date) -> bool: ... if sys.version_info >= (3, 8): - def __add__(self: _S, __other: timedelta) -> _S: ... - def __radd__(self: _S, __other: timedelta) -> _S: ... + def __add__(self: Self, __other: timedelta) -> Self: ... + def __radd__(self: Self, __other: timedelta) -> Self: ... @overload - def __sub__(self: _D, __other: timedelta) -> _D: ... + def __sub__(self: Self, __other: timedelta) -> Self: ... @overload def __sub__(self, __other: datetime) -> NoReturn: ... @overload @@ -85,6 +94,7 @@ class date: def __sub__(self, __other: datetime) -> NoReturn: ... @overload def __sub__(self, __other: date) -> timedelta: ... + def __hash__(self) -> int: ... def weekday(self) -> int: ... def isoweekday(self) -> int: ... @@ -98,7 +108,7 @@ class time: max: ClassVar[time] resolution: ClassVar[timedelta] def __new__( - cls: Type[_S], + cls: type[Self], hour: int = ..., minute: int = ..., second: int = ..., @@ -106,7 +116,7 @@ class time: tzinfo: _tzinfo | None = ..., *, fold: int = ..., - ) -> _S: ... + ) -> Self: ... @property def hour(self) -> int: ... @property @@ -127,22 +137,36 @@ class time: def isoformat(self, timespec: str = ...) -> str: ... if sys.version_info >= (3, 7): @classmethod - def fromisoformat(cls: Type[_S], __time_string: str) -> _S: ... + def fromisoformat(cls: type[Self], __time_string: str) -> Self: ... + def strftime(self, __format: str) -> str: ... def __format__(self, __fmt: str) -> str: ... def utcoffset(self) -> timedelta | None: ... def tzname(self) -> str | None: ... def dst(self) -> timedelta | None: ... - def replace( - self, - hour: int = ..., - minute: int = ..., - second: int = ..., - microsecond: int = ..., - tzinfo: _tzinfo | None = ..., - *, - fold: int = ..., - ) -> time: ... + if sys.version_info >= (3, 6): + def replace( + self: Self, + hour: int = ..., + minute: int = ..., + second: int = ..., + microsecond: int = ..., + tzinfo: _tzinfo | None = ..., + *, + fold: int = ..., + ) -> Self: ... + else: + # Prior to Python 3.6, the `replace` method always returned `time`, even in subclasses + def replace( + self, + hour: int = ..., + minute: int = ..., + second: int = ..., + microsecond: int = ..., + tzinfo: _tzinfo | None = ..., + *, + fold: int = ..., + ) -> time: ... _date = date _time = time @@ -152,7 +176,7 @@ class timedelta(SupportsAbs[timedelta]): max: ClassVar[timedelta] resolution: ClassVar[timedelta] def __new__( - cls: Type[_S], + cls: type[Self], days: float = ..., seconds: float = ..., microseconds: float = ..., @@ -160,7 +184,7 @@ class timedelta(SupportsAbs[timedelta]): minutes: float = ..., hours: float = ..., weeks: float = ..., - ) -> _S: ... + ) -> Self: ... @property def days(self) -> int: ... @property @@ -199,7 +223,7 @@ class datetime(date): max: ClassVar[datetime] resolution: ClassVar[timedelta] def __new__( - cls: Type[_S], + cls: type[Self], year: int, month: int, day: int, @@ -210,7 +234,7 @@ class datetime(date): tzinfo: _tzinfo | None = ..., *, fold: int = ..., - ) -> _S: ... + ) -> Self: ... @property def hour(self) -> int: ... @property @@ -227,48 +251,67 @@ class datetime(date): # but it is named "timestamp" in the C implementation and "t" in the Python implementation, # so it is only truly *safe* to pass it as a positional argument. @classmethod - def fromtimestamp(cls: Type[_S], __timestamp: float, tz: _tzinfo | None = ...) -> _S: ... + def fromtimestamp(cls: type[Self], __timestamp: float, tz: _tzinfo | None = ...) -> Self: ... @classmethod - def utcfromtimestamp(cls: Type[_S], __t: float) -> _S: ... + def utcfromtimestamp(cls: type[Self], __t: float) -> Self: ... if sys.version_info >= (3, 8): @classmethod - def now(cls: Type[_S], tz: _tzinfo | None = ...) -> _S: ... + def now(cls: type[Self], tz: _tzinfo | None = ...) -> Self: ... else: @overload @classmethod - def now(cls: Type[_S], tz: None = ...) -> _S: ... + def now(cls: type[Self], tz: None = ...) -> Self: ... @overload @classmethod def now(cls, tz: _tzinfo) -> datetime: ... + @classmethod - def utcnow(cls: Type[_S]) -> _S: ... + def utcnow(cls: type[Self]) -> Self: ... @classmethod def combine(cls, date: _date, time: _time, tzinfo: _tzinfo | None = ...) -> datetime: ... if sys.version_info >= (3, 7): @classmethod - def fromisoformat(cls: Type[_S], __date_string: str) -> _S: ... + def fromisoformat(cls: type[Self], __date_string: str) -> Self: ... + def timestamp(self) -> float: ... def utctimetuple(self) -> struct_time: ... def date(self) -> _date: ... def time(self) -> _time: ... def timetz(self) -> _time: ... - def replace( - self, - year: int = ..., - month: int = ..., - day: int = ..., - hour: int = ..., - minute: int = ..., - second: int = ..., - microsecond: int = ..., - tzinfo: _tzinfo | None = ..., - *, - fold: int = ..., - ) -> datetime: ... + if sys.version_info >= (3, 6): + def replace( + self: Self, + year: int = ..., + month: int = ..., + day: int = ..., + hour: int = ..., + minute: int = ..., + second: int = ..., + microsecond: int = ..., + tzinfo: _tzinfo | None = ..., + *, + fold: int = ..., + ) -> Self: ... + else: + # Prior to Python 3.6, the `replace` method always returned `datetime`, even in subclasses + def replace( + self, + year: int = ..., + month: int = ..., + day: int = ..., + hour: int = ..., + minute: int = ..., + second: int = ..., + microsecond: int = ..., + tzinfo: _tzinfo | None = ..., + *, + fold: int = ..., + ) -> datetime: ... if sys.version_info >= (3, 8): - def astimezone(self: _S, tz: _tzinfo | None = ...) -> _S: ... + def astimezone(self: Self, tz: _tzinfo | None = ...) -> Self: ... else: def astimezone(self, tz: _tzinfo | None = ...) -> datetime: ... + def ctime(self) -> str: ... def isoformat(self, sep: str = ..., timespec: str = ...) -> str: ... @classmethod @@ -282,7 +325,7 @@ class datetime(date): def __gt__(self, __other: datetime) -> bool: ... # type: ignore[override] if sys.version_info >= (3, 8): @overload # type: ignore[override] - def __sub__(self: _D, __other: timedelta) -> _D: ... + def __sub__(self: Self, __other: timedelta) -> Self: ... @overload def __sub__(self: _D, __other: _D) -> timedelta: ... else: diff --git a/mypy/typeshed/stdlib/dbm/__init__.pyi b/mypy/typeshed/stdlib/dbm/__init__.pyi index 5ecacd91b4ed8..d43a2415caffc 100644 --- a/mypy/typeshed/stdlib/dbm/__init__.pyi +++ b/mypy/typeshed/stdlib/dbm/__init__.pyi @@ -1,10 +1,12 @@ from _typeshed import Self from types import TracebackType -from typing import Iterator, MutableMapping, Type, Union +from typing import Iterator, MutableMapping from typing_extensions import Literal -_KeyType = Union[str, bytes] -_ValueType = Union[str, bytes] +__all__ = ["open", "whichdb", "error"] + +_KeyType = str | bytes +_ValueType = str | bytes _TFlags = Literal[ "r", "w", @@ -82,12 +84,12 @@ class _Database(MutableMapping[_KeyType, bytes]): def __del__(self) -> None: ... def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> None: ... class _error(Exception): ... -error: tuple[Type[_error], Type[OSError]] +error: tuple[type[_error], type[OSError]] def whichdb(filename: str) -> str: ... def open(file: str, flag: _TFlags = ..., mode: int = ...) -> _Database: ... diff --git a/mypy/typeshed/stdlib/dbm/dumb.pyi b/mypy/typeshed/stdlib/dbm/dumb.pyi index 0a941b0707546..5af95ace72ad8 100644 --- a/mypy/typeshed/stdlib/dbm/dumb.pyi +++ b/mypy/typeshed/stdlib/dbm/dumb.pyi @@ -1,9 +1,11 @@ from _typeshed import Self from types import TracebackType -from typing import Iterator, MutableMapping, Type, Union +from typing import Iterator, MutableMapping -_KeyType = Union[str, bytes] -_ValueType = Union[str, bytes] +__all__ = ["error", "open"] + +_KeyType = str | bytes +_ValueType = str | bytes error = OSError @@ -13,14 +15,14 @@ class _Database(MutableMapping[_KeyType, bytes]): def iterkeys(self) -> Iterator[bytes]: ... # undocumented def close(self) -> None: ... def __getitem__(self, key: _KeyType) -> bytes: ... - def __setitem__(self, key: _KeyType, value: _ValueType) -> None: ... + def __setitem__(self, key: _KeyType, val: _ValueType) -> None: ... def __delitem__(self, key: _KeyType) -> None: ... def __iter__(self) -> Iterator[bytes]: ... def __len__(self) -> int: ... def __del__(self) -> None: ... def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> None: ... def open(file: str, flag: str = ..., mode: int = ...) -> _Database: ... diff --git a/mypy/typeshed/stdlib/dbm/gnu.pyi b/mypy/typeshed/stdlib/dbm/gnu.pyi index 702f62d11b758..9a603228a6916 100644 --- a/mypy/typeshed/stdlib/dbm/gnu.pyi +++ b/mypy/typeshed/stdlib/dbm/gnu.pyi @@ -1,39 +1,39 @@ +import sys from _typeshed import Self from types import TracebackType -from typing import Type, TypeVar, Union, overload +from typing import TypeVar, overload -_T = TypeVar("_T") -_KeyType = Union[str, bytes] -_ValueType = Union[str, bytes] +if sys.platform != "win32": + _T = TypeVar("_T") + _KeyType = str | bytes + _ValueType = str | bytes -open_flags: str + open_flags: str -class error(OSError): ... - -# Actual typename gdbm, not exposed by the implementation -class _gdbm: - def firstkey(self) -> bytes | None: ... - def nextkey(self, key: _KeyType) -> bytes | None: ... - def reorganize(self) -> None: ... - def sync(self) -> None: ... - def close(self) -> None: ... - def __getitem__(self, item: _KeyType) -> bytes: ... - def __setitem__(self, key: _KeyType, value: _ValueType) -> None: ... - def __delitem__(self, key: _KeyType) -> None: ... - def __contains__(self, key: _KeyType) -> bool: ... - def __len__(self) -> int: ... - def __enter__(self: Self) -> Self: ... - def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None - ) -> None: ... - @overload - def get(self, k: _KeyType) -> bytes | None: ... - @overload - def get(self, k: _KeyType, default: bytes | _T) -> bytes | _T: ... - def keys(self) -> list[bytes]: ... - def setdefault(self, k: _KeyType, default: _ValueType = ...) -> bytes: ... - # Don't exist at runtime - __new__: None # type: ignore[assignment] - __init__: None # type: ignore[assignment] - -def open(__filename: str, __flags: str = ..., __mode: int = ...) -> _gdbm: ... + class error(OSError): ... + # Actual typename gdbm, not exposed by the implementation + class _gdbm: + def firstkey(self) -> bytes | None: ... + def nextkey(self, key: _KeyType) -> bytes | None: ... + def reorganize(self) -> None: ... + def sync(self) -> None: ... + def close(self) -> None: ... + def __getitem__(self, item: _KeyType) -> bytes: ... + def __setitem__(self, key: _KeyType, value: _ValueType) -> None: ... + def __delitem__(self, key: _KeyType) -> None: ... + def __contains__(self, key: _KeyType) -> bool: ... + def __len__(self) -> int: ... + def __enter__(self: Self) -> Self: ... + def __exit__( + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> None: ... + @overload + def get(self, k: _KeyType) -> bytes | None: ... + @overload + def get(self, k: _KeyType, default: bytes | _T) -> bytes | _T: ... + def keys(self) -> list[bytes]: ... + def setdefault(self, k: _KeyType, default: _ValueType = ...) -> bytes: ... + # Don't exist at runtime + __new__: None # type: ignore[assignment] + __init__: None # type: ignore[assignment] + def open(__filename: str, __flags: str = ..., __mode: int = ...) -> _gdbm: ... diff --git a/mypy/typeshed/stdlib/dbm/ndbm.pyi b/mypy/typeshed/stdlib/dbm/ndbm.pyi index 7b04c5385dbe6..8405bec2bcf21 100644 --- a/mypy/typeshed/stdlib/dbm/ndbm.pyi +++ b/mypy/typeshed/stdlib/dbm/ndbm.pyi @@ -1,35 +1,35 @@ +import sys from _typeshed import Self from types import TracebackType -from typing import Type, TypeVar, Union, overload +from typing import TypeVar, overload -_T = TypeVar("_T") -_KeyType = Union[str, bytes] -_ValueType = Union[str, bytes] +if sys.platform != "win32": + _T = TypeVar("_T") + _KeyType = str | bytes + _ValueType = str | bytes -class error(OSError): ... + class error(OSError): ... + library: str -library: str - -# Actual typename dbm, not exposed by the implementation -class _dbm: - def close(self) -> None: ... - def __getitem__(self, item: _KeyType) -> bytes: ... - def __setitem__(self, key: _KeyType, value: _ValueType) -> None: ... - def __delitem__(self, key: _KeyType) -> None: ... - def __len__(self) -> int: ... - def __del__(self) -> None: ... - def __enter__(self: Self) -> Self: ... - def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None - ) -> None: ... - @overload - def get(self, k: _KeyType) -> bytes | None: ... - @overload - def get(self, k: _KeyType, default: bytes | _T) -> bytes | _T: ... - def keys(self) -> list[bytes]: ... - def setdefault(self, k: _KeyType, default: _ValueType = ...) -> bytes: ... - # Don't exist at runtime - __new__: None # type: ignore[assignment] - __init__: None # type: ignore[assignment] - -def open(__filename: str, __flags: str = ..., __mode: int = ...) -> _dbm: ... + # Actual typename dbm, not exposed by the implementation + class _dbm: + def close(self) -> None: ... + def __getitem__(self, item: _KeyType) -> bytes: ... + def __setitem__(self, key: _KeyType, value: _ValueType) -> None: ... + def __delitem__(self, key: _KeyType) -> None: ... + def __len__(self) -> int: ... + def __del__(self) -> None: ... + def __enter__(self: Self) -> Self: ... + def __exit__( + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> None: ... + @overload + def get(self, k: _KeyType) -> bytes | None: ... + @overload + def get(self, k: _KeyType, default: bytes | _T) -> bytes | _T: ... + def keys(self) -> list[bytes]: ... + def setdefault(self, k: _KeyType, default: _ValueType = ...) -> bytes: ... + # Don't exist at runtime + __new__: None # type: ignore[assignment] + __init__: None # type: ignore[assignment] + def open(__filename: str, __flags: str = ..., __mode: int = ...) -> _dbm: ... diff --git a/mypy/typeshed/stdlib/decimal.pyi b/mypy/typeshed/stdlib/decimal.pyi index 07f9ca1bfdf09..819ed1641448c 100644 --- a/mypy/typeshed/stdlib/decimal.pyi +++ b/mypy/typeshed/stdlib/decimal.pyi @@ -1,12 +1,14 @@ import numbers import sys +from _typeshed import Self from types import TracebackType -from typing import Any, Container, NamedTuple, Sequence, Type, TypeVar, Union, overload +from typing import Any, Container, NamedTuple, Sequence, Union, overload -_Decimal = Union[Decimal, int] +_Decimal = Decimal | int _DecimalNew = Union[Decimal, float, str, tuple[int, Sequence[int], int]] -_ComparableNum = Union[Decimal, float, numbers.Rational] -_DecimalT = TypeVar("_DecimalT", bound=Decimal) +_ComparableNum = Decimal | float | numbers.Rational + +__libmpdec_version__: str class DecimalTuple(NamedTuple): sign: int @@ -50,9 +52,9 @@ def getcontext() -> Context: ... def localcontext(ctx: Context | None = ...) -> _ContextManager: ... class Decimal: - def __new__(cls: Type[_DecimalT], value: _DecimalNew = ..., context: Context | None = ...) -> _DecimalT: ... + def __new__(cls: type[Self], value: _DecimalNew = ..., context: Context | None = ...) -> Self: ... @classmethod - def from_float(cls, __f: float) -> Decimal: ... + def from_float(cls: type[Self], __f: float) -> Self: ... def __bool__(self) -> bool: ... def compare(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... def __hash__(self) -> int: ... @@ -80,7 +82,6 @@ class Decimal: def __rmul__(self, __other: _Decimal) -> Decimal: ... def __rsub__(self, __other: _Decimal) -> Decimal: ... def __rtruediv__(self, __other: _Decimal) -> Decimal: ... - def __str__(self) -> str: ... def __sub__(self, __other: _Decimal) -> Decimal: ... def __truediv__(self, __other: _Decimal) -> Decimal: ... def remainder_near(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... @@ -146,9 +147,9 @@ class Decimal: def rotate(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... def scaleb(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... def shift(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... - def __reduce__(self) -> tuple[Type[Decimal], tuple[str]]: ... - def __copy__(self) -> Decimal: ... - def __deepcopy__(self, __memo: Any) -> Decimal: ... + def __reduce__(self: Self) -> tuple[type[Self], tuple[str]]: ... + def __copy__(self: Self) -> Self: ... + def __deepcopy__(self: Self, __memo: Any) -> Self: ... def __format__(self, __specifier: str, __context: Context | None = ...) -> str: ... class _ContextManager: @@ -156,9 +157,9 @@ class _ContextManager: saved_context: Context def __init__(self, new_context: Context) -> None: ... def __enter__(self) -> Context: ... - def __exit__(self, t: Type[BaseException] | None, v: BaseException | None, tb: TracebackType | None) -> None: ... + def __exit__(self, t: type[BaseException] | None, v: BaseException | None, tb: TracebackType | None) -> None: ... -_TrapType = Type[DecimalException] +_TrapType = type[DecimalException] class Context: prec: int @@ -184,7 +185,7 @@ class Context: # __setattr__() only allows to set a specific set of attributes, # already defined above. def __delattr__(self, __name: str) -> None: ... - def __reduce__(self) -> tuple[Type[Context], tuple[Any, ...]]: ... + def __reduce__(self: Self) -> tuple[type[Self], tuple[Any, ...]]: ... def clear_flags(self) -> None: ... def clear_traps(self) -> None: ... def copy(self) -> Context: ... diff --git a/mypy/typeshed/stdlib/difflib.pyi b/mypy/typeshed/stdlib/difflib.pyi index d259e77dfe8c2..a572430155e94 100644 --- a/mypy/typeshed/stdlib/difflib.pyi +++ b/mypy/typeshed/stdlib/difflib.pyi @@ -1,11 +1,25 @@ import sys -from typing import Any, AnyStr, Callable, Generic, Iterable, Iterator, NamedTuple, Sequence, TypeVar, Union, overload +from typing import Any, AnyStr, Callable, Generic, Iterable, Iterator, NamedTuple, Sequence, TypeVar, overload if sys.version_info >= (3, 9): from types import GenericAlias +__all__ = [ + "get_close_matches", + "ndiff", + "restore", + "SequenceMatcher", + "Differ", + "IS_CHARACTER_JUNK", + "IS_LINE_JUNK", + "context_diff", + "unified_diff", + "diff_bytes", + "HtmlDiff", + "Match", +] + _T = TypeVar("_T") -_JunkCallback = Union[Callable[[str], bool], Callable[[str], bool]] class Match(NamedTuple): a: int @@ -23,6 +37,7 @@ class SequenceMatcher(Generic[_T]): def find_longest_match(self, alo: int = ..., ahi: int | None = ..., blo: int = ..., bhi: int | None = ...) -> Match: ... else: def find_longest_match(self, alo: int, ahi: int, blo: int, bhi: int) -> Match: ... + def get_matching_blocks(self) -> list[Match]: ... def get_opcodes(self) -> list[tuple[str, int, int, int, int]]: ... def get_grouped_opcodes(self, n: int = ...) -> Iterable[list[tuple[str, int, int, int, int]]]: ... @@ -41,7 +56,7 @@ def get_close_matches( ) -> list[Sequence[_T]]: ... class Differ: - def __init__(self, linejunk: _JunkCallback | None = ..., charjunk: _JunkCallback | None = ...) -> None: ... + def __init__(self, linejunk: Callable[[str], bool] | None = ..., charjunk: Callable[[str], bool] | None = ...) -> None: ... def compare(self, a: Sequence[str], b: Sequence[str]) -> Iterator[str]: ... def IS_LINE_JUNK(line: str, pat: Any = ...) -> bool: ... # pat is undocumented @@ -67,7 +82,7 @@ def context_diff( lineterm: str = ..., ) -> Iterator[str]: ... def ndiff( - a: Sequence[str], b: Sequence[str], linejunk: _JunkCallback | None = ..., charjunk: _JunkCallback | None = ... + a: Sequence[str], b: Sequence[str], linejunk: Callable[[str], bool] | None = ..., charjunk: Callable[[str], bool] | None = ... ) -> Iterator[str]: ... class HtmlDiff: @@ -75,8 +90,8 @@ class HtmlDiff: self, tabsize: int = ..., wrapcolumn: int | None = ..., - linejunk: _JunkCallback | None = ..., - charjunk: _JunkCallback | None = ..., + linejunk: Callable[[str], bool] | None = ..., + charjunk: Callable[[str], bool] | None = ..., ) -> None: ... def make_file( self, diff --git a/mypy/typeshed/stdlib/dis.pyi b/mypy/typeshed/stdlib/dis.pyi index ac0632d25c9ca..910458c08e005 100644 --- a/mypy/typeshed/stdlib/dis.pyi +++ b/mypy/typeshed/stdlib/dis.pyi @@ -1,27 +1,41 @@ import sys import types -from opcode import ( - EXTENDED_ARG as EXTENDED_ARG, - HAVE_ARGUMENT as HAVE_ARGUMENT, - cmp_op as cmp_op, - hascompare as hascompare, - hasconst as hasconst, - hasfree as hasfree, - hasjabs as hasjabs, - hasjrel as hasjrel, - haslocal as haslocal, - hasname as hasname, - hasnargs as hasnargs, - opmap as opmap, - opname as opname, - stack_effect as stack_effect, -) -from typing import IO, Any, Callable, Iterator, NamedTuple, Union +from _typeshed import Self +from opcode import * # `dis` re-exports it as a part of public API +from typing import IO, Any, Callable, Iterator, NamedTuple + +__all__ = [ + "code_info", + "dis", + "disassemble", + "distb", + "disco", + "findlinestarts", + "findlabels", + "show_code", + "get_instructions", + "Instruction", + "Bytecode", + "cmp_op", + "hasconst", + "hasname", + "hasjrel", + "hasjabs", + "haslocal", + "hascompare", + "hasfree", + "opname", + "opmap", + "HAVE_ARGUMENT", + "EXTENDED_ARG", + "hasnargs", + "stack_effect", +] # Strictly this should not have to include Callable, but mypy doesn't use FunctionType # for functions (python/mypy#3171) -_HaveCodeType = Union[types.MethodType, types.FunctionType, types.CodeType, type, Callable[..., Any]] -_HaveCodeOrStringType = Union[_HaveCodeType, str, bytes] +_HaveCodeType = types.MethodType | types.FunctionType | types.CodeType | type | Callable[..., Any] +_HaveCodeOrStringType = _HaveCodeType | str | bytes class Instruction(NamedTuple): opname: str @@ -38,11 +52,10 @@ class Bytecode: first_line: int def __init__(self, x: _HaveCodeOrStringType, *, first_line: int | None = ..., current_offset: int | None = ...) -> None: ... def __iter__(self) -> Iterator[Instruction]: ... - def __repr__(self) -> str: ... def info(self) -> str: ... def dis(self) -> str: ... @classmethod - def from_traceback(cls, tb: types.TracebackType) -> Bytecode: ... + def from_traceback(cls: type[Self], tb: types.TracebackType) -> Self: ... COMPILER_FLAG_NAMES: dict[int, str] diff --git a/mypy/typeshed/stdlib/distutils/ccompiler.pyi b/mypy/typeshed/stdlib/distutils/ccompiler.pyi index 7c7023ed0b657..4cdc62ce3bae4 100644 --- a/mypy/typeshed/stdlib/distutils/ccompiler.pyi +++ b/mypy/typeshed/stdlib/distutils/ccompiler.pyi @@ -1,6 +1,6 @@ -from typing import Any, Callable, Optional, Union +from typing import Any, Callable, Union -_Macro = Union[tuple[str], tuple[str, Optional[str]]] +_Macro = Union[tuple[str], tuple[str, str | None]] def gen_lib_options( compiler: CCompiler, library_dirs: list[str], runtime_library_dirs: list[str], libraries: list[str] diff --git a/mypy/typeshed/stdlib/distutils/cmd.pyi b/mypy/typeshed/stdlib/distutils/cmd.pyi index 875e851bed391..96a048c93f41a 100644 --- a/mypy/typeshed/stdlib/distutils/cmd.pyi +++ b/mypy/typeshed/stdlib/distutils/cmd.pyi @@ -57,7 +57,7 @@ class Command: ) -> str: ... def make_file( self, - infiles: str | list[str] | tuple[str], + infiles: str | list[str] | tuple[str, ...], outfile: str, func: Callable[..., Any], args: list[Any], diff --git a/mypy/typeshed/stdlib/distutils/command/__init__.pyi b/mypy/typeshed/stdlib/distutils/command/__init__.pyi index a4b9b1c2bd1b7..e69de29bb2d1d 100644 --- a/mypy/typeshed/stdlib/distutils/command/__init__.pyi +++ b/mypy/typeshed/stdlib/distutils/command/__init__.pyi @@ -1,40 +0,0 @@ -from . import ( - bdist_dumb as bdist_dumb, - bdist_rpm as bdist_rpm, - build as build, - build_clib as build_clib, - build_ext as build_ext, - build_py as build_py, - build_scripts as build_scripts, - check as check, - clean as clean, - install as install, - install_data as install_data, - install_headers as install_headers, - install_lib as install_lib, - register as register, - sdist as sdist, - upload as upload, -) - -__all__ = [ - "build", - "build_py", - "build_ext", - "build_clib", - "build_scripts", - "clean", - "install", - "install_lib", - "install_headers", - "install_scripts", - "install_data", - "sdist", - "register", - "bdist", - "bdist_dumb", - "bdist_rpm", - "bdist_wininst", - "check", - "upload", -] diff --git a/mypy/typeshed/stdlib/distutils/command/bdist_msi.pyi b/mypy/typeshed/stdlib/distutils/command/bdist_msi.pyi index e4f64ff6a59ef..66202e841d3c9 100644 --- a/mypy/typeshed/stdlib/distutils/command/bdist_msi.pyi +++ b/mypy/typeshed/stdlib/distutils/command/bdist_msi.pyi @@ -5,6 +5,7 @@ from ..cmd import Command if sys.platform == "win32": from msilib import Dialog + class PyDialog(Dialog): def __init__(self, *args, **kw) -> None: ... def title(self, title) -> None: ... @@ -12,6 +13,7 @@ if sys.platform == "win32": def cancel(self, title, next, name: str = ..., active: int = ...): ... def next(self, title, next, name: str = ..., active: int = ...): ... def xbutton(self, name, title, next, xpos): ... + class bdist_msi(Command): description: str user_options: Any diff --git a/mypy/typeshed/stdlib/distutils/command/bdist_wininst.pyi b/mypy/typeshed/stdlib/distutils/command/bdist_wininst.pyi index e69de29bb2d1d..1091fb2784931 100644 --- a/mypy/typeshed/stdlib/distutils/command/bdist_wininst.pyi +++ b/mypy/typeshed/stdlib/distutils/command/bdist_wininst.pyi @@ -0,0 +1,16 @@ +from _typeshed import StrOrBytesPath +from distutils.cmd import Command +from typing import Any, ClassVar + +class bdist_wininst(Command): + description: ClassVar[str] + user_options: ClassVar[list[tuple[Any, ...]]] + boolean_options: ClassVar[list[str]] + + def initialize_options(self) -> None: ... + def finalize_options(self) -> None: ... + def run(self) -> None: ... + def get_inidata(self) -> str: ... + def create_exe(self, arcname: StrOrBytesPath, fullname: str, bitmap: StrOrBytesPath | None = ...) -> None: ... + def get_installer_filename(self, fullname: str) -> str: ... + def get_exe_bytes(self) -> bytes: ... diff --git a/mypy/typeshed/stdlib/distutils/core.pyi b/mypy/typeshed/stdlib/distutils/core.pyi index fc4cd81c4752d..6564c9a86ded8 100644 --- a/mypy/typeshed/stdlib/distutils/core.pyi +++ b/mypy/typeshed/stdlib/distutils/core.pyi @@ -1,7 +1,7 @@ from distutils.cmd import Command as Command from distutils.dist import Distribution as Distribution from distutils.extension import Extension as Extension -from typing import Any, Mapping, Type +from typing import Any, Mapping def setup( *, @@ -20,14 +20,14 @@ def setup( scripts: list[str] = ..., ext_modules: list[Extension] = ..., classifiers: list[str] = ..., - distclass: Type[Distribution] = ..., + distclass: type[Distribution] = ..., script_name: str = ..., script_args: list[str] = ..., options: Mapping[str, Any] = ..., license: str = ..., keywords: list[str] | str = ..., platforms: list[str] | str = ..., - cmdclass: Mapping[str, Type[Command]] = ..., + cmdclass: Mapping[str, type[Command]] = ..., data_files: list[tuple[str, list[str]]] = ..., package_dir: Mapping[str, str] = ..., obsoletes: list[str] = ..., diff --git a/mypy/typeshed/stdlib/distutils/dist.pyi b/mypy/typeshed/stdlib/distutils/dist.pyi index 5bb04b0499954..c5b3afe7cc3bd 100644 --- a/mypy/typeshed/stdlib/distutils/dist.pyi +++ b/mypy/typeshed/stdlib/distutils/dist.pyi @@ -1,6 +1,6 @@ from _typeshed import StrOrBytesPath, SupportsWrite from distutils.cmd import Command -from typing import IO, Any, Iterable, Mapping, Type +from typing import IO, Any, Iterable, Mapping class DistributionMetadata: def __init__(self, path: int | StrOrBytesPath | None = ...) -> None: ... @@ -50,7 +50,7 @@ class DistributionMetadata: def set_obsoletes(self, value: Iterable[str]) -> None: ... class Distribution: - cmdclass: dict[str, Type[Command]] + cmdclass: dict[str, type[Command]] metadata: DistributionMetadata def __init__(self, attrs: Mapping[str, Any] | None = ...) -> None: ... def get_option_dict(self, command: str) -> dict[str, tuple[str, str]]: ... diff --git a/mypy/typeshed/stdlib/distutils/extension.pyi b/mypy/typeshed/stdlib/distutils/extension.pyi index 655ea1e9e3478..5639f44a6d031 100644 --- a/mypy/typeshed/stdlib/distutils/extension.pyi +++ b/mypy/typeshed/stdlib/distutils/extension.pyi @@ -1,4 +1,20 @@ class Extension: + name: str + sources: list[str] + include_dirs: list[str] + define_macros: list[tuple[str, str | None]] + undef_macros: list[str] + library_dirs: list[str] + libraries: list[str] + runtime_library_dirs: list[str] + extra_objects: list[str] + extra_compile_args: list[str] + extra_link_args: list[str] + export_symbols: list[str] + swig_opts: list[str] + depends: list[str] + language: str | None + optional: bool | None def __init__( self, name: str, @@ -13,7 +29,7 @@ class Extension: extra_compile_args: list[str] | None = ..., extra_link_args: list[str] | None = ..., export_symbols: list[str] | None = ..., - swig_opts: str | None = ..., # undocumented + swig_opts: list[str] | None = ..., depends: list[str] | None = ..., language: str | None = ..., optional: bool | None = ..., diff --git a/mypy/typeshed/stdlib/distutils/fancy_getopt.pyi b/mypy/typeshed/stdlib/distutils/fancy_getopt.pyi index dce8394b6289d..c2a5bd4c20a14 100644 --- a/mypy/typeshed/stdlib/distutils/fancy_getopt.pyi +++ b/mypy/typeshed/stdlib/distutils/fancy_getopt.pyi @@ -1,6 +1,6 @@ -from typing import Any, Iterable, Mapping, Optional, overload +from typing import Any, Iterable, Mapping, overload -_Option = tuple[str, Optional[str], str] +_Option = tuple[str, str | None, str] _GR = tuple[list[str], OptionDummy] def fancy_getopt( diff --git a/mypy/typeshed/stdlib/distutils/util.pyi b/mypy/typeshed/stdlib/distutils/util.pyi index 03ee0185cac46..22d982e6949d4 100644 --- a/mypy/typeshed/stdlib/distutils/util.pyi +++ b/mypy/typeshed/stdlib/distutils/util.pyi @@ -1,6 +1,7 @@ from _typeshed import StrPath from collections.abc import Callable, Container, Iterable, Mapping from typing import Any +from typing_extensions import Literal def get_platform() -> str: ... def convert_path(pathname: str) -> str: ... @@ -11,7 +12,7 @@ def split_quoted(s: str) -> list[str]: ... def execute( func: Callable[..., None], args: tuple[Any, ...], msg: str | None = ..., verbose: bool = ..., dry_run: bool = ... ) -> None: ... -def strtobool(val: str) -> bool: ... +def strtobool(val: str) -> Literal[0, 1]: ... def byte_compile( py_files: list[str], optimize: int = ..., diff --git a/mypy/typeshed/stdlib/distutils/version.pyi b/mypy/typeshed/stdlib/distutils/version.pyi index 1908cdeda97ad..8745e8c9f6802 100644 --- a/mypy/typeshed/stdlib/distutils/version.pyi +++ b/mypy/typeshed/stdlib/distutils/version.pyi @@ -1,38 +1,36 @@ +from _typeshed import Self from abc import abstractmethod -from typing import Pattern, TypeVar - -_T = TypeVar("_T", bound=Version) +from typing import Pattern class Version: - def __repr__(self) -> str: ... def __eq__(self, other: object) -> bool: ... - def __lt__(self: _T, other: _T | str) -> bool: ... - def __le__(self: _T, other: _T | str) -> bool: ... - def __gt__(self: _T, other: _T | str) -> bool: ... - def __ge__(self: _T, other: _T | str) -> bool: ... + def __lt__(self: Self, other: Self | str) -> bool: ... + def __le__(self: Self, other: Self | str) -> bool: ... + def __gt__(self: Self, other: Self | str) -> bool: ... + def __ge__(self: Self, other: Self | str) -> bool: ... @abstractmethod def __init__(self, vstring: str | None = ...) -> None: ... @abstractmethod - def parse(self: _T, vstring: str) -> _T: ... + def parse(self: Self, vstring: str) -> Self: ... @abstractmethod def __str__(self) -> str: ... @abstractmethod - def _cmp(self: _T, other: _T | str) -> bool: ... + def _cmp(self: Self, other: Self | str) -> bool: ... class StrictVersion(Version): version_re: Pattern[str] version: tuple[int, int, int] prerelease: tuple[str, int] | None def __init__(self, vstring: str | None = ...) -> None: ... - def parse(self: _T, vstring: str) -> _T: ... - def __str__(self) -> str: ... - def _cmp(self: _T, other: _T | str) -> bool: ... + def parse(self: Self, vstring: str) -> Self: ... + def __str__(self) -> str: ... # noqa: Y029 + def _cmp(self: Self, other: Self | str) -> bool: ... class LooseVersion(Version): component_re: Pattern[str] vstring: str version: tuple[str | int, ...] def __init__(self, vstring: str | None = ...) -> None: ... - def parse(self: _T, vstring: str) -> _T: ... - def __str__(self) -> str: ... - def _cmp(self: _T, other: _T | str) -> bool: ... + def parse(self: Self, vstring: str) -> Self: ... + def __str__(self) -> str: ... # noqa: Y029 + def _cmp(self: Self, other: Self | str) -> bool: ... diff --git a/mypy/typeshed/stdlib/doctest.pyi b/mypy/typeshed/stdlib/doctest.pyi index 611137740ac4e..651e1b298aafe 100644 --- a/mypy/typeshed/stdlib/doctest.pyi +++ b/mypy/typeshed/stdlib/doctest.pyi @@ -1,6 +1,42 @@ import types import unittest -from typing import Any, Callable, NamedTuple, Type +from typing import Any, Callable, NamedTuple + +__all__ = [ + "register_optionflag", + "DONT_ACCEPT_TRUE_FOR_1", + "DONT_ACCEPT_BLANKLINE", + "NORMALIZE_WHITESPACE", + "ELLIPSIS", + "SKIP", + "IGNORE_EXCEPTION_DETAIL", + "COMPARISON_FLAGS", + "REPORT_UDIFF", + "REPORT_CDIFF", + "REPORT_NDIFF", + "REPORT_ONLY_FIRST_FAILURE", + "REPORTING_FLAGS", + "FAIL_FAST", + "Example", + "DocTest", + "DocTestParser", + "DocTestFinder", + "DocTestRunner", + "OutputChecker", + "DocTestFailure", + "UnexpectedException", + "DebugRunner", + "testmod", + "testfile", + "run_docstring_examples", + "DocTestSuite", + "DocFileSuite", + "set_unittest_reportflags", + "script_from_examples", + "testsource", + "debug_src", + "debug", +] class TestResults(NamedTuple): failed: int @@ -47,6 +83,7 @@ class Example: options: dict[int, bool] | None = ..., ) -> None: ... def __hash__(self) -> int: ... + def __eq__(self, other: object) -> bool: ... class DocTest: examples: list[Example] @@ -66,6 +103,7 @@ class DocTest: ) -> None: ... def __hash__(self) -> int: ... def __lt__(self, other: DocTest) -> bool: ... + def __eq__(self, other: object) -> bool: ... class DocTestParser: def parse(self, string: str, name: str = ...) -> list[str | Example]: ... @@ -86,7 +124,7 @@ class DocTestFinder: ) -> list[DocTest]: ... _Out = Callable[[str], Any] -_ExcInfo = tuple[Type[BaseException], BaseException, types.TracebackType] +_ExcInfo = tuple[type[BaseException], BaseException, types.TracebackType] class DocTestRunner: DIVIDER: str @@ -172,6 +210,7 @@ class DocTestCase(unittest.TestCase): def debug(self) -> None: ... def id(self) -> str: ... def __hash__(self) -> int: ... + def __eq__(self, other: object) -> bool: ... def shortDescription(self) -> str: ... class SkipDocTestCase(DocTestCase): diff --git a/mypy/typeshed/stdlib/email/__init__.pyi b/mypy/typeshed/stdlib/email/__init__.pyi index e2c22554a0920..49e18ccb8c2ef 100644 --- a/mypy/typeshed/stdlib/email/__init__.pyi +++ b/mypy/typeshed/stdlib/email/__init__.pyi @@ -1,6 +1,11 @@ from email.message import Message from email.policy import Policy -from typing import IO, Callable +from typing import IO, Callable, TypeVar, Union + +# Definitions imported by multiple submodules in typeshed +_MessageT = TypeVar("_MessageT", bound=Message) # noqa: Y018 +_ParamType = Union[str, tuple[str | None, str | None, str]] +_ParamsType = Union[str, None, tuple[str, str | None, str]] def message_from_string(s: str, _class: Callable[[], Message] = ..., *, policy: Policy = ...) -> Message: ... def message_from_bytes(s: bytes, _class: Callable[[], Message] = ..., *, policy: Policy = ...) -> Message: ... diff --git a/mypy/typeshed/stdlib/email/_header_value_parser.pyi b/mypy/typeshed/stdlib/email/_header_value_parser.pyi index ddb9d9e45913f..749b6454a8f8a 100644 --- a/mypy/typeshed/stdlib/email/_header_value_parser.pyi +++ b/mypy/typeshed/stdlib/email/_header_value_parser.pyi @@ -1,11 +1,10 @@ import sys +from _typeshed import Self from email.errors import HeaderParseError, MessageDefect from email.policy import Policy -from typing import Any, Iterable, Iterator, Pattern, Type, TypeVar, Union +from typing import Any, Iterable, Iterator, Pattern from typing_extensions import Final -_T = TypeVar("_T") - WSP: Final[set[str]] CFWS_LEADER: Final[set[str]] SPECIALS: Final[set[str]] @@ -23,7 +22,7 @@ def quote_string(value: Any) -> str: ... if sys.version_info >= (3, 7): rfc2047_matcher: Pattern[str] -class TokenList(list[Union[TokenList, Terminal]]): +class TokenList(list[TokenList | Terminal]): token_type: str | None syntactic_break: bool ew_combine_allowed: bool @@ -182,10 +181,14 @@ class InvalidMailbox(TokenList): token_type: str @property def display_name(self) -> None: ... - local_part: None - domain: None - route: None - addr_spec: None + @property + def local_part(self) -> None: ... + @property + def domain(self) -> None: ... + @property + def route(self) -> None: ... + @property + def addr_spec(self) -> None: ... class Domain(TokenList): token_type: str @@ -313,8 +316,10 @@ if sys.version_info >= (3, 8): token_type: str as_ew_allowed: bool def fold(self, policy: Policy) -> str: ... + class MessageID(MsgID): token_type: str + class InvalidMessageID(MessageID): token_type: str @@ -327,7 +332,7 @@ class Terminal(str): syntactic_break: bool token_type: str defects: list[MessageDefect] - def __new__(cls: Type[_T], value: str, token_type: str) -> _T: ... + def __new__(cls: type[Self], value: str, token_type: str) -> Self: ... def pprint(self) -> None: ... @property def all_defects(self) -> list[MessageDefect]: ... diff --git a/mypy/typeshed/stdlib/email/base64mime.pyi b/mypy/typeshed/stdlib/email/base64mime.pyi index a8030a9789235..e55658046f55f 100644 --- a/mypy/typeshed/stdlib/email/base64mime.pyi +++ b/mypy/typeshed/stdlib/email/base64mime.pyi @@ -1,3 +1,5 @@ +__all__ = ["body_decode", "body_encode", "decode", "decodestring", "header_encode", "header_length"] + def header_length(bytearray: str | bytes) -> int: ... def header_encode(header_bytes: str | bytes, charset: str = ...) -> str: ... def body_encode(s: bytes, maxlinelen: int = ..., eol: str = ...) -> str: ... diff --git a/mypy/typeshed/stdlib/email/charset.pyi b/mypy/typeshed/stdlib/email/charset.pyi index 4bf5d11690eb9..fd3de9ceace27 100644 --- a/mypy/typeshed/stdlib/email/charset.pyi +++ b/mypy/typeshed/stdlib/email/charset.pyi @@ -1,4 +1,6 @@ -from typing import Any, Iterator +from typing import Iterator + +__all__ = ["Charset", "add_alias", "add_charset", "add_codec"] QP: int # undocumented BASE64: int # undocumented @@ -17,9 +19,8 @@ class Charset: def header_encode(self, string: str) -> str: ... def header_encode_lines(self, string: str, maxlengths: Iterator[int]) -> list[str]: ... def body_encode(self, string: str) -> str: ... - def __str__(self) -> str: ... - def __eq__(self, other: Any) -> bool: ... - def __ne__(self, other: Any) -> bool: ... + def __eq__(self, other: object) -> bool: ... + def __ne__(self, __other: object) -> bool: ... def add_charset( charset: str, header_enc: int | None = ..., body_enc: int | None = ..., output_charset: str | None = ... diff --git a/mypy/typeshed/stdlib/email/encoders.pyi b/mypy/typeshed/stdlib/email/encoders.pyi index e05225e895c46..55223bdc07621 100644 --- a/mypy/typeshed/stdlib/email/encoders.pyi +++ b/mypy/typeshed/stdlib/email/encoders.pyi @@ -1,5 +1,7 @@ from email.message import Message +__all__ = ["encode_7or8bit", "encode_base64", "encode_noop", "encode_quopri"] + def encode_base64(msg: Message) -> None: ... def encode_quopri(msg: Message) -> None: ... def encode_7or8bit(msg: Message) -> None: ... diff --git a/mypy/typeshed/stdlib/email/feedparser.pyi b/mypy/typeshed/stdlib/email/feedparser.pyi index ffcf4f0a7c6eb..b1c7e0f7d1276 100644 --- a/mypy/typeshed/stdlib/email/feedparser.pyi +++ b/mypy/typeshed/stdlib/email/feedparser.pyi @@ -1,21 +1,22 @@ +from email import _MessageT from email.message import Message from email.policy import Policy -from typing import Callable, Generic, TypeVar, overload +from typing import Callable, Generic, overload -_M = TypeVar("_M", bound=Message) +__all__ = ["FeedParser", "BytesFeedParser"] -class FeedParser(Generic[_M]): +class FeedParser(Generic[_MessageT]): @overload def __init__(self: FeedParser[Message], _factory: None = ..., *, policy: Policy = ...) -> None: ... @overload - def __init__(self, _factory: Callable[[], _M], *, policy: Policy = ...) -> None: ... + def __init__(self, _factory: Callable[[], _MessageT], *, policy: Policy = ...) -> None: ... def feed(self, data: str) -> None: ... - def close(self) -> _M: ... + def close(self) -> _MessageT: ... -class BytesFeedParser(Generic[_M]): +class BytesFeedParser(Generic[_MessageT]): @overload def __init__(self: BytesFeedParser[Message], _factory: None = ..., *, policy: Policy = ...) -> None: ... @overload - def __init__(self, _factory: Callable[[], _M], *, policy: Policy = ...) -> None: ... + def __init__(self, _factory: Callable[[], _MessageT], *, policy: Policy = ...) -> None: ... def feed(self, data: bytes) -> None: ... - def close(self) -> _M: ... + def close(self) -> _MessageT: ... diff --git a/mypy/typeshed/stdlib/email/generator.pyi b/mypy/typeshed/stdlib/email/generator.pyi index 1a810558a0dae..5a6b6374dd4b5 100644 --- a/mypy/typeshed/stdlib/email/generator.pyi +++ b/mypy/typeshed/stdlib/email/generator.pyi @@ -1,27 +1,39 @@ +from _typeshed import SupportsWrite from email.message import Message from email.policy import Policy -from typing import BinaryIO, TextIO + +__all__ = ["Generator", "DecodedGenerator", "BytesGenerator"] class Generator: - def clone(self, fp: TextIO) -> Generator: ... + def clone(self, fp: SupportsWrite[str]) -> Generator: ... def write(self, s: str) -> None: ... def __init__( - self, outfp: TextIO, mangle_from_: bool | None = ..., maxheaderlen: int | None = ..., *, policy: Policy | None = ... + self, + outfp: SupportsWrite[str], + mangle_from_: bool | None = ..., + maxheaderlen: int | None = ..., + *, + policy: Policy | None = ..., ) -> None: ... def flatten(self, msg: Message, unixfrom: bool = ..., linesep: str | None = ...) -> None: ... class BytesGenerator: - def clone(self, fp: BinaryIO) -> BytesGenerator: ... + def clone(self, fp: SupportsWrite[bytes]) -> BytesGenerator: ... def write(self, s: str) -> None: ... def __init__( - self, outfp: BinaryIO, mangle_from_: bool | None = ..., maxheaderlen: int | None = ..., *, policy: Policy | None = ... + self, + outfp: SupportsWrite[bytes], + mangle_from_: bool | None = ..., + maxheaderlen: int | None = ..., + *, + policy: Policy | None = ..., ) -> None: ... def flatten(self, msg: Message, unixfrom: bool = ..., linesep: str | None = ...) -> None: ... class DecodedGenerator(Generator): def __init__( self, - outfp: TextIO, + outfp: SupportsWrite[str], mangle_from_: bool | None = ..., maxheaderlen: int | None = ..., fmt: str | None = ..., diff --git a/mypy/typeshed/stdlib/email/header.pyi b/mypy/typeshed/stdlib/email/header.pyi index 4bebd50c45e4e..bd851bcf86796 100644 --- a/mypy/typeshed/stdlib/email/header.pyi +++ b/mypy/typeshed/stdlib/email/header.pyi @@ -1,5 +1,6 @@ from email.charset import Charset -from typing import Any + +__all__ = ["Header", "decode_header", "make_header"] class Header: def __init__( @@ -13,9 +14,8 @@ class Header: ) -> None: ... def append(self, s: bytes | str, charset: Charset | str | None = ..., errors: str = ...) -> None: ... def encode(self, splitchars: str = ..., maxlinelen: int | None = ..., linesep: str = ...) -> str: ... - def __str__(self) -> str: ... - def __eq__(self, other: Any) -> bool: ... - def __ne__(self, other: Any) -> bool: ... + def __eq__(self, other: object) -> bool: ... + def __ne__(self, __other: object) -> bool: ... def decode_header(header: Header | str) -> list[tuple[bytes, str | None]]: ... def make_header( diff --git a/mypy/typeshed/stdlib/email/headerregistry.pyi b/mypy/typeshed/stdlib/email/headerregistry.pyi index abf10ed4a4fdd..7f1d86b985a10 100644 --- a/mypy/typeshed/stdlib/email/headerregistry.pyi +++ b/mypy/typeshed/stdlib/email/headerregistry.pyi @@ -1,5 +1,6 @@ import sys import types +from _typeshed import Self from collections.abc import Iterable, Mapping from datetime import datetime as _datetime from email._header_value_parser import ( @@ -13,7 +14,7 @@ from email._header_value_parser import ( ) from email.errors import MessageDefect from email.policy import Policy -from typing import Any, ClassVar, Type +from typing import Any, ClassVar from typing_extensions import Literal class BaseHeader(str): @@ -23,7 +24,7 @@ class BaseHeader(str): def name(self) -> str: ... @property def defects(self) -> tuple[MessageDefect, ...]: ... - def __new__(cls, name: str, value: Any) -> BaseHeader: ... + def __new__(cls: type[Self], name: str, value: Any) -> Self: ... def init(self, name: str, *, parse_tree: TokenList, defects: Iterable[MessageDefect]) -> None: ... def fold(self, *, policy: Policy) -> str: ... @@ -132,6 +133,7 @@ class ContentTransferEncodingHeader: if sys.version_info >= (3, 8): from email._header_value_parser import MessageID + class MessageIDHeader: max_count: ClassVar[Literal[1]] @classmethod @@ -141,10 +143,10 @@ if sys.version_info >= (3, 8): class HeaderRegistry: def __init__( - self, base_class: Type[BaseHeader] = ..., default_class: Type[BaseHeader] = ..., use_default_map: bool = ... + self, base_class: type[BaseHeader] = ..., default_class: type[BaseHeader] = ..., use_default_map: bool = ... ) -> None: ... - def map_to_type(self, name: str, cls: Type[BaseHeader]) -> None: ... - def __getitem__(self, name: str) -> Type[BaseHeader]: ... + def map_to_type(self, name: str, cls: type[BaseHeader]) -> None: ... + def __getitem__(self, name: str) -> type[BaseHeader]: ... def __call__(self, name: str, value: Any) -> BaseHeader: ... class Address: @@ -159,7 +161,7 @@ class Address: def __init__( self, display_name: str = ..., username: str | None = ..., domain: str | None = ..., addr_spec: str | None = ... ) -> None: ... - def __str__(self) -> str: ... + def __eq__(self, other: object) -> bool: ... class Group: @property @@ -167,4 +169,4 @@ class Group: @property def addresses(self) -> tuple[Address, ...]: ... def __init__(self, display_name: str | None = ..., addresses: Iterable[Address] | None = ...) -> None: ... - def __str__(self) -> str: ... + def __eq__(self, other: object) -> bool: ... diff --git a/mypy/typeshed/stdlib/email/iterators.pyi b/mypy/typeshed/stdlib/email/iterators.pyi index 9081a3e3ba73c..ad5517712d256 100644 --- a/mypy/typeshed/stdlib/email/iterators.pyi +++ b/mypy/typeshed/stdlib/email/iterators.pyi @@ -1,5 +1,12 @@ +from _typeshed import SupportsWrite from email.message import Message from typing import Iterator +__all__ = ["body_line_iterator", "typed_subpart_iterator", "walk"] + def body_line_iterator(msg: Message, decode: bool = ...) -> Iterator[str]: ... def typed_subpart_iterator(msg: Message, maintype: str = ..., subtype: str | None = ...) -> Iterator[str]: ... +def walk(self: Message) -> Iterator[Message]: ... + +# We include the seemingly private function because it is documented in the stdlib documentation. +def _structure(msg: Message, fp: SupportsWrite[str] | None = ..., level: int = ..., include_default: bool = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/email/message.pyi b/mypy/typeshed/stdlib/email/message.pyi index b89c8f8ec167d..97de1cf5daf63 100644 --- a/mypy/typeshed/stdlib/email/message.pyi +++ b/mypy/typeshed/stdlib/email/message.pyi @@ -1,24 +1,23 @@ +from email import _ParamsType, _ParamType from email.charset import Charset from email.contentmanager import ContentManager from email.errors import MessageDefect from email.policy import Policy +from typing import Any, Generator, Iterator, Sequence, TypeVar -# using a type alias ("_HeaderType = Any") breaks mypy, who knows why -from typing import Any, Any as _HeaderType, Generator, Iterator, Optional, Sequence, TypeVar, Union +__all__ = ["Message", "EmailMessage"] _T = TypeVar("_T") -_PayloadType = Union[list[Message], str, bytes] -_CharsetType = Union[Charset, str, None] -_ParamsType = Union[str, None, tuple[str, Optional[str], str]] -_ParamType = Union[str, tuple[Optional[str], Optional[str], str]] +_PayloadType = list[Message] | str | bytes +_CharsetType = Charset | str | None +_HeaderType = Any class Message: policy: Policy # undocumented preamble: str | None epilogue: str | None defects: list[MessageDefect] - def __str__(self) -> str: ... def is_multipart(self) -> bool: ... def set_unixfrom(self, unixfrom: str) -> None: ... def get_unixfrom(self) -> str | None: ... diff --git a/mypy/typeshed/stdlib/email/mime/application.pyi b/mypy/typeshed/stdlib/email/mime/application.pyi index d176cd613e272..4966a17d94719 100644 --- a/mypy/typeshed/stdlib/email/mime/application.pyi +++ b/mypy/typeshed/stdlib/email/mime/application.pyi @@ -1,8 +1,9 @@ +from collections.abc import Callable +from email import _ParamsType from email.mime.nonmultipart import MIMENonMultipart from email.policy import Policy -from typing import Callable, Optional, Union -_ParamsType = Union[str, None, tuple[str, Optional[str], str]] +__all__ = ["MIMEApplication"] class MIMEApplication(MIMENonMultipart): def __init__( diff --git a/mypy/typeshed/stdlib/email/mime/audio.pyi b/mypy/typeshed/stdlib/email/mime/audio.pyi index 38657c932e2f7..fd107d7fcbc69 100644 --- a/mypy/typeshed/stdlib/email/mime/audio.pyi +++ b/mypy/typeshed/stdlib/email/mime/audio.pyi @@ -1,8 +1,9 @@ +from collections.abc import Callable +from email import _ParamsType from email.mime.nonmultipart import MIMENonMultipart from email.policy import Policy -from typing import Callable, Optional, Union -_ParamsType = Union[str, None, tuple[str, Optional[str], str]] +__all__ = ["MIMEAudio"] class MIMEAudio(MIMENonMultipart): def __init__( diff --git a/mypy/typeshed/stdlib/email/mime/base.pyi b/mypy/typeshed/stdlib/email/mime/base.pyi index cb655607b0327..c8f2fe6db79d7 100644 --- a/mypy/typeshed/stdlib/email/mime/base.pyi +++ b/mypy/typeshed/stdlib/email/mime/base.pyi @@ -1,8 +1,8 @@ import email.message +from email import _ParamsType from email.policy import Policy -from typing import Optional, Union -_ParamsType = Union[str, None, tuple[str, Optional[str], str]] +__all__ = ["MIMEBase"] class MIMEBase(email.message.Message): def __init__(self, _maintype: str, _subtype: str, *, policy: Policy | None = ..., **_params: _ParamsType) -> None: ... diff --git a/mypy/typeshed/stdlib/email/mime/image.pyi b/mypy/typeshed/stdlib/email/mime/image.pyi index 0325d9e594da7..480f6dcab34b2 100644 --- a/mypy/typeshed/stdlib/email/mime/image.pyi +++ b/mypy/typeshed/stdlib/email/mime/image.pyi @@ -1,8 +1,9 @@ +from collections.abc import Callable +from email import _ParamsType from email.mime.nonmultipart import MIMENonMultipart from email.policy import Policy -from typing import Callable, Optional, Union -_ParamsType = Union[str, None, tuple[str, Optional[str], str]] +__all__ = ["MIMEImage"] class MIMEImage(MIMENonMultipart): def __init__( diff --git a/mypy/typeshed/stdlib/email/mime/message.pyi b/mypy/typeshed/stdlib/email/mime/message.pyi index 8878741e8db32..9e7cd04b6e777 100644 --- a/mypy/typeshed/stdlib/email/mime/message.pyi +++ b/mypy/typeshed/stdlib/email/mime/message.pyi @@ -2,5 +2,7 @@ from email.message import Message from email.mime.nonmultipart import MIMENonMultipart from email.policy import Policy +__all__ = ["MIMEMessage"] + class MIMEMessage(MIMENonMultipart): def __init__(self, _msg: Message, _subtype: str = ..., *, policy: Policy | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/email/mime/multipart.pyi b/mypy/typeshed/stdlib/email/mime/multipart.pyi index 6c316c055329f..6cd480ccf0a41 100644 --- a/mypy/typeshed/stdlib/email/mime/multipart.pyi +++ b/mypy/typeshed/stdlib/email/mime/multipart.pyi @@ -1,9 +1,10 @@ +from collections.abc import Sequence +from email import _ParamsType from email.message import Message from email.mime.base import MIMEBase from email.policy import Policy -from typing import Optional, Sequence, Union -_ParamsType = Union[str, None, tuple[str, Optional[str], str]] +__all__ = ["MIMEMultipart"] class MIMEMultipart(MIMEBase): def __init__( diff --git a/mypy/typeshed/stdlib/email/mime/nonmultipart.pyi b/mypy/typeshed/stdlib/email/mime/nonmultipart.pyi index 4addff18861a7..5497d89b10726 100644 --- a/mypy/typeshed/stdlib/email/mime/nonmultipart.pyi +++ b/mypy/typeshed/stdlib/email/mime/nonmultipart.pyi @@ -1,3 +1,5 @@ from email.mime.base import MIMEBase +__all__ = ["MIMENonMultipart"] + class MIMENonMultipart(MIMEBase): ... diff --git a/mypy/typeshed/stdlib/email/mime/text.pyi b/mypy/typeshed/stdlib/email/mime/text.pyi index afcafa66ee606..9672c3b717b25 100644 --- a/mypy/typeshed/stdlib/email/mime/text.pyi +++ b/mypy/typeshed/stdlib/email/mime/text.pyi @@ -1,5 +1,7 @@ from email.mime.nonmultipart import MIMENonMultipart from email.policy import Policy +__all__ = ["MIMEText"] + class MIMEText(MIMENonMultipart): def __init__(self, _text: str, _subtype: str = ..., _charset: str | None = ..., *, policy: Policy | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/email/parser.pyi b/mypy/typeshed/stdlib/email/parser.pyi index 574c927eeaf58..1846bdcc36b2b 100644 --- a/mypy/typeshed/stdlib/email/parser.pyi +++ b/mypy/typeshed/stdlib/email/parser.pyi @@ -1,10 +1,13 @@ import email.feedparser +from email import _MessageT from email.message import Message from email.policy import Policy from typing import BinaryIO, Callable, TextIO -FeedParser = email.feedparser.FeedParser -BytesFeedParser = email.feedparser.BytesFeedParser +__all__ = ["Parser", "HeaderParser", "BytesParser", "BytesHeaderParser", "FeedParser", "BytesFeedParser"] + +FeedParser = email.feedparser.FeedParser[_MessageT] +BytesFeedParser = email.feedparser.BytesFeedParser[_MessageT] class Parser: def __init__(self, _class: Callable[[], Message] | None = ..., *, policy: Policy = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/email/policy.pyi b/mypy/typeshed/stdlib/email/policy.pyi index 15991c7e084b8..d4ebb1fd5e371 100644 --- a/mypy/typeshed/stdlib/email/policy.pyi +++ b/mypy/typeshed/stdlib/email/policy.pyi @@ -5,6 +5,8 @@ from email.header import Header from email.message import Message from typing import Any, Callable +__all__ = ["Compat32", "compat32", "Policy", "EmailPolicy", "default", "strict", "SMTP", "HTTP"] + class Policy(metaclass=ABCMeta): max_line_length: int | None linesep: str diff --git a/mypy/typeshed/stdlib/email/quoprimime.pyi b/mypy/typeshed/stdlib/email/quoprimime.pyi index 41c4bd8cca9e3..c5d324d17e13f 100644 --- a/mypy/typeshed/stdlib/email/quoprimime.pyi +++ b/mypy/typeshed/stdlib/email/quoprimime.pyi @@ -1,3 +1,16 @@ +__all__ = [ + "body_decode", + "body_encode", + "body_length", + "decode", + "decodestring", + "header_decode", + "header_encode", + "header_length", + "quote", + "unquote", +] + def header_check(octet: int) -> bool: ... def body_check(octet: int) -> bool: ... def header_length(bytearray: bytes) -> int: ... diff --git a/mypy/typeshed/stdlib/email/utils.pyi b/mypy/typeshed/stdlib/email/utils.pyi index 728a5a53f230f..aeffb0ef19817 100644 --- a/mypy/typeshed/stdlib/email/utils.pyi +++ b/mypy/typeshed/stdlib/email/utils.pyi @@ -1,10 +1,28 @@ import datetime import sys +from email import _ParamType from email.charset import Charset -from typing import Optional, Union, overload +from typing import overload -_ParamType = Union[str, tuple[Optional[str], Optional[str], str]] -_PDTZ = tuple[int, int, int, int, int, int, int, int, int, Optional[int]] +__all__ = [ + "collapse_rfc2231_value", + "decode_params", + "decode_rfc2231", + "encode_rfc2231", + "formataddr", + "formatdate", + "format_datetime", + "getaddresses", + "make_msgid", + "mktime_tz", + "parseaddr", + "parsedate", + "parsedate_tz", + "parsedate_to_datetime", + "unquote", +] + +_PDTZ = tuple[int, int, int, int, int, int, int, int, int, int | None] def quote(str: str) -> str: ... def unquote(str: str) -> str: ... diff --git a/mypy/typeshed/stdlib/ensurepip/__init__.pyi b/mypy/typeshed/stdlib/ensurepip/__init__.pyi index 749fedc044249..e2686b8d54370 100644 --- a/mypy/typeshed/stdlib/ensurepip/__init__.pyi +++ b/mypy/typeshed/stdlib/ensurepip/__init__.pyi @@ -1,3 +1,5 @@ +__all__ = ["version", "bootstrap"] + def version() -> str: ... def bootstrap( *, diff --git a/mypy/typeshed/stdlib/enum.pyi b/mypy/typeshed/stdlib/enum.pyi index a80a022ad6f50..f49bcd7a00e01 100644 --- a/mypy/typeshed/stdlib/enum.pyi +++ b/mypy/typeshed/stdlib/enum.pyi @@ -1,12 +1,45 @@ import sys import types +from _typeshed import Self from abc import ABCMeta from builtins import property as _builtins_property from collections.abc import Iterable, Iterator, Mapping -from typing import Any, Type, TypeVar, Union, overload +from typing import Any, TypeVar, overload +from typing_extensions import Literal -_T = TypeVar("_T") -_S = TypeVar("_S", bound=Type[Enum]) +if sys.version_info >= (3, 11): + __all__ = [ + "EnumType", + "EnumMeta", + "Enum", + "IntEnum", + "StrEnum", + "Flag", + "IntFlag", + "ReprEnum", + "auto", + "unique", + "property", + "verify", + "FlagBoundary", + "STRICT", + "CONFORM", + "EJECT", + "KEEP", + "global_flag_repr", + "global_enum_repr", + "global_str", + "global_enum", + "EnumCheck", + "CONTINUOUS", + "NAMED_FLAGS", + "UNIQUE", + ] +else: + __all__ = ["EnumMeta", "Enum", "IntEnum", "Flag", "IntFlag", "auto", "unique"] + +_EnumMemberT = TypeVar("_EnumMemberT") +_EnumerationT = TypeVar("_EnumerationT", bound=type[Enum]) # The following all work: # >>> from enum import Enum @@ -19,10 +52,11 @@ _S = TypeVar("_S", bound=Type[Enum]) # # >>> Enum('Foo', names={'RED': 1, 'YELLOW': 2}) # -_EnumNames = Union[str, Iterable[str], Iterable[Iterable[Union[str, Any]]], Mapping[str, Any]] +_EnumNames = str | Iterable[str] | Iterable[Iterable[str | Any]] | Mapping[str, Any] class _EnumDict(dict[str, Any]): def __init__(self) -> None: ... + def __setitem__(self, key: str, value: Any) -> None: ... # Note: EnumMeta actually subclasses type directly, not ABCMeta. # This is a temporary workaround to allow multiple creation of enums with builtins @@ -32,7 +66,7 @@ class _EnumDict(dict[str, Any]): class EnumMeta(ABCMeta): if sys.version_info >= (3, 11): def __new__( - metacls: Type[_T], + metacls: type[Self], # type: ignore cls: str, bases: tuple[type, ...], classdict: _EnumDict, @@ -40,23 +74,32 @@ class EnumMeta(ABCMeta): boundary: FlagBoundary | None = ..., _simple: bool = ..., **kwds: Any, - ) -> _T: ... + ) -> Self: ... elif sys.version_info >= (3, 9): - def __new__(metacls: Type[_T], cls: str, bases: tuple[type, ...], classdict: _EnumDict, **kwds: Any) -> _T: ... # type: ignore + def __new__(metacls: type[Self], cls: str, bases: tuple[type, ...], classdict: _EnumDict, **kwds: Any) -> Self: ... # type: ignore + else: + def __new__(metacls: type[Self], cls: str, bases: tuple[type, ...], classdict: _EnumDict) -> Self: ... # type: ignore + + if sys.version_info >= (3, 9): + @classmethod + def __prepare__(metacls, cls: str, bases: tuple[type, ...], **kwds: Any) -> _EnumDict: ... # type: ignore[override] else: - def __new__(metacls: Type[_T], cls: str, bases: tuple[type, ...], classdict: _EnumDict) -> _T: ... # type: ignore - def __iter__(self: Type[_T]) -> Iterator[_T]: ... - def __reversed__(self: Type[_T]) -> Iterator[_T]: ... - def __contains__(self: Type[Any], member: object) -> bool: ... - def __getitem__(self: Type[_T], name: str) -> _T: ... + @classmethod + def __prepare__(metacls, cls: str, bases: tuple[type, ...]) -> _EnumDict: ... # type: ignore[override] + + def __iter__(self: type[_EnumMemberT]) -> Iterator[_EnumMemberT]: ... + def __reversed__(self: type[_EnumMemberT]) -> Iterator[_EnumMemberT]: ... + def __contains__(self: type[Any], obj: object) -> bool: ... + def __getitem__(self: type[_EnumMemberT], name: str) -> _EnumMemberT: ... @_builtins_property - def __members__(self: Type[_T]) -> types.MappingProxyType[str, _T]: ... + def __members__(self: type[_EnumMemberT]) -> types.MappingProxyType[str, _EnumMemberT]: ... def __len__(self) -> int: ... + def __bool__(self) -> Literal[True]: ... + # Simple value lookup + @overload # type: ignore[override] + def __call__(cls: type[_EnumMemberT], value: Any, names: None = ...) -> _EnumMemberT: ... + # Functional Enum API if sys.version_info >= (3, 11): - # Simple value lookup - @overload # type: ignore[override] - def __call__(cls: Type[_T], value: Any, names: None = ...) -> _T: ... - # Functional Enum API @overload def __call__( cls, @@ -68,10 +111,8 @@ class EnumMeta(ABCMeta): type: type | None = ..., start: int = ..., boundary: FlagBoundary | None = ..., - ) -> Type[Enum]: ... + ) -> type[Enum]: ... else: - @overload # type: ignore[override] - def __call__(cls: Type[_T], value: Any, names: None = ...) -> _T: ... @overload def __call__( cls, @@ -82,7 +123,7 @@ class EnumMeta(ABCMeta): qualname: str | None = ..., type: type | None = ..., start: int = ..., - ) -> Type[Enum]: ... + ) -> type[Enum]: ... _member_names_: list[str] # undocumented _member_map_: dict[str, Enum] # undocumented _value2member_map_: dict[Any, Enum] # undocumented @@ -91,17 +132,19 @@ if sys.version_info >= (3, 11): # In 3.11 `EnumMeta` metaclass is renamed to `EnumType`, but old name also exists. EnumType = EnumMeta + class property(types.DynamicClassAttribute): + def __set_name__(self, ownerclass: type[Enum], name: str) -> None: ... + name: str + clsname: str + _magic_enum_attr = property +else: + _magic_enum_attr = types.DynamicClassAttribute + class Enum(metaclass=EnumMeta): - if sys.version_info >= (3, 11): - @property - def name(self) -> str: ... - @property - def value(self) -> Any: ... - else: - @types.DynamicClassAttribute - def name(self) -> str: ... - @types.DynamicClassAttribute - def value(self) -> Any: ... + @_magic_enum_attr + def name(self) -> str: ... + @_magic_enum_attr + def value(self) -> Any: ... _name_: str _value_: Any if sys.version_info >= (3, 7): @@ -112,76 +155,77 @@ class Enum(metaclass=EnumMeta): def _missing_(cls, value: object) -> Any: ... @staticmethod def _generate_next_value_(name: str, start: int, count: int, last_values: list[Any]) -> Any: ... - def __new__(cls: Type[_T], value: object) -> _T: ... - def __repr__(self) -> str: ... - def __str__(self) -> str: ... + def __new__(cls: type[Self], value: Any) -> Self: ... def __dir__(self) -> list[str]: ... def __format__(self, format_spec: str) -> str: ... def __hash__(self) -> Any: ... def __reduce_ex__(self, proto: object) -> Any: ... -class IntEnum(int, Enum): +if sys.version_info >= (3, 11): + class ReprEnum(Enum): ... + _IntEnumBase = ReprEnum +else: + _IntEnumBase = Enum + +class IntEnum(int, _IntEnumBase): _value_: int - if sys.version_info >= (3, 11): - @property - def value(self) -> int: ... - else: - @types.DynamicClassAttribute - def value(self) -> int: ... - def __new__(cls: Type[_T], value: int | _T) -> _T: ... + @_magic_enum_attr + def value(self) -> int: ... + def __new__(cls: type[Self], value: int) -> Self: ... -def unique(enumeration: _S) -> _S: ... +def unique(enumeration: _EnumerationT) -> _EnumerationT: ... _auto_null: Any # subclassing IntFlag so it picks up all implemented base functions, best modeling behavior of enum.auto() class auto(IntFlag): _value_: Any - if sys.version_info >= (3, 11): - @property - def value(self) -> Any: ... - else: - @types.DynamicClassAttribute - def value(self) -> Any: ... - def __new__(cls: Type[_T]) -> _T: ... + @_magic_enum_attr + def value(self) -> Any: ... + def __new__(cls: type[Self]) -> Self: ... class Flag(Enum): _name_: str | None # type: ignore[assignment] _value_: int - if sys.version_info >= (3, 11): - @property - def name(self) -> str | None: ... # type: ignore[override] - @property - def value(self) -> int: ... - else: - @types.DynamicClassAttribute - def name(self) -> str | None: ... # type: ignore[override] - @types.DynamicClassAttribute - def value(self) -> int: ... - def __contains__(self: _T, other: _T) -> bool: ... - def __repr__(self) -> str: ... - def __str__(self) -> str: ... + @_magic_enum_attr + def name(self) -> str | None: ... # type: ignore[override] + @_magic_enum_attr + def value(self) -> int: ... + def __contains__(self: Self, other: Self) -> bool: ... def __bool__(self) -> bool: ... - def __or__(self: _T, other: _T) -> _T: ... - def __and__(self: _T, other: _T) -> _T: ... - def __xor__(self: _T, other: _T) -> _T: ... - def __invert__(self: _T) -> _T: ... + def __or__(self: Self, other: Self) -> Self: ... + def __and__(self: Self, other: Self) -> Self: ... + def __xor__(self: Self, other: Self) -> Self: ... + def __invert__(self: Self) -> Self: ... class IntFlag(int, Flag): - def __new__(cls: Type[_T], value: int | _T) -> _T: ... - def __or__(self: _T, other: int | _T) -> _T: ... - def __and__(self: _T, other: int | _T) -> _T: ... - def __xor__(self: _T, other: int | _T) -> _T: ... - def __ror__(self: _T, n: int | _T) -> _T: ... - def __rand__(self: _T, n: int | _T) -> _T: ... - def __rxor__(self: _T, n: int | _T) -> _T: ... + def __new__(cls: type[Self], value: int) -> Self: ... + def __or__(self: Self, other: int) -> Self: ... + def __and__(self: Self, other: int) -> Self: ... + def __xor__(self: Self, other: int) -> Self: ... + def __ror__(self: Self, other: int) -> Self: ... + def __rand__(self: Self, other: int) -> Self: ... + def __rxor__(self: Self, other: int) -> Self: ... if sys.version_info >= (3, 11): - class StrEnum(str, Enum): - def __new__(cls: Type[_T], value: str | _T) -> _T: ... + class StrEnum(str, ReprEnum): + def __new__(cls: type[Self], value: str) -> Self: ... _value_: str - @property + @_magic_enum_attr def value(self) -> str: ... + + class EnumCheck(StrEnum): + CONTINUOUS: str + NAMED_FLAGS: str + UNIQUE: str + CONTINUOUS = EnumCheck.CONTINUOUS + NAMED_FLAGS = EnumCheck.NAMED_FLAGS + UNIQUE = EnumCheck.UNIQUE + + class verify: + def __init__(self, *checks: EnumCheck) -> None: ... + def __call__(self, enumeration: _EnumerationT) -> _EnumerationT: ... + class FlagBoundary(StrEnum): STRICT: str CONFORM: str @@ -191,10 +235,8 @@ if sys.version_info >= (3, 11): CONFORM = FlagBoundary.CONFORM EJECT = FlagBoundary.EJECT KEEP = FlagBoundary.KEEP - class property(types.DynamicClassAttribute): - def __set_name__(self, ownerclass: Type[Enum], name: str) -> None: ... - name: str - clsname: str - def global_enum(cls: _S) -> _S: ... + + def global_str(self: Enum) -> str: ... + def global_enum(cls: _EnumerationT, update_str: bool = ...) -> _EnumerationT: ... def global_enum_repr(self: Enum) -> str: ... def global_flag_repr(self: Flag) -> str: ... diff --git a/mypy/typeshed/stdlib/errno.pyi b/mypy/typeshed/stdlib/errno.pyi index b053604fc33a3..12410af23e714 100644 --- a/mypy/typeshed/stdlib/errno.pyi +++ b/mypy/typeshed/stdlib/errno.pyi @@ -36,7 +36,7 @@ EMLINK: int EPIPE: int EDOM: int ERANGE: int -EDEADLCK: int +EDEADLK: int ENAMETOOLONG: int ENOLCK: int ENOSYS: int @@ -135,3 +135,24 @@ ENOMEDIUM: int # undocumented ENOTRECOVERABLE: int # undocumented EOWNERDEAD: int # undocumented ERFKILL: int # undocumented +EAUTH: int # undocumented +EBADARCH: int # undocumented +EBADEXEC: int # undocumented +EBADMACHO: int # undocumented +EBADRPC: int # undocumented +EDEVERR: int # undocumented +EFTYPE: int # undocumented +EL: int # undocumented +ELOCKUNMAPPED: int # undocumented +ENEEDAUTH: int # undocumented +ENOATTR: int # undocumented +ENOPOLICY: int # undocumented +ENOTACTIVE: int # undocumented +EPROCLIM: int # undocumented +EPROCUNAVAIL: int # undocumented +EPROGMISMATCH: int # undocumented +EPROGUNAVAIL: int # undocumented +EPWROFF: int # undocumented +EQFULL: int # undocumented +ERPCMISMATCH: int # undocumented +ESHLIBVERS: int # undocumented diff --git a/mypy/typeshed/stdlib/fcntl.pyi b/mypy/typeshed/stdlib/fcntl.pyi index 47766357c83fb..69863bf580fae 100644 --- a/mypy/typeshed/stdlib/fcntl.pyi +++ b/mypy/typeshed/stdlib/fcntl.pyi @@ -6,80 +6,100 @@ from typing_extensions import Literal if sys.platform != "win32": FASYNC: int FD_CLOEXEC: int - DN_ACCESS: int - DN_ATTRIB: int - DN_CREATE: int - DN_DELETE: int - DN_MODIFY: int - DN_MULTISHOT: int - DN_RENAME: int F_DUPFD: int F_DUPFD_CLOEXEC: int - F_FULLFSYNC: int - F_EXLCK: int F_GETFD: int F_GETFL: int - F_GETLEASE: int F_GETLK: int - F_GETLK64: int F_GETOWN: int - F_NOCACHE: int - F_GETSIG: int - F_NOTIFY: int F_RDLCK: int F_SETFD: int F_SETFL: int - F_SETLEASE: int F_SETLK: int - F_SETLK64: int F_SETLKW: int - F_SETLKW64: int - if sys.version_info >= (3, 9) and sys.platform == "linux": - F_OFD_GETLK: int - F_OFD_SETLK: int - F_OFD_SETLKW: int F_SETOWN: int - F_SETSIG: int - F_SHLCK: int F_UNLCK: int F_WRLCK: int - I_ATMARK: int - I_CANPUT: int - I_CKBAND: int - I_FDINSERT: int - I_FIND: int - I_FLUSH: int - I_FLUSHBAND: int - I_GETBAND: int - I_GETCLTIME: int - I_GETSIG: int - I_GRDOPT: int - I_GWROPT: int - I_LINK: int - I_LIST: int - I_LOOK: int - I_NREAD: int - I_PEEK: int - I_PLINK: int - I_POP: int - I_PUNLINK: int - I_PUSH: int - I_RECVFD: int - I_SENDFD: int - I_SETCLTIME: int - I_SETSIG: int - I_SRDOPT: int - I_STR: int - I_SWROPT: int - I_UNLINK: int + if sys.platform == "darwin": + F_FULLFSYNC: int + F_NOCACHE: int + if sys.version_info >= (3, 9): + F_GETPATH: int + if sys.platform == "linux": + F_SETLKW64: int + F_SETSIG: int + F_SHLCK: int + F_SETLK64: int + F_SETLEASE: int + F_GETSIG: int + F_NOTIFY: int + F_EXLCK: int + F_GETLEASE: int + F_GETLK64: int + if sys.version_info >= (3, 8): + F_ADD_SEALS: int + F_GET_SEALS: int + F_SEAL_GROW: int + F_SEAL_SEAL: int + F_SEAL_SHRINK: int + F_SEAL_WRITE: int + if sys.version_info >= (3, 9): + F_OFD_GETLK: int + F_OFD_SETLK: int + F_OFD_SETLKW: int + if sys.version_info >= (3, 10): + F_GETPIPE_SZ: int + F_SETPIPE_SZ: int + + DN_ACCESS: int + DN_ATTRIB: int + DN_CREATE: int + DN_DELETE: int + DN_MODIFY: int + DN_MULTISHOT: int + DN_RENAME: int + LOCK_EX: int - LOCK_MAND: int LOCK_NB: int - LOCK_READ: int - LOCK_RW: int LOCK_SH: int LOCK_UN: int - LOCK_WRITE: int + if sys.platform == "linux": + LOCK_MAND: int + LOCK_READ: int + LOCK_RW: int + LOCK_WRITE: int + + # These are highly problematic, they might be present or not, depends on the specific OS. + if sys.platform == "linux": + I_ATMARK: int + I_CANPUT: int + I_CKBAND: int + I_FDINSERT: int + I_FIND: int + I_FLUSH: int + I_FLUSHBAND: int + I_GETBAND: int + I_GETCLTIME: int + I_GETSIG: int + I_GRDOPT: int + I_GWROPT: int + I_LINK: int + I_LIST: int + I_LOOK: int + I_NREAD: int + I_PEEK: int + I_PLINK: int + I_POP: int + I_PUNLINK: int + I_PUSH: int + I_RECVFD: int + I_SENDFD: int + I_SETCLTIME: int + I_SETSIG: int + I_SRDOPT: int + I_STR: int + I_SWROPT: int + I_UNLINK: int @overload def fcntl(__fd: FileDescriptorLike, __cmd: int, __arg: int = ...) -> int: ... @overload diff --git a/mypy/typeshed/stdlib/filecmp.pyi b/mypy/typeshed/stdlib/filecmp.pyi index 1c3d0a142a331..7c606af407918 100644 --- a/mypy/typeshed/stdlib/filecmp.pyi +++ b/mypy/typeshed/stdlib/filecmp.pyi @@ -2,15 +2,22 @@ import sys from _typeshed import StrOrBytesPath from os import PathLike from typing import Any, AnyStr, Callable, Generic, Iterable, Sequence +from typing_extensions import Literal if sys.version_info >= (3, 9): from types import GenericAlias +__all__ = ["clear_cache", "cmp", "dircmp", "cmpfiles", "DEFAULT_IGNORES"] + DEFAULT_IGNORES: list[str] +BUFSIZE: Literal[8192] def cmp(f1: StrOrBytesPath, f2: StrOrBytesPath, shallow: int | bool = ...) -> bool: ... def cmpfiles( - a: AnyStr | PathLike[AnyStr], b: AnyStr | PathLike[AnyStr], common: Iterable[AnyStr], shallow: int | bool = ... + a: AnyStr | PathLike[AnyStr], + b: AnyStr | PathLike[AnyStr], + common: Iterable[AnyStr | PathLike[AnyStr]], + shallow: int | bool = ..., ) -> tuple[list[AnyStr], list[AnyStr], list[AnyStr]]: ... class dircmp(Generic[AnyStr]): diff --git a/mypy/typeshed/stdlib/fileinput.pyi b/mypy/typeshed/stdlib/fileinput.pyi index 576822059560d..a3b62948ca205 100644 --- a/mypy/typeshed/stdlib/fileinput.pyi +++ b/mypy/typeshed/stdlib/fileinput.pyi @@ -1,7 +1,23 @@ import sys from _typeshed import Self, StrOrBytesPath +from types import TracebackType from typing import IO, Any, AnyStr, Callable, Generic, Iterable, Iterator +__all__ = [ + "input", + "close", + "nextfile", + "filename", + "lineno", + "filelineno", + "fileno", + "isfirstline", + "isstdin", + "FileInput", + "hook_compressed", + "hook_encoded", +] + if sys.version_info >= (3, 9): from types import GenericAlias @@ -46,7 +62,7 @@ def fileno() -> int: ... def isfirstline() -> bool: ... def isstdin() -> bool: ... -class FileInput(Iterable[AnyStr], Generic[AnyStr]): +class FileInput(Iterator[AnyStr], Generic[AnyStr]): if sys.version_info >= (3, 10): def __init__( self, @@ -79,14 +95,18 @@ class FileInput(Iterable[AnyStr], Generic[AnyStr]): mode: str = ..., openhook: Callable[[StrOrBytesPath, str], IO[AnyStr]] = ..., ) -> None: ... + def __del__(self) -> None: ... def close(self) -> None: ... def __enter__(self: Self) -> Self: ... - def __exit__(self, type: Any, value: Any, traceback: Any) -> None: ... - def __iter__(self) -> Iterator[AnyStr]: ... + def __exit__( + self, type: type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None + ) -> None: ... + def __iter__(self: Self) -> Self: ... def __next__(self) -> AnyStr: ... if sys.version_info < (3, 11): def __getitem__(self, i: int) -> AnyStr: ... + def nextfile(self) -> None: ... def readline(self) -> AnyStr: ... def filename(self) -> str: ... diff --git a/mypy/typeshed/stdlib/fnmatch.pyi b/mypy/typeshed/stdlib/fnmatch.pyi index 1cbcf00729ede..8351fce59ebb4 100644 --- a/mypy/typeshed/stdlib/fnmatch.pyi +++ b/mypy/typeshed/stdlib/fnmatch.pyi @@ -1,5 +1,7 @@ from typing import AnyStr, Iterable +__all__ = ["filter", "fnmatch", "fnmatchcase", "translate"] + def fnmatch(name: AnyStr, pat: AnyStr) -> bool: ... def fnmatchcase(name: AnyStr, pat: AnyStr) -> bool: ... def filter(names: Iterable[AnyStr], pat: AnyStr) -> list[AnyStr]: ... diff --git a/mypy/typeshed/stdlib/fractions.pyi b/mypy/typeshed/stdlib/fractions.pyi index 8de5ae20971c9..00989fb1fc029 100644 --- a/mypy/typeshed/stdlib/fractions.pyi +++ b/mypy/typeshed/stdlib/fractions.pyi @@ -1,13 +1,16 @@ import sys +from _typeshed import Self from decimal import Decimal from numbers import Integral, Rational, Real -from typing import Type, TypeVar, Union, overload +from typing import Any, overload from typing_extensions import Literal -_ComparableNum = Union[int, float, Decimal, Real] -_T = TypeVar("_T") +_ComparableNum = int | float | Decimal | Real -if sys.version_info < (3, 9): +if sys.version_info >= (3, 9): + __all__ = ["Fraction"] +else: + __all__ = ["Fraction", "gcd"] @overload def gcd(a: int, b: int) -> int: ... @overload @@ -20,103 +23,104 @@ if sys.version_info < (3, 9): class Fraction(Rational): @overload def __new__( - cls: Type[_T], numerator: int | Rational = ..., denominator: int | Rational | None = ..., *, _normalize: bool = ... - ) -> _T: ... + cls: type[Self], numerator: int | Rational = ..., denominator: int | Rational | None = ..., *, _normalize: bool = ... + ) -> Self: ... @overload - def __new__(cls: Type[_T], __value: float | Decimal | str, *, _normalize: bool = ...) -> _T: ... + def __new__(cls: type[Self], __value: float | Decimal | str, *, _normalize: bool = ...) -> Self: ... @classmethod - def from_float(cls, f: float) -> Fraction: ... + def from_float(cls: type[Self], f: float) -> Self: ... @classmethod - def from_decimal(cls, dec: Decimal) -> Fraction: ... + def from_decimal(cls: type[Self], dec: Decimal) -> Self: ... def limit_denominator(self, max_denominator: int = ...) -> Fraction: ... if sys.version_info >= (3, 8): def as_integer_ratio(self) -> tuple[int, int]: ... + @property def numerator(self) -> int: ... @property def denominator(self) -> int: ... @overload - def __add__(self, other: int | Fraction) -> Fraction: ... + def __add__(self, b: int | Fraction) -> Fraction: ... @overload - def __add__(self, other: float) -> float: ... + def __add__(self, b: float) -> float: ... @overload - def __add__(self, other: complex) -> complex: ... + def __add__(self, b: complex) -> complex: ... @overload - def __radd__(self, other: int | Fraction) -> Fraction: ... + def __radd__(self, a: int | Fraction) -> Fraction: ... @overload - def __radd__(self, other: float) -> float: ... + def __radd__(self, a: float) -> float: ... @overload - def __radd__(self, other: complex) -> complex: ... + def __radd__(self, a: complex) -> complex: ... @overload - def __sub__(self, other: int | Fraction) -> Fraction: ... + def __sub__(self, b: int | Fraction) -> Fraction: ... @overload - def __sub__(self, other: float) -> float: ... + def __sub__(self, b: float) -> float: ... @overload - def __sub__(self, other: complex) -> complex: ... + def __sub__(self, b: complex) -> complex: ... @overload - def __rsub__(self, other: int | Fraction) -> Fraction: ... + def __rsub__(self, a: int | Fraction) -> Fraction: ... @overload - def __rsub__(self, other: float) -> float: ... + def __rsub__(self, a: float) -> float: ... @overload - def __rsub__(self, other: complex) -> complex: ... + def __rsub__(self, a: complex) -> complex: ... @overload - def __mul__(self, other: int | Fraction) -> Fraction: ... + def __mul__(self, b: int | Fraction) -> Fraction: ... @overload - def __mul__(self, other: float) -> float: ... + def __mul__(self, b: float) -> float: ... @overload - def __mul__(self, other: complex) -> complex: ... + def __mul__(self, b: complex) -> complex: ... @overload - def __rmul__(self, other: int | Fraction) -> Fraction: ... + def __rmul__(self, a: int | Fraction) -> Fraction: ... @overload - def __rmul__(self, other: float) -> float: ... + def __rmul__(self, a: float) -> float: ... @overload - def __rmul__(self, other: complex) -> complex: ... + def __rmul__(self, a: complex) -> complex: ... @overload - def __truediv__(self, other: int | Fraction) -> Fraction: ... + def __truediv__(self, b: int | Fraction) -> Fraction: ... @overload - def __truediv__(self, other: float) -> float: ... + def __truediv__(self, b: float) -> float: ... @overload - def __truediv__(self, other: complex) -> complex: ... + def __truediv__(self, b: complex) -> complex: ... @overload - def __rtruediv__(self, other: int | Fraction) -> Fraction: ... + def __rtruediv__(self, a: int | Fraction) -> Fraction: ... @overload - def __rtruediv__(self, other: float) -> float: ... + def __rtruediv__(self, a: float) -> float: ... @overload - def __rtruediv__(self, other: complex) -> complex: ... + def __rtruediv__(self, a: complex) -> complex: ... @overload - def __floordiv__(self, other: int | Fraction) -> int: ... + def __floordiv__(self, b: int | Fraction) -> int: ... @overload - def __floordiv__(self, other: float) -> float: ... + def __floordiv__(self, b: float) -> float: ... @overload - def __rfloordiv__(self, other: int | Fraction) -> int: ... + def __rfloordiv__(self, a: int | Fraction) -> int: ... @overload - def __rfloordiv__(self, other: float) -> float: ... + def __rfloordiv__(self, a: float) -> float: ... @overload - def __mod__(self, other: int | Fraction) -> Fraction: ... + def __mod__(self, b: int | Fraction) -> Fraction: ... @overload - def __mod__(self, other: float) -> float: ... + def __mod__(self, b: float) -> float: ... @overload - def __rmod__(self, other: int | Fraction) -> Fraction: ... + def __rmod__(self, a: int | Fraction) -> Fraction: ... @overload - def __rmod__(self, other: float) -> float: ... + def __rmod__(self, a: float) -> float: ... @overload - def __divmod__(self, other: int | Fraction) -> tuple[int, Fraction]: ... + def __divmod__(self, b: int | Fraction) -> tuple[int, Fraction]: ... @overload - def __divmod__(self, other: float) -> tuple[float, Fraction]: ... + def __divmod__(self, b: float) -> tuple[float, Fraction]: ... @overload - def __rdivmod__(self, other: int | Fraction) -> tuple[int, Fraction]: ... + def __rdivmod__(self, a: int | Fraction) -> tuple[int, Fraction]: ... @overload - def __rdivmod__(self, other: float) -> tuple[float, Fraction]: ... + def __rdivmod__(self, a: float) -> tuple[float, Fraction]: ... @overload - def __pow__(self, other: int) -> Fraction: ... + def __pow__(self, b: int) -> Fraction: ... @overload - def __pow__(self, other: float | Fraction) -> float: ... + def __pow__(self, b: float | Fraction) -> float: ... @overload - def __pow__(self, other: complex) -> complex: ... + def __pow__(self, b: complex) -> complex: ... @overload - def __rpow__(self, other: int | float | Fraction) -> float: ... + def __rpow__(self, a: int | float | Fraction) -> float: ... @overload - def __rpow__(self, other: complex) -> complex: ... + def __rpow__(self, a: complex) -> complex: ... def __pos__(self) -> Fraction: ... def __neg__(self) -> Fraction: ... def __abs__(self) -> Fraction: ... @@ -128,12 +132,14 @@ class Fraction(Rational): @overload def __round__(self, ndigits: int) -> Fraction: ... def __hash__(self) -> int: ... - def __eq__(self, other: object) -> bool: ... - def __lt__(self, other: _ComparableNum) -> bool: ... - def __gt__(self, other: _ComparableNum) -> bool: ... - def __le__(self, other: _ComparableNum) -> bool: ... - def __ge__(self, other: _ComparableNum) -> bool: ... + def __eq__(self, b: object) -> bool: ... + def __lt__(self, b: _ComparableNum) -> bool: ... + def __gt__(self, b: _ComparableNum) -> bool: ... + def __le__(self, b: _ComparableNum) -> bool: ... + def __ge__(self, b: _ComparableNum) -> bool: ... def __bool__(self) -> bool: ... + def __copy__(self: Self) -> Self: ... + def __deepcopy__(self: Self, memo: Any) -> Self: ... if sys.version_info >= (3, 11): def __int__(self) -> int: ... # Not actually defined within fractions.py, but provides more useful diff --git a/mypy/typeshed/stdlib/ftplib.pyi b/mypy/typeshed/stdlib/ftplib.pyi index f84199c168e98..4a5dad0dd14ff 100644 --- a/mypy/typeshed/stdlib/ftplib.pyi +++ b/mypy/typeshed/stdlib/ftplib.pyi @@ -3,14 +3,16 @@ from _typeshed import Self, SupportsRead, SupportsReadline from socket import socket from ssl import SSLContext from types import TracebackType -from typing import Any, Callable, Iterable, Iterator, TextIO, Type +from typing import Any, Callable, Iterable, Iterator, TextIO from typing_extensions import Literal -MSG_OOB: int -FTP_PORT: int -MAXLINE: int -CRLF: str -B_CRLF: bytes +__all__ = ["FTP", "error_reply", "error_temp", "error_perm", "error_proto", "all_errors", "FTP_TLS"] + +MSG_OOB: Literal[1] +FTP_PORT: Literal[21] +MAXLINE: Literal[8192] +CRLF: Literal["\r\n"] +B_CRLF: Literal[b"\r\n"] class Error(Exception): ... class error_reply(Error): ... @@ -18,7 +20,7 @@ class error_temp(Error): ... class error_perm(Error): ... class error_proto(Error): ... -all_errors: tuple[Type[Exception], ...] +all_errors: tuple[type[Exception], ...] class FTP: debugging: int @@ -35,7 +37,7 @@ class FTP: encoding: str def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> None: ... source_address: tuple[str, int] | None if sys.version_info >= (3, 9): @@ -60,6 +62,7 @@ class FTP: timeout: float = ..., source_address: tuple[str, int] | None = ..., ) -> None: ... + def connect( self, host: str = ..., port: int = ..., timeout: float = ..., source_address: tuple[str, int] | None = ... ) -> str: ... diff --git a/mypy/typeshed/stdlib/functools.pyi b/mypy/typeshed/stdlib/functools.pyi index 990fed20d80da..741a53ed82a28 100644 --- a/mypy/typeshed/stdlib/functools.pyi +++ b/mypy/typeshed/stdlib/functools.pyi @@ -1,12 +1,59 @@ import sys import types -from _typeshed import SupportsAllComparisons, SupportsItems -from typing import Any, Callable, Generic, Hashable, Iterable, NamedTuple, Sequence, Sized, Type, TypeVar, overload -from typing_extensions import final +from _typeshed import Self, SupportsAllComparisons, SupportsItems +from typing import Any, Callable, Generic, Hashable, Iterable, NamedTuple, Sequence, Sized, TypeVar, overload +from typing_extensions import Literal, final if sys.version_info >= (3, 9): from types import GenericAlias + __all__ = [ + "update_wrapper", + "wraps", + "WRAPPER_ASSIGNMENTS", + "WRAPPER_UPDATES", + "total_ordering", + "cache", + "cmp_to_key", + "lru_cache", + "reduce", + "partial", + "partialmethod", + "singledispatch", + "singledispatchmethod", + "cached_property", + ] +elif sys.version_info >= (3, 8): + __all__ = [ + "update_wrapper", + "wraps", + "WRAPPER_ASSIGNMENTS", + "WRAPPER_UPDATES", + "total_ordering", + "cmp_to_key", + "lru_cache", + "reduce", + "partial", + "partialmethod", + "singledispatch", + "singledispatchmethod", + "cached_property", + ] +else: + __all__ = [ + "update_wrapper", + "wraps", + "WRAPPER_ASSIGNMENTS", + "WRAPPER_UPDATES", + "total_ordering", + "cmp_to_key", + "lru_cache", + "reduce", + "partial", + "partialmethod", + "singledispatch", + ] + _AnyCallable = Callable[..., Any] _T = TypeVar("_T") @@ -29,6 +76,8 @@ class _lru_cache_wrapper(Generic[_T]): def __call__(self, *args: Hashable, **kwargs: Hashable) -> _T: ... def cache_info(self) -> _CacheInfo: ... def cache_clear(self) -> None: ... + def __copy__(self) -> _lru_cache_wrapper[_T]: ... + def __deepcopy__(self, __memo: Any) -> _lru_cache_wrapper[_T]: ... if sys.version_info >= (3, 8): @overload @@ -39,20 +88,25 @@ if sys.version_info >= (3, 8): else: def lru_cache(maxsize: int | None = ..., typed: bool = ...) -> Callable[[Callable[..., _T]], _lru_cache_wrapper[_T]]: ... -WRAPPER_ASSIGNMENTS: Sequence[str] -WRAPPER_UPDATES: Sequence[str] +WRAPPER_ASSIGNMENTS: tuple[ + Literal["__module__"], Literal["__name__"], Literal["__qualname__"], Literal["__doc__"], Literal["__annotations__"], +] +WRAPPER_UPDATES: tuple[Literal["__dict__"]] def update_wrapper(wrapper: _T, wrapped: _AnyCallable, assigned: Sequence[str] = ..., updated: Sequence[str] = ...) -> _T: ... def wraps(wrapped: _AnyCallable, assigned: Sequence[str] = ..., updated: Sequence[str] = ...) -> Callable[[_T], _T]: ... -def total_ordering(cls: Type[_T]) -> Type[_T]: ... +def total_ordering(cls: type[_T]) -> type[_T]: ... def cmp_to_key(mycmp: Callable[[_T, _T], int]) -> Callable[[_T], SupportsAllComparisons]: ... class partial(Generic[_T]): - func: Callable[..., _T] - args: tuple[Any, ...] - keywords: dict[str, Any] - def __new__(cls: Type[_S], __func: Callable[..., _T], *args: Any, **kwargs: Any) -> _S: ... - def __call__(self, *args: Any, **kwargs: Any) -> _T: ... + @property + def func(self) -> Callable[..., _T]: ... + @property + def args(self) -> tuple[Any, ...]: ... + @property + def keywords(self) -> dict[str, Any]: ... + def __new__(cls: type[Self], __func: Callable[..., _T], *args: Any, **kwargs: Any) -> Self: ... + def __call__(__self, *args: Any, **kwargs: Any) -> _T: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... @@ -67,7 +121,11 @@ class partialmethod(Generic[_T]): def __init__(self, __func: Callable[..., _T], *args: Any, **keywords: Any) -> None: ... @overload def __init__(self, __func: _Descriptor, *args: Any, **keywords: Any) -> None: ... - def __get__(self, obj: Any, cls: Type[Any]) -> Callable[..., _T]: ... + if sys.version_info >= (3, 8): + def __get__(self, obj: Any, cls: type[Any] | None = ...) -> Callable[..., _T]: ... + else: + def __get__(self, obj: Any, cls: type[Any] | None) -> Callable[..., _T]: ... + @property def __isabstractmethod__(self) -> bool: ... if sys.version_info >= (3, 9): @@ -79,16 +137,16 @@ class _SingleDispatchCallable(Generic[_T]): # @fun.register(complex) # def _(arg, verbose=False): ... @overload - def register(self, cls: Type[Any], func: None = ...) -> Callable[[Callable[..., _T]], Callable[..., _T]]: ... + def register(self, cls: type[Any], func: None = ...) -> Callable[[Callable[..., _T]], Callable[..., _T]]: ... # @fun.register # def _(arg: int, verbose=False): @overload def register(self, cls: Callable[..., _T], func: None = ...) -> Callable[..., _T]: ... # fun.register(int, lambda x: x) @overload - def register(self, cls: Type[Any], func: Callable[..., _T]) -> Callable[..., _T]: ... + def register(self, cls: type[Any], func: Callable[..., _T]) -> Callable[..., _T]: ... def _clear_cache(self) -> None: ... - def __call__(self, *args: Any, **kwargs: Any) -> _T: ... + def __call__(__self, *args: Any, **kwargs: Any) -> _T: ... def singledispatch(func: Callable[..., _T]) -> _SingleDispatchCallable[_T]: ... @@ -97,22 +155,25 @@ if sys.version_info >= (3, 8): dispatcher: _SingleDispatchCallable[_T] func: Callable[..., _T] def __init__(self, func: Callable[..., _T]) -> None: ... + @property + def __isabstractmethod__(self) -> bool: ... @overload - def register(self, cls: Type[Any], method: None = ...) -> Callable[[Callable[..., _T]], Callable[..., _T]]: ... + def register(self, cls: type[Any], method: None = ...) -> Callable[[Callable[..., _T]], Callable[..., _T]]: ... @overload def register(self, cls: Callable[..., _T], method: None = ...) -> Callable[..., _T]: ... @overload - def register(self, cls: Type[Any], method: Callable[..., _T]) -> Callable[..., _T]: ... - def __call__(self, *args: Any, **kwargs: Any) -> _T: ... + def register(self, cls: type[Any], method: Callable[..., _T]) -> Callable[..., _T]: ... + def __get__(self, obj: _S, cls: type[_S] | None = ...) -> Callable[..., _T]: ... + class cached_property(Generic[_T]): func: Callable[[Any], _T] attrname: str | None def __init__(self, func: Callable[[Any], _T]) -> None: ... @overload - def __get__(self, instance: None, owner: Type[Any] | None = ...) -> cached_property[_T]: ... + def __get__(self, instance: None, owner: type[Any] | None = ...) -> cached_property[_T]: ... @overload - def __get__(self, instance: object, owner: Type[Any] | None = ...) -> _T: ... - def __set_name__(self, owner: Type[Any], name: str) -> None: ... + def __get__(self, instance: object, owner: type[Any] | None = ...) -> _T: ... + def __set_name__(self, owner: type[Any], name: str) -> None: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... diff --git a/mypy/typeshed/stdlib/gc.pyi b/mypy/typeshed/stdlib/gc.pyi index 39d2776783efe..7c15e0f5b0a23 100644 --- a/mypy/typeshed/stdlib/gc.pyi +++ b/mypy/typeshed/stdlib/gc.pyi @@ -1,12 +1,16 @@ import sys -from typing import Any - -DEBUG_COLLECTABLE: int -DEBUG_LEAK: int -DEBUG_SAVEALL: int -DEBUG_STATS: int -DEBUG_UNCOLLECTABLE: int -callbacks: list[Any] +from typing import Any, Callable +from typing_extensions import Literal + +DEBUG_COLLECTABLE: Literal[2] +DEBUG_LEAK: Literal[38] +DEBUG_SAVEALL: Literal[32] +DEBUG_STATS: Literal[1] +DEBUG_UNCOLLECTABLE: Literal[4] + +_CallbackType = Callable[[Literal["start", "stop"], dict[str, int]], object] + +callbacks: list[_CallbackType] garbage: list[Any] def collect(generation: int = ...) -> int: ... diff --git a/mypy/typeshed/stdlib/genericpath.pyi b/mypy/typeshed/stdlib/genericpath.pyi index f9518750d3f1f..3abedda262ea4 100644 --- a/mypy/typeshed/stdlib/genericpath.pyi +++ b/mypy/typeshed/stdlib/genericpath.pyi @@ -3,6 +3,20 @@ from _typeshed import BytesPath, StrOrBytesPath, StrPath, SupportsRichComparison from typing import Sequence, overload from typing_extensions import Literal +__all__ = [ + "commonprefix", + "exists", + "getatime", + "getctime", + "getmtime", + "getsize", + "isdir", + "isfile", + "samefile", + "sameopenfile", + "samestat", +] + # All overloads can return empty string. Ideally, Literal[""] would be a valid # Iterable[T], so that list[T] | Literal[""] could be used as a return # type. But because this only works when T is str, we need Sequence[T] instead. diff --git a/mypy/typeshed/stdlib/getopt.pyi b/mypy/typeshed/stdlib/getopt.pyi index 6ae226f52972b..42ddb1cb7020b 100644 --- a/mypy/typeshed/stdlib/getopt.pyi +++ b/mypy/typeshed/stdlib/getopt.pyi @@ -1,3 +1,5 @@ +__all__ = ["GetoptError", "error", "getopt", "gnu_getopt"] + def getopt(args: list[str], shortopts: str, longopts: list[str] = ...) -> tuple[list[tuple[str, str]], list[str]]: ... def gnu_getopt(args: list[str], shortopts: str, longopts: list[str] = ...) -> tuple[list[tuple[str, str]], list[str]]: ... diff --git a/mypy/typeshed/stdlib/getpass.pyi b/mypy/typeshed/stdlib/getpass.pyi index 27f4c6a9b635c..153db2f4cb9e4 100644 --- a/mypy/typeshed/stdlib/getpass.pyi +++ b/mypy/typeshed/stdlib/getpass.pyi @@ -1,5 +1,7 @@ from typing import TextIO +__all__ = ["getpass", "getuser", "GetPassWarning"] + def getpass(prompt: str = ..., stream: TextIO | None = ...) -> str: ... def getuser() -> str: ... diff --git a/mypy/typeshed/stdlib/gettext.pyi b/mypy/typeshed/stdlib/gettext.pyi index 21be9fb1ff299..1f3ef67ab0f34 100644 --- a/mypy/typeshed/stdlib/gettext.pyi +++ b/mypy/typeshed/stdlib/gettext.pyi @@ -1,8 +1,72 @@ import sys from _typeshed import StrPath -from typing import IO, Any, Container, Iterable, Sequence, Type, TypeVar, overload +from typing import IO, Any, Container, Iterable, Sequence, TypeVar, overload from typing_extensions import Literal +if sys.version_info >= (3, 11): + __all__ = [ + "NullTranslations", + "GNUTranslations", + "Catalog", + "bindtextdomain", + "find", + "translation", + "install", + "textdomain", + "dgettext", + "dngettext", + "gettext", + "ngettext", + "pgettext", + "dpgettext", + "npgettext", + "dnpgettext", + ] +elif sys.version_info >= (3, 8): + __all__ = [ + "NullTranslations", + "GNUTranslations", + "Catalog", + "find", + "translation", + "install", + "textdomain", + "bindtextdomain", + "bind_textdomain_codeset", + "dgettext", + "dngettext", + "gettext", + "lgettext", + "ldgettext", + "ldngettext", + "lngettext", + "ngettext", + "pgettext", + "dpgettext", + "npgettext", + "dnpgettext", + ] +else: + __all__ = [ + "NullTranslations", + "GNUTranslations", + "Catalog", + "find", + "translation", + "install", + "textdomain", + "bindtextdomain", + "bind_textdomain_codeset", + "dgettext", + "dngettext", + "gettext", + "lgettext", + "ldgettext", + "ldngettext", + "lngettext", + "ngettext", + ] + class NullTranslations: def __init__(self, fp: IO[str] | None = ...) -> None: ... def _parse(self, fp: IO[str]) -> None: ... @@ -14,11 +78,13 @@ class NullTranslations: if sys.version_info >= (3, 8): def pgettext(self, context: str, message: str) -> str: ... def npgettext(self, context: str, msgid1: str, msgid2: str, n: int) -> str: ... + def info(self) -> Any: ... def charset(self) -> Any: ... if sys.version_info < (3, 11): def output_charset(self) -> Any: ... def set_output_charset(self, charset: str) -> None: ... + def install(self, names: Container[str] | None = ...) -> None: ... class GNUTranslations(NullTranslations): @@ -27,6 +93,15 @@ class GNUTranslations(NullTranslations): CONTEXT: str VERSIONS: Sequence[int] +@overload # ignores incompatible overloads +def find( # type: ignore[misc] + domain: str, localedir: StrPath | None = ..., languages: Iterable[str] | None = ..., all: Literal[False] = ... +) -> str | None: ... +@overload +def find( + domain: str, localedir: StrPath | None = ..., languages: Iterable[str] | None = ..., all: Literal[True] = ... +) -> list[str]: ... +@overload def find(domain: str, localedir: StrPath | None = ..., languages: Iterable[str] | None = ..., all: bool = ...) -> Any: ... _T = TypeVar("_T") @@ -45,7 +120,7 @@ if sys.version_info >= (3, 11): domain: str, localedir: StrPath | None = ..., languages: Iterable[str] | None = ..., - class_: Type[_T] = ..., + class_: type[_T] = ..., fallback: Literal[False] = ..., ) -> _T: ... @overload @@ -53,7 +128,7 @@ if sys.version_info >= (3, 11): domain: str, localedir: StrPath | None = ..., languages: Iterable[str] | None = ..., - class_: Type[Any] = ..., + class_: type[Any] = ..., fallback: Literal[True] = ..., ) -> Any: ... def install(domain: str, localedir: StrPath | None = ..., names: Container[str] | None = ...) -> None: ... @@ -73,7 +148,7 @@ else: domain: str, localedir: StrPath | None = ..., languages: Iterable[str] | None = ..., - class_: Type[_T] = ..., + class_: type[_T] = ..., fallback: Literal[False] = ..., codeset: str | None = ..., ) -> _T: ... @@ -82,7 +157,7 @@ else: domain: str, localedir: StrPath | None = ..., languages: Iterable[str] | None = ..., - class_: Type[Any] = ..., + class_: type[Any] = ..., fallback: Literal[True] = ..., codeset: str | None = ..., ) -> Any: ... diff --git a/mypy/typeshed/stdlib/glob.pyi b/mypy/typeshed/stdlib/glob.pyi index c1cd176f500c2..ced0ceceb205a 100644 --- a/mypy/typeshed/stdlib/glob.pyi +++ b/mypy/typeshed/stdlib/glob.pyi @@ -2,10 +2,30 @@ import sys from _typeshed import StrOrBytesPath from typing import AnyStr, Iterator +__all__ = ["escape", "glob", "iglob"] + def glob0(dirname: AnyStr, pattern: AnyStr) -> list[AnyStr]: ... def glob1(dirname: AnyStr, pattern: AnyStr) -> list[AnyStr]: ... -if sys.version_info >= (3, 10): +if sys.version_info >= (3, 11): + def glob( + pathname: AnyStr, + *, + root_dir: StrOrBytesPath | None = ..., + dir_fd: int | None = ..., + recursive: bool = ..., + include_hidden: bool = ..., + ) -> list[AnyStr]: ... + def iglob( + pathname: AnyStr, + *, + root_dir: StrOrBytesPath | None = ..., + dir_fd: int | None = ..., + recursive: bool = ..., + include_hidden: bool = ..., + ) -> Iterator[AnyStr]: ... + +elif sys.version_info >= (3, 10): def glob( pathname: AnyStr, *, root_dir: StrOrBytesPath | None = ..., dir_fd: int | None = ..., recursive: bool = ... ) -> list[AnyStr]: ... diff --git a/mypy/typeshed/stdlib/graphlib.pyi b/mypy/typeshed/stdlib/graphlib.pyi index 96d64cbce18cc..cae2a07e95c6b 100644 --- a/mypy/typeshed/stdlib/graphlib.pyi +++ b/mypy/typeshed/stdlib/graphlib.pyi @@ -1,8 +1,14 @@ +import sys from _typeshed import SupportsItems -from typing import Generic, Iterable, TypeVar +from typing import Any, Generic, Iterable, TypeVar + +__all__ = ["TopologicalSorter", "CycleError"] _T = TypeVar("_T") +if sys.version_info >= (3, 11): + from types import GenericAlias + class TopologicalSorter(Generic[_T]): def __init__(self, graph: SupportsItems[_T, Iterable[_T]] | None = ...) -> None: ... def add(self, node: _T, *predecessors: _T) -> None: ... @@ -12,5 +18,7 @@ class TopologicalSorter(Generic[_T]): def done(self, *nodes: _T) -> None: ... def get_ready(self) -> tuple[_T, ...]: ... def static_order(self) -> Iterable[_T]: ... + if sys.version_info >= (3, 11): + def __class_getitem__(cls, item: Any) -> GenericAlias: ... class CycleError(ValueError): ... diff --git a/mypy/typeshed/stdlib/grp.pyi b/mypy/typeshed/stdlib/grp.pyi index b416269921d6d..4b66b84b63891 100644 --- a/mypy/typeshed/stdlib/grp.pyi +++ b/mypy/typeshed/stdlib/grp.pyi @@ -1,11 +1,13 @@ import sys from _typeshed import structseq -from typing import Any, Optional -from typing_extensions import final +from typing import Any +from typing_extensions import Final, final if sys.platform != "win32": @final - class struct_group(structseq[Any], tuple[str, Optional[str], int, list[str]]): + class struct_group(structseq[Any], tuple[str, str | None, int, list[str]]): + if sys.version_info >= (3, 10): + __match_args__: Final = ("gr_name", "gr_passwd", "gr_gid", "gr_mem") @property def gr_name(self) -> str: ... @property @@ -14,6 +16,7 @@ if sys.platform != "win32": def gr_gid(self) -> int: ... @property def gr_mem(self) -> list[str]: ... + def getgrall() -> list[struct_group]: ... def getgrgid(id: int) -> struct_group: ... def getgrnam(name: str) -> struct_group: ... diff --git a/mypy/typeshed/stdlib/gzip.pyi b/mypy/typeshed/stdlib/gzip.pyi index 070ceac482826..7347949ae865f 100644 --- a/mypy/typeshed/stdlib/gzip.pyi +++ b/mypy/typeshed/stdlib/gzip.pyi @@ -6,6 +6,11 @@ from io import FileIO from typing import Any, Protocol, TextIO, overload from typing_extensions import Literal +if sys.version_info >= (3, 8): + __all__ = ["BadGzipFile", "GzipFile", "open", "compress", "decompress"] +else: + __all__ = ["GzipFile", "open", "compress", "decompress"] + _ReadBinaryMode = Literal["r", "rb"] _WriteBinaryMode = Literal["a", "ab", "w", "wb", "x", "xb"] _OpenTextMode = Literal["rt", "at", "wt", "xt"] diff --git a/mypy/typeshed/stdlib/hashlib.pyi b/mypy/typeshed/stdlib/hashlib.pyi index fad3c5aad457c..4332153d281cc 100644 --- a/mypy/typeshed/stdlib/hashlib.pyi +++ b/mypy/typeshed/stdlib/hashlib.pyi @@ -1,6 +1,28 @@ import sys from _typeshed import ReadableBuffer, Self from typing import AbstractSet +from typing_extensions import final + +__all__ = ( + "md5", + "sha1", + "sha224", + "sha256", + "sha384", + "sha512", + "blake2b", + "blake2s", + "sha3_224", + "sha3_256", + "sha3_384", + "sha3_512", + "shake_128", + "shake_256", + "new", + "algorithms_guaranteed", + "algorithms_available", + "pbkdf2_hmac", +) class _Hash: @property @@ -76,7 +98,7 @@ def scrypt( maxmem: int = ..., dklen: int = ..., ) -> bytes: ... - +@final class _BlakeHash(_Hash): MAX_DIGEST_SIZE: int MAX_KEY_SIZE: int diff --git a/mypy/typeshed/stdlib/heapq.pyi b/mypy/typeshed/stdlib/heapq.pyi index fd3c2db8ad668..a7a787d44e626 100644 --- a/mypy/typeshed/stdlib/heapq.pyi +++ b/mypy/typeshed/stdlib/heapq.pyi @@ -1,14 +1,14 @@ +from _heapq import * from _typeshed import SupportsRichComparison from typing import Any, Callable, Iterable, TypeVar -_T = TypeVar("_T") +__all__ = ["heappush", "heappop", "heapify", "heapreplace", "merge", "nlargest", "nsmallest", "heappushpop"] -def heappush(__heap: list[_T], __item: _T) -> None: ... -def heappop(__heap: list[_T]) -> _T: ... -def heappushpop(__heap: list[_T], __item: _T) -> _T: ... -def heapify(__heap: list[Any]) -> None: ... -def heapreplace(__heap: list[_T], __item: _T) -> _T: ... -def merge(*iterables: Iterable[_T], key: Callable[[_T], Any] | None = ..., reverse: bool = ...) -> Iterable[_T]: ... -def nlargest(n: int, iterable: Iterable[_T], key: Callable[[_T], SupportsRichComparison] | None = ...) -> list[_T]: ... -def nsmallest(n: int, iterable: Iterable[_T], key: Callable[[_T], SupportsRichComparison] | None = ...) -> list[_T]: ... +_S = TypeVar("_S") + +__about__: str + +def merge(*iterables: Iterable[_S], key: Callable[[_S], Any] | None = ..., reverse: bool = ...) -> Iterable[_S]: ... +def nlargest(n: int, iterable: Iterable[_S], key: Callable[[_S], SupportsRichComparison] | None = ...) -> list[_S]: ... +def nsmallest(n: int, iterable: Iterable[_S], key: Callable[[_S], SupportsRichComparison] | None = ...) -> list[_S]: ... def _heapify_max(__x: list[Any]) -> None: ... # undocumented diff --git a/mypy/typeshed/stdlib/hmac.pyi b/mypy/typeshed/stdlib/hmac.pyi index 88c88631f99a1..6d355147f51ef 100644 --- a/mypy/typeshed/stdlib/hmac.pyi +++ b/mypy/typeshed/stdlib/hmac.pyi @@ -1,11 +1,11 @@ import sys from _typeshed import ReadableBuffer from types import ModuleType -from typing import Any, AnyStr, Callable, Union, overload +from typing import Any, AnyStr, Callable, overload # TODO more precise type for object of hashlib _Hash = Any -_DigestMod = Union[str, Callable[[], _Hash], ModuleType] +_DigestMod = str | Callable[[], _Hash] | ModuleType trans_5C: bytes trans_36: bytes @@ -26,7 +26,8 @@ else: class HMAC: digest_size: int block_size: int - name: str + @property + def name(self) -> str: ... def __init__(self, key: bytes, msg: ReadableBuffer | None = ..., digestmod: _DigestMod = ...) -> None: ... def update(self, msg: ReadableBuffer) -> None: ... def digest(self) -> bytes: ... diff --git a/mypy/typeshed/stdlib/html/__init__.pyi b/mypy/typeshed/stdlib/html/__init__.pyi index af2a800216562..109c5f4b50fbe 100644 --- a/mypy/typeshed/stdlib/html/__init__.pyi +++ b/mypy/typeshed/stdlib/html/__init__.pyi @@ -1,4 +1,6 @@ from typing import AnyStr +__all__ = ["escape", "unescape"] + def escape(s: AnyStr, quote: bool = ...) -> AnyStr: ... def unescape(s: AnyStr) -> AnyStr: ... diff --git a/mypy/typeshed/stdlib/html/entities.pyi b/mypy/typeshed/stdlib/html/entities.pyi index 1743fccf32b9b..be83fd1135be2 100644 --- a/mypy/typeshed/stdlib/html/entities.pyi +++ b/mypy/typeshed/stdlib/html/entities.pyi @@ -1,3 +1,5 @@ +__all__ = ["html5", "name2codepoint", "codepoint2name", "entitydefs"] + name2codepoint: dict[str, int] html5: dict[str, str] codepoint2name: dict[int, str] diff --git a/mypy/typeshed/stdlib/html/parser.pyi b/mypy/typeshed/stdlib/html/parser.pyi index 60e0de51d3b8a..1731a345920ba 100644 --- a/mypy/typeshed/stdlib/html/parser.pyi +++ b/mypy/typeshed/stdlib/html/parser.pyi @@ -1,6 +1,8 @@ from _markupbase import ParserBase from typing import Pattern +__all__ = ["HTMLParser"] + class HTMLParser(ParserBase): def __init__(self, *, convert_charrefs: bool = ...) -> None: ... def feed(self, data: str) -> None: ... diff --git a/mypy/typeshed/stdlib/http/__init__.pyi b/mypy/typeshed/stdlib/http/__init__.pyi index 93895549cb2a9..822cc0932939c 100644 --- a/mypy/typeshed/stdlib/http/__init__.pyi +++ b/mypy/typeshed/stdlib/http/__init__.pyi @@ -2,6 +2,8 @@ import sys from enum import IntEnum from typing_extensions import Literal +__all__ = ["HTTPStatus"] + class HTTPStatus(IntEnum): @property def phrase(self) -> str: ... diff --git a/mypy/typeshed/stdlib/http/client.pyi b/mypy/typeshed/stdlib/http/client.pyi index 1558f6ff46e89..801a195c9fb37 100644 --- a/mypy/typeshed/stdlib/http/client.pyi +++ b/mypy/typeshed/stdlib/http/client.pyi @@ -5,9 +5,31 @@ import sys import types from _typeshed import Self, WriteableBuffer from socket import socket -from typing import IO, Any, BinaryIO, Callable, Iterable, Iterator, Mapping, Protocol, Type, TypeVar, Union, overload - -_DataType = Union[bytes, IO[Any], Iterable[bytes], str] +from typing import IO, Any, BinaryIO, Callable, Iterable, Iterator, Mapping, Protocol, TypeVar, overload + +__all__ = [ + "HTTPResponse", + "HTTPConnection", + "HTTPException", + "NotConnected", + "UnknownProtocol", + "UnknownTransferEncoding", + "UnimplementedFileMode", + "IncompleteRead", + "InvalidURL", + "ImproperConnectionState", + "CannotSendRequest", + "CannotSendHeader", + "ResponseNotReady", + "BadStatusLine", + "LineTooLong", + "RemoteDisconnected", + "error", + "responses", + "HTTPSConnection", +] + +_DataType = bytes | IO[Any] | Iterable[bytes] | str _T = TypeVar("_T") HTTP_PORT: int @@ -107,8 +129,8 @@ class HTTPResponse(io.BufferedIOBase, BinaryIO): def __iter__(self) -> Iterator[bytes]: ... def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: types.TracebackType | None - ) -> bool | None: ... + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: types.TracebackType | None + ) -> None: ... def info(self) -> email.message.Message: ... def geturl(self) -> str: ... def getcode(self) -> int: ... @@ -135,7 +157,7 @@ class HTTPConnection: auto_open: int # undocumented debuglevel: int default_port: int # undocumented - response_class: Type[HTTPResponse] # undocumented + response_class: type[HTTPResponse] # undocumented timeout: float | None host: str port: int @@ -153,6 +175,7 @@ class HTTPConnection: def __init__( self, host: str, port: int | None = ..., timeout: float | None = ..., source_address: tuple[str, int] | None = ... ) -> None: ... + def request( self, method: str, url: str, body: _DataType | None = ..., headers: Mapping[str, str] = ..., *, encode_chunked: bool = ... ) -> None: ... diff --git a/mypy/typeshed/stdlib/http/cookiejar.pyi b/mypy/typeshed/stdlib/http/cookiejar.pyi index 6bfa7f385e695..4fb1c38c6ab81 100644 --- a/mypy/typeshed/stdlib/http/cookiejar.pyi +++ b/mypy/typeshed/stdlib/http/cookiejar.pyi @@ -4,6 +4,17 @@ from http.client import HTTPResponse from typing import ClassVar, Iterable, Iterator, Pattern, Sequence, TypeVar, overload from urllib.request import Request +__all__ = [ + "Cookie", + "CookieJar", + "CookiePolicy", + "DefaultCookiePolicy", + "FileCookieJar", + "LWPCookieJar", + "LoadError", + "MozillaCookieJar", +] + _T = TypeVar("_T") class LoadError(OSError): ... @@ -27,8 +38,6 @@ class CookieJar(Iterable[Cookie]): def clear_expired_cookies(self) -> None: ... # undocumented def __iter__(self) -> Iterator[Cookie]: ... def __len__(self) -> int: ... - def __repr__(self) -> str: ... - def __str__(self) -> str: ... class FileCookieJar(CookieJar): filename: str @@ -37,6 +46,7 @@ class FileCookieJar(CookieJar): def __init__(self, filename: StrPath | None = ..., delayload: bool = ..., policy: CookiePolicy | None = ...) -> None: ... else: def __init__(self, filename: str | None = ..., delayload: bool = ..., policy: CookiePolicy | None = ...) -> None: ... + def save(self, filename: str | None = ..., ignore_discard: bool = ..., ignore_expires: bool = ...) -> None: ... def load(self, filename: str | None = ..., ignore_discard: bool = ..., ignore_expires: bool = ...) -> None: ... def revert(self, filename: str | None = ..., ignore_discard: bool = ..., ignore_expires: bool = ...) -> None: ... @@ -102,6 +112,7 @@ class DefaultCookiePolicy(CookiePolicy): strict_ns_set_initial_dollar: bool = ..., strict_ns_set_path: bool = ..., ) -> None: ... + def blocked_domains(self) -> tuple[str, ...]: ... def set_blocked_domains(self, blocked_domains: Sequence[str]) -> None: ... def is_blocked(self, domain: str) -> bool: ... diff --git a/mypy/typeshed/stdlib/http/cookies.pyi b/mypy/typeshed/stdlib/http/cookies.pyi index 211fd37662d4c..2cc05961a3034 100644 --- a/mypy/typeshed/stdlib/http/cookies.pyi +++ b/mypy/typeshed/stdlib/http/cookies.pyi @@ -1,10 +1,12 @@ import sys -from typing import Any, Generic, Iterable, Mapping, TypeVar, Union, overload +from typing import Any, Generic, Iterable, Mapping, TypeVar, overload if sys.version_info >= (3, 9): from types import GenericAlias -_DataType = Union[str, Mapping[str, Union[str, Morsel[Any]]]] +__all__ = ["CookieError", "BaseCookie", "SimpleCookie"] + +_DataType = str | Mapping[str, str | Morsel[Any]] _T = TypeVar("_T") @overload @@ -19,14 +21,18 @@ def _unquote(str: str) -> str: ... class CookieError(Exception): ... class Morsel(dict[str, Any], Generic[_T]): - value: str - coded_value: _T - key: str + @property + def value(self) -> str: ... + @property + def coded_value(self) -> _T: ... + @property + def key(self) -> str: ... def __init__(self) -> None: ... if sys.version_info >= (3, 7): def set(self, key: str, val: str, coded_val: _T) -> None: ... else: def set(self, key: str, val: str, coded_val: _T, LegalChars: str = ...) -> None: ... + def setdefault(self, key: str, val: str | None = ...) -> str: ... # The dict update can also get a keywords argument so this is incompatible @overload # type: ignore[override] @@ -35,8 +41,11 @@ class Morsel(dict[str, Any], Generic[_T]): def update(self, values: Iterable[tuple[str, str]]) -> None: ... def isReservedKey(self, K: str) -> bool: ... def output(self, attrs: list[str] | None = ..., header: str = ...) -> str: ... + __str__ = output def js_output(self, attrs: list[str] | None = ...) -> str: ... def OutputString(self, attrs: list[str] | None = ...) -> str: ... + def __eq__(self, morsel: object) -> bool: ... + def __setitem__(self, K: str, V: Any) -> None: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... @@ -45,6 +54,7 @@ class BaseCookie(dict[str, Morsel[_T]], Generic[_T]): def value_decode(self, val: str) -> _T: ... def value_encode(self, val: _T) -> str: ... def output(self, attrs: list[str] | None = ..., header: str = ..., sep: str = ...) -> str: ... + __str__ = output def js_output(self, attrs: list[str] | None = ...) -> str: ... def load(self, rawdata: _DataType) -> None: ... def __setitem__(self, key: str, value: str | Morsel[_T]) -> None: ... diff --git a/mypy/typeshed/stdlib/http/server.pyi b/mypy/typeshed/stdlib/http/server.pyi index e3d0a8c318f45..53159b65ec14d 100644 --- a/mypy/typeshed/stdlib/http/server.pyi +++ b/mypy/typeshed/stdlib/http/server.pyi @@ -5,6 +5,11 @@ import sys from _typeshed import StrPath, SupportsRead, SupportsWrite from typing import Any, AnyStr, BinaryIO, ClassVar, Mapping, Sequence +if sys.version_info >= (3, 7): + __all__ = ["HTTPServer", "ThreadingHTTPServer", "BaseHTTPRequestHandler", "SimpleHTTPRequestHandler", "CGIHTTPRequestHandler"] +else: + __all__ = ["HTTPServer", "BaseHTTPRequestHandler", "SimpleHTTPRequestHandler", "CGIHTTPRequestHandler"] + class HTTPServer(socketserver.TCPServer): server_name: str server_port: int @@ -60,6 +65,7 @@ class SimpleHTTPRequestHandler(BaseHTTPRequestHandler): ) -> None: ... else: def __init__(self, request: bytes, client_address: tuple[str, int], server: socketserver.BaseServer) -> None: ... + def do_GET(self) -> None: ... def do_HEAD(self) -> None: ... def send_head(self) -> io.BytesIO | BinaryIO | None: ... # undocumented diff --git a/mypy/typeshed/stdlib/imaplib.pyi b/mypy/typeshed/stdlib/imaplib.pyi index 1b2774d8fde06..ab6490cea570b 100644 --- a/mypy/typeshed/stdlib/imaplib.pyi +++ b/mypy/typeshed/stdlib/imaplib.pyi @@ -5,21 +5,23 @@ from _typeshed import Self from socket import socket as _socket from ssl import SSLContext, SSLSocket from types import TracebackType -from typing import IO, Any, Callable, Pattern, Type, Union +from typing import IO, Any, Callable, Pattern from typing_extensions import Literal +__all__ = ["IMAP4", "IMAP4_stream", "Internaldate2tuple", "Int2AP", "ParseFlags", "Time2Internaldate", "IMAP4_SSL"] + # TODO: Commands should use their actual return types, not this type alias. # E.g. Tuple[Literal["OK"], List[bytes]] _CommandResults = tuple[str, list[Any]] -_AnyResponseData = Union[list[None], list[Union[bytes, tuple[bytes, bytes]]]] +_AnyResponseData = list[None] | list[bytes | tuple[bytes, bytes]] _list = list # conflicts with a method named "list" class IMAP4: - error: Type[Exception] - abort: Type[Exception] - readonly: Type[Exception] + error: type[Exception] + abort: type[Exception] + readonly: type[Exception] mustquote: Pattern[str] debug: int state: str @@ -32,7 +34,7 @@ class IMAP4: tagpre: str tagre: Pattern[str] welcome: bytes - capabilities: tuple[str] + capabilities: tuple[str, ...] PROTOCOL_VERSION: str if sys.version_info >= (3, 9): def __init__(self, host: str = ..., port: int = ..., timeout: float | None = ...) -> None: ... @@ -40,6 +42,7 @@ class IMAP4: else: def __init__(self, host: str = ..., port: int = ...) -> None: ... def open(self, host: str = ..., port: int = ...) -> None: ... + def __getattr__(self, attr: str) -> Any: ... host: str port: int @@ -63,7 +66,7 @@ class IMAP4: def deleteacl(self, mailbox: str, who: str) -> _CommandResults: ... def enable(self, capability: str) -> _CommandResults: ... def __enter__(self: Self) -> Self: ... - def __exit__(self, t: Type[BaseException] | None, v: BaseException | None, tb: TracebackType | None) -> None: ... + def __exit__(self, t: type[BaseException] | None, v: BaseException | None, tb: TracebackType | None) -> None: ... def expunge(self) -> _CommandResults: ... def fetch(self, message_set: str, message_parts: str) -> tuple[str, _AnyResponseData]: ... def getacl(self, mailbox: str) -> _CommandResults: ... @@ -96,6 +99,7 @@ class IMAP4: def unsubscribe(self, mailbox: str) -> _CommandResults: ... if sys.version_info >= (3, 9): def unselect(self) -> _CommandResults: ... + def xatom(self, name: str, *args: str) -> _CommandResults: ... def print_log(self) -> None: ... @@ -130,6 +134,7 @@ class IMAP4_SSL(IMAP4): def open(self, host: str = ..., port: int | None = ..., timeout: float | None = ...) -> None: ... else: def open(self, host: str = ..., port: int | None = ...) -> None: ... + def read(self, size: int) -> bytes: ... def readline(self) -> bytes: ... def send(self, data: bytes) -> None: ... @@ -151,6 +156,7 @@ class IMAP4_stream(IMAP4): def open(self, host: str | None = ..., port: int | None = ..., timeout: float | None = ...) -> None: ... else: def open(self, host: str | None = ..., port: int | None = ...) -> None: ... + def read(self, size: int) -> bytes: ... def readline(self) -> bytes: ... def send(self, data: bytes) -> None: ... @@ -165,5 +171,5 @@ class _Authenticator: def Internaldate2tuple(resp: str) -> time.struct_time: ... def Int2AP(num: int) -> str: ... -def ParseFlags(resp: str) -> tuple[str]: ... +def ParseFlags(resp: str) -> tuple[str, ...]: ... def Time2Internaldate(date_time: float | time.struct_time | str) -> str: ... diff --git a/mypy/typeshed/stdlib/imghdr.pyi b/mypy/typeshed/stdlib/imghdr.pyi index 4515cf2269b09..af046e899326a 100644 --- a/mypy/typeshed/stdlib/imghdr.pyi +++ b/mypy/typeshed/stdlib/imghdr.pyi @@ -1,6 +1,8 @@ from _typeshed import StrPath from typing import Any, BinaryIO, Callable, Protocol, overload +__all__ = ["what"] + class _ReadableBinary(Protocol): def tell(self) -> int: ... def read(self, size: int) -> bytes: ... diff --git a/mypy/typeshed/stdlib/imp.pyi b/mypy/typeshed/stdlib/imp.pyi index 88f2e789329b4..3054a4465f992 100644 --- a/mypy/typeshed/stdlib/imp.pyi +++ b/mypy/typeshed/stdlib/imp.pyi @@ -1,7 +1,8 @@ import types from _typeshed import StrPath from os import PathLike -from typing import IO, Any, Protocol, TypeVar +from types import TracebackType +from typing import IO, Any, Protocol from _imp import ( acquire_lock as acquire_lock, @@ -15,8 +16,6 @@ from _imp import ( release_lock as release_lock, ) -_T = TypeVar("_T") - SEARCH_ERROR: int PY_SOURCE: int PY_COMPILED: int @@ -47,7 +46,7 @@ class _FileLike(Protocol): def read(self) -> str | bytes: ... def close(self) -> Any: ... def __enter__(self) -> Any: ... - def __exit__(self, *args: Any) -> Any: ... + def __exit__(self, typ: type[BaseException] | None, exc: BaseException | None, tb: TracebackType | None) -> Any: ... # PathLike doesn't work for the pathname argument here def load_source(name: str, pathname: str, file: _FileLike | None = ...) -> types.ModuleType: ... diff --git a/mypy/typeshed/stdlib/importlib/__init__.pyi b/mypy/typeshed/stdlib/importlib/__init__.pyi index 1b91cc55f2df3..0e99786775b0b 100644 --- a/mypy/typeshed/stdlib/importlib/__init__.pyi +++ b/mypy/typeshed/stdlib/importlib/__init__.pyi @@ -2,6 +2,8 @@ from importlib.abc import Loader from types import ModuleType from typing import Mapping, Sequence +__all__ = ["__import__", "import_module", "invalidate_caches", "reload"] + # Signature of `builtins.__import__` should be kept identical to `importlib.__import__` def __import__( name: str, diff --git a/mypy/typeshed/stdlib/importlib/abc.pyi b/mypy/typeshed/stdlib/importlib/abc.pyi index 9bb370dfd7e83..877f8ff1a65c8 100644 --- a/mypy/typeshed/stdlib/importlib/abc.pyi +++ b/mypy/typeshed/stdlib/importlib/abc.pyi @@ -12,10 +12,10 @@ from _typeshed import ( from abc import ABCMeta, abstractmethod from importlib.machinery import ModuleSpec from io import BufferedRandom, BufferedReader, BufferedWriter, FileIO, TextIOWrapper -from typing import IO, Any, BinaryIO, Iterator, Mapping, NoReturn, Protocol, Sequence, Union, overload, runtime_checkable +from typing import IO, Any, BinaryIO, Iterator, Mapping, NoReturn, Protocol, Sequence, overload, runtime_checkable from typing_extensions import Literal -_Path = Union[bytes, str] +_Path = bytes | str class Finder(metaclass=ABCMeta): ... @@ -91,6 +91,7 @@ if sys.version_info >= (3, 7): else: @abstractmethod def is_resource(self, name: str) -> bool: ... + @abstractmethod def contents(self) -> Iterator[str]: ... @@ -157,7 +158,7 @@ if sys.version_info >= (3, 9): @overload @abstractmethod def open( - self, mode: OpenBinaryMode, buffering: int, encoding: None = ..., errors: None = ..., newline: None = ... + self, mode: OpenBinaryMode, buffering: int = ..., encoding: None = ..., errors: None = ..., newline: None = ... ) -> BinaryIO: ... # Fallback if mode is not specified @overload @@ -168,11 +169,12 @@ if sys.version_info >= (3, 9): @property def name(self) -> str: ... @abstractmethod - def __truediv__(self, key: StrPath) -> Traversable: ... + def __truediv__(self, child: StrPath) -> Traversable: ... @abstractmethod def read_bytes(self) -> bytes: ... @abstractmethod def read_text(self, encoding: str | None = ...) -> str: ... + class TraversableResources(ResourceReader): @abstractmethod def files(self) -> Traversable: ... diff --git a/mypy/typeshed/stdlib/importlib/machinery.pyi b/mypy/typeshed/stdlib/importlib/machinery.pyi index b73f9c5275836..f15ac48af5c51 100644 --- a/mypy/typeshed/stdlib/importlib/machinery.pyi +++ b/mypy/typeshed/stdlib/importlib/machinery.pyi @@ -22,8 +22,10 @@ class ModuleSpec: submodule_search_locations: list[str] | None loader_state: Any cached: str | None - parent: str | None + @property + def parent(self) -> str | None: ... has_location: bool + def __eq__(self, other: object) -> bool: ... class BuiltinImporter(importlib.abc.MetaPathFinder, importlib.abc.InspectLoader): # MetaPathFinder @@ -82,6 +84,7 @@ class FrozenImporter(importlib.abc.MetaPathFinder, importlib.abc.InspectLoader): else: @classmethod def create_module(cls, spec: ModuleSpec) -> types.ModuleType | None: ... + @staticmethod def exec_module(module: types.ModuleType) -> None: ... @@ -106,6 +109,7 @@ class PathFinder: elif sys.version_info >= (3, 8): @classmethod def find_distributions(cls, context: DistributionFinder.Context = ...) -> Iterable[PathDistribution]: ... + @classmethod def find_spec( cls, fullname: str, path: Sequence[bytes | str] | None = ..., target: types.ModuleType | None = ... @@ -123,10 +127,10 @@ def all_suffixes() -> list[str]: ... class FileFinder(importlib.abc.PathEntryFinder): path: str - def __init__(self, path: str, *loader_details: tuple[importlib.abc.Loader, list[str]]) -> None: ... + def __init__(self, path: str, *loader_details: tuple[type[importlib.abc.Loader], list[str]]) -> None: ... @classmethod def path_hook( - cls, *loader_details: tuple[importlib.abc.Loader, list[str]] + cls, *loader_details: tuple[type[importlib.abc.Loader], list[str]] ) -> Callable[[str], importlib.abc.PathEntryFinder]: ... class SourceFileLoader(importlib.abc.FileLoader, importlib.abc.SourceLoader): @@ -142,3 +146,4 @@ class ExtensionFileLoader(importlib.abc.ExecutionLoader): def exec_module(self, module: types.ModuleType) -> None: ... def is_package(self, fullname: str) -> bool: ... def get_code(self, fullname: str) -> None: ... + def __eq__(self, other: object) -> bool: ... diff --git a/mypy/typeshed/stdlib/importlib/metadata/__init__.pyi b/mypy/typeshed/stdlib/importlib/metadata/__init__.pyi index a9e223149b52c..52c5547a6128d 100644 --- a/mypy/typeshed/stdlib/importlib/metadata/__init__.pyi +++ b/mypy/typeshed/stdlib/importlib/metadata/__init__.pyi @@ -1,7 +1,7 @@ import abc import pathlib import sys -from _typeshed import StrPath +from _typeshed import Self, StrPath from collections.abc import Mapping from email.message import Message from importlib.abc import MetaPathFinder @@ -9,98 +9,207 @@ from os import PathLike from pathlib import Path from typing import Any, ClassVar, Iterable, NamedTuple, Pattern, overload +if sys.version_info >= (3, 10): + __all__ = [ + "Distribution", + "DistributionFinder", + "PackageMetadata", + "PackageNotFoundError", + "distribution", + "distributions", + "entry_points", + "files", + "metadata", + "packages_distributions", + "requires", + "version", + ] +else: + __all__ = [ + "Distribution", + "DistributionFinder", + "PackageNotFoundError", + "distribution", + "distributions", + "entry_points", + "files", + "metadata", + "requires", + "version", + ] + if sys.version_info >= (3, 10): from importlib.metadata._meta import PackageMetadata as PackageMetadata def packages_distributions() -> Mapping[str, list[str]]: ... -if sys.version_info >= (3, 8): - class PackageNotFoundError(ModuleNotFoundError): ... - class _EntryPointBase(NamedTuple): - name: str - value: str - group: str - class EntryPoint(_EntryPointBase): - pattern: ClassVar[Pattern[str]] - def load(self) -> Any: ... # Callable[[], Any] or an importable module +class PackageNotFoundError(ModuleNotFoundError): + @property + def name(self) -> str: ... # type: ignore[override] + +class _EntryPointBase(NamedTuple): + name: str + value: str + group: str + +class EntryPoint(_EntryPointBase): + pattern: ClassVar[Pattern[str]] + def load(self) -> Any: ... # Callable[[], Any] or an importable module + @property + def extras(self) -> list[str]: ... + if sys.version_info >= (3, 9): + @property + def module(self) -> str: ... + @property + def attr(self) -> str: ... + if sys.version_info >= (3, 10): + dist: ClassVar[Distribution | None] + def matches( + self, + *, + name: str = ..., + value: str = ..., + group: str = ..., + module: str = ..., + attr: str = ..., + extras: list[str] = ..., + ) -> bool: ... # undocumented + +if sys.version_info >= (3, 10): + class EntryPoints(list[EntryPoint]): # use as list is deprecated since 3.10 + # int argument is deprecated since 3.10 + def __getitem__(self, name: int | str) -> EntryPoint: ... # type: ignore[override] + def select( + self, + *, + name: str = ..., + value: str = ..., + group: str = ..., + module: str = ..., + attr: str = ..., + extras: list[str] = ..., + ) -> EntryPoints: ... + @property + def names(self) -> set[str]: ... @property - def extras(self) -> list[str]: ... - if sys.version_info >= (3, 9): - @property - def module(self) -> str: ... - @property - def attr(self) -> str: ... - if sys.version_info >= (3, 10): - dist: ClassVar[Distribution | None] - def matches(self, **params: Any) -> bool: ... # undocumented - class PackagePath(pathlib.PurePosixPath): - def read_text(self, encoding: str = ...) -> str: ... - def read_binary(self) -> bytes: ... - def locate(self) -> PathLike[str]: ... - # The following attributes are not defined on PackagePath, but are dynamically added by Distribution.files: - hash: FileHash | None - size: int | None - dist: Distribution - class FileHash: - mode: str - value: str - def __init__(self, spec: str) -> None: ... - class Distribution: - @abc.abstractmethod - def read_text(self, filename: str) -> str | None: ... - @abc.abstractmethod - def locate_file(self, path: StrPath) -> PathLike[str]: ... + def groups(self) -> set[str]: ... + + class SelectableGroups(dict[str, EntryPoints]): # use as dict is deprecated since 3.10 @classmethod - def from_name(cls, name: str) -> Distribution: ... + def load(cls: type[Self], eps: Iterable[EntryPoint]) -> Self: ... + @property + def groups(self) -> set[str]: ... + @property + def names(self) -> set[str]: ... @overload - @classmethod - def discover(cls, *, context: DistributionFinder.Context) -> Iterable[Distribution]: ... + def select(self: Self) -> Self: ... # type: ignore[misc] @overload - @classmethod - def discover( - cls, *, context: None = ..., name: str | None = ..., path: list[str] = ..., **kwargs: Any - ) -> Iterable[Distribution]: ... - @staticmethod - def at(path: StrPath) -> PathDistribution: ... + def select( + self, + *, + name: str = ..., + value: str = ..., + group: str = ..., + module: str = ..., + attr: str = ..., + extras: list[str] = ..., + ) -> EntryPoints: ... + +class PackagePath(pathlib.PurePosixPath): + def read_text(self, encoding: str = ...) -> str: ... + def read_binary(self) -> bytes: ... + def locate(self) -> PathLike[str]: ... + # The following attributes are not defined on PackagePath, but are dynamically added by Distribution.files: + hash: FileHash | None + size: int | None + dist: Distribution + +class FileHash: + mode: str + value: str + def __init__(self, spec: str) -> None: ... + +class Distribution: + @abc.abstractmethod + def read_text(self, filename: str) -> str | None: ... + @abc.abstractmethod + def locate_file(self, path: StrPath) -> PathLike[str]: ... + @classmethod + def from_name(cls, name: str) -> Distribution: ... + @overload + @classmethod + def discover(cls, *, context: DistributionFinder.Context) -> Iterable[Distribution]: ... + @overload + @classmethod + def discover( + cls, *, context: None = ..., name: str | None = ..., path: list[str] = ..., **kwargs: Any + ) -> Iterable[Distribution]: ... + @staticmethod + def at(path: StrPath) -> PathDistribution: ... + + if sys.version_info >= (3, 10): @property - def metadata(self) -> Message: ... + def metadata(self) -> PackageMetadata: ... @property - def version(self) -> str: ... + def entry_points(self) -> EntryPoints: ... + else: + @property + def metadata(self) -> Message: ... @property def entry_points(self) -> list[EntryPoint]: ... + + @property + def version(self) -> str: ... + @property + def files(self) -> list[PackagePath] | None: ... + @property + def requires(self) -> list[str] | None: ... + if sys.version_info >= (3, 10): @property - def files(self) -> list[PackagePath] | None: ... + def name(self) -> str: ... + +class DistributionFinder(MetaPathFinder): + class Context: + name: str | None + def __init__(self, *, name: str | None = ..., path: list[str] = ..., **kwargs: Any) -> None: ... @property - def requires(self) -> list[str] | None: ... - if sys.version_info >= (3, 10): - @property - def name(self) -> str: ... - class DistributionFinder(MetaPathFinder): - class Context: - name: str | None - def __init__(self, *, name: str | None = ..., path: list[str] = ..., **kwargs: Any) -> None: ... - @property - def path(self) -> list[str]: ... - @abc.abstractmethod - def find_distributions(self, context: DistributionFinder.Context = ...) -> Iterable[Distribution]: ... - class MetadataPathFinder(DistributionFinder): - @classmethod - def find_distributions(cls, context: DistributionFinder.Context = ...) -> Iterable[PathDistribution]: ... - if sys.version_info >= (3, 10): - # Yes, this is an instance method that has argumend named "cls" - def invalidate_caches(cls) -> None: ... # type: ignore - class PathDistribution(Distribution): - def __init__(self, path: Path) -> None: ... - def read_text(self, filename: StrPath) -> str: ... - def locate_file(self, path: StrPath) -> PathLike[str]: ... - def distribution(distribution_name: str) -> Distribution: ... + def path(self) -> list[str]: ... + + @abc.abstractmethod + def find_distributions(self, context: DistributionFinder.Context = ...) -> Iterable[Distribution]: ... + +class MetadataPathFinder(DistributionFinder): + @classmethod + def find_distributions(cls, context: DistributionFinder.Context = ...) -> Iterable[PathDistribution]: ... + if sys.version_info >= (3, 10): + # Yes, this is an instance method that has argumend named "cls" + def invalidate_caches(cls) -> None: ... # type: ignore + +class PathDistribution(Distribution): + def __init__(self, path: Path) -> None: ... + def read_text(self, filename: StrPath) -> str: ... + def locate_file(self, path: StrPath) -> PathLike[str]: ... + +def distribution(distribution_name: str) -> Distribution: ... +@overload +def distributions(*, context: DistributionFinder.Context) -> Iterable[Distribution]: ... +@overload +def distributions( + *, context: None = ..., name: str | None = ..., path: list[str] = ..., **kwargs: Any +) -> Iterable[Distribution]: ... + +if sys.version_info >= (3, 10): + def metadata(distribution_name: str) -> PackageMetadata: ... @overload - def distributions(*, context: DistributionFinder.Context) -> Iterable[Distribution]: ... + def entry_points() -> SelectableGroups: ... # type: ignore[misc] @overload - def distributions( - *, context: None = ..., name: str | None = ..., path: list[str] = ..., **kwargs: Any - ) -> Iterable[Distribution]: ... + def entry_points( + *, name: str = ..., value: str = ..., group: str = ..., module: str = ..., attr: str = ..., extras: list[str] = ... + ) -> EntryPoints: ... + +else: def metadata(distribution_name: str) -> Message: ... - def version(distribution_name: str) -> str: ... - def entry_points() -> dict[str, tuple[EntryPoint, ...]]: ... - def files(distribution_name: str) -> list[PackagePath] | None: ... - def requires(distribution_name: str) -> list[str] | None: ... + def entry_points() -> dict[str, list[EntryPoint]]: ... + +def version(distribution_name: str) -> str: ... +def files(distribution_name: str) -> list[PackagePath] | None: ... +def requires(distribution_name: str) -> list[str] | None: ... diff --git a/mypy/typeshed/stdlib/importlib/resources.pyi b/mypy/typeshed/stdlib/importlib/resources.pyi index b484d7126b21c..e6e3035e5daca 100644 --- a/mypy/typeshed/stdlib/importlib/resources.pyi +++ b/mypy/typeshed/stdlib/importlib/resources.pyi @@ -1,23 +1,52 @@ +import os import sys -from typing import Any +from contextlib import AbstractContextManager +from pathlib import Path +from types import ModuleType +from typing import Any, BinaryIO, Iterator, TextIO -# This is a >=3.7 module, so we conditionally include its source. -if sys.version_info >= (3, 7): - import os - from contextlib import AbstractContextManager - from pathlib import Path - from types import ModuleType - from typing import BinaryIO, Iterator, TextIO, Union +if sys.version_info >= (3, 10): + __all__ = [ + "Package", + "Resource", + "ResourceReader", + "as_file", + "contents", + "files", + "is_resource", + "open_binary", + "open_text", + "path", + "read_binary", + "read_text", + ] +elif sys.version_info >= (3, 9): + __all__ = [ + "Package", + "Resource", + "as_file", + "contents", + "files", + "is_resource", + "open_binary", + "open_text", + "path", + "read_binary", + "read_text", + ] +else: + __all__ = ["Package", "Resource", "contents", "is_resource", "open_binary", "open_text", "path", "read_binary", "read_text"] + +Package = str | ModuleType +Resource = str | os.PathLike[Any] - Package = Union[str, ModuleType] - Resource = Union[str, os.PathLike[Any]] - def open_binary(package: Package, resource: Resource) -> BinaryIO: ... - def open_text(package: Package, resource: Resource, encoding: str = ..., errors: str = ...) -> TextIO: ... - def read_binary(package: Package, resource: Resource) -> bytes: ... - def read_text(package: Package, resource: Resource, encoding: str = ..., errors: str = ...) -> str: ... - def path(package: Package, resource: Resource) -> AbstractContextManager[Path]: ... - def is_resource(package: Package, name: str) -> bool: ... - def contents(package: Package) -> Iterator[str]: ... +def open_binary(package: Package, resource: Resource) -> BinaryIO: ... +def open_text(package: Package, resource: Resource, encoding: str = ..., errors: str = ...) -> TextIO: ... +def read_binary(package: Package, resource: Resource) -> bytes: ... +def read_text(package: Package, resource: Resource, encoding: str = ..., errors: str = ...) -> str: ... +def path(package: Package, resource: Resource) -> AbstractContextManager[Path]: ... +def is_resource(package: Package, name: str) -> bool: ... +def contents(package: Package) -> Iterator[str]: ... if sys.version_info >= (3, 9): from importlib.abc import Traversable diff --git a/mypy/typeshed/stdlib/inspect.pyi b/mypy/typeshed/stdlib/inspect.pyi index a96e30865a59a..f87cd0e55acb0 100644 --- a/mypy/typeshed/stdlib/inspect.pyi +++ b/mypy/typeshed/stdlib/inspect.pyi @@ -21,10 +21,120 @@ from types import ( ) if sys.version_info >= (3, 7): - from types import ClassMethodDescriptorType, WrapperDescriptorType, MemberDescriptorType, MethodDescriptorType - -from typing import Any, ClassVar, Coroutine, NamedTuple, Protocol, Type, TypeVar, Union -from typing_extensions import Literal, TypeGuard + from types import ( + ClassMethodDescriptorType, + WrapperDescriptorType, + MemberDescriptorType, + MethodDescriptorType, + MethodWrapperType, + ) + +from typing import Any, ClassVar, Coroutine, NamedTuple, Protocol, TypeVar, Union +from typing_extensions import Literal, ParamSpec, TypeGuard + +if sys.version_info >= (3, 11): + __all__ = [ + "ArgInfo", + "Arguments", + "Attribute", + "BlockFinder", + "BoundArguments", + "CORO_CLOSED", + "CORO_CREATED", + "CORO_RUNNING", + "CORO_SUSPENDED", + "CO_ASYNC_GENERATOR", + "CO_COROUTINE", + "CO_GENERATOR", + "CO_ITERABLE_COROUTINE", + "CO_NESTED", + "CO_NEWLOCALS", + "CO_NOFREE", + "CO_OPTIMIZED", + "CO_VARARGS", + "CO_VARKEYWORDS", + "ClassFoundException", + "ClosureVars", + "EndOfBlock", + "FrameInfo", + "FullArgSpec", + "GEN_CLOSED", + "GEN_CREATED", + "GEN_RUNNING", + "GEN_SUSPENDED", + "Parameter", + "Signature", + "TPFLAGS_IS_ABSTRACT", + "Traceback", + "classify_class_attrs", + "cleandoc", + "currentframe", + "findsource", + "formatannotation", + "formatannotationrelativeto", + "formatargvalues", + "get_annotations", + "getabsfile", + "getargs", + "getargvalues", + "getattr_static", + "getblock", + "getcallargs", + "getclasstree", + "getclosurevars", + "getcomments", + "getcoroutinelocals", + "getcoroutinestate", + "getdoc", + "getfile", + "getframeinfo", + "getfullargspec", + "getgeneratorlocals", + "getgeneratorstate", + "getinnerframes", + "getlineno", + "getmembers", + "getmembers_static", + "getmodule", + "getmodulename", + "getmro", + "getouterframes", + "getsource", + "getsourcefile", + "getsourcelines", + "indentsize", + "isabstract", + "isasyncgen", + "isasyncgenfunction", + "isawaitable", + "isbuiltin", + "isclass", + "iscode", + "iscoroutine", + "iscoroutinefunction", + "isdatadescriptor", + "isframe", + "isfunction", + "isgenerator", + "isgeneratorfunction", + "isgetsetdescriptor", + "ismemberdescriptor", + "ismethod", + "ismethoddescriptor", + "ismethodwrapper", + "ismodule", + "isroutine", + "istraceback", + "signature", + "stack", + "trace", + "unwrap", + "walktree", + ] + +_P = ParamSpec("_P") +_T_cont = TypeVar("_T_cont", contravariant=True) +_V_cont = TypeVar("_V_cont", contravariant=True) # # Types and members @@ -55,10 +165,17 @@ TPFLAGS_IS_ABSTRACT: Literal[1048576] modulesbyfile: dict[str, Any] -def getmembers(object: object, predicate: Callable[[Any], bool] | None = ...) -> list[tuple[str, Any]]: ... +_GetMembersPredicate = Callable[[Any], bool] +_GetMembersReturn = list[tuple[str, Any]] + +def getmembers(object: object, predicate: _GetMembersPredicate | None = ...) -> _GetMembersReturn: ... + +if sys.version_info >= (3, 11): + def getmembers_static(object: object, predicate: _GetMembersPredicate | None = ...) -> _GetMembersReturn: ... + def getmodulename(path: str) -> str | None: ... def ismodule(object: object) -> TypeGuard[ModuleType]: ... -def isclass(object: object) -> TypeGuard[Type[Any]]: ... +def isclass(object: object) -> TypeGuard[type[Any]]: ... def ismethod(object: object) -> TypeGuard[MethodType]: ... def isfunction(object: object) -> TypeGuard[FunctionType]: ... @@ -80,9 +197,6 @@ if sys.version_info >= (3, 8): else: def isasyncgenfunction(object: object) -> bool: ... -_T_cont = TypeVar("_T_cont", contravariant=True) -_V_cont = TypeVar("_V_cont", contravariant=True) - class _SupportsSet(Protocol[_T_cont, _V_cont]): def __set__(self, __instance: _T_cont, __value: _V_cont) -> None: ... @@ -95,6 +209,9 @@ def isframe(object: object) -> TypeGuard[FrameType]: ... def iscode(object: object) -> TypeGuard[CodeType]: ... def isbuiltin(object: object) -> TypeGuard[BuiltinFunctionType]: ... +if sys.version_info >= (3, 11): + def ismethodwrapper(object: object) -> TypeGuard[MethodWrapperType]: ... + if sys.version_info >= (3, 7): def isroutine( object: object, @@ -125,7 +242,7 @@ def isdatadescriptor(object: object) -> TypeGuard[_SupportsSet[Any, Any] | _Supp # # Retrieving source code # -_SourceObjectType = Union[ModuleType, Type[Any], MethodType, FunctionType, TracebackType, FrameType, CodeType, Callable[..., Any]] +_SourceObjectType = Union[ModuleType, type[Any], MethodType, FunctionType, TracebackType, FrameType, CodeType, Callable[..., Any]] def findsource(object: _SourceObjectType) -> tuple[list[str], int]: ... def getabsfile(object: _SourceObjectType, _filename: str | None = ...) -> str: ... @@ -166,32 +283,33 @@ class Signature: empty = _empty @property def parameters(self) -> types.MappingProxyType[str, Parameter]: ... - # TODO: can we be more specific here? @property def return_annotation(self) -> Any: ... def bind(self, *args: Any, **kwargs: Any) -> BoundArguments: ... def bind_partial(self, *args: Any, **kwargs: Any) -> BoundArguments: ... def replace( - self: Self, *, parameters: Sequence[Parameter] | Type[_void] | None = ..., return_annotation: Any = ... + self: Self, *, parameters: Sequence[Parameter] | type[_void] | None = ..., return_annotation: Any = ... ) -> Self: ... if sys.version_info >= (3, 10): @classmethod def from_callable( - cls, + cls: type[Self], obj: Callable[..., Any], *, follow_wrapped: bool = ..., globals: Mapping[str, Any] | None = ..., locals: Mapping[str, Any] | None = ..., eval_str: bool = ..., - ) -> Signature: ... + ) -> Self: ... else: @classmethod - def from_callable(cls, obj: Callable[..., Any], *, follow_wrapped: bool = ...) -> Signature: ... + def from_callable(cls: type[Self], obj: Callable[..., Any], *, follow_wrapped: bool = ...) -> Self: ... + + def __eq__(self, other: object) -> bool: ... if sys.version_info >= (3, 10): def get_annotations( - obj: Callable[..., Any] | Type[Any] | ModuleType, + obj: Callable[..., Any] | type[Any] | ModuleType, *, globals: Mapping[str, Any] | None = ..., locals: Mapping[str, Any] | None = ..., @@ -230,19 +348,24 @@ class Parameter: def replace( self: Self, *, - name: str | Type[_void] = ..., - kind: _ParameterKind | Type[_void] = ..., + name: str | type[_void] = ..., + kind: _ParameterKind | type[_void] = ..., default: Any = ..., annotation: Any = ..., ) -> Self: ... + def __eq__(self, other: object) -> bool: ... class BoundArguments: arguments: OrderedDict[str, Any] - args: tuple[Any, ...] - kwargs: dict[str, Any] - signature: Signature + @property + def args(self) -> tuple[Any, ...]: ... + @property + def kwargs(self) -> dict[str, Any]: ... + @property + def signature(self) -> Signature: ... def __init__(self, signature: Signature, arguments: OrderedDict[str, Any]) -> None: ... def apply_defaults(self) -> None: ... + def __eq__(self, other: object) -> bool: ... # # Classes and functions @@ -252,7 +375,7 @@ class BoundArguments: # seem to be supporting this at the moment: # _ClassTreeItem = list[_ClassTreeItem] | Tuple[type, Tuple[type, ...]] def getclasstree(classes: list[type], unique: bool = ...) -> list[Any]: ... -def walktree(classes: list[type], children: dict[Type[Any], list[type]], parent: Type[Any] | None) -> list[Any]: ... +def walktree(classes: list[type], children: dict[type[Any], list[type]], parent: type[Any] | None) -> list[Any]: ... class Arguments(NamedTuple): args: list[str] @@ -318,7 +441,7 @@ def formatargvalues( formatvalue: Callable[[Any], str] | None = ..., ) -> str: ... def getmro(cls: type) -> tuple[type, ...]: ... -def getcallargs(__func: Callable[..., Any], *args: Any, **kwds: Any) -> dict[str, Any]: ... +def getcallargs(__func: Callable[_P, Any], *args: _P.args, **kwds: _P.kwargs) -> dict[str, Any]: ... class ClosureVars(NamedTuple): nonlocals: Mapping[str, Any] diff --git a/mypy/typeshed/stdlib/io.pyi b/mypy/typeshed/stdlib/io.pyi index 50452917c6f31..ef4789251cc30 100644 --- a/mypy/typeshed/stdlib/io.pyi +++ b/mypy/typeshed/stdlib/io.pyi @@ -4,13 +4,58 @@ import sys from _typeshed import ReadableBuffer, Self, StrOrBytesPath, WriteableBuffer from os import _Opener from types import TracebackType -from typing import IO, Any, BinaryIO, Callable, Iterable, Iterator, TextIO, Type +from typing import IO, Any, BinaryIO, Callable, Iterable, Iterator, TextIO +from typing_extensions import Literal -DEFAULT_BUFFER_SIZE: int - -SEEK_SET: int -SEEK_CUR: int -SEEK_END: int +if sys.version_info >= (3, 8): + __all__ = [ + "BlockingIOError", + "open", + "open_code", + "IOBase", + "RawIOBase", + "FileIO", + "BytesIO", + "StringIO", + "BufferedIOBase", + "BufferedReader", + "BufferedWriter", + "BufferedRWPair", + "BufferedRandom", + "TextIOBase", + "TextIOWrapper", + "UnsupportedOperation", + "SEEK_SET", + "SEEK_CUR", + "SEEK_END", + ] +else: + __all__ = [ + "BlockingIOError", + "open", + "IOBase", + "RawIOBase", + "FileIO", + "BytesIO", + "StringIO", + "BufferedIOBase", + "BufferedReader", + "BufferedWriter", + "BufferedRWPair", + "BufferedRandom", + "TextIOBase", + "TextIOWrapper", + "UnsupportedOperation", + "SEEK_SET", + "SEEK_CUR", + "SEEK_END", + ] + +DEFAULT_BUFFER_SIZE: Literal[8192] + +SEEK_SET: Literal[0] +SEEK_CUR: Literal[1] +SEEK_END: Literal[2] open = builtins.open @@ -26,8 +71,8 @@ class IOBase: def __next__(self) -> bytes: ... def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None - ) -> bool | None: ... + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> None: ... def close(self) -> None: ... def fileno(self) -> int: ... def flush(self) -> None: ... @@ -180,3 +225,4 @@ class IncrementalNewlineDecoder(codecs.IncrementalDecoder): def decode(self, input: bytes | str, final: bool = ...) -> str: ... @property def newlines(self) -> str | tuple[str, ...] | None: ... + def setstate(self, __state: tuple[bytes, int]) -> None: ... diff --git a/mypy/typeshed/stdlib/ipaddress.pyi b/mypy/typeshed/stdlib/ipaddress.pyi index 1cfd9a7c93784..d777cef74597d 100644 --- a/mypy/typeshed/stdlib/ipaddress.pyi +++ b/mypy/typeshed/stdlib/ipaddress.pyi @@ -1,25 +1,23 @@ import sys +from _typeshed import Self from typing import Any, Container, Generic, Iterable, Iterator, SupportsInt, TypeVar, overload +from typing_extensions import Literal # Undocumented length constants -IPV4LENGTH: int -IPV6LENGTH: int +IPV4LENGTH: Literal[32] +IPV6LENGTH: Literal[128] _A = TypeVar("_A", IPv4Address, IPv6Address) _N = TypeVar("_N", IPv4Network, IPv6Network) -_T = TypeVar("_T") -def ip_address(address: object) -> IPv4Address | IPv6Address: ... -def ip_network(address: object, strict: bool = ...) -> IPv4Network | IPv6Network: ... -def ip_interface(address: object) -> IPv4Interface | IPv6Interface: ... +_RawIPAddress = int | str | bytes | IPv4Address | IPv6Address +_RawNetworkPart = IPv4Network | IPv6Network | IPv4Interface | IPv6Interface + +def ip_address(address: _RawIPAddress) -> IPv4Address | IPv6Address: ... +def ip_network(address: _RawIPAddress | _RawNetworkPart, strict: bool = ...) -> IPv4Network | IPv6Network: ... +def ip_interface(address: _RawIPAddress | _RawNetworkPart) -> IPv4Interface | IPv6Interface: ... class _IPAddressBase: - def __eq__(self, other: Any) -> bool: ... - def __ge__(self: _T, other: _T) -> bool: ... - def __gt__(self: _T, other: _T) -> bool: ... - def __le__(self: _T, other: _T) -> bool: ... - def __lt__(self: _T, other: _T) -> bool: ... - def __ne__(self, other: Any) -> bool: ... @property def compressed(self) -> str: ... @property @@ -31,10 +29,22 @@ class _IPAddressBase: class _BaseAddress(_IPAddressBase, SupportsInt): def __init__(self, address: object) -> None: ... - def __add__(self: _T, other: int) -> _T: ... + def __add__(self: Self, other: int) -> Self: ... def __hash__(self) -> int: ... def __int__(self) -> int: ... - def __sub__(self: _T, other: int) -> _T: ... + def __sub__(self: Self, other: int) -> Self: ... + def __format__(self, fmt: str) -> str: ... + def __eq__(self, other: object) -> bool: ... + def __lt__(self: Self, other: Self) -> bool: ... + if sys.version_info >= (3, 11): + def __ge__(self: Self, other: Self) -> bool: ... + def __gt__(self: Self, other: Self) -> bool: ... + def __le__(self: Self, other: Self) -> bool: ... + else: + def __ge__(self: Self, other: Self, NotImplemented: Any = ...) -> bool: ... + def __gt__(self: Self, other: Self, NotImplemented: Any = ...) -> bool: ... + def __le__(self: Self, other: Self, NotImplemented: Any = ...) -> bool: ... + @property def is_global(self) -> bool: ... @property @@ -61,10 +71,21 @@ class _BaseNetwork(_IPAddressBase, Container[_A], Iterable[_A], Generic[_A]): def __contains__(self, other: Any) -> bool: ... def __getitem__(self, n: int) -> _A: ... def __iter__(self) -> Iterator[_A]: ... - def address_exclude(self: _T, other: _T) -> Iterator[_T]: ... + def __eq__(self, other: object) -> bool: ... + def __lt__(self: Self, other: Self) -> bool: ... + if sys.version_info >= (3, 11): + def __ge__(self: Self, other: Self) -> bool: ... + def __gt__(self: Self, other: Self) -> bool: ... + def __le__(self: Self, other: Self) -> bool: ... + else: + def __ge__(self: Self, other: Self, NotImplemented: Any = ...) -> bool: ... + def __gt__(self: Self, other: Self, NotImplemented: Any = ...) -> bool: ... + def __le__(self: Self, other: Self, NotImplemented: Any = ...) -> bool: ... + + def address_exclude(self: Self, other: Self) -> Iterator[Self]: ... @property def broadcast_address(self) -> _A: ... - def compare_networks(self: _T, other: _T) -> int: ... + def compare_networks(self: Self, other: Self) -> int: ... def hosts(self) -> Iterator[_A]: ... @property def is_global(self) -> bool: ... @@ -88,10 +109,11 @@ class _BaseNetwork(_IPAddressBase, Container[_A], Iterable[_A], Generic[_A]): @property def prefixlen(self) -> int: ... if sys.version_info >= (3, 7): - def subnet_of(self: _T, other: _T) -> bool: ... - def supernet_of(self: _T, other: _T) -> bool: ... - def subnets(self: _T, prefixlen_diff: int = ..., new_prefix: int | None = ...) -> Iterator[_T]: ... - def supernet(self: _T, prefixlen_diff: int = ..., new_prefix: int | None = ...) -> _T: ... + def subnet_of(self: Self, other: Self) -> bool: ... + def supernet_of(self: Self, other: Self) -> bool: ... + + def subnets(self: Self, prefixlen_diff: int = ..., new_prefix: int | None = ...) -> Iterator[Self]: ... + def supernet(self: Self, prefixlen_diff: int = ..., new_prefix: int | None = ...) -> Self: ... @property def with_hostmask(self) -> str: ... @property @@ -114,11 +136,23 @@ class _BaseInterface(_BaseAddress, Generic[_A, _N]): @property def with_prefixlen(self) -> str: ... -class IPv4Address(_BaseAddress): ... -class IPv4Network(_BaseNetwork[IPv4Address]): ... +class _BaseV4: + @property + def version(self) -> Literal[4]: ... + @property + def max_prefixlen(self) -> Literal[32]: ... + +class IPv4Address(_BaseV4, _BaseAddress): ... +class IPv4Network(_BaseV4, _BaseNetwork[IPv4Address]): ... class IPv4Interface(IPv4Address, _BaseInterface[IPv4Address, IPv4Network]): ... -class IPv6Address(_BaseAddress): +class _BaseV6: + @property + def version(self) -> Literal[6]: ... + @property + def max_prefixlen(self) -> Literal[128]: ... + +class IPv6Address(_BaseV6, _BaseAddress): @property def ipv4_mapped(self) -> IPv4Address | None: ... @property @@ -131,7 +165,7 @@ class IPv6Address(_BaseAddress): @property def scope_id(self) -> str | None: ... -class IPv6Network(_BaseNetwork[IPv6Address]): +class IPv6Network(_BaseV6, _BaseNetwork[IPv6Address]): @property def is_site_local(self) -> bool: ... diff --git a/mypy/typeshed/stdlib/itertools.pyi b/mypy/typeshed/stdlib/itertools.pyi index a5a7f4f1b62f8..bec03b1876ac3 100644 --- a/mypy/typeshed/stdlib/itertools.pyi +++ b/mypy/typeshed/stdlib/itertools.pyi @@ -1,19 +1,6 @@ import sys -from _typeshed import _T_co -from typing import ( - Any, - Callable, - Generic, - Iterable, - Iterator, - SupportsComplex, - SupportsFloat, - SupportsInt, - Type, - TypeVar, - Union, - overload, -) +from _typeshed import Self, _T_co +from typing import Any, Callable, Generic, Iterable, Iterator, SupportsComplex, SupportsFloat, SupportsInt, TypeVar, overload from typing_extensions import Literal, SupportsIndex if sys.version_info >= (3, 9): @@ -22,7 +9,7 @@ if sys.version_info >= (3, 9): _T = TypeVar("_T") _S = TypeVar("_S") _N = TypeVar("_N", int, float, SupportsFloat, SupportsInt, SupportsIndex, SupportsComplex) -_Step = Union[int, float, SupportsFloat, SupportsInt, SupportsIndex, SupportsComplex] +_Step = int | float | SupportsFloat | SupportsInt | SupportsIndex | SupportsComplex Predicate = Callable[[_T], object] @@ -36,12 +23,12 @@ class count(Iterator[_N], Generic[_N]): @overload def __new__(cls, *, step: _N) -> count[_N]: ... def __next__(self) -> _N: ... - def __iter__(self) -> Iterator[_N]: ... + def __iter__(self: Self) -> Self: ... class cycle(Iterator[_T], Generic[_T]): def __init__(self, __iterable: Iterable[_T]) -> None: ... def __next__(self) -> _T: ... - def __iter__(self) -> Iterator[_T]: ... + def __iter__(self: Self) -> Self: ... class repeat(Iterator[_T], Generic[_T]): @overload @@ -49,7 +36,8 @@ class repeat(Iterator[_T], Generic[_T]): @overload def __init__(self, object: _T, times: int) -> None: ... def __next__(self) -> _T: ... - def __iter__(self) -> Iterator[_T]: ... + def __iter__(self: Self) -> Self: ... + def __length_hint__(self) -> int: ... class accumulate(Iterator[_T], Generic[_T]): if sys.version_info >= (3, 8): @@ -59,32 +47,33 @@ class accumulate(Iterator[_T], Generic[_T]): def __init__(self, iterable: Iterable[_S], func: Callable[[_T, _S], _T], *, initial: _T | None = ...) -> None: ... else: def __init__(self, iterable: Iterable[_T], func: Callable[[_T, _T], _T] | None = ...) -> None: ... - def __iter__(self) -> Iterator[_T]: ... + + def __iter__(self: Self) -> Self: ... def __next__(self) -> _T: ... class chain(Iterator[_T], Generic[_T]): def __init__(self, *iterables: Iterable[_T]) -> None: ... def __next__(self) -> _T: ... - def __iter__(self) -> Iterator[_T]: ... + def __iter__(self: Self) -> Self: ... @classmethod - # We use Type and not Type[_S] to not lose the type inference from __iterable - def from_iterable(cls: Type[Any], __iterable: Iterable[Iterable[_S]]) -> Iterator[_S]: ... + # We use type[Any] and not type[_S] to not lose the type inference from __iterable + def from_iterable(cls: type[Any], __iterable: Iterable[Iterable[_S]]) -> chain[_S]: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, __item: Any) -> GenericAlias: ... class compress(Iterator[_T], Generic[_T]): def __init__(self, data: Iterable[_T], selectors: Iterable[Any]) -> None: ... - def __iter__(self) -> Iterator[_T]: ... + def __iter__(self: Self) -> Self: ... def __next__(self) -> _T: ... class dropwhile(Iterator[_T], Generic[_T]): def __init__(self, __predicate: Predicate[_T], __iterable: Iterable[_T]) -> None: ... - def __iter__(self) -> Iterator[_T]: ... + def __iter__(self: Self) -> Self: ... def __next__(self) -> _T: ... class filterfalse(Iterator[_T], Generic[_T]): def __init__(self, __predicate: Predicate[_T] | None, __iterable: Iterable[_T]) -> None: ... - def __iter__(self) -> Iterator[_T]: ... + def __iter__(self: Self) -> Self: ... def __next__(self) -> _T: ... _T1 = TypeVar("_T1") @@ -95,7 +84,7 @@ class groupby(Iterator[tuple[_T, Iterator[_S]]], Generic[_T, _S]): def __new__(cls, iterable: Iterable[_T1], key: None = ...) -> groupby[_T1, _T1]: ... @overload def __new__(cls, iterable: Iterable[_T1], key: Callable[[_T1], _T2]) -> groupby[_T2, _T1]: ... - def __iter__(self) -> Iterator[tuple[_T, Iterator[_S]]]: ... + def __iter__(self: Self) -> Self: ... def __next__(self) -> tuple[_T, Iterator[_S]]: ... class islice(Iterator[_T], Generic[_T]): @@ -103,24 +92,24 @@ class islice(Iterator[_T], Generic[_T]): def __init__(self, __iterable: Iterable[_T], __stop: int | None) -> None: ... @overload def __init__(self, __iterable: Iterable[_T], __start: int | None, __stop: int | None, __step: int | None = ...) -> None: ... - def __iter__(self) -> Iterator[_T]: ... + def __iter__(self: Self) -> Self: ... def __next__(self) -> _T: ... class starmap(Iterator[_T], Generic[_T]): def __init__(self, __function: Callable[..., _T], __iterable: Iterable[Iterable[Any]]) -> None: ... - def __iter__(self) -> Iterator[_T]: ... + def __iter__(self: Self) -> Self: ... def __next__(self) -> _T: ... class takewhile(Iterator[_T], Generic[_T]): def __init__(self, __predicate: Predicate[_T], __iterable: Iterable[_T]) -> None: ... - def __iter__(self) -> Iterator[_T]: ... + def __iter__(self: Self) -> Self: ... def __next__(self) -> _T: ... def tee(__iterable: Iterable[_T], __n: int = ...) -> tuple[Iterator[_T], ...]: ... class zip_longest(Iterator[Any]): def __init__(self, *p: Iterable[Any], fillvalue: Any = ...) -> None: ... - def __iter__(self) -> Iterator[Any]: ... + def __iter__(self: Self) -> Self: ... def __next__(self) -> Any: ... _T3 = TypeVar("_T3") @@ -174,12 +163,12 @@ class product(Iterator[_T_co], Generic[_T_co]): def __new__(cls, *iterables: Iterable[_T1], repeat: int) -> product[tuple[_T1, ...]]: ... @overload def __new__(cls, *iterables: Iterable[Any], repeat: int = ...) -> product[tuple[Any, ...]]: ... - def __iter__(self) -> Iterator[_T_co]: ... + def __iter__(self: Self) -> Self: ... def __next__(self) -> _T_co: ... class permutations(Iterator[tuple[_T, ...]], Generic[_T]): def __init__(self, iterable: Iterable[_T], r: int | None = ...) -> None: ... - def __iter__(self) -> Iterator[tuple[_T, ...]]: ... + def __iter__(self: Self) -> Self: ... def __next__(self) -> tuple[_T, ...]: ... class combinations(Iterator[_T_co], Generic[_T_co]): @@ -193,16 +182,16 @@ class combinations(Iterator[_T_co], Generic[_T_co]): def __new__(cls, iterable: Iterable[_T], r: Literal[5]) -> combinations[tuple[_T, _T, _T, _T, _T]]: ... @overload def __new__(cls, iterable: Iterable[_T], r: int) -> combinations[tuple[_T, ...]]: ... - def __iter__(self) -> Iterator[_T_co]: ... + def __iter__(self: Self) -> Self: ... def __next__(self) -> _T_co: ... class combinations_with_replacement(Iterator[tuple[_T, ...]], Generic[_T]): def __init__(self, iterable: Iterable[_T], r: int) -> None: ... - def __iter__(self) -> Iterator[tuple[_T, ...]]: ... + def __iter__(self: Self) -> Self: ... def __next__(self) -> tuple[_T, ...]: ... if sys.version_info >= (3, 10): class pairwise(Iterator[_T_co], Generic[_T_co]): def __new__(cls, __iterable: Iterable[_T]) -> pairwise[tuple[_T, _T]]: ... - def __iter__(self) -> Iterator[_T_co]: ... + def __iter__(self: Self) -> Self: ... def __next__(self) -> _T_co: ... diff --git a/mypy/typeshed/stdlib/json/__init__.pyi b/mypy/typeshed/stdlib/json/__init__.pyi index 3e26d1b14f82a..8e1a36756398e 100644 --- a/mypy/typeshed/stdlib/json/__init__.pyi +++ b/mypy/typeshed/stdlib/json/__init__.pyi @@ -1,9 +1,11 @@ from _typeshed import SupportsRead -from typing import IO, Any, Callable, Type +from typing import IO, Any, Callable from .decoder import JSONDecodeError as JSONDecodeError, JSONDecoder as JSONDecoder from .encoder import JSONEncoder as JSONEncoder +__all__ = ["dump", "dumps", "load", "loads", "JSONDecoder", "JSONDecodeError", "JSONEncoder"] + def dumps( obj: Any, *, @@ -11,7 +13,7 @@ def dumps( ensure_ascii: bool = ..., check_circular: bool = ..., allow_nan: bool = ..., - cls: Type[JSONEncoder] | None = ..., + cls: type[JSONEncoder] | None = ..., indent: None | int | str = ..., separators: tuple[str, str] | None = ..., default: Callable[[Any], Any] | None = ..., @@ -26,7 +28,7 @@ def dump( ensure_ascii: bool = ..., check_circular: bool = ..., allow_nan: bool = ..., - cls: Type[JSONEncoder] | None = ..., + cls: type[JSONEncoder] | None = ..., indent: None | int | str = ..., separators: tuple[str, str] | None = ..., default: Callable[[Any], Any] | None = ..., @@ -36,7 +38,7 @@ def dump( def loads( s: str | bytes, *, - cls: Type[JSONDecoder] | None = ..., + cls: type[JSONDecoder] | None = ..., object_hook: Callable[[dict[Any, Any]], Any] | None = ..., parse_float: Callable[[str], Any] | None = ..., parse_int: Callable[[str], Any] | None = ..., @@ -47,7 +49,7 @@ def loads( def load( fp: SupportsRead[str | bytes], *, - cls: Type[JSONDecoder] | None = ..., + cls: type[JSONDecoder] | None = ..., object_hook: Callable[[dict[Any, Any]], Any] | None = ..., parse_float: Callable[[str], Any] | None = ..., parse_int: Callable[[str], Any] | None = ..., diff --git a/mypy/typeshed/stdlib/json/decoder.pyi b/mypy/typeshed/stdlib/json/decoder.pyi index adf09bb4bb7d4..8668367585451 100644 --- a/mypy/typeshed/stdlib/json/decoder.pyi +++ b/mypy/typeshed/stdlib/json/decoder.pyi @@ -1,5 +1,7 @@ from typing import Any, Callable +__all__ = ["JSONDecoder", "JSONDecodeError"] + class JSONDecodeError(ValueError): msg: str doc: str diff --git a/mypy/typeshed/stdlib/keyword.pyi b/mypy/typeshed/stdlib/keyword.pyi index ac052feeba580..e9a9877d57dab 100644 --- a/mypy/typeshed/stdlib/keyword.pyi +++ b/mypy/typeshed/stdlib/keyword.pyi @@ -1,6 +1,11 @@ import sys from typing import Sequence +if sys.version_info >= (3, 9): + __all__ = ["iskeyword", "issoftkeyword", "kwlist", "softkwlist"] +else: + __all__ = ["iskeyword", "kwlist"] + def iskeyword(s: str) -> bool: ... kwlist: Sequence[str] diff --git a/mypy/typeshed/stdlib/lib2to3/pgen2/driver.pyi b/mypy/typeshed/stdlib/lib2to3/pgen2/driver.pyi index a8159dccf0378..4ecba031942c7 100644 --- a/mypy/typeshed/stdlib/lib2to3/pgen2/driver.pyi +++ b/mypy/typeshed/stdlib/lib2to3/pgen2/driver.pyi @@ -4,6 +4,8 @@ from lib2to3.pytree import _NL, _Convert from logging import Logger from typing import IO, Any, Iterable +__all__ = ["Driver", "load_grammar"] + class Driver: grammar: Grammar logger: Logger diff --git a/mypy/typeshed/stdlib/lib2to3/pgen2/grammar.pyi b/mypy/typeshed/stdlib/lib2to3/pgen2/grammar.pyi index 77cc6aec3d67b..b5836e1b90c59 100644 --- a/mypy/typeshed/stdlib/lib2to3/pgen2/grammar.pyi +++ b/mypy/typeshed/stdlib/lib2to3/pgen2/grammar.pyi @@ -1,8 +1,6 @@ -from _typeshed import StrPath -from typing import Optional, TypeVar +from _typeshed import Self, StrPath -_P = TypeVar("_P") -_Label = tuple[int, Optional[str]] +_Label = tuple[int, str | None] _DFA = list[list[tuple[int, int]]] _DFAS = tuple[_DFA, dict[int, int]] @@ -19,7 +17,7 @@ class Grammar: def __init__(self) -> None: ... def dump(self, filename: StrPath) -> None: ... def load(self, filename: StrPath) -> None: ... - def copy(self: _P) -> _P: ... + def copy(self: Self) -> Self: ... def report(self) -> None: ... opmap_raw: str diff --git a/mypy/typeshed/stdlib/lib2to3/pgen2/pgen.pyi b/mypy/typeshed/stdlib/lib2to3/pgen2/pgen.pyi index 11680157d199e..2628e1223fb42 100644 --- a/mypy/typeshed/stdlib/lib2to3/pgen2/pgen.pyi +++ b/mypy/typeshed/stdlib/lib2to3/pgen2/pgen.pyi @@ -41,6 +41,6 @@ class DFAState: def __init__(self, nfaset: dict[NFAState, Any], final: NFAState) -> None: ... def addarc(self, next: DFAState, label: str) -> None: ... def unifystate(self, old: DFAState, new: DFAState) -> None: ... - def __eq__(self, other: Any) -> bool: ... + def __eq__(self, other: DFAState) -> bool: ... # type: ignore[override] def generate_grammar(filename: StrPath = ...) -> PgenGrammar: ... diff --git a/mypy/typeshed/stdlib/lib2to3/pgen2/tokenize.pyi b/mypy/typeshed/stdlib/lib2to3/pgen2/tokenize.pyi index 3679caee93140..c1b5a91df9e65 100644 --- a/mypy/typeshed/stdlib/lib2to3/pgen2/tokenize.pyi +++ b/mypy/typeshed/stdlib/lib2to3/pgen2/tokenize.pyi @@ -1,6 +1,151 @@ -from lib2to3.pgen2.token import * # noqa +import sys +from lib2to3.pgen2.token import * from typing import Callable, Iterable, Iterator +if sys.version_info >= (3, 8): + __all__ = [ + "AMPER", + "AMPEREQUAL", + "ASYNC", + "AT", + "ATEQUAL", + "AWAIT", + "BACKQUOTE", + "CIRCUMFLEX", + "CIRCUMFLEXEQUAL", + "COLON", + "COLONEQUAL", + "COMMA", + "COMMENT", + "DEDENT", + "DOT", + "DOUBLESLASH", + "DOUBLESLASHEQUAL", + "DOUBLESTAR", + "DOUBLESTAREQUAL", + "ENDMARKER", + "EQEQUAL", + "EQUAL", + "ERRORTOKEN", + "GREATER", + "GREATEREQUAL", + "INDENT", + "ISEOF", + "ISNONTERMINAL", + "ISTERMINAL", + "LBRACE", + "LEFTSHIFT", + "LEFTSHIFTEQUAL", + "LESS", + "LESSEQUAL", + "LPAR", + "LSQB", + "MINEQUAL", + "MINUS", + "NAME", + "NEWLINE", + "NL", + "NOTEQUAL", + "NT_OFFSET", + "NUMBER", + "N_TOKENS", + "OP", + "PERCENT", + "PERCENTEQUAL", + "PLUS", + "PLUSEQUAL", + "RARROW", + "RBRACE", + "RIGHTSHIFT", + "RIGHTSHIFTEQUAL", + "RPAR", + "RSQB", + "SEMI", + "SLASH", + "SLASHEQUAL", + "STAR", + "STAREQUAL", + "STRING", + "TILDE", + "VBAR", + "VBAREQUAL", + "tok_name", + "tokenize", + "generate_tokens", + "untokenize", + ] +else: + __all__ = [ + "AMPER", + "AMPEREQUAL", + "ASYNC", + "AT", + "ATEQUAL", + "AWAIT", + "BACKQUOTE", + "CIRCUMFLEX", + "CIRCUMFLEXEQUAL", + "COLON", + "COMMA", + "COMMENT", + "DEDENT", + "DOT", + "DOUBLESLASH", + "DOUBLESLASHEQUAL", + "DOUBLESTAR", + "DOUBLESTAREQUAL", + "ENDMARKER", + "EQEQUAL", + "EQUAL", + "ERRORTOKEN", + "GREATER", + "GREATEREQUAL", + "INDENT", + "ISEOF", + "ISNONTERMINAL", + "ISTERMINAL", + "LBRACE", + "LEFTSHIFT", + "LEFTSHIFTEQUAL", + "LESS", + "LESSEQUAL", + "LPAR", + "LSQB", + "MINEQUAL", + "MINUS", + "NAME", + "NEWLINE", + "NL", + "NOTEQUAL", + "NT_OFFSET", + "NUMBER", + "N_TOKENS", + "OP", + "PERCENT", + "PERCENTEQUAL", + "PLUS", + "PLUSEQUAL", + "RARROW", + "RBRACE", + "RIGHTSHIFT", + "RIGHTSHIFTEQUAL", + "RPAR", + "RSQB", + "SEMI", + "SLASH", + "SLASHEQUAL", + "STAR", + "STAREQUAL", + "STRING", + "TILDE", + "VBAR", + "VBAREQUAL", + "tok_name", + "tokenize", + "generate_tokens", + "untokenize", + ] + _Coord = tuple[int, int] _TokenEater = Callable[[int, str, _Coord, _Coord, str], None] _TokenInfo = tuple[int, str, _Coord, _Coord, str] diff --git a/mypy/typeshed/stdlib/lib2to3/pytree.pyi b/mypy/typeshed/stdlib/lib2to3/pytree.pyi index 2ed9a2788d846..68e5d8ba13236 100644 --- a/mypy/typeshed/stdlib/lib2to3/pytree.pyi +++ b/mypy/typeshed/stdlib/lib2to3/pytree.pyi @@ -1,11 +1,11 @@ +from _typeshed import Self from lib2to3.pgen2.grammar import Grammar -from typing import Any, Callable, Iterator, Optional, TypeVar, Union +from typing import Any, Callable, Iterator -_P = TypeVar("_P") -_NL = Union[Node, Leaf] +_NL = Node | Leaf _Context = tuple[str, int, int] _Results = dict[str, _NL] -_RawNode = tuple[int, str, _Context, Optional[list[_NL]]] +_RawNode = tuple[int, str, _Context, list[_NL] | None] _Convert = Callable[[Grammar, _RawNode], Any] HUGE: int @@ -19,9 +19,9 @@ class Base: children: list[_NL] was_changed: bool was_checked: bool - def __eq__(self, other: Any) -> bool: ... - def _eq(self: _P, other: _P) -> bool: ... - def clone(self: _P) -> _P: ... + def __eq__(self, other: object) -> bool: ... + def _eq(self: Self, other: Self) -> bool: ... + def clone(self: Self) -> Self: ... def post_order(self) -> Iterator[_NL]: ... def pre_order(self) -> Iterator[_NL]: ... def replace(self, new: _NL | list[_NL]) -> None: ... @@ -49,6 +49,7 @@ class Node(Base): def set_child(self, i: int, child: _NL) -> None: ... def insert_child(self, i: int, child: _NL) -> None: ... def append_child(self, child: _NL) -> None: ... + def __unicode__(self) -> str: ... class Leaf(Base): lineno: int @@ -58,6 +59,7 @@ class Leaf(Base): def __init__( self, type: int, value: str, context: _Context | None = ..., prefix: str | None = ..., fixers_applied: list[Any] = ... ) -> None: ... + def __unicode__(self) -> str: ... def convert(gr: Grammar, raw_node: _RawNode) -> _NL: ... diff --git a/mypy/typeshed/stdlib/linecache.pyi b/mypy/typeshed/stdlib/linecache.pyi index e53d3efea5b20..6b3761f4a0c94 100644 --- a/mypy/typeshed/stdlib/linecache.pyi +++ b/mypy/typeshed/stdlib/linecache.pyi @@ -1,5 +1,11 @@ +import sys from typing import Any, Protocol +if sys.version_info >= (3, 9): + __all__ = ["getline", "clearcache", "checkcache", "lazycache"] +else: + __all__ = ["getline", "clearcache", "checkcache"] + _ModuleGlobals = dict[str, Any] _ModuleMetadata = tuple[int, float, list[str], str] diff --git a/mypy/typeshed/stdlib/locale.pyi b/mypy/typeshed/stdlib/locale.pyi index f3942102716ac..e5227beca149b 100644 --- a/mypy/typeshed/stdlib/locale.pyi +++ b/mypy/typeshed/stdlib/locale.pyi @@ -1,10 +1,38 @@ import sys +from _typeshed import StrPath + +__all__ = [ + "getlocale", + "getdefaultlocale", + "getpreferredencoding", + "Error", + "setlocale", + "resetlocale", + "localeconv", + "strcoll", + "strxfrm", + "str", + "atof", + "atoi", + "format", + "format_string", + "currency", + "normalize", + "LC_CTYPE", + "LC_COLLATE", + "LC_MESSAGES", + "LC_TIME", + "LC_MONETARY", + "LC_NUMERIC", + "LC_ALL", + "CHAR_MAX", +] # This module defines a function "str()", which is why "str" can't be used # as a type annotation or type alias. from builtins import str as _str from decimal import Decimal -from typing import Any, Callable, Iterable, Mapping, Sequence +from typing import Any, Callable, Iterable, Mapping CODESET: int D_T_FMT: int @@ -79,11 +107,11 @@ CHAR_MAX: int class Error(Exception): ... -def setlocale(category: int, locale: _str | Iterable[_str] | None = ...) -> _str: ... +def setlocale(category: int, locale: _str | Iterable[_str | None] | None = ...) -> _str: ... def localeconv() -> Mapping[_str, int | _str | list[int]]: ... def nl_langinfo(__key: int) -> _str: ... def getdefaultlocale(envvars: tuple[_str, ...] = ...) -> tuple[_str | None, _str | None]: ... -def getlocale(category: int = ...) -> Sequence[_str]: ... +def getlocale(category: int = ...) -> tuple[_str | None, _str | None]: ... def getpreferredencoding(do_setlocale: bool = ...) -> _str: ... def normalize(localename: _str) -> _str: ... def resetlocale(category: int = ...) -> None: ... @@ -103,6 +131,17 @@ def atof(string: _str, func: Callable[[_str], float] = ...) -> float: ... def atoi(string: _str) -> int: ... def str(val: float) -> _str: ... +# native gettext functions +# https://docs.python.org/3/library/locale.html#access-to-message-catalogs +# https://github.com/python/cpython/blob/f4c03484da59049eb62a9bf7777b963e2267d187/Modules/_localemodule.c#L626 +if sys.platform == "linux" or sys.platform == "darwin": + def gettext(__msg: _str) -> _str: ... + def dgettext(__domain: _str | None, __msg: _str) -> _str: ... + def dcgettext(__domain: _str | None, __msg: _str, __category: int) -> _str: ... + def textdomain(__domain: _str | None) -> _str: ... + def bindtextdomain(__domain: _str, __dir: StrPath | None) -> _str: ... + def bind_textdomain_codeset(__domain: _str, __codeset: _str | None) -> _str | None: ... + locale_alias: dict[_str, _str] # undocumented locale_encoding_alias: dict[_str, _str] # undocumented windows_locale: dict[int, _str] # undocumented diff --git a/mypy/typeshed/stdlib/logging/__init__.pyi b/mypy/typeshed/stdlib/logging/__init__.pyi index 442e79a9c6f32..8de4d0d88260a 100644 --- a/mypy/typeshed/stdlib/logging/__init__.pyi +++ b/mypy/typeshed/stdlib/logging/__init__.pyi @@ -6,14 +6,59 @@ from io import TextIOWrapper from string import Template from time import struct_time from types import FrameType, TracebackType -from typing import Any, ClassVar, Generic, Optional, Pattern, TextIO, Type, TypeVar, Union, overload +from typing import Any, ClassVar, Generic, Pattern, TextIO, TypeVar, Union, overload from typing_extensions import Literal -_SysExcInfoType = Union[tuple[Type[BaseException], BaseException, Optional[TracebackType]], tuple[None, None, None]] -_ExcInfoType = Union[None, bool, _SysExcInfoType, BaseException] -_ArgsType = Union[tuple[object, ...], Mapping[str, object]] -_FilterType = Union[Filter, Callable[[LogRecord], int]] -_Level = Union[int, str] +__all__ = [ + "BASIC_FORMAT", + "BufferingFormatter", + "CRITICAL", + "DEBUG", + "ERROR", + "FATAL", + "FileHandler", + "Filter", + "Formatter", + "Handler", + "INFO", + "LogRecord", + "Logger", + "LoggerAdapter", + "NOTSET", + "NullHandler", + "StreamHandler", + "WARN", + "WARNING", + "addLevelName", + "basicConfig", + "captureWarnings", + "critical", + "debug", + "disable", + "error", + "exception", + "fatal", + "getLevelName", + "getLogger", + "getLoggerClass", + "info", + "log", + "makeLogRecord", + "setLoggerClass", + "shutdown", + "warn", + "warning", + "getLogRecordFactory", + "setLogRecordFactory", + "lastResort", + "raiseExceptions", +] + +_SysExcInfoType = Union[tuple[type[BaseException], BaseException, TracebackType | None], tuple[None, None, None]] +_ExcInfoType = None | bool | _SysExcInfoType | BaseException +_ArgsType = tuple[object, ...] | Mapping[str, object] +_FilterType = Filter | Callable[[LogRecord], int] +_Level = int | str _FormatStyle = Literal["%", "{", "$"] raiseExceptions: bool @@ -39,11 +84,11 @@ class Manager: # undocumented disable: int emittedNoHandlerWarning: bool loggerDict: dict[str, Logger | PlaceHolder] - loggerClass: Type[Logger] | None + loggerClass: type[Logger] | None logRecordFactory: Callable[..., LogRecord] | None def __init__(self, rootnode: RootLogger) -> None: ... def getLogger(self, name: str) -> Logger: ... - def setLoggerClass(self, klass: Type[Logger]) -> None: ... + def setLoggerClass(self, klass: type[Logger]) -> None: ... def setLogRecordFactory(self, factory: Callable[..., LogRecord]) -> None: ... class Logger(Filterer): @@ -227,6 +272,7 @@ class Logger(Filterer): def findCaller(self, stack_info: bool = ..., stacklevel: int = ...) -> tuple[str, int, str, str | None]: ... else: def findCaller(self, stack_info: bool = ...) -> tuple[str, int, str, str | None]: ... + def handle(self, record: LogRecord) -> None: ... def makeRecord( self, @@ -301,6 +347,7 @@ class Formatter: ) -> None: ... else: def __init__(self, fmt: str | None = ..., datefmt: str | None = ..., style: _FormatStyle = ...) -> None: ... + def format(self, record: LogRecord) -> str: ... def formatTime(self, record: LogRecord, datefmt: str | None = ...) -> str: ... def formatException(self, ei: _SysExcInfoType) -> str: ... @@ -372,6 +419,7 @@ class LoggerAdapter(Generic[_L]): else: extra: Mapping[str, object] def __init__(self, logger: _L, extra: Mapping[str, object]) -> None: ... + def process(self, msg: Any, kwargs: MutableMapping[str, Any]) -> tuple[Any, MutableMapping[str, Any]]: ... if sys.version_info >= (3, 8): def debug( @@ -529,6 +577,7 @@ class LoggerAdapter(Generic[_L]): extra: Mapping[str, object] | None = ..., **kwargs: object, ) -> None: ... + def isEnabledFor(self, level: int) -> bool: ... def getEffectiveLevel(self) -> int: ... def setLevel(self, level: _Level) -> None: ... @@ -546,7 +595,7 @@ class LoggerAdapter(Generic[_L]): def name(self) -> str: ... # undocumented def getLogger(name: str | None = ...) -> Logger: ... -def getLoggerClass() -> Type[Logger]: ... +def getLoggerClass() -> type[Logger]: ... def getLogRecordFactory() -> Callable[..., LogRecord]: ... if sys.version_info >= (3, 8): @@ -703,7 +752,7 @@ else: ) -> None: ... def shutdown(handlerList: Sequence[Any] = ...) -> None: ... # handlerList is undocumented -def setLoggerClass(klass: Type[Logger]) -> None: ... +def setLoggerClass(klass: type[Logger]) -> None: ... def captureWarnings(capture: bool) -> None: ... def setLogRecordFactory(factory: Callable[..., LogRecord]) -> None: ... @@ -733,6 +782,7 @@ class FileHandler(StreamHandler[TextIOWrapper]): ) -> None: ... else: def __init__(self, filename: StrPath, mode: str = ..., encoding: str | None = ..., delay: bool = ...) -> None: ... + def _open(self) -> TextIOWrapper: ... # undocumented class NullHandler(Handler): ... @@ -760,9 +810,11 @@ class PercentStyle: # undocumented def __init__(self, fmt: str, *, defaults: Mapping[str, Any] | None = ...) -> None: ... else: def __init__(self, fmt: str) -> None: ... + def usesTime(self) -> bool: ... if sys.version_info >= (3, 8): def validate(self) -> None: ... + def format(self, record: Any) -> str: ... class StrFormatStyle(PercentStyle): # undocumented diff --git a/mypy/typeshed/stdlib/logging/handlers.pyi b/mypy/typeshed/stdlib/logging/handlers.pyi index 50d6d05835567..6402361490003 100644 --- a/mypy/typeshed/stdlib/logging/handlers.pyi +++ b/mypy/typeshed/stdlib/logging/handlers.pyi @@ -29,6 +29,7 @@ class WatchedFileHandler(FileHandler): ) -> None: ... else: def __init__(self, filename: StrPath, mode: str = ..., encoding: str | None = ..., delay: bool = ...) -> None: ... + def _statstream(self) -> None: ... # undocumented def reopenIfNeeded(self) -> None: ... @@ -41,6 +42,7 @@ class BaseRotatingHandler(FileHandler): ) -> None: ... else: def __init__(self, filename: StrPath, mode: str, encoding: str | None = ..., delay: bool = ...) -> None: ... + def rotation_filename(self, default_name: str) -> str: ... def rotate(self, source: str, dest: str) -> None: ... @@ -68,6 +70,7 @@ class RotatingFileHandler(BaseRotatingHandler): encoding: str | None = ..., delay: bool = ..., ) -> None: ... + def doRollover(self) -> None: ... def shouldRollover(self, record: LogRecord) -> int: ... # undocumented @@ -75,7 +78,7 @@ class TimedRotatingFileHandler(BaseRotatingHandler): when: str # undocumented backupCount: int # undocumented utc: bool # undocumented - atTime: datetime.datetime | None # undocumented + atTime: datetime.time | None # undocumented interval: int # undocumented suffix: str # undocumented dayOfWeek: int # undocumented @@ -91,7 +94,7 @@ class TimedRotatingFileHandler(BaseRotatingHandler): encoding: str | None = ..., delay: bool = ..., utc: bool = ..., - atTime: datetime.datetime | None = ..., + atTime: datetime.time | None = ..., errors: str | None = ..., ) -> None: ... else: @@ -104,8 +107,9 @@ class TimedRotatingFileHandler(BaseRotatingHandler): encoding: str | None = ..., delay: bool = ..., utc: bool = ..., - atTime: datetime.datetime | None = ..., + atTime: datetime.time | None = ..., ) -> None: ... + def doRollover(self) -> None: ... def shouldRollover(self, record: LogRecord) -> int: ... # undocumented def computeRollover(self, currentTime: int) -> int: ... # undocumented @@ -250,11 +254,12 @@ class QueueHandler(Handler): else: queue: Queue[Any] # undocumented def __init__(self, queue: Queue[Any]) -> None: ... + def prepare(self, record: LogRecord) -> Any: ... def enqueue(self, record: LogRecord) -> None: ... class QueueListener: - handlers: tuple[Handler] # undocumented + handlers: tuple[Handler, ...] # undocumented respect_handler_level: bool # undocumented if sys.version_info >= (3, 7): queue: SimpleQueue[Any] | Queue[Any] # undocumented @@ -264,6 +269,7 @@ class QueueListener: else: queue: Queue[Any] # undocumented def __init__(self, queue: Queue[Any], *handlers: Handler, respect_handler_level: bool = ...) -> None: ... + def dequeue(self, block: bool) -> LogRecord: ... def prepare(self, record: LogRecord) -> Any: ... def start(self) -> None: ... diff --git a/mypy/typeshed/stdlib/lzma.pyi b/mypy/typeshed/stdlib/lzma.pyi index e4bd977d7eab6..45bf24b3ef6de 100644 --- a/mypy/typeshed/stdlib/lzma.pyi +++ b/mypy/typeshed/stdlib/lzma.pyi @@ -1,43 +1,82 @@ import io from _typeshed import ReadableBuffer, Self, StrOrBytesPath -from typing import IO, Any, Mapping, Sequence, TextIO, Union, overload +from typing import IO, Any, Mapping, Sequence, TextIO, overload from typing_extensions import Literal, final +__all__ = [ + "CHECK_NONE", + "CHECK_CRC32", + "CHECK_CRC64", + "CHECK_SHA256", + "CHECK_ID_MAX", + "CHECK_UNKNOWN", + "FILTER_LZMA1", + "FILTER_LZMA2", + "FILTER_DELTA", + "FILTER_X86", + "FILTER_IA64", + "FILTER_ARM", + "FILTER_ARMTHUMB", + "FILTER_POWERPC", + "FILTER_SPARC", + "FORMAT_AUTO", + "FORMAT_XZ", + "FORMAT_ALONE", + "FORMAT_RAW", + "MF_HC3", + "MF_HC4", + "MF_BT2", + "MF_BT3", + "MF_BT4", + "MODE_FAST", + "MODE_NORMAL", + "PRESET_DEFAULT", + "PRESET_EXTREME", + "LZMACompressor", + "LZMADecompressor", + "LZMAFile", + "LZMAError", + "open", + "compress", + "decompress", + "is_check_supported", +] + _OpenBinaryWritingMode = Literal["w", "wb", "x", "xb", "a", "ab"] _OpenTextWritingMode = Literal["wt", "xt", "at"] -_PathOrFile = Union[StrOrBytesPath, IO[bytes]] +_PathOrFile = StrOrBytesPath | IO[bytes] _FilterChain = Sequence[Mapping[str, Any]] -FORMAT_AUTO: int -FORMAT_XZ: int -FORMAT_ALONE: int -FORMAT_RAW: int -CHECK_NONE: int -CHECK_CRC32: int -CHECK_CRC64: int -CHECK_SHA256: int -CHECK_ID_MAX: int -CHECK_UNKNOWN: int -FILTER_LZMA1: int -FILTER_LZMA2: int -FILTER_DELTA: int -FILTER_X86: int -FILTER_IA64: int -FILTER_ARM: int -FILTER_ARMTHUMB: int -FILTER_SPARC: int -FILTER_POWERPC: int -MF_HC3: int -MF_HC4: int -MF_BT2: int -MF_BT3: int -MF_BT4: int -MODE_FAST: int -MODE_NORMAL: int -PRESET_DEFAULT: int -PRESET_EXTREME: int +FORMAT_AUTO: Literal[0] +FORMAT_XZ: Literal[1] +FORMAT_ALONE: Literal[2] +FORMAT_RAW: Literal[3] +CHECK_NONE: Literal[0] +CHECK_CRC32: Literal[1] +CHECK_CRC64: Literal[4] +CHECK_SHA256: Literal[10] +CHECK_ID_MAX: Literal[15] +CHECK_UNKNOWN: Literal[16] +FILTER_LZMA1: int # v big number +FILTER_LZMA2: Literal[33] +FILTER_DELTA: Literal[3] +FILTER_X86: Literal[4] +FILTER_IA64: Literal[6] +FILTER_ARM: Literal[7] +FILTER_ARMTHUMB: Literal[8] +FILTER_SPARC: Literal[9] +FILTER_POWERPC: Literal[5] +MF_HC3: Literal[3] +MF_HC4: Literal[4] +MF_BT2: Literal[18] +MF_BT3: Literal[19] +MF_BT4: Literal[20] +MODE_FAST: Literal[1] +MODE_NORMAL: Literal[2] +PRESET_DEFAULT: Literal[6] +PRESET_EXTREME: int # v big number # from _lzma.c @final diff --git a/mypy/typeshed/stdlib/mailbox.pyi b/mypy/typeshed/stdlib/mailbox.pyi index ffd9c3005cecd..143891d3240bf 100644 --- a/mypy/typeshed/stdlib/mailbox.pyi +++ b/mypy/typeshed/stdlib/mailbox.pyi @@ -1,31 +1,37 @@ import email.message import sys from _typeshed import Self, StrOrBytesPath +from abc import ABCMeta, abstractmethod from types import TracebackType -from typing import ( - IO, - Any, - AnyStr, - Callable, - Generic, - Iterable, - Iterator, - Mapping, - Protocol, - Sequence, - Type, - TypeVar, - Union, - overload, -) +from typing import IO, Any, AnyStr, Callable, Generic, Iterable, Iterator, Mapping, Protocol, Sequence, TypeVar, overload from typing_extensions import Literal if sys.version_info >= (3, 9): from types import GenericAlias +__all__ = [ + "Mailbox", + "Maildir", + "mbox", + "MH", + "Babyl", + "MMDF", + "Message", + "MaildirMessage", + "mboxMessage", + "MHMessage", + "BabylMessage", + "MMDFMessage", + "Error", + "NoSuchMailboxError", + "NotEmptyError", + "ExternalClashError", + "FormatError", +] + _T = TypeVar("_T") _MessageT = TypeVar("_MessageT", bound=Message) -_MessageData = Union[email.message.Message, bytes, str, IO[str], IO[bytes]] +_MessageData = email.message.Message | bytes | str | IO[str] | IO[bytes] class _HasIteritems(Protocol): def iteritems(self) -> Iterator[tuple[str, _MessageData]]: ... @@ -42,21 +48,28 @@ class Mailbox(Generic[_MessageT]): def __init__( self, path: StrOrBytesPath, factory: Callable[[IO[Any]], _MessageT] | None = ..., create: bool = ... ) -> None: ... + @abstractmethod def add(self, message: _MessageData) -> str: ... + @abstractmethod def remove(self, key: str) -> None: ... def __delitem__(self, key: str) -> None: ... def discard(self, key: str) -> None: ... + @abstractmethod def __setitem__(self, key: str, message: _MessageData) -> None: ... @overload def get(self, key: str, default: None = ...) -> _MessageT | None: ... @overload def get(self, key: str, default: _T) -> _MessageT | _T: ... def __getitem__(self, key: str) -> _MessageT: ... + @abstractmethod def get_message(self, key: str) -> _MessageT: ... def get_string(self, key: str) -> str: ... + @abstractmethod def get_bytes(self, key: str) -> bytes: ... # As '_ProxyFile' doesn't implement the full IO spec, and BytesIO is incompatible with it, get_file return is Any here + @abstractmethod def get_file(self, key: str) -> Any: ... + @abstractmethod def iterkeys(self) -> Iterator[str]: ... def keys(self) -> list[str]: ... def itervalues(self) -> Iterator[_MessageT]: ... @@ -64,7 +77,9 @@ class Mailbox(Generic[_MessageT]): def values(self) -> list[_MessageT]: ... def iteritems(self) -> Iterator[tuple[str, _MessageT]]: ... def items(self) -> list[tuple[str, _MessageT]]: ... + @abstractmethod def __contains__(self, key: str) -> bool: ... + @abstractmethod def __len__(self) -> int: ... def clear(self) -> None: ... @overload @@ -73,9 +88,13 @@ class Mailbox(Generic[_MessageT]): def pop(self, key: str, default: _T = ...) -> _MessageT | _T: ... def popitem(self) -> tuple[str, _MessageT]: ... def update(self, arg: _HasIteritems | _HasItems | Iterable[tuple[str, _MessageData]] | None = ...) -> None: ... + @abstractmethod def flush(self) -> None: ... + @abstractmethod def lock(self) -> None: ... + @abstractmethod def unlock(self) -> None: ... + @abstractmethod def close(self) -> None: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... @@ -86,7 +105,19 @@ class Maildir(Mailbox[MaildirMessage]): def __init__( self, dirname: StrOrBytesPath, factory: Callable[[IO[Any]], MaildirMessage] | None = ..., create: bool = ... ) -> None: ... + def add(self, message: _MessageData) -> str: ... + def remove(self, key: str) -> None: ... + def __setitem__(self, key: str, message: _MessageData) -> None: ... + def get_message(self, key: str) -> MaildirMessage: ... + def get_bytes(self, key: str) -> bytes: ... def get_file(self, key: str) -> _ProxyFile[bytes]: ... + def iterkeys(self) -> Iterator[str]: ... + def __contains__(self, key: str) -> bool: ... + def __len__(self) -> int: ... + def flush(self) -> None: ... + def lock(self) -> None: ... + def unlock(self) -> None: ... + def close(self) -> None: ... def list_folders(self) -> list[str]: ... def get_folder(self, folder: str) -> Maildir: ... def add_folder(self, folder: str) -> Maildir: ... @@ -94,9 +125,20 @@ class Maildir(Mailbox[MaildirMessage]): def clean(self) -> None: ... def next(self) -> str | None: ... -class _singlefileMailbox(Mailbox[_MessageT]): ... +class _singlefileMailbox(Mailbox[_MessageT], metaclass=ABCMeta): + def add(self, message: _MessageData) -> str: ... + def remove(self, key: str) -> None: ... + def __setitem__(self, key: str, message: _MessageData) -> None: ... + def iterkeys(self) -> Iterator[str]: ... + def __contains__(self, key: str) -> bool: ... + def __len__(self) -> int: ... + def lock(self) -> None: ... + def unlock(self) -> None: ... + def flush(self) -> None: ... + def close(self) -> None: ... class _mboxMMDF(_singlefileMailbox[_MessageT]): + def get_message(self, key: str) -> _MessageT: ... def get_file(self, key: str, from_: bool = ...) -> _PartialFile[bytes]: ... def get_bytes(self, key: str, from_: bool = ...) -> bytes: ... def get_string(self, key: str, from_: bool = ...) -> str: ... @@ -115,7 +157,19 @@ class MH(Mailbox[MHMessage]): def __init__( self, path: StrOrBytesPath, factory: Callable[[IO[Any]], MHMessage] | None = ..., create: bool = ... ) -> None: ... + def add(self, message: _MessageData) -> str: ... + def remove(self, key: str) -> None: ... + def __setitem__(self, key: str, message: _MessageData) -> None: ... + def get_message(self, key: str) -> MHMessage: ... + def get_bytes(self, key: str) -> bytes: ... def get_file(self, key: str) -> _ProxyFile[bytes]: ... + def iterkeys(self) -> Iterator[str]: ... + def __contains__(self, key: str) -> bool: ... + def __len__(self) -> int: ... + def flush(self) -> None: ... + def lock(self) -> None: ... + def unlock(self) -> None: ... + def close(self) -> None: ... def list_folders(self) -> list[str]: ... def get_folder(self, folder: StrOrBytesPath) -> MH: ... def add_folder(self, folder: StrOrBytesPath) -> MH: ... @@ -128,6 +182,8 @@ class Babyl(_singlefileMailbox[BabylMessage]): def __init__( self, path: StrOrBytesPath, factory: Callable[[IO[Any]], BabylMessage] | None = ..., create: bool = ... ) -> None: ... + def get_message(self, key: str) -> BabylMessage: ... + def get_bytes(self, key: str) -> bytes: ... def get_file(self, key: str) -> IO[bytes]: ... def get_labels(self) -> list[str]: ... @@ -184,7 +240,7 @@ class _ProxyFile(Generic[AnyStr]): def seek(self, offset: int, whence: int = ...) -> None: ... def close(self) -> None: ... def __enter__(self: Self) -> Self: ... - def __exit__(self, exc_type: Type[BaseException] | None, exc: BaseException | None, tb: TracebackType | None) -> None: ... + def __exit__(self, exc_type: type[BaseException] | None, exc: BaseException | None, tb: TracebackType | None) -> None: ... def readable(self) -> bool: ... def writable(self) -> bool: ... def seekable(self) -> bool: ... diff --git a/mypy/typeshed/stdlib/mailcap.pyi b/mypy/typeshed/stdlib/mailcap.pyi index 56218d1370fe0..232ab99c314d7 100644 --- a/mypy/typeshed/stdlib/mailcap.pyi +++ b/mypy/typeshed/stdlib/mailcap.pyi @@ -1,6 +1,8 @@ -from typing import Mapping, Sequence, Union +from typing import Mapping, Sequence -_Cap = dict[str, Union[str, int]] +_Cap = dict[str, str | int] + +__all__ = ["getcaps", "findmatch"] def findmatch( caps: Mapping[str, list[_Cap]], MIMEtype: str, key: str = ..., filename: str = ..., plist: Sequence[str] = ... diff --git a/mypy/typeshed/stdlib/math.pyi b/mypy/typeshed/stdlib/math.pyi index d5e6f99dfa680..e4ab311990be1 100644 --- a/mypy/typeshed/stdlib/math.pyi +++ b/mypy/typeshed/stdlib/math.pyi @@ -1,10 +1,10 @@ import sys from _typeshed import SupportsTrunc -from typing import Iterable, SupportsFloat, Union, overload +from typing import Iterable, SupportsFloat, overload from typing_extensions import SupportsIndex if sys.version_info >= (3, 8): - _SupportsFloatOrIndex = Union[SupportsFloat, SupportsIndex] + _SupportsFloatOrIndex = SupportsFloat | SupportsIndex else: _SupportsFloatOrIndex = SupportsFloat @@ -41,6 +41,10 @@ if sys.version_info >= (3, 8): def erf(__x: _SupportsFloatOrIndex) -> float: ... def erfc(__x: _SupportsFloatOrIndex) -> float: ... def exp(__x: _SupportsFloatOrIndex) -> float: ... + +if sys.version_info >= (3, 11): + def exp2(__x: _SupportsFloatOrIndex) -> float: ... + def expm1(__x: _SupportsFloatOrIndex) -> float: ... def fabs(__x: _SupportsFloatOrIndex) -> float: ... diff --git a/mypy/typeshed/stdlib/mimetypes.pyi b/mypy/typeshed/stdlib/mimetypes.pyi index 8f51c1580eeca..e51b7cdf37bde 100644 --- a/mypy/typeshed/stdlib/mimetypes.pyi +++ b/mypy/typeshed/stdlib/mimetypes.pyi @@ -2,6 +2,22 @@ import sys from _typeshed import StrPath from typing import IO, Sequence +__all__ = [ + "knownfiles", + "inited", + "MimeTypes", + "guess_type", + "guess_all_extensions", + "guess_extension", + "add_type", + "init", + "read_mime_types", + "suffix_map", + "encodings_map", + "types_map", + "common_types", +] + if sys.version_info >= (3, 8): def guess_type(url: StrPath, strict: bool = ...) -> tuple[str | None, str | None]: ... @@ -32,6 +48,7 @@ class MimeTypes: def guess_type(self, url: StrPath, strict: bool = ...) -> tuple[str | None, str | None]: ... else: def guess_type(self, url: str, strict: bool = ...) -> tuple[str | None, str | None]: ... + def guess_all_extensions(self, type: str, strict: bool = ...) -> list[str]: ... def read(self, filename: str, strict: bool = ...) -> None: ... def readfp(self, fp: IO[str], strict: bool = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/mmap.pyi b/mypy/typeshed/stdlib/mmap.pyi index b79ab92f0c871..7448881724792 100644 --- a/mypy/typeshed/stdlib/mmap.pyi +++ b/mypy/typeshed/stdlib/mmap.pyi @@ -1,6 +1,5 @@ import sys -from _typeshed import ReadableBuffer -from contextlib import AbstractContextManager +from _typeshed import ReadableBuffer, Self from typing import Iterable, Iterator, NoReturn, Sized, overload ACCESS_DEFAULT: int @@ -13,6 +12,8 @@ ALLOCATIONGRANULARITY: int if sys.platform == "linux": MAP_DENYWRITE: int MAP_EXECUTABLE: int + if sys.version_info >= (3, 10): + MAP_POPULATE: int if sys.platform != "win32": MAP_ANON: int @@ -25,18 +26,20 @@ if sys.platform != "win32": PAGESIZE: int -class mmap(AbstractContextManager[mmap], Iterable[int], Sized): +class mmap(Iterable[int], Sized): if sys.platform == "win32": def __init__(self, fileno: int, length: int, tagname: str | None = ..., access: int = ..., offset: int = ...) -> None: ... else: def __init__( self, fileno: int, length: int, flags: int = ..., prot: int = ..., access: int = ..., offset: int = ... ) -> None: ... + def close(self) -> None: ... if sys.version_info >= (3, 8): def flush(self, offset: int = ..., size: int = ...) -> None: ... else: def flush(self, offset: int = ..., size: int = ...) -> int: ... + def move(self, dest: int, src: int, count: int) -> None: ... def read_byte(self) -> int: ... def readline(self) -> bytes: ... @@ -49,22 +52,25 @@ class mmap(AbstractContextManager[mmap], Iterable[int], Sized): closed: bool if sys.version_info >= (3, 8) and sys.platform != "win32": def madvise(self, option: int, start: int = ..., length: int = ...) -> None: ... + def find(self, sub: ReadableBuffer, start: int = ..., stop: int = ...) -> int: ... def rfind(self, sub: ReadableBuffer, start: int = ..., stop: int = ...) -> int: ... def read(self, n: int | None = ...) -> bytes: ... def write(self, bytes: ReadableBuffer) -> int: ... @overload - def __getitem__(self, index: int) -> int: ... + def __getitem__(self, __index: int) -> int: ... @overload - def __getitem__(self, index: slice) -> bytes: ... - def __delitem__(self, index: int | slice) -> NoReturn: ... + def __getitem__(self, __index: slice) -> bytes: ... + def __delitem__(self, __index: int | slice) -> NoReturn: ... @overload - def __setitem__(self, index: int, object: int) -> None: ... + def __setitem__(self, __index: int, __object: int) -> None: ... @overload - def __setitem__(self, index: slice, object: ReadableBuffer) -> None: ... + def __setitem__(self, __index: slice, __object: ReadableBuffer) -> None: ... # Doesn't actually exist, but the object is actually iterable because it has __getitem__ and # __len__, so we claim that there is also an __iter__ to help type checkers. def __iter__(self) -> Iterator[int]: ... + def __enter__(self: Self) -> Self: ... + def __exit__(self, *args: object) -> None: ... if sys.version_info >= (3, 8) and sys.platform != "win32": MADV_NORMAL: int diff --git a/mypy/typeshed/stdlib/modulefinder.pyi b/mypy/typeshed/stdlib/modulefinder.pyi index 3e7694ccffc9b..9efe032cfd29b 100644 --- a/mypy/typeshed/stdlib/modulefinder.pyi +++ b/mypy/typeshed/stdlib/modulefinder.pyi @@ -19,7 +19,6 @@ def ReplacePackage(oldname: str, newname: str) -> None: ... class Module: # undocumented def __init__(self, name: str, file: str | None = ..., path: str | None = ...) -> None: ... - def __repr__(self) -> str: ... class ModuleFinder: @@ -47,6 +46,7 @@ class ModuleFinder: excludes: Container[str] = ..., replace_paths: Sequence[tuple[str, str]] = ..., ) -> None: ... + def msg(self, level: int, str: str, *args: Any) -> None: ... # undocumented def msgin(self, *args: Any) -> None: ... # undocumented def msgout(self, *args: Any) -> None: ... # undocumented diff --git a/mypy/typeshed/stdlib/msilib/__init__.pyi b/mypy/typeshed/stdlib/msilib/__init__.pyi index b5866492a0977..c512489be34d1 100644 --- a/mypy/typeshed/stdlib/msilib/__init__.pyi +++ b/mypy/typeshed/stdlib/msilib/__init__.pyi @@ -1,10 +1,16 @@ import sys from types import ModuleType -from typing import Any, Container, Iterable, Sequence, Type +from typing import Any, Container, Iterable, Sequence from typing_extensions import Literal if sys.platform == "win32": - from _msi import _Database + from _msi import ( + CreateRecord as CreateRecord, + FCICreate as FCICreate, + OpenDatabase as OpenDatabase, + UuidCreate as UuidCreate, + _Database, + ) AMD64: bool if sys.version_info < (3, 7): @@ -22,6 +28,7 @@ if sys.platform == "win32": type_nullable: Literal[0x1000] type_key: Literal[0x2000] knownbits: Literal[0x3FFF] + class Table: name: str @@ -30,12 +37,14 @@ if sys.platform == "win32": def add_field(self, index: int, name: str, type: int) -> None: ... def sql(self) -> str: ... def create(self, db: _Database) -> None: ... + class _Unspecified: ... + def change_sequence( seq: Sequence[tuple[str, str | None, int]], action: str, - seqno: int | Type[_Unspecified] = ..., - cond: str | Type[_Unspecified] = ..., + seqno: int | type[_Unspecified] = ..., + cond: str | type[_Unspecified] = ..., ) -> None: ... def add_data(db: _Database, table: str, values: Iterable[tuple[Any, ...]]) -> None: ... def add_stream(db: _Database, name: str, path: str) -> None: ... @@ -45,6 +54,7 @@ if sys.platform == "win32": def add_tables(db: _Database, module: ModuleType) -> None: ... def make_id(str: str) -> str: ... def gen_uuid() -> str: ... + class CAB: name: str @@ -56,6 +66,7 @@ if sys.platform == "win32": def append(self, full: str, file: str, logical: str) -> tuple[int, str]: ... def commit(self, db: _Database) -> None: ... _directories: set[str] + class Directory: db: _Database @@ -91,11 +102,12 @@ if sys.platform == "win32": def add_file(self, file: str, src: str | None = ..., version: str | None = ..., language: str | None = ...) -> str: ... def glob(self, pattern: str, exclude: Container[str] | None = ...) -> list[str]: ... def remove_pyc(self) -> None: ... + class Binary: name: str def __init__(self, fname: str) -> None: ... - def __repr__(self) -> str: ... + class Feature: id: str @@ -112,6 +124,7 @@ if sys.platform == "win32": attributes: int = ..., ) -> None: ... def set_current(self) -> None: ... + class Control: dlg: Dialog @@ -120,12 +133,14 @@ if sys.platform == "win32": def event(self, event: str, argument: str, condition: str = ..., ordering: int | None = ...) -> None: ... def mapping(self, event: str, attribute: str) -> None: ... def condition(self, action: str, condition: str) -> None: ... + class RadioButtonGroup(Control): property: str index: int def __init__(self, dlg: Dialog, name: str, property: str) -> None: ... def add(self, name: str, x: int, y: int, w: int, h: int, text: str, value: str | None = ...) -> None: ... + class Dialog: db: _Database diff --git a/mypy/typeshed/stdlib/msilib/sequence.pyi b/mypy/typeshed/stdlib/msilib/sequence.pyi index 87dff754009d5..30346aba33673 100644 --- a/mypy/typeshed/stdlib/msilib/sequence.pyi +++ b/mypy/typeshed/stdlib/msilib/sequence.pyi @@ -1,9 +1,8 @@ import sys -from typing import Optional if sys.platform == "win32": - _SequenceType = list[tuple[str, Optional[str], int]] + _SequenceType = list[tuple[str, str | None, int]] AdminExecuteSequence: _SequenceType AdminUISequence: _SequenceType diff --git a/mypy/typeshed/stdlib/msvcrt.pyi b/mypy/typeshed/stdlib/msvcrt.pyi index 0441ed8acd240..35841c62f67ac 100644 --- a/mypy/typeshed/stdlib/msvcrt.pyi +++ b/mypy/typeshed/stdlib/msvcrt.pyi @@ -1,12 +1,13 @@ import sys +from typing_extensions import Literal # This module is only available on Windows if sys.platform == "win32": - LK_LOCK: int - LK_NBLCK: int - LK_NBRLCK: int - LK_RLCK: int - LK_UNLCK: int + LK_UNLCK: Literal[0] + LK_LOCK: Literal[1] + LK_NBLCK: Literal[2] + LK_RLCK: Literal[3] + LK_NBRLCK: Literal[4] def locking(__fd: int, __mode: int, __nbytes: int) -> None: ... def setmode(__fd: int, __mode: int) -> int: ... def open_osfhandle(__handle: int, __flags: int) -> int: ... diff --git a/mypy/typeshed/stdlib/multiprocessing/__init__.pyi b/mypy/typeshed/stdlib/multiprocessing/__init__.pyi index 000fed79f3e4a..3a8a382b8a275 100644 --- a/mypy/typeshed/stdlib/multiprocessing/__init__.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/__init__.pyi @@ -1,7 +1,7 @@ import sys from collections.abc import Callable, Iterable from logging import Logger -from multiprocessing import connection, context, pool, synchronize +from multiprocessing import connection, context, pool, reduction as reducer, synchronize from multiprocessing.context import ( AuthenticationError as AuthenticationError, BaseContext, @@ -20,7 +20,7 @@ from multiprocessing.process import active_children as active_children, current_ # multiprocessing.queues or the aliases defined below. See #4266 for discussion. from multiprocessing.queues import JoinableQueue as JoinableQueue, Queue as Queue, SimpleQueue as SimpleQueue from multiprocessing.spawn import freeze_support as freeze_support -from typing import Any, Union, overload +from typing import Any, overload from typing_extensions import Literal if sys.version_info >= (3, 8): @@ -29,6 +29,86 @@ if sys.version_info >= (3, 8): if sys.platform != "win32": from multiprocessing.context import ForkContext, ForkServerContext +if sys.version_info >= (3, 8): + __all__ = [ + "Array", + "AuthenticationError", + "Barrier", + "BoundedSemaphore", + "BufferTooShort", + "Condition", + "Event", + "JoinableQueue", + "Lock", + "Manager", + "Pipe", + "Pool", + "Process", + "ProcessError", + "Queue", + "RLock", + "RawArray", + "RawValue", + "Semaphore", + "SimpleQueue", + "TimeoutError", + "Value", + "active_children", + "allow_connection_pickling", + "cpu_count", + "current_process", + "freeze_support", + "get_all_start_methods", + "get_context", + "get_logger", + "get_start_method", + "parent_process", + "log_to_stderr", + "reducer", + "set_executable", + "set_forkserver_preload", + "set_start_method", + ] +else: + __all__ = [ + "Array", + "AuthenticationError", + "Barrier", + "BoundedSemaphore", + "BufferTooShort", + "Condition", + "Event", + "JoinableQueue", + "Lock", + "Manager", + "Pipe", + "Pool", + "Process", + "ProcessError", + "Queue", + "RLock", + "RawArray", + "RawValue", + "Semaphore", + "SimpleQueue", + "TimeoutError", + "Value", + "active_children", + "allow_connection_pickling", + "cpu_count", + "current_process", + "freeze_support", + "get_all_start_methods", + "get_context", + "get_logger", + "get_start_method", + "log_to_stderr", + "reducer", + "set_executable", + "set_forkserver_preload", + "set_start_method", + ] + # The following type aliases can be used to annotate the return values of # the corresponding functions. They are not defined at runtime. # @@ -54,7 +134,7 @@ _SemaphoreType = synchronize.Semaphore # be identical (modulo self). # Synchronization primitives -_LockLike = Union[synchronize.Lock, synchronize.RLock] +_LockLike = synchronize.Lock | synchronize.RLock RawValue = context._default_context.RawValue RawArray = context._default_context.RawArray Value = context._default_context.Value diff --git a/mypy/typeshed/stdlib/multiprocessing/connection.pyi b/mypy/typeshed/stdlib/multiprocessing/connection.pyi index 56db4594edc0a..5db6fa4cda7e0 100644 --- a/mypy/typeshed/stdlib/multiprocessing/connection.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/connection.pyi @@ -2,19 +2,16 @@ import socket import sys import types from _typeshed import Self -from typing import Any, Iterable, Type, Union +from typing import Any, Iterable, Union +from typing_extensions import SupportsIndex -if sys.version_info >= (3, 8): - from typing import SupportsIndex +__all__ = ["Client", "Listener", "Pipe", "wait"] # https://docs.python.org/3/library/multiprocessing.html#address-formats _Address = Union[str, tuple[str, int]] class _ConnectionBase: - if sys.version_info >= (3, 8): - def __init__(self, handle: SupportsIndex, readable: bool = ..., writable: bool = ...) -> None: ... - else: - def __init__(self, handle: int, readable: bool = ..., writable: bool = ...) -> None: ... + def __init__(self, handle: SupportsIndex, readable: bool = ..., writable: bool = ...) -> None: ... @property def closed(self) -> bool: ... # undocumented @property @@ -31,7 +28,7 @@ class _ConnectionBase: def poll(self, timeout: float | None = ...) -> bool: ... def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_value: BaseException | None, exc_tb: types.TracebackType | None + self, exc_type: type[BaseException] | None, exc_value: BaseException | None, exc_tb: types.TracebackType | None ) -> None: ... class Connection(_ConnectionBase): ... @@ -51,7 +48,7 @@ class Listener: def last_accepted(self) -> _Address | None: ... def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_value: BaseException | None, exc_tb: types.TracebackType | None + self, exc_type: type[BaseException] | None, exc_value: BaseException | None, exc_tb: types.TracebackType | None ) -> None: ... def deliver_challenge(connection: Connection, authkey: bytes) -> None: ... diff --git a/mypy/typeshed/stdlib/multiprocessing/context.pyi b/mypy/typeshed/stdlib/multiprocessing/context.pyi index 83e1b7884efc0..315918a04b985 100644 --- a/mypy/typeshed/stdlib/multiprocessing/context.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/context.pyi @@ -8,10 +8,15 @@ from multiprocessing import queues, synchronize from multiprocessing.pool import Pool as _Pool from multiprocessing.process import BaseProcess from multiprocessing.sharedctypes import SynchronizedArray, SynchronizedBase -from typing import Any, Type, TypeVar, Union, overload +from typing import Any, ClassVar, TypeVar, overload from typing_extensions import Literal -_LockLike = Union[synchronize.Lock, synchronize.RLock] +if sys.version_info >= (3, 8): + __all__ = () +else: + __all__: list[str] = [] + +_LockLike = synchronize.Lock | synchronize.RLock _CT = TypeVar("_CT", bound=_CData) class ProcessError(Exception): ... @@ -20,11 +25,11 @@ class TimeoutError(ProcessError): ... class AuthenticationError(ProcessError): ... class BaseContext: - Process: Type[BaseProcess] - ProcessError: Type[Exception] - BufferTooShort: Type[Exception] - TimeoutError: Type[Exception] - AuthenticationError: Type[Exception] + Process: type[BaseProcess] + ProcessError: type[Exception] + BufferTooShort: type[Exception] + TimeoutError: type[Exception] + AuthenticationError: type[Exception] # N.B. The methods below are applied at runtime to generate # multiprocessing.*, so the signatures should be identical (modulo self). @@ -33,6 +38,7 @@ class BaseContext: if sys.version_info >= (3, 8): @staticmethod def parent_process() -> BaseProcess | None: ... + @staticmethod def active_children() -> list[BaseProcess]: ... def cpu_count(self) -> int: ... @@ -60,26 +66,26 @@ class BaseContext: maxtasksperchild: int | None = ..., ) -> _Pool: ... @overload - def RawValue(self, typecode_or_type: Type[_CT], *args: Any) -> _CT: ... + def RawValue(self, typecode_or_type: type[_CT], *args: Any) -> _CT: ... @overload def RawValue(self, typecode_or_type: str, *args: Any) -> Any: ... @overload - def RawArray(self, typecode_or_type: Type[_CT], size_or_initializer: int | Sequence[Any]) -> ctypes.Array[_CT]: ... + def RawArray(self, typecode_or_type: type[_CT], size_or_initializer: int | Sequence[Any]) -> ctypes.Array[_CT]: ... @overload def RawArray(self, typecode_or_type: str, size_or_initializer: int | Sequence[Any]) -> Any: ... @overload - def Value(self, typecode_or_type: Type[_CT], *args: Any, lock: Literal[False]) -> _CT: ... + def Value(self, typecode_or_type: type[_CT], *args: Any, lock: Literal[False]) -> _CT: ... @overload - def Value(self, typecode_or_type: Type[_CT], *args: Any, lock: Literal[True] | _LockLike) -> SynchronizedBase[_CT]: ... + def Value(self, typecode_or_type: type[_CT], *args: Any, lock: Literal[True] | _LockLike) -> SynchronizedBase[_CT]: ... @overload def Value(self, typecode_or_type: str, *args: Any, lock: Literal[True] | _LockLike) -> SynchronizedBase[Any]: ... @overload - def Value(self, typecode_or_type: str | Type[_CData], *args: Any, lock: bool | _LockLike = ...) -> Any: ... + def Value(self, typecode_or_type: str | type[_CData], *args: Any, lock: bool | _LockLike = ...) -> Any: ... @overload - def Array(self, typecode_or_type: Type[_CT], size_or_initializer: int | Sequence[Any], *, lock: Literal[False]) -> _CT: ... + def Array(self, typecode_or_type: type[_CT], size_or_initializer: int | Sequence[Any], *, lock: Literal[False]) -> _CT: ... @overload def Array( - self, typecode_or_type: Type[_CT], size_or_initializer: int | Sequence[Any], *, lock: Literal[True] | _LockLike + self, typecode_or_type: type[_CT], size_or_initializer: int | Sequence[Any], *, lock: Literal[True] | _LockLike ) -> SynchronizedArray[_CT]: ... @overload def Array( @@ -87,7 +93,7 @@ class BaseContext: ) -> SynchronizedArray[Any]: ... @overload def Array( - self, typecode_or_type: str | Type[_CData], size_or_initializer: int | Sequence[Any], *, lock: bool | _LockLike = ... + self, typecode_or_type: str | type[_CData], size_or_initializer: int | Sequence[Any], *, lock: bool | _LockLike = ... ) -> Any: ... def freeze_support(self) -> None: ... def get_logger(self) -> Logger: ... @@ -113,6 +119,7 @@ class BaseContext: def get_context(self, method: Literal["spawn"]) -> SpawnContext: ... @overload def get_context(self, method: str) -> BaseContext: ... + def get_start_method(self, allow_none: bool = ...) -> str: ... def set_start_method(self, method: str | None, force: bool = ...) -> None: ... @property @@ -127,11 +134,13 @@ class Process(BaseProcess): def _Popen(process_obj: BaseProcess) -> DefaultContext: ... class DefaultContext(BaseContext): - Process: Type[multiprocessing.Process] + Process: type[multiprocessing.Process] def __init__(self, context: BaseContext) -> None: ... def set_start_method(self, method: str | None, force: bool = ...) -> None: ... def get_start_method(self, allow_none: bool = ...) -> str: ... def get_all_start_methods(self) -> list[str]: ... + if sys.version_info < (3, 8): + __all__: ClassVar[list[str]] _default_context: DefaultContext @@ -140,32 +149,38 @@ if sys.platform != "win32": _start_method: str @staticmethod def _Popen(process_obj: BaseProcess) -> Any: ... + class SpawnProcess(BaseProcess): _start_method: str @staticmethod def _Popen(process_obj: BaseProcess) -> SpawnProcess: ... + class ForkServerProcess(BaseProcess): _start_method: str @staticmethod def _Popen(process_obj: BaseProcess) -> Any: ... + class ForkContext(BaseContext): _name: str - Process: Type[ForkProcess] + Process: type[ForkProcess] + class SpawnContext(BaseContext): _name: str - Process: Type[SpawnProcess] + Process: type[SpawnProcess] + class ForkServerContext(BaseContext): _name: str - Process: Type[ForkServerProcess] + Process: type[ForkServerProcess] else: class SpawnProcess(BaseProcess): _start_method: str @staticmethod def _Popen(process_obj: BaseProcess) -> Any: ... + class SpawnContext(BaseContext): _name: str - Process: Type[SpawnProcess] + Process: type[SpawnProcess] def _force_start_method(method: str) -> None: ... def get_spawning_popen() -> Any | None: ... diff --git a/mypy/typeshed/stdlib/multiprocessing/dummy/__init__.pyi b/mypy/typeshed/stdlib/multiprocessing/dummy/__init__.pyi index b4d1c8404d8d5..48f42999866a2 100644 --- a/mypy/typeshed/stdlib/multiprocessing/dummy/__init__.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/dummy/__init__.pyi @@ -3,6 +3,28 @@ import threading import weakref from queue import Queue as Queue from typing import Any, Callable, Iterable, Mapping, Sequence +from typing_extensions import Literal + +from .connection import Pipe as Pipe + +__all__ = [ + "Process", + "current_process", + "active_children", + "freeze_support", + "Lock", + "RLock", + "Semaphore", + "BoundedSemaphore", + "Condition", + "Event", + "Barrier", + "Queue", + "Manager", + "Pipe", + "Pool", + "JoinableQueue", +] JoinableQueue = Queue Barrier = threading.Barrier @@ -18,7 +40,8 @@ class DummyProcess(threading.Thread): _parent: threading.Thread _pid: None _start_called: int - exitcode: int | None + @property + def exitcode(self) -> Literal[0] | None: ... def __init__( self, group: Any = ..., diff --git a/mypy/typeshed/stdlib/multiprocessing/dummy/connection.pyi b/mypy/typeshed/stdlib/multiprocessing/dummy/connection.pyi index 9500a38364f0a..c61617cd91d4f 100644 --- a/mypy/typeshed/stdlib/multiprocessing/dummy/connection.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/dummy/connection.pyi @@ -1,7 +1,9 @@ from _typeshed import Self from queue import Queue from types import TracebackType -from typing import Any, Type, Union +from typing import Any, Union + +__all__ = ["Client", "Listener", "Pipe"] families: list[None] @@ -16,7 +18,7 @@ class Connection: send_bytes: Any def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_value: BaseException | None, exc_tb: TracebackType | None ) -> None: ... def __init__(self, _in: Any, _out: Any) -> None: ... def close(self) -> None: ... @@ -28,7 +30,7 @@ class Listener: def address(self) -> Queue[Any] | None: ... def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_value: BaseException | None, exc_tb: TracebackType | None ) -> None: ... def __init__(self, address: _Address | None = ..., family: int | None = ..., backlog: int = ...) -> None: ... def accept(self) -> Connection: ... diff --git a/mypy/typeshed/stdlib/multiprocessing/managers.pyi b/mypy/typeshed/stdlib/multiprocessing/managers.pyi index 79310614efc11..a0f76b636c4b2 100644 --- a/mypy/typeshed/stdlib/multiprocessing/managers.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/managers.pyi @@ -1,7 +1,8 @@ import queue import sys import threading -from contextlib import AbstractContextManager +from _typeshed import Self +from types import TracebackType from typing import Any, AnyStr, Callable, Generic, Iterable, Mapping, Sequence, TypeVar from .connection import Connection @@ -10,8 +11,12 @@ from .context import BaseContext if sys.version_info >= (3, 8): from .shared_memory import _SLT, ShareableList, SharedMemory + __all__ = ["BaseManager", "SyncManager", "BaseProxy", "Token", "SharedMemoryManager"] + _SharedMemory = SharedMemory _ShareableList = ShareableList +else: + __all__ = ["BaseManager", "SyncManager", "BaseProxy", "Token"] if sys.version_info >= (3, 9): from types import GenericAlias @@ -32,7 +37,6 @@ class Token: address: tuple[str | bytes, int] id: str | bytes | int | None def __init__(self, typeid: bytes | str | None, address: tuple[str | bytes, int], id: str | bytes | int | None) -> None: ... - def __repr__(self) -> str: ... def __getstate__(self) -> tuple[str | bytes | None, tuple[str | bytes, int], str | bytes | int | None]: ... def __setstate__(self, state: tuple[str | bytes | None, tuple[str | bytes, int], str | bytes | int | None]) -> None: ... @@ -70,7 +74,7 @@ class Server: def serve_forever(self) -> None: ... def accept_connection(self, c: Connection, name: str) -> None: ... -class BaseManager(AbstractContextManager[BaseManager]): +class BaseManager: def __init__( self, address: Any | None = ..., authkey: bytes | None = ..., serializer: str = ..., ctx: BaseContext | None = ... ) -> None: ... @@ -91,12 +95,16 @@ class BaseManager(AbstractContextManager[BaseManager]): method_to_typeid: Mapping[str, str] | None = ..., create_method: bool = ..., ) -> None: ... + def __enter__(self: Self) -> Self: ... + def __exit__( + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> None: ... # Conflicts with method names _dict = dict _list = list -class SyncManager(BaseManager, AbstractContextManager[SyncManager]): +class SyncManager(BaseManager): def BoundedSemaphore(self, value: Any = ...) -> threading.BoundedSemaphore: ... def Condition(self, lock: Any = ...) -> threading.Condition: ... def Event(self) -> threading.Event: ... @@ -114,6 +122,7 @@ class RemoteError(Exception): ... if sys.version_info >= (3, 8): class SharedMemoryServer(Server): ... + class SharedMemoryManager(BaseManager): def get_server(self) -> SharedMemoryServer: ... def SharedMemory(self, size: int) -> _SharedMemory: ... diff --git a/mypy/typeshed/stdlib/multiprocessing/pool.pyi b/mypy/typeshed/stdlib/multiprocessing/pool.pyi index 518e4b7364d75..5e38e01618342 100644 --- a/mypy/typeshed/stdlib/multiprocessing/pool.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/pool.pyi @@ -1,6 +1,6 @@ import sys from _typeshed import Self -from contextlib import AbstractContextManager +from types import TracebackType from typing import Any, Callable, Generic, Iterable, Iterator, Mapping, TypeVar from typing_extensions import Literal @@ -9,7 +9,6 @@ if sys.version_info >= (3, 9): __all__ = ["Pool", "ThreadPool"] -_PT = TypeVar("_PT", bound=Pool) _S = TypeVar("_S") _T = TypeVar("_T") @@ -25,6 +24,7 @@ class ApplyResult(Generic[_T]): callback: Callable[[_T], None] | None, error_callback: Callable[[BaseException], None] | None, ) -> None: ... + def get(self, timeout: float | None = ...) -> _T: ... def wait(self, timeout: float | None = ...) -> None: ... def ready(self) -> bool: ... @@ -60,13 +60,14 @@ class IMapIterator(Iterator[_T]): def __init__(self, pool: Pool) -> None: ... else: def __init__(self, cache: dict[int, IMapIterator[Any]]) -> None: ... - def __iter__(self: _S) -> _S: ... + + def __iter__(self: Self) -> Self: ... def next(self, timeout: float | None = ...) -> _T: ... def __next__(self, timeout: float | None = ...) -> _T: ... class IMapUnorderedIterator(IMapIterator[_T]): ... -class Pool(AbstractContextManager[Pool]): +class Pool: def __init__( self, processes: int | None = ..., @@ -110,8 +111,11 @@ class Pool(AbstractContextManager[Pool]): def terminate(self) -> None: ... def join(self) -> None: ... def __enter__(self: Self) -> Self: ... + def __exit__( + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> None: ... -class ThreadPool(Pool, AbstractContextManager[ThreadPool]): +class ThreadPool(Pool): def __init__( self, processes: int | None = ..., initializer: Callable[..., Any] | None = ..., initargs: Iterable[Any] = ... ) -> None: ... diff --git a/mypy/typeshed/stdlib/multiprocessing/process.pyi b/mypy/typeshed/stdlib/multiprocessing/process.pyi index 4746c78b1b4d8..1601decbbebcf 100644 --- a/mypy/typeshed/stdlib/multiprocessing/process.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/process.pyi @@ -1,5 +1,11 @@ import sys -from typing import Any, Callable, Mapping +from collections.abc import Callable, Iterable, Mapping +from typing import Any + +if sys.version_info >= (3, 8): + __all__ = ["BaseProcess", "current_process", "active_children", "parent_process"] +else: + __all__ = ["BaseProcess", "current_process", "active_children"] class BaseProcess: name: str @@ -11,7 +17,7 @@ class BaseProcess: group: None = ..., target: Callable[..., Any] | None = ..., name: str | None = ..., - args: tuple[Any, ...] = ..., + args: Iterable[Any] = ..., kwargs: Mapping[str, Any] = ..., *, daemon: bool | None = ..., @@ -22,6 +28,7 @@ class BaseProcess: if sys.version_info >= (3, 7): def kill(self) -> None: ... def close(self) -> None: ... + def join(self, timeout: float | None = ...) -> None: ... def is_alive(self) -> bool: ... @property diff --git a/mypy/typeshed/stdlib/multiprocessing/queues.pyi b/mypy/typeshed/stdlib/multiprocessing/queues.pyi index 1c9d76917292a..1d31fa694c454 100644 --- a/mypy/typeshed/stdlib/multiprocessing/queues.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/queues.pyi @@ -5,6 +5,8 @@ from typing import Any, Generic, TypeVar if sys.version_info >= (3, 9): from types import GenericAlias +__all__ = ["Queue", "SimpleQueue", "JoinableQueue"] + _T = TypeVar("_T") class Queue(queue.Queue[_T]): @@ -30,6 +32,7 @@ class SimpleQueue(Generic[_T]): def __init__(self, *, ctx: Any = ...) -> None: ... if sys.version_info >= (3, 9): def close(self) -> None: ... + def empty(self) -> bool: ... def get(self) -> _T: ... def put(self, item: _T) -> None: ... diff --git a/mypy/typeshed/stdlib/multiprocessing/reduction.pyi b/mypy/typeshed/stdlib/multiprocessing/reduction.pyi new file mode 100644 index 0000000000000..9e7387da64a5b --- /dev/null +++ b/mypy/typeshed/stdlib/multiprocessing/reduction.pyi @@ -0,0 +1,84 @@ +import pickle +import sys +from abc import ABCMeta +from copyreg import _DispatchTableType +from typing import Any +from typing_extensions import Literal + +if sys.platform == "win32": + __all__ = ["send_handle", "recv_handle", "ForkingPickler", "register", "dump", "DupHandle", "duplicate", "steal_handle"] +else: + __all__ = ["send_handle", "recv_handle", "ForkingPickler", "register", "dump", "DupFd", "sendfds", "recvfds"] + +class ForkingPickler(pickle.Pickler): + dispatch_table: _DispatchTableType + def __init__(self, *args) -> None: ... + @classmethod + def register(cls, type, reduce) -> None: ... + @classmethod + def dumps(cls, obj, protocol: Any | None = ...): ... + loads = pickle.loads + +register = ForkingPickler.register + +def dump(obj, file, protocol: Any | None = ...) -> None: ... + +if sys.platform == "win32": + if sys.version_info >= (3, 8): + def duplicate(handle, target_process: Any | None = ..., inheritable: bool = ..., *, source_process: Any | None = ...): ... + else: + def duplicate(handle, target_process: Any | None = ..., inheritable: bool = ...): ... + + def steal_handle(source_pid, handle): ... + def send_handle(conn, handle, destination_pid) -> None: ... + def recv_handle(conn): ... + + class DupHandle: + def __init__(self, handle, access, pid: Any | None = ...) -> None: ... + def detach(self): ... + +else: + if sys.platform == "darwin": + ACKNOWLEDGE: Literal[True] + else: + ACKNOWLEDGE: Literal[False] + + def recvfds(sock, size): ... + def send_handle(conn, handle, destination_pid) -> None: ... + def recv_handle(conn) -> None: ... + def sendfds(sock, fds) -> None: ... + def DupFd(fd): ... + +# These aliases are to work around pyright complaints. +# Pyright doesn't like it when a class object is defined as an alias +# of a global object with the same name. +_ForkingPickler = ForkingPickler +_register = register +_dump = dump +_send_handle = send_handle +_recv_handle = recv_handle + +if sys.platform == "win32": + _steal_handle = steal_handle + _duplicate = duplicate + _DupHandle = DupHandle +else: + _sendfds = sendfds + _recvfds = recvfds + _DupFd = DupFd + +class AbstractReducer(metaclass=ABCMeta): + ForkingPickler = _ForkingPickler + register = _register + dump = _dump + send_handle = _send_handle + recv_handle = _recv_handle + if sys.platform == "win32": + steal_handle = _steal_handle + duplicate = _duplicate + DupHandle = _DupHandle + else: + sendfds = _sendfds + recvfds = _recvfds + DupFd = _DupFd + def __init__(self, *args) -> None: ... diff --git a/mypy/typeshed/stdlib/multiprocessing/shared_memory.pyi b/mypy/typeshed/stdlib/multiprocessing/shared_memory.pyi index 1b51da38bc430..a4c4fd071c5f5 100644 --- a/mypy/typeshed/stdlib/multiprocessing/shared_memory.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/shared_memory.pyi @@ -1,33 +1,35 @@ import sys +from _typeshed import Self from typing import Any, Generic, Iterable, TypeVar if sys.version_info >= (3, 9): from types import GenericAlias -_S = TypeVar("_S") +__all__ = ["SharedMemory", "ShareableList"] + _SLT = TypeVar("_SLT", int, float, bool, str, bytes, None) -if sys.version_info >= (3, 8): - class SharedMemory: - def __init__(self, name: str | None = ..., create: bool = ..., size: int = ...) -> None: ... - @property - def buf(self) -> memoryview: ... - @property - def name(self) -> str: ... - @property - def size(self) -> int: ... - def close(self) -> None: ... - def unlink(self) -> None: ... - class ShareableList(Generic[_SLT]): - shm: SharedMemory - def __init__(self, sequence: Iterable[_SLT] | None = ..., *, name: str | None = ...) -> None: ... - def __getitem__(self, position: int) -> _SLT: ... - def __setitem__(self, position: int, value: _SLT) -> None: ... - def __reduce__(self: _S) -> tuple[_S, tuple[_SLT, ...]]: ... - def __len__(self) -> int: ... - @property - def format(self) -> str: ... - def count(self, value: _SLT) -> int: ... - def index(self, value: _SLT) -> int: ... - if sys.version_info >= (3, 9): - def __class_getitem__(cls, item: Any) -> GenericAlias: ... +class SharedMemory: + def __init__(self, name: str | None = ..., create: bool = ..., size: int = ...) -> None: ... + @property + def buf(self) -> memoryview: ... + @property + def name(self) -> str: ... + @property + def size(self) -> int: ... + def close(self) -> None: ... + def unlink(self) -> None: ... + +class ShareableList(Generic[_SLT]): + shm: SharedMemory + def __init__(self, sequence: Iterable[_SLT] | None = ..., *, name: str | None = ...) -> None: ... + def __getitem__(self, position: int) -> _SLT: ... + def __setitem__(self, position: int, value: _SLT) -> None: ... + def __reduce__(self: Self) -> tuple[Self, tuple[_SLT, ...]]: ... + def __len__(self) -> int: ... + @property + def format(self) -> str: ... + def count(self, value: _SLT) -> int: ... + def index(self, value: _SLT) -> int: ... + if sys.version_info >= (3, 9): + def __class_getitem__(cls, item: Any) -> GenericAlias: ... diff --git a/mypy/typeshed/stdlib/multiprocessing/sharedctypes.pyi b/mypy/typeshed/stdlib/multiprocessing/sharedctypes.pyi index bd9d8f0898759..8b1b1c1cee6ee 100644 --- a/mypy/typeshed/stdlib/multiprocessing/sharedctypes.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/sharedctypes.pyi @@ -3,25 +3,28 @@ from collections.abc import Callable, Iterable, Sequence from ctypes import _CData, _SimpleCData, c_char from multiprocessing.context import BaseContext from multiprocessing.synchronize import _LockLike -from typing import Any, Generic, Protocol, Type, TypeVar, overload +from types import TracebackType +from typing import Any, Generic, Protocol, TypeVar, overload from typing_extensions import Literal +__all__ = ["RawValue", "RawArray", "Value", "Array", "copy", "synchronized"] + _T = TypeVar("_T") _CT = TypeVar("_CT", bound=_CData) @overload -def RawValue(typecode_or_type: Type[_CT], *args: Any) -> _CT: ... +def RawValue(typecode_or_type: type[_CT], *args: Any) -> _CT: ... @overload def RawValue(typecode_or_type: str, *args: Any) -> Any: ... @overload -def RawArray(typecode_or_type: Type[_CT], size_or_initializer: int | Sequence[Any]) -> ctypes.Array[_CT]: ... +def RawArray(typecode_or_type: type[_CT], size_or_initializer: int | Sequence[Any]) -> ctypes.Array[_CT]: ... @overload def RawArray(typecode_or_type: str, size_or_initializer: int | Sequence[Any]) -> Any: ... @overload -def Value(typecode_or_type: Type[_CT], *args: Any, lock: Literal[False], ctx: BaseContext | None = ...) -> _CT: ... +def Value(typecode_or_type: type[_CT], *args: Any, lock: Literal[False], ctx: BaseContext | None = ...) -> _CT: ... @overload def Value( - typecode_or_type: Type[_CT], *args: Any, lock: Literal[True] | _LockLike, ctx: BaseContext | None = ... + typecode_or_type: type[_CT], *args: Any, lock: Literal[True] | _LockLike, ctx: BaseContext | None = ... ) -> SynchronizedBase[_CT]: ... @overload def Value( @@ -29,15 +32,15 @@ def Value( ) -> SynchronizedBase[Any]: ... @overload def Value( - typecode_or_type: str | Type[_CData], *args: Any, lock: bool | _LockLike = ..., ctx: BaseContext | None = ... + typecode_or_type: str | type[_CData], *args: Any, lock: bool | _LockLike = ..., ctx: BaseContext | None = ... ) -> Any: ... @overload def Array( - typecode_or_type: Type[_CT], size_or_initializer: int | Sequence[Any], *, lock: Literal[False], ctx: BaseContext | None = ... + typecode_or_type: type[_CT], size_or_initializer: int | Sequence[Any], *, lock: Literal[False], ctx: BaseContext | None = ... ) -> _CT: ... @overload def Array( - typecode_or_type: Type[_CT], + typecode_or_type: type[_CT], size_or_initializer: int | Sequence[Any], *, lock: Literal[True] | _LockLike, @@ -53,7 +56,7 @@ def Array( ) -> SynchronizedArray[Any]: ... @overload def Array( - typecode_or_type: str | Type[_CData], + typecode_or_type: str | type[_CData], size_or_initializer: int | Sequence[Any], *, lock: bool | _LockLike = ..., @@ -76,11 +79,13 @@ class SynchronizedBase(Generic[_CT]): acquire: _AcquireFunc release: Callable[[], None] def __init__(self, obj: Any, lock: _LockLike | None = ..., ctx: Any | None = ...) -> None: ... - def __reduce__(self) -> tuple[Callable[..., Any], tuple[Any, _LockLike]]: ... + def __reduce__(self) -> tuple[Callable[[Any, _LockLike], SynchronizedBase[Any]], tuple[Any, _LockLike]]: ... def get_obj(self) -> _CT: ... def get_lock(self) -> _LockLike: ... def __enter__(self) -> bool: ... - def __exit__(self, *args: Any) -> None: ... + def __exit__( + self, __exc_type: type[BaseException] | None, __exc_val: BaseException | None, __exc_tb: TracebackType | None + ) -> None: ... class Synchronized(SynchronizedBase[_SimpleCData[_T]], Generic[_T]): value: _T @@ -88,7 +93,7 @@ class Synchronized(SynchronizedBase[_SimpleCData[_T]], Generic[_T]): class SynchronizedArray(SynchronizedBase[ctypes.Array[_CT]], Generic[_CT]): def __len__(self) -> int: ... def __getitem__(self, i: int) -> _CT: ... - def __setitem__(self, i: int, o: _CT) -> None: ... + def __setitem__(self, i: int, value: _CT) -> None: ... def __getslice__(self, start: int, stop: int) -> list[_CT]: ... def __setslice__(self, start: int, stop: int, values: Iterable[_CT]) -> None: ... diff --git a/mypy/typeshed/stdlib/multiprocessing/spawn.pyi b/mypy/typeshed/stdlib/multiprocessing/spawn.pyi index 34c7322e0d466..4f981ea467c48 100644 --- a/mypy/typeshed/stdlib/multiprocessing/spawn.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/spawn.pyi @@ -1,6 +1,16 @@ from types import ModuleType from typing import Any, Mapping, Sequence +__all__ = [ + "_main", + "freeze_support", + "set_executable", + "get_executable", + "get_preparation_data", + "get_command_line", + "import_main_path", +] + WINEXE: bool WINSERVICE: bool diff --git a/mypy/typeshed/stdlib/multiprocessing/synchronize.pyi b/mypy/typeshed/stdlib/multiprocessing/synchronize.pyi index c32c9aafe9a4d..0cfc815b2d824 100644 --- a/mypy/typeshed/stdlib/multiprocessing/synchronize.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/synchronize.pyi @@ -2,9 +2,12 @@ import sys import threading from contextlib import AbstractContextManager from multiprocessing.context import BaseContext -from typing import Any, Callable, Union +from types import TracebackType +from typing import Any, Callable -_LockLike = Union[Lock, RLock] +__all__ = ["Lock", "RLock", "Semaphore", "BoundedSemaphore", "Condition", "Event"] + +_LockLike = Lock | RLock class Barrier(threading.Barrier): def __init__( @@ -20,13 +23,17 @@ class Condition(AbstractContextManager[bool]): def notify(self, n: int = ...) -> None: ... else: def notify(self) -> None: ... + def notify_all(self) -> None: ... def wait(self, timeout: float | None = ...) -> bool: ... def wait_for(self, predicate: Callable[[], bool], timeout: float | None = ...) -> bool: ... def acquire(self, block: bool = ..., timeout: float | None = ...) -> bool: ... def release(self) -> None: ... + def __exit__( + self, __exc_type: type[BaseException] | None, __exc_val: BaseException | None, __exc_tb: TracebackType | None + ) -> None: ... -class Event(AbstractContextManager[bool]): +class Event: def __init__(self, lock: _LockLike | None = ..., *, ctx: BaseContext) -> None: ... def is_set(self) -> bool: ... def set(self) -> None: ... @@ -46,3 +53,6 @@ class Semaphore(SemLock): class SemLock(AbstractContextManager[bool]): def acquire(self, block: bool = ..., timeout: float | None = ...) -> bool: ... def release(self) -> None: ... + def __exit__( + self, __exc_type: type[BaseException] | None, __exc_val: BaseException | None, __exc_tb: TracebackType | None + ) -> None: ... diff --git a/mypy/typeshed/stdlib/netrc.pyi b/mypy/typeshed/stdlib/netrc.pyi index 7c1c2068aff69..45f6cfbeda7bf 100644 --- a/mypy/typeshed/stdlib/netrc.pyi +++ b/mypy/typeshed/stdlib/netrc.pyi @@ -1,5 +1,6 @@ from _typeshed import StrOrBytesPath -from typing import Optional + +__all__ = ["netrc", "NetrcParseError"] class NetrcParseError(Exception): filename: str | None @@ -8,7 +9,7 @@ class NetrcParseError(Exception): def __init__(self, msg: str, filename: StrOrBytesPath | None = ..., lineno: int | None = ...) -> None: ... # (login, account, password) tuple -_NetrcTuple = tuple[str, Optional[str], Optional[str]] +_NetrcTuple = tuple[str, str | None, str | None] class netrc: hosts: dict[str, _NetrcTuple] diff --git a/mypy/typeshed/stdlib/nis.pyi b/mypy/typeshed/stdlib/nis.pyi index b762ae46241c2..10eef2336a834 100644 --- a/mypy/typeshed/stdlib/nis.pyi +++ b/mypy/typeshed/stdlib/nis.pyi @@ -5,4 +5,5 @@ if sys.platform != "win32": def get_default_domain() -> str: ... def maps(domain: str = ...) -> list[str]: ... def match(key: str, map: str, domain: str = ...) -> str: ... + class error(Exception): ... diff --git a/mypy/typeshed/stdlib/nntplib.pyi b/mypy/typeshed/stdlib/nntplib.pyi index f0a0fb42da5c9..cc48cb83ae4c2 100644 --- a/mypy/typeshed/stdlib/nntplib.pyi +++ b/mypy/typeshed/stdlib/nntplib.pyi @@ -3,9 +3,22 @@ import socket import ssl import sys from _typeshed import Self -from typing import IO, Any, Iterable, NamedTuple, Union +from typing import IO, Any, Iterable, NamedTuple +from typing_extensions import Literal -_File = Union[IO[bytes], bytes, str, None] +__all__ = [ + "NNTP", + "NNTPError", + "NNTPReplyError", + "NNTPTemporaryError", + "NNTPPermanentError", + "NNTPProtocolError", + "NNTPDataError", + "decode_header", + "NNTP_SSL", +] + +_File = IO[bytes] | bytes | str | None class NNTPError(Exception): response: str @@ -16,8 +29,8 @@ class NNTPPermanentError(NNTPError): ... class NNTPProtocolError(NNTPError): ... class NNTPDataError(NNTPError): ... -NNTP_PORT: int -NNTP_SSL_PORT: int +NNTP_PORT: Literal[119] +NNTP_SSL_PORT: Literal[563] class GroupInfo(NamedTuple): group: str @@ -34,11 +47,13 @@ def decode_header(header_str: str) -> str: ... _list = list # conflicts with a method named "list" -class _NNTPBase: +class NNTP: encoding: str errors: str host: str + port: int + sock: socket.socket file: IO[bytes] debugging: int welcome: str @@ -47,9 +62,18 @@ class _NNTPBase: authenticated: bool nntp_implementation: str nntp_version: int - def __init__(self, file: IO[bytes], host: str, readermode: bool | None = ..., timeout: float = ...) -> None: ... + def __init__( + self, + host: str, + port: int = ..., + user: str | None = ..., + password: str | None = ..., + readermode: bool | None = ..., + usenetrc: bool = ..., + timeout: float = ..., + ) -> None: ... def __enter__(self: Self) -> Self: ... - def __exit__(self, *args: Any) -> None: ... + def __exit__(self, *args: object) -> None: ... def getwelcome(self) -> str: ... def getcapabilities(self) -> dict[str, _list[str]]: ... def set_debuglevel(self, level: int) -> None: ... @@ -77,6 +101,7 @@ class _NNTPBase: if sys.version_info < (3, 9): def xgtitle(self, group: str, *, file: _File = ...) -> tuple[str, _list[tuple[str, str]]]: ... def xpath(self, id: Any) -> tuple[str, str]: ... + def date(self) -> tuple[str, datetime.datetime]: ... def post(self, data: bytes | Iterable[bytes]) -> str: ... def ihave(self, message_id: Any, data: bytes | Iterable[bytes]) -> str: ... @@ -84,22 +109,9 @@ class _NNTPBase: def login(self, user: str | None = ..., password: str | None = ..., usenetrc: bool = ...) -> None: ... def starttls(self, context: ssl.SSLContext | None = ...) -> None: ... -class NNTP(_NNTPBase): - port: int - sock: socket.socket - def __init__( - self, - host: str, - port: int = ..., - user: str | None = ..., - password: str | None = ..., - readermode: bool | None = ..., - usenetrc: bool = ..., - timeout: float = ..., - ) -> None: ... - -class NNTP_SSL(_NNTPBase): - sock: socket.socket +class NNTP_SSL(NNTP): + ssl_context: ssl.SSLContext | None + sock: ssl.SSLSocket def __init__( self, host: str, diff --git a/mypy/typeshed/stdlib/ntpath.pyi b/mypy/typeshed/stdlib/ntpath.pyi index f691356cb702c..ffe5cc1e5a2dd 100644 --- a/mypy/typeshed/stdlib/ntpath.pyi +++ b/mypy/typeshed/stdlib/ntpath.pyi @@ -44,10 +44,94 @@ from posixpath import ( ) from typing import AnyStr, overload -altsep: str -if sys.version_info < (3, 7) and sys.platform == "win32": +if sys.version_info >= (3, 7) or sys.platform != "win32": + __all__ = [ + "normcase", + "isabs", + "join", + "splitdrive", + "split", + "splitext", + "basename", + "dirname", + "commonprefix", + "getsize", + "getmtime", + "getatime", + "getctime", + "islink", + "exists", + "lexists", + "isdir", + "isfile", + "ismount", + "expanduser", + "expandvars", + "normpath", + "abspath", + "curdir", + "pardir", + "sep", + "pathsep", + "defpath", + "altsep", + "extsep", + "devnull", + "realpath", + "supports_unicode_filenames", + "relpath", + "samefile", + "sameopenfile", + "samestat", + "commonpath", + ] +else: + __all__ = [ + "normcase", + "isabs", + "join", + "splitdrive", + "split", + "splitext", + "basename", + "dirname", + "commonprefix", + "getsize", + "getmtime", + "getatime", + "getctime", + "islink", + "exists", + "lexists", + "isdir", + "isfile", + "ismount", + "expanduser", + "expandvars", + "normpath", + "abspath", + "splitunc", + "curdir", + "pardir", + "sep", + "pathsep", + "defpath", + "altsep", + "extsep", + "devnull", + "realpath", + "supports_unicode_filenames", + "relpath", + "samefile", + "sameopenfile", + "samestat", + "commonpath", + ] + def splitunc(p: AnyStr) -> tuple[AnyStr, AnyStr]: ... # deprecated +altsep: str + # First parameter is not actually pos-only, # but must be defined as pos-only in the stub or cross-platform code doesn't type-check, # as the parameter name is different in posixpath.join() diff --git a/mypy/typeshed/stdlib/numbers.pyi b/mypy/typeshed/stdlib/numbers.pyi index eaf53d25347ac..d94ae7faf8906 100644 --- a/mypy/typeshed/stdlib/numbers.pyi +++ b/mypy/typeshed/stdlib/numbers.pyi @@ -4,6 +4,8 @@ from abc import ABCMeta, abstractmethod from typing import Any, SupportsFloat, overload +__all__ = ["Number", "Complex", "Real", "Rational", "Integral"] + class Number(metaclass=ABCMeta): @abstractmethod def __hash__(self) -> int: ... @@ -40,9 +42,12 @@ class Complex(Number): def __pow__(self, exponent: Any) -> Any: ... @abstractmethod def __rpow__(self, base: Any) -> Any: ... + @abstractmethod def __abs__(self) -> Real: ... + @abstractmethod def conjugate(self) -> Any: ... - def __eq__(self, other: Any) -> bool: ... + @abstractmethod + def __eq__(self, other: object) -> bool: ... class Real(Complex, SupportsFloat): @abstractmethod diff --git a/mypy/typeshed/stdlib/opcode.pyi b/mypy/typeshed/stdlib/opcode.pyi index 982ddee43a630..402dbb74cf580 100644 --- a/mypy/typeshed/stdlib/opcode.pyi +++ b/mypy/typeshed/stdlib/opcode.pyi @@ -1,7 +1,40 @@ import sys -from typing import Sequence +from typing_extensions import Literal -cmp_op: Sequence[str] +__all__ = [ + "cmp_op", + "hasconst", + "hasname", + "hasjrel", + "hasjabs", + "haslocal", + "hascompare", + "hasfree", + "opname", + "opmap", + "HAVE_ARGUMENT", + "EXTENDED_ARG", + "hasnargs", + "stack_effect", +] + +if sys.version_info >= (3, 9): + cmp_op: tuple[Literal["<"], Literal["<="], Literal["=="], Literal["!="], Literal[">"], Literal[">="]] +else: + cmp_op: tuple[ + Literal["<"], + Literal["<="], + Literal["=="], + Literal["!="], + Literal[">"], + Literal[">="], + Literal["in"], + Literal["not in"], + Literal["is"], + Literal["is not"], + Literal["exception match"], + Literal["BAD"], + ] hasconst: list[int] hasname: list[int] hasjrel: list[int] @@ -12,8 +45,8 @@ hasfree: list[int] opname: list[str] opmap: dict[str, int] -HAVE_ARGUMENT: int -EXTENDED_ARG: int +HAVE_ARGUMENT: Literal[90] +EXTENDED_ARG: Literal[144] if sys.version_info >= (3, 8): def stack_effect(__opcode: int, __oparg: int | None = ..., *, jump: bool | None = ...) -> int: ... diff --git a/mypy/typeshed/stdlib/operator.pyi b/mypy/typeshed/stdlib/operator.pyi index 180bd161c0457..603e15ebc7bec 100644 --- a/mypy/typeshed/stdlib/operator.pyi +++ b/mypy/typeshed/stdlib/operator.pyi @@ -2,6 +2,122 @@ import sys from _operator import * +if sys.version_info >= (3, 11): + __all__ = [ + "abs", + "add", + "and_", + "attrgetter", + "call", + "concat", + "contains", + "countOf", + "delitem", + "eq", + "floordiv", + "ge", + "getitem", + "gt", + "iadd", + "iand", + "iconcat", + "ifloordiv", + "ilshift", + "imatmul", + "imod", + "imul", + "index", + "indexOf", + "inv", + "invert", + "ior", + "ipow", + "irshift", + "is_", + "is_not", + "isub", + "itemgetter", + "itruediv", + "ixor", + "le", + "length_hint", + "lshift", + "lt", + "matmul", + "methodcaller", + "mod", + "mul", + "ne", + "neg", + "not_", + "or_", + "pos", + "pow", + "rshift", + "setitem", + "sub", + "truediv", + "truth", + "xor", + ] +else: + __all__ = [ + "abs", + "add", + "and_", + "attrgetter", + "concat", + "contains", + "countOf", + "delitem", + "eq", + "floordiv", + "ge", + "getitem", + "gt", + "iadd", + "iand", + "iconcat", + "ifloordiv", + "ilshift", + "imatmul", + "imod", + "imul", + "index", + "indexOf", + "inv", + "invert", + "ior", + "ipow", + "irshift", + "is_", + "is_not", + "isub", + "itemgetter", + "itruediv", + "ixor", + "le", + "length_hint", + "lshift", + "lt", + "matmul", + "methodcaller", + "mod", + "mul", + "ne", + "neg", + "not_", + "or_", + "pos", + "pow", + "rshift", + "setitem", + "sub", + "truediv", + "truth", + "xor", + ] + __lt__ = lt __le__ = le __eq__ = eq diff --git a/mypy/typeshed/stdlib/optparse.pyi b/mypy/typeshed/stdlib/optparse.pyi index 416bc5446cc5e..7aedf583e556f 100644 --- a/mypy/typeshed/stdlib/optparse.pyi +++ b/mypy/typeshed/stdlib/optparse.pyi @@ -1,11 +1,32 @@ -from typing import IO, Any, AnyStr, Callable, Iterable, Mapping, Sequence, Type, overload +from abc import abstractmethod +from typing import IO, Any, AnyStr, Callable, Iterable, Mapping, Sequence, overload + +__all__ = [ + "Option", + "make_option", + "SUPPRESS_HELP", + "SUPPRESS_USAGE", + "Values", + "OptionContainer", + "OptionGroup", + "OptionParser", + "HelpFormatter", + "IndentedHelpFormatter", + "TitledHelpFormatter", + "OptParseError", + "OptionError", + "OptionConflictError", + "OptionValueError", + "BadOptionError", + "check_choice", +] NO_DEFAULT: tuple[str, ...] SUPPRESS_HELP: str SUPPRESS_USAGE: str def check_builtin(option: Option, opt: Any, value: str) -> Any: ... -def check_choice(option: Option, opt: Any, value: str) -> Any: ... +def check_choice(option: Option, opt: Any, value: str) -> str: ... class OptParseError(Exception): msg: str @@ -47,9 +68,11 @@ class HelpFormatter: def expand_default(self, option: Option) -> str: ... def format_description(self, description: str) -> str: ... def format_epilog(self, epilog: str) -> str: ... + @abstractmethod def format_heading(self, heading: Any) -> str: ... def format_option(self, option: Option) -> str: ... def format_option_strings(self, option: Option) -> str: ... + @abstractmethod def format_usage(self, usage: Any) -> str: ... def indent(self) -> None: ... def set_long_opt_delimiter(self, delim: str) -> None: ... @@ -119,8 +142,8 @@ class OptionContainer: conflict_handler: str defaults: dict[str, Any] description: Any - option_class: Type[Option] - def __init__(self, option_class: Type[Option], conflict_handler: Any, description: Any) -> None: ... + option_class: type[Option] + def __init__(self, option_class: type[Option], conflict_handler: Any, description: Any) -> None: ... def _check_conflict(self, option: Any) -> None: ... def _create_option_mappings(self) -> None: ... def _share_option_mappings(self, parser: OptionParser) -> None: ... @@ -157,7 +180,8 @@ class Values: def read_file(self, filename: str, mode: str = ...) -> None: ... def read_module(self, modname: str, mode: str = ...) -> None: ... def __getattr__(self, name: str) -> Any: ... - def __setattr__(self, name: str, value: Any) -> None: ... + def __setattr__(self, __name: str, __value: Any) -> None: ... + def __eq__(self, other: object) -> bool: ... class OptionParser(OptionContainer): allow_interspersed_args: bool @@ -177,7 +201,7 @@ class OptionParser(OptionContainer): self, usage: str | None = ..., option_list: Iterable[Option] | None = ..., - option_class: Type[Option] = ..., + option_class: type[Option] = ..., version: str | None = ..., conflict_handler: str = ..., description: str | None = ..., diff --git a/mypy/typeshed/stdlib/os/__init__.pyi b/mypy/typeshed/stdlib/os/__init__.pyi index 5308416adff42..2ef781bbe2886 100644 --- a/mypy/typeshed/stdlib/os/__init__.pyi +++ b/mypy/typeshed/stdlib/os/__init__.pyi @@ -1,5 +1,6 @@ import sys from _typeshed import ( + BytesPath, FileDescriptorLike, OpenBinaryMode, OpenBinaryModeReading, @@ -11,6 +12,7 @@ from _typeshed import ( StrPath, structseq, ) +from abc import abstractmethod from builtins import OSError from contextlib import AbstractContextManager from io import BufferedRandom, BufferedReader, BufferedWriter, FileIO, TextIOWrapper as _TextIOWrapper @@ -30,11 +32,10 @@ from typing import ( Protocol, Sequence, TypeVar, - Union, overload, runtime_checkable, ) -from typing_extensions import Literal, final +from typing_extensions import Final, Literal, final from . import path as _path @@ -45,6 +46,8 @@ if sys.version_info >= (3, 9): path = _path _T = TypeVar("_T") +_T1 = TypeVar("_T1") +_T2 = TypeVar("_T2") _AnyStr_co = TypeVar("_AnyStr_co", str, bytes, covariant=True) # ----- os variables ----- @@ -237,6 +240,7 @@ class _Environ(MutableMapping[AnyStr, AnyStr], Generic[AnyStr]): putenv: Callable[[AnyStr, AnyStr], None], unsetenv: Callable[[AnyStr, AnyStr], None], ) -> None: ... + def setdefault(self, key: AnyStr, value: AnyStr) -> AnyStr: ... # type: ignore[override] def copy(self) -> dict[AnyStr, AnyStr]: ... def __delitem__(self, key: AnyStr) -> None: ... @@ -244,6 +248,16 @@ class _Environ(MutableMapping[AnyStr, AnyStr], Generic[AnyStr]): def __setitem__(self, key: AnyStr, value: AnyStr) -> None: ... def __iter__(self) -> Iterator[AnyStr]: ... def __len__(self) -> int: ... + if sys.version_info >= (3, 9): + def __or__(self, other: Mapping[_T1, _T2]) -> dict[AnyStr | _T1, AnyStr | _T2]: ... + def __ror__(self, other: Mapping[_T1, _T2]) -> dict[AnyStr | _T1, AnyStr | _T2]: ... + # We use @overload instead of a Union for reasons similar to those given for + # overloading MutableMapping.update in stdlib/typing.pyi + # The type: ignore is needed due to incompatible __or__/__ior__ signatures + @overload # type: ignore[misc] + def __ior__(self: Self, other: Mapping[AnyStr, AnyStr]) -> Self: ... + @overload + def __ior__(self: Self, other: Iterable[tuple[AnyStr, AnyStr]]) -> Self: ... environ: _Environ[str] if sys.platform != "win32": @@ -300,6 +314,8 @@ class stat_result(structseq[float], tuple[int, int, int, int, int, int, int, flo # st_uid, st_gid, st_size, st_atime, st_mtime, st_ctime. # # More items may be added at the end by some implementations. + if sys.version_info >= (3, 10): + __match_args__: Final = ("st_mode", "st_ino", "st_dev", "st_nlink", "st_uid", "st_gid", "st_size") @property def st_mode(self) -> int: ... # protection bits, @property @@ -352,31 +368,32 @@ class stat_result(structseq[float], tuple[int, int, int, int, int, int, int, flo if sys.platform == "darwin": @property def st_flags(self) -> int: ... # user defined flags for file - # Atributes documented as sometimes appearing, but deliberately omitted from the stub: `st_creator`, `st_rsize`, `st_type`. + # Attributes documented as sometimes appearing, but deliberately omitted from the stub: `st_creator`, `st_rsize`, `st_type`. # See https://github.com/python/typeshed/pull/6560#issuecomment-991253327 @runtime_checkable class PathLike(Protocol[_AnyStr_co]): + @abstractmethod def __fspath__(self) -> _AnyStr_co: ... @overload -def listdir(path: str | None = ...) -> list[str]: ... +def listdir(path: StrPath | None = ...) -> list[str]: ... @overload -def listdir(path: bytes) -> list[bytes]: ... +def listdir(path: BytesPath) -> list[bytes]: ... @overload def listdir(path: int) -> list[str]: ... -@overload -def listdir(path: PathLike[str]) -> list[str]: ... -_FdOrAnyPath = Union[int, StrOrBytesPath] +_FdOrAnyPath = int | StrOrBytesPath @final class DirEntry(Generic[AnyStr]): # This is what the scandir iterator yields # The constructor is hidden - name: AnyStr - path: AnyStr + @property + def name(self) -> AnyStr: ... + @property + def path(self) -> AnyStr: ... def inode(self) -> int: ... def is_dir(self, *, follow_symlinks: bool = ...) -> bool: ... def is_file(self, *, follow_symlinks: bool = ...) -> bool: ... @@ -387,54 +404,48 @@ class DirEntry(Generic[AnyStr]): def __class_getitem__(cls, item: Any) -> GenericAlias: ... if sys.version_info >= (3, 7): - @final - class statvfs_result(structseq[int], tuple[int, int, int, int, int, int, int, int, int, int, int]): - @property - def f_bsize(self) -> int: ... - @property - def f_frsize(self) -> int: ... - @property - def f_blocks(self) -> int: ... - @property - def f_bfree(self) -> int: ... - @property - def f_bavail(self) -> int: ... - @property - def f_files(self) -> int: ... - @property - def f_ffree(self) -> int: ... - @property - def f_favail(self) -> int: ... - @property - def f_flag(self) -> int: ... - @property - def f_namemax(self) -> int: ... - @property - def f_fsid(self) -> int: ... - + _StatVfsTuple = tuple[int, int, int, int, int, int, int, int, int, int, int] else: - @final - class statvfs_result(structseq[int], tuple[int, int, int, int, int, int, int, int, int, int]): - @property - def f_bsize(self) -> int: ... - @property - def f_frsize(self) -> int: ... - @property - def f_blocks(self) -> int: ... - @property - def f_bfree(self) -> int: ... - @property - def f_bavail(self) -> int: ... - @property - def f_files(self) -> int: ... - @property - def f_ffree(self) -> int: ... - @property - def f_favail(self) -> int: ... - @property - def f_flag(self) -> int: ... + _StatVfsTuple = tuple[int, int, int, int, int, int, int, int, int, int] + +@final +class statvfs_result(structseq[int], _StatVfsTuple): + if sys.version_info >= (3, 10): + __match_args__: Final = ( + "f_bsize", + "f_frsize", + "f_blocks", + "f_bfree", + "f_bavail", + "f_files", + "f_ffree", + "f_favail", + "f_flag", + "f_namemax", + ) + @property + def f_bsize(self) -> int: ... + @property + def f_frsize(self) -> int: ... + @property + def f_blocks(self) -> int: ... + @property + def f_bfree(self) -> int: ... + @property + def f_bavail(self) -> int: ... + @property + def f_files(self) -> int: ... + @property + def f_ffree(self) -> int: ... + @property + def f_favail(self) -> int: ... + @property + def f_flag(self) -> int: ... + @property + def f_namemax(self) -> int: ... + if sys.version_info >= (3, 7): @property - def f_namemax(self) -> int: ... + def f_fsid(self) -> int: ... # ----- os function stubs ----- def fsencode(filename: StrOrBytesPath) -> bytes: ... @@ -453,6 +464,8 @@ def strerror(__code: int) -> str: ... def umask(__mask: int) -> int: ... @final class uname_result(structseq[str], tuple[str, str, str, str, str]): + if sys.version_info >= (3, 10): + __match_args__: Final = ("sysname", "nodename", "release", "version", "machine") @property def sysname(self) -> str: ... @property @@ -479,6 +492,7 @@ if sys.platform != "win32": if sys.platform != "darwin": def getresuid() -> tuple[int, int, int]: ... def getresgid() -> tuple[int, int, int]: ... + def getuid() -> int: ... def setegid(__egid: int) -> None: ... def seteuid(__euid: int) -> None: ... @@ -490,6 +504,7 @@ if sys.platform != "win32": if sys.platform != "darwin": def setresgid(rgid: int, egid: int, sgid: int) -> None: ... def setresuid(ruid: int, euid: int, suid: int) -> None: ... + def setreuid(__ruid: int, __euid: int) -> None: ... def getsid(__pid: int) -> int: ... def setsid() -> None: ... @@ -573,7 +588,7 @@ def fdopen( def fdopen( fd: int, mode: OpenBinaryMode, - buffering: int, + buffering: int = ..., encoding: None = ..., errors: None = ..., newline: None = ..., @@ -626,6 +641,7 @@ if sys.platform != "win32": def pipe2(__flags: int) -> tuple[int, int]: ... # some flavors of Unix def posix_fallocate(fd: int, offset: int, length: int) -> None: ... def posix_fadvise(fd: int, offset: int, length: int, advice: int) -> None: ... + def pread(__fd: int, __length: int, __offset: int) -> bytes: ... def pwrite(__fd: int, __buffer: bytes, __offset: int) -> int: ... if sys.platform != "darwin": @@ -655,6 +671,8 @@ if sys.platform != "win32": @final class terminal_size(structseq[int], tuple[int, int]): + if sys.version_info >= (3, 10): + __match_args__: Final = ("columns", "lines") @property def columns(self) -> int: ... @property @@ -664,6 +682,10 @@ def get_terminal_size(fd: int = ...) -> terminal_size: ... def get_inheritable(__fd: int) -> bool: ... def set_inheritable(__fd: int, __inheritable: bool) -> None: ... +if sys.platform == "win32": + def get_handle_inheritable(__handle: int) -> bool: ... + def set_handle_inheritable(__handle: int, __inheritable: bool) -> None: ... + if sys.platform != "win32": # Unix only def tcgetpgrp(__fd: int) -> int: ... @@ -726,22 +748,18 @@ def rmdir(path: StrOrBytesPath, *, dir_fd: int | None = ...) -> None: ... class _ScandirIterator(Iterator[DirEntry[AnyStr]], AbstractContextManager[_ScandirIterator[AnyStr]]): def __next__(self) -> DirEntry[AnyStr]: ... + def __exit__(self, *args: object) -> None: ... def close(self) -> None: ... +@overload +def scandir(path: None = ...) -> _ScandirIterator[str]: ... + if sys.version_info >= (3, 7): - @overload - def scandir(path: None = ...) -> _ScandirIterator[str]: ... @overload def scandir(path: int) -> _ScandirIterator[str]: ... - @overload - def scandir(path: AnyStr | PathLike[AnyStr]) -> _ScandirIterator[AnyStr]: ... - -else: - @overload - def scandir(path: None = ...) -> _ScandirIterator[str]: ... - @overload - def scandir(path: AnyStr | PathLike[AnyStr]) -> _ScandirIterator[AnyStr]: ... +@overload +def scandir(path: AnyStr | PathLike[AnyStr]) -> _ScandirIterator[AnyStr]: ... def stat(path: _FdOrAnyPath, *, dir_fd: int | None = ..., follow_symlinks: bool = ...) -> stat_result: ... if sys.version_info < (3, 7): @@ -827,17 +845,17 @@ def execlpe(file: StrOrBytesPath, __arg0: StrOrBytesPath, *args: Any) -> NoRetur # Not separating out PathLike[str] and PathLike[bytes] here because it doesn't make much difference # in practice, and doing so would explode the number of combinations in this already long union. # All these combinations are necessary due to list being invariant. -_ExecVArgs = Union[ - tuple[StrOrBytesPath, ...], - list[bytes], - list[str], - list[PathLike[Any]], - list[Union[bytes, str]], - list[Union[bytes, PathLike[Any]]], - list[Union[str, PathLike[Any]]], - list[Union[bytes, str, PathLike[Any]]], -] -_ExecEnv = Union[Mapping[bytes, Union[bytes, str]], Mapping[str, Union[bytes, str]]] +_ExecVArgs = ( + tuple[StrOrBytesPath, ...] + | list[bytes] + | list[str] + | list[PathLike[Any]] + | list[bytes | str] + | list[bytes | PathLike[Any]] + | list[str | PathLike[Any]] + | list[bytes | str | PathLike[Any]] +) +_ExecEnv = Mapping[bytes, bytes | str] | Mapping[str, bytes | str] def execv(__path: StrOrBytesPath, __argv: _ExecVArgs) -> NoReturn: ... def execve(path: _FdOrAnyPath, argv: _ExecVArgs, env: _ExecEnv) -> NoReturn: ... @@ -874,6 +892,8 @@ else: def system(command: StrOrBytesPath) -> int: ... @final class times_result(structseq[float], tuple[float, float, float, float, float]): + if sys.version_info >= (3, 10): + __match_args__: Final = ("user", "system", "children_user", "children_system", "elapsed") @property def user(self) -> float: ... @property @@ -900,6 +920,8 @@ else: if sys.platform != "darwin": @final class waitid_result(structseq[int], tuple[int, int, int, int, int]): + if sys.version_info >= (3, 10): + __match_args__: Final = ("si_pid", "si_uid", "si_signo", "si_status", "si_code") @property def si_pid(self) -> int: ... @property @@ -910,7 +932,9 @@ else: def si_status(self) -> int: ... @property def si_code(self) -> int: ... + def waitid(idtype: int, ident: int, options: int) -> waitid_result: ... + def wait3(options: int) -> tuple[int, int, Any]: ... def wait4(pid: int, options: int) -> tuple[int, int, Any]: ... def WCOREDUMP(__status: int) -> bool: ... @@ -955,9 +979,12 @@ else: if sys.platform != "win32": @final class sched_param(structseq[int], tuple[int]): - def __new__(cls, sched_priority: int) -> sched_param: ... + if sys.version_info >= (3, 10): + __match_args__: Final = ("sched_priority",) + def __new__(cls: type[Self], sched_priority: int) -> Self: ... @property def sched_priority(self) -> int: ... + def sched_get_priority_min(policy: int) -> int: ... # some flavors of Unix def sched_get_priority_max(policy: int) -> int: ... # some flavors of Unix def sched_yield() -> None: ... # some flavors of Unix @@ -998,7 +1025,8 @@ if sys.version_info >= (3, 8): def __init__(self, path: str | None, cookie: _T, remove_dll_directory: Callable[[_T], Any]) -> None: ... def close(self) -> None: ... def __enter__(self: Self) -> Self: ... - def __exit__(self, *args: Any) -> None: ... + def __exit__(self, *args: object) -> None: ... + def add_dll_directory(path: str) -> _AddedDllDirectory: ... if sys.platform == "linux": MFD_CLOEXEC: int @@ -1019,6 +1047,12 @@ if sys.version_info >= (3, 8): MFD_HUGE_2GB: int MFD_HUGE_16GB: int def memfd_create(name: str, flags: int = ...) -> int: ... + def copy_file_range( + src: int, dst: int, count: int, offset_src: int | None = ..., offset_dst: int | None = ... + ) -> int: ... if sys.version_info >= (3, 9): def waitstatus_to_exitcode(status: int) -> int: ... + + if sys.platform == "linux": + def pidfd_open(pid: int, flags: int = ...) -> int: ... diff --git a/mypy/typeshed/stdlib/os/path.pyi b/mypy/typeshed/stdlib/os/path.pyi index 4533738983f7a..dc688a9f877f0 100644 --- a/mypy/typeshed/stdlib/os/path.pyi +++ b/mypy/typeshed/stdlib/os/path.pyi @@ -2,5 +2,7 @@ import sys if sys.platform == "win32": from ntpath import * + from ntpath import __all__ as __all__ else: from posixpath import * + from posixpath import __all__ as __all__ diff --git a/mypy/typeshed/stdlib/ossaudiodev.pyi b/mypy/typeshed/stdlib/ossaudiodev.pyi index f221c95b8036b..d956a89729fd1 100644 --- a/mypy/typeshed/stdlib/ossaudiodev.pyi +++ b/mypy/typeshed/stdlib/ossaudiodev.pyi @@ -1,131 +1,132 @@ +import sys from typing import Any, overload from typing_extensions import Literal -AFMT_AC3: int -AFMT_A_LAW: int -AFMT_IMA_ADPCM: int -AFMT_MPEG: int -AFMT_MU_LAW: int -AFMT_QUERY: int -AFMT_S16_BE: int -AFMT_S16_LE: int -AFMT_S16_NE: int -AFMT_S8: int -AFMT_U16_BE: int -AFMT_U16_LE: int -AFMT_U8: int -SNDCTL_COPR_HALT: int -SNDCTL_COPR_LOAD: int -SNDCTL_COPR_RCODE: int -SNDCTL_COPR_RCVMSG: int -SNDCTL_COPR_RDATA: int -SNDCTL_COPR_RESET: int -SNDCTL_COPR_RUN: int -SNDCTL_COPR_SENDMSG: int -SNDCTL_COPR_WCODE: int -SNDCTL_COPR_WDATA: int -SNDCTL_DSP_BIND_CHANNEL: int -SNDCTL_DSP_CHANNELS: int -SNDCTL_DSP_GETBLKSIZE: int -SNDCTL_DSP_GETCAPS: int -SNDCTL_DSP_GETCHANNELMASK: int -SNDCTL_DSP_GETFMTS: int -SNDCTL_DSP_GETIPTR: int -SNDCTL_DSP_GETISPACE: int -SNDCTL_DSP_GETODELAY: int -SNDCTL_DSP_GETOPTR: int -SNDCTL_DSP_GETOSPACE: int -SNDCTL_DSP_GETSPDIF: int -SNDCTL_DSP_GETTRIGGER: int -SNDCTL_DSP_MAPINBUF: int -SNDCTL_DSP_MAPOUTBUF: int -SNDCTL_DSP_NONBLOCK: int -SNDCTL_DSP_POST: int -SNDCTL_DSP_PROFILE: int -SNDCTL_DSP_RESET: int -SNDCTL_DSP_SAMPLESIZE: int -SNDCTL_DSP_SETDUPLEX: int -SNDCTL_DSP_SETFMT: int -SNDCTL_DSP_SETFRAGMENT: int -SNDCTL_DSP_SETSPDIF: int -SNDCTL_DSP_SETSYNCRO: int -SNDCTL_DSP_SETTRIGGER: int -SNDCTL_DSP_SPEED: int -SNDCTL_DSP_STEREO: int -SNDCTL_DSP_SUBDIVIDE: int -SNDCTL_DSP_SYNC: int -SNDCTL_FM_4OP_ENABLE: int -SNDCTL_FM_LOAD_INSTR: int -SNDCTL_MIDI_INFO: int -SNDCTL_MIDI_MPUCMD: int -SNDCTL_MIDI_MPUMODE: int -SNDCTL_MIDI_PRETIME: int -SNDCTL_SEQ_CTRLRATE: int -SNDCTL_SEQ_GETINCOUNT: int -SNDCTL_SEQ_GETOUTCOUNT: int -SNDCTL_SEQ_GETTIME: int -SNDCTL_SEQ_NRMIDIS: int -SNDCTL_SEQ_NRSYNTHS: int -SNDCTL_SEQ_OUTOFBAND: int -SNDCTL_SEQ_PANIC: int -SNDCTL_SEQ_PERCMODE: int -SNDCTL_SEQ_RESET: int -SNDCTL_SEQ_RESETSAMPLES: int -SNDCTL_SEQ_SYNC: int -SNDCTL_SEQ_TESTMIDI: int -SNDCTL_SEQ_THRESHOLD: int -SNDCTL_SYNTH_CONTROL: int -SNDCTL_SYNTH_ID: int -SNDCTL_SYNTH_INFO: int -SNDCTL_SYNTH_MEMAVL: int -SNDCTL_SYNTH_REMOVESAMPLE: int -SNDCTL_TMR_CONTINUE: int -SNDCTL_TMR_METRONOME: int -SNDCTL_TMR_SELECT: int -SNDCTL_TMR_SOURCE: int -SNDCTL_TMR_START: int -SNDCTL_TMR_STOP: int -SNDCTL_TMR_TEMPO: int -SNDCTL_TMR_TIMEBASE: int -SOUND_MIXER_ALTPCM: int -SOUND_MIXER_BASS: int -SOUND_MIXER_CD: int -SOUND_MIXER_DIGITAL1: int -SOUND_MIXER_DIGITAL2: int -SOUND_MIXER_DIGITAL3: int -SOUND_MIXER_IGAIN: int -SOUND_MIXER_IMIX: int -SOUND_MIXER_LINE: int -SOUND_MIXER_LINE1: int -SOUND_MIXER_LINE2: int -SOUND_MIXER_LINE3: int -SOUND_MIXER_MIC: int -SOUND_MIXER_MONITOR: int -SOUND_MIXER_NRDEVICES: int -SOUND_MIXER_OGAIN: int -SOUND_MIXER_PCM: int -SOUND_MIXER_PHONEIN: int -SOUND_MIXER_PHONEOUT: int -SOUND_MIXER_RADIO: int -SOUND_MIXER_RECLEV: int -SOUND_MIXER_SPEAKER: int -SOUND_MIXER_SYNTH: int -SOUND_MIXER_TREBLE: int -SOUND_MIXER_VIDEO: int -SOUND_MIXER_VOLUME: int +if sys.platform != "win32" and sys.platform != "darwin": + AFMT_AC3: int + AFMT_A_LAW: int + AFMT_IMA_ADPCM: int + AFMT_MPEG: int + AFMT_MU_LAW: int + AFMT_QUERY: int + AFMT_S16_BE: int + AFMT_S16_LE: int + AFMT_S16_NE: int + AFMT_S8: int + AFMT_U16_BE: int + AFMT_U16_LE: int + AFMT_U8: int + SNDCTL_COPR_HALT: int + SNDCTL_COPR_LOAD: int + SNDCTL_COPR_RCODE: int + SNDCTL_COPR_RCVMSG: int + SNDCTL_COPR_RDATA: int + SNDCTL_COPR_RESET: int + SNDCTL_COPR_RUN: int + SNDCTL_COPR_SENDMSG: int + SNDCTL_COPR_WCODE: int + SNDCTL_COPR_WDATA: int + SNDCTL_DSP_BIND_CHANNEL: int + SNDCTL_DSP_CHANNELS: int + SNDCTL_DSP_GETBLKSIZE: int + SNDCTL_DSP_GETCAPS: int + SNDCTL_DSP_GETCHANNELMASK: int + SNDCTL_DSP_GETFMTS: int + SNDCTL_DSP_GETIPTR: int + SNDCTL_DSP_GETISPACE: int + SNDCTL_DSP_GETODELAY: int + SNDCTL_DSP_GETOPTR: int + SNDCTL_DSP_GETOSPACE: int + SNDCTL_DSP_GETSPDIF: int + SNDCTL_DSP_GETTRIGGER: int + SNDCTL_DSP_MAPINBUF: int + SNDCTL_DSP_MAPOUTBUF: int + SNDCTL_DSP_NONBLOCK: int + SNDCTL_DSP_POST: int + SNDCTL_DSP_PROFILE: int + SNDCTL_DSP_RESET: int + SNDCTL_DSP_SAMPLESIZE: int + SNDCTL_DSP_SETDUPLEX: int + SNDCTL_DSP_SETFMT: int + SNDCTL_DSP_SETFRAGMENT: int + SNDCTL_DSP_SETSPDIF: int + SNDCTL_DSP_SETSYNCRO: int + SNDCTL_DSP_SETTRIGGER: int + SNDCTL_DSP_SPEED: int + SNDCTL_DSP_STEREO: int + SNDCTL_DSP_SUBDIVIDE: int + SNDCTL_DSP_SYNC: int + SNDCTL_FM_4OP_ENABLE: int + SNDCTL_FM_LOAD_INSTR: int + SNDCTL_MIDI_INFO: int + SNDCTL_MIDI_MPUCMD: int + SNDCTL_MIDI_MPUMODE: int + SNDCTL_MIDI_PRETIME: int + SNDCTL_SEQ_CTRLRATE: int + SNDCTL_SEQ_GETINCOUNT: int + SNDCTL_SEQ_GETOUTCOUNT: int + SNDCTL_SEQ_GETTIME: int + SNDCTL_SEQ_NRMIDIS: int + SNDCTL_SEQ_NRSYNTHS: int + SNDCTL_SEQ_OUTOFBAND: int + SNDCTL_SEQ_PANIC: int + SNDCTL_SEQ_PERCMODE: int + SNDCTL_SEQ_RESET: int + SNDCTL_SEQ_RESETSAMPLES: int + SNDCTL_SEQ_SYNC: int + SNDCTL_SEQ_TESTMIDI: int + SNDCTL_SEQ_THRESHOLD: int + SNDCTL_SYNTH_CONTROL: int + SNDCTL_SYNTH_ID: int + SNDCTL_SYNTH_INFO: int + SNDCTL_SYNTH_MEMAVL: int + SNDCTL_SYNTH_REMOVESAMPLE: int + SNDCTL_TMR_CONTINUE: int + SNDCTL_TMR_METRONOME: int + SNDCTL_TMR_SELECT: int + SNDCTL_TMR_SOURCE: int + SNDCTL_TMR_START: int + SNDCTL_TMR_STOP: int + SNDCTL_TMR_TEMPO: int + SNDCTL_TMR_TIMEBASE: int + SOUND_MIXER_ALTPCM: int + SOUND_MIXER_BASS: int + SOUND_MIXER_CD: int + SOUND_MIXER_DIGITAL1: int + SOUND_MIXER_DIGITAL2: int + SOUND_MIXER_DIGITAL3: int + SOUND_MIXER_IGAIN: int + SOUND_MIXER_IMIX: int + SOUND_MIXER_LINE: int + SOUND_MIXER_LINE1: int + SOUND_MIXER_LINE2: int + SOUND_MIXER_LINE3: int + SOUND_MIXER_MIC: int + SOUND_MIXER_MONITOR: int + SOUND_MIXER_NRDEVICES: int + SOUND_MIXER_OGAIN: int + SOUND_MIXER_PCM: int + SOUND_MIXER_PHONEIN: int + SOUND_MIXER_PHONEOUT: int + SOUND_MIXER_RADIO: int + SOUND_MIXER_RECLEV: int + SOUND_MIXER_SPEAKER: int + SOUND_MIXER_SYNTH: int + SOUND_MIXER_TREBLE: int + SOUND_MIXER_VIDEO: int + SOUND_MIXER_VOLUME: int -control_labels: list[str] -control_names: list[str] + control_labels: list[str] + control_names: list[str] -# TODO: oss_audio_device return type -@overload -def open(mode: Literal["r", "w", "rw"]) -> Any: ... -@overload -def open(device: str, mode: Literal["r", "w", "rw"]) -> Any: ... + # TODO: oss_audio_device return type + @overload + def open(mode: Literal["r", "w", "rw"]) -> Any: ... + @overload + def open(device: str, mode: Literal["r", "w", "rw"]) -> Any: ... -# TODO: oss_mixer_device return type -def openmixer(device: str = ...) -> Any: ... + # TODO: oss_mixer_device return type + def openmixer(device: str = ...) -> Any: ... -class OSSAudioError(Exception): ... - -error = OSSAudioError + class OSSAudioError(Exception): ... + error = OSSAudioError diff --git a/mypy/typeshed/stdlib/parser.pyi b/mypy/typeshed/stdlib/parser.pyi index ab819a71a15f8..95e770b572568 100644 --- a/mypy/typeshed/stdlib/parser.pyi +++ b/mypy/typeshed/stdlib/parser.pyi @@ -1,6 +1,7 @@ from _typeshed import StrOrBytesPath from types import CodeType from typing import Any, Sequence +from typing_extensions import final def expr(source: str) -> STType: ... def suite(source: str) -> STType: ... @@ -14,6 +15,7 @@ def issuite(st: STType) -> bool: ... class ParserError(Exception): ... +@final class STType: def compile(self, filename: StrOrBytesPath = ...) -> CodeType: ... def isexpr(self) -> bool: ... diff --git a/mypy/typeshed/stdlib/pathlib.pyi b/mypy/typeshed/stdlib/pathlib.pyi index b541345c06d4c..45917ce59f8f1 100644 --- a/mypy/typeshed/stdlib/pathlib.pyi +++ b/mypy/typeshed/stdlib/pathlib.pyi @@ -11,31 +11,41 @@ from _typeshed import ( from io import BufferedRandom, BufferedReader, BufferedWriter, FileIO, TextIOWrapper from os import PathLike, stat_result from types import TracebackType -from typing import IO, Any, BinaryIO, Generator, Sequence, Type, TypeVar, overload +from typing import IO, Any, BinaryIO, Generator, Sequence, overload from typing_extensions import Literal if sys.version_info >= (3, 9): from types import GenericAlias -_P = TypeVar("_P", bound=PurePath) +__all__ = ["PurePath", "PurePosixPath", "PureWindowsPath", "Path", "PosixPath", "WindowsPath"] class PurePath(PathLike[str]): - parts: tuple[str, ...] - drive: str - root: str - anchor: str - name: str - suffix: str - suffixes: list[str] - stem: str - def __new__(cls: Type[_P], *args: StrPath) -> _P: ... + @property + def parts(self) -> tuple[str, ...]: ... + @property + def drive(self) -> str: ... + @property + def root(self) -> str: ... + @property + def anchor(self) -> str: ... + @property + def name(self) -> str: ... + @property + def suffix(self) -> str: ... + @property + def suffixes(self) -> list[str]: ... + @property + def stem(self) -> str: ... + def __new__(cls: type[Self], *args: StrPath) -> Self: ... def __hash__(self) -> int: ... + def __eq__(self, other: object) -> bool: ... + def __fspath__(self) -> str: ... def __lt__(self, other: PurePath) -> bool: ... def __le__(self, other: PurePath) -> bool: ... def __gt__(self, other: PurePath) -> bool: ... def __ge__(self, other: PurePath) -> bool: ... - def __truediv__(self: _P, key: StrPath) -> _P: ... - def __rtruediv__(self: _P, key: StrPath) -> _P: ... + def __truediv__(self: Self, key: StrPath) -> Self: ... + def __rtruediv__(self: Self, key: StrPath) -> Self: ... def __bytes__(self) -> bytes: ... def as_posix(self) -> str: ... def as_uri(self) -> str: ... @@ -43,50 +53,48 @@ class PurePath(PathLike[str]): def is_reserved(self) -> bool: ... if sys.version_info >= (3, 9): def is_relative_to(self, *other: StrPath) -> bool: ... + def match(self, path_pattern: str) -> bool: ... - def relative_to(self: _P, *other: StrPath) -> _P: ... - def with_name(self: _P, name: str) -> _P: ... + def relative_to(self: Self, *other: StrPath) -> Self: ... + def with_name(self: Self, name: str) -> Self: ... if sys.version_info >= (3, 9): - def with_stem(self: _P, stem: str) -> _P: ... - def with_suffix(self: _P, suffix: str) -> _P: ... - def joinpath(self: _P, *other: StrPath) -> _P: ... + def with_stem(self: Self, stem: str) -> Self: ... + + def with_suffix(self: Self, suffix: str) -> Self: ... + def joinpath(self: Self, *other: StrPath) -> Self: ... @property - def parents(self: _P) -> Sequence[_P]: ... + def parents(self: Self) -> Sequence[Self]: ... @property - def parent(self: _P) -> _P: ... - if sys.version_info >= (3, 9): + def parent(self: Self) -> Self: ... + if sys.version_info >= (3, 9) and sys.version_info < (3, 11): def __class_getitem__(cls, type: Any) -> GenericAlias: ... class PurePosixPath(PurePath): ... class PureWindowsPath(PurePath): ... class Path(PurePath): - def __new__(cls: Type[_P], *args: StrPath, **kwargs: Any) -> _P: ... + def __new__(cls: type[Self], *args: StrPath, **kwargs: Any) -> Self: ... def __enter__(self: Self) -> Self: ... - def __exit__( - self, exc_type: Type[BaseException] | None, exc_value: BaseException | None, traceback: TracebackType | None - ) -> bool | None: ... + def __exit__(self, t: type[BaseException] | None, v: BaseException | None, tb: TracebackType | None) -> None: ... @classmethod - def cwd(cls: Type[_P]) -> _P: ... + def cwd(cls: type[Self]) -> Self: ... if sys.version_info >= (3, 10): def stat(self, *, follow_symlinks: bool = ...) -> stat_result: ... def chmod(self, mode: int, *, follow_symlinks: bool = ...) -> None: ... else: def stat(self) -> stat_result: ... def chmod(self, mode: int) -> None: ... + def exists(self) -> bool: ... - def glob(self: _P, pattern: str) -> Generator[_P, None, None]: ... - def group(self) -> str: ... + def glob(self: Self, pattern: str) -> Generator[Self, None, None]: ... def is_dir(self) -> bool: ... def is_file(self) -> bool: ... - if sys.version_info >= (3, 7): - def is_mount(self) -> bool: ... def is_symlink(self) -> bool: ... def is_socket(self) -> bool: ... def is_fifo(self) -> bool: ... def is_block_device(self) -> bool: ... def is_char_device(self) -> bool: ... - def iterdir(self: _P) -> Generator[_P, None, None]: ... + def iterdir(self: Self) -> Generator[Self, None, None]: ... def lchmod(self, mode: int) -> None: ... def lstat(self) -> stat_result: ... def mkdir(self, mode: int = ..., parents: bool = ..., exist_ok: bool = ...) -> None: ... @@ -138,37 +146,47 @@ class Path(PurePath): # Buffering cannot be determined: fall back to BinaryIO @overload def open( - self, mode: OpenBinaryMode, buffering: int, encoding: None = ..., errors: None = ..., newline: None = ... + self, mode: OpenBinaryMode, buffering: int = ..., encoding: None = ..., errors: None = ..., newline: None = ... ) -> BinaryIO: ... # Fallback if mode is not specified @overload def open( self, mode: str, buffering: int = ..., encoding: str | None = ..., errors: str | None = ..., newline: str | None = ... ) -> IO[Any]: ... - def owner(self) -> str: ... + if sys.platform != "win32": + # These methods do "exist" on Windows, but they always raise NotImplementedError, + # so it's safer to pretend they don't exist + def owner(self) -> str: ... + def group(self) -> str: ... + if sys.version_info >= (3, 7): + def is_mount(self) -> bool: ... + if sys.version_info >= (3, 9): - def readlink(self: _P) -> _P: ... + def readlink(self: Self) -> Self: ... if sys.version_info >= (3, 8): - def rename(self: _P, target: str | PurePath) -> _P: ... - def replace(self: _P, target: str | PurePath) -> _P: ... + def rename(self: Self, target: str | PurePath) -> Self: ... + def replace(self: Self, target: str | PurePath) -> Self: ... else: def rename(self, target: str | PurePath) -> None: ... def replace(self, target: str | PurePath) -> None: ... - def resolve(self: _P, strict: bool = ...) -> _P: ... - def rglob(self: _P, pattern: str) -> Generator[_P, None, None]: ... + + def resolve(self: Self, strict: bool = ...) -> Self: ... + def rglob(self: Self, pattern: str) -> Generator[Self, None, None]: ... def rmdir(self) -> None: ... def symlink_to(self, target: str | Path, target_is_directory: bool = ...) -> None: ... if sys.version_info >= (3, 10): def hardlink_to(self, target: str | Path) -> None: ... + def touch(self, mode: int = ..., exist_ok: bool = ...) -> None: ... if sys.version_info >= (3, 8): def unlink(self, missing_ok: bool = ...) -> None: ... else: def unlink(self) -> None: ... + @classmethod - def home(cls: Type[_P]) -> _P: ... - def absolute(self: _P) -> _P: ... - def expanduser(self: _P) -> _P: ... + def home(cls: type[Self]) -> Self: ... + def absolute(self: Self) -> Self: ... + def expanduser(self: Self) -> Self: ... def read_bytes(self) -> bytes: ... def read_text(self, encoding: str | None = ..., errors: str | None = ...) -> str: ... def samefile(self, other_path: str | bytes | int | Path) -> bool: ... diff --git a/mypy/typeshed/stdlib/pdb.pyi b/mypy/typeshed/stdlib/pdb.pyi index 83bd32d764502..c1cba5e8d23ba 100644 --- a/mypy/typeshed/stdlib/pdb.pyi +++ b/mypy/typeshed/stdlib/pdb.pyi @@ -1,12 +1,17 @@ import signal import sys +from _typeshed import Self from bdb import Bdb from cmd import Cmd from inspect import _SourceObjectType from types import CodeType, FrameType, TracebackType from typing import IO, Any, Callable, ClassVar, Iterable, Mapping, Sequence, TypeVar +from typing_extensions import ParamSpec + +__all__ = ["run", "pm", "Pdb", "runeval", "runctx", "runcall", "set_trace", "post_mortem", "help"] _T = TypeVar("_T") +_P = ParamSpec("_P") line_prefix: str # undocumented @@ -15,7 +20,7 @@ class Restart(Exception): ... def run(statement: str, globals: dict[str, Any] | None = ..., locals: Mapping[str, Any] | None = ...) -> None: ... def runeval(expression: str, globals: dict[str, Any] | None = ..., locals: Mapping[str, Any] | None = ...) -> Any: ... def runctx(statement: str, globals: dict[str, Any], locals: Mapping[str, Any]) -> None: ... -def runcall(func: Callable[..., _T], *args: Any, **kwds: Any) -> _T | None: ... +def runcall(func: Callable[_P, _T], *args: _P.args, **kwds: _P.kwargs) -> _T | None: ... if sys.version_info >= (3, 7): def set_trace(*, header: str | None = ...) -> None: ... @@ -171,4 +176,4 @@ def getsourcelines(obj: _SourceObjectType) -> tuple[list[str], int]: ... def lasti2lineno(code: CodeType, lasti: int) -> int: ... class _rstr(str): - def __repr__(self) -> _rstr: ... + def __repr__(self: Self) -> Self: ... diff --git a/mypy/typeshed/stdlib/pickle.pyi b/mypy/typeshed/stdlib/pickle.pyi index 46c349137459c..26ee94ca26829 100644 --- a/mypy/typeshed/stdlib/pickle.pyi +++ b/mypy/typeshed/stdlib/pickle.pyi @@ -1,11 +1,178 @@ import sys -from typing import Any, Callable, ClassVar, Iterable, Iterator, Mapping, Optional, Protocol, Type, Union +from typing import Any, Callable, ClassVar, Iterable, Iterator, Mapping, Protocol, Union from typing_extensions import final +if sys.version_info >= (3, 8): + __all__ = [ + "PickleError", + "PicklingError", + "UnpicklingError", + "Pickler", + "Unpickler", + "dump", + "dumps", + "load", + "loads", + "PickleBuffer", + "ADDITEMS", + "APPEND", + "APPENDS", + "BINBYTES", + "BINBYTES8", + "BINFLOAT", + "BINGET", + "BININT", + "BININT1", + "BININT2", + "BINPERSID", + "BINPUT", + "BINSTRING", + "BINUNICODE", + "BINUNICODE8", + "BUILD", + "BYTEARRAY8", + "DEFAULT_PROTOCOL", + "DICT", + "DUP", + "EMPTY_DICT", + "EMPTY_LIST", + "EMPTY_SET", + "EMPTY_TUPLE", + "EXT1", + "EXT2", + "EXT4", + "FALSE", + "FLOAT", + "FRAME", + "FROZENSET", + "GET", + "GLOBAL", + "HIGHEST_PROTOCOL", + "INST", + "INT", + "LIST", + "LONG", + "LONG1", + "LONG4", + "LONG_BINGET", + "LONG_BINPUT", + "MARK", + "MEMOIZE", + "NEWFALSE", + "NEWOBJ", + "NEWOBJ_EX", + "NEWTRUE", + "NEXT_BUFFER", + "NONE", + "OBJ", + "PERSID", + "POP", + "POP_MARK", + "PROTO", + "PUT", + "READONLY_BUFFER", + "REDUCE", + "SETITEM", + "SETITEMS", + "SHORT_BINBYTES", + "SHORT_BINSTRING", + "SHORT_BINUNICODE", + "STACK_GLOBAL", + "STOP", + "STRING", + "TRUE", + "TUPLE", + "TUPLE1", + "TUPLE2", + "TUPLE3", + "UNICODE", + ] +else: + __all__ = [ + "PickleError", + "PicklingError", + "UnpicklingError", + "Pickler", + "Unpickler", + "dump", + "dumps", + "load", + "loads", + "ADDITEMS", + "APPEND", + "APPENDS", + "BINBYTES", + "BINBYTES8", + "BINFLOAT", + "BINGET", + "BININT", + "BININT1", + "BININT2", + "BINPERSID", + "BINPUT", + "BINSTRING", + "BINUNICODE", + "BINUNICODE8", + "BUILD", + "DEFAULT_PROTOCOL", + "DICT", + "DUP", + "EMPTY_DICT", + "EMPTY_LIST", + "EMPTY_SET", + "EMPTY_TUPLE", + "EXT1", + "EXT2", + "EXT4", + "FALSE", + "FLOAT", + "FRAME", + "FROZENSET", + "GET", + "GLOBAL", + "HIGHEST_PROTOCOL", + "INST", + "INT", + "LIST", + "LONG", + "LONG1", + "LONG4", + "LONG_BINGET", + "LONG_BINPUT", + "MARK", + "MEMOIZE", + "NEWFALSE", + "NEWOBJ", + "NEWOBJ_EX", + "NEWTRUE", + "NONE", + "OBJ", + "PERSID", + "POP", + "POP_MARK", + "PROTO", + "PUT", + "REDUCE", + "SETITEM", + "SETITEMS", + "SHORT_BINBYTES", + "SHORT_BINSTRING", + "SHORT_BINUNICODE", + "STACK_GLOBAL", + "STOP", + "STRING", + "TRUE", + "TUPLE", + "TUPLE1", + "TUPLE2", + "TUPLE3", + "UNICODE", + ] + HIGHEST_PROTOCOL: int DEFAULT_PROTOCOL: int -bytes_types: tuple[Type[Any], ...] # undocumented +bytes_types: tuple[type[Any], ...] # undocumented class _ReadableFileobj(Protocol): def read(self, __n: int) -> bytes: ... @@ -22,7 +189,7 @@ if sys.version_info >= (3, 8): def __init__(self, buffer: Any) -> None: ... def raw(self) -> memoryview: ... def release(self) -> None: ... - _BufferCallback = Optional[Callable[[PickleBuffer], Any]] + _BufferCallback = Callable[[PickleBuffer], Any] | None def dump( obj: Any, file: _WritableFileobj, @@ -60,8 +227,8 @@ _reducedtype = Union[ str, tuple[Callable[..., Any], tuple[Any, ...]], tuple[Callable[..., Any], tuple[Any, ...], Any], - tuple[Callable[..., Any], tuple[Any, ...], Any, Optional[Iterator[Any]]], - tuple[Callable[..., Any], tuple[Any, ...], Any, Optional[Iterator[Any]], Optional[Iterator[Any]]], + tuple[Callable[..., Any], tuple[Any, ...], Any, Iterator[Any] | None], + tuple[Callable[..., Any], tuple[Any, ...], Any, Iterator[Any] | None, Iterator[Any] | None], ] class Pickler: @@ -82,6 +249,7 @@ class Pickler: def reducer_override(self, obj: Any) -> Any: ... else: def __init__(self, file: _WritableFileobj, protocol: int | None = ..., *, fix_imports: bool = ...) -> None: ... + def dump(self, __obj: Any) -> None: ... def clear_memo(self) -> None: ... def persistent_id(self, obj: Any) -> Any: ... @@ -103,6 +271,7 @@ class Unpickler: def __init__( self, file: _ReadableFileobj, *, fix_imports: bool = ..., encoding: str = ..., errors: str = ... ) -> None: ... + def load(self) -> Any: ... def find_class(self, __module_name: str, __global_name: str) -> Any: ... def persistent_load(self, pid: Any) -> Any: ... diff --git a/mypy/typeshed/stdlib/pickletools.pyi b/mypy/typeshed/stdlib/pickletools.pyi index 04a695f5f1037..7b79ddcff347b 100644 --- a/mypy/typeshed/stdlib/pickletools.pyi +++ b/mypy/typeshed/stdlib/pickletools.pyi @@ -1,7 +1,9 @@ -from typing import IO, Any, Callable, Iterator, MutableMapping, Type +from typing import IO, Any, Callable, Iterator, MutableMapping + +__all__ = ["dis", "genops", "optimize"] _Reader = Callable[[IO[bytes]], Any] -bytes_types: tuple[Type[Any], ...] +bytes_types: tuple[type[Any], ...] UP_TO_NEWLINE: int TAKEN_FROM_ARGUMENT1: int @@ -108,9 +110,9 @@ long4: ArgumentDescriptor class StackObject: name: str - obtype: Type[Any] | tuple[Type[Any], ...] + obtype: type[Any] | tuple[type[Any], ...] doc: str - def __init__(self, name: str, obtype: Type[Any] | tuple[Type[Any], ...], doc: str) -> None: ... + def __init__(self, name: str, obtype: type[Any] | tuple[type[Any], ...], doc: str) -> None: ... pyint: StackObject pylong: StackObject diff --git a/mypy/typeshed/stdlib/pipes.pyi b/mypy/typeshed/stdlib/pipes.pyi index fb9d7e4e1d163..d6bbd7eafac3b 100644 --- a/mypy/typeshed/stdlib/pipes.pyi +++ b/mypy/typeshed/stdlib/pipes.pyi @@ -1,5 +1,7 @@ import os +__all__ = ["Template"] + class Template: def __init__(self) -> None: ... def reset(self) -> None: ... diff --git a/mypy/typeshed/stdlib/pkgutil.pyi b/mypy/typeshed/stdlib/pkgutil.pyi index e0f392fd91d83..7c27f6702a7e1 100644 --- a/mypy/typeshed/stdlib/pkgutil.pyi +++ b/mypy/typeshed/stdlib/pkgutil.pyi @@ -1,14 +1,31 @@ import sys from _typeshed import SupportsRead from importlib.abc import Loader, MetaPathFinder, PathEntryFinder -from typing import IO, Any, Callable, Iterable, Iterator, NamedTuple +from typing import IO, Any, Callable, Iterable, Iterator, NamedTuple, TypeVar + +__all__ = [ + "get_importer", + "iter_importers", + "get_loader", + "find_loader", + "walk_packages", + "iter_modules", + "get_data", + "ImpImporter", + "ImpLoader", + "read_code", + "extend_path", + "ModuleInfo", +] + +_PathT = TypeVar("_PathT", bound=Iterable[str]) class ModuleInfo(NamedTuple): module_finder: MetaPathFinder | PathEntryFinder name: str ispkg: bool -def extend_path(path: list[str], name: str) -> list[str]: ... +def extend_path(path: _PathT, name: str) -> _PathT: ... class ImpImporter: def __init__(self, path: str | None = ...) -> None: ... @@ -18,7 +35,7 @@ class ImpLoader: def find_loader(fullname: str) -> Loader | None: ... def get_importer(path_item: str) -> PathEntryFinder | None: ... -def get_loader(module_or_name: str) -> Loader: ... +def get_loader(module_or_name: str) -> Loader | None: ... def iter_importers(fullname: str = ...) -> Iterator[MetaPathFinder | PathEntryFinder]: ... def iter_modules(path: Iterable[str] | None = ..., prefix: str = ...) -> Iterator[ModuleInfo]: ... def read_code(stream: SupportsRead[bytes]) -> Any: ... # undocumented diff --git a/mypy/typeshed/stdlib/plistlib.pyi b/mypy/typeshed/stdlib/plistlib.pyi index 7abe9dd2942be..67d1611de8282 100644 --- a/mypy/typeshed/stdlib/plistlib.pyi +++ b/mypy/typeshed/stdlib/plistlib.pyi @@ -1,7 +1,59 @@ import sys +from _typeshed import Self from datetime import datetime from enum import Enum -from typing import IO, Any, Mapping, MutableMapping, Type +from typing import IO, Any, Mapping, MutableMapping + +if sys.version_info >= (3, 9): + __all__ = ["InvalidFileException", "FMT_XML", "FMT_BINARY", "load", "dump", "loads", "dumps", "UID"] +elif sys.version_info >= (3, 8): + __all__ = [ + "readPlist", + "writePlist", + "readPlistFromBytes", + "writePlistToBytes", + "Data", + "InvalidFileException", + "FMT_XML", + "FMT_BINARY", + "load", + "dump", + "loads", + "dumps", + "UID", + ] +elif sys.version_info >= (3, 7): + __all__ = [ + "readPlist", + "writePlist", + "readPlistFromBytes", + "writePlistToBytes", + "Data", + "InvalidFileException", + "FMT_XML", + "FMT_BINARY", + "load", + "dump", + "loads", + "dumps", + ] +else: + __all__ = [ + "readPlist", + "writePlist", + "readPlistFromBytes", + "writePlistToBytes", + "Plist", + "Data", + "Dict", + "InvalidFileException", + "FMT_XML", + "FMT_BINARY", + "load", + "dump", + "loads", + "dumps", + ] class PlistFormat(Enum): FMT_XML: int @@ -11,8 +63,8 @@ FMT_XML = PlistFormat.FMT_XML FMT_BINARY = PlistFormat.FMT_BINARY if sys.version_info >= (3, 9): - def load(fp: IO[bytes], *, fmt: PlistFormat | None = ..., dict_type: Type[MutableMapping[str, Any]] = ...) -> Any: ... - def loads(value: bytes, *, fmt: PlistFormat | None = ..., dict_type: Type[MutableMapping[str, Any]] = ...) -> Any: ... + def load(fp: IO[bytes], *, fmt: PlistFormat | None = ..., dict_type: type[MutableMapping[str, Any]] = ...) -> Any: ... + def loads(value: bytes, *, fmt: PlistFormat | None = ..., dict_type: type[MutableMapping[str, Any]] = ...) -> Any: ... else: def load( @@ -20,14 +72,14 @@ else: *, fmt: PlistFormat | None = ..., use_builtin_types: bool = ..., - dict_type: Type[MutableMapping[str, Any]] = ..., + dict_type: type[MutableMapping[str, Any]] = ..., ) -> Any: ... def loads( value: bytes, *, fmt: PlistFormat | None = ..., use_builtin_types: bool = ..., - dict_type: Type[MutableMapping[str, Any]] = ..., + dict_type: type[MutableMapping[str, Any]] = ..., ) -> Any: ... def dump( @@ -53,11 +105,20 @@ if sys.version_info < (3, 9): def writePlistToBytes(value: Mapping[str, Any]) -> bytes: ... if sys.version_info < (3, 7): - class Dict(dict[str, Any]): + class _InternalDict(dict[str, Any]): def __getattr__(self, attr: str) -> Any: ... def __setattr__(self, attr: str, value: Any) -> None: ... def __delattr__(self, attr: str) -> None: ... + class Dict(_InternalDict): # deprecated + def __init__(self, **kwargs: Any) -> None: ... + + class Plist(_InternalDict): # deprecated + def __init__(self, **kwargs: Any) -> None: ... + @classmethod + def fromFile(cls: type[Self], pathOrFile: str | IO[bytes]) -> Self: ... + def write(self, pathOrFile: str | IO[bytes]) -> None: ... + if sys.version_info < (3, 9): class Data: data: bytes @@ -68,8 +129,9 @@ if sys.version_info >= (3, 8): data: int def __init__(self, data: int) -> None: ... def __index__(self) -> int: ... - def __reduce__(self) -> Any: ... + def __reduce__(self: Self) -> tuple[type[Self], tuple[int]]: ... def __hash__(self) -> int: ... + def __eq__(self, other: object) -> bool: ... class InvalidFileException(ValueError): def __init__(self, message: str = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/poplib.pyi b/mypy/typeshed/stdlib/poplib.pyi index 028af412847b3..111e5c4ca76ab 100644 --- a/mypy/typeshed/stdlib/poplib.pyi +++ b/mypy/typeshed/stdlib/poplib.pyi @@ -1,16 +1,24 @@ import socket import ssl -from typing import Any, BinaryIO, Pattern, overload +import sys +from typing import Any, BinaryIO, NoReturn, Pattern, overload +from typing_extensions import Literal + +if sys.version_info >= (3, 10): + __all__ = ["POP3", "error_proto", "POP3_SSL"] +else: + __all__ = ["POP3", "error_proto"] _LongResp = tuple[bytes, list[bytes], int] class error_proto(Exception): ... -POP3_PORT: int -POP3_SSL_PORT: int -CR: bytes -LF: bytes -CRLF: bytes +POP3_PORT: Literal[110] +POP3_SSL_PORT: Literal[995] +CR: Literal[b"\r"] +LF: Literal[b"\n"] +CRLF: Literal[b"\r\n"] +HAVE_SSL: bool _list = list # conflicts with a method named "list" @@ -57,4 +65,4 @@ class POP3_SSL(POP3): context: ssl.SSLContext | None = ..., ) -> None: ... # "context" is actually the last argument, but that breaks LSP and it doesn't really matter because all the arguments are ignored - def stls(self, context: Any = ..., keyfile: Any = ..., certfile: Any = ...) -> bytes: ... + def stls(self, context: Any = ..., keyfile: Any = ..., certfile: Any = ...) -> NoReturn: ... diff --git a/mypy/typeshed/stdlib/posix.pyi b/mypy/typeshed/stdlib/posix.pyi index 9f658039bcf25..5dba5b36e3d2b 100644 --- a/mypy/typeshed/stdlib/posix.pyi +++ b/mypy/typeshed/stdlib/posix.pyi @@ -273,7 +273,8 @@ if sys.platform != "win32": from os import CLD_KILLED as CLD_KILLED, CLD_STOPPED as CLD_STOPPED, waitstatus_to_exitcode as waitstatus_to_exitcode if sys.platform == "linux": - from os import P_PIDFD as P_PIDFD + from os import P_PIDFD as P_PIDFD, pidfd_open as pidfd_open + if sys.version_info >= (3, 8): from os import ( POSIX_SPAWN_CLOSE as POSIX_SPAWN_CLOSE, @@ -302,6 +303,7 @@ if sys.platform != "win32": MFD_HUGE_MASK as MFD_HUGE_MASK, MFD_HUGE_SHIFT as MFD_HUGE_SHIFT, MFD_HUGETLB as MFD_HUGETLB, + copy_file_range as copy_file_range, memfd_create as memfd_create, ) if sys.version_info >= (3, 7): diff --git a/mypy/typeshed/stdlib/posixpath.pyi b/mypy/typeshed/stdlib/posixpath.pyi index 58cadb4de03cc..c72ba8a99bdde 100644 --- a/mypy/typeshed/stdlib/posixpath.pyi +++ b/mypy/typeshed/stdlib/posixpath.pyi @@ -16,6 +16,47 @@ from genericpath import ( from os import PathLike from typing import AnyStr, Sequence, overload +__all__ = [ + "normcase", + "isabs", + "join", + "splitdrive", + "split", + "splitext", + "basename", + "dirname", + "commonprefix", + "getsize", + "getmtime", + "getatime", + "getctime", + "islink", + "exists", + "lexists", + "isdir", + "isfile", + "ismount", + "expanduser", + "expandvars", + "normpath", + "abspath", + "samefile", + "sameopenfile", + "samestat", + "curdir", + "pardir", + "sep", + "pathsep", + "defpath", + "altsep", + "extsep", + "devnull", + "realpath", + "supports_unicode_filenames", + "relpath", + "commonpath", +] + supports_unicode_filenames: bool # aliases (also in os) curdir: str diff --git a/mypy/typeshed/stdlib/pprint.pyi b/mypy/typeshed/stdlib/pprint.pyi index 9e343feb49bc5..0addc8f538b21 100644 --- a/mypy/typeshed/stdlib/pprint.pyi +++ b/mypy/typeshed/stdlib/pprint.pyi @@ -1,5 +1,10 @@ import sys -from typing import IO, Any +from typing import IO + +if sys.version_info >= (3, 8): + __all__ = ["pprint", "pformat", "isreadable", "isrecursive", "saferepr", "PrettyPrinter", "pp"] +else: + __all__ = ["pprint", "pformat", "isreadable", "isrecursive", "saferepr", "PrettyPrinter"] if sys.version_info >= (3, 10): def pformat( @@ -126,8 +131,9 @@ class PrettyPrinter: *, compact: bool = ..., ) -> None: ... + def pformat(self, object: object) -> str: ... def pprint(self, object: object) -> None: ... def isreadable(self, object: object) -> bool: ... def isrecursive(self, object: object) -> bool: ... - def format(self, object: object, context: dict[int, Any], maxlevels: int, level: int) -> tuple[str, bool, bool]: ... + def format(self, object: object, context: dict[int, int], maxlevels: int, level: int) -> tuple[str, bool, bool]: ... diff --git a/mypy/typeshed/stdlib/profile.pyi b/mypy/typeshed/stdlib/profile.pyi index 7581c0122c9c1..982bcabad4011 100644 --- a/mypy/typeshed/stdlib/profile.pyi +++ b/mypy/typeshed/stdlib/profile.pyi @@ -1,13 +1,16 @@ -from _typeshed import StrOrBytesPath +from _typeshed import Self, StrOrBytesPath from typing import Any, Callable, TypeVar +from typing_extensions import ParamSpec + +__all__ = ["run", "runctx", "Profile"] def run(statement: str, filename: str | None = ..., sort: str | int = ...) -> None: ... def runctx( statement: str, globals: dict[str, Any], locals: dict[str, Any], filename: str | None = ..., sort: str | int = ... ) -> None: ... -_SelfT = TypeVar("_SelfT", bound=Profile) _T = TypeVar("_T") +_P = ParamSpec("_P") _Label = tuple[str, int, str] class Profile: @@ -21,7 +24,7 @@ class Profile: def dump_stats(self, file: StrOrBytesPath) -> None: ... def create_stats(self) -> None: ... def snapshot_stats(self) -> None: ... - def run(self: _SelfT, cmd: str) -> _SelfT: ... - def runctx(self: _SelfT, cmd: str, globals: dict[str, Any], locals: dict[str, Any]) -> _SelfT: ... - def runcall(self, __func: Callable[..., _T], *args: Any, **kw: Any) -> _T: ... + def run(self: Self, cmd: str) -> Self: ... + def runctx(self: Self, cmd: str, globals: dict[str, Any], locals: dict[str, Any]) -> Self: ... + def runcall(self, __func: Callable[_P, _T], *args: _P.args, **kw: _P.kwargs) -> _T: ... def calibrate(self, m: int, verbose: int = ...) -> float: ... diff --git a/mypy/typeshed/stdlib/pstats.pyi b/mypy/typeshed/stdlib/pstats.pyi index 6e008c823ff2a..a7b8bebe4066b 100644 --- a/mypy/typeshed/stdlib/pstats.pyi +++ b/mypy/typeshed/stdlib/pstats.pyi @@ -1,14 +1,22 @@ import sys -from _typeshed import StrOrBytesPath +from _typeshed import Self, StrOrBytesPath from cProfile import Profile as _cProfile from profile import Profile -from typing import IO, Any, Iterable, TypeVar, Union, overload +from typing import IO, Any, Iterable, overload +from typing_extensions import Literal -_Selector = Union[str, float, int] -_T = TypeVar("_T", bound=Stats) +if sys.version_info >= (3, 9): + __all__ = ["Stats", "SortKey", "FunctionProfile", "StatsProfile"] +elif sys.version_info >= (3, 7): + __all__ = ["Stats", "SortKey"] +else: + __all__ = ["Stats"] + +_Selector = str | float | int if sys.version_info >= (3, 7): from enum import Enum + class SortKey(str, Enum): CALLS: str CUMULATIVE: str @@ -20,32 +28,54 @@ if sys.version_info >= (3, 7): STDNAME: str TIME: str +if sys.version_info >= (3, 9): + from dataclasses import dataclass + + @dataclass(unsafe_hash=True) + class FunctionProfile: + ncalls: int + tottime: float + percall_tottime: float + cumtime: float + percall_cumtime: float + file_name: str + line_number: int + @dataclass(unsafe_hash=True) + class StatsProfile: + total_tt: float + func_profiles: dict[str, FunctionProfile] + +_SortArgDict = dict[str, tuple[tuple[tuple[int, int], ...], str]] + class Stats: - sort_arg_dict_default: dict[str, tuple[Any, str]] + sort_arg_dict_default: _SortArgDict def __init__( - self: _T, + self: Self, __arg: None | str | Profile | _cProfile = ..., - *args: None | str | Profile | _cProfile | _T, + *args: None | str | Profile | _cProfile | Self, stream: IO[Any] | None = ..., ) -> None: ... def init(self, arg: None | str | Profile | _cProfile) -> None: ... def load_stats(self, arg: None | str | Profile | _cProfile) -> None: ... def get_top_level_stats(self) -> None: ... - def add(self: _T, *arg_list: None | str | Profile | _cProfile | _T) -> _T: ... + def add(self: Self, *arg_list: None | str | Profile | _cProfile | Self) -> Self: ... def dump_stats(self, filename: StrOrBytesPath) -> None: ... - def get_sort_arg_defs(self) -> dict[str, tuple[tuple[tuple[int, int], ...], str]]: ... + def get_sort_arg_defs(self) -> _SortArgDict: ... @overload - def sort_stats(self: _T, field: int) -> _T: ... + def sort_stats(self: Self, field: Literal[-1, 0, 1, 2]) -> Self: ... @overload - def sort_stats(self: _T, *field: str) -> _T: ... - def reverse_order(self: _T) -> _T: ... - def strip_dirs(self: _T) -> _T: ... + def sort_stats(self: Self, *field: str) -> Self: ... + def reverse_order(self: Self) -> Self: ... + def strip_dirs(self: Self) -> Self: ... def calc_callees(self) -> None: ... def eval_print_amount(self, sel: _Selector, list: list[str], msg: str) -> tuple[list[str], str]: ... + if sys.version_info >= (3, 9): + def get_stats_profile(self) -> StatsProfile: ... + def get_print_list(self, sel_list: Iterable[_Selector]) -> tuple[int, list[str]]: ... - def print_stats(self: _T, *amount: _Selector) -> _T: ... - def print_callees(self: _T, *amount: _Selector) -> _T: ... - def print_callers(self: _T, *amount: _Selector) -> _T: ... + def print_stats(self: Self, *amount: _Selector) -> Self: ... + def print_callees(self: Self, *amount: _Selector) -> Self: ... + def print_callers(self: Self, *amount: _Selector) -> Self: ... def print_call_heading(self, name_size: int, column_title: str) -> None: ... def print_call_line(self, name_size: int, source: str, call_dict: dict[str, Any], arrow: str = ...) -> None: ... def print_title(self) -> None: ... diff --git a/mypy/typeshed/stdlib/pwd.pyi b/mypy/typeshed/stdlib/pwd.pyi index 08a9facf642e9..80813479d7afc 100644 --- a/mypy/typeshed/stdlib/pwd.pyi +++ b/mypy/typeshed/stdlib/pwd.pyi @@ -1,11 +1,13 @@ import sys from _typeshed import structseq from typing import Any -from typing_extensions import final +from typing_extensions import Final, final if sys.platform != "win32": @final class struct_passwd(structseq[Any], tuple[str, str, int, int, str, str, str]): + if sys.version_info >= (3, 10): + __match_args__: Final = ("pw_name", "pw_passwd", "pw_uid", "pw_gid", "pw_gecos", "pw_dir", "pw_shell") @property def pw_name(self) -> str: ... @property @@ -20,6 +22,7 @@ if sys.platform != "win32": def pw_dir(self) -> str: ... @property def pw_shell(self) -> str: ... + def getpwall() -> list[struct_passwd]: ... def getpwuid(__uid: int) -> struct_passwd: ... def getpwnam(__name: str) -> struct_passwd: ... diff --git a/mypy/typeshed/stdlib/py_compile.pyi b/mypy/typeshed/stdlib/py_compile.pyi index 1df818509d0e6..c544a7941981c 100644 --- a/mypy/typeshed/stdlib/py_compile.pyi +++ b/mypy/typeshed/stdlib/py_compile.pyi @@ -1,15 +1,21 @@ import sys -from typing import AnyStr, Type +from typing import AnyStr + +if sys.version_info >= (3, 7): + __all__ = ["compile", "main", "PyCompileError", "PycInvalidationMode"] +else: + __all__ = ["compile", "main", "PyCompileError"] class PyCompileError(Exception): exc_type_name: str exc_value: BaseException file: str msg: str - def __init__(self, exc_type: Type[BaseException], exc_value: BaseException, file: str, msg: str = ...) -> None: ... + def __init__(self, exc_type: type[BaseException], exc_value: BaseException, file: str, msg: str = ...) -> None: ... if sys.version_info >= (3, 7): import enum + class PycInvalidationMode(enum.Enum): TIMESTAMP: int CHECKED_HASH: int @@ -42,4 +48,8 @@ else: file: AnyStr, cfile: AnyStr | None = ..., dfile: AnyStr | None = ..., doraise: bool = ..., optimize: int = ... ) -> AnyStr | None: ... -def main(args: list[str] | None = ...) -> int: ... +if sys.version_info >= (3, 10): + def main() -> None: ... + +else: + def main(args: list[str] | None = ...) -> int: ... diff --git a/mypy/typeshed/stdlib/pyclbr.pyi b/mypy/typeshed/stdlib/pyclbr.pyi index 10d106b4f5117..3033833a81626 100644 --- a/mypy/typeshed/stdlib/pyclbr.pyi +++ b/mypy/typeshed/stdlib/pyclbr.pyi @@ -1,5 +1,7 @@ import sys -from typing import Sequence +from collections.abc import Sequence + +__all__ = ["readmodule", "readmodule_ex", "Class", "Function"] class Class: module: str @@ -9,7 +11,26 @@ class Class: file: int lineno: int + if sys.version_info >= (3, 10): + end_lineno: int | None + if sys.version_info >= (3, 7): + parent: Class | None + children: dict[str, Class | Function] + + if sys.version_info >= (3, 10): + def __init__( + self, + module: str, + name: str, + super_: list[Class | str] | None, + file: str, + lineno: int, + parent: Class | None = ..., + *, + end_lineno: int | None = ..., + ) -> None: ... + elif sys.version_info >= (3, 7): def __init__( self, module: str, name: str, super: list[Class | str] | None, file: str, lineno: int, parent: Class | None = ... ) -> None: ... @@ -22,8 +43,28 @@ class Function: file: int lineno: int + if sys.version_info >= (3, 10): + end_lineno: int | None + is_async: bool + if sys.version_info >= (3, 7): - def __init__(self, module: str, name: str, file: str, lineno: int, parent: Function | None = ...) -> None: ... + parent: Function | Class | None + children: dict[str, Class | Function] + + if sys.version_info >= (3, 10): + def __init__( + self, + module: str, + name: str, + file: str, + lineno: int, + parent: Function | Class | None = ..., + is_async: bool = ..., + *, + end_lineno: int | None = ..., + ) -> None: ... + elif sys.version_info >= (3, 7): + def __init__(self, module: str, name: str, file: str, lineno: int, parent: Function | Class | None = ...) -> None: ... else: def __init__(self, module: str, name: str, file: str, lineno: int) -> None: ... diff --git a/mypy/typeshed/stdlib/pydoc.pyi b/mypy/typeshed/stdlib/pydoc.pyi index a1d4359d28fc9..b4fa66c601558 100644 --- a/mypy/typeshed/stdlib/pydoc.pyi +++ b/mypy/typeshed/stdlib/pydoc.pyi @@ -1,10 +1,15 @@ from _typeshed import SupportsWrite +from abc import abstractmethod from reprlib import Repr from types import MethodType, ModuleType, TracebackType -from typing import IO, Any, AnyStr, Callable, Container, Mapping, MutableMapping, NoReturn, Optional, Type +from typing import IO, Any, AnyStr, Callable, Container, Mapping, MutableMapping, NoReturn, TypeVar + +__all__ = ["help"] # the return type of sys.exc_info(), used by ErrorDuringImport.__init__ -_Exc_Info = tuple[Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType]] +_Exc_Info = tuple[type[BaseException] | None, BaseException | None, TracebackType | None] + +_T = TypeVar("_T") __author__: str __date__: str @@ -28,7 +33,7 @@ def synopsis(filename: str, cache: MutableMapping[str, tuple[int, str]] = ...) - class ErrorDuringImport(Exception): filename: str - exc: Type[BaseException] | None + exc: type[BaseException] | None value: BaseException | None tb: TracebackType | None def __init__(self, filename: str, exc_info: _Exc_Info) -> None: ... @@ -40,11 +45,17 @@ class Doc: PYTHONDOCS: str def document(self, object: object, name: str | None = ..., *args: Any) -> str: ... def fail(self, object: object, name: str | None = ..., *args: Any) -> NoReturn: ... + @abstractmethod def docmodule(self, object: object, name: str | None = ..., *args: Any) -> str: ... + @abstractmethod def docclass(self, object: object, name: str | None = ..., *args: Any) -> str: ... + @abstractmethod def docroutine(self, object: object, name: str | None = ..., *args: Any) -> str: ... + @abstractmethod def docother(self, object: object, name: str | None = ..., *args: Any) -> str: ... + @abstractmethod def docproperty(self, object: object, name: str | None = ..., *args: Any) -> str: ... + @abstractmethod def docdata(self, object: object, name: str | None = ..., *args: Any) -> str: ... def getdocloc(self, object: object, basedir: str = ...) -> str | None: ... @@ -64,8 +75,9 @@ class HTMLRepr(Repr): def repr_unicode(self, x: AnyStr, level: complex) -> str: ... class HTMLDoc(Doc): - repr: Callable[[object], str] - escape: Callable[[str], str] + _repr_instance: HTMLRepr = ... + repr = _repr_instance.repr + escape = _repr_instance.escape def page(self, title: str, contents: str) -> str: ... def heading(self, title: str, fgcol: str, bgcol: str, extras: str = ...) -> str: ... def section( @@ -81,7 +93,7 @@ class HTMLDoc(Doc): ) -> str: ... def bigsection(self, title: str, *args: Any) -> str: ... def preformat(self, text: str) -> str: ... - def multicolumn(self, list: list[Any], format: Callable[[Any], str], cols: int = ...) -> str: ... + def multicolumn(self, list: list[_T], format: Callable[[_T], str], cols: int = ...) -> str: ... def grey(self, text: str) -> str: ... def namelink(self, name: str, *dicts: MutableMapping[str, str]) -> str: ... def classlink(self, object: object, modname: str) -> str: ... @@ -138,7 +150,8 @@ class TextRepr(Repr): def repr_instance(self, x: object, level: complex) -> str: ... class TextDoc(Doc): - repr: Callable[[object], str] + _repr_instance: TextRepr = ... + repr = _repr_instance.repr def bold(self, text: str) -> str: ... def indent(self, text: str, prefix: str = ...) -> str: ... def section(self, title: str, contents: str) -> str: ... @@ -189,8 +202,10 @@ class Helper: symbols: dict[str, str] topics: dict[str, str | tuple[str, ...]] def __init__(self, input: IO[str] | None = ..., output: IO[str] | None = ...) -> None: ... - input: IO[str] - output: IO[str] + @property + def input(self) -> IO[str]: ... + @property + def output(self) -> IO[str]: ... def __call__(self, request: str | Helper | object = ...) -> None: ... def interact(self) -> None: ... def getline(self, prompt: str) -> str: ... @@ -206,21 +221,12 @@ class Helper: help: Helper -# See Python issue #11182: "remove the unused and undocumented pydoc.Scanner class" -# class Scanner: -# roots = ... # type: Any -# state = ... # type: Any -# children = ... # type: Any -# descendp = ... # type: Any -# def __init__(self, roots, children, descendp) -> None: ... -# def next(self): ... - class ModuleScanner: quit: bool def run( self, callback: Callable[[str | None, str, str], None], - key: Any | None = ..., + key: str | None = ..., completer: Callable[[], None] | None = ..., onerror: Callable[[str], None] | None = ..., ) -> None: ... diff --git a/mypy/typeshed/stdlib/pyexpat/__init__.pyi b/mypy/typeshed/stdlib/pyexpat/__init__.pyi index 5aca55c2b813d..24c93965b21f2 100644 --- a/mypy/typeshed/stdlib/pyexpat/__init__.pyi +++ b/mypy/typeshed/stdlib/pyexpat/__init__.pyi @@ -1,7 +1,7 @@ import pyexpat.errors as errors import pyexpat.model as model from _typeshed import SupportsRead -from typing import Any, Callable, Optional +from typing import Any, Callable from typing_extensions import final EXPAT_VERSION: str # undocumented @@ -20,7 +20,7 @@ XML_PARAM_ENTITY_PARSING_NEVER: int XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE: int XML_PARAM_ENTITY_PARSING_ALWAYS: int -_Model = tuple[int, int, Optional[str], tuple[Any, ...]] +_Model = tuple[int, int, str | None, tuple[Any, ...]] @final class XMLParserType: diff --git a/mypy/typeshed/stdlib/queue.pyi b/mypy/typeshed/stdlib/queue.pyi index 9671155b7eb62..532d5d98344d1 100644 --- a/mypy/typeshed/stdlib/queue.pyi +++ b/mypy/typeshed/stdlib/queue.pyi @@ -5,6 +5,11 @@ from typing import Any, Generic, TypeVar if sys.version_info >= (3, 9): from types import GenericAlias +if sys.version_info >= (3, 7): + __all__ = ["Empty", "Full", "Queue", "PriorityQueue", "LifoQueue", "SimpleQueue"] +else: + __all__ = ["Empty", "Full", "Queue", "PriorityQueue", "LifoQueue"] + _T = TypeVar("_T") class Empty(Exception): ... @@ -18,6 +23,8 @@ class Queue(Generic[_T]): not_full: Condition # undocumented all_tasks_done: Condition # undocumented unfinished_tasks: int # undocumented + # Despite the fact that `queue` has `deque` type, + # we treat it as `Any` to allow different implementations in subtypes. queue: Any # undocumented def __init__(self, maxsize: int = ...) -> None: ... def _init(self, maxsize: int) -> None: ... @@ -36,8 +43,11 @@ class Queue(Generic[_T]): if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... -class PriorityQueue(Queue[_T]): ... -class LifoQueue(Queue[_T]): ... +class PriorityQueue(Queue[_T]): + queue: list[_T] + +class LifoQueue(Queue[_T]): + queue: list[_T] if sys.version_info >= (3, 7): class SimpleQueue(Generic[_T]): diff --git a/mypy/typeshed/stdlib/quopri.pyi b/mypy/typeshed/stdlib/quopri.pyi index c2ffabe7d5316..b8dc0787fd1ae 100644 --- a/mypy/typeshed/stdlib/quopri.pyi +++ b/mypy/typeshed/stdlib/quopri.pyi @@ -1,5 +1,7 @@ from typing import BinaryIO +__all__ = ["encode", "decode", "encodestring", "decodestring"] + def encode(input: BinaryIO, output: BinaryIO, quotetabs: int, header: int = ...) -> None: ... def encodestring(s: bytes, quotetabs: int = ..., header: int = ...) -> bytes: ... def decode(input: BinaryIO, output: BinaryIO, header: int = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/random.pyi b/mypy/typeshed/stdlib/random.pyi index ffa866ef9aa05..612a54cb95b03 100644 --- a/mypy/typeshed/stdlib/random.pyi +++ b/mypy/typeshed/stdlib/random.pyi @@ -5,12 +5,73 @@ from collections.abc import Callable, Iterable, MutableSequence, Sequence, Set a from fractions import Fraction from typing import Any, ClassVar, NoReturn, TypeVar +if sys.version_info >= (3, 9): + __all__ = [ + "Random", + "SystemRandom", + "betavariate", + "choice", + "choices", + "expovariate", + "gammavariate", + "gauss", + "getrandbits", + "getstate", + "lognormvariate", + "normalvariate", + "paretovariate", + "randbytes", + "randint", + "random", + "randrange", + "sample", + "seed", + "setstate", + "shuffle", + "triangular", + "uniform", + "vonmisesvariate", + "weibullvariate", + ] +else: + __all__ = [ + "Random", + "seed", + "random", + "uniform", + "randint", + "choice", + "sample", + "randrange", + "shuffle", + "normalvariate", + "lognormvariate", + "expovariate", + "vonmisesvariate", + "gammavariate", + "triangular", + "gauss", + "betavariate", + "paretovariate", + "weibullvariate", + "getstate", + "setstate", + "getrandbits", + "choices", + "SystemRandom", + ] + _T = TypeVar("_T") class Random(_random.Random): VERSION: ClassVar[int] def __init__(self, x: Any = ...) -> None: ... - def seed(self, a: Any = ..., version: int = ...) -> None: ... + # Using other `seed` types is deprecated since 3.9 and removed in 3.11 + if sys.version_info >= (3, 9): + def seed(self, a: int | float | str | bytes | bytearray | None = ..., version: int = ...) -> None: ... # type: ignore[override] + else: + def seed(self, a: Any = ..., version: int = ...) -> None: ... + def getstate(self) -> tuple[Any, ...]: ... def setstate(self, state: tuple[Any, ...]) -> None: ... def getrandbits(self, __k: int) -> int: ... @@ -18,6 +79,7 @@ class Random(_random.Random): def randint(self, a: int, b: int) -> int: ... if sys.version_info >= (3, 9): def randbytes(self, n: int) -> bytes: ... + def choice(self, seq: SupportsLenAndGetItem[_T]) -> _T: ... def choices( self, @@ -28,21 +90,29 @@ class Random(_random.Random): k: int = ..., ) -> list[_T]: ... def shuffle(self, x: MutableSequence[Any], random: Callable[[], float] | None = ...) -> None: ... - if sys.version_info >= (3, 9): + if sys.version_info >= (3, 11): + def sample(self, population: Sequence[_T], k: int, *, counts: Iterable[int] | None = ...) -> list[_T]: ... + elif sys.version_info >= (3, 9): def sample( - self, population: Sequence[_T] | AbstractSet[_T], k: int, *, counts: Iterable[_T] | None = ... + self, population: Sequence[_T] | AbstractSet[_T], k: int, *, counts: Iterable[int] | None = ... ) -> list[_T]: ... else: def sample(self, population: Sequence[_T] | AbstractSet[_T], k: int) -> list[_T]: ... + def random(self) -> float: ... def uniform(self, a: float, b: float) -> float: ... def triangular(self, low: float = ..., high: float = ..., mode: float | None = ...) -> float: ... def betavariate(self, alpha: float, beta: float) -> float: ... def expovariate(self, lambd: float) -> float: ... def gammavariate(self, alpha: float, beta: float) -> float: ... - def gauss(self, mu: float, sigma: float) -> float: ... + if sys.version_info >= (3, 11): + def gauss(self, mu: float = ..., sigma: float = ...) -> float: ... + def normalvariate(self, mu: float = ..., sigma: float = ...) -> float: ... + else: + def gauss(self, mu: float, sigma: float) -> float: ... + def normalvariate(self, mu: float, sigma: float) -> float: ... + def lognormvariate(self, mu: float, sigma: float) -> float: ... - def normalvariate(self, mu: float, sigma: float) -> float: ... def vonmisesvariate(self, mu: float, kappa: float) -> float: ... def paretovariate(self, alpha: float) -> float: ... def weibullvariate(self, alpha: float, beta: float) -> float: ... @@ -54,41 +124,29 @@ class SystemRandom(Random): def setstate(self, *args: Any, **kwds: Any) -> NoReturn: ... # ----- random function stubs ----- -def seed(a: Any = ..., version: int = ...) -> None: ... -def getstate() -> object: ... -def setstate(state: object) -> None: ... -def getrandbits(__k: int) -> int: ... -def randrange(start: int, stop: None | int = ..., step: int = ...) -> int: ... -def randint(a: int, b: int) -> int: ... - -if sys.version_info >= (3, 9): - def randbytes(n: int) -> bytes: ... - -def choice(seq: SupportsLenAndGetItem[_T]) -> _T: ... -def choices( - population: SupportsLenAndGetItem[_T], - weights: Sequence[float] | None = ..., - *, - cum_weights: Sequence[float] | None = ..., - k: int = ..., -) -> list[_T]: ... -def shuffle(x: MutableSequence[Any], random: Callable[[], float] | None = ...) -> None: ... +_inst: Random = ... +seed = _inst.seed +random = _inst.random +uniform = _inst.uniform +triangular = _inst.triangular +randint = _inst.randint +choice = _inst.choice +randrange = _inst.randrange +sample = _inst.sample +shuffle = _inst.shuffle +choices = _inst.choices +normalvariate = _inst.normalvariate +lognormvariate = _inst.lognormvariate +expovariate = _inst.expovariate +vonmisesvariate = _inst.vonmisesvariate +gammavariate = _inst.gammavariate +gauss = _inst.gauss +betavariate = _inst.betavariate +paretovariate = _inst.paretovariate +weibullvariate = _inst.weibullvariate +getstate = _inst.getstate +setstate = _inst.setstate +getrandbits = _inst.getrandbits if sys.version_info >= (3, 9): - def sample(population: Sequence[_T] | AbstractSet[_T], k: int, *, counts: Iterable[_T] | None = ...) -> list[_T]: ... - -else: - def sample(population: Sequence[_T] | AbstractSet[_T], k: int) -> list[_T]: ... - -def random() -> float: ... -def uniform(a: float, b: float) -> float: ... -def triangular(low: float = ..., high: float = ..., mode: float | None = ...) -> float: ... -def betavariate(alpha: float, beta: float) -> float: ... -def expovariate(lambd: float) -> float: ... -def gammavariate(alpha: float, beta: float) -> float: ... -def gauss(mu: float, sigma: float) -> float: ... -def lognormvariate(mu: float, sigma: float) -> float: ... -def normalvariate(mu: float, sigma: float) -> float: ... -def vonmisesvariate(mu: float, kappa: float) -> float: ... -def paretovariate(alpha: float) -> float: ... -def weibullvariate(alpha: float, beta: float) -> float: ... + randbytes = _inst.randbytes diff --git a/mypy/typeshed/stdlib/re.pyi b/mypy/typeshed/stdlib/re.pyi index 01a60d170c502..57dab8eb820f4 100644 --- a/mypy/typeshed/stdlib/re.pyi +++ b/mypy/typeshed/stdlib/re.pyi @@ -1,7 +1,8 @@ import enum +import sre_compile import sys from sre_constants import error as error -from typing import Any, AnyStr, Callable, Iterator, Union, overload +from typing import Any, AnyStr, Callable, Iterator, overload # ----- re variables and constants ----- if sys.version_info >= (3, 7): @@ -9,24 +10,123 @@ if sys.version_info >= (3, 7): else: from typing import Match, Pattern +if sys.version_info >= (3, 11): + __all__ = [ + "match", + "fullmatch", + "search", + "sub", + "subn", + "split", + "findall", + "finditer", + "compile", + "purge", + "template", + "escape", + "error", + "Pattern", + "Match", + "A", + "I", + "L", + "M", + "S", + "X", + "U", + "ASCII", + "IGNORECASE", + "LOCALE", + "MULTILINE", + "DOTALL", + "VERBOSE", + "UNICODE", + "RegexFlag", + "NOFLAG", + ] +elif sys.version_info >= (3, 8): + __all__ = [ + "match", + "fullmatch", + "search", + "sub", + "subn", + "split", + "findall", + "finditer", + "compile", + "purge", + "template", + "escape", + "error", + "Pattern", + "Match", + "A", + "I", + "L", + "M", + "S", + "X", + "U", + "ASCII", + "IGNORECASE", + "LOCALE", + "MULTILINE", + "DOTALL", + "VERBOSE", + "UNICODE", + ] +else: + __all__ = [ + "match", + "fullmatch", + "search", + "sub", + "subn", + "split", + "findall", + "finditer", + "compile", + "purge", + "template", + "escape", + "error", + "A", + "I", + "L", + "M", + "S", + "X", + "U", + "ASCII", + "IGNORECASE", + "LOCALE", + "MULTILINE", + "DOTALL", + "VERBOSE", + "UNICODE", + ] + class RegexFlag(enum.IntFlag): - A: int - ASCII: int - DEBUG: int - I: int - IGNORECASE: int - L: int - LOCALE: int - M: int - MULTILINE: int - S: int - DOTALL: int - X: int - VERBOSE: int - U: int - UNICODE: int - T: int - TEMPLATE: int + A = sre_compile.SRE_FLAG_ASCII + ASCII = A + DEBUG = sre_compile.SRE_FLAG_DEBUG + I = sre_compile.SRE_FLAG_IGNORECASE + IGNORECASE = I + L = sre_compile.SRE_FLAG_LOCALE + LOCALE = L + M = sre_compile.SRE_FLAG_MULTILINE + MULTILINE = M + S = sre_compile.SRE_FLAG_DOTALL + DOTALL = S + X = sre_compile.SRE_FLAG_VERBOSE + VERBOSE = X + U = sre_compile.SRE_FLAG_UNICODE + UNICODE = U + T = sre_compile.SRE_FLAG_TEMPLATE + TEMPLATE = T + if sys.version_info >= (3, 11): + NOFLAG: int A = RegexFlag.A ASCII = RegexFlag.ASCII @@ -45,12 +145,19 @@ U = RegexFlag.U UNICODE = RegexFlag.UNICODE T = RegexFlag.T TEMPLATE = RegexFlag.TEMPLATE -_FlagsType = Union[int, RegexFlag] +if sys.version_info >= (3, 11): + NOFLAG = RegexFlag.NOFLAG +_FlagsType = int | RegexFlag if sys.version_info < (3, 7): # undocumented _pattern_type: type +# Type-wise these overloads are unnecessary, they could also be modeled using +# unions in the parameter types. However mypy has a bug regarding TypeVar +# constraints (https://github.com/python/mypy/issues/11880), +# which limits us here because AnyStr is a constrained TypeVar. + @overload def compile(pattern: AnyStr, flags: _FlagsType = ...) -> Pattern[AnyStr]: ... @overload @@ -63,8 +170,6 @@ def search(pattern: Pattern[AnyStr], string: AnyStr, flags: _FlagsType = ...) -> def match(pattern: AnyStr, string: AnyStr, flags: _FlagsType = ...) -> Match[AnyStr] | None: ... @overload def match(pattern: Pattern[AnyStr], string: AnyStr, flags: _FlagsType = ...) -> Match[AnyStr] | None: ... - -# New in Python 3.4 @overload def fullmatch(pattern: AnyStr, string: AnyStr, flags: _FlagsType = ...) -> Match[AnyStr] | None: ... @overload diff --git a/mypy/typeshed/stdlib/readline.pyi b/mypy/typeshed/stdlib/readline.pyi index fd3a4b1dcc654..df08a3cc25ff6 100644 --- a/mypy/typeshed/stdlib/readline.pyi +++ b/mypy/typeshed/stdlib/readline.pyi @@ -1,10 +1,11 @@ import sys from _typeshed import StrOrBytesPath -from typing import Callable, Optional, Sequence +from typing import Callable, Sequence if sys.platform != "win32": - _CompleterT = Optional[Callable[[str, int], Optional[str]]] - _CompDispT = Optional[Callable[[str, Sequence[str], int], None]] + _Completer = Callable[[str, int], str | None] + _CompDisp = Callable[[str, Sequence[str], int], None] + def parse_and_bind(__string: str) -> None: ... def read_init_file(__filename: StrOrBytesPath | None = ...) -> None: ... def get_line_buffer() -> str: ... @@ -22,13 +23,13 @@ if sys.platform != "win32": def replace_history_item(__pos: int, __line: str) -> None: ... def add_history(__string: str) -> None: ... def set_auto_history(__enabled: bool) -> None: ... - def set_startup_hook(__function: Callable[[], None] | None = ...) -> None: ... - def set_pre_input_hook(__function: Callable[[], None] | None = ...) -> None: ... - def set_completer(__function: _CompleterT = ...) -> None: ... - def get_completer() -> _CompleterT: ... + def set_startup_hook(__function: Callable[[], object] | None = ...) -> None: ... + def set_pre_input_hook(__function: Callable[[], object] | None = ...) -> None: ... + def set_completer(__function: _Completer | None = ...) -> None: ... + def get_completer() -> _Completer | None: ... def get_completion_type() -> int: ... def get_begidx() -> int: ... def get_endidx() -> int: ... def set_completer_delims(__string: str) -> None: ... def get_completer_delims() -> str: ... - def set_completion_display_matches_hook(__function: _CompDispT = ...) -> None: ... + def set_completion_display_matches_hook(__function: _CompDisp | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/reprlib.pyi b/mypy/typeshed/stdlib/reprlib.pyi index 2095c0af69835..2d114a7c4f26c 100644 --- a/mypy/typeshed/stdlib/reprlib.pyi +++ b/mypy/typeshed/stdlib/reprlib.pyi @@ -2,6 +2,8 @@ from array import array from collections import deque from typing import Any, Callable +__all__ = ["Repr", "repr", "recursive_repr"] + _ReprFunc = Callable[[Any], str] def recursive_repr(fillvalue: str = ...) -> Callable[[_ReprFunc], _ReprFunc]: ... diff --git a/mypy/typeshed/stdlib/resource.pyi b/mypy/typeshed/stdlib/resource.pyi index 19a6f470b7755..f2e979ff89af4 100644 --- a/mypy/typeshed/stdlib/resource.pyi +++ b/mypy/typeshed/stdlib/resource.pyi @@ -1,7 +1,7 @@ import sys from _typeshed import structseq from typing import overload -from typing_extensions import final +from typing_extensions import Final, final if sys.platform != "win32": RLIMIT_AS: int @@ -29,6 +29,25 @@ if sys.platform != "win32": class struct_rusage( structseq[float], tuple[float, float, int, int, int, int, int, int, int, int, int, int, int, int, int, int] ): + if sys.version_info >= (3, 10): + __match_args__: Final = ( + "ru_utime", + "ru_stime", + "ru_maxrss", + "ru_ixrss", + "ru_idrss", + "ru_isrss", + "ru_minflt", + "ru_majflt", + "ru_nswap", + "ru_inblock", + "ru_oublock", + "ru_msgsnd", + "ru_msgrcv", + "ru_nsignals", + "ru_nvcsw", + "ru_nivcsw", + ) @property def ru_utime(self) -> float: ... @property @@ -61,6 +80,7 @@ if sys.platform != "win32": def ru_nvcsw(self) -> int: ... @property def ru_nivcsw(self) -> int: ... + def getpagesize() -> int: ... def getrlimit(__resource: int) -> tuple[int, int]: ... def getrusage(__who: int) -> struct_rusage: ... diff --git a/mypy/typeshed/stdlib/rlcompleter.pyi b/mypy/typeshed/stdlib/rlcompleter.pyi index f971c424213df..1840b7cfced78 100644 --- a/mypy/typeshed/stdlib/rlcompleter.pyi +++ b/mypy/typeshed/stdlib/rlcompleter.pyi @@ -1,5 +1,9 @@ from typing import Any +__all__ = ["Completer"] + class Completer: def __init__(self, namespace: dict[str, Any] | None = ...) -> None: ... def complete(self, text: str, state: int) -> str | None: ... + def attr_matches(self, text: str) -> list[str]: ... + def global_matches(self, text: str) -> list[str]: ... diff --git a/mypy/typeshed/stdlib/runpy.pyi b/mypy/typeshed/stdlib/runpy.pyi index 371fa9d07cf82..256f8dab14e93 100644 --- a/mypy/typeshed/stdlib/runpy.pyi +++ b/mypy/typeshed/stdlib/runpy.pyi @@ -2,18 +2,20 @@ from _typeshed import Self from types import ModuleType from typing import Any +__all__ = ["run_module", "run_path"] + class _TempModule: mod_name: str module: ModuleType def __init__(self, mod_name: str) -> None: ... def __enter__(self: Self) -> Self: ... - def __exit__(self, *args: Any) -> None: ... + def __exit__(self, *args: object) -> None: ... class _ModifiedArgv0: value: Any def __init__(self, value: Any) -> None: ... def __enter__(self) -> None: ... - def __exit__(self, *args: Any) -> None: ... + def __exit__(self, *args: object) -> None: ... def run_module( mod_name: str, init_globals: dict[str, Any] | None = ..., run_name: str | None = ..., alter_sys: bool = ... diff --git a/mypy/typeshed/stdlib/sched.pyi b/mypy/typeshed/stdlib/sched.pyi index 71aacc5c26103..dff781b0c1763 100644 --- a/mypy/typeshed/stdlib/sched.pyi +++ b/mypy/typeshed/stdlib/sched.pyi @@ -1,14 +1,30 @@ +import sys from typing import Any, Callable, NamedTuple -class Event(NamedTuple): - time: float - priority: Any - action: Callable[..., Any] - argument: tuple[Any, ...] - kwargs: dict[str, Any] +__all__ = ["scheduler"] + +if sys.version_info >= (3, 10): + class Event(NamedTuple): + time: float + priority: Any + sequence: int + action: Callable[..., Any] + argument: tuple[Any, ...] + kwargs: dict[str, Any] + +else: + class Event(NamedTuple): + time: float + priority: Any + action: Callable[..., Any] + argument: tuple[Any, ...] + kwargs: dict[str, Any] class scheduler: - def __init__(self, timefunc: Callable[[], float] = ..., delayfunc: Callable[[float], None] = ...) -> None: ... + timefunc: Callable[[], float] + delayfunc: Callable[[float], object] + + def __init__(self, timefunc: Callable[[], float] = ..., delayfunc: Callable[[float], object] = ...) -> None: ... def enterabs( self, time: float, diff --git a/mypy/typeshed/stdlib/secrets.pyi b/mypy/typeshed/stdlib/secrets.pyi index f57eef8492d7b..99b7c14ebafc7 100644 --- a/mypy/typeshed/stdlib/secrets.pyi +++ b/mypy/typeshed/stdlib/secrets.pyi @@ -3,6 +3,8 @@ from hmac import compare_digest as compare_digest from random import SystemRandom as SystemRandom from typing import TypeVar +__all__ = ["choice", "randbelow", "randbits", "SystemRandom", "token_bytes", "token_hex", "token_urlsafe", "compare_digest"] + _T = TypeVar("_T") def randbelow(exclusive_upper_bound: int) -> int: ... diff --git a/mypy/typeshed/stdlib/select.pyi b/mypy/typeshed/stdlib/select.pyi index e57504b5b447e..d4a3656e110e9 100644 --- a/mypy/typeshed/stdlib/select.pyi +++ b/mypy/typeshed/stdlib/select.pyi @@ -1,7 +1,8 @@ import sys from _typeshed import FileDescriptorLike, Self from types import TracebackType -from typing import Any, Iterable, Type +from typing import Any, Iterable +from typing_extensions import final if sys.platform != "win32": PIPE_BUF: int @@ -33,6 +34,7 @@ error = OSError if sys.platform != "linux" and sys.platform != "win32": # BSD only + @final class kevent: data: Any fflags: int @@ -50,6 +52,7 @@ if sys.platform != "linux" and sys.platform != "win32": udata: Any = ..., ) -> None: ... # BSD only + @final class kqueue: closed: bool def __init__(self) -> None: ... @@ -100,14 +103,15 @@ if sys.platform != "linux" and sys.platform != "win32": KQ_NOTE_WRITE: int if sys.platform == "linux": + @final class epoll: def __init__(self, sizehint: int = ..., flags: int = ...) -> None: ... def __enter__(self: Self) -> Self: ... def __exit__( self, - exc_type: Type[BaseException] | None = ..., - exc_val: BaseException | None = ..., - exc_tb: TracebackType | None = ..., + __exc_type: type[BaseException] | None = ..., + __exc_val: BaseException | None = ..., + __exc_tb: TracebackType | None = ..., ) -> None: ... def close(self) -> None: ... closed: bool diff --git a/mypy/typeshed/stdlib/selectors.pyi b/mypy/typeshed/stdlib/selectors.pyi index c3fe7ec47acef..23a94a29a74d2 100644 --- a/mypy/typeshed/stdlib/selectors.pyi +++ b/mypy/typeshed/stdlib/selectors.pyi @@ -27,7 +27,7 @@ class BaseSelector(metaclass=ABCMeta): @abstractmethod def get_map(self) -> Mapping[FileDescriptorLike, SelectorKey]: ... def __enter__(self: Self) -> Self: ... - def __exit__(self, *args: Any) -> None: ... + def __exit__(self, *args: object) -> None: ... class SelectSelector(BaseSelector): def register(self, fileobj: FileDescriptorLike, events: _EventMask, data: Any = ...) -> SelectorKey: ... diff --git a/mypy/typeshed/stdlib/shelve.pyi b/mypy/typeshed/stdlib/shelve.pyi index 90b2aafa4f034..2a211ab342082 100644 --- a/mypy/typeshed/stdlib/shelve.pyi +++ b/mypy/typeshed/stdlib/shelve.pyi @@ -1,7 +1,10 @@ from _typeshed import Self from collections.abc import Iterator, MutableMapping +from dbm import _TFlags from types import TracebackType -from typing import Type, TypeVar, overload +from typing import TypeVar, overload + +__all__ = ["Shelf", "BsdDbShelf", "DbfilenameShelf", "open"] _T = TypeVar("_T") _VT = TypeVar("_VT") @@ -19,9 +22,10 @@ class Shelf(MutableMapping[str, _VT]): def __getitem__(self, key: str) -> _VT: ... def __setitem__(self, key: str, value: _VT) -> None: ... def __delitem__(self, key: str) -> None: ... + def __contains__(self, key: str) -> bool: ... # type: ignore[override] def __enter__(self: Self) -> Self: ... def __exit__( - self, type: Type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None + self, type: type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None ) -> None: ... def close(self) -> None: ... def sync(self) -> None: ... @@ -34,6 +38,6 @@ class BsdDbShelf(Shelf[_VT]): def last(self) -> tuple[str, _VT]: ... class DbfilenameShelf(Shelf[_VT]): - def __init__(self, filename: str, flag: str = ..., protocol: int | None = ..., writeback: bool = ...) -> None: ... + def __init__(self, filename: str, flag: _TFlags = ..., protocol: int | None = ..., writeback: bool = ...) -> None: ... -def open(filename: str, flag: str = ..., protocol: int | None = ..., writeback: bool = ...) -> Shelf[object]: ... +def open(filename: str, flag: _TFlags = ..., protocol: int | None = ..., writeback: bool = ...) -> Shelf[object]: ... diff --git a/mypy/typeshed/stdlib/shlex.pyi b/mypy/typeshed/stdlib/shlex.pyi index dfe554b0a7732..6385011575a47 100644 --- a/mypy/typeshed/stdlib/shlex.pyi +++ b/mypy/typeshed/stdlib/shlex.pyi @@ -1,5 +1,11 @@ import sys -from typing import Any, Iterable, TextIO, TypeVar +from _typeshed import Self +from typing import Iterable, TextIO + +if sys.version_info >= (3, 8): + __all__ = ["shlex", "split", "quote", "join"] +else: + __all__ = ["shlex", "split", "quote"] def split(s: str, comments: bool = ..., posix: bool = ...) -> list[str]: ... @@ -8,8 +14,6 @@ if sys.version_info >= (3, 8): def quote(s: str) -> str: ... -_SLT = TypeVar("_SLT", bound=shlex) - class shlex(Iterable[str]): commenters: str wordchars: str @@ -18,14 +22,18 @@ class shlex(Iterable[str]): quotes: str escapedquotes: str whitespace_split: bool - infile: str + infile: str | None instream: TextIO source: str debug: int lineno: int token: str eof: str - punctuation_chars: str + if sys.version_info >= (3, 7): + @property + def punctuation_chars(self) -> str: ... + else: + punctuation_chars: str def __init__( self, instream: str | TextIO | None = ..., @@ -37,9 +45,8 @@ class shlex(Iterable[str]): def push_token(self, tok: str) -> None: ... def read_token(self) -> str: ... def sourcehook(self, newfile: str) -> tuple[str, TextIO]: ... - # TODO argument types - def push_source(self, newstream: Any, newfile: Any = ...) -> None: ... + def push_source(self, newstream: str | TextIO, newfile: str | None = ...) -> None: ... def pop_source(self) -> None: ... def error_leader(self, infile: str | None = ..., lineno: int | None = ...) -> None: ... - def __iter__(self: _SLT) -> _SLT: ... + def __iter__(self: Self) -> Self: ... def __next__(self) -> str: ... diff --git a/mypy/typeshed/stdlib/shutil.pyi b/mypy/typeshed/stdlib/shutil.pyi index f4c492caccaf0..5fa5f6669f1b1 100644 --- a/mypy/typeshed/stdlib/shutil.pyi +++ b/mypy/typeshed/stdlib/shutil.pyi @@ -1,9 +1,39 @@ import os import sys -from _typeshed import StrOrBytesPath, StrPath, SupportsRead, SupportsWrite -from typing import Any, AnyStr, Callable, Iterable, NamedTuple, Sequence, TypeVar, Union, overload - -_PathT = TypeVar("_PathT", str, os.PathLike[str]) +from _typeshed import BytesPath, StrOrBytesPath, StrPath, SupportsRead, SupportsWrite +from typing import Any, AnyStr, Callable, Iterable, NamedTuple, Sequence, TypeVar, overload + +__all__ = [ + "copyfileobj", + "copyfile", + "copymode", + "copystat", + "copy", + "copy2", + "copytree", + "move", + "rmtree", + "Error", + "SpecialFileError", + "ExecError", + "make_archive", + "get_archive_formats", + "register_archive_format", + "unregister_archive_format", + "get_unpack_formats", + "register_unpack_format", + "unregister_unpack_format", + "unpack_archive", + "ignore_patterns", + "chown", + "which", + "get_terminal_size", + "SameFileError", + "disk_usage", +] + +_StrOrBytesPathT = TypeVar("_StrOrBytesPathT", bound=StrOrBytesPath) +_StrPathT = TypeVar("_StrPathT", bound=StrPath) # Return value of some functions that may either return a path-like object that was passed in or # a string _PathReturn = Any @@ -16,11 +46,17 @@ class ReadError(OSError): ... class RegistryError(Exception): ... def copyfileobj(fsrc: SupportsRead[AnyStr], fdst: SupportsWrite[AnyStr], length: int = ...) -> None: ... -def copyfile(src: StrPath, dst: _PathT, *, follow_symlinks: bool = ...) -> _PathT: ... -def copymode(src: StrPath, dst: StrPath, *, follow_symlinks: bool = ...) -> None: ... -def copystat(src: StrPath, dst: StrPath, *, follow_symlinks: bool = ...) -> None: ... +def copyfile(src: StrOrBytesPath, dst: _StrOrBytesPathT, *, follow_symlinks: bool = ...) -> _StrOrBytesPathT: ... +def copymode(src: StrOrBytesPath, dst: StrOrBytesPath, *, follow_symlinks: bool = ...) -> None: ... +def copystat(src: StrOrBytesPath, dst: StrOrBytesPath, *, follow_symlinks: bool = ...) -> None: ... +@overload def copy(src: StrPath, dst: StrPath, *, follow_symlinks: bool = ...) -> _PathReturn: ... +@overload +def copy(src: BytesPath, dst: BytesPath, *, follow_symlinks: bool = ...) -> _PathReturn: ... +@overload def copy2(src: StrPath, dst: StrPath, *, follow_symlinks: bool = ...) -> _PathReturn: ... +@overload +def copy2(src: BytesPath, dst: BytesPath, *, follow_symlinks: bool = ...) -> _PathReturn: ... def ignore_patterns(*patterns: StrPath) -> Callable[[Any, list[str]], set[str]]: ... if sys.version_info >= (3, 8): @@ -44,10 +80,13 @@ else: ignore_dangling_symlinks: bool = ..., ) -> _PathReturn: ... -def rmtree(path: bytes | StrPath, ignore_errors: bool = ..., onerror: Callable[[Any, Any, Any], Any] | None = ...) -> None: ... +def rmtree(path: StrOrBytesPath, ignore_errors: bool = ..., onerror: Callable[[Any, Any, Any], Any] | None = ...) -> None: ... -_CopyFn = Union[Callable[[str, str], None], Callable[[StrPath, StrPath], None]] +_CopyFn = Callable[[str, str], None] | Callable[[StrPath, StrPath], None] +# N.B. shutil.move appears to take bytes arguments, however, +# this does not work when dst is (or is within) an existing directory. +# (#6832) if sys.version_info >= (3, 9): def move(src: StrPath, dst: StrPath, copy_function: _CopyFn = ...) -> _PathReturn: ... @@ -61,16 +100,27 @@ class _ntuple_diskusage(NamedTuple): free: int def disk_usage(path: int | StrOrBytesPath) -> _ntuple_diskusage: ... -def chown(path: StrPath, user: str | int | None = ..., group: str | int | None = ...) -> None: ... + +# While chown can be imported on Windows, it doesn't actually work; +# see https://bugs.python.org/issue33140. We keep it here because it's +# in __all__. +@overload +def chown(path: StrOrBytesPath, user: str | int, group: None = ...) -> None: ... +@overload +def chown(path: StrOrBytesPath, user: None = ..., *, group: str | int) -> None: ... +@overload +def chown(path: StrOrBytesPath, user: None, group: str | int) -> None: ... +@overload +def chown(path: StrOrBytesPath, user: str | int, group: str | int) -> None: ... if sys.version_info >= (3, 8): @overload - def which(cmd: StrPath, mode: int = ..., path: StrPath | None = ...) -> str | None: ... + def which(cmd: _StrPathT, mode: int = ..., path: StrPath | None = ...) -> str | _StrPathT | None: ... @overload def which(cmd: bytes, mode: int = ..., path: StrPath | None = ...) -> bytes | None: ... else: - def which(cmd: StrPath, mode: int = ..., path: StrPath | None = ...) -> str | None: ... + def which(cmd: _StrPathT, mode: int = ..., path: StrPath | None = ...) -> str | _StrPathT | None: ... def make_archive( base_name: str, @@ -84,11 +134,13 @@ def make_archive( logger: Any | None = ..., ) -> str: ... def get_archive_formats() -> list[tuple[str, str]]: ... +@overload def register_archive_format( - name: str, - function: Callable[..., Any], - extra_args: Sequence[tuple[str, Any] | list[Any]] | None = ..., - description: str = ..., + name: str, function: Callable[..., object], extra_args: Sequence[tuple[str, Any] | list[Any]], description: str = ... +) -> None: ... +@overload +def register_archive_format( + name: str, function: Callable[[str, str], object], extra_args: None = ..., description: str = ... ) -> None: ... def unregister_archive_format(name: str) -> None: ... @@ -99,8 +151,17 @@ else: # See http://bugs.python.org/issue30218 def unpack_archive(filename: str, extract_dir: StrPath | None = ..., format: str | None = ...) -> None: ... +@overload +def register_unpack_format( + name: str, + extensions: list[str], + function: Callable[..., object], + extra_args: Sequence[tuple[str, Any]], + description: str = ..., +) -> None: ... +@overload def register_unpack_format( - name: str, extensions: list[str], function: Any, extra_args: Sequence[tuple[str, Any]] | None = ..., description: str = ... + name: str, extensions: list[str], function: Callable[[str, str], object], extra_args: None = ..., description: str = ... ) -> None: ... def unregister_unpack_format(name: str) -> None: ... def get_unpack_formats() -> list[tuple[str, list[str], str]]: ... diff --git a/mypy/typeshed/stdlib/signal.pyi b/mypy/typeshed/stdlib/signal.pyi index 777391662aa36..2defe79959913 100644 --- a/mypy/typeshed/stdlib/signal.pyi +++ b/mypy/typeshed/stdlib/signal.pyi @@ -2,8 +2,8 @@ import sys from _typeshed import structseq from enum import IntEnum from types import FrameType -from typing import Any, Callable, Iterable, Optional, Union -from typing_extensions import final +from typing import Any, Callable, Iterable, Union +from typing_extensions import Final, final NSIG: int @@ -60,12 +60,18 @@ class Handlers(IntEnum): SIG_DFL: Handlers SIG_IGN: Handlers -_SIGNUM = Union[int, Signals] -_HANDLER = Union[Callable[[int, Optional[FrameType]], Any], int, Handlers, None] +_SIGNUM = int | Signals +_HANDLER = Union[Callable[[int, FrameType | None], Any], int, Handlers, None] -def default_int_handler(signum: int, frame: FrameType | None) -> None: ... -def getsignal(__signalnum: _SIGNUM) -> _HANDLER: ... -def signal(__signalnum: _SIGNUM, __handler: _HANDLER) -> _HANDLER: ... +def default_int_handler(__signalnum: int, __frame: FrameType | None) -> None: ... + +if sys.version_info >= (3, 10): # arguments changed in 3.10.2 + def getsignal(signalnum: _SIGNUM) -> _HANDLER: ... + def signal(signalnum: _SIGNUM, handler: _HANDLER) -> _HANDLER: ... + +else: + def getsignal(__signalnum: _SIGNUM) -> _HANDLER: ... + def signal(__signalnum: _SIGNUM, __handler: _HANDLER) -> _HANDLER: ... SIGABRT: Signals SIGEMT: Signals @@ -105,10 +111,12 @@ else: SIGWINCH: Signals SIGXCPU: Signals SIGXFSZ: Signals + class ItimerError(IOError): ... ITIMER_PROF: int ITIMER_REAL: int ITIMER_VIRTUAL: int + class Sigmasks(IntEnum): SIG_BLOCK: int SIG_UNBLOCK: int @@ -120,11 +128,18 @@ else: def getitimer(__which: int) -> tuple[float, float]: ... def pause() -> None: ... def pthread_kill(__thread_id: int, __signalnum: int) -> None: ... - def pthread_sigmask(__how: int, __mask: Iterable[int]) -> set[_SIGNUM]: ... + if sys.version_info >= (3, 10): # arguments changed in 3.10.2 + def pthread_sigmask(how: int, mask: Iterable[int]) -> set[_SIGNUM]: ... + else: + def pthread_sigmask(__how: int, __mask: Iterable[int]) -> set[_SIGNUM]: ... + def setitimer(__which: int, __seconds: float, __interval: float = ...) -> tuple[float, float]: ... def siginterrupt(__signalnum: int, __flag: bool) -> None: ... def sigpending() -> Any: ... - def sigwait(__sigset: Iterable[int]) -> _SIGNUM: ... + if sys.version_info >= (3, 10): # argument changed in 3.10.2 + def sigwait(sigset: Iterable[int]) -> _SIGNUM: ... + else: + def sigwait(__sigset: Iterable[int]) -> _SIGNUM: ... if sys.platform != "darwin": SIGCLD: Signals SIGPOLL: Signals @@ -133,6 +148,8 @@ else: SIGRTMIN: Signals @final class struct_siginfo(structseq[int], tuple[int, int, int, int, int, int, int]): + if sys.version_info >= (3, 10): + __match_args__: Final = ("si_signo", "si_code", "si_errno", "si_pid", "si_uid", "si_status", "si_band") @property def si_signo(self) -> int: ... @property @@ -147,6 +164,7 @@ else: def si_status(self) -> int: ... @property def si_band(self) -> int: ... + def sigtimedwait(sigset: Iterable[int], timeout: float) -> struct_siginfo | None: ... def sigwaitinfo(sigset: Iterable[int]) -> struct_siginfo: ... @@ -160,3 +178,7 @@ if sys.version_info >= (3, 7): else: def set_wakeup_fd(fd: int) -> int: ... + +if sys.version_info >= (3, 9): + if sys.platform == "linux": + def pidfd_send_signal(__pidfd: int, __sig: int, __siginfo: None = ..., __flags: int = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/smtpd.pyi b/mypy/typeshed/stdlib/smtpd.pyi index e5401552caaeb..037f62a8d6e1b 100644 --- a/mypy/typeshed/stdlib/smtpd.pyi +++ b/mypy/typeshed/stdlib/smtpd.pyi @@ -1,8 +1,14 @@ import asynchat import asyncore import socket +import sys from collections import defaultdict -from typing import Any, Type +from typing import Any + +if sys.version_info >= (3, 11): + __all__ = ["SMTPChannel", "SMTPServer", "DebuggingServer", "PureProxy"] +else: + __all__ = ["SMTPChannel", "SMTPServer", "DebuggingServer", "PureProxy", "MailmanProxy"] _Address = tuple[str, int] # (host, port) @@ -56,7 +62,7 @@ class SMTPChannel(asynchat.async_chat): def smtp_EXPN(self, arg: str) -> None: ... class SMTPServer(asyncore.dispatcher): - channel_class: Type[SMTPChannel] + channel_class: type[SMTPChannel] data_size_limit: int enable_SMTPUTF8: bool @@ -79,5 +85,6 @@ class DebuggingServer(SMTPServer): ... class PureProxy(SMTPServer): def process_message(self, peer: _Address, mailfrom: str, rcpttos: list[str], data: bytes | str) -> str | None: ... # type: ignore[override] -class MailmanProxy(PureProxy): - def process_message(self, peer: _Address, mailfrom: str, rcpttos: list[str], data: bytes | str) -> str | None: ... # type: ignore[override] +if sys.version_info < (3, 11): + class MailmanProxy(PureProxy): + def process_message(self, peer: _Address, mailfrom: str, rcpttos: list[str], data: bytes | str) -> str | None: ... # type: ignore[override] diff --git a/mypy/typeshed/stdlib/smtplib.pyi b/mypy/typeshed/stdlib/smtplib.pyi index 0a57f1f5d2de7..3136667dcd119 100644 --- a/mypy/typeshed/stdlib/smtplib.pyi +++ b/mypy/typeshed/stdlib/smtplib.pyi @@ -4,12 +4,46 @@ from email.message import Message as _Message from socket import socket from ssl import SSLContext from types import TracebackType -from typing import Any, Pattern, Protocol, Sequence, Type, Union, overload +from typing import Any, Pattern, Protocol, Sequence, overload + +if sys.version_info >= (3, 7): + __all__ = [ + "SMTPException", + "SMTPNotSupportedError", + "SMTPServerDisconnected", + "SMTPResponseException", + "SMTPSenderRefused", + "SMTPRecipientsRefused", + "SMTPDataError", + "SMTPConnectError", + "SMTPHeloError", + "SMTPAuthenticationError", + "quoteaddr", + "quotedata", + "SMTP", + "SMTP_SSL", + ] +else: + __all__ = [ + "SMTPException", + "SMTPServerDisconnected", + "SMTPResponseException", + "SMTPSenderRefused", + "SMTPRecipientsRefused", + "SMTPDataError", + "SMTPConnectError", + "SMTPHeloError", + "SMTPAuthenticationError", + "quoteaddr", + "quotedata", + "SMTP", + "SMTP_SSL", + ] _Reply = tuple[int, bytes] _SendErrs = dict[str, _Reply] # Should match source_address for socket.create_connection -_SourceAddress = tuple[Union[bytearray, bytes, str], int] +_SourceAddress = tuple[bytearray | bytes | str, int] SMTP_PORT: int SMTP_SSL_PORT: int @@ -79,7 +113,7 @@ class SMTP: ) -> None: ... def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_value: BaseException | None, tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_value: BaseException | None, tb: TracebackType | None ) -> None: ... def set_debuglevel(self, debuglevel: int) -> None: ... def connect(self, host: str = ..., port: int = ..., source_address: _SourceAddress | None = ...) -> _Reply: ... diff --git a/mypy/typeshed/stdlib/sndhdr.pyi b/mypy/typeshed/stdlib/sndhdr.pyi index 84d6441a83b10..f4d487607fbb2 100644 --- a/mypy/typeshed/stdlib/sndhdr.pyi +++ b/mypy/typeshed/stdlib/sndhdr.pyi @@ -1,6 +1,8 @@ from _typeshed import StrOrBytesPath from typing import NamedTuple +__all__ = ["what", "whathdr"] + class SndHeaders(NamedTuple): filetype: str framerate: int diff --git a/mypy/typeshed/stdlib/socket.pyi b/mypy/typeshed/stdlib/socket.pyi index 430fef4ff3449..7801940f8564b 100644 --- a/mypy/typeshed/stdlib/socket.pyi +++ b/mypy/typeshed/stdlib/socket.pyi @@ -3,7 +3,7 @@ from _typeshed import ReadableBuffer, Self, WriteableBuffer from collections.abc import Iterable from enum import IntEnum, IntFlag from io import RawIOBase -from typing import Any, BinaryIO, TextIO, TypeVar, overload +from typing import Any, BinaryIO, TextIO, overload from typing_extensions import Literal # Ideally, we'd just do "from _socket import *". Unfortunately, socket @@ -12,8 +12,6 @@ from typing_extensions import Literal import _socket from _socket import ( _FD, - CMSG_LEN as CMSG_LEN, - CMSG_SPACE as CMSG_SPACE, EAI_ADDRFAMILY as EAI_ADDRFAMILY, EAI_AGAIN as EAI_AGAIN, EAI_BADFLAGS as EAI_BADFLAGS, @@ -213,7 +211,7 @@ from _socket import ( if sys.version_info >= (3, 7): from _socket import close as close if sys.platform != "win32": - from _socket import sethostname as sethostname + from _socket import CMSG_LEN as CMSG_LEN, CMSG_SPACE as CMSG_SPACE, sethostname as sethostname if sys.platform != "win32" or sys.version_info >= (3, 8): from _socket import if_indextoname as if_indextoname, if_nameindex as if_nameindex, if_nametoindex as if_nametoindex if sys.platform == "linux": @@ -366,6 +364,8 @@ if sys.platform == "linux" and sys.version_info >= (3, 9): SO_J1939_PROMISC as SO_J1939_PROMISC, SO_J1939_SEND_PRIO as SO_J1939_SEND_PRIO, ) +if sys.platform == "linux" and sys.version_info >= (3, 10): + from _socket import IPPROTO_MPTCP as IPPROTO_MPTCP if sys.platform == "win32": from _socket import ( RCVALL_IPLEVEL as RCVALL_IPLEVEL, @@ -378,8 +378,6 @@ if sys.platform == "win32": SIO_RCVALL as SIO_RCVALL, ) -_T = TypeVar("_T") - # Re-exported from errno EBADF: int EAGAIN: int @@ -544,7 +542,7 @@ class socket(_socket.socket): ) -> None: ... def __enter__(self: Self) -> Self: ... def __exit__(self, *args: object) -> None: ... - def dup(self: _T) -> _T: ... # noqa: F811 + def dup(self: Self) -> Self: ... # noqa: F811 def accept(self) -> tuple[socket, _RetAddress]: ... # Note that the makefile's documented windows-specific behavior is not represented # mode strings with duplicates are intentionally excluded @@ -621,10 +619,5 @@ if sys.version_info >= (3, 8): # the 5th tuple item is an address def getaddrinfo( - host: bytearray | bytes | str | None, - port: str | int | None, - family: int = ..., - type: int = ..., - proto: int = ..., - flags: int = ..., + host: bytes | str | None, port: str | int | None, family: int = ..., type: int = ..., proto: int = ..., flags: int = ... ) -> list[tuple[AddressFamily, SocketKind, int, str, tuple[str, int] | tuple[str, int, int, int]]]: ... diff --git a/mypy/typeshed/stdlib/socketserver.pyi b/mypy/typeshed/stdlib/socketserver.pyi index c663e73bef50f..9bdd8ccfe31f7 100644 --- a/mypy/typeshed/stdlib/socketserver.pyi +++ b/mypy/typeshed/stdlib/socketserver.pyi @@ -2,22 +2,60 @@ import sys import types from _typeshed import Self from socket import socket as _socket -from typing import Any, BinaryIO, Callable, ClassVar, Type, TypeVar, Union +from typing import Any, BinaryIO, Callable, ClassVar, Union + +if sys.platform == "win32": + __all__ = [ + "BaseServer", + "TCPServer", + "UDPServer", + "ThreadingUDPServer", + "ThreadingTCPServer", + "BaseRequestHandler", + "StreamRequestHandler", + "DatagramRequestHandler", + "ThreadingMixIn", + ] +else: + __all__ = [ + "BaseServer", + "TCPServer", + "UDPServer", + "ThreadingUDPServer", + "ThreadingTCPServer", + "BaseRequestHandler", + "StreamRequestHandler", + "DatagramRequestHandler", + "ThreadingMixIn", + "ForkingUDPServer", + "ForkingTCPServer", + "ForkingMixIn", + "UnixStreamServer", + "UnixDatagramServer", + "ThreadingUnixStreamServer", + "ThreadingUnixDatagramServer", + ] -_T = TypeVar("_T") _RequestType = Union[_socket, tuple[bytes, _socket]] _AddressType = Union[tuple[str, int], str] +# This can possibly be generic at some point: class BaseServer: address_family: int - RequestHandlerClass: Callable[..., BaseRequestHandler] server_address: tuple[str, int] socket: _socket allow_reuse_address: bool request_queue_size: int socket_type: int timeout: float | None - def __init__(self, server_address: Any, RequestHandlerClass: Callable[..., BaseRequestHandler]) -> None: ... + def __init__( + self: Self, server_address: Any, RequestHandlerClass: Callable[[Any, Any, Self], BaseRequestHandler] + ) -> None: ... + # It is not actually a `@property`, but we need a `Self` type: + @property + def RequestHandlerClass(self: Self) -> Callable[[Any, Any, Self], BaseRequestHandler]: ... + @RequestHandlerClass.setter + def RequestHandlerClass(self: Self, val: Callable[[Any, Any, Self], BaseRequestHandler]) -> None: ... def fileno(self) -> int: ... def handle_request(self) -> None: ... def serve_forever(self, poll_interval: float = ...) -> None: ... @@ -33,56 +71,41 @@ class BaseServer: def verify_request(self, request: _RequestType, client_address: _AddressType) -> bool: ... def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: types.TracebackType | None + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: types.TracebackType | None ) -> None: ... def service_actions(self) -> None: ... def shutdown_request(self, request: _RequestType) -> None: ... # undocumented def close_request(self, request: _RequestType) -> None: ... # undocumented class TCPServer(BaseServer): + allow_reuse_port: bool + request_queue_size: int def __init__( - self, + self: Self, server_address: tuple[str, int], - RequestHandlerClass: Callable[..., BaseRequestHandler], + RequestHandlerClass: Callable[[Any, Any, Self], BaseRequestHandler], bind_and_activate: bool = ..., ) -> None: ... def get_request(self) -> tuple[_socket, Any]: ... - def finish_request(self, request: _RequestType, client_address: _AddressType) -> None: ... - def handle_error(self, request: _RequestType, client_address: _AddressType) -> None: ... - def process_request(self, request: _RequestType, client_address: _AddressType) -> None: ... - def verify_request(self, request: _RequestType, client_address: _AddressType) -> bool: ... - def shutdown_request(self, request: _RequestType) -> None: ... # undocumented - def close_request(self, request: _RequestType) -> None: ... # undocumented class UDPServer(BaseServer): max_packet_size: ClassVar[int] - def __init__( - self, - server_address: tuple[str, int], - RequestHandlerClass: Callable[..., BaseRequestHandler], - bind_and_activate: bool = ..., - ) -> None: ... def get_request(self) -> tuple[tuple[bytes, _socket], Any]: ... - def finish_request(self, request: _RequestType, client_address: _AddressType) -> None: ... - def handle_error(self, request: _RequestType, client_address: _AddressType) -> None: ... - def process_request(self, request: _RequestType, client_address: _AddressType) -> None: ... - def verify_request(self, request: _RequestType, client_address: _AddressType) -> bool: ... - def shutdown_request(self, request: _RequestType) -> None: ... # undocumented - def close_request(self, request: _RequestType) -> None: ... # undocumented if sys.platform != "win32": class UnixStreamServer(BaseServer): def __init__( - self, + self: Self, server_address: str | bytes, - RequestHandlerClass: Callable[..., BaseRequestHandler], + RequestHandlerClass: Callable[[Any, Any, Self], BaseRequestHandler], bind_and_activate: bool = ..., ) -> None: ... + class UnixDatagramServer(BaseServer): def __init__( - self, + self: Self, server_address: str | bytes, - RequestHandlerClass: Callable[..., BaseRequestHandler], + RequestHandlerClass: Callable[[Any, Any, Self], BaseRequestHandler], bind_and_activate: bool = ..., ) -> None: ... diff --git a/mypy/typeshed/stdlib/spwd.pyi b/mypy/typeshed/stdlib/spwd.pyi index 7a62d62523f52..27b1061e1b0e9 100644 --- a/mypy/typeshed/stdlib/spwd.pyi +++ b/mypy/typeshed/stdlib/spwd.pyi @@ -1,11 +1,23 @@ import sys from _typeshed import structseq from typing import Any -from typing_extensions import final +from typing_extensions import Final, final if sys.platform != "win32": @final class struct_spwd(structseq[Any], tuple[str, str, int, int, int, int, int, int, int]): + if sys.version_info >= (3, 10): + __match_args__: Final = ( + "sp_namp", + "sp_pwdp", + "sp_lstchg", + "sp_min", + "sp_max", + "sp_warn", + "sp_inact", + "sp_expire", + "sp_flag", + ) @property def sp_namp(self) -> str: ... @property @@ -24,5 +36,6 @@ if sys.platform != "win32": def sp_expire(self) -> int: ... @property def sp_flag(self) -> int: ... + def getspall() -> list[struct_spwd]: ... def getspnam(__arg: str) -> struct_spwd: ... diff --git a/mypy/typeshed/stdlib/sqlite3/__init__.pyi b/mypy/typeshed/stdlib/sqlite3/__init__.pyi index d5d20d67b58ea..d747be90fd0a5 100644 --- a/mypy/typeshed/stdlib/sqlite3/__init__.pyi +++ b/mypy/typeshed/stdlib/sqlite3/__init__.pyi @@ -1 +1 @@ -from sqlite3.dbapi2 import * # noqa: F403 +from sqlite3.dbapi2 import * diff --git a/mypy/typeshed/stdlib/sqlite3/dbapi2.pyi b/mypy/typeshed/stdlib/sqlite3/dbapi2.pyi index ea9098940d4b2..05e5a176d8ff2 100644 --- a/mypy/typeshed/stdlib/sqlite3/dbapi2.pyi +++ b/mypy/typeshed/stdlib/sqlite3/dbapi2.pyi @@ -1,7 +1,9 @@ import sys from _typeshed import Self, StrOrBytesPath from datetime import date, datetime, time -from typing import Any, Callable, Generator, Iterable, Iterator, Protocol, Type, TypeVar +from types import TracebackType +from typing import Any, Callable, Generator, Iterable, Iterator, Protocol, TypeVar +from typing_extensions import Literal, final _T = TypeVar("_T") @@ -94,7 +96,7 @@ if sys.version_info >= (3, 7): detect_types: int = ..., isolation_level: str | None = ..., check_same_thread: bool = ..., - factory: Type[Connection] | None = ..., + factory: type[Connection] | None = ..., cached_statements: int = ..., uri: bool = ..., ) -> Connection: ... @@ -106,14 +108,14 @@ else: detect_types: int = ..., isolation_level: str | None = ..., check_same_thread: bool = ..., - factory: Type[Connection] | None = ..., + factory: type[Connection] | None = ..., cached_statements: int = ..., uri: bool = ..., ) -> Connection: ... def enable_callback_tracebacks(__enable: bool) -> None: ... def enable_shared_cache(enable: int) -> None: ... -def register_adapter(__type: Type[_T], __caster: Callable[[_T], int | float | str | bytes]) -> None: ... +def register_adapter(__type: type[_T], __caster: Callable[[_T], int | float | str | bytes]) -> None: ... def register_converter(__name: str, __converter: Callable[[bytes], Any]) -> None: ... if sys.version_info < (3, 8): @@ -151,6 +153,7 @@ class Connection: def create_function(self, name: str, narg: int, func: Any, *, deterministic: bool = ...) -> None: ... else: def create_function(self, name: str, num_params: int, func: Any) -> None: ... + def cursor(self, cursorClass: type | None = ...) -> Cursor: ... def execute(self, sql: str, parameters: Iterable[Any] = ...) -> Cursor: ... # TODO: please check in executemany() if seq_of_parameters type is possible like this @@ -178,9 +181,12 @@ class Connection: name: str = ..., sleep: float = ..., ) -> None: ... + def __call__(self, *args: Any, **kwargs: Any) -> Any: ... def __enter__(self: Self) -> Self: ... - def __exit__(self, t: type | None, exc: BaseException | None, tb: Any | None) -> None: ... + def __exit__( + self, __type: type[BaseException] | None, __value: BaseException | None, __traceback: TracebackType | None + ) -> Literal[False]: ... class Cursor(Iterator[Any]): arraysize: Any @@ -202,7 +208,7 @@ class Cursor(Iterator[Any]): def fetchone(self) -> Any: ... def setinputsizes(self, __sizes: object) -> None: ... # does nothing def setoutputsize(self, __size: object, __column: object = ...) -> None: ... # does nothing - def __iter__(self) -> Cursor: ... + def __iter__(self: Self) -> Self: ... def __next__(self) -> Any: ... class DataError(DatabaseError): ... @@ -221,6 +227,7 @@ class OperationalError(DatabaseError): ... OptimizedUnicode = str +@final class PrepareProtocol: def __init__(self, *args: Any, **kwargs: Any) -> None: ... @@ -229,18 +236,19 @@ class ProgrammingError(DatabaseError): ... class Row: def __init__(self, *args: Any, **kwargs: Any) -> None: ... def keys(self): ... - def __eq__(self, other): ... - def __ge__(self, other): ... - def __getitem__(self, index): ... - def __gt__(self, other): ... + def __eq__(self, __other): ... + def __ge__(self, __other): ... + def __getitem__(self, __index): ... + def __gt__(self, __other): ... def __hash__(self): ... def __iter__(self): ... - def __le__(self, other): ... + def __le__(self, __other): ... def __len__(self): ... - def __lt__(self, other): ... - def __ne__(self, other): ... + def __lt__(self, __other): ... + def __ne__(self, __other): ... if sys.version_info < (3, 8): + @final class Statement: def __init__(self, *args, **kwargs): ... diff --git a/mypy/typeshed/stdlib/sre_constants.pyi b/mypy/typeshed/stdlib/sre_constants.pyi index df7e1a28007b8..00644994fe3ef 100644 --- a/mypy/typeshed/stdlib/sre_constants.pyi +++ b/mypy/typeshed/stdlib/sre_constants.pyi @@ -1,4 +1,5 @@ import sys +from _typeshed import Self from typing import Any MAXGROUPS: int @@ -15,7 +16,7 @@ class error(Exception): class _NamedIntConstant(int): name: Any - def __new__(cls, value: int, name: str) -> _NamedIntConstant: ... + def __new__(cls: type[Self], value: int, name: str) -> Self: ... MAXREPEAT: _NamedIntConstant OPCODES: list[_NamedIntConstant] diff --git a/mypy/typeshed/stdlib/sre_parse.pyi b/mypy/typeshed/stdlib/sre_parse.pyi index c4de55bcbf7ec..05e71c255967d 100644 --- a/mypy/typeshed/stdlib/sre_parse.pyi +++ b/mypy/typeshed/stdlib/sre_parse.pyi @@ -1,7 +1,7 @@ import sys from sre_constants import * from sre_constants import _NamedIntConstant as _NIC, error as _Error -from typing import Any, Iterable, Match, Optional, Pattern as _Pattern, Union, overload +from typing import Any, Iterable, Match, Pattern as _Pattern, overload SPECIAL_CHARS: str REPEAT_CHARS: str @@ -37,11 +37,11 @@ if sys.version_info >= (3, 8): else: Pattern = _State -_OpSubpatternType = tuple[Optional[int], int, int, SubPattern] +_OpSubpatternType = tuple[int | None, int, int, SubPattern] _OpGroupRefExistsType = tuple[int, SubPattern, SubPattern] _OpInType = list[tuple[_NIC, int]] _OpBranchType = tuple[None, list[SubPattern]] -_AvType = Union[_OpInType, _OpBranchType, Iterable[SubPattern], _OpGroupRefExistsType, _OpSubpatternType] +_AvType = _OpInType | _OpBranchType | Iterable[SubPattern] | _OpGroupRefExistsType | _OpSubpatternType _CodeType = tuple[_NIC, _AvType] class SubPattern: @@ -54,6 +54,7 @@ class SubPattern: else: pattern: Pattern def __init__(self, pattern: Pattern, data: list[_CodeType] | None = ...) -> None: ... + def dump(self, level: int = ...) -> None: ... def __len__(self) -> int: ... def __delitem__(self, index: int | slice) -> None: ... @@ -77,6 +78,7 @@ class Tokenizer: def getuntil(self, terminator: str, name: str) -> str: ... else: def getuntil(self, terminator: str) -> str: ... + @property def pos(self) -> int: ... def tell(self) -> int: ... @@ -85,8 +87,8 @@ class Tokenizer: def fix_flags(src: str | bytes, flags: int) -> int: ... -_TemplateType = tuple[list[tuple[int, int]], list[Optional[str]]] -_TemplateByteType = tuple[list[tuple[int, int]], list[Optional[bytes]]] +_TemplateType = tuple[list[tuple[int, int]], list[str | None]] +_TemplateByteType = tuple[list[tuple[int, int]], list[bytes | None]] if sys.version_info >= (3, 8): def parse(str: str, flags: int = ..., state: State | None = ...) -> SubPattern: ... @overload diff --git a/mypy/typeshed/stdlib/ssl.pyi b/mypy/typeshed/stdlib/ssl.pyi index cdb727285647b..b7fe6914db0ed 100644 --- a/mypy/typeshed/stdlib/ssl.pyi +++ b/mypy/typeshed/stdlib/ssl.pyi @@ -2,17 +2,17 @@ import enum import socket import sys from _typeshed import ReadableBuffer, Self, StrOrBytesPath, WriteableBuffer -from typing import Any, Callable, ClassVar, Iterable, NamedTuple, Optional, Type, Union, overload -from typing_extensions import Literal, TypedDict +from typing import Any, Callable, Iterable, NamedTuple, Union, overload +from typing_extensions import Literal, TypedDict, final _PCTRTT = tuple[tuple[str, str], ...] _PCTRTTT = tuple[_PCTRTT, ...] -_PeerCertRetDictType = dict[str, Union[str, _PCTRTTT, _PCTRTT]] -_PeerCertRetType = Union[_PeerCertRetDictType, bytes, None] -_EnumRetType = list[tuple[bytes, str, Union[set[str], bool]]] -_PasswordType = Union[Callable[[], Union[str, bytes]], str, bytes] +_PeerCertRetDictType = dict[str, str | _PCTRTTT | _PCTRTT] +_PeerCertRetType = _PeerCertRetDictType | bytes | None +_EnumRetType = list[tuple[bytes, str, set[str] | bool]] +_PasswordType = Union[Callable[[], str | bytes], str, bytes] -_SrvnmeCbType = Callable[[Union[SSLSocket, SSLObject], Optional[str], SSLSocket], Optional[int]] +_SrvnmeCbType = Callable[[SSLSocket | SSLObject, str | None, SSLSocket], int | None] class _Cipher(TypedDict): aead: bool @@ -294,9 +294,9 @@ class _ASN1Object(NamedTuple): longname: str oid: str @classmethod - def fromnid(cls: Type[Self], nid: int) -> Self: ... + def fromnid(cls: type[Self], nid: int) -> Self: ... @classmethod - def fromname(cls: Type[Self], name: str) -> Self: ... + def fromname(cls: type[Self], name: str) -> Self: ... class Purpose(_ASN1Object, enum.Enum): SERVER_AUTH: _ASN1Object @@ -307,7 +307,8 @@ class SSLSocket(socket.socket): server_side: bool server_hostname: str | None session: SSLSession | None - session_reused: bool | None + @property + def session_reused(self) -> bool | None: ... if sys.version_info >= (3, 7): def __init__(self, *args: Any, **kwargs: Any) -> None: ... else: @@ -332,6 +333,7 @@ class SSLSocket(socket.socket): _context: SSLContext | None = ..., _session: Any | None = ..., ) -> None: ... + def connect(self, addr: socket._Address | bytes) -> None: ... def connect_ex(self, addr: socket._Address | bytes) -> int: ... def recv(self, buflen: int = ..., flags: int = ...) -> bytes: ... @@ -391,12 +393,15 @@ class SSLContext: maximum_version: TLSVersion minimum_version: TLSVersion sni_callback: Callable[[SSLObject, str, SSLContext], None | int] | None - sslobject_class: ClassVar[Type[SSLObject]] - sslsocket_class: ClassVar[Type[SSLSocket]] + # The following two attributes have class-level defaults. + # However, the docs explicitly state that it's OK to override these attributes on instances, + # so making these ClassVars wouldn't be appropriate + sslobject_class: type[SSLObject] + sslsocket_class: type[SSLSocket] if sys.version_info >= (3, 8): keylog_filename: str post_handshake_auth: bool - def __new__(cls, protocol: int = ..., *args: Any, **kwargs: Any) -> SSLContext: ... + def __new__(cls: type[Self], protocol: int = ..., *args: Any, **kwargs: Any) -> Self: ... def __init__(self, protocol: int = ...) -> None: ... def cert_store_stats(self) -> dict[str, int]: ... def load_cert_chain( @@ -416,6 +421,7 @@ class SSLContext: def set_servername_callback(self, server_name_callback: _SrvnmeCbType | None) -> None: ... else: def set_servername_callback(self, __method: _SrvnmeCbType | None) -> None: ... + def load_dh_params(self, __path: str) -> None: ... def set_ecdh_curve(self, __name: str) -> None: ... def wrap_socket( @@ -439,14 +445,18 @@ class SSLContext: class SSLObject: context: SSLContext - server_side: bool - server_hostname: str | None + @property + def server_side(self) -> bool: ... + @property + def server_hostname(self) -> str | None: ... session: SSLSession | None - session_reused: bool + @property + def session_reused(self) -> bool: ... if sys.version_info >= (3, 7): def __init__(self, *args: Any, **kwargs: Any) -> None: ... else: def __init__(self, sslobj: Any, owner: SSLSocket | SSLObject | None = ..., session: Any | None = ...) -> None: ... + def read(self, len: int = ..., buffer: bytearray | None = ...) -> bytes: ... def write(self, data: bytes) -> int: ... @overload @@ -468,6 +478,7 @@ class SSLObject: if sys.version_info >= (3, 8): def verify_client_post_handshake(self) -> None: ... +@final class MemoryBIO: pending: int eof: bool @@ -475,6 +486,7 @@ class MemoryBIO: def write(self, __buf: bytes) -> int: ... def write_eof(self) -> None: ... +@final class SSLSession: id: bytes time: int diff --git a/mypy/typeshed/stdlib/statistics.pyi b/mypy/typeshed/stdlib/statistics.pyi index 908d6adaf45df..446a778794f16 100644 --- a/mypy/typeshed/stdlib/statistics.pyi +++ b/mypy/typeshed/stdlib/statistics.pyi @@ -1,12 +1,71 @@ import sys -from _typeshed import SupportsRichComparisonT +from _typeshed import Self, SupportsRichComparisonT from decimal import Decimal from fractions import Fraction -from typing import Any, Hashable, Iterable, NamedTuple, Sequence, SupportsFloat, Type, TypeVar, Union +from typing import Any, Hashable, Iterable, NamedTuple, Sequence, SupportsFloat, TypeVar +from typing_extensions import Literal + +if sys.version_info >= (3, 10): + __all__ = [ + "NormalDist", + "StatisticsError", + "correlation", + "covariance", + "fmean", + "geometric_mean", + "harmonic_mean", + "linear_regression", + "mean", + "median", + "median_grouped", + "median_high", + "median_low", + "mode", + "multimode", + "pstdev", + "pvariance", + "quantiles", + "stdev", + "variance", + ] +elif sys.version_info >= (3, 8): + __all__ = [ + "NormalDist", + "StatisticsError", + "fmean", + "geometric_mean", + "harmonic_mean", + "mean", + "median", + "median_grouped", + "median_high", + "median_low", + "mode", + "multimode", + "pstdev", + "pvariance", + "quantiles", + "stdev", + "variance", + ] +else: + __all__ = [ + "StatisticsError", + "pstdev", + "pvariance", + "stdev", + "variance", + "median", + "median_low", + "median_high", + "median_grouped", + "mean", + "mode", + "harmonic_mean", + ] -_T = TypeVar("_T") # Most functions in this module accept homogeneous collections of one of these types -_Number = Union[float, Decimal, Fraction] +_Number = float | Decimal | Fraction _NumberT = TypeVar("_NumberT", float, Decimal, Fraction) # Used in mode, multimode @@ -14,8 +73,13 @@ _HashableT = TypeVar("_HashableT", bound=Hashable) class StatisticsError(ValueError): ... -if sys.version_info >= (3, 8): +if sys.version_info >= (3, 11): + def fmean(data: Iterable[SupportsFloat], weights: Iterable[SupportsFloat] | None = ...) -> float: ... + +elif sys.version_info >= (3, 8): def fmean(data: Iterable[SupportsFloat]) -> float: ... + +if sys.version_info >= (3, 8): def geometric_mean(data: Iterable[SupportsFloat]) -> float: ... def mean(data: Iterable[_NumberT]) -> _NumberT: ... @@ -39,7 +103,9 @@ def pstdev(data: Iterable[_NumberT], mu: _NumberT | None = ...) -> _NumberT: ... def pvariance(data: Iterable[_NumberT], mu: _NumberT | None = ...) -> _NumberT: ... if sys.version_info >= (3, 8): - def quantiles(data: Iterable[_NumberT], *, n: int = ..., method: str = ...) -> list[_NumberT]: ... + def quantiles( + data: Iterable[_NumberT], *, n: int = ..., method: Literal["inclusive", "exclusive"] = ... + ) -> list[_NumberT]: ... def stdev(data: Iterable[_NumberT], xbar: _NumberT | None = ...) -> _NumberT: ... def variance(data: Iterable[_NumberT], xbar: _NumberT | None = ...) -> _NumberT: ... @@ -58,7 +124,7 @@ if sys.version_info >= (3, 8): @property def variance(self) -> float: ... @classmethod - def from_samples(cls: Type[_T], data: Iterable[SupportsFloat]) -> _T: ... + def from_samples(cls: type[Self], data: Iterable[SupportsFloat]) -> Self: ... def samples(self, n: int, *, seed: Any | None = ...) -> list[float]: ... def pdf(self, x: float) -> float: ... def cdf(self, x: float) -> float: ... @@ -67,6 +133,8 @@ if sys.version_info >= (3, 8): def quantiles(self, n: int = ...) -> list[float]: ... if sys.version_info >= (3, 9): def zscore(self, x: float) -> float: ... + + def __eq__(self, x2: object) -> bool: ... def __add__(self, x2: float | NormalDist) -> NormalDist: ... def __sub__(self, x2: float | NormalDist) -> NormalDist: ... def __mul__(self, x2: float) -> NormalDist: ... @@ -81,7 +149,15 @@ if sys.version_info >= (3, 8): if sys.version_info >= (3, 10): def correlation(__x: Sequence[_Number], __y: Sequence[_Number]) -> float: ... def covariance(__x: Sequence[_Number], __y: Sequence[_Number]) -> float: ... + class LinearRegression(NamedTuple): slope: float intercept: float + +if sys.version_info >= (3, 11): + def linear_regression( + __regressor: Sequence[_Number], __dependent_variable: Sequence[_Number], *, proportional: bool = ... + ) -> LinearRegression: ... + +elif sys.version_info >= (3, 10): def linear_regression(__regressor: Sequence[_Number], __dependent_variable: Sequence[_Number]) -> LinearRegression: ... diff --git a/mypy/typeshed/stdlib/string.pyi b/mypy/typeshed/stdlib/string.pyi index 374d59959ac9f..535f38545132c 100644 --- a/mypy/typeshed/stdlib/string.pyi +++ b/mypy/typeshed/stdlib/string.pyi @@ -7,6 +7,21 @@ if sys.version_info >= (3, 8): else: from typing import Pattern +__all__ = [ + "ascii_letters", + "ascii_lowercase", + "ascii_uppercase", + "capwords", + "digits", + "hexdigits", + "octdigits", + "printable", + "punctuation", + "whitespace", + "Formatter", + "Template", +] + ascii_letters: str ascii_lowercase: str ascii_uppercase: str diff --git a/mypy/typeshed/stdlib/struct.pyi b/mypy/typeshed/stdlib/struct.pyi index 47af629732593..1f6c45a23c0a6 100644 --- a/mypy/typeshed/stdlib/struct.pyi +++ b/mypy/typeshed/stdlib/struct.pyi @@ -2,6 +2,8 @@ import sys from _typeshed import ReadableBuffer, WriteableBuffer from typing import Any, Iterator +__all__ = ["calcsize", "pack", "pack_into", "unpack", "unpack_from", "iter_unpack", "Struct", "error"] + class error(Exception): ... def pack(fmt: str | bytes, *v: Any) -> bytes: ... diff --git a/mypy/typeshed/stdlib/subprocess.pyi b/mypy/typeshed/stdlib/subprocess.pyi index fce517745ee61..ced2e708f8ffd 100644 --- a/mypy/typeshed/stdlib/subprocess.pyi +++ b/mypy/typeshed/stdlib/subprocess.pyi @@ -1,12 +1,93 @@ import sys from _typeshed import Self, StrOrBytesPath from types import TracebackType -from typing import IO, Any, AnyStr, Callable, Generic, Iterable, Mapping, Sequence, Type, TypeVar, Union, overload +from typing import IO, Any, AnyStr, Callable, Generic, Iterable, Mapping, Sequence, TypeVar, overload from typing_extensions import Literal if sys.version_info >= (3, 9): from types import GenericAlias +if sys.platform == "win32": + if sys.version_info >= (3, 7): + __all__ = [ + "Popen", + "PIPE", + "STDOUT", + "call", + "check_call", + "getstatusoutput", + "getoutput", + "check_output", + "run", + "CalledProcessError", + "DEVNULL", + "SubprocessError", + "TimeoutExpired", + "CompletedProcess", + "CREATE_NEW_CONSOLE", + "CREATE_NEW_PROCESS_GROUP", + "STD_INPUT_HANDLE", + "STD_OUTPUT_HANDLE", + "STD_ERROR_HANDLE", + "SW_HIDE", + "STARTF_USESTDHANDLES", + "STARTF_USESHOWWINDOW", + "STARTUPINFO", + "ABOVE_NORMAL_PRIORITY_CLASS", + "BELOW_NORMAL_PRIORITY_CLASS", + "HIGH_PRIORITY_CLASS", + "IDLE_PRIORITY_CLASS", + "NORMAL_PRIORITY_CLASS", + "REALTIME_PRIORITY_CLASS", + "CREATE_NO_WINDOW", + "DETACHED_PROCESS", + "CREATE_DEFAULT_ERROR_MODE", + "CREATE_BREAKAWAY_FROM_JOB", + ] + else: + __all__ = [ + "Popen", + "PIPE", + "STDOUT", + "call", + "check_call", + "getstatusoutput", + "getoutput", + "check_output", + "run", + "CalledProcessError", + "DEVNULL", + "SubprocessError", + "TimeoutExpired", + "CompletedProcess", + "CREATE_NEW_CONSOLE", + "CREATE_NEW_PROCESS_GROUP", + "STD_INPUT_HANDLE", + "STD_OUTPUT_HANDLE", + "STD_ERROR_HANDLE", + "SW_HIDE", + "STARTF_USESTDHANDLES", + "STARTF_USESHOWWINDOW", + "STARTUPINFO", + ] +else: + __all__ = [ + "Popen", + "PIPE", + "STDOUT", + "call", + "check_call", + "getstatusoutput", + "getoutput", + "check_output", + "run", + "CalledProcessError", + "DEVNULL", + "SubprocessError", + "TimeoutExpired", + "CompletedProcess", + ] + # We prefer to annotate inputs to methods (eg subprocess.check_call) with these # union types. # For outputs we use laborious literal based overloads to try to determine @@ -21,18 +102,18 @@ if sys.version_info >= (3, 9): # reveal_type(x) # bytes, based on the overloads # except TimeoutError as e: # reveal_type(e.cmd) # Any, but morally is _CMD -_FILE = Union[None, int, IO[Any]] -_TXT = Union[bytes, str] +_FILE = None | int | IO[Any] +_TXT = bytes | str if sys.version_info >= (3, 8): - _CMD = Union[StrOrBytesPath, Sequence[StrOrBytesPath]] + _CMD = StrOrBytesPath | Sequence[StrOrBytesPath] else: # Python 3.6 doesn't support _CMD being a single PathLike. # See: https://bugs.python.org/issue31961 - _CMD = Union[_TXT, Sequence[StrOrBytesPath]] + _CMD = _TXT | Sequence[StrOrBytesPath] if sys.platform == "win32": _ENV = Mapping[str, str] else: - _ENV = Union[Mapping[bytes, StrOrBytesPath], Mapping[str, StrOrBytesPath]] + _ENV = Mapping[bytes, StrOrBytesPath] | Mapping[str, StrOrBytesPath] _T = TypeVar("_T") @@ -991,6 +1072,7 @@ class Popen(Generic[AnyStr]): encoding: str | None = ..., errors: str | None = ..., ) -> Popen[Any]: ... + def poll(self) -> int | None: ... if sys.version_info >= (3, 7): def wait(self, timeout: float | None = ...) -> int: ... @@ -1008,7 +1090,7 @@ class Popen(Generic[AnyStr]): def kill(self) -> None: ... def __enter__(self: Self) -> Self: ... def __exit__( - self, type: Type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None + self, exc_type: type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None ) -> None: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... @@ -1043,22 +1125,27 @@ if sys.platform == "win32": wShowWindow: int if sys.version_info >= (3, 7): lpAttributeList: Mapping[str, Any] - STD_INPUT_HANDLE: Any - STD_OUTPUT_HANDLE: Any - STD_ERROR_HANDLE: Any - SW_HIDE: int - STARTF_USESTDHANDLES: int - STARTF_USESHOWWINDOW: int - CREATE_NEW_CONSOLE: int - CREATE_NEW_PROCESS_GROUP: int + from _winapi import ( + CREATE_NEW_CONSOLE as CREATE_NEW_CONSOLE, + CREATE_NEW_PROCESS_GROUP as CREATE_NEW_PROCESS_GROUP, + STARTF_USESHOWWINDOW as STARTF_USESHOWWINDOW, + STARTF_USESTDHANDLES as STARTF_USESTDHANDLES, + STD_ERROR_HANDLE as STD_ERROR_HANDLE, + STD_INPUT_HANDLE as STD_INPUT_HANDLE, + STD_OUTPUT_HANDLE as STD_OUTPUT_HANDLE, + SW_HIDE as SW_HIDE, + ) + if sys.version_info >= (3, 7): - ABOVE_NORMAL_PRIORITY_CLASS: int - BELOW_NORMAL_PRIORITY_CLASS: int - HIGH_PRIORITY_CLASS: int - IDLE_PRIORITY_CLASS: int - NORMAL_PRIORITY_CLASS: int - REALTIME_PRIORITY_CLASS: int - CREATE_NO_WINDOW: int - DETACHED_PROCESS: int - CREATE_DEFAULT_ERROR_MODE: int - CREATE_BREAKAWAY_FROM_JOB: int + from _winapi import ( + ABOVE_NORMAL_PRIORITY_CLASS as ABOVE_NORMAL_PRIORITY_CLASS, + BELOW_NORMAL_PRIORITY_CLASS as BELOW_NORMAL_PRIORITY_CLASS, + CREATE_BREAKAWAY_FROM_JOB as CREATE_BREAKAWAY_FROM_JOB, + CREATE_DEFAULT_ERROR_MODE as CREATE_DEFAULT_ERROR_MODE, + CREATE_NO_WINDOW as CREATE_NO_WINDOW, + DETACHED_PROCESS as DETACHED_PROCESS, + HIGH_PRIORITY_CLASS as HIGH_PRIORITY_CLASS, + IDLE_PRIORITY_CLASS as IDLE_PRIORITY_CLASS, + NORMAL_PRIORITY_CLASS as NORMAL_PRIORITY_CLASS, + REALTIME_PRIORITY_CLASS as REALTIME_PRIORITY_CLASS, + ) diff --git a/mypy/typeshed/stdlib/sunau.pyi b/mypy/typeshed/stdlib/sunau.pyi index 8393136aa795f..73aa8999caa10 100644 --- a/mypy/typeshed/stdlib/sunau.pyi +++ b/mypy/typeshed/stdlib/sunau.pyi @@ -1,8 +1,9 @@ import sys from _typeshed import Self -from typing import IO, Any, NamedTuple, NoReturn, Union +from typing import IO, Any, NamedTuple, NoReturn, overload +from typing_extensions import Literal -_File = Union[str, IO[bytes]] +_File = str | IO[bytes] class Error(Exception): ... @@ -32,7 +33,7 @@ class _sunau_params(NamedTuple): class Au_read: def __init__(self, f: _File) -> None: ... def __enter__(self: Self) -> Self: ... - def __exit__(self, *args: Any) -> None: ... + def __exit__(self, *args: object) -> None: ... def getfp(self) -> IO[bytes] | None: ... def rewind(self) -> None: ... def close(self) -> None: ... @@ -52,7 +53,7 @@ class Au_read: class Au_write: def __init__(self, f: _File) -> None: ... def __enter__(self: Self) -> Self: ... - def __exit__(self, *args: Any) -> None: ... + def __exit__(self, *args: object) -> None: ... def setnchannels(self, nchannels: int) -> None: ... def getnchannels(self) -> int: ... def setsampwidth(self, sampwidth: int) -> None: ... @@ -72,7 +73,11 @@ class Au_write: def writeframes(self, data: bytes) -> None: ... def close(self) -> None: ... -# Returns a Au_read if mode is rb and Au_write if mode is wb +@overload +def open(f: _File, mode: Literal["r", "rb"]) -> Au_read: ... +@overload +def open(f: _File, mode: Literal["w", "wb"]) -> Au_write: ... +@overload def open(f: _File, mode: str | None = ...) -> Any: ... if sys.version_info < (3, 9): diff --git a/mypy/typeshed/stdlib/symtable.pyi b/mypy/typeshed/stdlib/symtable.pyi index bc25a4c4639b1..91e95270901ed 100644 --- a/mypy/typeshed/stdlib/symtable.pyi +++ b/mypy/typeshed/stdlib/symtable.pyi @@ -1,6 +1,8 @@ import sys from typing import Any, Sequence +__all__ = ["symtable", "SymbolTable", "Class", "Function", "Symbol"] + def symtable(code: str, filename: str, compile_type: str) -> SymbolTable: ... class SymbolTable: @@ -37,6 +39,7 @@ class Symbol: def is_nonlocal(self) -> bool: ... else: def __init__(self, name: str, flags: int, namespaces: Sequence[SymbolTable] | None = ...) -> None: ... + def get_name(self) -> str: ... def is_referenced(self) -> bool: ... def is_parameter(self) -> bool: ... diff --git a/mypy/typeshed/stdlib/sys.pyi b/mypy/typeshed/stdlib/sys.pyi index cb1545711d69b..4fca35a2c82d9 100644 --- a/mypy/typeshed/stdlib/sys.pyi +++ b/mypy/typeshed/stdlib/sys.pyi @@ -5,13 +5,13 @@ from importlib.abc import PathEntryFinder from importlib.machinery import ModuleSpec from io import TextIOWrapper from types import FrameType, ModuleType, TracebackType -from typing import Any, AsyncGenerator, Callable, NoReturn, Optional, Protocol, Sequence, TextIO, Type, TypeVar, Union, overload +from typing import Any, AsyncGenerator, Callable, Coroutine, NoReturn, Protocol, Sequence, TextIO, TypeVar, Union, overload from typing_extensions import Literal, final _T = TypeVar("_T") # The following type alias are stub-only and do not exist during runtime -_ExcInfo = tuple[Type[BaseException], BaseException, TracebackType] +_ExcInfo = tuple[type[BaseException], BaseException, TracebackType] _OptExcInfo = Union[_ExcInfo, tuple[None, None, None]] # Intentionally omits one deprecated and one optional method of `importlib.abc.MetaPathFinder` @@ -31,12 +31,12 @@ if sys.platform == "win32": dllhandle: int dont_write_bytecode: bool displayhook: Callable[[object], Any] -excepthook: Callable[[Type[BaseException], BaseException, TracebackType | None], Any] +excepthook: Callable[[type[BaseException], BaseException, TracebackType | None], Any] exec_prefix: str executable: str -float_repr_style: str +float_repr_style: Literal["short", "legacy"] hexversion: int -last_type: Type[BaseException] | None +last_type: type[BaseException] | None last_value: BaseException | None last_traceback: TracebackType | None maxsize: int @@ -46,7 +46,7 @@ modules: dict[str, ModuleType] if sys.version_info >= (3, 10): orig_argv: list[str] path: list[str] -path_hooks: list[Any] # TODO precise type; function, path to finder +path_hooks: list[Callable[[str], PathEntryFinder]] path_importer_cache: dict[str, PathEntryFinder | None] platform: str if sys.version_info >= (3, 9): @@ -74,49 +74,105 @@ if sys.platform == "win32": winver: str _xoptions: dict[Any, Any] +# Type alias used as a mixin for structseq classes that cannot be instantiated at runtime +# This can't be represented in the type system, so we just use `structseq[Any]` +_uninstantiable_structseq = structseq[Any] + flags: _flags -class _flags: - debug: int - division_warning: int - inspect: int - interactive: int - optimize: int - dont_write_bytecode: int - no_user_site: int - no_site: int - ignore_environment: int - verbose: int - bytes_warning: int - quiet: int - hash_randomization: int +if sys.version_info >= (3, 10): + _FlagTuple = tuple[int, int, int, int, int, int, int, int, int, int, int, int, int, bool, int, int] +elif sys.version_info >= (3, 7): + _FlagTuple = tuple[int, int, int, int, int, int, int, int, int, int, int, int, int, bool, int] +else: + _FlagTuple = tuple[int, int, int, int, int, int, int, int, int, int, int, int, int] + +@final +class _flags(_uninstantiable_structseq, _FlagTuple): + @property + def debug(self) -> int: ... + @property + def inspect(self) -> int: ... + @property + def interactive(self) -> int: ... + @property + def optimize(self) -> int: ... + @property + def dont_write_bytecode(self) -> int: ... + @property + def no_user_site(self) -> int: ... + @property + def no_site(self) -> int: ... + @property + def ignore_environment(self) -> int: ... + @property + def verbose(self) -> int: ... + @property + def bytes_warning(self) -> int: ... + @property + def quiet(self) -> int: ... + @property + def hash_randomization(self) -> int: ... + @property + def isolated(self) -> int: ... if sys.version_info >= (3, 7): - dev_mode: int - utf8_mode: int + @property + def dev_mode(self) -> bool: ... + @property + def utf8_mode(self) -> int: ... + if sys.version_info >= (3, 10): + @property + def warn_default_encoding(self) -> int: ... # undocumented float_info: _float_info -class _float_info: - epsilon: float # DBL_EPSILON - dig: int # DBL_DIG - mant_dig: int # DBL_MANT_DIG - max: float # DBL_MAX - max_exp: int # DBL_MAX_EXP - max_10_exp: int # DBL_MAX_10_EXP - min: float # DBL_MIN - min_exp: int # DBL_MIN_EXP - min_10_exp: int # DBL_MIN_10_EXP - radix: int # FLT_RADIX - rounds: int # FLT_ROUNDS +@final +class _float_info(structseq[float], tuple[float, int, int, float, int, int, int, int, float, int, int]): + @property + def max(self) -> float: ... # DBL_MAX + @property + def max_exp(self) -> int: ... # DBL_MAX_EXP + @property + def max_10_exp(self) -> int: ... # DBL_MAX_10_EXP + @property + def min(self) -> float: ... # DBL_MIN + @property + def min_exp(self) -> int: ... # DBL_MIN_EXP + @property + def min_10_exp(self) -> int: ... # DBL_MIN_10_EXP + @property + def dig(self) -> int: ... # DBL_DIG + @property + def mant_dig(self) -> int: ... # DBL_MANT_DIG + @property + def epsilon(self) -> float: ... # DBL_EPSILON + @property + def radix(self) -> int: ... # FLT_RADIX + @property + def rounds(self) -> int: ... # FLT_ROUNDS hash_info: _hash_info -class _hash_info: - width: int - modulus: int - inf: int - nan: int - imag: int +@final +class _hash_info(structseq[Any | int], tuple[int, int, int, int, int, str, int, int, int]): + @property + def width(self) -> int: ... + @property + def modulus(self) -> int: ... + @property + def inf(self) -> int: ... + @property + def nan(self) -> int: ... + @property + def imag(self) -> int: ... + @property + def algorithm(self) -> str: ... + @property + def hash_bits(self) -> int: ... + @property + def seed_bits(self) -> int: ... + @property + def cutoff(self) -> int: ... # undocumented implementation: _implementation @@ -125,16 +181,22 @@ class _implementation: version: _version_info hexversion: int cache_tag: str - _multiarch: str + # Define __getattr__, as the documentation states: + # > sys.implementation may contain additional attributes specific to the Python implementation. + # > These non-standard attributes must start with an underscore, and are not described here. + def __getattr__(self, name: str) -> Any: ... int_info: _int_info -class _int_info: - bits_per_digit: int - sizeof_digit: int +@final +class _int_info(structseq[int], tuple[int, int]): + @property + def bits_per_digit(self) -> int: ... + @property + def sizeof_digit(self) -> int: ... @final -class _version_info(structseq[Any | int], tuple[int, int, int, str, int]): +class _version_info(_uninstantiable_structseq, tuple[int, int, int, str, int]): @property def major(self) -> int: ... @property @@ -153,8 +215,8 @@ def _clear_type_cache() -> None: ... def _current_frames() -> dict[int, FrameType]: ... def _getframe(__depth: int = ...) -> FrameType: ... def _debugmallocstats() -> None: ... -def __displayhook__(value: object) -> None: ... -def __excepthook__(type_: Type[BaseException], value: BaseException, traceback: TracebackType | None) -> None: ... +def __displayhook__(__value: object) -> None: ... +def __excepthook__(__exctype: type[BaseException], __value: BaseException, __traceback: TracebackType | None) -> None: ... def exc_info() -> _OptExcInfo: ... # sys.exit() accepts an optional argument of anything printable @@ -180,24 +242,36 @@ _ProfileFunc = Callable[[FrameType, str, Any], Any] def getprofile() -> _ProfileFunc | None: ... def setprofile(profilefunc: _ProfileFunc | None) -> None: ... -_TraceFunc = Callable[[FrameType, str, Any], Optional[Callable[[FrameType, str, Any], Any]]] +_TraceFunc = Callable[[FrameType, str, Any], Callable[[FrameType, str, Any], Any] | None] def gettrace() -> _TraceFunc | None: ... def settrace(tracefunc: _TraceFunc | None) -> None: ... -class _WinVersion(tuple[int, int, int, int, str, int, int, int, int, tuple[int, int, int]]): - major: int - minor: int - build: int - platform: int - service_pack: str - service_pack_minor: int - service_pack_major: int - suite_mast: int - product_type: int - platform_version: tuple[int, int, int] - if sys.platform == "win32": + # A tuple of length 5, even though it has more than 5 attributes. + @final + class _WinVersion(_uninstantiable_structseq, tuple[int, int, int, int, str]): + @property + def major(self) -> int: ... + @property + def minor(self) -> int: ... + @property + def build(self) -> int: ... + @property + def platform(self) -> int: ... + @property + def service_pack(self) -> str: ... + @property + def service_pack_minor(self) -> int: ... + @property + def service_pack_major(self) -> int: ... + @property + def suite_mask(self) -> int: ... + @property + def product_type(self) -> int: ... + @property + def platform_version(self) -> tuple[int, int, int]: ... + def getwindowsversion() -> _WinVersion: ... def intern(__string: str) -> str: ... @@ -218,27 +292,44 @@ if sys.version_info < (3, 9): def getcheckinterval() -> int: ... # deprecated def setcheckinterval(__n: int) -> None: ... # deprecated +if sys.version_info < (3, 9): + # An 11-tuple or None + def callstats() -> tuple[int, int, int, int, int, int, int, int, int, int, int] | None: ... + if sys.version_info >= (3, 8): - # not exported by sys + # Doesn't exist at runtime, but exported in the stubs so pytest etc. can annotate their code more easily. class UnraisableHookArgs: - exc_type: Type[BaseException] + exc_type: type[BaseException] exc_value: BaseException | None exc_traceback: TracebackType | None err_msg: str | None object: _object | None unraisablehook: Callable[[UnraisableHookArgs], Any] + def __unraisablehook__(__unraisable: UnraisableHookArgs) -> Any: ... def addaudithook(hook: Callable[[str, tuple[Any, ...]], Any]) -> None: ... def audit(__event: str, *args: Any) -> None: ... -_AsyncgenHook = Optional[Callable[[AsyncGenerator[Any, Any]], None]] +_AsyncgenHook = Callable[[AsyncGenerator[Any, Any]], None] | None -class _asyncgen_hooks(tuple[_AsyncgenHook, _AsyncgenHook]): - firstiter: _AsyncgenHook - finalizer: _AsyncgenHook +@final +class _asyncgen_hooks(structseq[_AsyncgenHook], tuple[_AsyncgenHook, _AsyncgenHook]): + @property + def firstiter(self) -> _AsyncgenHook: ... + @property + def finalizer(self) -> _AsyncgenHook: ... def get_asyncgen_hooks() -> _asyncgen_hooks: ... def set_asyncgen_hooks(firstiter: _AsyncgenHook = ..., finalizer: _AsyncgenHook = ...) -> None: ... +if sys.version_info >= (3, 6): + if sys.platform == "win32": + def _enablelegacywindowsfsencoding() -> None: ... + if sys.version_info >= (3, 7): def get_coroutine_origin_tracking_depth() -> int: ... def set_coroutine_origin_tracking_depth(depth: int) -> None: ... + +if sys.version_info < (3, 8): + _CoroWrapper = Callable[[Coroutine[Any, Any, Any]], Any] + def set_coroutine_wrapper(__wrapper: _CoroWrapper) -> None: ... + def get_coroutine_wrapper() -> _CoroWrapper: ... diff --git a/mypy/typeshed/stdlib/sysconfig.pyi b/mypy/typeshed/stdlib/sysconfig.pyi index 17077144f6e98..13c40b927f4ef 100644 --- a/mypy/typeshed/stdlib/sysconfig.pyi +++ b/mypy/typeshed/stdlib/sysconfig.pyi @@ -1,5 +1,19 @@ from typing import IO, Any, overload +__all__ = [ + "get_config_h_filename", + "get_config_var", + "get_config_vars", + "get_makefile_filename", + "get_path", + "get_path_names", + "get_paths", + "get_platform", + "get_python_version", + "get_scheme_names", + "parse_config_h", +] + def get_config_var(name: str) -> str | None: ... @overload def get_config_vars() -> dict[str, Any]: ... diff --git a/mypy/typeshed/stdlib/tabnanny.pyi b/mypy/typeshed/stdlib/tabnanny.pyi index 4c7be83b05117..020100031c14c 100644 --- a/mypy/typeshed/stdlib/tabnanny.pyi +++ b/mypy/typeshed/stdlib/tabnanny.pyi @@ -1,6 +1,8 @@ from _typeshed import StrOrBytesPath from typing import Iterable +__all__ = ["check", "NannyNag", "process_tokens"] + verbose: int filename_only: int diff --git a/mypy/typeshed/stdlib/tarfile.pyi b/mypy/typeshed/stdlib/tarfile.pyi index 4931a6f0e6795..2837c46e1d217 100644 --- a/mypy/typeshed/stdlib/tarfile.pyi +++ b/mypy/typeshed/stdlib/tarfile.pyi @@ -2,13 +2,30 @@ import bz2 import io import sys from _typeshed import Self, StrOrBytesPath, StrPath +from builtins import type as Type # alias to avoid name clashes with fields named "type" from collections.abc import Callable, Iterable, Iterator, Mapping from gzip import _ReadableFileobj as _GzipReadableFileobj, _WritableFileobj as _GzipWritableFileobj from types import TracebackType -from typing import IO, Protocol, Type, TypeVar, overload +from typing import IO, Protocol, overload from typing_extensions import Literal -_TF = TypeVar("_TF", bound=TarFile) +__all__ = [ + "TarFile", + "TarInfo", + "is_tarfile", + "TarError", + "ReadError", + "CompressionError", + "StreamError", + "ExtractError", + "HeaderError", + "ENCODING", + "USTAR_FORMAT", + "GNU_FORMAT", + "PAX_FORMAT", + "DEFAULT_FORMAT", + "open", +] class _Fileobj(Protocol): def read(self, __size: int) -> bytes: ... @@ -78,7 +95,7 @@ def open( bufsize: int = ..., *, format: int | None = ..., - tarinfo: Type[TarInfo] | None = ..., + tarinfo: type[TarInfo] | None = ..., dereference: bool | None = ..., ignore_zeros: bool | None = ..., encoding: str | None = ..., @@ -100,12 +117,12 @@ class TarFile: mode: Literal["r", "a", "w", "x"] fileobj: _Fileobj | None format: int | None - tarinfo: Type[TarInfo] + tarinfo: type[TarInfo] dereference: bool | None ignore_zeros: bool | None encoding: str | None errors: str - fileobject: Type[ExFileObject] + fileobject: type[ExFileObject] pax_headers: Mapping[str, str] | None debug: int | None errorlevel: int | None @@ -116,7 +133,7 @@ class TarFile: mode: Literal["r", "a", "w", "x"] = ..., fileobj: _Fileobj | None = ..., format: int | None = ..., - tarinfo: Type[TarInfo] | None = ..., + tarinfo: type[TarInfo] | None = ..., dereference: bool | None = ..., ignore_zeros: bool | None = ..., encoding: str | None = ..., @@ -128,19 +145,19 @@ class TarFile: ) -> None: ... def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, type: type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None ) -> None: ... def __iter__(self) -> Iterator[TarInfo]: ... @classmethod def open( - cls: Type[_TF], + cls: type[Self], name: StrOrBytesPath | None = ..., mode: str = ..., fileobj: IO[bytes] | None = ..., # depends on mode bufsize: int = ..., *, format: int | None = ..., - tarinfo: Type[TarInfo] | None = ..., + tarinfo: type[TarInfo] | None = ..., dereference: bool | None = ..., ignore_zeros: bool | None = ..., encoding: str | None = ..., @@ -148,113 +165,113 @@ class TarFile: pax_headers: Mapping[str, str] | None = ..., debug: int | None = ..., errorlevel: int | None = ..., - ) -> _TF: ... + ) -> Self: ... @classmethod def taropen( - cls: Type[_TF], + cls: type[Self], name: StrOrBytesPath | None, mode: Literal["r", "a", "w", "x"] = ..., fileobj: _Fileobj | None = ..., *, compresslevel: int = ..., format: int | None = ..., - tarinfo: Type[TarInfo] | None = ..., + tarinfo: type[TarInfo] | None = ..., dereference: bool | None = ..., ignore_zeros: bool | None = ..., encoding: str | None = ..., pax_headers: Mapping[str, str] | None = ..., debug: int | None = ..., errorlevel: int | None = ..., - ) -> _TF: ... + ) -> Self: ... @overload @classmethod def gzopen( - cls: Type[_TF], + cls: type[Self], name: StrOrBytesPath | None, mode: Literal["r"] = ..., fileobj: _GzipReadableFileobj | None = ..., compresslevel: int = ..., *, format: int | None = ..., - tarinfo: Type[TarInfo] | None = ..., + tarinfo: type[TarInfo] | None = ..., dereference: bool | None = ..., ignore_zeros: bool | None = ..., encoding: str | None = ..., pax_headers: Mapping[str, str] | None = ..., debug: int | None = ..., errorlevel: int | None = ..., - ) -> _TF: ... + ) -> Self: ... @overload @classmethod def gzopen( - cls: Type[_TF], + cls: type[Self], name: StrOrBytesPath | None, mode: Literal["w", "x"], fileobj: _GzipWritableFileobj | None = ..., compresslevel: int = ..., *, format: int | None = ..., - tarinfo: Type[TarInfo] | None = ..., + tarinfo: type[TarInfo] | None = ..., dereference: bool | None = ..., ignore_zeros: bool | None = ..., encoding: str | None = ..., pax_headers: Mapping[str, str] | None = ..., debug: int | None = ..., errorlevel: int | None = ..., - ) -> _TF: ... + ) -> Self: ... @overload @classmethod def bz2open( - cls: Type[_TF], + cls: type[Self], name: StrOrBytesPath | None, mode: Literal["w", "x"], fileobj: _Bz2WritableFileobj | None = ..., compresslevel: int = ..., *, format: int | None = ..., - tarinfo: Type[TarInfo] | None = ..., + tarinfo: type[TarInfo] | None = ..., dereference: bool | None = ..., ignore_zeros: bool | None = ..., encoding: str | None = ..., pax_headers: Mapping[str, str] | None = ..., debug: int | None = ..., errorlevel: int | None = ..., - ) -> _TF: ... + ) -> Self: ... @overload @classmethod def bz2open( - cls: Type[_TF], + cls: type[Self], name: StrOrBytesPath | None, mode: Literal["r"] = ..., fileobj: _Bz2ReadableFileobj | None = ..., compresslevel: int = ..., *, format: int | None = ..., - tarinfo: Type[TarInfo] | None = ..., + tarinfo: type[TarInfo] | None = ..., dereference: bool | None = ..., ignore_zeros: bool | None = ..., encoding: str | None = ..., pax_headers: Mapping[str, str] | None = ..., debug: int | None = ..., errorlevel: int | None = ..., - ) -> _TF: ... + ) -> Self: ... @classmethod def xzopen( - cls: Type[_TF], + cls: type[Self], name: StrOrBytesPath | None, mode: Literal["r", "w", "x"] = ..., fileobj: IO[bytes] | None = ..., preset: int | None = ..., *, format: int | None = ..., - tarinfo: Type[TarInfo] | None = ..., + tarinfo: type[TarInfo] | None = ..., dereference: bool | None = ..., ignore_zeros: bool | None = ..., encoding: str | None = ..., pax_headers: Mapping[str, str] | None = ..., debug: int | None = ..., errorlevel: int | None = ..., - ) -> _TF: ... + ) -> Self: ... def getmember(self, name: str) -> TarInfo: ... def getmembers(self) -> _list[TarInfo]: ... def getnames(self) -> _list[str]: ... @@ -298,6 +315,7 @@ class TarFile: *, filter: Callable[[TarInfo], TarInfo | None] | None = ..., ) -> None: ... + def addfile(self, tarinfo: TarInfo, fileobj: IO[bytes] | None = ...) -> None: ... def gettarinfo(self, name: str | None = ..., arcname: str | None = ..., fileobj: IO[bytes] | None = ...) -> TarInfo: ... def close(self) -> None: ... @@ -340,9 +358,9 @@ class TarInfo: pax_headers: Mapping[str, str] def __init__(self, name: str = ...) -> None: ... @classmethod - def frombuf(cls, buf: bytes, encoding: str, errors: str) -> TarInfo: ... + def frombuf(cls: Type[Self], buf: bytes, encoding: str, errors: str) -> Self: ... @classmethod - def fromtarfile(cls, tarfile: TarFile) -> TarInfo: ... + def fromtarfile(cls: Type[Self], tarfile: TarFile) -> Self: ... @property def linkpath(self) -> str: ... @linkpath.setter diff --git a/mypy/typeshed/stdlib/telnetlib.pyi b/mypy/typeshed/stdlib/telnetlib.pyi index cf00856d93326..359be6e497813 100644 --- a/mypy/typeshed/stdlib/telnetlib.pyi +++ b/mypy/typeshed/stdlib/telnetlib.pyi @@ -1,7 +1,10 @@ import socket from _typeshed import Self +from types import TracebackType from typing import Any, Callable, Match, Pattern, Sequence +__all__ = ["Telnet"] + DEBUGLEVEL: int TELNET_PORT: int @@ -111,4 +114,6 @@ class Telnet: self, list: Sequence[Pattern[bytes] | bytes], timeout: float | None = ... ) -> tuple[int, Match[bytes] | None, bytes]: ... def __enter__(self: Self) -> Self: ... - def __exit__(self, type: Any, value: Any, traceback: Any) -> None: ... + def __exit__( + self, type: type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None + ) -> None: ... diff --git a/mypy/typeshed/stdlib/tempfile.pyi b/mypy/typeshed/stdlib/tempfile.pyi index 4aec26175a483..19a4dbee2ee7e 100644 --- a/mypy/typeshed/stdlib/tempfile.pyi +++ b/mypy/typeshed/stdlib/tempfile.pyi @@ -2,18 +2,34 @@ import os import sys from _typeshed import Self from types import TracebackType -from typing import IO, Any, AnyStr, Generic, Iterable, Iterator, Type, Union, overload +from typing import IO, Any, AnyStr, Generic, Iterable, Iterator, overload from typing_extensions import Literal if sys.version_info >= (3, 9): from types import GenericAlias +__all__ = [ + "NamedTemporaryFile", + "TemporaryFile", + "SpooledTemporaryFile", + "TemporaryDirectory", + "mkstemp", + "mkdtemp", + "mktemp", + "TMP_MAX", + "gettempprefix", + "tempdir", + "gettempdir", + "gettempprefixb", + "gettempdirb", +] + # global variables TMP_MAX: int tempdir: str | None template: str -_DirT = Union[AnyStr, os.PathLike[AnyStr]] +_DirT = AnyStr | os.PathLike[AnyStr] if sys.version_info >= (3, 8): @overload @@ -169,7 +185,7 @@ class _TemporaryFileWrapper(Generic[AnyStr], IO[AnyStr]): delete: bool def __init__(self, file: IO[AnyStr], name: str, delete: bool = ...) -> None: ... def __enter__(self: Self) -> Self: ... - def __exit__(self, exc: Type[BaseException] | None, value: BaseException | None, tb: TracebackType | None) -> bool | None: ... + def __exit__(self, exc: type[BaseException] | None, value: BaseException | None, tb: TracebackType | None) -> None: ... def __getattr__(self, name: str) -> Any: ... def close(self) -> None: ... # These methods don't exist directly on this object, but @@ -290,11 +306,10 @@ class SpooledTemporaryFile(IO[AnyStr]): prefix: str | None = ..., dir: str | None = ..., ) -> None: ... + def rollover(self) -> None: ... def __enter__(self: Self) -> Self: ... - def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None - ) -> bool | None: ... + def __exit__(self, exc: type[BaseException] | None, value: BaseException | None, tb: TracebackType | None) -> None: ... # These methods are copied from the abstract methods of IO, because # SpooledTemporaryFile implements IO. # See also https://github.com/python/typeshed/pull/2452#issuecomment-420657918. @@ -307,7 +322,7 @@ class SpooledTemporaryFile(IO[AnyStr]): def readlines(self, hint: int = ...) -> list[AnyStr]: ... def seek(self, offset: int, whence: int = ...) -> int: ... def tell(self) -> int: ... - def truncate(self, size: int | None = ...) -> int: ... + def truncate(self, size: int | None = ...) -> None: ... # type: ignore[override] def write(self, s: AnyStr) -> int: ... def writelines(self, iterable: Iterable[AnyStr]) -> None: ... def __iter__(self) -> Iterator[AnyStr]: ... @@ -343,11 +358,10 @@ class TemporaryDirectory(Generic[AnyStr]): def __init__(self: TemporaryDirectory[str], suffix: None = ..., prefix: None = ..., dir: None = ...) -> None: ... @overload def __init__(self, suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., dir: _DirT[AnyStr] | None = ...) -> None: ... + def cleanup(self) -> None: ... def __enter__(self) -> AnyStr: ... - def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None - ) -> None: ... + def __exit__(self, exc: type[BaseException] | None, value: BaseException | None, tb: TracebackType | None) -> None: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... diff --git a/mypy/typeshed/stdlib/termios.pyi b/mypy/typeshed/stdlib/termios.pyi index 7142df15715d0..c6a90df31b591 100644 --- a/mypy/typeshed/stdlib/termios.pyi +++ b/mypy/typeshed/stdlib/termios.pyi @@ -1,9 +1,9 @@ import sys from _typeshed import FileDescriptorLike -from typing import Any, Union +from typing import Any if sys.platform != "win32": - _Attr = list[Union[int, list[Union[bytes, int]]]] + _Attr = list[int | list[bytes | int]] # TODO constants not really documented B0: int @@ -243,4 +243,5 @@ if sys.platform != "win32": def tcdrain(__fd: FileDescriptorLike) -> None: ... def tcflush(__fd: FileDescriptorLike, __queue: int) -> None: ... def tcflow(__fd: FileDescriptorLike, __action: int) -> None: ... + class error(Exception): ... diff --git a/mypy/typeshed/stdlib/textwrap.pyi b/mypy/typeshed/stdlib/textwrap.pyi index 3b8fd5c0349a4..aeb1d87141bea 100644 --- a/mypy/typeshed/stdlib/textwrap.pyi +++ b/mypy/typeshed/stdlib/textwrap.pyi @@ -1,5 +1,7 @@ from typing import Callable, Pattern +__all__ = ["TextWrapper", "wrap", "fill", "dedent", "indent", "shorten"] + class TextWrapper: width: int initial_indent: str diff --git a/mypy/typeshed/stdlib/threading.pyi b/mypy/typeshed/stdlib/threading.pyi index 3e91221baed21..c3fa57fafa7cb 100644 --- a/mypy/typeshed/stdlib/threading.pyi +++ b/mypy/typeshed/stdlib/threading.pyi @@ -1,14 +1,95 @@ import sys from types import FrameType, TracebackType -from typing import Any, Callable, Iterable, Mapping, Optional, Type, TypeVar +from typing import Any, Callable, Iterable, Mapping, TypeVar # TODO recursive type -_TF = Callable[[FrameType, str, Any], Optional[Callable[..., Any]]] +_TF = Callable[[FrameType, str, Any], Callable[..., Any] | None] _PF = Callable[[FrameType, str, Any], None] _T = TypeVar("_T") -__all__: list[str] +if sys.version_info >= (3, 10): + __all__ = [ + "get_ident", + "active_count", + "Condition", + "current_thread", + "enumerate", + "main_thread", + "TIMEOUT_MAX", + "Event", + "Lock", + "RLock", + "Semaphore", + "BoundedSemaphore", + "Thread", + "Barrier", + "BrokenBarrierError", + "Timer", + "ThreadError", + "setprofile", + "settrace", + "local", + "stack_size", + "excepthook", + "ExceptHookArgs", + "gettrace", + "getprofile", + "get_native_id", + ] +elif sys.version_info >= (3, 8): + __all__ = [ + "get_ident", + "active_count", + "Condition", + "current_thread", + "enumerate", + "main_thread", + "TIMEOUT_MAX", + "Event", + "Lock", + "RLock", + "Semaphore", + "BoundedSemaphore", + "Thread", + "Barrier", + "BrokenBarrierError", + "Timer", + "ThreadError", + "setprofile", + "settrace", + "local", + "stack_size", + "excepthook", + "ExceptHookArgs", + "get_native_id", + ] +else: + __all__ = [ + "get_ident", + "active_count", + "Condition", + "current_thread", + "enumerate", + "main_thread", + "TIMEOUT_MAX", + "Event", + "Lock", + "RLock", + "Semaphore", + "BoundedSemaphore", + "Thread", + "Barrier", + "BrokenBarrierError", + "Timer", + "ThreadError", + "setprofile", + "settrace", + "local", + "stack_size", + ] + +_profile_hook: _PF | None def active_count() -> int: ... def activeCount() -> int: ... # deprecated alias for active_count() @@ -35,13 +116,14 @@ TIMEOUT_MAX: float class ThreadError(Exception): ... class local: - def __getattribute__(self, name: str) -> Any: ... - def __setattr__(self, name: str, value: Any) -> None: ... - def __delattr__(self, name: str) -> None: ... + def __getattribute__(self, __name: str) -> Any: ... + def __setattr__(self, __name: str, __value: Any) -> None: ... + def __delattr__(self, __name: str) -> None: ... class Thread: name: str - ident: int | None + @property + def ident(self) -> int | None: ... daemon: bool def __init__( self, @@ -59,6 +141,7 @@ class Thread: if sys.version_info >= (3, 8): @property def native_id(self) -> int | None: ... # only available on some platforms + def is_alive(self) -> bool: ... if sys.version_info < (3, 9): def isAlive(self) -> bool: ... @@ -75,7 +158,7 @@ class Lock: def __init__(self) -> None: ... def __enter__(self) -> bool: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> bool | None: ... def acquire(self, blocking: bool = ..., timeout: float = ...) -> bool: ... def release(self) -> None: ... @@ -86,9 +169,7 @@ class _RLock: def acquire(self, blocking: bool = ..., timeout: float = ...) -> bool: ... def release(self) -> None: ... __enter__ = acquire - def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None - ) -> bool | None: ... + def __exit__(self, t: type[BaseException] | None, v: BaseException | None, tb: TracebackType | None) -> None: ... RLock = _RLock @@ -96,7 +177,7 @@ class Condition: def __init__(self, lock: Lock | _RLock | None = ...) -> None: ... def __enter__(self) -> bool: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> bool | None: ... def acquire(self, blocking: bool = ..., timeout: float = ...) -> bool: ... def release(self) -> None: ... @@ -108,9 +189,7 @@ class Condition: class Semaphore: def __init__(self, value: int = ...) -> None: ... - def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None - ) -> bool | None: ... + def __exit__(self, t: type[BaseException] | None, v: BaseException | None, tb: TracebackType | None) -> None: ... def acquire(self, blocking: bool = ..., timeout: float | None = ...) -> bool: ... def __enter__(self, blocking: bool = ..., timeout: float | None = ...) -> bool: ... if sys.version_info >= (3, 9): @@ -145,9 +224,12 @@ class Timer(Thread): def cancel(self) -> None: ... class Barrier: - parties: int - n_waiting: int - broken: bool + @property + def parties(self) -> int: ... + @property + def n_waiting(self) -> int: ... + @property + def broken(self) -> bool: ... def __init__(self, parties: int, action: Callable[[], None] | None = ..., timeout: float | None = ...) -> None: ... def wait(self, timeout: float | None = ...) -> int: ... def reset(self) -> None: ... diff --git a/mypy/typeshed/stdlib/time.pyi b/mypy/typeshed/stdlib/time.pyi index 6e23b331d1c85..25f8d7056cd87 100644 --- a/mypy/typeshed/stdlib/time.pyi +++ b/mypy/typeshed/stdlib/time.pyi @@ -1,8 +1,7 @@ import sys from _typeshed import structseq -from types import SimpleNamespace -from typing import Any, Union -from typing_extensions import final +from typing import Any, Protocol +from typing_extensions import Final, Literal, final _TimeTuple = tuple[int, int, int, int, int, int, int, int, int] @@ -38,7 +37,9 @@ if sys.version_info >= (3, 9) and sys.platform == "linux": # even if an iterable with length >9 is passed. # https://github.com/python/typeshed/pull/6560#discussion_r767162532 @final -class struct_time(structseq[Union[Any, int]], _TimeTuple): +class struct_time(structseq[Any | int], _TimeTuple): + if sys.version_info >= (3, 10): + __match_args__: Final = ("tm_year", "tm_mon", "tm_mday", "tm_hour", "tm_min", "tm_sec", "tm_wday", "tm_yday", "tm_isdst") @property def tm_year(self) -> int: ... @property @@ -80,7 +81,13 @@ def time() -> float: ... if sys.platform != "win32": def tzset() -> None: ... # Unix only -def get_clock_info(name: str) -> SimpleNamespace: ... +class _ClockInfo(Protocol): + adjustable: bool + implementation: str + monotonic: bool + resolution: float + +def get_clock_info(name: Literal["monotonic", "perf_counter", "process_time", "time", "thread_time"]) -> _ClockInfo: ... def monotonic() -> float: ... def perf_counter() -> float: ... def process_time() -> float: ... @@ -94,6 +101,10 @@ if sys.version_info >= (3, 7): if sys.platform != "win32": def clock_gettime_ns(clock_id: int) -> int: ... def clock_settime_ns(clock_id: int, time: int) -> int: ... + + if sys.platform == "linux": + def pthread_getcpuclockid(thread_id: int) -> int: ... + def monotonic_ns() -> int: ... def perf_counter_ns() -> int: ... def process_time_ns() -> int: ... diff --git a/mypy/typeshed/stdlib/timeit.pyi b/mypy/typeshed/stdlib/timeit.pyi index d82dd80598dcb..bfaea728ff423 100644 --- a/mypy/typeshed/stdlib/timeit.pyi +++ b/mypy/typeshed/stdlib/timeit.pyi @@ -1,7 +1,9 @@ -from typing import IO, Any, Callable, Sequence, Union +from typing import IO, Any, Callable, Sequence + +__all__ = ["Timer", "timeit", "repeat", "default_timer"] _Timer = Callable[[], float] -_Stmt = Union[str, Callable[[], Any]] +_Stmt = str | Callable[[], Any] default_timer: _Timer @@ -25,7 +27,4 @@ def repeat( number: int = ..., globals: dict[str, Any] | None = ..., ) -> list[float]: ... - -_timerFunc = Callable[[], float] - -def main(args: Sequence[str] | None = ..., *, _wrap_timer: Callable[[_timerFunc], _timerFunc] | None = ...) -> None: ... +def main(args: Sequence[str] | None = ..., *, _wrap_timer: Callable[[_Timer], _Timer] | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/tkinter/__init__.pyi b/mypy/typeshed/stdlib/tkinter/__init__.pyi index 50de97f48fdca..2a6172ba46a3a 100644 --- a/mypy/typeshed/stdlib/tkinter/__init__.pyi +++ b/mypy/typeshed/stdlib/tkinter/__init__.pyi @@ -5,9 +5,144 @@ from enum import Enum from tkinter.constants import * from tkinter.font import _FontDescription from types import TracebackType -from typing import Any, Callable, Generic, Mapping, Optional, Protocol, Sequence, Type, TypeVar, Union, overload +from typing import Any, Callable, Generic, Mapping, Protocol, Sequence, TypeVar, Union, overload from typing_extensions import Literal, TypedDict +if sys.version_info >= (3, 9): + __all__ = [ + "TclError", + "NO", + "FALSE", + "OFF", + "YES", + "TRUE", + "ON", + "N", + "S", + "W", + "E", + "NW", + "SW", + "NE", + "SE", + "NS", + "EW", + "NSEW", + "CENTER", + "NONE", + "X", + "Y", + "BOTH", + "LEFT", + "TOP", + "RIGHT", + "BOTTOM", + "RAISED", + "SUNKEN", + "FLAT", + "RIDGE", + "GROOVE", + "SOLID", + "HORIZONTAL", + "VERTICAL", + "NUMERIC", + "CHAR", + "WORD", + "BASELINE", + "INSIDE", + "OUTSIDE", + "SEL", + "SEL_FIRST", + "SEL_LAST", + "END", + "INSERT", + "CURRENT", + "ANCHOR", + "ALL", + "NORMAL", + "DISABLED", + "ACTIVE", + "HIDDEN", + "CASCADE", + "CHECKBUTTON", + "COMMAND", + "RADIOBUTTON", + "SEPARATOR", + "SINGLE", + "BROWSE", + "MULTIPLE", + "EXTENDED", + "DOTBOX", + "UNDERLINE", + "PIESLICE", + "CHORD", + "ARC", + "FIRST", + "LAST", + "BUTT", + "PROJECTING", + "ROUND", + "BEVEL", + "MITER", + "MOVETO", + "SCROLL", + "UNITS", + "PAGES", + "TkVersion", + "TclVersion", + "READABLE", + "WRITABLE", + "EXCEPTION", + "EventType", + "Event", + "NoDefaultRoot", + "Variable", + "StringVar", + "IntVar", + "DoubleVar", + "BooleanVar", + "mainloop", + "getint", + "getdouble", + "getboolean", + "Misc", + "CallWrapper", + "XView", + "YView", + "Wm", + "Tk", + "Tcl", + "Pack", + "Place", + "Grid", + "BaseWidget", + "Widget", + "Toplevel", + "Button", + "Canvas", + "Checkbutton", + "Entry", + "Frame", + "Label", + "Listbox", + "Menu", + "Menubutton", + "Message", + "Radiobutton", + "Scale", + "Scrollbar", + "Text", + "OptionMenu", + "Image", + "PhotoImage", + "BitmapImage", + "image_names", + "image_types", + "Spinbox", + "LabelFrame", + "PanedWindow", + ] + # Using anything from tkinter.font in this file means that 'import tkinter' # seems to also load tkinter.font. That's not how it actually works, but # unfortunately not much can be done about it. https://github.com/python/typeshed/pull/4346 @@ -38,16 +173,16 @@ EXCEPTION = _tkinter.EXCEPTION # than the _Compound defined here. Many other options have similar things. _Anchor = Literal["nw", "n", "ne", "w", "center", "e", "sw", "s", "se"] # manual page: Tk_GetAnchor _Bitmap = str # manual page: Tk_GetBitmap -_ButtonCommand = Union[str, Callable[[], Any]] # accepts string of tcl code, return value is returned from Button.invoke() +_ButtonCommand = str | Callable[[], Any] # accepts string of tcl code, return value is returned from Button.invoke() _CanvasItemId = int _Color = str # typically '#rrggbb', '#rgb' or color names. _Compound = Literal["top", "left", "center", "right", "bottom", "none"] # -compound in manual page named 'options' _Cursor = Union[str, tuple[str], tuple[str, str], tuple[str, str, str], tuple[str, str, str, str]] # manual page: Tk_GetCursor -_EntryValidateCommand = Union[ - Callable[[], bool], str, list[str], tuple[str, ...] -] # example when it's sequence: entry['invalidcommand'] = [entry.register(print), '%P'] -_GridIndex = Union[int, str, Literal["all"]] -_ImageSpec = Union[_Image, str] # str can be from e.g. tkinter.image_names() +_EntryValidateCommand = ( + str | list[str] | tuple[str, ...] | Callable[[], bool] +) # example when it's sequence: entry['invalidcommand'] = [entry.register(print), '%P'] +_GridIndex = int | str | Literal["all"] +_ImageSpec = _Image | str # str can be from e.g. tkinter.image_names() _Padding = Union[ _ScreenUnits, tuple[_ScreenUnits], @@ -56,9 +191,9 @@ _Padding = Union[ tuple[_ScreenUnits, _ScreenUnits, _ScreenUnits, _ScreenUnits], ] _Relief = Literal["raised", "sunken", "flat", "ridge", "solid", "groove"] # manual page: Tk_GetRelief -_ScreenUnits = Union[str, float] # Often the right type instead of int. Manual page: Tk_GetPixels -_XYScrollCommand = Union[str, Callable[[float, float], Any]] # -xscrollcommand and -yscrollcommand in 'options' manual page -_TakeFocusValue = Union[int, Literal[""], Callable[[str], Optional[bool]]] # -takefocus in manual page named 'options' +_ScreenUnits = str | float # Often the right type instead of int. Manual page: Tk_GetPixels +_XYScrollCommand = str | Callable[[float, float], Any] # -xscrollcommand and -yscrollcommand in 'options' manual page +_TakeFocusValue = Union[int, Literal[""], Callable[[str], bool | None]] # -takefocus in manual page named 'options' class EventType(str, Enum): Activate: str @@ -101,9 +236,9 @@ class EventType(str, Enum): VirtualEvent: str Visibility: str -_W = TypeVar("_W", bound="Misc") +_W = TypeVar("_W", bound=Misc) # Events considered covariant because you should never assign to event.widget. -_W_co = TypeVar("_W_co", covariant=True, bound="Misc") +_W_co = TypeVar("_W_co", covariant=True, bound=Misc) class Event(Generic[_W_co]): serial: int @@ -126,7 +261,7 @@ class Event(Generic[_W_co]): widget: _W_co delta: int -def NoDefaultRoot(): ... +def NoDefaultRoot() -> None: ... _TraceMode = Literal["array", "read", "write", "unset"] @@ -139,9 +274,10 @@ class Variable: def trace_remove(self, mode: _TraceMode, cbname: str) -> None: ... def trace_info(self) -> list[tuple[tuple[_TraceMode, ...], str]]: ... def trace_variable(self, mode, callback): ... # deprecated - def trace_vdelete(self, mode, cbname): ... # deprecated + def trace_vdelete(self, mode, cbname) -> None: ... # deprecated def trace_vinfo(self): ... # deprecated trace = trace_variable # deprecated + def __eq__(self, other: object) -> bool: ... class StringVar(Variable): def __init__(self, master: Misc | None = ..., value: str | None = ..., name: str | None = ...) -> None: ... @@ -187,13 +323,13 @@ class Misc: def destroy(self) -> None: ... def deletecommand(self, name: str) -> None: ... def tk_strictMotif(self, boolean: Any | None = ...): ... - def tk_bisque(self): ... - def tk_setPalette(self, *args, **kw): ... + def tk_bisque(self) -> None: ... + def tk_setPalette(self, *args, **kw) -> None: ... def wait_variable(self, name: str | Variable = ...) -> None: ... waitvar = wait_variable def wait_window(self, window: Misc | None = ...) -> None: ... def wait_visibility(self, window: Misc | None = ...) -> None: ... - def setvar(self, name: str = ..., value: str = ...): ... + def setvar(self, name: str = ..., value: str = ...) -> None: ... def getvar(self, name: str = ...): ... def getint(self, s): ... def getdouble(self, s): ... @@ -214,30 +350,32 @@ class Misc: # after_idle is essentially partialmethod(after, "idle") def after_idle(self, func: Callable[..., Any], *args: Any) -> str: ... def after_cancel(self, id: str) -> None: ... - def bell(self, displayof: Literal[0] | Misc | None = ...): ... + def bell(self, displayof: Literal[0] | Misc | None = ...) -> None: ... def clipboard_get(self, *, displayof: Misc = ..., type: str = ...) -> str: ... def clipboard_clear(self, *, displayof: Misc = ...) -> None: ... - def clipboard_append(self, string: str, *, displayof: Misc = ..., format: str = ..., type: str = ...): ... + def clipboard_append(self, string: str, *, displayof: Misc = ..., format: str = ..., type: str = ...) -> None: ... def grab_current(self): ... - def grab_release(self): ... + def grab_release(self) -> None: ... def grab_set(self) -> None: ... def grab_set_global(self) -> None: ... - def grab_status(self): ... - def option_add(self, pattern, value, priority: Any | None = ...): ... - def option_clear(self): ... + def grab_status(self) -> Literal["local", "global"] | None: ... + def option_add( + self, pattern, value, priority: int | Literal["widgetDefault", "startupFile", "userDefault", "interactive"] | None = ... + ) -> None: ... + def option_clear(self) -> None: ... def option_get(self, name, className): ... - def option_readfile(self, fileName, priority: Any | None = ...): ... - def selection_clear(self, **kw): ... + def option_readfile(self, fileName, priority: Any | None = ...) -> None: ... + def selection_clear(self, **kw) -> None: ... def selection_get(self, **kw): ... - def selection_handle(self, command, **kw): ... - def selection_own(self, **kw): ... + def selection_handle(self, command, **kw) -> None: ... + def selection_own(self, **kw) -> None: ... def selection_own_get(self, **kw): ... def send(self, interp, cmd, *args): ... - def lower(self, belowThis: Any | None = ...): ... - def tkraise(self, aboveThis: Any | None = ...): ... + def lower(self, belowThis: Any | None = ...) -> None: ... + def tkraise(self, aboveThis: Any | None = ...) -> None: ... lift = tkraise - def winfo_atom(self, name: str, displayof: Literal[0] | Misc | None = ...): ... - def winfo_atomname(self, id: int, displayof: Literal[0] | Misc | None = ...): ... + def winfo_atom(self, name: str, displayof: Literal[0] | Misc | None = ...) -> int: ... + def winfo_atomname(self, id: int, displayof: Literal[0] | Misc | None = ...) -> str: ... def winfo_cells(self) -> int: ... def winfo_children(self) -> list[Widget]: ... # Widget because it can't be Toplevel or Tk def winfo_class(self) -> str: ... @@ -287,7 +425,10 @@ class Misc: def winfo_y(self) -> int: ... def update(self) -> None: ... def update_idletasks(self) -> None: ... - def bindtags(self, tagList: Any | None = ...): ... + @overload + def bindtags(self, tagList: None = ...) -> tuple[str, ...]: ... + @overload + def bindtags(self, tagList: list[str] | tuple[str, ...]) -> None: ... # bind with isinstance(func, str) doesn't return anything, but all other # binds do. The default value of func is not str. @overload @@ -330,7 +471,7 @@ class Misc: def unbind_all(self, sequence: str) -> None: ... def unbind_class(self, className: str, sequence: str) -> None: ... def mainloop(self, n: int = ...) -> None: ... - def quit(self): ... + def quit(self) -> None: ... def nametowidget(self, name: str | Misc | _tkinter.Tcl_Obj) -> Any: ... def register( self, func: Callable[..., Any], subst: Callable[..., Sequence[Any]] | None = ..., needcleanup: int = ... @@ -434,7 +575,7 @@ class CallWrapper: func: Any subst: Any widget: Any - def __init__(self, func, subst, widget): ... + def __init__(self, func, subst, widget) -> None: ... def __call__(self, *args): ... class XView: @@ -488,11 +629,11 @@ class Wm: # Some of these always return empty string, but return type is set to None to prevent accidentally using it def wm_deiconify(self) -> None: ... deiconify = wm_deiconify - def wm_focusmodel(self, model: Any | None = ...): ... + def wm_focusmodel(self, model: Literal["active", "passive"] | None = ...) -> Literal["active", "passive", ""]: ... focusmodel = wm_focusmodel def wm_forget(self, window: Wm) -> None: ... forget = wm_forget - def wm_frame(self): ... + def wm_frame(self) -> str: ... frame = wm_frame @overload def wm_geometry(self, newGeometry: None = ...) -> str: ... @@ -511,15 +652,15 @@ class Wm: iconify = wm_iconify def wm_iconmask(self, bitmap: Any | None = ...): ... iconmask = wm_iconmask - def wm_iconname(self, newName: Any | None = ...): ... + def wm_iconname(self, newName: Any | None = ...) -> str: ... iconname = wm_iconname def wm_iconphoto(self, default: bool, __image1: Image, *args: Image) -> None: ... iconphoto = wm_iconphoto - def wm_iconposition(self, x: Any | None = ..., y: Any | None = ...): ... + def wm_iconposition(self, x: int | None = ..., y: int | None = ...) -> tuple[int, int] | None: ... iconposition = wm_iconposition def wm_iconwindow(self, pathName: Any | None = ...): ... iconwindow = wm_iconwindow - def wm_manage(self, widget): ... + def wm_manage(self, widget) -> None: ... manage = wm_manage @overload def wm_maxsize(self, width: None = ..., height: None = ...) -> tuple[int, int]: ... @@ -536,7 +677,7 @@ class Wm: @overload def wm_overrideredirect(self, boolean: bool) -> None: ... overrideredirect = wm_overrideredirect - def wm_positionfrom(self, who: Any | None = ...): ... + def wm_positionfrom(self, who: Literal["program", "user"] | None = ...) -> Literal["", "program", "user"]: ... positionfrom = wm_positionfrom @overload def wm_protocol(self, name: str, func: Callable[[], Any] | str) -> None: ... @@ -550,7 +691,7 @@ class Wm: @overload def wm_resizable(self, width: bool, height: bool) -> None: ... resizable = wm_resizable - def wm_sizefrom(self, who: Any | None = ...): ... + def wm_sizefrom(self, who: Literal["program", "user"] | None = ...) -> Literal["", "program", "user"]: ... sizefrom = wm_sizefrom @overload def wm_state(self, newstate: None = ...) -> str: ... @@ -571,12 +712,14 @@ class Wm: withdraw = wm_withdraw class _ExceptionReportingCallback(Protocol): - def __call__(self, __exc: Type[BaseException], __val: BaseException, __tb: TracebackType | None) -> Any: ... + def __call__(self, __exc: type[BaseException], __val: BaseException, __tb: TracebackType | None) -> Any: ... class Tk(Misc, Wm): master: None def __init__( - # please update ttkthemes stub if you change this + # Make sure to keep in sync with other functions that use the same + # args. + # use `git grep screenName` to find them self, screenName: str | None = ..., baseName: str | None = ..., @@ -610,46 +753,42 @@ class Tk(Misc, Wm): @overload def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure - def loadtk(self) -> None: ... # differs from _tkinter.TkappType.loadtk def destroy(self) -> None: ... def readprofile(self, baseName: str, className: str) -> None: ... report_callback_exception: _ExceptionReportingCallback # Tk has __getattr__ so that tk_instance.foo falls back to tk_instance.tk.foo - # Please keep in sync with _tkinter.TkappType - call: Callable[..., Any] - def eval(self, __code: str) -> str: ... - adderrorinfo: Any - createcommand: Any - createfilehandler: Any - createtimerhandler: Any - deletecommand: Any - deletefilehandler: Any - dooneevent: Any - evalfile: Any - exprboolean: Any - exprdouble: Any - exprlong: Any - exprstring: Any - getboolean: Any - getdouble: Any - getint: Any - getvar: Any - globalgetvar: Any - globalsetvar: Any - globalunsetvar: Any - interpaddr: Any - mainloop: Any - quit: Any - record: Any - setvar: Any + # Please keep in sync with _tkinter.TkappType. + # Some methods are intentionally missing because they are inherited from Misc instead. + def adderrorinfo(self, __msg): ... + def call(self, __command: Any, *args: Any) -> Any: ... + def createcommand(self, __name, __func): ... + if sys.platform != "win32": + def createfilehandler(self, __file, __mask, __func): ... + def deletefilehandler(self, __file): ... + + def createtimerhandler(self, __milliseconds, __func): ... + def dooneevent(self, __flags: int = ...): ... + def eval(self, __script: str) -> str: ... + def evalfile(self, __fileName): ... + def exprboolean(self, __s): ... + def exprdouble(self, __s): ... + def exprlong(self, __s): ... + def exprstring(self, __s): ... + def globalgetvar(self, *args, **kwargs): ... + def globalsetvar(self, *args, **kwargs): ... + def globalunsetvar(self, *args, **kwargs): ... + def interpaddr(self): ... + def loadtk(self) -> None: ... + def record(self, __script): ... if sys.version_info < (3, 11): - split: Any - splitlist: Any - unsetvar: Any - wantobjects: Any - willdispatch: Any + def split(self, __arg): ... + + def splitlist(self, __arg): ... + def unsetvar(self, *args, **kwargs): ... + def wantobjects(self, *args, **kwargs): ... + def willdispatch(self): ... -def Tcl(screenName: Any | None = ..., baseName: Any | None = ..., className: str = ..., useTk: bool = ...): ... +def Tcl(screenName: str | None = ..., baseName: str | None = ..., className: str = ..., useTk: bool = ...) -> Tk: ... _InMiscTotal = TypedDict("_InMiscTotal", {"in": Misc}) _InMiscNonTotal = TypedDict("_InMiscNonTotal", {"in": Misc}, total=False) @@ -769,7 +908,7 @@ class Grid: class BaseWidget(Misc): master: Misc widgetName: Any - def __init__(self, master, widgetName, cnf=..., kw=..., extra=...): ... + def __init__(self, master, widgetName, cnf=..., kw=..., extra=...) -> None: ... def destroy(self) -> None: ... # This class represents any widget except Toplevel or Tk. @@ -942,7 +1081,7 @@ class Button(Widget): @overload def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure - def flash(self): ... + def flash(self) -> None: ... def invoke(self) -> Any: ... class Canvas(Widget, XView, YView): @@ -1059,7 +1198,7 @@ class Canvas(Widget, XView, YView): @overload def tag_bind( self, - tagOrId: str | int, + tagOrId: str | _CanvasItemId, sequence: str | None = ..., func: Callable[[Event[Canvas]], Any] | None = ..., add: Literal["", "+"] | bool | None = ..., @@ -1069,16 +1208,16 @@ class Canvas(Widget, XView, YView): self, tagOrId: str | int, sequence: str | None, func: str, add: Literal["", "+"] | bool | None = ... ) -> None: ... @overload - def tag_bind(self, tagOrId: str | int, *, func: str, add: Literal["", "+"] | bool | None = ...) -> None: ... - def tag_unbind(self, tagOrId: str | int, sequence: str, funcid: str | None = ...) -> None: ... + def tag_bind(self, tagOrId: str | _CanvasItemId, *, func: str, add: Literal["", "+"] | bool | None = ...) -> None: ... + def tag_unbind(self, tagOrId: str | _CanvasItemId, sequence: str, funcid: str | None = ...) -> None: ... def canvasx(self, screenx, gridspacing: Any | None = ...): ... def canvasy(self, screeny, gridspacing: Any | None = ...): ... @overload - def coords(self) -> list[float]: ... + def coords(self, __tagOrId: str | _CanvasItemId) -> list[float]: ... @overload - def coords(self, __args: list[int] | list[float] | tuple[float, ...]) -> None: ... + def coords(self, __tagOrId: str | _CanvasItemId, __args: list[int] | list[float] | tuple[float, ...]) -> None: ... @overload - def coords(self, __x1: float, __y1: float, *args: float) -> None: ... + def coords(self, __tagOrId: str | _CanvasItemId, __x1: float, __y1: float, *args: float) -> None: ... # create_foo() methods accept coords as a list, a tuple, or as separate arguments. # Keyword arguments should be the same in each pair of overloads. def create_arc(self, *args, **kw) -> _CanvasItemId: ... @@ -1398,7 +1537,7 @@ class Canvas(Widget, XView, YView): width: _ScreenUnits = ..., window: Widget = ..., ) -> _CanvasItemId: ... - def dchars(self, *args): ... + def dchars(self, *args) -> None: ... def delete(self, *tagsOrCanvasIds: str | _CanvasItemId) -> None: ... @overload def dtag(self, __tag: str, __tag_to_delete: str | None = ...) -> None: ... @@ -1406,18 +1545,19 @@ class Canvas(Widget, XView, YView): def dtag(self, __id: _CanvasItemId, __tag_to_delete: str) -> None: ... def focus(self, *args): ... def gettags(self, __tagOrId: str | _CanvasItemId) -> tuple[str, ...]: ... - def icursor(self, *args): ... + def icursor(self, *args) -> None: ... def index(self, *args): ... - def insert(self, *args): ... + def insert(self, *args) -> None: ... def itemcget(self, tagOrId, option): ... # itemconfigure kwargs depend on item type, which is not known when type checking def itemconfigure( self, tagOrId: str | _CanvasItemId, cnf: dict[str, Any] | None = ..., **kw: Any ) -> dict[str, tuple[str, str, str, str, str]] | None: ... itemconfig = itemconfigure - def move(self, *args): ... + def move(self, *args) -> None: ... if sys.version_info >= (3, 8): def moveto(self, tagOrId: str | _CanvasItemId, x: Literal[""] | float = ..., y: Literal[""] | float = ...) -> None: ... + def postscript(self, cnf=..., **kw): ... # tkinter does: # lower = tag_lower @@ -1429,14 +1569,14 @@ class Canvas(Widget, XView, YView): def tag_raise(self, __first: str | _CanvasItemId, __second: str | _CanvasItemId | None = ...) -> None: ... def tkraise(self, __first: str | _CanvasItemId, __second: str | _CanvasItemId | None = ...) -> None: ... # type: ignore[override] def lift(self, __first: str | _CanvasItemId, __second: str | _CanvasItemId | None = ...) -> None: ... # type: ignore[override] - def scale(self, *args): ... - def scan_mark(self, x, y): ... - def scan_dragto(self, x, y, gain: int = ...): ... - def select_adjust(self, tagOrId, index): ... - def select_clear(self): ... - def select_from(self, tagOrId, index): ... + def scale(self, *args) -> None: ... + def scan_mark(self, x, y) -> None: ... + def scan_dragto(self, x, y, gain: int = ...) -> None: ... + def select_adjust(self, tagOrId, index) -> None: ... + def select_clear(self) -> None: ... + def select_from(self, tagOrId, index) -> None: ... def select_item(self): ... - def select_to(self, tagOrId, index): ... + def select_to(self, tagOrId, index) -> None: ... def type(self, tagOrId): ... class Checkbutton(Widget): @@ -1550,13 +1690,13 @@ class Checkbutton(Widget): @overload def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure - def deselect(self): ... - def flash(self): ... + def deselect(self) -> None: ... + def flash(self) -> None: ... def invoke(self) -> Any: ... - def select(self): ... - def toggle(self): ... + def select(self) -> None: ... + def toggle(self) -> None: ... -_EntryIndex = Union[str, int] # "INDICES" in manual page +_EntryIndex = str | int # "INDICES" in manual page class Entry(Widget, XView): def __init__( @@ -1654,8 +1794,8 @@ class Entry(Widget, XView): def icursor(self, index: _EntryIndex) -> None: ... def index(self, index: _EntryIndex) -> int: ... def insert(self, index: _EntryIndex, string: str) -> None: ... - def scan_mark(self, x): ... - def scan_dragto(self, x): ... + def scan_mark(self, x) -> None: ... + def scan_dragto(self, x) -> None: ... def selection_adjust(self, index: _EntryIndex) -> None: ... def selection_clear(self) -> None: ... # type: ignore[override] def selection_from(self, index: _EntryIndex) -> None: ... @@ -1890,31 +2030,31 @@ class Listbox(Widget, XView, YView): @overload def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure - def activate(self, index): ... - def bbox(self, index): ... + def activate(self, index) -> None: ... + def bbox(self, index) -> tuple[int, int, int, int] | None: ... # type: ignore[override] def curselection(self): ... - def delete(self, first, last: Any | None = ...): ... + def delete(self, first, last: Any | None = ...) -> None: ... def get(self, first, last: Any | None = ...): ... def index(self, index): ... - def insert(self, index, *elements): ... + def insert(self, index, *elements) -> None: ... def nearest(self, y): ... - def scan_mark(self, x, y): ... - def scan_dragto(self, x, y): ... - def see(self, index): ... - def selection_anchor(self, index): ... + def scan_mark(self, x, y) -> None: ... + def scan_dragto(self, x, y) -> None: ... + def see(self, index) -> None: ... + def selection_anchor(self, index) -> None: ... select_anchor: Any - def selection_clear(self, first, last: Any | None = ...): ... # type: ignore[override] + def selection_clear(self, first, last: Any | None = ...) -> None: ... # type: ignore[override] select_clear: Any def selection_includes(self, index): ... select_includes: Any - def selection_set(self, first, last: Any | None = ...): ... + def selection_set(self, first, last: Any | None = ...) -> None: ... select_set: Any - def size(self): ... + def size(self) -> int: ... # type: ignore[override] def itemcget(self, index, option): ... def itemconfigure(self, index, cnf: Any | None = ..., **kw): ... itemconfig: Any -_MenuIndex = Union[str, int] +_MenuIndex = str | int class Menu(Widget): def __init__( @@ -2434,10 +2574,10 @@ class Radiobutton(Widget): @overload def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure - def deselect(self): ... - def flash(self): ... + def deselect(self) -> None: ... + def flash(self) -> None: ... def invoke(self) -> Any: ... - def select(self): ... + def select(self) -> None: ... class Scale(Widget): def __init__( @@ -2525,10 +2665,10 @@ class Scale(Widget): @overload def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure - def get(self): ... - def set(self, value): ... - def coords(self, value: Any | None = ...): ... - def identify(self, x, y): ... + def get(self) -> float: ... + def set(self, value) -> None: ... + def coords(self, value: float | None = ...) -> tuple[int, int]: ... + def identify(self, x, y) -> Literal["", "slider", "trough1", "trough2"]: ... class Scrollbar(Widget): def __init__( @@ -2594,13 +2734,13 @@ class Scrollbar(Widget): def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure def activate(self, index: Any | None = ...): ... - def delta(self, deltax, deltay): ... - def fraction(self, x, y): ... - def identify(self, x, y): ... - def get(self): ... - def set(self, first, last): ... + def delta(self, deltax: int, deltay: int) -> float: ... + def fraction(self, x: int, y: int) -> float: ... + def identify(self, x: int, y: int) -> Literal["arrow1", "arrow2", "slider", "trough1", "trough2", ""]: ... + def get(self) -> tuple[float, float, float, float] | tuple[float, float]: ... + def set(self, first: float, last: float) -> None: ... -_TextIndex = Union[_tkinter.Tcl_Obj, str, float, Misc] +_TextIndex = _tkinter.Tcl_Obj | str | float | Misc class Text(Widget, XView, YView): def __init__( @@ -2876,13 +3016,13 @@ class Text(Widget, XView, YView): def window_cget(self, index, option): ... def window_configure(self, index, cnf: Any | None = ..., **kw): ... window_config = window_configure - def window_create(self, index, cnf=..., **kw): ... + def window_create(self, index, cnf=..., **kw) -> None: ... def window_names(self): ... def yview_pickplace(self, *what): ... # deprecated class _setit: - def __init__(self, var, value, callback: Any | None = ...): ... - def __call__(self, *args): ... + def __init__(self, var, value, callback: Any | None = ...) -> None: ... + def __call__(self, *args) -> None: ... # manual page: tk_optionMenu class OptionMenu(Menubutton): @@ -2909,9 +3049,11 @@ class _Image(Protocol): class Image: name: Any tk: _tkinter.TkappType - def __init__(self, imgtype, name: Any | None = ..., cnf=..., master: Misc | _tkinter.TkappType | None = ..., **kw): ... - def __del__(self): ... - def __setitem__(self, key, value): ... + def __init__( + self, imgtype, name: Any | None = ..., cnf=..., master: Misc | _tkinter.TkappType | None = ..., **kw + ) -> None: ... + def __del__(self) -> None: ... + def __setitem__(self, key, value) -> None: ... def __getitem__(self, key): ... configure: Any config: Any @@ -3107,13 +3249,13 @@ class Spinbox(Widget, XView): @overload def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure - def bbox(self, index): ... - def delete(self, first, last: Any | None = ...): ... - def get(self): ... + def bbox(self, index) -> tuple[int, int, int, int] | None: ... # type: ignore[override] + def delete(self, first, last: Any | None = ...) -> Literal[""]: ... + def get(self) -> str: ... def icursor(self, index): ... - def identify(self, x, y): ... - def index(self, index): ... - def insert(self, index, s): ... + def identify(self, x: int, y: int) -> Literal["", "buttondown", "buttonup", "entry"]: ... + def index(self, index: _EntryIndex) -> int: ... + def insert(self, index: _EntryIndex, s: str) -> Literal[""]: ... # spinbox.invoke("asdf") gives error mentioning .invoke("none"), but it's not documented def invoke(self, element: Literal["none", "buttonup", "buttondown"]) -> Literal[""]: ... def scan(self, *args): ... @@ -3253,10 +3395,10 @@ class PanedWindow(Widget): @overload def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure - def add(self, child: Widget, **kw): ... - def remove(self, child): ... + def add(self, child: Widget, **kw) -> None: ... + def remove(self, child) -> None: ... forget: Any - def identify(self, x, y): ... + def identify(self, x: int, y: int): ... def proxy(self, *args): ... def proxy_coord(self): ... def proxy_forget(self): ... diff --git a/mypy/typeshed/stdlib/tkinter/colorchooser.pyi b/mypy/typeshed/stdlib/tkinter/colorchooser.pyi index b5fdc7c549148..e0473afa5a7af 100644 --- a/mypy/typeshed/stdlib/tkinter/colorchooser.pyi +++ b/mypy/typeshed/stdlib/tkinter/colorchooser.pyi @@ -1,6 +1,10 @@ +import sys from tkinter.commondialog import Dialog from typing import Any, ClassVar +if sys.version_info >= (3, 9): + __all__ = ["Chooser", "askcolor"] + class Chooser(Dialog): command: ClassVar[str] diff --git a/mypy/typeshed/stdlib/tkinter/commondialog.pyi b/mypy/typeshed/stdlib/tkinter/commondialog.pyi index aee58111c73f1..1c5fb0f537065 100644 --- a/mypy/typeshed/stdlib/tkinter/commondialog.pyi +++ b/mypy/typeshed/stdlib/tkinter/commondialog.pyi @@ -1,5 +1,9 @@ +import sys from typing import Any, ClassVar, Mapping +if sys.version_info >= (3, 9): + __all__ = ["Dialog"] + class Dialog: command: ClassVar[str | None] master: Any | None diff --git a/mypy/typeshed/stdlib/tkinter/dialog.pyi b/mypy/typeshed/stdlib/tkinter/dialog.pyi index bc927e1f24acf..f9c8487c44a93 100644 --- a/mypy/typeshed/stdlib/tkinter/dialog.pyi +++ b/mypy/typeshed/stdlib/tkinter/dialog.pyi @@ -1,6 +1,10 @@ +import sys from tkinter import Widget from typing import Any, Mapping +if sys.version_info >= (3, 9): + __all__ = ["Dialog"] + DIALOG_ICON: str class Dialog(Widget): diff --git a/mypy/typeshed/stdlib/tkinter/dnd.pyi b/mypy/typeshed/stdlib/tkinter/dnd.pyi index 339291a20d0f3..e2cfc43f606a2 100644 --- a/mypy/typeshed/stdlib/tkinter/dnd.pyi +++ b/mypy/typeshed/stdlib/tkinter/dnd.pyi @@ -1,6 +1,10 @@ +import sys from tkinter import Event, Misc, Tk, Widget from typing import ClassVar, Protocol +if sys.version_info >= (3, 9): + __all__ = ["dnd_start", "DndHandler"] + class _DndSource(Protocol): def dnd_end(self, target: Widget | None, event: Event[Misc] | None) -> None: ... diff --git a/mypy/typeshed/stdlib/tkinter/filedialog.pyi b/mypy/typeshed/stdlib/tkinter/filedialog.pyi index b818d5e8253e5..dc0e01a6d1d1e 100644 --- a/mypy/typeshed/stdlib/tkinter/filedialog.pyi +++ b/mypy/typeshed/stdlib/tkinter/filedialog.pyi @@ -1,8 +1,26 @@ +import sys from _typeshed import StrOrBytesPath from tkinter import Button, Entry, Frame, Listbox, Misc, Scrollbar, StringVar, Toplevel, commondialog from typing import IO, Any, ClassVar, Iterable from typing_extensions import Literal +if sys.version_info >= (3, 9): + __all__ = [ + "FileDialog", + "LoadFileDialog", + "SaveFileDialog", + "Open", + "SaveAs", + "Directory", + "askopenfilename", + "asksaveasfilename", + "askopenfilenames", + "askopenfile", + "askopenfiles", + "asksaveasfile", + "askdirectory", + ] + dialogstates: dict[Any, tuple[Any, Any]] class FileDialog: @@ -46,7 +64,7 @@ class LoadFileDialog(FileDialog): class SaveFileDialog(FileDialog): title: str - def ok_command(self): ... + def ok_command(self) -> None: ... class _Dialog(commondialog.Dialog): ... diff --git a/mypy/typeshed/stdlib/tkinter/font.pyi b/mypy/typeshed/stdlib/tkinter/font.pyi index 211e8ec9a0beb..4b0101b327880 100644 --- a/mypy/typeshed/stdlib/tkinter/font.pyi +++ b/mypy/typeshed/stdlib/tkinter/font.pyi @@ -1,25 +1,24 @@ import _tkinter import sys import tkinter -from typing import Any, Union, overload +from typing import Any, overload from typing_extensions import Literal, TypedDict +if sys.version_info >= (3, 9): + __all__ = ["NORMAL", "ROMAN", "BOLD", "ITALIC", "nametofont", "Font", "families", "names"] + NORMAL: Literal["normal"] ROMAN: Literal["roman"] BOLD: Literal["bold"] ITALIC: Literal["italic"] -_FontDescription = Union[ - # "Helvetica 12" - str, - # A font object constructed in Python - Font, - # ("Helvetica", 12, BOLD) - list[Any], - tuple[Any, ...], - # A font object constructed in Tcl - _tkinter.Tcl_Obj, -] +_FontDescription = ( + str # "Helvetica 12" + | Font # A font object constructed in Python + | list[Any] # ("Helvetica", 12, BOLD) + | tuple[Any, ...] + | _tkinter.Tcl_Obj # A font object constructed in Tcl +) class _FontDict(TypedDict): family: str @@ -101,6 +100,7 @@ class Font: @overload def metrics(self, *, displayof: tkinter.Misc | None = ...) -> _MetricsDict: ... def measure(self, text: str, displayof: tkinter.Misc | None = ...) -> int: ... + def __eq__(self, other: object) -> bool: ... def families(root: tkinter.Misc | None = ..., displayof: tkinter.Misc | None = ...) -> tuple[str, ...]: ... def names(root: tkinter.Misc | None = ...) -> tuple[str, ...]: ... diff --git a/mypy/typeshed/stdlib/tkinter/messagebox.pyi b/mypy/typeshed/stdlib/tkinter/messagebox.pyi index fc4afcef0cc21..96109b1167867 100644 --- a/mypy/typeshed/stdlib/tkinter/messagebox.pyi +++ b/mypy/typeshed/stdlib/tkinter/messagebox.pyi @@ -1,6 +1,19 @@ +import sys from tkinter.commondialog import Dialog from typing import Any, ClassVar +if sys.version_info >= (3, 9): + __all__ = [ + "showinfo", + "showwarning", + "showerror", + "askquestion", + "askokcancel", + "askyesno", + "askyesnocancel", + "askretrycancel", + ] + ERROR: str INFO: str QUESTION: str diff --git a/mypy/typeshed/stdlib/tkinter/scrolledtext.pyi b/mypy/typeshed/stdlib/tkinter/scrolledtext.pyi index 246979d5afd7a..00309431d457e 100644 --- a/mypy/typeshed/stdlib/tkinter/scrolledtext.pyi +++ b/mypy/typeshed/stdlib/tkinter/scrolledtext.pyi @@ -1,6 +1,8 @@ from tkinter import Frame, Misc, Scrollbar, Text from typing import Any +__all__ = ["ScrolledText"] + # The methods from Pack, Place, and Grid are dynamically added over the parent's impls class ScrolledText(Text): frame: Frame diff --git a/mypy/typeshed/stdlib/tkinter/simpledialog.pyi b/mypy/typeshed/stdlib/tkinter/simpledialog.pyi index ec801afaceee7..fbe78530721f3 100644 --- a/mypy/typeshed/stdlib/tkinter/simpledialog.pyi +++ b/mypy/typeshed/stdlib/tkinter/simpledialog.pyi @@ -4,7 +4,7 @@ from typing import Any class Dialog(Toplevel): def __init__(self, parent: Misc | None, title: str | None = ...) -> None: ... def body(self, master) -> None: ... - def buttonbox(self): ... + def buttonbox(self) -> None: ... class SimpleDialog: def __init__( @@ -22,6 +22,6 @@ class SimpleDialog: def wm_delete_window(self) -> None: ... def done(self, num: int) -> None: ... -def askfloat(title: str | None, prompt: str, **kwargs: Any) -> float: ... -def askinteger(title: str | None, prompt: str, **kwargs: Any) -> int: ... -def askstring(title: str | None, prompt: str, **kwargs: Any) -> str: ... +def askfloat(title: str | None, prompt: str, **kwargs: Any) -> float | None: ... +def askinteger(title: str | None, prompt: str, **kwargs: Any) -> int | None: ... +def askstring(title: str | None, prompt: str, **kwargs: Any) -> str | None: ... diff --git a/mypy/typeshed/stdlib/tkinter/tix.pyi b/mypy/typeshed/stdlib/tkinter/tix.pyi index 6842ab7b1108d..6f9201a1bdf95 100644 --- a/mypy/typeshed/stdlib/tkinter/tix.pyi +++ b/mypy/typeshed/stdlib/tkinter/tix.pyi @@ -45,7 +45,7 @@ class tixCommand: def tix_resetoptions(self, newScheme: str, newFontSet: str, newScmPrio: str | None = ...) -> None: ... class Tk(tkinter.Tk, tixCommand): - def __init__(self, screenName: str | None = ..., baseName: str | None = ..., className: str = ...): ... + def __init__(self, screenName: str | None = ..., baseName: str | None = ..., className: str = ...) -> None: ... class TixWidget(tkinter.Widget): def __init__( diff --git a/mypy/typeshed/stdlib/tkinter/ttk.pyi b/mypy/typeshed/stdlib/tkinter/ttk.pyi index f7319291da6da..c48b5cd7aa0da 100644 --- a/mypy/typeshed/stdlib/tkinter/ttk.pyi +++ b/mypy/typeshed/stdlib/tkinter/ttk.pyi @@ -2,10 +2,66 @@ import _tkinter import sys import tkinter from tkinter.font import _FontDescription -from typing import Any, Callable, Union, overload +from typing import Any, Callable, overload from typing_extensions import Literal, TypedDict -def tclobjs_to_py(adict): ... +if sys.version_info >= (3, 7): + __all__ = [ + "Button", + "Checkbutton", + "Combobox", + "Entry", + "Frame", + "Label", + "Labelframe", + "LabelFrame", + "Menubutton", + "Notebook", + "Panedwindow", + "PanedWindow", + "Progressbar", + "Radiobutton", + "Scale", + "Scrollbar", + "Separator", + "Sizegrip", + "Spinbox", + "Style", + "Treeview", + "LabeledScale", + "OptionMenu", + "tclobjs_to_py", + "setup_master", + ] +else: + __all__ = [ + "Button", + "Checkbutton", + "Combobox", + "Entry", + "Frame", + "Label", + "Labelframe", + "LabelFrame", + "Menubutton", + "Notebook", + "Panedwindow", + "PanedWindow", + "Progressbar", + "Radiobutton", + "Scale", + "Scrollbar", + "Separator", + "Sizegrip", + "Style", + "Treeview", + "LabeledScale", + "OptionMenu", + "tclobjs_to_py", + "setup_master", + ] + +def tclobjs_to_py(adict: dict[Any, Any]) -> dict[Any, Any]: ... def setup_master(master: Any | None = ...): ... # from ttk_widget (aka ttk::widget) manual page, differs from tkinter._Compound @@ -14,16 +70,16 @@ _TtkCompound = Literal["text", "image", tkinter._Compound] class Style: master: Any tk: _tkinter.TkappType - def __init__(self, master: tkinter.Misc | None = ...): ... + def __init__(self, master: tkinter.Misc | None = ...) -> None: ... def configure(self, style, query_opt: Any | None = ..., **kw): ... def map(self, style, query_opt: Any | None = ..., **kw): ... def lookup(self, style, option, state: Any | None = ..., default: Any | None = ...): ... def layout(self, style, layoutspec: Any | None = ...): ... - def element_create(self, elementname, etype, *args, **kw): ... + def element_create(self, elementname, etype, *args, **kw) -> None: ... def element_names(self): ... def element_options(self, elementname): ... - def theme_create(self, themename, parent: Any | None = ..., settings: Any | None = ...): ... - def theme_settings(self, themename, settings): ... + def theme_create(self, themename, parent: Any | None = ..., settings: Any | None = ...) -> None: ... + def theme_settings(self, themename, settings) -> None: ... def theme_names(self) -> tuple[str, ...]: ... @overload def theme_use(self, themename: str) -> None: ... @@ -31,8 +87,8 @@ class Style: def theme_use(self, themename: None = ...) -> str: ... class Widget(tkinter.Widget): - def __init__(self, master: tkinter.Misc | None, widgetname, kw: Any | None = ...): ... - def identify(self, x, y): ... + def __init__(self, master: tkinter.Misc | None, widgetname, kw: Any | None = ...) -> None: ... + def identify(self, x: int, y: int) -> str: ... def instate(self, statespec, callback: Any | None = ..., *args, **kw): ... def state(self, statespec: Any | None = ...): ... @@ -207,8 +263,8 @@ class Entry(Widget, tkinter.Entry): ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload def config(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... - def bbox(self, index): ... - def identify(self, x, y): ... + def bbox(self, index) -> tuple[int, int, int, int]: ... # type: ignore[override] + def identify(self, x: int, y: int) -> str: ... def validate(self): ... class Combobox(Entry): @@ -293,8 +349,8 @@ class Combobox(Entry): ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload def config(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... - def current(self, newindex: Any | None = ...): ... - def set(self, value): ... + def current(self, newindex: int | None = ...) -> int: ... + def set(self, value: Any) -> None: ... class Frame(Widget): def __init__( @@ -521,11 +577,11 @@ class Notebook(Widget): compound: tkinter._Compound = ..., underline: int = ..., ) -> None: ... - def forget(self, tab_id): ... - def hide(self, tab_id): ... - def identify(self, x, y): ... + def forget(self, tab_id) -> None: ... + def hide(self, tab_id) -> None: ... + def identify(self, x: int, y: int) -> str: ... def index(self, tab_id): ... - def insert(self, pos, child, **kw): ... + def insert(self, pos, child, **kw) -> None: ... def select(self, tab_id: Any | None = ...): ... def tab(self, tab_id, option: Any | None = ..., **kw): ... def tabs(self): ... @@ -575,7 +631,7 @@ class Panedwindow(Widget, tkinter.PanedWindow): @overload def config(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... forget: Any - def insert(self, pos, child, **kw): ... + def insert(self, pos, child, **kw) -> None: ... def pane(self, pane, option: Any | None = ..., **kw): ... def sashpos(self, index, newpos: Any | None = ...): ... @@ -618,9 +674,9 @@ class Progressbar(Widget): @overload def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure - def start(self, interval: Any | None = ...): ... - def step(self, amount: Any | None = ...): ... - def stop(self): ... + def start(self, interval: Literal["idle"] | int | None = ...) -> None: ... + def step(self, amount: float | None = ...) -> None: ... + def stop(self) -> None: ... class Radiobutton(Widget): def __init__( @@ -669,7 +725,8 @@ class Radiobutton(Widget): config = configure def invoke(self) -> Any: ... -class Scale(Widget, tkinter.Scale): +# type ignore, because identify() methods of Widget and tkinter.Scale are incompatible +class Scale(Widget, tkinter.Scale): # type: ignore[misc] def __init__( self, master: tkinter.Misc | None = ..., @@ -727,9 +784,10 @@ class Scale(Widget, tkinter.Scale): ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... @overload def config(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... - def get(self, x: Any | None = ..., y: Any | None = ...): ... + def get(self, x: int | None = ..., y: int | None = ...) -> float: ... -class Scrollbar(Widget, tkinter.Scrollbar): +# type ignore, because identify() methods of Widget and tkinter.Scale are incompatible +class Scrollbar(Widget, tkinter.Scrollbar): # type: ignore[misc] def __init__( self, master: tkinter.Misc | None = ..., @@ -902,7 +960,7 @@ class _TreeviewTagDict(TypedDict): class _TreeviewHeaderDict(TypedDict): text: str - image: list[str] + image: list[str] | Literal[""] anchor: tkinter._Anchor command: str state: str # Doesn't seem to appear anywhere else than in these dicts @@ -914,7 +972,7 @@ class _TreeviewColumnDict(TypedDict): anchor: tkinter._Anchor id: str -_TreeviewColumnId = Union[int, str] # manual page: "COLUMN IDENTIFIERS" +_TreeviewColumnId = int | str # manual page: "COLUMN IDENTIFIERS" class Treeview(Widget, tkinter.XView, tkinter.YView): def __init__( @@ -994,7 +1052,7 @@ class Treeview(Widget, tkinter.XView, tkinter.YView): @overload def heading(self, column: _TreeviewColumnId, option: Literal["text"]) -> str: ... @overload - def heading(self, column: _TreeviewColumnId, option: Literal["image"]) -> tuple[str]: ... + def heading(self, column: _TreeviewColumnId, option: Literal["image"]) -> tuple[str] | str: ... @overload def heading(self, column: _TreeviewColumnId, option: Literal["anchor"]) -> _tkinter.Tcl_Obj: ... @overload @@ -1002,6 +1060,8 @@ class Treeview(Widget, tkinter.XView, tkinter.YView): @overload def heading(self, column: _TreeviewColumnId, option: str) -> Any: ... @overload + def heading(self, column: _TreeviewColumnId, option: None = ...) -> _TreeviewHeaderDict: ... # type: ignore[misc] + @overload def heading( self, column: _TreeviewColumnId, @@ -1011,8 +1071,8 @@ class Treeview(Widget, tkinter.XView, tkinter.YView): image: tkinter._ImageSpec = ..., anchor: tkinter._Anchor = ..., command: str | Callable[[], Any] = ..., - ) -> _TreeviewHeaderDict | None: ... - def identify(self, component, x, y): ... + ) -> None: ... + def identify(self, component, x, y): ... # Internal Method. Leave untyped def identify_row(self, y: int) -> str: ... def identify_column(self, x: int) -> str: ... def identify_region(self, x: int, y: int) -> Literal["heading", "separator", "tree", "cell", "nothing"]: ... @@ -1044,6 +1104,8 @@ class Treeview(Widget, tkinter.XView, tkinter.YView): @overload def item(self, item: str, option: str) -> Any: ... @overload + def item(self, item: str, option: None = ...) -> _TreeviewItemDict: ... # type: ignore[misc] + @overload def item( self, item: str, @@ -1054,7 +1116,7 @@ class Treeview(Widget, tkinter.XView, tkinter.YView): values: list[Any] | tuple[Any, ...] | Literal[""] = ..., open: bool = ..., tags: str | list[str] | tuple[str, ...] = ..., - ) -> _TreeviewItemDict | None: ... + ) -> None: ... def move(self, item: str, parent: str, index: int) -> None: ... reattach = move def next(self, item: str) -> str: ... # returning empty string means last item @@ -1065,6 +1127,7 @@ class Treeview(Widget, tkinter.XView, tkinter.YView): def selection(self) -> tuple[str, ...]: ... else: def selection(self, selop: Any | None = ..., items: Any | None = ...) -> tuple[str, ...]: ... + def selection_set(self, items: str | list[str] | tuple[str, ...]) -> None: ... def selection_add(self, items: str | list[str] | tuple[str, ...]) -> None: ... def selection_remove(self, items: str | list[str] | tuple[str, ...]) -> None: ... @@ -1119,7 +1182,7 @@ class LabeledScale(Frame): from_: float = ..., to: float = ..., *, - compound: Literal["top"] | Literal["bottom"] = ..., + compound: Literal["top", "bottom"] = ..., **kw: Any, ) -> None: ... # destroy is overridden, signature does not change @@ -1134,9 +1197,9 @@ class OptionMenu(Menubutton): *values: str, # rest of these are keyword-only because *args syntax used above style: str = ..., - direction: Literal["above"] | Literal["below"] | Literal["left"] | Literal["right"] | Literal["flush"] = ..., + direction: Literal["above", "below", "left", "right", "flush"] = ..., command: Callable[[tkinter.StringVar], Any] | None = ..., ) -> None: ... # configure, config, cget, destroy are inherited from Menubutton # destroy and __setitem__ are overridden, signature does not change - def set_menu(self, default: Any | None = ..., *values): ... + def set_menu(self, default: Any | None = ..., *values) -> None: ... diff --git a/mypy/typeshed/stdlib/token.pyi b/mypy/typeshed/stdlib/token.pyi index 9451015e9df50..49329ec442f02 100644 --- a/mypy/typeshed/stdlib/token.pyi +++ b/mypy/typeshed/stdlib/token.pyi @@ -1,5 +1,284 @@ import sys +if sys.version_info >= (3, 10): + __all__ = [ + "tok_name", + "ISTERMINAL", + "ISNONTERMINAL", + "ISEOF", + "ENDMARKER", + "NAME", + "NUMBER", + "STRING", + "NEWLINE", + "INDENT", + "DEDENT", + "LPAR", + "RPAR", + "LSQB", + "RSQB", + "COLON", + "COMMA", + "SEMI", + "PLUS", + "MINUS", + "STAR", + "SLASH", + "VBAR", + "AMPER", + "LESS", + "GREATER", + "EQUAL", + "DOT", + "PERCENT", + "LBRACE", + "RBRACE", + "EQEQUAL", + "NOTEQUAL", + "LESSEQUAL", + "GREATEREQUAL", + "TILDE", + "CIRCUMFLEX", + "LEFTSHIFT", + "RIGHTSHIFT", + "DOUBLESTAR", + "PLUSEQUAL", + "MINEQUAL", + "STAREQUAL", + "SLASHEQUAL", + "PERCENTEQUAL", + "AMPEREQUAL", + "VBAREQUAL", + "CIRCUMFLEXEQUAL", + "LEFTSHIFTEQUAL", + "RIGHTSHIFTEQUAL", + "DOUBLESTAREQUAL", + "DOUBLESLASH", + "DOUBLESLASHEQUAL", + "AT", + "ATEQUAL", + "RARROW", + "ELLIPSIS", + "COLONEQUAL", + "OP", + "AWAIT", + "ASYNC", + "TYPE_IGNORE", + "TYPE_COMMENT", + "SOFT_KEYWORD", + "ERRORTOKEN", + "COMMENT", + "NL", + "ENCODING", + "N_TOKENS", + "NT_OFFSET", + ] +elif sys.version_info >= (3, 8): + __all__ = [ + "tok_name", + "ISTERMINAL", + "ISNONTERMINAL", + "ISEOF", + "ENDMARKER", + "NAME", + "NUMBER", + "STRING", + "NEWLINE", + "INDENT", + "DEDENT", + "LPAR", + "RPAR", + "LSQB", + "RSQB", + "COLON", + "COMMA", + "SEMI", + "PLUS", + "MINUS", + "STAR", + "SLASH", + "VBAR", + "AMPER", + "LESS", + "GREATER", + "EQUAL", + "DOT", + "PERCENT", + "LBRACE", + "RBRACE", + "EQEQUAL", + "NOTEQUAL", + "LESSEQUAL", + "GREATEREQUAL", + "TILDE", + "CIRCUMFLEX", + "LEFTSHIFT", + "RIGHTSHIFT", + "DOUBLESTAR", + "PLUSEQUAL", + "MINEQUAL", + "STAREQUAL", + "SLASHEQUAL", + "PERCENTEQUAL", + "AMPEREQUAL", + "VBAREQUAL", + "CIRCUMFLEXEQUAL", + "LEFTSHIFTEQUAL", + "RIGHTSHIFTEQUAL", + "DOUBLESTAREQUAL", + "DOUBLESLASH", + "DOUBLESLASHEQUAL", + "AT", + "ATEQUAL", + "RARROW", + "ELLIPSIS", + "COLONEQUAL", + "OP", + "AWAIT", + "ASYNC", + "TYPE_IGNORE", + "TYPE_COMMENT", + "ERRORTOKEN", + "COMMENT", + "NL", + "ENCODING", + "N_TOKENS", + "NT_OFFSET", + ] +elif sys.version_info >= (3, 7): + __all__ = [ + "tok_name", + "ISTERMINAL", + "ISNONTERMINAL", + "ISEOF", + "ENDMARKER", + "NAME", + "NUMBER", + "STRING", + "NEWLINE", + "INDENT", + "DEDENT", + "LPAR", + "RPAR", + "LSQB", + "RSQB", + "COLON", + "COMMA", + "SEMI", + "PLUS", + "MINUS", + "STAR", + "SLASH", + "VBAR", + "AMPER", + "LESS", + "GREATER", + "EQUAL", + "DOT", + "PERCENT", + "LBRACE", + "RBRACE", + "EQEQUAL", + "NOTEQUAL", + "LESSEQUAL", + "GREATEREQUAL", + "TILDE", + "CIRCUMFLEX", + "LEFTSHIFT", + "RIGHTSHIFT", + "DOUBLESTAR", + "PLUSEQUAL", + "MINEQUAL", + "STAREQUAL", + "SLASHEQUAL", + "PERCENTEQUAL", + "AMPEREQUAL", + "VBAREQUAL", + "CIRCUMFLEXEQUAL", + "LEFTSHIFTEQUAL", + "RIGHTSHIFTEQUAL", + "DOUBLESTAREQUAL", + "DOUBLESLASH", + "DOUBLESLASHEQUAL", + "AT", + "ATEQUAL", + "RARROW", + "ELLIPSIS", + "OP", + "ERRORTOKEN", + "COMMENT", + "NL", + "ENCODING", + "N_TOKENS", + "NT_OFFSET", + ] +else: + __all__ = [ + "tok_name", + "ISTERMINAL", + "ISNONTERMINAL", + "ISEOF", + "ENDMARKER", + "NAME", + "NUMBER", + "STRING", + "NEWLINE", + "INDENT", + "DEDENT", + "LPAR", + "RPAR", + "LSQB", + "RSQB", + "COLON", + "COMMA", + "SEMI", + "PLUS", + "MINUS", + "STAR", + "SLASH", + "VBAR", + "AMPER", + "LESS", + "GREATER", + "EQUAL", + "DOT", + "PERCENT", + "LBRACE", + "RBRACE", + "EQEQUAL", + "NOTEQUAL", + "LESSEQUAL", + "GREATEREQUAL", + "TILDE", + "CIRCUMFLEX", + "LEFTSHIFT", + "RIGHTSHIFT", + "DOUBLESTAR", + "PLUSEQUAL", + "MINEQUAL", + "STAREQUAL", + "SLASHEQUAL", + "PERCENTEQUAL", + "AMPEREQUAL", + "VBAREQUAL", + "CIRCUMFLEXEQUAL", + "LEFTSHIFTEQUAL", + "RIGHTSHIFTEQUAL", + "DOUBLESTAREQUAL", + "DOUBLESLASH", + "DOUBLESLASHEQUAL", + "AT", + "ATEQUAL", + "RARROW", + "ELLIPSIS", + "OP", + "AWAIT", + "ASYNC", + "ERRORTOKEN", + "N_TOKENS", + "NT_OFFSET", + ] + ENDMARKER: int NAME: int NUMBER: int diff --git a/mypy/typeshed/stdlib/tokenize.pyi b/mypy/typeshed/stdlib/tokenize.pyi index 7614ebfe403e0..7b17e8de6153f 100644 --- a/mypy/typeshed/stdlib/tokenize.pyi +++ b/mypy/typeshed/stdlib/tokenize.pyi @@ -1,8 +1,313 @@ import sys from _typeshed import StrOrBytesPath from builtins import open as _builtin_open -from token import * # noqa: F403 -from typing import Any, Callable, Generator, Iterable, NamedTuple, Pattern, Sequence, TextIO, Union +from token import * +from typing import Any, Callable, Generator, Iterable, NamedTuple, Pattern, Sequence, TextIO + +if sys.version_info >= (3, 10): + __all__ = [ + "tok_name", + "ISTERMINAL", + "ISNONTERMINAL", + "ISEOF", + "ENDMARKER", + "NAME", + "NUMBER", + "STRING", + "NEWLINE", + "INDENT", + "DEDENT", + "LPAR", + "RPAR", + "LSQB", + "RSQB", + "COLON", + "COMMA", + "SEMI", + "PLUS", + "MINUS", + "STAR", + "SLASH", + "VBAR", + "AMPER", + "LESS", + "GREATER", + "EQUAL", + "DOT", + "PERCENT", + "LBRACE", + "RBRACE", + "EQEQUAL", + "NOTEQUAL", + "LESSEQUAL", + "GREATEREQUAL", + "TILDE", + "CIRCUMFLEX", + "LEFTSHIFT", + "RIGHTSHIFT", + "DOUBLESTAR", + "PLUSEQUAL", + "MINEQUAL", + "STAREQUAL", + "SLASHEQUAL", + "PERCENTEQUAL", + "AMPEREQUAL", + "VBAREQUAL", + "CIRCUMFLEXEQUAL", + "LEFTSHIFTEQUAL", + "RIGHTSHIFTEQUAL", + "DOUBLESTAREQUAL", + "DOUBLESLASH", + "DOUBLESLASHEQUAL", + "AT", + "ATEQUAL", + "RARROW", + "ELLIPSIS", + "COLONEQUAL", + "OP", + "AWAIT", + "ASYNC", + "TYPE_IGNORE", + "TYPE_COMMENT", + "SOFT_KEYWORD", + "ERRORTOKEN", + "COMMENT", + "NL", + "ENCODING", + "N_TOKENS", + "NT_OFFSET", + "tokenize", + "generate_tokens", + "detect_encoding", + "untokenize", + "TokenInfo", + ] +elif sys.version_info >= (3, 8): + __all__ = [ + "tok_name", + "ISTERMINAL", + "ISNONTERMINAL", + "ISEOF", + "ENDMARKER", + "NAME", + "NUMBER", + "STRING", + "NEWLINE", + "INDENT", + "DEDENT", + "LPAR", + "RPAR", + "LSQB", + "RSQB", + "COLON", + "COMMA", + "SEMI", + "PLUS", + "MINUS", + "STAR", + "SLASH", + "VBAR", + "AMPER", + "LESS", + "GREATER", + "EQUAL", + "DOT", + "PERCENT", + "LBRACE", + "RBRACE", + "EQEQUAL", + "NOTEQUAL", + "LESSEQUAL", + "GREATEREQUAL", + "TILDE", + "CIRCUMFLEX", + "LEFTSHIFT", + "RIGHTSHIFT", + "DOUBLESTAR", + "PLUSEQUAL", + "MINEQUAL", + "STAREQUAL", + "SLASHEQUAL", + "PERCENTEQUAL", + "AMPEREQUAL", + "VBAREQUAL", + "CIRCUMFLEXEQUAL", + "LEFTSHIFTEQUAL", + "RIGHTSHIFTEQUAL", + "DOUBLESTAREQUAL", + "DOUBLESLASH", + "DOUBLESLASHEQUAL", + "AT", + "ATEQUAL", + "RARROW", + "ELLIPSIS", + "COLONEQUAL", + "OP", + "AWAIT", + "ASYNC", + "TYPE_IGNORE", + "TYPE_COMMENT", + "ERRORTOKEN", + "COMMENT", + "NL", + "ENCODING", + "N_TOKENS", + "NT_OFFSET", + "tokenize", + "generate_tokens", + "detect_encoding", + "untokenize", + "TokenInfo", + ] +elif sys.version_info >= (3, 7): + __all__ = [ + "tok_name", + "ISTERMINAL", + "ISNONTERMINAL", + "ISEOF", + "ENDMARKER", + "NAME", + "NUMBER", + "STRING", + "NEWLINE", + "INDENT", + "DEDENT", + "LPAR", + "RPAR", + "LSQB", + "RSQB", + "COLON", + "COMMA", + "SEMI", + "PLUS", + "MINUS", + "STAR", + "SLASH", + "VBAR", + "AMPER", + "LESS", + "GREATER", + "EQUAL", + "DOT", + "PERCENT", + "LBRACE", + "RBRACE", + "EQEQUAL", + "NOTEQUAL", + "LESSEQUAL", + "GREATEREQUAL", + "TILDE", + "CIRCUMFLEX", + "LEFTSHIFT", + "RIGHTSHIFT", + "DOUBLESTAR", + "PLUSEQUAL", + "MINEQUAL", + "STAREQUAL", + "SLASHEQUAL", + "PERCENTEQUAL", + "AMPEREQUAL", + "VBAREQUAL", + "CIRCUMFLEXEQUAL", + "LEFTSHIFTEQUAL", + "RIGHTSHIFTEQUAL", + "DOUBLESTAREQUAL", + "DOUBLESLASH", + "DOUBLESLASHEQUAL", + "AT", + "ATEQUAL", + "RARROW", + "ELLIPSIS", + "OP", + "ERRORTOKEN", + "COMMENT", + "NL", + "ENCODING", + "N_TOKENS", + "NT_OFFSET", + "tokenize", + "detect_encoding", + "untokenize", + "TokenInfo", + ] +else: + __all__ = [ + "tok_name", + "ISTERMINAL", + "ISNONTERMINAL", + "ISEOF", + "ENDMARKER", + "NAME", + "NUMBER", + "STRING", + "NEWLINE", + "INDENT", + "DEDENT", + "LPAR", + "RPAR", + "LSQB", + "RSQB", + "COLON", + "COMMA", + "SEMI", + "PLUS", + "MINUS", + "STAR", + "SLASH", + "VBAR", + "AMPER", + "LESS", + "GREATER", + "EQUAL", + "DOT", + "PERCENT", + "LBRACE", + "RBRACE", + "EQEQUAL", + "NOTEQUAL", + "LESSEQUAL", + "GREATEREQUAL", + "TILDE", + "CIRCUMFLEX", + "LEFTSHIFT", + "RIGHTSHIFT", + "DOUBLESTAR", + "PLUSEQUAL", + "MINEQUAL", + "STAREQUAL", + "SLASHEQUAL", + "PERCENTEQUAL", + "AMPEREQUAL", + "VBAREQUAL", + "CIRCUMFLEXEQUAL", + "LEFTSHIFTEQUAL", + "RIGHTSHIFTEQUAL", + "DOUBLESTAREQUAL", + "DOUBLESLASH", + "DOUBLESLASHEQUAL", + "AT", + "ATEQUAL", + "RARROW", + "ELLIPSIS", + "OP", + "AWAIT", + "ASYNC", + "ERRORTOKEN", + "N_TOKENS", + "NT_OFFSET", + "COMMENT", + "tokenize", + "detect_encoding", + "NL", + "untokenize", + "ENCODING", + "TokenInfo", + ] + +if sys.version_info >= (3, 8): + from token import EXACT_TOKEN_TYPES as EXACT_TOKEN_TYPES +else: + EXACT_TOKEN_TYPES: dict[str, int] if sys.version_info < (3, 7): COMMENT: int @@ -26,7 +331,7 @@ class TokenInfo(_TokenInfo): def exact_type(self) -> int: ... # Backwards compatible tokens can be sequences of a shorter length too -_Token = Union[TokenInfo, Sequence[Union[int, str, _Position]]] +_Token = TokenInfo | Sequence[int | str | _Position] class TokenError(Exception): ... class StopTokenizing(Exception): ... # undocumented diff --git a/mypy/typeshed/stdlib/tomllib.pyi b/mypy/typeshed/stdlib/tomllib.pyi new file mode 100644 index 0000000000000..3a6ce93f87e14 --- /dev/null +++ b/mypy/typeshed/stdlib/tomllib.pyi @@ -0,0 +1,10 @@ +from _typeshed import SupportsRead +from collections.abc import Callable +from typing import Any + +__all__ = ("loads", "load", "TOMLDecodeError") + +class TOMLDecodeError(ValueError): ... + +def load(__fp: SupportsRead[bytes], *, parse_float: Callable[[str], Any] = ...) -> dict[str, Any]: ... +def loads(__s: str, *, parse_float: Callable[[str], Any] = ...) -> dict[str, Any]: ... diff --git a/mypy/typeshed/stdlib/trace.pyi b/mypy/typeshed/stdlib/trace.pyi index ee8dffa678208..6128064478bcb 100644 --- a/mypy/typeshed/stdlib/trace.pyi +++ b/mypy/typeshed/stdlib/trace.pyi @@ -1,13 +1,15 @@ import sys import types from _typeshed import StrPath -from typing import Any, Callable, Mapping, Optional, Sequence, TypeVar +from typing import Any, Callable, Mapping, Sequence, TypeVar from typing_extensions import ParamSpec +__all__ = ["Trace", "CoverageResults"] + _T = TypeVar("_T") _P = ParamSpec("_P") _localtrace = Callable[[types.FrameType, str, Any], Callable[..., Any]] -_fileModuleFunction = tuple[str, Optional[str], str] +_fileModuleFunction = tuple[str, str | None, str] class CoverageResults: def __init__( @@ -46,6 +48,7 @@ class Trace: def runfunc(self, __func: Callable[_P, _T], *args: _P.args, **kw: _P.kwargs) -> _T: ... else: def runfunc(self, func: Callable[_P, _T], *args: _P.args, **kw: _P.kwargs) -> _T: ... + def file_module_function_of(self, frame: types.FrameType) -> _fileModuleFunction: ... def globaltrace_trackcallers(self, frame: types.FrameType, why: str, arg: Any) -> None: ... def globaltrace_countfuncs(self, frame: types.FrameType, why: str, arg: Any) -> None: ... diff --git a/mypy/typeshed/stdlib/traceback.pyi b/mypy/typeshed/stdlib/traceback.pyi index 4e36490c24e4f..859bfef646228 100644 --- a/mypy/typeshed/stdlib/traceback.pyi +++ b/mypy/typeshed/stdlib/traceback.pyi @@ -1,16 +1,39 @@ import sys -from _typeshed import SupportsWrite +from _typeshed import Self, SupportsWrite from types import FrameType, TracebackType -from typing import IO, Any, Generator, Iterable, Iterator, Mapping, Optional, Type, overload +from typing import IO, Any, Generator, Iterable, Iterator, Mapping, overload +from typing_extensions import Literal -_PT = tuple[str, int, str, Optional[str]] +__all__ = [ + "extract_stack", + "extract_tb", + "format_exception", + "format_exception_only", + "format_list", + "format_stack", + "format_tb", + "print_exc", + "format_exc", + "print_exception", + "print_last", + "print_stack", + "print_tb", + "clear_frames", + "FrameSummary", + "StackSummary", + "TracebackException", + "walk_stack", + "walk_tb", +] + +_PT = tuple[str, int, str, str | None] def print_tb(tb: TracebackType | None, limit: int | None = ..., file: IO[str] | None = ...) -> None: ... if sys.version_info >= (3, 10): @overload def print_exception( - __exc: Type[BaseException] | None, + __exc: type[BaseException] | None, value: BaseException | None = ..., tb: TracebackType | None = ..., limit: int | None = ..., @@ -23,7 +46,7 @@ if sys.version_info >= (3, 10): ) -> None: ... @overload def format_exception( - __exc: Type[BaseException] | None, + __exc: type[BaseException] | None, value: BaseException | None = ..., tb: TracebackType | None = ..., limit: int | None = ..., @@ -34,7 +57,7 @@ if sys.version_info >= (3, 10): else: def print_exception( - etype: Type[BaseException] | None, + etype: type[BaseException] | None, value: BaseException | None, tb: TracebackType | None, limit: int | None = ..., @@ -42,7 +65,7 @@ else: chain: bool = ..., ) -> None: ... def format_exception( - etype: Type[BaseException] | None, + etype: type[BaseException] | None, value: BaseException | None, tb: TracebackType | None, limit: int | None = ..., @@ -60,10 +83,10 @@ def format_list(extracted_list: list[FrameSummary]) -> list[str]: ... def print_list(extracted_list: list[FrameSummary], file: SupportsWrite[str] | None = ...) -> None: ... if sys.version_info >= (3, 10): - def format_exception_only(__exc: Type[BaseException] | None, value: BaseException | None = ...) -> list[str]: ... + def format_exception_only(__exc: type[BaseException] | None, value: BaseException | None = ...) -> list[str]: ... else: - def format_exception_only(etype: Type[BaseException] | None, value: BaseException | None) -> list[str]: ... + def format_exception_only(etype: type[BaseException] | None, value: BaseException | None) -> list[str]: ... def format_exc(limit: int | None = ..., chain: bool = ...) -> str: ... def format_tb(tb: TracebackType | None, limit: int | None = ...) -> list[str]: ... @@ -77,7 +100,7 @@ class TracebackException: __context__: TracebackException __suppress_context__: bool stack: StackSummary - exc_type: Type[BaseException] + exc_type: type[BaseException] filename: str lineno: int text: str @@ -86,7 +109,7 @@ class TracebackException: if sys.version_info >= (3, 10): def __init__( self, - exc_type: Type[BaseException], + exc_type: type[BaseException], exc_value: BaseException, exc_traceback: TracebackType | None, *, @@ -98,18 +121,18 @@ class TracebackException: ) -> None: ... @classmethod def from_exception( - cls, + cls: type[Self], exc: BaseException, *, limit: int | None = ..., lookup_lines: bool = ..., capture_locals: bool = ..., compact: bool = ..., - ) -> TracebackException: ... + ) -> Self: ... else: def __init__( self, - exc_type: Type[BaseException], + exc_type: type[BaseException], exc_value: BaseException, exc_traceback: TracebackType | None, *, @@ -120,31 +143,62 @@ class TracebackException: ) -> None: ... @classmethod def from_exception( - cls, exc: BaseException, *, limit: int | None = ..., lookup_lines: bool = ..., capture_locals: bool = ... - ) -> TracebackException: ... + cls: type[Self], exc: BaseException, *, limit: int | None = ..., lookup_lines: bool = ..., capture_locals: bool = ... + ) -> Self: ... + + def __eq__(self, other: object) -> bool: ... def format(self, *, chain: bool = ...) -> Generator[str, None, None]: ... def format_exception_only(self) -> Generator[str, None, None]: ... class FrameSummary(Iterable[Any]): + if sys.version_info >= (3, 11): + def __init__( + self, + filename: str, + lineno: int | None, + name: str, + *, + lookup_line: bool = ..., + locals: Mapping[str, str] | None = ..., + line: str | None = ..., + end_lineno: int | None = ..., + colno: int | None = ..., + end_colno: int | None = ..., + ) -> None: ... + end_lineno: int | None + colno: int | None + end_colno: int | None + else: + def __init__( + self, + filename: str, + lineno: int | None, + name: str, + *, + lookup_line: bool = ..., + locals: Mapping[str, str] | None = ..., + line: str | None = ..., + ) -> None: ... filename: str - lineno: int + lineno: int | None name: str - line: str locals: dict[str, str] | None - def __init__( - self, - filename: str, - lineno: int, - name: str, - *, - lookup_line: bool = ..., - locals: Mapping[str, str] | None = ..., - line: str | None = ..., - ) -> None: ... - # TODO: more precise typing for __getitem__ and __iter__, - # for a namedtuple-like view on (filename, lineno, name, str). - def __getitem__(self, i: int) -> Any: ... + @property + def line(self) -> str | None: ... + @overload + def __getitem__(self, pos: Literal[0]) -> str: ... + @overload + def __getitem__(self, pos: Literal[1]) -> int: ... + @overload + def __getitem__(self, pos: Literal[2]) -> str: ... + @overload + def __getitem__(self, pos: Literal[3]) -> str | None: ... + @overload + def __getitem__(self, pos: int) -> Any: ... def __iter__(self) -> Iterator[Any]: ... + def __eq__(self, other: object) -> bool: ... + if sys.version_info >= (3, 8): + def __len__(self) -> Literal[4]: ... class StackSummary(list[FrameSummary]): @classmethod diff --git a/mypy/typeshed/stdlib/tracemalloc.pyi b/mypy/typeshed/stdlib/tracemalloc.pyi index 4d7bbb7994a61..e2e6800cbab42 100644 --- a/mypy/typeshed/stdlib/tracemalloc.pyi +++ b/mypy/typeshed/stdlib/tracemalloc.pyi @@ -1,21 +1,25 @@ import sys from _tracemalloc import * -from typing import Optional, Sequence, Union, overload +from typing import Any, Sequence, Union, overload from typing_extensions import SupportsIndex def get_object_traceback(obj: object) -> Traceback | None: ... def take_snapshot() -> Snapshot: ... -class DomainFilter: +class BaseFilter: inclusive: bool - domain: int + def __init__(self, inclusive: bool) -> None: ... + +class DomainFilter(BaseFilter): + @property + def domain(self) -> int: ... def __init__(self, inclusive: bool, domain: int) -> None: ... -class Filter: +class Filter(BaseFilter): domain: int | None - inclusive: bool lineno: int | None - filename_pattern: str + @property + def filename_pattern(self) -> str: ... all_frames: bool def __init__( self, inclusive: bool, filename_pattern: str, lineno: int | None = ..., all_frames: bool = ..., domain: int | None = ... @@ -26,6 +30,7 @@ class Statistic: size: int traceback: Traceback def __init__(self, traceback: Traceback, size: int, count: int) -> None: ... + def __eq__(self, other: object) -> bool: ... class StatisticDiff: count: int @@ -34,28 +39,46 @@ class StatisticDiff: size_diff: int traceback: Traceback def __init__(self, traceback: Traceback, size: int, size_diff: int, count: int, count_diff: int) -> None: ... + def __eq__(self, other: object) -> bool: ... _FrameTupleT = tuple[str, int] class Frame: - filename: str - lineno: int + @property + def filename(self) -> str: ... + @property + def lineno(self) -> int: ... def __init__(self, frame: _FrameTupleT) -> None: ... + def __eq__(self, other: object) -> bool: ... + def __lt__(self, other: Frame) -> bool: ... + if sys.version_info >= (3, 11): + def __gt__(self, other: Frame) -> bool: ... + def __ge__(self, other: Frame) -> bool: ... + def __le__(self, other: Frame) -> bool: ... + else: + def __gt__(self, other: Frame, NotImplemented: Any = ...) -> bool: ... + def __ge__(self, other: Frame, NotImplemented: Any = ...) -> bool: ... + def __le__(self, other: Frame, NotImplemented: Any = ...) -> bool: ... if sys.version_info >= (3, 9): - _TraceTupleT = Union[tuple[int, int, Sequence[_FrameTupleT], Optional[int]], tuple[int, int, Sequence[_FrameTupleT]]] + _TraceTupleT = Union[tuple[int, int, Sequence[_FrameTupleT], int | None], tuple[int, int, Sequence[_FrameTupleT]]] else: _TraceTupleT = tuple[int, int, Sequence[_FrameTupleT]] class Trace: - domain: int - size: int - traceback: Traceback + @property + def domain(self) -> int: ... + @property + def size(self) -> int: ... + @property + def traceback(self) -> Traceback: ... def __init__(self, trace: _TraceTupleT) -> None: ... + def __eq__(self, other: object) -> bool: ... class Traceback(Sequence[Frame]): if sys.version_info >= (3, 9): - total_nframe: int | None + @property + def total_nframe(self) -> int | None: ... def __init__(self, frames: Sequence[_FrameTupleT], total_nframe: int | None = ...) -> None: ... else: def __init__(self, frames: Sequence[_FrameTupleT]) -> None: ... @@ -63,11 +86,23 @@ class Traceback(Sequence[Frame]): def format(self, limit: int | None = ..., most_recent_first: bool = ...) -> list[str]: ... else: def format(self, limit: int | None = ...) -> list[str]: ... + @overload - def __getitem__(self, i: SupportsIndex) -> Frame: ... + def __getitem__(self, index: SupportsIndex) -> Frame: ... @overload - def __getitem__(self, s: slice) -> Sequence[Frame]: ... + def __getitem__(self, index: slice) -> Sequence[Frame]: ... + def __contains__(self, frame: Frame) -> bool: ... # type: ignore[override] def __len__(self) -> int: ... + def __eq__(self, other: object) -> bool: ... + def __lt__(self, other: Traceback) -> bool: ... + if sys.version_info >= (3, 11): + def __gt__(self, other: Traceback) -> bool: ... + def __ge__(self, other: Traceback) -> bool: ... + def __le__(self, other: Traceback) -> bool: ... + else: + def __gt__(self, other: Traceback, NotImplemented: Any = ...) -> bool: ... + def __ge__(self, other: Traceback, NotImplemented: Any = ...) -> bool: ... + def __le__(self, other: Traceback, NotImplemented: Any = ...) -> bool: ... class Snapshot: def __init__(self, traces: Sequence[_TraceTupleT], traceback_limit: int) -> None: ... diff --git a/mypy/typeshed/stdlib/tty.pyi b/mypy/typeshed/stdlib/tty.pyi index 015669a680846..63f594a8fbb14 100644 --- a/mypy/typeshed/stdlib/tty.pyi +++ b/mypy/typeshed/stdlib/tty.pyi @@ -1,8 +1,8 @@ import sys -from typing import IO, Union +from typing import IO if sys.platform != "win32": - _FD = Union[int, IO[str]] + _FD = int | IO[str] # XXX: Undocumented integer constants IFLAG: int diff --git a/mypy/typeshed/stdlib/turtle.pyi b/mypy/typeshed/stdlib/turtle.pyi index e5efcb4f6ed91..2ff965465be6a 100644 --- a/mypy/typeshed/stdlib/turtle.pyi +++ b/mypy/typeshed/stdlib/turtle.pyi @@ -1,5 +1,131 @@ -from tkinter import Canvas, Frame, PhotoImage -from typing import Any, Callable, ClassVar, Sequence, TypeVar, Union, overload +from _typeshed import Self +from tkinter import Canvas, Frame, Misc, PhotoImage, Scrollbar +from typing import Any, Callable, ClassVar, Sequence, Union, overload + +__all__ = [ + "ScrolledCanvas", + "TurtleScreen", + "Screen", + "RawTurtle", + "Turtle", + "RawPen", + "Pen", + "Shape", + "Vec2D", + "addshape", + "bgcolor", + "bgpic", + "bye", + "clearscreen", + "colormode", + "delay", + "exitonclick", + "getcanvas", + "getshapes", + "listen", + "mainloop", + "mode", + "numinput", + "onkey", + "onkeypress", + "onkeyrelease", + "onscreenclick", + "ontimer", + "register_shape", + "resetscreen", + "screensize", + "setup", + "setworldcoordinates", + "textinput", + "title", + "tracer", + "turtles", + "update", + "window_height", + "window_width", + "back", + "backward", + "begin_fill", + "begin_poly", + "bk", + "circle", + "clear", + "clearstamp", + "clearstamps", + "clone", + "color", + "degrees", + "distance", + "dot", + "down", + "end_fill", + "end_poly", + "fd", + "fillcolor", + "filling", + "forward", + "get_poly", + "getpen", + "getscreen", + "get_shapepoly", + "getturtle", + "goto", + "heading", + "hideturtle", + "home", + "ht", + "isdown", + "isvisible", + "left", + "lt", + "onclick", + "ondrag", + "onrelease", + "pd", + "pen", + "pencolor", + "pendown", + "pensize", + "penup", + "pos", + "position", + "pu", + "radians", + "right", + "reset", + "resizemode", + "rt", + "seth", + "setheading", + "setpos", + "setposition", + "settiltangle", + "setundobuffer", + "setx", + "sety", + "shape", + "shapesize", + "shapetransform", + "shearfactor", + "showturtle", + "speed", + "st", + "stamp", + "tilt", + "tiltangle", + "towards", + "turtlesize", + "undo", + "undobufferentries", + "up", + "width", + "write", + "xcor", + "ycor", + "write_docstringdict", + "done", + "Terminator", +] # Note: '_Color' is the alias we use for arguments and _AnyColor is the # alias we use for return types. Really, these two aliases should be the @@ -11,14 +137,24 @@ _AnyColor = Any # TODO: Replace this with a TypedDict once it becomes standardized. _PenState = dict[str, Any] -_Speed = Union[str, float] +_Speed = str | float _PolygonCoords = Sequence[tuple[float, float]] # TODO: Type this more accurately # Vec2D is actually a custom subclass of 'tuple'. Vec2D = tuple[float, float] -class ScrolledCanvas(Frame): ... +# Does not actually inherit from Canvas, but dynamically gets all methods of Canvas +class ScrolledCanvas(Canvas, Frame): # type: ignore[misc] + bg: str + hscroll: Scrollbar + vscroll: Scrollbar + def __init__( + self, master: Misc | None, width: int = ..., height: int = ..., canvwidth: int = ..., canvheight: int = ... + ) -> None: ... + canvwidth: int + canvheight: int + def reset(self, canvwidth: int | None = ..., canvheight: int | None = ..., bg: str | None = ...) -> None: ... class TurtleScreenBase: cv: Canvas @@ -205,8 +341,6 @@ class TPen: st = showturtle ht = hideturtle -_T = TypeVar("_T") - class RawTurtle(TPen, TNavigator): screen: TurtleScreen screens: ClassVar[list[TurtleScreen]] @@ -217,7 +351,7 @@ class RawTurtle(TPen, TNavigator): def setundobuffer(self, size: int | None) -> None: ... def undobufferentries(self) -> int: ... def clear(self) -> None: ... - def clone(self: _T) -> _T: ... + def clone(self: Self) -> Self: ... @overload def shape(self, name: None = ...) -> str: ... @overload @@ -262,7 +396,7 @@ class RawTurtle(TPen, TNavigator): def end_poly(self) -> None: ... def get_poly(self) -> _PolygonCoords | None: ... def getscreen(self) -> TurtleScreen: ... - def getturtle(self: _T) -> _T: ... + def getturtle(self: Self) -> Self: ... getpen = getturtle def onclick(self, fun: Callable[[float, float], Any], btn: int = ..., add: bool | None = ...) -> None: ... def onrelease(self, fun: Callable[[float, float], Any], btn: int = ..., add: bool | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/types.pyi b/mypy/typeshed/stdlib/types.pyi index caf745b99554e..9b2fa1f4a2aad 100644 --- a/mypy/typeshed/stdlib/types.pyi +++ b/mypy/typeshed/stdlib/types.pyi @@ -7,6 +7,7 @@ from typing import ( AsyncGenerator, Awaitable, Callable, + ClassVar, Coroutine, Generator, Generic, @@ -16,16 +17,158 @@ from typing import ( KeysView, Mapping, MutableSequence, - Type, TypeVar, ValuesView, overload, ) from typing_extensions import Literal, ParamSpec, final +if sys.version_info >= (3, 10): + __all__ = [ + "FunctionType", + "LambdaType", + "CodeType", + "MappingProxyType", + "SimpleNamespace", + "CellType", + "GeneratorType", + "CoroutineType", + "AsyncGeneratorType", + "MethodType", + "BuiltinFunctionType", + "BuiltinMethodType", + "WrapperDescriptorType", + "MethodWrapperType", + "MethodDescriptorType", + "ClassMethodDescriptorType", + "ModuleType", + "TracebackType", + "FrameType", + "GetSetDescriptorType", + "MemberDescriptorType", + "new_class", + "resolve_bases", + "prepare_class", + "DynamicClassAttribute", + "coroutine", + "GenericAlias", + "UnionType", + "EllipsisType", + "NoneType", + "NotImplementedType", + ] +elif sys.version_info >= (3, 9): + __all__ = [ + "FunctionType", + "LambdaType", + "CodeType", + "MappingProxyType", + "SimpleNamespace", + "CellType", + "GeneratorType", + "CoroutineType", + "AsyncGeneratorType", + "MethodType", + "BuiltinFunctionType", + "BuiltinMethodType", + "WrapperDescriptorType", + "MethodWrapperType", + "MethodDescriptorType", + "ClassMethodDescriptorType", + "ModuleType", + "TracebackType", + "FrameType", + "GetSetDescriptorType", + "MemberDescriptorType", + "new_class", + "resolve_bases", + "prepare_class", + "DynamicClassAttribute", + "coroutine", + "GenericAlias", + ] +elif sys.version_info >= (3, 8): + __all__ = [ + "FunctionType", + "LambdaType", + "CodeType", + "MappingProxyType", + "SimpleNamespace", + "CellType", + "GeneratorType", + "CoroutineType", + "AsyncGeneratorType", + "MethodType", + "BuiltinFunctionType", + "BuiltinMethodType", + "WrapperDescriptorType", + "MethodWrapperType", + "MethodDescriptorType", + "ClassMethodDescriptorType", + "ModuleType", + "TracebackType", + "FrameType", + "GetSetDescriptorType", + "MemberDescriptorType", + "new_class", + "resolve_bases", + "prepare_class", + "DynamicClassAttribute", + "coroutine", + ] +elif sys.version_info >= (3, 7): + __all__ = [ + "FunctionType", + "LambdaType", + "CodeType", + "MappingProxyType", + "SimpleNamespace", + "GeneratorType", + "CoroutineType", + "AsyncGeneratorType", + "MethodType", + "BuiltinFunctionType", + "BuiltinMethodType", + "WrapperDescriptorType", + "MethodWrapperType", + "MethodDescriptorType", + "ClassMethodDescriptorType", + "ModuleType", + "TracebackType", + "FrameType", + "GetSetDescriptorType", + "MemberDescriptorType", + "new_class", + "resolve_bases", + "prepare_class", + "DynamicClassAttribute", + "coroutine", + ] +else: + __all__ = [ + "FunctionType", + "LambdaType", + "CodeType", + "MappingProxyType", + "SimpleNamespace", + "GeneratorType", + "CoroutineType", + "AsyncGeneratorType", + "MethodType", + "BuiltinFunctionType", + "ModuleType", + "TracebackType", + "FrameType", + "GetSetDescriptorType", + "MemberDescriptorType", + "new_class", + "prepare_class", + "DynamicClassAttribute", + "coroutine", + ] + # Note, all classes "defined" here require special handling. -_T = TypeVar("_T") _T1 = TypeVar("_T1") _T2 = TypeVar("_T2") _T_co = TypeVar("_T_co", covariant=True) @@ -36,21 +179,28 @@ _V_co = TypeVar("_V_co", covariant=True) @final class _Cell: - __hash__: None # type: ignore[assignment] + __hash__: ClassVar[None] # type: ignore[assignment] cell_contents: Any # Make sure this class definition stays roughly in line with `builtins.function` @final class FunctionType: - __closure__: tuple[_Cell, ...] | None + @property + def __closure__(self) -> tuple[_Cell, ...] | None: ... __code__: CodeType __defaults__: tuple[Any, ...] | None __dict__: dict[str, Any] - __globals__: dict[str, Any] + @property + def __globals__(self) -> dict[str, Any]: ... __name__: str __qualname__: str __annotations__: dict[str, Any] __kwdefaults__: dict[str, Any] + if sys.version_info >= (3, 10): + @property + def __builtins__(self) -> dict[str, Any]: ... + + __module__: str def __init__( self, code: CodeType, @@ -60,31 +210,49 @@ class FunctionType: closure: tuple[_Cell, ...] | None = ..., ) -> None: ... def __call__(self, *args: Any, **kwargs: Any) -> Any: ... - def __get__(self, obj: object | None, type: type | None = ...) -> MethodType: ... + @overload + def __get__(self, obj: None, type: type) -> FunctionType: ... + @overload + def __get__(self, obj: object, type: type | None = ...) -> MethodType: ... LambdaType = FunctionType @final class CodeType: - """Create a code object. Not for the faint of heart.""" - - co_argcount: int + @property + def co_argcount(self) -> int: ... if sys.version_info >= (3, 8): - co_posonlyargcount: int - co_kwonlyargcount: int - co_nlocals: int - co_stacksize: int - co_flags: int - co_code: bytes - co_consts: tuple[Any, ...] - co_names: tuple[str, ...] - co_varnames: tuple[str, ...] - co_filename: str - co_name: str - co_firstlineno: int - co_lnotab: bytes - co_freevars: tuple[str, ...] - co_cellvars: tuple[str, ...] + @property + def co_posonlyargcount(self) -> int: ... + + @property + def co_kwonlyargcount(self) -> int: ... + @property + def co_nlocals(self) -> int: ... + @property + def co_stacksize(self) -> int: ... + @property + def co_flags(self) -> int: ... + @property + def co_code(self) -> bytes: ... + @property + def co_consts(self) -> tuple[Any, ...]: ... + @property + def co_names(self) -> tuple[str, ...]: ... + @property + def co_varnames(self) -> tuple[str, ...]: ... + @property + def co_filename(self) -> str: ... + @property + def co_name(self) -> str: ... + @property + def co_firstlineno(self) -> int: ... + @property + def co_lnotab(self) -> bytes: ... + @property + def co_freevars(self) -> tuple[str, ...]: ... + @property + def co_cellvars(self) -> tuple[str, ...]: ... if sys.version_info >= (3, 8): def __init__( self, @@ -146,7 +314,8 @@ class CodeType: co_linetable: object = ..., ) -> CodeType: ... def co_lines(self) -> Iterator[tuple[int, int, int | None]]: ... - co_linetable: object + @property + def co_linetable(self) -> object: ... elif sys.version_info >= (3, 8): def replace( self, @@ -173,9 +342,9 @@ class CodeType: @final class MappingProxyType(Mapping[_KT, _VT_co], Generic[_KT, _VT_co]): - __hash__: None # type: ignore[assignment] + __hash__: ClassVar[None] # type: ignore[assignment] def __init__(self, mapping: SupportsKeysAndGetItem[_KT, _VT_co]) -> None: ... - def __getitem__(self, k: _KT) -> _VT_co: ... + def __getitem__(self, __k: _KT) -> _VT_co: ... def __iter__(self) -> Iterator[_KT]: ... def __len__(self) -> int: ... def copy(self) -> dict[_KT, _VT_co]: ... @@ -189,16 +358,17 @@ class MappingProxyType(Mapping[_KT, _VT_co], Generic[_KT, _VT_co]): def __ror__(self, __value: Mapping[_T1, _T2]) -> dict[_KT | _T1, _VT_co | _T2]: ... class SimpleNamespace: - __hash__: None # type: ignore[assignment] + __hash__: ClassVar[None] # type: ignore[assignment] def __init__(self, **kwargs: Any) -> None: ... - def __getattribute__(self, name: str) -> Any: ... - def __setattr__(self, name: str, value: Any) -> None: ... - def __delattr__(self, name: str) -> None: ... + def __getattribute__(self, __name: str) -> Any: ... + def __setattr__(self, __name: str, __value: Any) -> None: ... + def __delattr__(self, __name: str) -> None: ... class ModuleType: __name__: str __file__: str | None - __dict__: dict[str, Any] + @property + def __dict__(self) -> dict[str, Any]: ... # type: ignore[override] __loader__: _LoaderProtocol | None __package__: str | None __path__: MutableSequence[str] @@ -211,37 +381,49 @@ class ModuleType: @final class GeneratorType(Generator[_T_co, _T_contra, _V_co]): - gi_code: CodeType - gi_frame: FrameType - gi_running: bool - gi_yieldfrom: GeneratorType[_T_co, _T_contra, Any] | None + @property + def gi_code(self) -> CodeType: ... + @property + def gi_frame(self) -> FrameType: ... + @property + def gi_running(self) -> bool: ... + @property + def gi_yieldfrom(self) -> GeneratorType[_T_co, _T_contra, Any] | None: ... + __name__: str + __qualname__: str def __iter__(self) -> GeneratorType[_T_co, _T_contra, _V_co]: ... def __next__(self) -> _T_co: ... def close(self) -> None: ... def send(self, __arg: _T_contra) -> _T_co: ... @overload def throw( - self, __typ: Type[BaseException], __val: BaseException | object = ..., __tb: TracebackType | None = ... + self, __typ: type[BaseException], __val: BaseException | object = ..., __tb: TracebackType | None = ... ) -> _T_co: ... @overload def throw(self, __typ: BaseException, __val: None = ..., __tb: TracebackType | None = ...) -> _T_co: ... @final class AsyncGeneratorType(AsyncGenerator[_T_co, _T_contra]): - ag_await: Awaitable[Any] | None - ag_frame: FrameType - ag_running: bool - ag_code: CodeType + @property + def ag_await(self) -> Awaitable[Any] | None: ... + @property + def ag_frame(self) -> FrameType: ... + @property + def ag_running(self) -> bool: ... + @property + def ag_code(self) -> CodeType: ... + __name__: str + __qualname__: str def __aiter__(self) -> AsyncGeneratorType[_T_co, _T_contra]: ... - def __anext__(self) -> Awaitable[_T_co]: ... - def asend(self, __val: _T_contra) -> Awaitable[_T_co]: ... + def __anext__(self) -> Coroutine[Any, Any, _T_co]: ... + def asend(self, __val: _T_contra) -> Coroutine[Any, Any, _T_co]: ... @overload - def athrow( - self, __typ: Type[BaseException], __val: BaseException | object = ..., __tb: TracebackType | None = ... - ) -> Awaitable[_T_co]: ... + async def athrow( + self, __typ: type[BaseException], __val: BaseException | object = ..., __tb: TracebackType | None = ... + ) -> _T_co: ... @overload - def athrow(self, __typ: BaseException, __val: None = ..., __tb: TracebackType | None = ...) -> Awaitable[_T_co]: ... - def aclose(self) -> Awaitable[None]: ... + async def athrow(self, __typ: BaseException, __val: None = ..., __tb: TracebackType | None = ...) -> _T_co: ... + def aclose(self) -> Coroutine[Any, Any, None]: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, __item: Any) -> GenericAlias: ... @@ -249,52 +431,65 @@ class AsyncGeneratorType(AsyncGenerator[_T_co, _T_contra]): class CoroutineType(Coroutine[_T_co, _T_contra, _V_co]): __name__: str __qualname__: str - cr_await: Any | None - cr_code: CodeType - cr_frame: FrameType - cr_running: bool + @property + def cr_await(self) -> Any | None: ... + @property + def cr_code(self) -> CodeType: ... + @property + def cr_frame(self) -> FrameType: ... + @property + def cr_running(self) -> bool: ... + if sys.version_info >= (3, 7): + @property + def cr_origin(self) -> tuple[tuple[str, int, str], ...] | None: ... + def close(self) -> None: ... def __await__(self) -> Generator[Any, None, _V_co]: ... def send(self, __arg: _T_contra) -> _T_co: ... @overload def throw( - self, __typ: Type[BaseException], __val: BaseException | object = ..., __tb: TracebackType | None = ... + self, __typ: type[BaseException], __val: BaseException | object = ..., __tb: TracebackType | None = ... ) -> _T_co: ... @overload def throw(self, __typ: BaseException, __val: None = ..., __tb: TracebackType | None = ...) -> _T_co: ... class _StaticFunctionType: - """Fictional type to correct the type of MethodType.__func__. - - FunctionType is a descriptor, so mypy follows the descriptor protocol and - converts MethodType.__func__ back to MethodType (the return type of - FunctionType.__get__). But this is actually a special case; MethodType is - implemented in C and its attribute access doesn't go through - __getattribute__. - - By wrapping FunctionType in _StaticFunctionType, we get the right result; - similar to wrapping a function in staticmethod() at runtime to prevent it - being bound as a method. - """ - + # Fictional type to correct the type of MethodType.__func__. + # FunctionType is a descriptor, so mypy follows the descriptor protocol and + # converts MethodType.__func__ back to MethodType (the return type of + # FunctionType.__get__). But this is actually a special case; MethodType is + # implemented in C and its attribute access doesn't go through + # __getattribute__. + # By wrapping FunctionType in _StaticFunctionType, we get the right result; + # similar to wrapping a function in staticmethod() at runtime to prevent it + # being bound as a method. def __get__(self, obj: object | None, type: type | None) -> FunctionType: ... @final class MethodType: - __closure__: tuple[_Cell, ...] | None # inherited from the added function - __defaults__: tuple[Any, ...] | None # inherited from the added function - __func__: _StaticFunctionType - __self__: object - __name__: str # inherited from the added function - __qualname__: str # inherited from the added function - def __init__(self, func: Callable[..., Any], obj: object) -> None: ... + @property + def __closure__(self) -> tuple[_Cell, ...] | None: ... # inherited from the added function + @property + def __defaults__(self) -> tuple[Any, ...] | None: ... # inherited from the added function + @property + def __func__(self) -> _StaticFunctionType: ... + @property + def __self__(self) -> object: ... + @property + def __name__(self) -> str: ... # inherited from the added function + @property + def __qualname__(self) -> str: ... # inherited from the added function + def __init__(self, __func: Callable[..., Any], __obj: object) -> None: ... def __call__(self, *args: Any, **kwargs: Any) -> Any: ... @final class BuiltinFunctionType: - __self__: object | ModuleType - __name__: str - __qualname__: str + @property + def __self__(self) -> object | ModuleType: ... + @property + def __name__(self) -> str: ... + @property + def __qualname__(self) -> str: ... def __call__(self, *args: Any, **kwargs: Any) -> Any: ... BuiltinMethodType = BuiltinFunctionType @@ -302,32 +497,48 @@ BuiltinMethodType = BuiltinFunctionType if sys.version_info >= (3, 7): @final class WrapperDescriptorType: - __name__: str - __qualname__: str - __objclass__: type + @property + def __name__(self) -> str: ... + @property + def __qualname__(self) -> str: ... + @property + def __objclass__(self) -> type: ... def __call__(self, *args: Any, **kwargs: Any) -> Any: ... - def __get__(self, obj: Any, type: type = ...) -> Any: ... + def __get__(self, __obj: Any, __type: type = ...) -> Any: ... + @final class MethodWrapperType: - __self__: object - __name__: str - __qualname__: str - __objclass__: type + @property + def __self__(self) -> object: ... + @property + def __name__(self) -> str: ... + @property + def __qualname__(self) -> str: ... + @property + def __objclass__(self) -> type: ... def __call__(self, *args: Any, **kwargs: Any) -> Any: ... - def __eq__(self, other: Any) -> bool: ... - def __ne__(self, other: Any) -> bool: ... + def __eq__(self, __other: object) -> bool: ... + def __ne__(self, __other: object) -> bool: ... + @final class MethodDescriptorType: - __name__: str - __qualname__: str - __objclass__: type + @property + def __name__(self) -> str: ... + @property + def __qualname__(self) -> str: ... + @property + def __objclass__(self) -> type: ... def __call__(self, *args: Any, **kwargs: Any) -> Any: ... def __get__(self, obj: Any, type: type = ...) -> Any: ... + @final class ClassMethodDescriptorType: - __name__: str - __qualname__: str - __objclass__: type + @property + def __name__(self) -> str: ... + @property + def __qualname__(self) -> str: ... + @property + def __objclass__(self) -> type: ... def __call__(self, *args: Any, **kwargs: Any) -> Any: ... def __get__(self, obj: Any, type: type = ...) -> Any: ... @@ -349,16 +560,23 @@ class TracebackType: @final class FrameType: - f_back: FrameType | None - f_builtins: dict[str, Any] - f_code: CodeType - f_globals: dict[str, Any] - f_lasti: int + @property + def f_back(self) -> FrameType | None: ... + @property + def f_builtins(self) -> dict[str, Any]: ... + @property + def f_code(self) -> CodeType: ... + @property + def f_globals(self) -> dict[str, Any]: ... + @property + def f_lasti(self) -> int: ... # see discussion in #6769: f_lineno *can* sometimes be None, # but you should probably file a bug report with CPython if you encounter it being None in the wild. # An `int | None` annotation here causes too many false-positive errors. - f_lineno: int | Any - f_locals: dict[str, Any] + @property + def f_lineno(self) -> int | Any: ... + @property + def f_locals(self) -> dict[str, Any]: ... f_trace: Callable[[FrameType, str, Any], Any] | None if sys.version_info >= (3, 7): f_trace_lines: bool @@ -367,19 +585,27 @@ class FrameType: @final class GetSetDescriptorType: - __name__: str - __objclass__: type + @property + def __name__(self) -> str: ... + @property + def __qualname__(self) -> str: ... + @property + def __objclass__(self) -> type: ... def __get__(self, __obj: Any, __type: type = ...) -> Any: ... def __set__(self, __instance: Any, __value: Any) -> None: ... - def __delete__(self, obj: Any) -> None: ... + def __delete__(self, __obj: Any) -> None: ... @final class MemberDescriptorType: - __name__: str - __objclass__: type + @property + def __name__(self) -> str: ... + @property + def __qualname__(self) -> str: ... + @property + def __objclass__(self) -> type: ... def __get__(self, __obj: Any, __type: type = ...) -> Any: ... def __set__(self, __instance: Any, __value: Any) -> None: ... - def __delete__(self, obj: Any) -> None: ... + def __delete__(self, __obj: Any) -> None: ... if sys.version_info >= (3, 7): def new_class( @@ -421,9 +647,12 @@ if sys.version_info >= (3, 8): if sys.version_info >= (3, 9): class GenericAlias: - __origin__: type - __args__: tuple[Any, ...] - __parameters__: tuple[Any, ...] + @property + def __origin__(self) -> type: ... + @property + def __args__(self) -> tuple[Any, ...]: ... + @property + def __parameters__(self) -> tuple[Any, ...]: ... def __init__(self, origin: type, args: Any) -> None: ... def __getattr__(self, name: str) -> Any: ... # incomplete @@ -431,12 +660,13 @@ if sys.version_info >= (3, 10): @final class NoneType: def __bool__(self) -> Literal[False]: ... - EllipsisType = ellipsis # noqa F811 from builtins + EllipsisType = ellipsis # noqa: F821 from builtins from builtins import _NotImplementedType - NotImplementedType = _NotImplementedType # noqa F811 from builtins + NotImplementedType = _NotImplementedType @final class UnionType: - __args__: tuple[Any, ...] - def __or__(self, obj: Any) -> UnionType: ... - def __ror__(self, obj: Any) -> UnionType: ... + @property + def __args__(self) -> tuple[Any, ...]: ... + def __or__(self, __obj: Any) -> UnionType: ... + def __ror__(self, __obj: Any) -> UnionType: ... diff --git a/mypy/typeshed/stdlib/typing.pyi b/mypy/typeshed/stdlib/typing.pyi index 6e461b8aa260b..4ad3ab3da274e 100644 --- a/mypy/typeshed/stdlib/typing.pyi +++ b/mypy/typeshed/stdlib/typing.pyi @@ -1,6 +1,6 @@ import collections # Needed by aliases like DefaultDict, see mypy issue 2986 import sys -from _typeshed import SupportsKeysAndGetItem +from _typeshed import Self as TypeshedSelf, SupportsKeysAndGetItem from abc import ABCMeta, abstractmethod from types import BuiltinFunctionType, CodeType, FrameType, FunctionType, MethodType, ModuleType, TracebackType from typing_extensions import Literal as _Literal, ParamSpec as _ParamSpec, final as _final @@ -11,31 +11,485 @@ if sys.version_info >= (3, 7): if sys.version_info >= (3, 9): from types import GenericAlias +if sys.version_info >= (3, 11): + __all__ = [ + "Annotated", + "Any", + "Callable", + "ClassVar", + "Concatenate", + "Final", + "ForwardRef", + "Generic", + "Literal", + "Optional", + "ParamSpec", + "Protocol", + "Tuple", + "Type", + "TypeVar", + "TypeVarTuple", + "Union", + "Unpack", + "AbstractSet", + "ByteString", + "Container", + "ContextManager", + "Hashable", + "ItemsView", + "Iterable", + "Iterator", + "KeysView", + "Mapping", + "MappingView", + "MutableMapping", + "MutableSequence", + "MutableSet", + "Sequence", + "Sized", + "ValuesView", + "Awaitable", + "AsyncIterator", + "AsyncIterable", + "Coroutine", + "Collection", + "AsyncGenerator", + "AsyncContextManager", + "Reversible", + "SupportsAbs", + "SupportsBytes", + "SupportsComplex", + "SupportsFloat", + "SupportsIndex", + "SupportsInt", + "SupportsRound", + "ChainMap", + "Counter", + "Deque", + "Dict", + "DefaultDict", + "List", + "OrderedDict", + "Set", + "FrozenSet", + "NamedTuple", + "TypedDict", + "Generator", + "BinaryIO", + "IO", + "Match", + "Pattern", + "TextIO", + "AnyStr", + "assert_never", + "assert_type", + "cast", + "final", + "get_args", + "get_origin", + "get_type_hints", + "is_typeddict", + "Never", + "NewType", + "no_type_check", + "no_type_check_decorator", + "NoReturn", + "overload", + "ParamSpecArgs", + "ParamSpecKwargs", + "reveal_type", + "runtime_checkable", + "Self", + "Text", + "TYPE_CHECKING", + "TypeAlias", + "TypeGuard", + ] +elif sys.version_info >= (3, 10): + __all__ = [ + "Annotated", + "Any", + "Callable", + "ClassVar", + "Concatenate", + "Final", + "ForwardRef", + "Generic", + "Literal", + "Optional", + "ParamSpec", + "Protocol", + "Tuple", + "Type", + "TypeVar", + "Union", + "AbstractSet", + "ByteString", + "Container", + "ContextManager", + "Hashable", + "ItemsView", + "Iterable", + "Iterator", + "KeysView", + "Mapping", + "MappingView", + "MutableMapping", + "MutableSequence", + "MutableSet", + "Sequence", + "Sized", + "ValuesView", + "Awaitable", + "AsyncIterator", + "AsyncIterable", + "Coroutine", + "Collection", + "AsyncGenerator", + "AsyncContextManager", + "Reversible", + "SupportsAbs", + "SupportsBytes", + "SupportsComplex", + "SupportsFloat", + "SupportsIndex", + "SupportsInt", + "SupportsRound", + "ChainMap", + "Counter", + "Deque", + "Dict", + "DefaultDict", + "List", + "OrderedDict", + "Set", + "FrozenSet", + "NamedTuple", + "TypedDict", + "Generator", + "BinaryIO", + "IO", + "Match", + "Pattern", + "TextIO", + "AnyStr", + "cast", + "final", + "get_args", + "get_origin", + "get_type_hints", + "is_typeddict", + "NewType", + "no_type_check", + "no_type_check_decorator", + "NoReturn", + "overload", + "ParamSpecArgs", + "ParamSpecKwargs", + "runtime_checkable", + "Text", + "TYPE_CHECKING", + "TypeAlias", + "TypeGuard", + ] +elif sys.version_info >= (3, 9): + __all__ = [ + "Annotated", + "Any", + "Callable", + "ClassVar", + "Final", + "ForwardRef", + "Generic", + "Literal", + "Optional", + "Protocol", + "Tuple", + "Type", + "TypeVar", + "Union", + "AbstractSet", + "ByteString", + "Container", + "ContextManager", + "Hashable", + "ItemsView", + "Iterable", + "Iterator", + "KeysView", + "Mapping", + "MappingView", + "MutableMapping", + "MutableSequence", + "MutableSet", + "Sequence", + "Sized", + "ValuesView", + "Awaitable", + "AsyncIterator", + "AsyncIterable", + "Coroutine", + "Collection", + "AsyncGenerator", + "AsyncContextManager", + "Reversible", + "SupportsAbs", + "SupportsBytes", + "SupportsComplex", + "SupportsFloat", + "SupportsIndex", + "SupportsInt", + "SupportsRound", + "ChainMap", + "Counter", + "Deque", + "Dict", + "DefaultDict", + "List", + "OrderedDict", + "Set", + "FrozenSet", + "NamedTuple", + "TypedDict", + "Generator", + "BinaryIO", + "IO", + "Match", + "Pattern", + "TextIO", + "AnyStr", + "cast", + "final", + "get_args", + "get_origin", + "get_type_hints", + "NewType", + "no_type_check", + "no_type_check_decorator", + "NoReturn", + "overload", + "runtime_checkable", + "Text", + "TYPE_CHECKING", + ] +elif sys.version_info >= (3, 8): + __all__ = [ + "Any", + "Callable", + "ClassVar", + "Final", + "ForwardRef", + "Generic", + "Literal", + "Optional", + "Protocol", + "Tuple", + "Type", + "TypeVar", + "Union", + "AbstractSet", + "ByteString", + "Container", + "ContextManager", + "Hashable", + "ItemsView", + "Iterable", + "Iterator", + "KeysView", + "Mapping", + "MappingView", + "MutableMapping", + "MutableSequence", + "MutableSet", + "Sequence", + "Sized", + "ValuesView", + "Awaitable", + "AsyncIterator", + "AsyncIterable", + "Coroutine", + "Collection", + "AsyncGenerator", + "AsyncContextManager", + "Reversible", + "SupportsAbs", + "SupportsBytes", + "SupportsComplex", + "SupportsFloat", + "SupportsIndex", + "SupportsInt", + "SupportsRound", + "ChainMap", + "Counter", + "Deque", + "Dict", + "DefaultDict", + "List", + "OrderedDict", + "Set", + "FrozenSet", + "NamedTuple", + "TypedDict", + "Generator", + "AnyStr", + "cast", + "final", + "get_args", + "get_origin", + "get_type_hints", + "NewType", + "no_type_check", + "no_type_check_decorator", + "NoReturn", + "overload", + "runtime_checkable", + "Text", + "TYPE_CHECKING", + ] +elif sys.version_info >= (3, 7): + __all__ = [ + "Any", + "Callable", + "ClassVar", + "ForwardRef", + "Generic", + "Optional", + "Tuple", + "Type", + "TypeVar", + "Union", + "AbstractSet", + "ByteString", + "Container", + "ContextManager", + "Hashable", + "ItemsView", + "Iterable", + "Iterator", + "KeysView", + "Mapping", + "MappingView", + "MutableMapping", + "MutableSequence", + "MutableSet", + "Sequence", + "Sized", + "ValuesView", + "Awaitable", + "AsyncIterator", + "AsyncIterable", + "Coroutine", + "Collection", + "AsyncGenerator", + "AsyncContextManager", + "Reversible", + "SupportsAbs", + "SupportsBytes", + "SupportsComplex", + "SupportsFloat", + "SupportsInt", + "SupportsRound", + "ChainMap", + "Counter", + "Deque", + "Dict", + "DefaultDict", + "List", + "OrderedDict", + "Set", + "FrozenSet", + "NamedTuple", + "Generator", + "AnyStr", + "cast", + "get_type_hints", + "NewType", + "no_type_check", + "no_type_check_decorator", + "NoReturn", + "overload", + "Text", + "TYPE_CHECKING", + ] +else: + __all__ = [ + "Any", + "Callable", + "ClassVar", + "Generic", + "Optional", + "Tuple", + "Type", + "TypeVar", + "Union", + "AbstractSet", + "GenericMeta", + "ByteString", + "Container", + "ContextManager", + "Hashable", + "ItemsView", + "Iterable", + "Iterator", + "KeysView", + "Mapping", + "MappingView", + "MutableMapping", + "MutableSequence", + "MutableSet", + "Sequence", + "Sized", + "ValuesView", + "Reversible", + "SupportsAbs", + "SupportsBytes", + "SupportsComplex", + "SupportsFloat", + "SupportsInt", + "SupportsRound", + "Counter", + "Deque", + "Dict", + "DefaultDict", + "List", + "Set", + "FrozenSet", + "NamedTuple", + "Generator", + "AnyStr", + "cast", + "get_type_hints", + "NewType", + "no_type_check", + "no_type_check_decorator", + "overload", + "Text", + "TYPE_CHECKING", + ] + Any = object() +@_final class TypeVar: __name__: str - __bound__: Type[Any] | None - __constraints__: Tuple[Type[Any], ...] + __bound__: Any | None + __constraints__: tuple[Any, ...] __covariant__: bool __contravariant__: bool def __init__( - self, - name: str, - *constraints: Type[Any], - bound: None | Type[Any] | str = ..., - covariant: bool = ..., - contravariant: bool = ..., + self, name: str, *constraints: Any, bound: Any | None = ..., covariant: bool = ..., contravariant: bool = ... ) -> None: ... if sys.version_info >= (3, 10): - def __or__(self, other: Any) -> _SpecialForm: ... - def __ror__(self, other: Any) -> _SpecialForm: ... + def __or__(self, right: Any) -> _SpecialForm: ... + def __ror__(self, left: Any) -> _SpecialForm: ... # Used for an undocumented mypy feature. Does not exist at runtime. _promote = object() +# N.B. Keep this definition in sync with typing_extensions._SpecialForm +@_final class _SpecialForm: - def __getitem__(self, typeargs: Any) -> object: ... + def __getitem__(self, parameters: Any) -> object: ... if sys.version_info >= (3, 10): def __or__(self, other: Any) -> _SpecialForm: ... def __ror__(self, other: Any) -> _SpecialForm: ... @@ -46,23 +500,40 @@ _T = TypeVar("_T") def overload(func: _F) -> _F: ... +# Unlike the vast majority module-level objects in stub files, +# these `_SpecialForm` objects in typing need the default value `= ...`, +# due to the fact that they are used elswhere in the same file. +# Otherwise, flake8 erroneously flags them as undefined. +# `_SpecialForm` objects in typing.py that are not used elswhere in the same file +# do not need the default value assignment. Union: _SpecialForm = ... -Optional: _SpecialForm = ... -Tuple: _SpecialForm = ... Generic: _SpecialForm = ... # Protocol is only present in 3.8 and later, but mypy needs it unconditionally Protocol: _SpecialForm = ... Callable: _SpecialForm = ... Type: _SpecialForm = ... -ClassVar: _SpecialForm = ... NoReturn: _SpecialForm = ... + +Optional: _SpecialForm +Tuple: _SpecialForm +ClassVar: _SpecialForm if sys.version_info >= (3, 8): - Final: _SpecialForm = ... + Final: _SpecialForm def final(f: _T) -> _T: ... - Literal: _SpecialForm = ... + Literal: _SpecialForm # TypedDict is a (non-subscriptable) special form. TypedDict: object +if sys.version_info >= (3, 11): + Self: _SpecialForm + Never: _SpecialForm = ... + Unpack: _SpecialForm + + class TypeVarTuple: + __name__: str + def __init__(self, name: str) -> None: ... + def __iter__(self) -> Any: ... + if sys.version_info < (3, 7): class GenericMeta(type): ... @@ -70,35 +541,36 @@ if sys.version_info >= (3, 10): class ParamSpecArgs: __origin__: ParamSpec def __init__(self, origin: ParamSpec) -> None: ... + class ParamSpecKwargs: __origin__: ParamSpec def __init__(self, origin: ParamSpec) -> None: ... + class ParamSpec: __name__: str - __bound__: Type[Any] | None + __bound__: Any | None __covariant__: bool __contravariant__: bool - def __init__( - self, name: str, *, bound: None | Type[Any] | str = ..., contravariant: bool = ..., covariant: bool = ... - ) -> None: ... + def __init__(self, name: str, *, bound: Any | None = ..., contravariant: bool = ..., covariant: bool = ...) -> None: ... @property def args(self) -> ParamSpecArgs: ... @property def kwargs(self) -> ParamSpecKwargs: ... - def __or__(self, other: Any) -> _SpecialForm: ... - def __ror__(self, other: Any) -> _SpecialForm: ... - Concatenate: _SpecialForm = ... - TypeAlias: _SpecialForm = ... - TypeGuard: _SpecialForm = ... + def __or__(self, right: Any) -> _SpecialForm: ... + def __ror__(self, left: Any) -> _SpecialForm: ... + Concatenate: _SpecialForm + TypeAlias: _SpecialForm + TypeGuard: _SpecialForm + class NewType: - def __init__(self, name: str, tp: type) -> None: ... + def __init__(self, name: str, tp: Any) -> None: ... def __call__(self, x: _T) -> _T: ... def __or__(self, other: Any) -> _SpecialForm: ... def __ror__(self, other: Any) -> _SpecialForm: ... __supertype__: type else: - def NewType(name: str, tp: Type[_T]) -> Type[_T]: ... + def NewType(name: str, tp: Any) -> Any: ... # These type variables are used by the container types. _S = TypeVar("_S") @@ -133,18 +605,14 @@ if sys.version_info >= (3, 7): OrderedDict = _Alias() if sys.version_info >= (3, 9): - Annotated: _SpecialForm = ... + Annotated: _SpecialForm # Predefined type variables. -AnyStr = TypeVar("AnyStr", str, bytes) +AnyStr = TypeVar("AnyStr", str, bytes) # noqa: Y001 -if sys.version_info >= (3, 8): - # This class did actually exist in 3.7, but had a different base. - # We'll just pretend it didn't exist though: the main external use case for _ProtocolMeta is - # to inherit from for your own custom protocol metaclasses. If you're using 3.7, at runtime - # you'd use typing_extensions.Protocol, which would be unrelated to typing._ProtocolMeta and - # so you'd run into metaclass conflicts at runtime if you used typing._ProtocolMeta. - class _ProtocolMeta(ABCMeta): ... +# Technically in 3.7 this inherited from GenericMeta. But let's not reflect that, since +# type checkers tend to assume that Protocols all have the ABCMeta metaclass. +class _ProtocolMeta(ABCMeta): ... # Abstract base classes. @@ -288,7 +756,6 @@ class AsyncIterator(AsyncIterable[_T_co], Protocol[_T_co]): def __aiter__(self) -> AsyncIterator[_T_co]: ... class AsyncGenerator(AsyncIterator[_T_co], Generic[_T_co, _T_contra]): - @abstractmethod def __anext__(self) -> Awaitable[_T_co]: ... @abstractmethod def asend(self, __value: _T_contra) -> Awaitable[_T_co]: ... @@ -300,10 +767,7 @@ class AsyncGenerator(AsyncIterator[_T_co], Generic[_T_co, _T_contra]): @overload @abstractmethod def athrow(self, __typ: BaseException, __val: None = ..., __tb: TracebackType | None = ...) -> Awaitable[_T_co]: ... - @abstractmethod def aclose(self) -> Awaitable[None]: ... - @abstractmethod - def __aiter__(self) -> AsyncGenerator[_T_co, _T_contra]: ... @property def ag_await(self) -> Any: ... @property @@ -327,14 +791,14 @@ class Collection(Iterable[_T_co], Container[_T_co], Protocol[_T_co]): class Sequence(Collection[_T_co], Reversible[_T_co], Generic[_T_co]): @overload @abstractmethod - def __getitem__(self, i: int) -> _T_co: ... + def __getitem__(self, index: int) -> _T_co: ... @overload @abstractmethod - def __getitem__(self, s: slice) -> Sequence[_T_co]: ... + def __getitem__(self, index: slice) -> Sequence[_T_co]: ... # Mixin methods def index(self, value: Any, start: int = ..., stop: int = ...) -> int: ... def count(self, value: Any) -> int: ... - def __contains__(self, x: object) -> bool: ... + def __contains__(self, value: object) -> bool: ... def __iter__(self) -> Iterator[_T_co]: ... def __reversed__(self) -> Iterator[_T_co]: ... @@ -343,22 +807,22 @@ class MutableSequence(Sequence[_T], Generic[_T]): def insert(self, index: int, value: _T) -> None: ... @overload @abstractmethod - def __getitem__(self, i: int) -> _T: ... + def __getitem__(self, index: int) -> _T: ... @overload @abstractmethod - def __getitem__(self, s: slice) -> MutableSequence[_T]: ... + def __getitem__(self, index: slice) -> MutableSequence[_T]: ... @overload @abstractmethod - def __setitem__(self, i: int, o: _T) -> None: ... + def __setitem__(self, index: int, value: _T) -> None: ... @overload @abstractmethod - def __setitem__(self, s: slice, o: Iterable[_T]) -> None: ... + def __setitem__(self, index: slice, value: Iterable[_T]) -> None: ... @overload @abstractmethod - def __delitem__(self, i: int) -> None: ... + def __delitem__(self, index: int) -> None: ... @overload @abstractmethod - def __delitem__(self, i: slice) -> None: ... + def __delitem__(self, index: slice) -> None: ... # Mixin methods def append(self, value: _T) -> None: ... def clear(self) -> None: ... @@ -366,20 +830,21 @@ class MutableSequence(Sequence[_T], Generic[_T]): def reverse(self) -> None: ... def pop(self, index: int = ...) -> _T: ... def remove(self, value: _T) -> None: ... - def __iadd__(self, x: Iterable[_T]) -> MutableSequence[_T]: ... + def __iadd__(self: TypeshedSelf, values: Iterable[_T]) -> TypeshedSelf: ... class AbstractSet(Collection[_T_co], Generic[_T_co]): @abstractmethod def __contains__(self, x: object) -> bool: ... + def _hash(self) -> int: ... # Mixin methods - def __le__(self, s: AbstractSet[Any]) -> bool: ... - def __lt__(self, s: AbstractSet[Any]) -> bool: ... - def __gt__(self, s: AbstractSet[Any]) -> bool: ... - def __ge__(self, s: AbstractSet[Any]) -> bool: ... - def __and__(self, s: AbstractSet[Any]) -> AbstractSet[_T_co]: ... - def __or__(self, s: AbstractSet[_T]) -> AbstractSet[_T_co | _T]: ... - def __sub__(self, s: AbstractSet[Any]) -> AbstractSet[_T_co]: ... - def __xor__(self, s: AbstractSet[_T]) -> AbstractSet[_T_co | _T]: ... + def __le__(self, other: AbstractSet[Any]) -> bool: ... + def __lt__(self, other: AbstractSet[Any]) -> bool: ... + def __gt__(self, other: AbstractSet[Any]) -> bool: ... + def __ge__(self, other: AbstractSet[Any]) -> bool: ... + def __and__(self, other: AbstractSet[Any]) -> AbstractSet[_T_co]: ... + def __or__(self, other: AbstractSet[_T]) -> AbstractSet[_T_co | _T]: ... + def __sub__(self, other: AbstractSet[Any]) -> AbstractSet[_T_co]: ... + def __xor__(self, other: AbstractSet[_T]) -> AbstractSet[_T_co | _T]: ... def isdisjoint(self, other: Iterable[Any]) -> bool: ... class MutableSet(AbstractSet[_T], Generic[_T]): @@ -391,48 +856,50 @@ class MutableSet(AbstractSet[_T], Generic[_T]): def clear(self) -> None: ... def pop(self) -> _T: ... def remove(self, value: _T) -> None: ... - def __ior__(self, s: AbstractSet[_S]) -> MutableSet[_T | _S]: ... - def __iand__(self, s: AbstractSet[Any]) -> MutableSet[_T]: ... - def __ixor__(self, s: AbstractSet[_S]) -> MutableSet[_T | _S]: ... - def __isub__(self, s: AbstractSet[Any]) -> MutableSet[_T]: ... + def __ior__(self: TypeshedSelf, it: AbstractSet[_T]) -> TypeshedSelf: ... # type: ignore[override,misc] + def __iand__(self: TypeshedSelf, it: AbstractSet[Any]) -> TypeshedSelf: ... + def __ixor__(self: TypeshedSelf, it: AbstractSet[_T]) -> TypeshedSelf: ... # type: ignore[override,misc] + def __isub__(self: TypeshedSelf, it: AbstractSet[Any]) -> TypeshedSelf: ... class MappingView(Sized): def __init__(self, mapping: Mapping[Any, Any]) -> None: ... # undocumented def __len__(self) -> int: ... -class ItemsView(MappingView, AbstractSet[Tuple[_KT_co, _VT_co]], Generic[_KT_co, _VT_co]): +class ItemsView(MappingView, AbstractSet[tuple[_KT_co, _VT_co]], Generic[_KT_co, _VT_co]): def __init__(self, mapping: Mapping[_KT_co, _VT_co]) -> None: ... # undocumented - def __and__(self, o: Iterable[Any]) -> set[tuple[_KT_co, _VT_co]]: ... - def __rand__(self, o: Iterable[_T]) -> set[_T]: ... - def __contains__(self, o: object) -> bool: ... + def __and__(self, other: Iterable[Any]) -> set[tuple[_KT_co, _VT_co]]: ... + def __rand__(self, other: Iterable[_T]) -> set[_T]: ... + def __contains__(self, item: object) -> bool: ... def __iter__(self) -> Iterator[tuple[_KT_co, _VT_co]]: ... if sys.version_info >= (3, 8): def __reversed__(self) -> Iterator[tuple[_KT_co, _VT_co]]: ... - def __or__(self, o: Iterable[_T]) -> set[tuple[_KT_co, _VT_co] | _T]: ... - def __ror__(self, o: Iterable[_T]) -> set[tuple[_KT_co, _VT_co] | _T]: ... - def __sub__(self, o: Iterable[Any]) -> set[tuple[_KT_co, _VT_co]]: ... - def __rsub__(self, o: Iterable[_T]) -> set[_T]: ... - def __xor__(self, o: Iterable[_T]) -> set[tuple[_KT_co, _VT_co] | _T]: ... - def __rxor__(self, o: Iterable[_T]) -> set[tuple[_KT_co, _VT_co] | _T]: ... + + def __or__(self, other: Iterable[_T]) -> set[tuple[_KT_co, _VT_co] | _T]: ... + def __ror__(self, other: Iterable[_T]) -> set[tuple[_KT_co, _VT_co] | _T]: ... + def __sub__(self, other: Iterable[Any]) -> set[tuple[_KT_co, _VT_co]]: ... + def __rsub__(self, other: Iterable[_T]) -> set[_T]: ... + def __xor__(self, other: Iterable[_T]) -> set[tuple[_KT_co, _VT_co] | _T]: ... + def __rxor__(self, other: Iterable[_T]) -> set[tuple[_KT_co, _VT_co] | _T]: ... class KeysView(MappingView, AbstractSet[_KT_co], Generic[_KT_co]): def __init__(self, mapping: Mapping[_KT_co, Any]) -> None: ... # undocumented - def __and__(self, o: Iterable[Any]) -> set[_KT_co]: ... - def __rand__(self, o: Iterable[_T]) -> set[_T]: ... - def __contains__(self, o: object) -> bool: ... + def __and__(self, other: Iterable[Any]) -> set[_KT_co]: ... + def __rand__(self, other: Iterable[_T]) -> set[_T]: ... + def __contains__(self, key: object) -> bool: ... def __iter__(self) -> Iterator[_KT_co]: ... if sys.version_info >= (3, 8): def __reversed__(self) -> Iterator[_KT_co]: ... - def __or__(self, o: Iterable[_T]) -> set[_KT_co | _T]: ... - def __ror__(self, o: Iterable[_T]) -> set[_KT_co | _T]: ... - def __sub__(self, o: Iterable[Any]) -> set[_KT_co]: ... - def __rsub__(self, o: Iterable[_T]) -> set[_T]: ... - def __xor__(self, o: Iterable[_T]) -> set[_KT_co | _T]: ... - def __rxor__(self, o: Iterable[_T]) -> set[_KT_co | _T]: ... + + def __or__(self, other: Iterable[_T]) -> set[_KT_co | _T]: ... + def __ror__(self, other: Iterable[_T]) -> set[_KT_co | _T]: ... + def __sub__(self, other: Iterable[Any]) -> set[_KT_co]: ... + def __rsub__(self, other: Iterable[_T]) -> set[_T]: ... + def __xor__(self, other: Iterable[_T]) -> set[_KT_co | _T]: ... + def __rxor__(self, other: Iterable[_T]) -> set[_KT_co | _T]: ... class ValuesView(MappingView, Iterable[_VT_co], Generic[_VT_co]): def __init__(self, mapping: Mapping[Any, _VT_co]) -> None: ... # undocumented - def __contains__(self, o: object) -> bool: ... + def __contains__(self, value: object) -> bool: ... def __iter__(self) -> Iterator[_VT_co]: ... if sys.version_info >= (3, 8): def __reversed__(self) -> Iterator[_VT_co]: ... @@ -440,16 +907,18 @@ class ValuesView(MappingView, Iterable[_VT_co], Generic[_VT_co]): @runtime_checkable class ContextManager(Protocol[_T_co]): def __enter__(self) -> _T_co: ... + @abstractmethod def __exit__( self, __exc_type: Type[BaseException] | None, __exc_value: BaseException | None, __traceback: TracebackType | None ) -> bool | None: ... @runtime_checkable class AsyncContextManager(Protocol[_T_co]): - def __aenter__(self) -> Awaitable[_T_co]: ... - def __aexit__( + async def __aenter__(self) -> _T_co: ... + @abstractmethod + async def __aexit__( self, __exc_type: Type[BaseException] | None, __exc_value: BaseException | None, __traceback: TracebackType | None - ) -> Awaitable[bool | None]: ... + ) -> bool | None: ... class Mapping(Collection[_KT], Generic[_KT, _VT_co]): # TODO: We wish the key type could also be covariant, but that doesn't work, @@ -458,9 +927,9 @@ class Mapping(Collection[_KT], Generic[_KT, _VT_co]): def __getitem__(self, __k: _KT) -> _VT_co: ... # Mixin methods @overload - def get(self, key: _KT) -> _VT_co | None: ... + def get(self, __key: _KT) -> _VT_co | None: ... @overload - def get(self, __key: _KT, __default: _VT_co | _T) -> _VT_co | _T: ... + def get(self, __key: _KT, default: _VT_co | _T) -> _VT_co | _T: ... def items(self) -> ItemsView[_KT, _VT_co]: ... def keys(self) -> KeysView[_KT]: ... def values(self) -> ValuesView[_VT_co]: ... @@ -475,19 +944,32 @@ class MutableMapping(Mapping[_KT, _VT], Generic[_KT, _VT]): @overload def pop(self, __key: _KT) -> _VT: ... @overload - def pop(self, __key: _KT, __default: _VT | _T = ...) -> _VT | _T: ... + def pop(self, __key: _KT, default: _VT | _T) -> _VT | _T: ... def popitem(self) -> tuple[_KT, _VT]: ... - def setdefault(self, __key: _KT, __default: _VT = ...) -> _VT: ... + # This overload should be allowed only if the value type is compatible with None. + # Keep OrderedDict.setdefault in line with MutableMapping.setdefault, modulo positional-only differences. + @overload + def setdefault(self: MutableMapping[_KT, _T | None], __key: _KT) -> _T | None: ... + @overload + def setdefault(self, __key: _KT, __default: _VT) -> _VT: ... # 'update' used to take a Union, but using overloading is better. # The second overloaded type here is a bit too general, because - # Mapping[Tuple[_KT, _VT], W] is a subclass of Iterable[Tuple[_KT, _VT]], + # Mapping[tuple[_KT, _VT], W] is a subclass of Iterable[tuple[_KT, _VT]], # but will always have the behavior of the first overloaded type - # at runtime, leading to keys of a mix of types _KT and Tuple[_KT, _VT]. + # at runtime, leading to keys of a mix of types _KT and tuple[_KT, _VT]. # We don't currently have any way of forcing all Mappings to use # the first overload, but by using overloading rather than a Union, # mypy will commit to using the first overload when the argument is # known to be a Mapping with unknown type parameters, which is closer # to the behavior we want. See mypy issue #1430. + # + # Various mapping classes have __ior__ methods that should be kept roughly in line with .update(): + # -- dict.__ior__ + # -- os._Environ.__ior__ + # -- collections.UserDict.__ior__ + # -- collections.ChainMap.__ior__ + # -- weakref.WeakValueDictionary.__ior__ + # -- weakref.WeakKeyDictionary.__ior__ @overload def update(self, __m: SupportsKeysAndGetItem[_KT, _VT], **kwargs: _VT) -> None: ... @overload @@ -497,8 +979,11 @@ class MutableMapping(Mapping[_KT, _VT], Generic[_KT, _VT]): Text = str -TYPE_CHECKING = True +TYPE_CHECKING: bool +# In stubs, the arguments of the IO class are marked as positional-only. +# This differs from runtime, but better reflects the fact that in reality +# classes deriving from IO use different names for the arguments. class IO(Iterator[AnyStr], Generic[AnyStr]): # TODO use abstract properties @property @@ -516,27 +1001,27 @@ class IO(Iterator[AnyStr], Generic[AnyStr]): @abstractmethod def isatty(self) -> bool: ... @abstractmethod - def read(self, n: int = ...) -> AnyStr: ... + def read(self, __n: int = ...) -> AnyStr: ... @abstractmethod def readable(self) -> bool: ... @abstractmethod - def readline(self, limit: int = ...) -> AnyStr: ... + def readline(self, __limit: int = ...) -> AnyStr: ... @abstractmethod - def readlines(self, hint: int = ...) -> list[AnyStr]: ... + def readlines(self, __hint: int = ...) -> list[AnyStr]: ... @abstractmethod - def seek(self, offset: int, whence: int = ...) -> int: ... + def seek(self, __offset: int, __whence: int = ...) -> int: ... @abstractmethod def seekable(self) -> bool: ... @abstractmethod def tell(self) -> int: ... @abstractmethod - def truncate(self, size: int | None = ...) -> int: ... + def truncate(self, __size: int | None = ...) -> int: ... @abstractmethod def writable(self) -> bool: ... @abstractmethod - def write(self, s: AnyStr) -> int: ... + def write(self, __s: AnyStr) -> int: ... @abstractmethod - def writelines(self, lines: Iterable[AnyStr]) -> None: ... + def writelines(self, __lines: Iterable[AnyStr]) -> None: ... @abstractmethod def __next__(self) -> AnyStr: ... @abstractmethod @@ -545,8 +1030,8 @@ class IO(Iterator[AnyStr], Generic[AnyStr]): def __enter__(self) -> IO[AnyStr]: ... @abstractmethod def __exit__( - self, t: Type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None - ) -> bool | None: ... + self, __t: Type[BaseException] | None, __value: BaseException | None, __traceback: TracebackType | None + ) -> None: ... class BinaryIO(IO[bytes]): @abstractmethod @@ -571,15 +1056,21 @@ class ByteString(Sequence[int], metaclass=ABCMeta): ... @_final class Match(Generic[AnyStr]): - pos: int - endpos: int - lastindex: int | None - lastgroup: str | None - string: AnyStr + @property + def pos(self) -> int: ... + @property + def endpos(self) -> int: ... + @property + def lastindex(self) -> int | None: ... + @property + def lastgroup(self) -> str | None: ... + @property + def string(self) -> AnyStr: ... # The regular expression object whose match() or search() method produced # this match instance. - re: Pattern[AnyStr] + @property + def re(self) -> Pattern[AnyStr]: ... def expand(self, template: AnyStr) -> AnyStr: ... # group() returns "AnyStr" or "AnyStr | None", depending on the pattern. @overload @@ -587,13 +1078,13 @@ class Match(Generic[AnyStr]): @overload def group(self, __group: str | int) -> AnyStr | Any: ... @overload - def group(self, __group1: str | int, __group2: str | int, *groups: str | int) -> Tuple[AnyStr | Any, ...]: ... + def group(self, __group1: str | int, __group2: str | int, *groups: str | int) -> tuple[AnyStr | Any, ...]: ... # Each item of groups()'s return tuple is either "AnyStr" or # "AnyStr | None", depending on the pattern. @overload - def groups(self) -> Tuple[AnyStr | Any, ...]: ... + def groups(self) -> tuple[AnyStr | Any, ...]: ... @overload - def groups(self, default: _T) -> Tuple[AnyStr | _T, ...]: ... + def groups(self, default: _T) -> tuple[AnyStr | _T, ...]: ... # Each value in groupdict()'s return dict is either "AnyStr" or # "AnyStr | None", depending on the pattern. @overload @@ -604,21 +1095,27 @@ class Match(Generic[AnyStr]): def end(self, __group: int | str = ...) -> int: ... def span(self, __group: int | str = ...) -> tuple[int, int]: ... @property - def regs(self) -> Tuple[tuple[int, int], ...]: ... # undocumented + def regs(self) -> tuple[tuple[int, int], ...]: ... # undocumented # __getitem__() returns "AnyStr" or "AnyStr | None", depending on the pattern. @overload def __getitem__(self, __key: _Literal[0]) -> AnyStr: ... @overload def __getitem__(self, __key: int | str) -> AnyStr | Any: ... + def __copy__(self) -> Match[AnyStr]: ... + def __deepcopy__(self, __memo: Any) -> Match[AnyStr]: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... @_final class Pattern(Generic[AnyStr]): - flags: int - groupindex: Mapping[str, int] - groups: int - pattern: AnyStr + @property + def flags(self) -> int: ... + @property + def groupindex(self) -> Mapping[str, int]: ... + @property + def groups(self) -> int: ... + @property + def pattern(self) -> AnyStr: ... def search(self, string: AnyStr, pos: int = ..., endpos: int = ...) -> Match[AnyStr] | None: ... def match(self, string: AnyStr, pos: int = ..., endpos: int = ...) -> Match[AnyStr] | None: ... def fullmatch(self, string: AnyStr, pos: int = ..., endpos: int = ...) -> Match[AnyStr] | None: ... @@ -633,27 +1130,27 @@ class Pattern(Generic[AnyStr]): def subn(self, repl: AnyStr, string: AnyStr, count: int = ...) -> tuple[AnyStr, int]: ... @overload def subn(self, repl: Callable[[Match[AnyStr]], AnyStr], string: AnyStr, count: int = ...) -> tuple[AnyStr, int]: ... + def __copy__(self) -> Pattern[AnyStr]: ... + def __deepcopy__(self, __memo: Any) -> Pattern[AnyStr]: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... # Functions if sys.version_info >= (3, 7): - _get_type_hints_obj_allowed_types = Union[ - object, - Callable[..., Any], - FunctionType, - BuiltinFunctionType, - MethodType, - ModuleType, - WrapperDescriptorType, - MethodWrapperType, - MethodDescriptorType, - ] + _get_type_hints_obj_allowed_types = ( + object + | Callable[..., Any] + | FunctionType + | BuiltinFunctionType + | MethodType + | ModuleType + | WrapperDescriptorType + | MethodWrapperType + | MethodDescriptorType + ) else: - _get_type_hints_obj_allowed_types = Union[ - object, Callable[..., Any], FunctionType, BuiltinFunctionType, MethodType, ModuleType, - ] + _get_type_hints_obj_allowed_types = object | Callable[..., Any] | FunctionType | BuiltinFunctionType | MethodType | ModuleType if sys.version_info >= (3, 9): def get_type_hints( @@ -670,7 +1167,7 @@ else: if sys.version_info >= (3, 8): def get_origin(tp: Any) -> Any | None: ... - def get_args(tp: Any) -> Tuple[Any, ...]: ... + def get_args(tp: Any) -> tuple[Any, ...]: ... @overload def cast(typ: Type[_T], val: Any) -> _T: ... @@ -679,15 +1176,20 @@ def cast(typ: str, val: Any) -> Any: ... @overload def cast(typ: object, val: Any) -> Any: ... +if sys.version_info >= (3, 11): + def reveal_type(__obj: _T) -> _T: ... + def assert_never(__arg: Never) -> Never: ... + def assert_type(__val: _T, __typ: Any) -> _T: ... + # Type constructors -class NamedTuple(Tuple[Any, ...]): +class NamedTuple(tuple[Any, ...]): if sys.version_info < (3, 8): _field_types: collections.OrderedDict[str, type] elif sys.version_info < (3, 9): _field_types: dict[str, type] _field_defaults: dict[str, Any] - _fields: Tuple[str, ...] + _fields: tuple[str, ...] _source: str @overload def __init__(self, typename: str, fields: Iterable[tuple[str, Any]] = ...) -> None: ... @@ -699,11 +1201,12 @@ class NamedTuple(Tuple[Any, ...]): def _asdict(self) -> dict[str, Any]: ... else: def _asdict(self) -> collections.OrderedDict[str, Any]: ... - def _replace(self: _T, **kwargs: Any) -> _T: ... + + def _replace(self: TypeshedSelf, **kwargs: Any) -> TypeshedSelf: ... # Internal mypy fallback type for all typed dicts (does not exist at runtime) class _TypedDict(Mapping[str, object], metaclass=ABCMeta): - def copy(self: _T) -> _T: ... + def copy(self: TypeshedSelf) -> TypeshedSelf: ... # Using NoReturn so that only calls using mypy plugin hook that specialize the signature # can go through. def setdefault(self, k: NoReturn, default: object) -> object: ... @@ -714,28 +1217,31 @@ class _TypedDict(Mapping[str, object], metaclass=ABCMeta): def items(self) -> ItemsView[str, object]: ... def keys(self) -> KeysView[str]: ... def values(self) -> ValuesView[object]: ... - def __or__(self: _T, __value: _T) -> _T: ... - def __ior__(self: _T, __value: _T) -> _T: ... + def __or__(self: TypeshedSelf, __value: TypeshedSelf) -> TypeshedSelf: ... + def __ior__(self: TypeshedSelf, __value: TypeshedSelf) -> TypeshedSelf: ... # This itself is only available during type checking def type_check_only(func_or_cls: _F) -> _F: ... if sys.version_info >= (3, 7): + @_final class ForwardRef: __forward_arg__: str __forward_code__: CodeType __forward_evaluated__: bool __forward_value__: Any | None __forward_is_argument__: bool + __forward_is_class__: bool + __forward_module__: Any | None if sys.version_info >= (3, 9): # The module and is_class arguments were added in later Python 3.9 versions. def __init__(self, arg: str, is_argument: bool = ..., module: Any | None = ..., *, is_class: bool = ...) -> None: ... else: def __init__(self, arg: str, is_argument: bool = ...) -> None: ... + def _evaluate(self, globalns: dict[str, Any] | None, localns: dict[str, Any] | None) -> Any | None: ... - def __eq__(self, other: Any) -> bool: ... + def __eq__(self, other: object) -> bool: ... def __hash__(self) -> int: ... - def __repr__(self) -> str: ... if sys.version_info >= (3, 11): def __or__(self, other: Any) -> _SpecialForm: ... def __ror__(self, other: Any) -> _SpecialForm: ... diff --git a/mypy/typeshed/stdlib/typing_extensions.pyi b/mypy/typeshed/stdlib/typing_extensions.pyi index e7f288377b83c..892218f682837 100644 --- a/mypy/typeshed/stdlib/typing_extensions.pyi +++ b/mypy/typeshed/stdlib/typing_extensions.pyi @@ -1,6 +1,7 @@ import abc import sys -from typing import ( +from _typeshed import Self as TypeshedSelf # see #6932 for why the alias cannot have a leading underscore +from typing import ( # noqa: Y022,Y027 TYPE_CHECKING as TYPE_CHECKING, Any, AsyncContextManager as AsyncContextManager, @@ -33,36 +34,38 @@ _T = TypeVar("_T") _F = TypeVar("_F", bound=Callable[..., Any]) _TC = TypeVar("_TC", bound=Type[object]) +# unfortunately we have to duplicate this class definition from typing.pyi or we break pytype class _SpecialForm: - def __getitem__(self, typeargs: Any) -> Any: ... + def __getitem__(self, parameters: Any) -> object: ... + if sys.version_info >= (3, 10): + def __or__(self, other: Any) -> _SpecialForm: ... + def __ror__(self, other: Any) -> _SpecialForm: ... + +# Do not import (and re-export) Protocol or runtime_checkable from +# typing module because type checkers need to be able to distinguish +# typing.Protocol and typing_extensions.Protocol so they can properly +# warn users about potential runtime exceptions when using typing.Protocol +# on older versions of Python. +Protocol: _SpecialForm = ... def runtime_checkable(cls: _TC) -> _TC: ... # This alias for above is kept here for backwards compatibility. runtime = runtime_checkable -Protocol: _SpecialForm = ... -Final: _SpecialForm = ... -Self: _SpecialForm = ... -Required: _SpecialForm = ... -NotRequired: _SpecialForm = ... +Final: _SpecialForm def final(f: _F) -> _F: ... -Literal: _SpecialForm = ... +Literal: _SpecialForm def IntVar(name: str) -> Any: ... # returns a new TypeVar -if sys.version_info < (3, 8): - # Technically in 3.6 this inherited from GenericMeta. But let's not reflect that, since - # type checkers tend to assume that Protocols all have the ABCMeta metaclass. - class _ProtocolMeta(abc.ABCMeta): ... - # Internal mypy fallback type for all typed dicts (does not exist at runtime) class _TypedDict(Mapping[str, object], metaclass=abc.ABCMeta): __required_keys__: frozenset[str] __optional_keys__: frozenset[str] __total__: bool - def copy(self: _T) -> _T: ... + def copy(self: TypeshedSelf) -> TypeshedSelf: ... # Using NoReturn so that only calls using mypy plugin hook that specialize the signature # can go through. def setdefault(self, k: NoReturn, default: object) -> object: ... @@ -75,7 +78,7 @@ class _TypedDict(Mapping[str, object], metaclass=abc.ABCMeta): def __delitem__(self, k: NoReturn) -> None: ... # TypedDict is a (non-subscriptable) special form. -TypedDict: object = ... +TypedDict: object OrderedDict = _Alias() @@ -89,36 +92,74 @@ if sys.version_info >= (3, 7): def get_args(tp: Any) -> tuple[Any, ...]: ... def get_origin(tp: Any) -> Any | None: ... -Annotated: _SpecialForm = ... -_AnnotatedAlias: Any = ... # undocumented +Annotated: _SpecialForm +_AnnotatedAlias: Any # undocumented @runtime_checkable class SupportsIndex(Protocol, metaclass=abc.ABCMeta): @abc.abstractmethod def __index__(self) -> int: ... -# PEP 612 support for Python < 3.9 +# New things in 3.10 if sys.version_info >= (3, 10): - from typing import Concatenate as Concatenate, ParamSpec as ParamSpec, TypeAlias as TypeAlias, TypeGuard as TypeGuard + from typing import ( + Concatenate as Concatenate, + ParamSpec as ParamSpec, + TypeAlias as TypeAlias, + TypeGuard as TypeGuard, + is_typeddict as is_typeddict, + ) else: class ParamSpecArgs: __origin__: ParamSpec def __init__(self, origin: ParamSpec) -> None: ... + class ParamSpecKwargs: __origin__: ParamSpec def __init__(self, origin: ParamSpec) -> None: ... + class ParamSpec: __name__: str - __bound__: Type[Any] | None + __bound__: type[Any] | None __covariant__: bool __contravariant__: bool def __init__( - self, name: str, *, bound: None | Type[Any] | str = ..., contravariant: bool = ..., covariant: bool = ... + self, name: str, *, bound: None | type[Any] | str = ..., contravariant: bool = ..., covariant: bool = ... ) -> None: ... @property def args(self) -> ParamSpecArgs: ... @property def kwargs(self) -> ParamSpecKwargs: ... - Concatenate: _SpecialForm = ... - TypeAlias: _SpecialForm = ... - TypeGuard: _SpecialForm = ... + Concatenate: _SpecialForm + TypeAlias: _SpecialForm + TypeGuard: _SpecialForm + def is_typeddict(tp: object) -> bool: ... + +# New things in 3.11 +if sys.version_info >= (3, 11): + from typing import Never as Never, Self as Self, assert_never as assert_never, reveal_type as reveal_type +else: + Self: _SpecialForm + Never: _SpecialForm + def reveal_type(__obj: _T) -> _T: ... + def assert_never(__arg: NoReturn) -> NoReturn: ... + +# Experimental (hopefully these will be in 3.11) +Required: _SpecialForm +NotRequired: _SpecialForm +LiteralString: _SpecialForm +Unpack: _SpecialForm + +@final +class TypeVarTuple: + __name__: str + def __init__(self, name: str) -> None: ... + def __iter__(self) -> Any: ... # Unpack[Self] + +def dataclass_transform( + *, + eq_default: bool = ..., + order_default: bool = ..., + kw_only_default: bool = ..., + field_descriptors: tuple[type[Any] | Callable[..., Any], ...] = ..., +) -> Callable[[_T], _T]: ... diff --git a/mypy/typeshed/stdlib/unicodedata.pyi b/mypy/typeshed/stdlib/unicodedata.pyi index ead25ba4062c4..aec8867df48d9 100644 --- a/mypy/typeshed/stdlib/unicodedata.pyi +++ b/mypy/typeshed/stdlib/unicodedata.pyi @@ -1,10 +1,13 @@ import sys from typing import Any, TypeVar +from typing_extensions import final ucd_3_2_0: UCD -ucnhash_CAPI: Any unidata_version: str +if sys.version_info < (3, 10): + ucnhash_CAPI: Any + _T = TypeVar("_T") def bidirectional(__chr: str) -> str: ... @@ -23,7 +26,7 @@ def mirrored(__chr: str) -> int: ... def name(__chr: str, __default: _T = ...) -> str | _T: ... def normalize(__form: str, __unistr: str) -> str: ... def numeric(__chr: str, __default: _T = ...) -> float | _T: ... - +@final class UCD: # The methods below are constructed from the same array in C # (unicodedata_functions) and hence identical to the methods above. diff --git a/mypy/typeshed/stdlib/unittest/__init__.pyi b/mypy/typeshed/stdlib/unittest/__init__.pyi index d3b0efaa83ff0..4bbf98c992c1a 100644 --- a/mypy/typeshed/stdlib/unittest/__init__.pyi +++ b/mypy/typeshed/stdlib/unittest/__init__.pyi @@ -1,5 +1,4 @@ import sys -from unittest.async_case import * from .case import ( FunctionTestCase as FunctionTestCase, @@ -29,6 +28,59 @@ from .signals import ( from .suite import BaseTestSuite as BaseTestSuite, TestSuite as TestSuite if sys.version_info >= (3, 8): + from unittest.async_case import * + from .case import addModuleCleanup as addModuleCleanup + __all__ = [ + "TestResult", + "TestCase", + "IsolatedAsyncioTestCase", + "TestSuite", + "TextTestRunner", + "TestLoader", + "FunctionTestCase", + "main", + "defaultTestLoader", + "SkipTest", + "skip", + "skipIf", + "skipUnless", + "expectedFailure", + "TextTestResult", + "installHandler", + "registerResult", + "removeResult", + "removeHandler", + "addModuleCleanup", + "getTestCaseNames", + "makeSuite", + "findTestCases", + ] + +else: + __all__ = [ + "TestResult", + "TestCase", + "TestSuite", + "TextTestRunner", + "TestLoader", + "FunctionTestCase", + "main", + "defaultTestLoader", + "SkipTest", + "skip", + "skipIf", + "skipUnless", + "expectedFailure", + "TextTestResult", + "installHandler", + "registerResult", + "removeResult", + "removeHandler", + "getTestCaseNames", + "makeSuite", + "findTestCases", + ] + def load_tests(loader: TestLoader, tests: TestSuite, pattern: str | None) -> TestSuite: ... diff --git a/mypy/typeshed/stdlib/unittest/_log.pyi b/mypy/typeshed/stdlib/unittest/_log.pyi index f9e406199cd48..4de5d502e0049 100644 --- a/mypy/typeshed/stdlib/unittest/_log.pyi +++ b/mypy/typeshed/stdlib/unittest/_log.pyi @@ -1,7 +1,7 @@ import logging import sys from types import TracebackType -from typing import ClassVar, Generic, NamedTuple, Type, TypeVar +from typing import ClassVar, Generic, NamedTuple, TypeVar from unittest.case import TestCase _L = TypeVar("_L", None, _LoggingWatcher) @@ -21,7 +21,8 @@ class _AssertLogsContext(Generic[_L]): no_logs: bool else: def __init__(self, test_case: TestCase, logger_name: str, level: int) -> None: ... + def __enter__(self) -> _L: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_value: BaseException | None, tb: TracebackType | None ) -> bool | None: ... diff --git a/mypy/typeshed/stdlib/unittest/async_case.pyi b/mypy/typeshed/stdlib/unittest/async_case.pyi index bdf534b37c9f6..0442ec4445595 100644 --- a/mypy/typeshed/stdlib/unittest/async_case.pyi +++ b/mypy/typeshed/stdlib/unittest/async_case.pyi @@ -1,10 +1,11 @@ -import sys -from typing import Any, Awaitable, Callable +from typing import Awaitable, Callable +from typing_extensions import ParamSpec from .case import TestCase -if sys.version_info >= (3, 8): - class IsolatedAsyncioTestCase(TestCase): - async def asyncSetUp(self) -> None: ... - async def asyncTearDown(self) -> None: ... - def addAsyncCleanup(self, __func: Callable[..., Awaitable[Any]], *args: Any, **kwargs: Any) -> None: ... +_P = ParamSpec("_P") + +class IsolatedAsyncioTestCase(TestCase): + async def asyncSetUp(self) -> None: ... + async def asyncTearDown(self) -> None: ... + def addAsyncCleanup(self, __func: Callable[_P, Awaitable[object]], *args: _P.args, **kwargs: _P.kwargs) -> None: ... diff --git a/mypy/typeshed/stdlib/unittest/case.pyi b/mypy/typeshed/stdlib/unittest/case.pyi index 858bf38e700d3..87441920fe501 100644 --- a/mypy/typeshed/stdlib/unittest/case.pyi +++ b/mypy/typeshed/stdlib/unittest/case.pyi @@ -19,10 +19,10 @@ from typing import ( NoReturn, Pattern, Sequence, - Type, TypeVar, overload, ) +from typing_extensions import ParamSpec from warnings import WarningMessage if sys.version_info >= (3, 9): @@ -30,6 +30,7 @@ if sys.version_info >= (3, 9): _E = TypeVar("_E", bound=BaseException) _FT = TypeVar("_FT", bound=Callable[..., Any]) +_P = ParamSpec("_P") DIFF_OMITTED: str @@ -43,9 +44,11 @@ else: # this is generic over the logging watcher, but in lower versions # the watcher is hard-coded. _L = TypeVar("_L") + class _LoggingWatcher(NamedTuple): records: list[logging.LogRecord] output: list[str] + class _AssertLogsContext(_BaseTestCaseContext, Generic[_L]): LOGGING_FORMAT: ClassVar[str] test_case: TestCase @@ -55,11 +58,11 @@ else: def __init__(self, test_case: TestCase, logger_name: str, level: int) -> None: ... def __enter__(self) -> _LoggingWatcher: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> bool | None: ... if sys.version_info >= (3, 8): - def addModuleCleanup(__function: Callable[..., Any], *args: Any, **kwargs: Any) -> None: ... + def addModuleCleanup(__function: Callable[_P, object], *args: _P.args, **kwargs: _P.kwargs) -> None: ... def doModuleCleanups() -> None: ... def expectedFailure(test_item: _FT) -> _FT: ... @@ -71,7 +74,7 @@ class SkipTest(Exception): def __init__(self, reason: str) -> None: ... class TestCase: - failureException: Type[BaseException] + failureException: type[BaseException] longMessage: bool maxDiff: int | None # undocumented @@ -79,6 +82,7 @@ class TestCase: # undocumented _testMethodDoc: str def __init__(self, methodName: str = ...) -> None: ... + def __eq__(self, other: object) -> bool: ... def setUp(self) -> None: ... def tearDown(self) -> None: ... @classmethod @@ -107,51 +111,58 @@ class TestCase: def assertGreaterEqual(self, a: Any, b: Any, msg: Any = ...) -> None: ... def assertLess(self, a: Any, b: Any, msg: Any = ...) -> None: ... def assertLessEqual(self, a: Any, b: Any, msg: Any = ...) -> None: ... + # `assertRaises`, `assertRaisesRegex`, and `assertRaisesRegexp` + # are not using `ParamSpec` intentionally, + # because they might be used with explicitly wrong arg types to raise some error in tests. @overload def assertRaises( # type: ignore[misc] self, - expected_exception: Type[BaseException] | tuple[Type[BaseException], ...], - callable: Callable[..., Any], + expected_exception: type[BaseException] | tuple[type[BaseException], ...], + callable: Callable[..., object], *args: Any, **kwargs: Any, ) -> None: ... @overload - def assertRaises(self, expected_exception: Type[_E] | tuple[Type[_E], ...], msg: Any = ...) -> _AssertRaisesContext[_E]: ... + def assertRaises(self, expected_exception: type[_E] | tuple[type[_E], ...], msg: Any = ...) -> _AssertRaisesContext[_E]: ... @overload def assertRaisesRegex( # type: ignore[misc] self, - expected_exception: Type[BaseException] | tuple[Type[BaseException], ...], + expected_exception: type[BaseException] | tuple[type[BaseException], ...], expected_regex: str | bytes | Pattern[str] | Pattern[bytes], - callable: Callable[..., Any], + callable: Callable[..., object], *args: Any, **kwargs: Any, ) -> None: ... @overload def assertRaisesRegex( self, - expected_exception: Type[_E] | tuple[Type[_E], ...], + expected_exception: type[_E] | tuple[type[_E], ...], expected_regex: str | bytes | Pattern[str] | Pattern[bytes], msg: Any = ..., ) -> _AssertRaisesContext[_E]: ... @overload def assertWarns( # type: ignore[misc] - self, expected_warning: Type[Warning] | tuple[Type[Warning], ...], callable: Callable[..., Any], *args: Any, **kwargs: Any + self, + expected_warning: type[Warning] | tuple[type[Warning], ...], + callable: Callable[_P, object], + *args: _P.args, + **kwargs: _P.kwargs, ) -> None: ... @overload - def assertWarns(self, expected_warning: Type[Warning] | tuple[Type[Warning], ...], msg: Any = ...) -> _AssertWarnsContext: ... + def assertWarns(self, expected_warning: type[Warning] | tuple[type[Warning], ...], msg: Any = ...) -> _AssertWarnsContext: ... @overload def assertWarnsRegex( # type: ignore[misc] self, - expected_warning: Type[Warning] | tuple[Type[Warning], ...], + expected_warning: type[Warning] | tuple[type[Warning], ...], expected_regex: str | bytes | Pattern[str] | Pattern[bytes], - callable: Callable[..., Any], - *args: Any, - **kwargs: Any, + callable: Callable[_P, object], + *args: _P.args, + **kwargs: _P.kwargs, ) -> None: ... @overload def assertWarnsRegex( self, - expected_warning: Type[Warning] | tuple[Type[Warning], ...], + expected_warning: type[Warning] | tuple[type[Warning], ...], expected_regex: str | bytes | Pattern[str] | Pattern[bytes], msg: Any = ..., ) -> _AssertWarnsContext: ... @@ -162,6 +173,7 @@ class TestCase: def assertNoLogs( self, logger: str | logging.Logger | None = ..., level: int | str | None = ... ) -> _AssertLogsContext[None]: ... + @overload def assertAlmostEqual( self, first: float, second: float, places: int | None = ..., msg: Any = ..., delta: float | None = ... @@ -193,10 +205,10 @@ class TestCase: def assertRegex(self, text: AnyStr, expected_regex: AnyStr | Pattern[AnyStr], msg: Any = ...) -> None: ... def assertNotRegex(self, text: AnyStr, unexpected_regex: AnyStr | Pattern[AnyStr], msg: Any = ...) -> None: ... def assertCountEqual(self, first: Iterable[Any], second: Iterable[Any], msg: Any = ...) -> None: ... - def addTypeEqualityFunc(self, typeobj: Type[Any], function: Callable[..., None]) -> None: ... + def addTypeEqualityFunc(self, typeobj: type[Any], function: Callable[..., None]) -> None: ... def assertMultiLineEqual(self, first: str, second: str, msg: Any = ...) -> None: ... def assertSequenceEqual( - self, seq1: Sequence[Any], seq2: Sequence[Any], msg: Any = ..., seq_type: Type[Sequence[Any]] | None = ... + self, seq1: Sequence[Any], seq2: Sequence[Any], msg: Any = ..., seq_type: type[Sequence[Any]] | None = ... ) -> None: ... def assertListEqual(self, list1: list[Any], list2: list[Any], msg: Any = ...) -> None: ... def assertTupleEqual(self, tuple1: tuple[Any, ...], tuple2: tuple[Any, ...], msg: Any = ...) -> None: ... @@ -208,18 +220,20 @@ class TestCase: def id(self) -> str: ... def shortDescription(self) -> str | None: ... if sys.version_info >= (3, 8): - def addCleanup(self, __function: Callable[..., Any], *args: Any, **kwargs: Any) -> None: ... + def addCleanup(self, __function: Callable[_P, object], *args: _P.args, **kwargs: _P.kwargs) -> None: ... else: - def addCleanup(self, function: Callable[..., Any], *args: Any, **kwargs: Any) -> None: ... + def addCleanup(self, function: Callable[_P, object], *args: _P.args, **kwargs: _P.kwargs) -> None: ... + def doCleanups(self) -> None: ... if sys.version_info >= (3, 8): @classmethod - def addClassCleanup(cls, __function: Callable[..., Any], *args: Any, **kwargs: Any) -> None: ... + def addClassCleanup(cls, __function: Callable[_P, object], *args: _P.args, **kwargs: _P.kwargs) -> None: ... @classmethod def doClassCleanups(cls) -> None: ... + def _formatMessage(self, msg: str | None, standardMsg: str) -> str: ... # undocumented def _getAssertEqualityFunc(self, first: Any, second: Any) -> Callable[..., None]: ... # undocumented - if sys.version_info < (3, 11): + if sys.version_info < (3, 12): def failUnlessEqual(self, first: Any, second: Any, msg: Any = ...) -> None: ... def assertEquals(self, first: Any, second: Any, msg: Any = ...) -> None: ... def failIfEqual(self, first: Any, second: Any, msg: Any = ...) -> None: ... @@ -230,13 +244,13 @@ class TestCase: @overload def failUnlessRaises( # type: ignore[misc] self, - exception: Type[BaseException] | tuple[Type[BaseException], ...], - callable: Callable[..., Any] = ..., - *args: Any, - **kwargs: Any, + exception: type[BaseException] | tuple[type[BaseException], ...], + callable: Callable[_P, object] = ..., + *args: _P.args, + **kwargs: _P.kwargs, ) -> None: ... @overload - def failUnlessRaises(self, exception: Type[_E] | tuple[Type[_E], ...], msg: Any = ...) -> _AssertRaisesContext[_E]: ... + def failUnlessRaises(self, exception: type[_E] | tuple[type[_E], ...], msg: Any = ...) -> _AssertRaisesContext[_E]: ... def failUnlessAlmostEqual(self, first: float, second: float, places: int = ..., msg: Any = ...) -> None: ... def assertAlmostEquals( self, first: float, second: float, places: int = ..., msg: Any = ..., delta: float = ... @@ -250,16 +264,16 @@ class TestCase: @overload def assertRaisesRegexp( # type: ignore[misc] self, - exception: Type[BaseException] | tuple[Type[BaseException], ...], + exception: type[BaseException] | tuple[type[BaseException], ...], expected_regex: str | bytes | Pattern[str] | Pattern[bytes], - callable: Callable[..., Any], + callable: Callable[..., object], *args: Any, **kwargs: Any, ) -> None: ... @overload def assertRaisesRegexp( self, - exception: Type[_E] | tuple[Type[_E], ...], + exception: type[_E] | tuple[type[_E], ...], expected_regex: str | bytes | Pattern[str] | Pattern[bytes], msg: Any = ..., ) -> _AssertRaisesContext[_E]: ... @@ -281,7 +295,7 @@ class _AssertRaisesContext(Generic[_E]): exception: _E def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_value: BaseException | None, tb: TracebackType | None ) -> bool: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... @@ -293,5 +307,5 @@ class _AssertWarnsContext: warnings: list[WarningMessage] def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_value: BaseException | None, tb: TracebackType | None ) -> None: ... diff --git a/mypy/typeshed/stdlib/unittest/loader.pyi b/mypy/typeshed/stdlib/unittest/loader.pyi index aca7e4f9554f6..8b3c82233cec7 100644 --- a/mypy/typeshed/stdlib/unittest/loader.pyi +++ b/mypy/typeshed/stdlib/unittest/loader.pyi @@ -3,7 +3,7 @@ import unittest.case import unittest.result import unittest.suite from types import ModuleType -from typing import Any, Callable, Pattern, Sequence, Type +from typing import Any, Callable, Pattern, Sequence _SortComparisonMethod = Callable[[str, str], int] _SuiteClass = Callable[[list[unittest.case.TestCase]], unittest.suite.TestSuite] @@ -11,7 +11,7 @@ _SuiteClass = Callable[[list[unittest.case.TestCase]], unittest.suite.TestSuite] VALID_MODULE_NAME: Pattern[str] class TestLoader: - errors: list[Type[BaseException]] + errors: list[type[BaseException]] testMethodPrefix: str sortTestMethodsUsing: _SortComparisonMethod @@ -19,18 +19,18 @@ class TestLoader: testNamePatterns: list[str] | None suiteClass: _SuiteClass - def loadTestsFromTestCase(self, testCaseClass: Type[unittest.case.TestCase]) -> unittest.suite.TestSuite: ... + def loadTestsFromTestCase(self, testCaseClass: type[unittest.case.TestCase]) -> unittest.suite.TestSuite: ... def loadTestsFromModule(self, module: ModuleType, *args: Any, pattern: Any = ...) -> unittest.suite.TestSuite: ... def loadTestsFromName(self, name: str, module: ModuleType | None = ...) -> unittest.suite.TestSuite: ... def loadTestsFromNames(self, names: Sequence[str], module: ModuleType | None = ...) -> unittest.suite.TestSuite: ... - def getTestCaseNames(self, testCaseClass: Type[unittest.case.TestCase]) -> Sequence[str]: ... + def getTestCaseNames(self, testCaseClass: type[unittest.case.TestCase]) -> Sequence[str]: ... def discover(self, start_dir: str, pattern: str = ..., top_level_dir: str | None = ...) -> unittest.suite.TestSuite: ... defaultTestLoader: TestLoader if sys.version_info >= (3, 7): def getTestCaseNames( - testCaseClass: Type[unittest.case.TestCase], + testCaseClass: type[unittest.case.TestCase], prefix: str, sortUsing: _SortComparisonMethod = ..., testNamePatterns: list[str] | None = ..., @@ -38,11 +38,11 @@ if sys.version_info >= (3, 7): else: def getTestCaseNames( - testCaseClass: Type[unittest.case.TestCase], prefix: str, sortUsing: _SortComparisonMethod = ... + testCaseClass: type[unittest.case.TestCase], prefix: str, sortUsing: _SortComparisonMethod = ... ) -> Sequence[str]: ... def makeSuite( - testCaseClass: Type[unittest.case.TestCase], + testCaseClass: type[unittest.case.TestCase], prefix: str = ..., sortUsing: _SortComparisonMethod = ..., suiteClass: _SuiteClass = ..., diff --git a/mypy/typeshed/stdlib/unittest/main.pyi b/mypy/typeshed/stdlib/unittest/main.pyi index 6d1117ecaf79a..d3c0ca722f4dc 100644 --- a/mypy/typeshed/stdlib/unittest/main.pyi +++ b/mypy/typeshed/stdlib/unittest/main.pyi @@ -4,7 +4,7 @@ import unittest.loader import unittest.result import unittest.suite from types import ModuleType -from typing import Any, Iterable, Protocol, Type +from typing import Any, Iterable, Protocol MAIN_EXAMPLES: str MODULE_EXAMPLES: str @@ -30,7 +30,7 @@ class TestProgram: module: None | str | ModuleType = ..., defaultTest: str | Iterable[str] | None = ..., argv: list[str] | None = ..., - testRunner: Type[_TestRunner] | _TestRunner | None = ..., + testRunner: type[_TestRunner] | _TestRunner | None = ..., testLoader: unittest.loader.TestLoader = ..., exit: bool = ..., verbosity: int = ..., @@ -47,6 +47,7 @@ class TestProgram: def createTests(self, from_discovery: bool = ..., Loader: unittest.loader.TestLoader | None = ...) -> None: ... else: def createTests(self) -> None: ... + def runTests(self) -> None: ... # undocumented main = TestProgram diff --git a/mypy/typeshed/stdlib/unittest/mock.pyi b/mypy/typeshed/stdlib/unittest/mock.pyi index 72d0bab95c2e4..f5cd4218cea0b 100644 --- a/mypy/typeshed/stdlib/unittest/mock.pyi +++ b/mypy/typeshed/stdlib/unittest/mock.pyi @@ -1,8 +1,12 @@ import sys -from typing import Any, Awaitable, Callable, Generic, Iterable, Mapping, Sequence, Type, TypeVar, overload +from _typeshed import Self +from contextlib import _GeneratorContextManager +from types import TracebackType +from typing import Any, Awaitable, Callable, Generic, Iterable, Mapping, Sequence, TypeVar, overload +from typing_extensions import Literal _T = TypeVar("_T") -_TT = TypeVar("_TT", bound=Type[Any]) +_TT = TypeVar("_TT", bound=type[Any]) _R = TypeVar("_R") if sys.version_info >= (3, 8): @@ -73,25 +77,36 @@ class _Sentinel: sentinel: Any DEFAULT: Any +_ArgsKwargs = tuple[tuple[Any, ...], Mapping[str, Any]] +_NameArgsKwargs = tuple[str, tuple[Any, ...], Mapping[str, Any]] +_CallValue = str | tuple[Any, ...] | Mapping[str, Any] | _ArgsKwargs | _NameArgsKwargs + class _Call(tuple[Any, ...]): def __new__( - cls, value: Any = ..., name: Any | None = ..., parent: Any | None = ..., two: bool = ..., from_kall: bool = ... - ) -> Any: ... + cls: type[Self], + value: _CallValue = ..., + name: str | None = ..., + parent: Any | None = ..., + two: bool = ..., + from_kall: bool = ..., + ) -> Self: ... name: Any parent: Any from_kall: Any def __init__( - self, value: Any = ..., name: Any | None = ..., parent: Any | None = ..., two: bool = ..., from_kall: bool = ... + self, value: _CallValue = ..., name: str | None = ..., parent: Any | None = ..., two: bool = ..., from_kall: bool = ... ) -> None: ... - def __eq__(self, other: Any) -> bool: ... - __ne__: Any + def __eq__(self, other: object) -> bool: ... + def __ne__(self, __other: object) -> bool: ... def __call__(self, *args: Any, **kwargs: Any) -> _Call: ... def __getattr__(self, attr: Any) -> Any: ... + def __getattribute__(self, attr: str) -> Any: ... if sys.version_info >= (3, 8): @property - def args(self): ... + def args(self) -> tuple[Any, ...]: ... @property - def kwargs(self): ... + def kwargs(self) -> Mapping[str, Any]: ... + def call_list(self) -> Any: ... call: _Call @@ -103,13 +118,13 @@ class Base: def __init__(self, *args: Any, **kwargs: Any) -> None: ... class NonCallableMock(Base, Any): - def __new__(__cls, *args: Any, **kw: Any) -> NonCallableMock: ... + def __new__(__cls: type[Self], *args: Any, **kw: Any) -> Self: ... def __init__( self, - spec: list[str] | object | Type[object] | None = ..., + spec: list[str] | object | type[object] | None = ..., wraps: Any | None = ..., name: str | None = ..., - spec_set: list[str] | object | Type[object] | None = ..., + spec_set: list[str] | object | type[object] | None = ..., parent: NonCallableMock | None = ..., _spec_state: Any | None = ..., _new_name: str = ..., @@ -120,6 +135,8 @@ class NonCallableMock(Base, Any): **kwargs: Any, ) -> None: ... def __getattr__(self, name: str) -> Any: ... + def __delattr__(self, name: str) -> None: ... + def __setattr__(self, name: str, value: Any) -> None: ... if sys.version_info >= (3, 8): def _calls_repr(self, prefix: str = ...) -> str: ... def assert_called_with(self, *args: Any, **kwargs: Any) -> None: ... @@ -137,10 +154,12 @@ class NonCallableMock(Base, Any): else: def assert_called(_mock_self) -> None: ... def assert_called_once(_mock_self) -> None: ... + def reset_mock(self, visited: Any = ..., *, return_value: bool = ..., side_effect: bool = ...) -> None: ... if sys.version_info >= (3, 7): def _extract_mock_name(self) -> str: ... def _get_call_signature_from_name(self, name: str) -> Any: ... + def assert_any_call(self, *args: Any, **kwargs: Any) -> None: ... def assert_has_calls(self, calls: Sequence[_Call], any_order: bool = ...) -> None: ... def mock_add_spec(self, spec: Any, spec_set: bool = ...) -> None: ... @@ -224,23 +243,30 @@ class _patch(Generic[_T]): new_callable: Any | None, kwargs: Mapping[str, Any], ) -> None: ... + def copy(self) -> _patch[_T]: ... @overload def __call__(self, func: _TT) -> _TT: ... @overload def __call__(self, func: Callable[..., _R]) -> Callable[..., _R]: ... if sys.version_info >= (3, 8): - def decoration_helper(self, patched, args, keywargs): ... + def decoration_helper( + self, patched: _patch[Any], args: Sequence[Any], keywargs: Any + ) -> _GeneratorContextManager[tuple[Sequence[Any], Any]]: ... + def decorate_class(self, klass: _TT) -> _TT: ... def decorate_callable(self, func: Callable[..., _R]) -> Callable[..., _R]: ... if sys.version_info >= (3, 8): def decorate_async_callable(self, func: Callable[..., Awaitable[_R]]) -> Callable[..., Awaitable[_R]]: ... + def get_original(self) -> tuple[Any, bool]: ... target: Any temp_original: Any is_local: bool def __enter__(self) -> _T: ... - def __exit__(self, *exc_info: Any) -> None: ... + def __exit__( + self, __exc_type: type[BaseException] | None, __exc_value: BaseException | None, __traceback: TracebackType | None + ) -> None: ... def start(self) -> _T: ... def stop(self) -> None: ... @@ -252,120 +278,71 @@ class _patch_dict: def __call__(self, f: Any) -> Any: ... def decorate_class(self, klass: Any) -> Any: ... def __enter__(self) -> Any: ... - def __exit__(self, *args: Any) -> Any: ... + def __exit__(self, *args: object) -> Any: ... start: Any stop: Any +if sys.version_info >= (3, 8): + _Mock = MagicMock | AsyncMock +else: + _Mock = MagicMock + class _patcher: TEST_PREFIX: str - dict: Type[_patch_dict] - if sys.version_info >= (3, 8): - # This overload also covers the case, where new==DEFAULT. In this case, the return type is _patch[Any]. - # Ideally we'd be able to add an overload for it so that the return type is _patch[MagicMock], - # but that's impossible with the current type system. - @overload - def __call__( # type: ignore[misc] - self, - target: Any, - new: _T, - spec: Any | None = ..., - create: bool = ..., - spec_set: Any | None = ..., - autospec: Any | None = ..., - new_callable: Any | None = ..., - **kwargs: Any, - ) -> _patch[_T]: ... - @overload - def __call__( - self, - target: Any, - *, - spec: Any | None = ..., - create: bool = ..., - spec_set: Any | None = ..., - autospec: Any | None = ..., - new_callable: Any | None = ..., - **kwargs: Any, - ) -> _patch[MagicMock | AsyncMock]: ... - else: - @overload - def __call__( # type: ignore[misc] - self, - target: Any, - new: _T, - spec: Any | None = ..., - create: bool = ..., - spec_set: Any | None = ..., - autospec: Any | None = ..., - new_callable: Any | None = ..., - **kwargs: Any, - ) -> _patch[_T]: ... - @overload - def __call__( - self, - target: Any, - *, - spec: Any | None = ..., - create: bool = ..., - spec_set: Any | None = ..., - autospec: Any | None = ..., - new_callable: Any | None = ..., - **kwargs: Any, - ) -> _patch[MagicMock]: ... - if sys.version_info >= (3, 8): - @overload - def object( # type: ignore[misc] - self, - target: Any, - attribute: str, - new: _T, - spec: Any | None = ..., - create: bool = ..., - spec_set: Any | None = ..., - autospec: Any | None = ..., - new_callable: Any | None = ..., - **kwargs: Any, - ) -> _patch[_T]: ... - @overload - def object( - self, - target: Any, - attribute: str, - *, - spec: Any | None = ..., - create: bool = ..., - spec_set: Any | None = ..., - autospec: Any | None = ..., - new_callable: Any | None = ..., - **kwargs: Any, - ) -> _patch[MagicMock | AsyncMock]: ... - else: - @overload - def object( # type: ignore[misc] - self, - target: Any, - attribute: str, - new: _T, - spec: Any | None = ..., - create: bool = ..., - spec_set: Any | None = ..., - autospec: Any | None = ..., - new_callable: Any | None = ..., - **kwargs: Any, - ) -> _patch[_T]: ... - @overload - def object( - self, - target: Any, - attribute: str, - *, - spec: Any | None = ..., - create: bool = ..., - spec_set: Any | None = ..., - autospec: Any | None = ..., - new_callable: Any | None = ..., - **kwargs: Any, - ) -> _patch[MagicMock]: ... + dict: type[_patch_dict] + # This overload also covers the case, where new==DEFAULT. In this case, the return type is _patch[Any]. + # Ideally we'd be able to add an overload for it so that the return type is _patch[MagicMock], + # but that's impossible with the current type system. + @overload + def __call__( # type: ignore[misc] + self, + target: Any, + new: _T, + spec: Any | None = ..., + create: bool = ..., + spec_set: Any | None = ..., + autospec: Any | None = ..., + new_callable: Any | None = ..., + **kwargs: Any, + ) -> _patch[_T]: ... + @overload + def __call__( + self, + target: Any, + *, + spec: Any | None = ..., + create: bool = ..., + spec_set: Any | None = ..., + autospec: Any | None = ..., + new_callable: Any | None = ..., + **kwargs: Any, + ) -> _patch[_Mock]: ... + @overload + def object( # type: ignore[misc] + self, + target: Any, + attribute: str, + new: _T, + spec: Any | None = ..., + create: bool = ..., + spec_set: Any | None = ..., + autospec: Any | None = ..., + new_callable: Any | None = ..., + **kwargs: Any, + ) -> _patch[_T]: ... + @overload + def object( + self, + target: Any, + attribute: str, + *, + spec: Any | None = ..., + create: bool = ..., + spec_set: Any | None = ..., + autospec: Any | None = ..., + new_callable: Any | None = ..., + **kwargs: Any, + ) -> _patch[_Mock]: ... def multiple( self, target: Any, @@ -404,28 +381,44 @@ if sys.version_info >= (3, 8): await_count: int await_args: _Call | None await_args_list: _CallList + class AsyncMagicMixin(MagicMixin): def __init__(self, *args: Any, **kw: Any) -> None: ... + class AsyncMock(AsyncMockMixin, AsyncMagicMixin, Mock): ... class MagicProxy: - name: Any + name: str parent: Any - def __init__(self, name, parent) -> None: ... + def __init__(self, name: str, parent: Any) -> None: ... if sys.version_info < (3, 8): def __call__(self, *args: Any, **kwargs: Any) -> Any: ... - def create_mock(self): ... - def __get__(self, obj, _type: Any | None = ...): ... + + def create_mock(self) -> Any: ... + def __get__(self, obj: Any, _type: Any | None = ...) -> Any: ... class _ANY: - def __eq__(self, other: Any) -> bool: ... - def __ne__(self, other: Any) -> bool: ... + def __eq__(self, other: object) -> Literal[True]: ... + def __ne__(self, other: object) -> Literal[False]: ... ANY: Any -def create_autospec( - spec: Any, spec_set: Any = ..., instance: Any = ..., _parent: Any | None = ..., _name: Any | None = ..., **kwargs: Any -) -> Any: ... +if sys.version_info >= (3, 10): + def create_autospec( + spec: Any, + spec_set: Any = ..., + instance: Any = ..., + _parent: Any | None = ..., + _name: Any | None = ..., + *, + unsafe: bool = ..., + **kwargs: Any, + ) -> Any: ... + +else: + def create_autospec( + spec: Any, spec_set: Any = ..., instance: Any = ..., _parent: Any | None = ..., _name: Any | None = ..., **kwargs: Any + ) -> Any: ... class _SpecState: spec: Any diff --git a/mypy/typeshed/stdlib/unittest/result.pyi b/mypy/typeshed/stdlib/unittest/result.pyi index 9a19aef77d21c..1c79f8ab648c7 100644 --- a/mypy/typeshed/stdlib/unittest/result.pyi +++ b/mypy/typeshed/stdlib/unittest/result.pyi @@ -1,8 +1,8 @@ import unittest.case from types import TracebackType -from typing import Any, Callable, TextIO, Type, TypeVar, Union +from typing import Any, Callable, TextIO, TypeVar, Union -_SysExcInfoType = Union[tuple[Type[BaseException], BaseException, TracebackType], tuple[None, None, None]] +_SysExcInfoType = Union[tuple[type[BaseException], BaseException, TracebackType], tuple[None, None, None]] _F = TypeVar("_F", bound=Callable[..., Any]) diff --git a/mypy/typeshed/stdlib/unittest/runner.pyi b/mypy/typeshed/stdlib/unittest/runner.pyi index 85481880ab173..479a9f2c304c1 100644 --- a/mypy/typeshed/stdlib/unittest/runner.pyi +++ b/mypy/typeshed/stdlib/unittest/runner.pyi @@ -1,7 +1,7 @@ import unittest.case import unittest.result import unittest.suite -from typing import Callable, TextIO, Type +from typing import Callable, Iterable, TextIO _ResultClassType = Callable[[TextIO, bool, int], unittest.result.TestResult] @@ -10,12 +10,12 @@ class TextTestResult(unittest.result.TestResult): dots: bool # undocumented separator1: str separator2: str - showall: bool # undocumented + showAll: bool # undocumented stream: TextIO # undocumented def __init__(self, stream: TextIO, descriptions: bool, verbosity: int) -> None: ... def getDescription(self, test: unittest.case.TestCase) -> str: ... def printErrors(self) -> None: ... - def printErrorList(self, flavour: str, errors: tuple[unittest.case.TestCase, str]) -> None: ... + def printErrorList(self, flavour: str, errors: Iterable[tuple[unittest.case.TestCase, str]]) -> None: ... class TextTestRunner: resultclass: _ResultClassType @@ -27,7 +27,7 @@ class TextTestRunner: failfast: bool = ..., buffer: bool = ..., resultclass: _ResultClassType | None = ..., - warnings: Type[Warning] | None = ..., + warnings: type[Warning] | None = ..., *, tb_locals: bool = ..., ) -> None: ... diff --git a/mypy/typeshed/stdlib/unittest/suite.pyi b/mypy/typeshed/stdlib/unittest/suite.pyi index 396b46eadf5a1..ca483b06ac9f1 100644 --- a/mypy/typeshed/stdlib/unittest/suite.pyi +++ b/mypy/typeshed/stdlib/unittest/suite.pyi @@ -1,8 +1,8 @@ import unittest.case import unittest.result -from typing import Iterable, Iterator, Union +from typing import Iterable, Iterator -_TestType = Union[unittest.case.TestCase, TestSuite] +_TestType = unittest.case.TestCase | TestSuite class BaseTestSuite(Iterable[_TestType]): _tests: list[unittest.case.TestCase] @@ -15,6 +15,7 @@ class BaseTestSuite(Iterable[_TestType]): def debug(self) -> None: ... def countTestCases(self) -> int: ... def __iter__(self) -> Iterator[_TestType]: ... + def __eq__(self, other: object) -> bool: ... class TestSuite(BaseTestSuite): def run(self, result: unittest.result.TestResult, debug: bool = ...) -> unittest.result.TestResult: ... diff --git a/mypy/typeshed/stdlib/unittest/util.pyi b/mypy/typeshed/stdlib/unittest/util.pyi index 680ca24b7c335..30ab6061b1009 100644 --- a/mypy/typeshed/stdlib/unittest/util.pyi +++ b/mypy/typeshed/stdlib/unittest/util.pyi @@ -11,7 +11,7 @@ _MIN_COMMON_LEN: int _MIN_DIFF_LEN: int def _shorten(s: str, prefixlen: int, suffixlen: int) -> str: ... -def _common_shorten_repr(*args: str) -> tuple[str]: ... +def _common_shorten_repr(*args: str) -> tuple[str, ...]: ... def safe_repr(obj: object, short: bool = ...) -> str: ... def strclass(cls: type) -> str: ... def sorted_list_difference(expected: Sequence[_T], actual: Sequence[_T]) -> tuple[list[_T], list[_T]]: ... diff --git a/mypy/typeshed/stdlib/urllib/error.pyi b/mypy/typeshed/stdlib/urllib/error.pyi index 1d91fedceeca2..48c8287e979a4 100644 --- a/mypy/typeshed/stdlib/urllib/error.pyi +++ b/mypy/typeshed/stdlib/urllib/error.pyi @@ -2,13 +2,15 @@ from email.message import Message from typing import IO from urllib.response import addinfourl -# Stubs for urllib.error +__all__ = ["URLError", "HTTPError", "ContentTooShortError"] class URLError(IOError): reason: str | BaseException def __init__(self, reason: str | BaseException, filename: str | None = ...) -> None: ... class HTTPError(URLError, addinfourl): + @property + def reason(self) -> str: ... # type: ignore[override] code: int def __init__(self, url: str, code: int, msg: str, hdrs: Message, fp: IO[bytes] | None) -> None: ... diff --git a/mypy/typeshed/stdlib/urllib/parse.pyi b/mypy/typeshed/stdlib/urllib/parse.pyi index 7404b53820143..a45e23dd9084b 100644 --- a/mypy/typeshed/stdlib/urllib/parse.pyi +++ b/mypy/typeshed/stdlib/urllib/parse.pyi @@ -1,10 +1,34 @@ import sys -from typing import Any, AnyStr, Callable, Generic, Mapping, NamedTuple, Sequence, Union, overload +from typing import Any, AnyStr, Callable, Generic, Mapping, NamedTuple, Sequence, overload if sys.version_info >= (3, 9): from types import GenericAlias -_Str = Union[bytes, str] +__all__ = [ + "urlparse", + "urlunparse", + "urljoin", + "urldefrag", + "urlsplit", + "urlunsplit", + "urlencode", + "parse_qs", + "parse_qsl", + "quote", + "quote_plus", + "quote_from_bytes", + "unquote", + "unquote_plus", + "unquote_to_bytes", + "DefragResult", + "ParseResult", + "SplitResult", + "DefragResultBytes", + "ParseResultBytes", + "SplitResultBytes", +] + +_Str = bytes | str uses_relative: list[str] uses_netloc: list[str] @@ -21,14 +45,18 @@ class _ResultMixinBase(Generic[AnyStr]): class _ResultMixinStr(_ResultMixinBase[str]): def encode(self, encoding: str = ..., errors: str = ...) -> _ResultMixinBytes: ... -class _ResultMixinBytes(_ResultMixinBase[str]): +class _ResultMixinBytes(_ResultMixinBase[bytes]): def decode(self, encoding: str = ..., errors: str = ...) -> _ResultMixinStr: ... class _NetlocResultMixinBase(Generic[AnyStr]): - username: AnyStr | None - password: AnyStr | None - hostname: AnyStr | None - port: int | None + @property + def username(self) -> AnyStr | None: ... + @property + def password(self) -> AnyStr | None: ... + @property + def hostname(self) -> AnyStr | None: ... + @property + def port(self) -> int | None: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... @@ -36,8 +64,12 @@ class _NetlocResultMixinStr(_NetlocResultMixinBase[str], _ResultMixinStr): ... class _NetlocResultMixinBytes(_NetlocResultMixinBase[bytes], _ResultMixinBytes): ... class _DefragResultBase(tuple[Any, ...], Generic[AnyStr]): - url: AnyStr - fragment: AnyStr + if sys.version_info >= (3, 10): + __match_args__ = ("url", "fragment") + @property + def url(self) -> AnyStr: ... + @property + def fragment(self) -> AnyStr: ... class _SplitResultBase(NamedTuple): scheme: str @@ -140,3 +172,4 @@ def urlunparse(components: Sequence[AnyStr | None]) -> AnyStr: ... def urlunsplit(components: tuple[AnyStr | None, AnyStr | None, AnyStr | None, AnyStr | None, AnyStr | None]) -> AnyStr: ... @overload def urlunsplit(components: Sequence[AnyStr | None]) -> AnyStr: ... +def unwrap(url: str) -> str: ... diff --git a/mypy/typeshed/stdlib/urllib/request.pyi b/mypy/typeshed/stdlib/urllib/request.pyi index 3749d7a390ead..265ef21967158 100644 --- a/mypy/typeshed/stdlib/urllib/request.pyi +++ b/mypy/typeshed/stdlib/urllib/request.pyi @@ -1,19 +1,57 @@ import ssl import sys -from _typeshed import StrOrBytesPath +from _typeshed import StrOrBytesPath, SupportsRead from email.message import Message from http.client import HTTPMessage, HTTPResponse, _HTTPConnectionProtocol from http.cookiejar import CookieJar -from typing import IO, Any, Callable, ClassVar, Mapping, NoReturn, Pattern, Sequence, TypeVar, overload +from typing import IO, Any, Callable, ClassVar, Iterable, Mapping, MutableMapping, NoReturn, Pattern, Sequence, TypeVar, overload from urllib.error import HTTPError from urllib.response import addclosehook, addinfourl +__all__ = [ + "Request", + "OpenerDirector", + "BaseHandler", + "HTTPDefaultErrorHandler", + "HTTPRedirectHandler", + "HTTPCookieProcessor", + "ProxyHandler", + "HTTPPasswordMgr", + "HTTPPasswordMgrWithDefaultRealm", + "HTTPPasswordMgrWithPriorAuth", + "AbstractBasicAuthHandler", + "HTTPBasicAuthHandler", + "ProxyBasicAuthHandler", + "AbstractDigestAuthHandler", + "HTTPDigestAuthHandler", + "ProxyDigestAuthHandler", + "HTTPHandler", + "FileHandler", + "FTPHandler", + "CacheFTPHandler", + "DataHandler", + "UnknownHandler", + "HTTPErrorProcessor", + "urlopen", + "install_opener", + "build_opener", + "pathname2url", + "url2pathname", + "getproxies", + "urlretrieve", + "urlcleanup", + "URLopener", + "FancyURLopener", + "HTTPSHandler", +] + _T = TypeVar("_T") _UrlopenRet = Any +_DataType = bytes | SupportsRead[bytes] | Iterable[bytes] | None def urlopen( url: str | Request, - data: bytes | None = ..., + data: _DataType | None = ..., timeout: float | None = ..., *, cafile: str | None = ..., @@ -51,8 +89,8 @@ class Request: host: str origin_req_host: str selector: str - data: bytes | None - headers: dict[str, str] + data: _DataType + headers: MutableMapping[str, str] unredirected_hdrs: dict[str, str] unverifiable: bool method: str | None @@ -60,8 +98,8 @@ class Request: def __init__( self, url: str, - data: bytes | None = ..., - headers: dict[str, str] = ..., + data: _DataType = ..., + headers: MutableMapping[str, str] = ..., origin_req_host: str | None = ..., unverifiable: bool = ..., method: str | None = ..., @@ -83,7 +121,7 @@ class Request: class OpenerDirector: addheaders: list[tuple[str, str]] def add_handler(self, handler: BaseHandler) -> None: ... - def open(self, fullurl: str | Request, data: bytes | None = ..., timeout: float | None = ...) -> _UrlopenRet: ... + def open(self, fullurl: str | Request, data: _DataType = ..., timeout: float | None = ...) -> _UrlopenRet: ... def error(self, proto: str, *args: Any) -> _UrlopenRet: ... def close(self) -> None: ... @@ -92,6 +130,7 @@ class BaseHandler: parent: OpenerDirector def add_parent(self, parent: OpenerDirector) -> None: ... def close(self) -> None: ... + def __lt__(self, other: object) -> bool: ... class HTTPDefaultErrorHandler(BaseHandler): def http_error_default( @@ -241,7 +280,7 @@ def urlretrieve( url: str, filename: StrOrBytesPath | None = ..., reporthook: Callable[[int, int, int], None] | None = ..., - data: bytes | None = ..., + data: _DataType = ..., ) -> tuple[str, HTTPMessage]: ... def urlcleanup() -> None: ... diff --git a/mypy/typeshed/stdlib/urllib/response.pyi b/mypy/typeshed/stdlib/urllib/response.pyi index 18b498b407448..2efec0d47d44f 100644 --- a/mypy/typeshed/stdlib/urllib/response.pyi +++ b/mypy/typeshed/stdlib/urllib/response.pyi @@ -2,18 +2,18 @@ import sys from _typeshed import Self from email.message import Message from types import TracebackType -from typing import IO, Any, BinaryIO, Callable, Iterable, Type, TypeVar +from typing import IO, Any, BinaryIO, Callable, Iterable -_AIUT = TypeVar("_AIUT", bound=addbase) +__all__ = ["addbase", "addclosehook", "addinfo", "addinfourl"] class addbase(BinaryIO): fp: IO[bytes] def __init__(self, fp: IO[bytes]) -> None: ... def __enter__(self: Self) -> Self: ... def __exit__( - self, type: Type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None + self, type: type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None ) -> None: ... - def __iter__(self: _AIUT) -> _AIUT: ... + def __iter__(self: Self) -> Self: ... def __next__(self) -> bytes: ... def close(self) -> None: ... # These methods don't actually exist, but the class inherits at runtime from @@ -51,6 +51,7 @@ class addinfourl(addinfo): if sys.version_info >= (3, 9): @property def status(self) -> int | None: ... + def __init__(self, fp: IO[bytes], headers: Message, url: str, code: int | None = ...) -> None: ... def geturl(self) -> str: ... def getcode(self) -> int | None: ... diff --git a/mypy/typeshed/stdlib/urllib/robotparser.pyi b/mypy/typeshed/stdlib/urllib/robotparser.pyi index 3611263279936..d1d69546db427 100644 --- a/mypy/typeshed/stdlib/urllib/robotparser.pyi +++ b/mypy/typeshed/stdlib/urllib/robotparser.pyi @@ -1,7 +1,9 @@ import sys from typing import Iterable, NamedTuple -class _RequestRate(NamedTuple): +__all__ = ["RobotFileParser"] + +class RequestRate(NamedTuple): requests: int seconds: int @@ -14,6 +16,6 @@ class RobotFileParser: def mtime(self) -> int: ... def modified(self) -> None: ... def crawl_delay(self, useragent: str) -> str | None: ... - def request_rate(self, useragent: str) -> _RequestRate | None: ... + def request_rate(self, useragent: str) -> RequestRate | None: ... if sys.version_info >= (3, 8): def site_maps(self) -> list[str] | None: ... diff --git a/mypy/typeshed/stdlib/uu.pyi b/mypy/typeshed/stdlib/uu.pyi index aacd458c02c7b..d75df67a1f76d 100644 --- a/mypy/typeshed/stdlib/uu.pyi +++ b/mypy/typeshed/stdlib/uu.pyi @@ -1,7 +1,9 @@ import sys -from typing import BinaryIO, Union +from typing import BinaryIO -_File = Union[str, BinaryIO] +__all__ = ["Error", "encode", "decode"] + +_File = str | BinaryIO class Error(Exception): ... diff --git a/mypy/typeshed/stdlib/uuid.pyi b/mypy/typeshed/stdlib/uuid.pyi index 782c0491ffb2e..4d46e89beddd3 100644 --- a/mypy/typeshed/stdlib/uuid.pyi +++ b/mypy/typeshed/stdlib/uuid.pyi @@ -1,5 +1,4 @@ import sys -from typing import Any # Because UUID has properties called int and bytes we need to rename these temporarily. _Int = int @@ -8,6 +7,7 @@ _FieldsType = tuple[int, int, int, int, int, int] if sys.version_info >= (3, 7): from enum import Enum + class SafeUUID(Enum): safe: int unsafe: int @@ -38,6 +38,7 @@ class UUID: int: _Int | None = ..., version: _Int | None = ..., ) -> None: ... + @property def bytes(self) -> _Bytes: ... @property @@ -71,11 +72,11 @@ class UUID: @property def version(self) -> _Int | None: ... def __int__(self) -> _Int: ... - def __eq__(self, other: Any) -> bool: ... - def __lt__(self, other: Any) -> bool: ... - def __le__(self, other: Any) -> bool: ... - def __gt__(self, other: Any) -> bool: ... - def __ge__(self, other: Any) -> bool: ... + def __eq__(self, other: object) -> bool: ... + def __lt__(self, other: UUID) -> bool: ... + def __le__(self, other: UUID) -> bool: ... + def __gt__(self, other: UUID) -> bool: ... + def __ge__(self, other: UUID) -> bool: ... def getnode() -> int: ... def uuid1(node: _Int | None = ..., clock_seq: _Int | None = ...) -> UUID: ... diff --git a/mypy/typeshed/stdlib/venv/__init__.pyi b/mypy/typeshed/stdlib/venv/__init__.pyi index 7650e87d98b40..815490a205abc 100644 --- a/mypy/typeshed/stdlib/venv/__init__.pyi +++ b/mypy/typeshed/stdlib/venv/__init__.pyi @@ -35,6 +35,7 @@ class EnvBuilder: with_pip: bool = ..., prompt: str | None = ..., ) -> None: ... + def create(self, env_dir: StrOrBytesPath) -> None: ... def clear_directory(self, path: StrOrBytesPath) -> None: ... # undocumented def ensure_directories(self, env_dir: StrOrBytesPath) -> SimpleNamespace: ... diff --git a/mypy/typeshed/stdlib/warnings.pyi b/mypy/typeshed/stdlib/warnings.pyi index b1c9f4dda8edf..1799d69f5ba67 100644 --- a/mypy/typeshed/stdlib/warnings.pyi +++ b/mypy/typeshed/stdlib/warnings.pyi @@ -1,32 +1,43 @@ from _warnings import warn as warn, warn_explicit as warn_explicit from types import ModuleType, TracebackType -from typing import Any, Sequence, TextIO, Type, overload +from typing import Any, Sequence, TextIO, overload from typing_extensions import Literal +__all__ = [ + "warn", + "warn_explicit", + "showwarning", + "formatwarning", + "filterwarnings", + "simplefilter", + "resetwarnings", + "catch_warnings", +] + _ActionKind = Literal["default", "error", "ignore", "always", "module", "once"] -filters: Sequence[tuple[str, str | None, Type[Warning], str | None, int]] # undocumented, do not mutate +filters: Sequence[tuple[str, str | None, type[Warning], str | None, int]] # undocumented, do not mutate def showwarning( - message: Warning | str, category: Type[Warning], filename: str, lineno: int, file: TextIO | None = ..., line: str | None = ... + message: Warning | str, category: type[Warning], filename: str, lineno: int, file: TextIO | None = ..., line: str | None = ... ) -> None: ... -def formatwarning(message: Warning | str, category: Type[Warning], filename: str, lineno: int, line: str | None = ...) -> str: ... +def formatwarning(message: Warning | str, category: type[Warning], filename: str, lineno: int, line: str | None = ...) -> str: ... def filterwarnings( action: _ActionKind, message: str = ..., - category: Type[Warning] = ..., + category: type[Warning] = ..., module: str = ..., lineno: int = ..., append: bool = ..., ) -> None: ... -def simplefilter(action: _ActionKind, category: Type[Warning] = ..., lineno: int = ..., append: bool = ...) -> None: ... +def simplefilter(action: _ActionKind, category: type[Warning] = ..., lineno: int = ..., append: bool = ...) -> None: ... def resetwarnings() -> None: ... class _OptionError(Exception): ... class WarningMessage: message: Warning | str - category: Type[Warning] + category: type[Warning] filename: str lineno: int file: TextIO | None @@ -35,7 +46,7 @@ class WarningMessage: def __init__( self, message: Warning | str, - category: Type[Warning], + category: type[Warning], filename: str, lineno: int, file: TextIO | None = ..., @@ -52,7 +63,7 @@ class catch_warnings: def __new__(cls, *, record: bool, module: ModuleType | None = ...) -> catch_warnings: ... def __enter__(self) -> list[WarningMessage] | None: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> None: ... class _catch_warnings_without_records(catch_warnings): diff --git a/mypy/typeshed/stdlib/wave.pyi b/mypy/typeshed/stdlib/wave.pyi index 3ce1b88a68358..de20c6c4f5d41 100644 --- a/mypy/typeshed/stdlib/wave.pyi +++ b/mypy/typeshed/stdlib/wave.pyi @@ -1,12 +1,18 @@ import sys -from _typeshed import Self -from typing import IO, Any, BinaryIO, NamedTuple, NoReturn, Union +from _typeshed import ReadableBuffer, Self +from typing import IO, Any, BinaryIO, NamedTuple, NoReturn, overload +from typing_extensions import Literal -_File = Union[str, IO[bytes]] +if sys.version_info >= (3, 9): + __all__ = ["open", "Error", "Wave_read", "Wave_write"] +else: + __all__ = ["open", "openfp", "Error", "Wave_read", "Wave_write"] + +_File = str | IO[bytes] class Error(Exception): ... -WAVE_FORMAT_PCM: int +WAVE_FORMAT_PCM: Literal[1] class _wave_params(NamedTuple): nchannels: int @@ -19,7 +25,7 @@ class _wave_params(NamedTuple): class Wave_read: def __init__(self, f: _File) -> None: ... def __enter__(self: Self) -> Self: ... - def __exit__(self, *args: Any) -> None: ... + def __exit__(self, *args: object) -> None: ... def getfp(self) -> BinaryIO | None: ... def rewind(self) -> None: ... def close(self) -> None: ... @@ -39,7 +45,7 @@ class Wave_read: class Wave_write: def __init__(self, f: _File) -> None: ... def __enter__(self: Self) -> Self: ... - def __exit__(self, *args: Any) -> None: ... + def __exit__(self, *args: object) -> None: ... def setnchannels(self, nchannels: int) -> None: ... def getnchannels(self) -> int: ... def setsampwidth(self, sampwidth: int) -> None: ... @@ -57,12 +63,15 @@ class Wave_write: def getmark(self, id: Any) -> NoReturn: ... def getmarkers(self) -> None: ... def tell(self) -> int: ... - # should be any bytes-like object after 3.4, but we don't have a type for that - def writeframesraw(self, data: bytes) -> None: ... - def writeframes(self, data: bytes) -> None: ... + def writeframesraw(self, data: ReadableBuffer) -> None: ... + def writeframes(self, data: ReadableBuffer) -> None: ... def close(self) -> None: ... -# Returns a Wave_read if mode is rb and Wave_write if mode is wb +@overload +def open(f: _File, mode: Literal["r", "rb"]) -> Wave_read: ... +@overload +def open(f: _File, mode: Literal["w", "wb"]) -> Wave_write: ... +@overload def open(f: _File, mode: str | None = ...) -> Any: ... if sys.version_info < (3, 9): diff --git a/mypy/typeshed/stdlib/weakref.pyi b/mypy/typeshed/stdlib/weakref.pyi index fd1cad7fe8407..8204885291436 100644 --- a/mypy/typeshed/stdlib/weakref.pyi +++ b/mypy/typeshed/stdlib/weakref.pyi @@ -1,5 +1,8 @@ +import sys +from _typeshed import Self, SupportsKeysAndGetItem from _weakrefset import WeakSet as WeakSet -from typing import Any, Callable, Generic, Iterable, Iterator, Mapping, MutableMapping, Type, TypeVar, overload +from typing import Any, Callable, Generic, Iterable, Iterator, Mapping, MutableMapping, TypeVar, overload +from typing_extensions import ParamSpec from _weakref import ( CallableProxyType as CallableProxyType, @@ -11,31 +14,56 @@ from _weakref import ( ref as ref, ) -_S = TypeVar("_S") +__all__ = [ + "ref", + "proxy", + "getweakrefcount", + "getweakrefs", + "WeakKeyDictionary", + "ReferenceType", + "ProxyType", + "CallableProxyType", + "ProxyTypes", + "WeakValueDictionary", + "WeakSet", + "WeakMethod", + "finalize", +] + _T = TypeVar("_T") +_T1 = TypeVar("_T1") +_T2 = TypeVar("_T2") _KT = TypeVar("_KT") _VT = TypeVar("_VT") _CallableT = TypeVar("_CallableT", bound=Callable[..., Any]) +_P = ParamSpec("_P") -ProxyTypes: tuple[Type[Any], ...] +ProxyTypes: tuple[type[Any], ...] class WeakMethod(ref[_CallableT], Generic[_CallableT]): - def __new__(cls, meth: _CallableT, callback: Callable[[_CallableT], object] | None = ...) -> WeakMethod[_CallableT]: ... + def __new__(cls: type[Self], meth: _CallableT, callback: Callable[[_CallableT], object] | None = ...) -> Self: ... def __call__(self) -> _CallableT | None: ... + def __eq__(self, other: object) -> bool: ... + def __ne__(self, other: object) -> bool: ... class WeakValueDictionary(MutableMapping[_KT, _VT]): @overload def __init__(self) -> None: ... @overload - def __init__(self, __other: Mapping[_KT, _VT] | Iterable[tuple[_KT, _VT]], **kwargs: _VT) -> None: ... + def __init__(self: WeakValueDictionary[_KT, _VT], __other: Mapping[_KT, _VT] | Iterable[tuple[_KT, _VT]]) -> None: ... + @overload + def __init__( + self: WeakValueDictionary[str, _VT], __other: Mapping[str, _VT] | Iterable[tuple[str, _VT]] = ..., **kwargs: _VT + ) -> None: ... def __len__(self) -> int: ... - def __getitem__(self, k: _KT) -> _VT: ... - def __setitem__(self, k: _KT, v: _VT) -> None: ... - def __delitem__(self, v: _KT) -> None: ... - def __contains__(self, o: object) -> bool: ... + def __getitem__(self, key: _KT) -> _VT: ... + def __setitem__(self, key: _KT, value: _VT) -> None: ... + def __delitem__(self, key: _KT) -> None: ... + def __contains__(self, key: object) -> bool: ... def __iter__(self) -> Iterator[_KT]: ... - def __str__(self) -> str: ... def copy(self) -> WeakValueDictionary[_KT, _VT]: ... + __copy__ = copy + def __deepcopy__(self: Self, memo: Any) -> Self: ... # These are incompatible with Mapping def keys(self) -> Iterator[_KT]: ... # type: ignore[override] def values(self) -> Iterator[_VT]: ... # type: ignore[override] @@ -47,11 +75,19 @@ class WeakValueDictionary(MutableMapping[_KT, _VT]): def pop(self, key: _KT) -> _VT: ... @overload def pop(self, key: _KT, default: _VT | _T = ...) -> _VT | _T: ... + if sys.version_info >= (3, 9): + def __or__(self, other: Mapping[_T1, _T2]) -> WeakValueDictionary[_KT | _T1, _VT | _T2]: ... + def __ror__(self, other: Mapping[_T1, _T2]) -> WeakValueDictionary[_KT | _T1, _VT | _T2]: ... + # WeakValueDictionary.__ior__ should be kept roughly in line with MutableMapping.update() + @overload # type: ignore[misc] + def __ior__(self: Self, other: SupportsKeysAndGetItem[_KT, _VT]) -> Self: ... + @overload + def __ior__(self: Self, other: Iterable[tuple[_KT, _VT]]) -> Self: ... class KeyedRef(ref[_T], Generic[_KT, _T]): key: _KT # This __new__ method uses a non-standard name for the "cls" parameter - def __new__(type, ob: _T, callback: Callable[[_T], Any], key: _KT) -> KeyedRef[_KT, _T]: ... # type: ignore + def __new__(type: type[Self], ob: _T, callback: Callable[[_T], Any], key: _KT) -> Self: ... # type: ignore def __init__(self, ob: _T, callback: Callable[[_T], Any], key: _KT) -> None: ... class WeakKeyDictionary(MutableMapping[_KT, _VT]): @@ -60,13 +96,14 @@ class WeakKeyDictionary(MutableMapping[_KT, _VT]): @overload def __init__(self, dict: Mapping[_KT, _VT] | Iterable[tuple[_KT, _VT]]) -> None: ... def __len__(self) -> int: ... - def __getitem__(self, k: _KT) -> _VT: ... - def __setitem__(self, k: _KT, v: _VT) -> None: ... - def __delitem__(self, v: _KT) -> None: ... - def __contains__(self, o: object) -> bool: ... + def __getitem__(self, key: _KT) -> _VT: ... + def __setitem__(self, key: _KT, value: _VT) -> None: ... + def __delitem__(self, key: _KT) -> None: ... + def __contains__(self, key: object) -> bool: ... def __iter__(self) -> Iterator[_KT]: ... - def __str__(self) -> str: ... def copy(self) -> WeakKeyDictionary[_KT, _VT]: ... + __copy__ = copy + def __deepcopy__(self: Self, memo: Any) -> Self: ... # These are incompatible with Mapping def keys(self) -> Iterator[_KT]: ... # type: ignore[override] def values(self) -> Iterator[_VT]: ... # type: ignore[override] @@ -77,11 +114,20 @@ class WeakKeyDictionary(MutableMapping[_KT, _VT]): def pop(self, key: _KT) -> _VT: ... @overload def pop(self, key: _KT, default: _VT | _T = ...) -> _VT | _T: ... + if sys.version_info >= (3, 9): + def __or__(self, other: Mapping[_T1, _T2]) -> WeakKeyDictionary[_KT | _T1, _VT | _T2]: ... + def __ror__(self, other: Mapping[_T1, _T2]) -> WeakKeyDictionary[_KT | _T1, _VT | _T2]: ... + # WeakKeyDictionary.__ior__ should be kept roughly in line with MutableMapping.update() + @overload # type: ignore[misc] + def __ior__(self: Self, other: SupportsKeysAndGetItem[_KT, _VT]) -> Self: ... + @overload + def __ior__(self: Self, other: Iterable[tuple[_KT, _VT]]) -> Self: ... -class finalize: - def __init__(self, __obj: object, __func: Callable[..., Any], *args: Any, **kwargs: Any) -> None: ... +class finalize: # TODO: This is a good candidate for to be a `Generic[_P, _T]` class + def __init__(self, __obj: object, __func: Callable[_P, Any], *args: _P.args, **kwargs: _P.kwargs) -> None: ... def __call__(self, _: Any = ...) -> Any | None: ... def detach(self) -> tuple[Any, Any, tuple[Any, ...], dict[str, Any]] | None: ... def peek(self) -> tuple[Any, Any, tuple[Any, ...], dict[str, Any]] | None: ... - alive: bool + @property + def alive(self) -> bool: ... atexit: bool diff --git a/mypy/typeshed/stdlib/webbrowser.pyi b/mypy/typeshed/stdlib/webbrowser.pyi index 459d886ac9306..ce8fca262d2d4 100644 --- a/mypy/typeshed/stdlib/webbrowser.pyi +++ b/mypy/typeshed/stdlib/webbrowser.pyi @@ -1,5 +1,9 @@ import sys +from abc import abstractmethod from typing import Callable, Sequence +from typing_extensions import Literal + +__all__ = ["Error", "open", "open_new", "open_new_tab", "get", "register"] class Error(Exception): ... @@ -23,16 +27,19 @@ class BaseBrowser: name: str basename: str def __init__(self, name: str = ...) -> None: ... + @abstractmethod def open(self, url: str, new: int = ..., autoraise: bool = ...) -> bool: ... def open_new(self, url: str) -> bool: ... def open_new_tab(self, url: str) -> bool: ... class GenericBrowser(BaseBrowser): def __init__(self, name: str | Sequence[str]) -> None: ... + def open(self, url: str, new: int = ..., autoraise: bool = ...) -> bool: ... class BackgroundBrowser(GenericBrowser): ... class UnixBrowser(BaseBrowser): + def open(self, url: str, new: Literal[0, 1, 2] = ..., autoraise: bool = ...) -> bool: ... # type: ignore[override] raise_opts: list[str] | None background: bool redirect_stdout: bool @@ -49,12 +56,20 @@ class Galeon(UnixBrowser): class Chrome(UnixBrowser): ... class Opera(UnixBrowser): ... class Elinks(UnixBrowser): ... -class Konqueror(BaseBrowser): ... -class Grail(BaseBrowser): ... + +class Konqueror(BaseBrowser): + def open(self, url: str, new: int = ..., autoraise: bool = ...) -> bool: ... + +class Grail(BaseBrowser): + def open(self, url: str, new: int = ..., autoraise: bool = ...) -> bool: ... if sys.platform == "win32": - class WindowsDefault(BaseBrowser): ... + class WindowsDefault(BaseBrowser): + def open(self, url: str, new: int = ..., autoraise: bool = ...) -> bool: ... if sys.platform == "darwin": - class MacOSX(BaseBrowser): ... - class MacOSXOSAScript(BaseBrowser): ... # In runtime this class does not have `name` and `basename` + class MacOSX(BaseBrowser): + def open(self, url: str, new: int = ..., autoraise: bool = ...) -> bool: ... + + class MacOSXOSAScript(BaseBrowser): # In runtime this class does not have `name` and `basename` + def open(self, url: str, new: int = ..., autoraise: bool = ...) -> bool: ... diff --git a/mypy/typeshed/stdlib/winreg.pyi b/mypy/typeshed/stdlib/winreg.pyi index 57f0c4b3ddba5..5dc7e4363d6f2 100644 --- a/mypy/typeshed/stdlib/winreg.pyi +++ b/mypy/typeshed/stdlib/winreg.pyi @@ -1,11 +1,11 @@ import sys from _typeshed import Self from types import TracebackType -from typing import Any, Type, Union +from typing import Any from typing_extensions import Literal, final if sys.platform == "win32": - _KeyType = Union[HKEYType, int] + _KeyType = HKEYType | int def CloseKey(__hkey: _KeyType) -> None: ... def ConnectRegistry(__computer_name: str | None, __key: _KeyType) -> HKEYType: ... def CreateKey(__key: _KeyType, __sub_key: str | None) -> HKEYType: ... @@ -95,7 +95,7 @@ if sys.platform == "win32": def __int__(self) -> int: ... def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_value: BaseException | None, traceback: TracebackType | None ) -> bool | None: ... def Close(self) -> None: ... def Detach(self) -> int: ... diff --git a/mypy/typeshed/stdlib/winsound.pyi b/mypy/typeshed/stdlib/winsound.pyi index 3d79f3b043f27..588bd5969e98d 100644 --- a/mypy/typeshed/stdlib/winsound.pyi +++ b/mypy/typeshed/stdlib/winsound.pyi @@ -3,21 +3,21 @@ from typing import overload from typing_extensions import Literal if sys.platform == "win32": - SND_FILENAME: int - SND_ALIAS: int - SND_LOOP: int - SND_MEMORY: int - SND_PURGE: int - SND_ASYNC: int - SND_NODEFAULT: int - SND_NOSTOP: int - SND_NOWAIT: int + SND_FILENAME: Literal[131072] + SND_ALIAS: Literal[65536] + SND_LOOP: Literal[8] + SND_MEMORY: Literal[4] + SND_PURGE: Literal[64] + SND_ASYNC: Literal[1] + SND_NODEFAULT: Literal[2] + SND_NOSTOP: Literal[16] + SND_NOWAIT: Literal[8192] - MB_ICONASTERISK: int - MB_ICONEXCLAMATION: int - MB_ICONHAND: int - MB_ICONQUESTION: int - MB_OK: int + MB_ICONASTERISK: Literal[64] + MB_ICONEXCLAMATION: Literal[48] + MB_ICONHAND: Literal[16] + MB_ICONQUESTION: Literal[32] + MB_OK: Literal[0] def Beep(frequency: int, duration: int) -> None: ... # Can actually accept anything ORed with 4, and if not it's definitely str, but that's inexpressible @overload diff --git a/mypy/typeshed/stdlib/wsgiref/handlers.pyi b/mypy/typeshed/stdlib/wsgiref/handlers.pyi index eccc0d1647678..9e2153788cacc 100644 --- a/mypy/typeshed/stdlib/wsgiref/handlers.pyi +++ b/mypy/typeshed/stdlib/wsgiref/handlers.pyi @@ -1,12 +1,14 @@ from abc import abstractmethod from types import TracebackType -from typing import IO, Callable, MutableMapping, Optional, Type +from typing import IO, Callable, MutableMapping from .headers import Headers from .types import ErrorStream, InputStream, StartResponse, WSGIApplication, WSGIEnvironment from .util import FileWrapper -_exc_info = tuple[Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType]] +__all__ = ["BaseHandler", "SimpleHandler", "BaseCGIHandler", "CGIHandler", "IISCGIHandler", "read_environ"] + +_exc_info = tuple[type[BaseException] | None, BaseException | None, TracebackType | None] def format_date_time(timestamp: float | None) -> str: ... # undocumented def read_environ() -> dict[str, str]: ... @@ -23,8 +25,8 @@ class BaseHandler: os_environ: MutableMapping[str, str] - wsgi_file_wrapper: Type[FileWrapper] | None - headers_class: Type[Headers] # undocumented + wsgi_file_wrapper: type[FileWrapper] | None + headers_class: type[Headers] # undocumented traceback_limit: int | None error_status: str diff --git a/mypy/typeshed/stdlib/wsgiref/simple_server.pyi b/mypy/typeshed/stdlib/wsgiref/simple_server.pyi index 76d0b269793d7..389d30c22db26 100644 --- a/mypy/typeshed/stdlib/wsgiref/simple_server.pyi +++ b/mypy/typeshed/stdlib/wsgiref/simple_server.pyi @@ -1,9 +1,11 @@ from http.server import BaseHTTPRequestHandler, HTTPServer -from typing import Type, TypeVar, overload +from typing import TypeVar, overload from .handlers import SimpleHandler from .types import ErrorStream, StartResponse, WSGIApplication, WSGIEnvironment +__all__ = ["WSGIServer", "WSGIRequestHandler", "demo_app", "make_server"] + server_version: str # undocumented sys_version: str # undocumented software_version: str # undocumented @@ -30,8 +32,8 @@ def demo_app(environ: WSGIEnvironment, start_response: StartResponse) -> list[by _S = TypeVar("_S", bound=WSGIServer) @overload -def make_server(host: str, port: int, app: WSGIApplication, *, handler_class: Type[WSGIRequestHandler] = ...) -> WSGIServer: ... +def make_server(host: str, port: int, app: WSGIApplication, *, handler_class: type[WSGIRequestHandler] = ...) -> WSGIServer: ... @overload def make_server( - host: str, port: int, app: WSGIApplication, server_class: Type[_S], handler_class: Type[WSGIRequestHandler] = ... + host: str, port: int, app: WSGIApplication, server_class: type[_S], handler_class: type[WSGIRequestHandler] = ... ) -> _S: ... diff --git a/mypy/typeshed/stdlib/wsgiref/util.pyi b/mypy/typeshed/stdlib/wsgiref/util.pyi index c769c77d36e9e..f2c3135df786e 100644 --- a/mypy/typeshed/stdlib/wsgiref/util.pyi +++ b/mypy/typeshed/stdlib/wsgiref/util.pyi @@ -3,6 +3,8 @@ from typing import IO, Any, Callable from .types import WSGIEnvironment +__all__ = ["FileWrapper", "guess_scheme", "application_uri", "request_uri", "shift_path_info", "setup_testing_defaults"] + class FileWrapper: filelike: IO[bytes] blksize: int @@ -10,6 +12,7 @@ class FileWrapper: def __init__(self, filelike: IO[bytes], blksize: int = ...) -> None: ... if sys.version_info < (3, 11): def __getitem__(self, key: Any) -> bytes: ... + def __iter__(self) -> FileWrapper: ... def __next__(self) -> bytes: ... diff --git a/mypy/typeshed/stdlib/wsgiref/validate.pyi b/mypy/typeshed/stdlib/wsgiref/validate.pyi index 68e22727bc732..35491756c2884 100644 --- a/mypy/typeshed/stdlib/wsgiref/validate.pyi +++ b/mypy/typeshed/stdlib/wsgiref/validate.pyi @@ -1,6 +1,8 @@ from _typeshed.wsgi import ErrorStream, InputStream, WSGIApplication from typing import Any, Callable, Iterable, Iterator, NoReturn +__all__ = ["validator"] + class WSGIWarning(Warning): ... def validator(application: WSGIApplication) -> WSGIApplication: ... diff --git a/mypy/typeshed/stdlib/xdrlib.pyi b/mypy/typeshed/stdlib/xdrlib.pyi index f59843f8ee9d9..e9716e29014d3 100644 --- a/mypy/typeshed/stdlib/xdrlib.pyi +++ b/mypy/typeshed/stdlib/xdrlib.pyi @@ -1,5 +1,7 @@ from typing import Callable, Sequence, TypeVar +__all__ = ["Error", "Packer", "Unpacker", "ConversionError"] + _T = TypeVar("_T") class Error(Exception): diff --git a/mypy/typeshed/stdlib/xml/dom/minicompat.pyi b/mypy/typeshed/stdlib/xml/dom/minicompat.pyi index 38e6d05e4743e..411401d11ccd4 100644 --- a/mypy/typeshed/stdlib/xml/dom/minicompat.pyi +++ b/mypy/typeshed/stdlib/xml/dom/minicompat.pyi @@ -1,8 +1,10 @@ -from typing import Any, Iterable, Type, TypeVar +from typing import Any, Iterable, TypeVar + +__all__ = ["NodeList", "EmptyNodeList", "StringTypes", "defproperty"] _T = TypeVar("_T") -StringTypes: tuple[Type[str]] +StringTypes: tuple[type[str]] class NodeList(list[_T]): length: int @@ -14,4 +16,4 @@ class EmptyNodeList(tuple[Any, ...]): def __add__(self, other: Iterable[_T]) -> NodeList[_T]: ... # type: ignore[override] def __radd__(self, other: Iterable[_T]) -> NodeList[_T]: ... -def defproperty(klass: Type[Any], name: str, doc: str) -> None: ... +def defproperty(klass: type[Any], name: str, doc: str) -> None: ... diff --git a/mypy/typeshed/stdlib/xml/dom/minidom.pyi b/mypy/typeshed/stdlib/xml/dom/minidom.pyi index e9a26e30d7219..d8bcc299b9918 100644 --- a/mypy/typeshed/stdlib/xml/dom/minidom.pyi +++ b/mypy/typeshed/stdlib/xml/dom/minidom.pyi @@ -1,11 +1,11 @@ import sys import xml.dom -from _typeshed import Self -from typing import IO, Any +from _typeshed import Self, SupportsRead +from typing import Any from xml.dom.xmlbuilder import DocumentLS, DOMImplementationLS from xml.sax.xmlreader import XMLReader -def parse(file: str | IO[Any], parser: XMLReader | None = ..., bufsize: int | None = ...): ... +def parse(file: str | SupportsRead[bytes] | SupportsRead[str], parser: XMLReader | None = ..., bufsize: int | None = ...): ... def parseString(string: str | bytes, parser: XMLReader | None = ...): ... def getDOMImplementation(features=...) -> DOMImplementation | None: ... @@ -22,12 +22,14 @@ class Node(xml.dom.Node): def lastChild(self) -> Node | None: ... @property def localName(self) -> str | None: ... + def __bool__(self) -> bool: ... if sys.version_info >= (3, 9): def toxml(self, encoding: Any | None = ..., standalone: Any | None = ...): ... def toprettyxml(self, indent: str = ..., newl: str = ..., encoding: Any | None = ..., standalone: Any | None = ...): ... else: def toxml(self, encoding: Any | None = ...): ... def toprettyxml(self, indent: str = ..., newl: str = ..., encoding: Any | None = ...): ... + def hasChildNodes(self) -> bool: ... def insertBefore(self, newChild, refChild): ... def appendChild(self, node): ... @@ -86,7 +88,7 @@ class NamedNodeMap: def values(self): ... def get(self, name, value: Any | None = ...): ... def __len__(self) -> int: ... - def __eq__(self, other: Any) -> bool: ... + def __eq__(self, other: object) -> bool: ... def __ge__(self, other: Any) -> bool: ... def __gt__(self, other: Any) -> bool: ... def __le__(self, other: Any) -> bool: ... @@ -329,4 +331,5 @@ class Document(Node, DocumentLS): def writexml( self, writer, indent: str = ..., addindent: str = ..., newl: str = ..., encoding: Any | None = ... ) -> None: ... + def renameNode(self, n, namespaceURI: str, name): ... diff --git a/mypy/typeshed/stdlib/xml/dom/pulldom.pyi b/mypy/typeshed/stdlib/xml/dom/pulldom.pyi index c2b7aa0772fa1..b2bec64fd1dc5 100644 --- a/mypy/typeshed/stdlib/xml/dom/pulldom.pyi +++ b/mypy/typeshed/stdlib/xml/dom/pulldom.pyi @@ -1,5 +1,6 @@ import sys -from typing import IO, Any, Sequence, Union +from _typeshed import SupportsRead +from typing import Any, Sequence from typing_extensions import Literal from xml.dom.minidom import Document, DOMImplementation, Element, Text from xml.sax.handler import ContentHandler @@ -14,8 +15,8 @@ PROCESSING_INSTRUCTION: Literal["PROCESSING_INSTRUCTION"] IGNORABLE_WHITESPACE: Literal["IGNORABLE_WHITESPACE"] CHARACTERS: Literal["CHARACTERS"] -_DocumentFactory = Union[DOMImplementation, None] -_Node = Union[Document, Element, Text] +_DocumentFactory = DOMImplementation | None +_Node = Document | Element | Text _Event = tuple[ Literal[ @@ -62,13 +63,14 @@ class ErrorHandler: def fatalError(self, exception) -> None: ... class DOMEventStream: - stream: IO[bytes] + stream: SupportsRead[bytes] | SupportsRead[str] parser: XMLReader bufsize: int - def __init__(self, stream: IO[bytes], parser: XMLReader, bufsize: int) -> None: ... + def __init__(self, stream: SupportsRead[bytes] | SupportsRead[str], parser: XMLReader, bufsize: int) -> None: ... pulldom: Any if sys.version_info < (3, 11): def __getitem__(self, pos): ... + def __next__(self): ... def __iter__(self): ... def getEvent(self) -> _Event: ... @@ -85,5 +87,7 @@ class SAX2DOM(PullDOM): default_bufsize: int -def parse(stream_or_string: str | IO[bytes], parser: XMLReader | None = ..., bufsize: int | None = ...) -> DOMEventStream: ... +def parse( + stream_or_string: str | SupportsRead[bytes] | SupportsRead[str], parser: XMLReader | None = ..., bufsize: int | None = ... +) -> DOMEventStream: ... def parseString(string: str, parser: XMLReader | None = ...) -> DOMEventStream: ... diff --git a/mypy/typeshed/stdlib/xml/dom/xmlbuilder.pyi b/mypy/typeshed/stdlib/xml/dom/xmlbuilder.pyi index 2738d735e73f5..ec47ec134e085 100644 --- a/mypy/typeshed/stdlib/xml/dom/xmlbuilder.pyi +++ b/mypy/typeshed/stdlib/xml/dom/xmlbuilder.pyi @@ -1,9 +1,11 @@ -from typing import Any, NoReturn, Optional +from typing import Any, NoReturn from typing_extensions import Literal from urllib.request import OpenerDirector from xml.dom.expatbuilder import ExpatBuilder, ExpatBuilderNS from xml.dom.minidom import Node +__all__ = ["DOMBuilder", "DOMEntityResolver", "DOMInputSource"] + # UNKNOWN TYPES: # - `Options.errorHandler`. # The same as `_DOMBuilderErrorHandlerType`? @@ -16,13 +18,13 @@ from xml.dom.minidom import Node # probably the same as `Options.errorHandler`? # Maybe `xml.sax.handler.ErrorHandler`? -_DOMBuilderErrorHandlerType = Optional[Any] +_DOMBuilderErrorHandlerType = Any | None # probably some kind of IO... -_DOMInputSourceCharacterStreamType = Optional[Any] +_DOMInputSourceCharacterStreamType = Any | None # probably a string?? -_DOMInputSourceStringDataType = Optional[Any] +_DOMInputSourceStringDataType = Any | None # probably a string?? -_DOMInputSourceEncodingType = Optional[Any] +_DOMInputSourceEncodingType = Any | None class Options: namespaces: int diff --git a/mypy/typeshed/stdlib/xml/etree/ElementInclude.pyi b/mypy/typeshed/stdlib/xml/etree/ElementInclude.pyi index b355bef1208c3..5cd85cc217535 100644 --- a/mypy/typeshed/stdlib/xml/etree/ElementInclude.pyi +++ b/mypy/typeshed/stdlib/xml/etree/ElementInclude.pyi @@ -20,6 +20,7 @@ if sys.version_info >= (3, 9): def include( elem: Element, loader: Callable[..., str | Element] | None = ..., base_url: str | None = ..., max_depth: int | None = ... ) -> None: ... + class LimitedRecursiveIncludeError(FatalIncludeError): ... else: diff --git a/mypy/typeshed/stdlib/xml/etree/ElementTree.pyi b/mypy/typeshed/stdlib/xml/etree/ElementTree.pyi index c4236cf292bb6..7b50b42790216 100644 --- a/mypy/typeshed/stdlib/xml/etree/ElementTree.pyi +++ b/mypy/typeshed/stdlib/xml/etree/ElementTree.pyi @@ -1,7 +1,6 @@ import sys -from _typeshed import FileDescriptor, StrOrBytesPath, SupportsWrite +from _typeshed import FileDescriptor, StrOrBytesPath, SupportsRead, SupportsWrite from typing import ( - IO, Any, Callable, Generator, @@ -13,13 +12,98 @@ from typing import ( MutableSequence, Sequence, TypeVar, - Union, overload, ) -from typing_extensions import Literal, SupportsIndex +from typing_extensions import Literal, SupportsIndex, TypeGuard + +if sys.version_info >= (3, 9): + __all__ = [ + "Comment", + "dump", + "Element", + "ElementTree", + "fromstring", + "fromstringlist", + "indent", + "iselement", + "iterparse", + "parse", + "ParseError", + "PI", + "ProcessingInstruction", + "QName", + "SubElement", + "tostring", + "tostringlist", + "TreeBuilder", + "VERSION", + "XML", + "XMLID", + "XMLParser", + "XMLPullParser", + "register_namespace", + "canonicalize", + "C14NWriterTarget", + ] +elif sys.version_info >= (3, 8): + __all__ = [ + "Comment", + "dump", + "Element", + "ElementTree", + "fromstring", + "fromstringlist", + "iselement", + "iterparse", + "parse", + "ParseError", + "PI", + "ProcessingInstruction", + "QName", + "SubElement", + "tostring", + "tostringlist", + "TreeBuilder", + "VERSION", + "XML", + "XMLID", + "XMLParser", + "XMLPullParser", + "register_namespace", + "canonicalize", + "C14NWriterTarget", + ] +else: + __all__ = [ + "Comment", + "dump", + "Element", + "ElementTree", + "fromstring", + "fromstringlist", + "iselement", + "iterparse", + "parse", + "ParseError", + "PI", + "ProcessingInstruction", + "QName", + "SubElement", + "tostring", + "tostringlist", + "TreeBuilder", + "VERSION", + "XML", + "XMLID", + "XMLParser", + "XMLPullParser", + "register_namespace", + ] _T = TypeVar("_T") -_File = Union[StrOrBytesPath, FileDescriptor, IO[Any]] +_FileRead = StrOrBytesPath | FileDescriptor | SupportsRead[bytes] | SupportsRead[str] +_FileWriteC14N = StrOrBytesPath | FileDescriptor | SupportsWrite[bytes] +_FileWrite = _FileWriteC14N | SupportsWrite[str] VERSION: str @@ -27,7 +111,8 @@ class ParseError(SyntaxError): code: int position: tuple[int, int] -def iselement(element: object) -> bool: ... +# In reality it works based on `.tag` attribute duck typing. +def iselement(element: object) -> TypeGuard[Element]: ... if sys.version_info >= (3, 8): @overload @@ -35,7 +120,7 @@ if sys.version_info >= (3, 8): xml_data: str | bytes | None = ..., *, out: None = ..., - from_file: _File | None = ..., + from_file: _FileRead | None = ..., with_comments: bool = ..., strip_text: bool = ..., rewrite_prefixes: bool = ..., @@ -49,7 +134,7 @@ if sys.version_info >= (3, 8): xml_data: str | bytes | None = ..., *, out: SupportsWrite[str], - from_file: _File | None = ..., + from_file: _FileRead | None = ..., with_comments: bool = ..., strip_text: bool = ..., rewrite_prefixes: bool = ..., @@ -84,19 +169,22 @@ class Element(MutableSequence[Element]): def iterfind(self, path: str, namespaces: dict[str, str] | None = ...) -> Generator[Element, None, None]: ... def itertext(self) -> Generator[str, None, None]: ... def keys(self) -> KeysView[str]: ... + # makeelement returns the type of self in Python impl, but not in C impl def makeelement(self, __tag: str, __attrib: dict[str, str]) -> Element: ... def remove(self, __subelement: Element) -> None: ... def set(self, __key: str, __value: str) -> None: ... - def __delitem__(self, i: SupportsIndex | slice) -> None: ... + def __copy__(self) -> Element: ... # returns the type of self in Python impl, but not in C impl + def __deepcopy__(self, __memo: Any) -> Element: ... # Only exists in C impl + def __delitem__(self, __i: SupportsIndex | slice) -> None: ... @overload - def __getitem__(self, i: SupportsIndex) -> Element: ... + def __getitem__(self, __i: SupportsIndex) -> Element: ... @overload - def __getitem__(self, s: slice) -> MutableSequence[Element]: ... + def __getitem__(self, __s: slice) -> MutableSequence[Element]: ... def __len__(self) -> int: ... @overload - def __setitem__(self, i: SupportsIndex, o: Element) -> None: ... + def __setitem__(self, __i: SupportsIndex, __o: Element) -> None: ... @overload - def __setitem__(self, s: slice, o: Iterable[Element]) -> None: ... + def __setitem__(self, __s: slice, __o: Iterable[Element]) -> None: ... if sys.version_info < (3, 9): def getchildren(self) -> list[Element]: ... def getiterator(self, tag: str | None = ...) -> list[Element]: ... @@ -110,14 +198,20 @@ PI: Callable[..., Element] class QName: text: str def __init__(self, text_or_uri: str, tag: str | None = ...) -> None: ... + def __lt__(self, other: QName | str) -> bool: ... + def __le__(self, other: QName | str) -> bool: ... + def __gt__(self, other: QName | str) -> bool: ... + def __ge__(self, other: QName | str) -> bool: ... + def __eq__(self, other: object) -> bool: ... class ElementTree: - def __init__(self, element: Element | None = ..., file: _File | None = ...) -> None: ... + def __init__(self, element: Element | None = ..., file: _FileRead | None = ...) -> None: ... def getroot(self) -> Element: ... - def parse(self, source: _File, parser: XMLParser | None = ...) -> Element: ... + def parse(self, source: _FileRead, parser: XMLParser | None = ...) -> Element: ... def iter(self, tag: str | None = ...) -> Generator[Element, None, None]: ... if sys.version_info < (3, 9): def getiterator(self, tag: str | None = ...) -> list[Element]: ... + def find(self, path: str, namespaces: dict[str, str] | None = ...) -> Element | None: ... @overload def findtext(self, path: str, default: None = ..., namespaces: dict[str, str] | None = ...) -> str | None: ... @@ -127,7 +221,7 @@ class ElementTree: def iterfind(self, path: str, namespaces: dict[str, str] | None = ...) -> Generator[Element, None, None]: ... def write( self, - file_or_filename: _File, + file_or_filename: _FileWrite, encoding: str | None = ..., xml_declaration: bool | None = ..., default_namespace: str | None = ..., @@ -135,7 +229,7 @@ class ElementTree: *, short_empty_elements: bool = ..., ) -> None: ... - def write_c14n(self, file: _File) -> None: ... + def write_c14n(self, file: _FileWriteC14N) -> None: ... def register_namespace(prefix: str, uri: str) -> None: ... @@ -230,8 +324,10 @@ def dump(elem: Element) -> None: ... if sys.version_info >= (3, 9): def indent(tree: Element | ElementTree, space: str = ..., level: int = ...) -> None: ... -def parse(source: _File, parser: XMLParser | None = ...) -> ElementTree: ... -def iterparse(source: _File, events: Sequence[str] | None = ..., parser: XMLParser | None = ...) -> Iterator[tuple[str, Any]]: ... +def parse(source: _FileRead, parser: XMLParser | None = ...) -> ElementTree: ... +def iterparse( + source: _FileRead, events: Sequence[str] | None = ..., parser: XMLParser | None = ... +) -> Iterator[tuple[str, Any]]: ... class XMLPullParser: def __init__(self, events: Sequence[str] | None = ..., *, _parser: XMLParser | None = ...) -> None: ... @@ -274,6 +370,7 @@ class TreeBuilder: insert_pis: bool else: def __init__(self, element_factory: _ElementFactory | None = ...) -> None: ... + def close(self) -> Element: ... def data(self, __data: str | bytes) -> None: ... def start(self, __tag: str | bytes, __attrs: dict[str | bytes, str | bytes]) -> Element: ... @@ -315,5 +412,6 @@ class XMLParser: else: def __init__(self, html: int = ..., target: Any = ..., encoding: str | None = ...) -> None: ... def doctype(self, __name: str, __pubid: str, __system: str) -> None: ... + def close(self) -> Any: ... def feed(self, __data: str | bytes) -> None: ... diff --git a/mypy/typeshed/stdlib/xml/etree/cElementTree.pyi b/mypy/typeshed/stdlib/xml/etree/cElementTree.pyi index c41e2bee0eb15..02272d803c185 100644 --- a/mypy/typeshed/stdlib/xml/etree/cElementTree.pyi +++ b/mypy/typeshed/stdlib/xml/etree/cElementTree.pyi @@ -1 +1 @@ -from xml.etree.ElementTree import * # noqa: F403 +from xml.etree.ElementTree import * diff --git a/mypy/typeshed/stdlib/xml/sax/__init__.pyi b/mypy/typeshed/stdlib/xml/sax/__init__.pyi index a123e7e894e2b..418164aa887f7 100644 --- a/mypy/typeshed/stdlib/xml/sax/__init__.pyi +++ b/mypy/typeshed/stdlib/xml/sax/__init__.pyi @@ -1,8 +1,12 @@ import sys -from typing import IO, Any, Iterable, NoReturn +from _typeshed import SupportsRead, _T_co +from typing import Any, Iterable, NoReturn, Protocol from xml.sax.handler import ContentHandler, ErrorHandler from xml.sax.xmlreader import Locator, XMLReader +class _SupportsReadClose(SupportsRead[_T_co], Protocol[_T_co]): + def close(self) -> None: ... + class SAXException(Exception): def __init__(self, msg: str, exception: Exception | None = ...) -> None: ... def getMessage(self) -> str: ... @@ -28,6 +32,8 @@ if sys.version_info >= (3, 8): else: def make_parser(parser_list: list[str] = ...) -> XMLReader: ... -def parse(source: str | IO[str] | IO[bytes], handler: ContentHandler, errorHandler: ErrorHandler = ...) -> None: ... +def parse( + source: str | _SupportsReadClose[bytes] | _SupportsReadClose[str], handler: ContentHandler, errorHandler: ErrorHandler = ... +) -> None: ... def parseString(string: bytes | str, handler: ContentHandler, errorHandler: ErrorHandler | None = ...) -> None: ... def _create_parser(parser_name: str) -> XMLReader: ... diff --git a/mypy/typeshed/stdlib/xmlrpc/client.pyi b/mypy/typeshed/stdlib/xmlrpc/client.pyi index e9f9e03ae56db..a59be37f9e812 100644 --- a/mypy/typeshed/stdlib/xmlrpc/client.pyi +++ b/mypy/typeshed/stdlib/xmlrpc/client.pyi @@ -6,15 +6,17 @@ from _typeshed import Self, SupportsRead, SupportsWrite from datetime import datetime from io import BytesIO from types import TracebackType -from typing import Any, Callable, Iterable, Mapping, Protocol, Type, Union, overload +from typing import Any, Callable, Iterable, Mapping, Protocol, Union, overload from typing_extensions import Literal class _SupportsTimeTuple(Protocol): def timetuple(self) -> time.struct_time: ... -_DateTimeComparable = Union[DateTime, datetime, str, _SupportsTimeTuple] -_Marshallable = Union[None, bool, int, float, str, bytes, tuple[Any, ...], list[Any], dict[Any, Any], datetime, DateTime, Binary] -_XMLDate = Union[int, datetime, tuple[int, ...], time.struct_time] +_DateTimeComparable = DateTime | datetime | str | _SupportsTimeTuple +_Marshallable = ( + bool | int | float | str | bytes | None | tuple[Any, ...] | list[Any] | dict[Any, Any] | datetime | DateTime | Binary +) +_XMLDate = int | datetime | tuple[int, ...] | time.struct_time _HostType = Union[tuple[str, dict[str, str]], str] def escape(s: str) -> str: ... # undocumented @@ -83,10 +85,11 @@ class Binary: def __init__(self, data: bytes | None = ...) -> None: ... def decode(self, data: bytes) -> None: ... def encode(self, out: SupportsWrite[str]) -> None: ... + def __eq__(self, other: object) -> bool: ... def _binary(data: bytes) -> Binary: ... # undocumented -WRAPPERS: tuple[Type[DateTime], Type[Binary]] # undocumented +WRAPPERS: tuple[type[DateTime], type[Binary]] # undocumented class ExpatParser: # undocumented def __init__(self, target: Unmarshaller) -> None: ... @@ -96,7 +99,7 @@ class ExpatParser: # undocumented class Marshaller: dispatch: dict[ - Type[Any], Callable[[Marshaller, Any, Callable[[str], Any]], None] + type[Any], Callable[[Marshaller, Any, Callable[[str], Any]], None] ] # TODO: Replace 'Any' with some kind of binding memo: dict[Any, None] @@ -176,7 +179,7 @@ class MultiCall: __server: ServerProxy __call_list: list[tuple[str, tuple[_Marshallable, ...]]] def __init__(self, server: ServerProxy) -> None: ... - def __getattr__(self, item: str) -> _MultiCallMethod: ... + def __getattr__(self, name: str) -> _MultiCallMethod: ... def __call__(self) -> MultiCallIterator: ... # A little white lie @@ -228,6 +231,7 @@ class Transport: ) -> None: ... else: def __init__(self, use_datetime: bool = ..., use_builtin_types: bool = ...) -> None: ... + def request(self, host: _HostType, handler: str, request_body: bytes, verbose: bool = ...) -> tuple[_Marshallable, ...]: ... def single_request( self, host: _HostType, handler: str, request_body: bytes, verbose: bool = ... @@ -254,6 +258,7 @@ class SafeTransport(Transport): ) -> None: ... else: def __init__(self, use_datetime: bool = ..., use_builtin_types: bool = ..., *, context: Any | None = ...) -> None: ... + def make_connection(self, host: _HostType) -> http.client.HTTPSConnection: ... class ServerProxy: @@ -292,6 +297,7 @@ class ServerProxy: *, context: Any | None = ..., ) -> None: ... + def __getattr__(self, name: str) -> _Method: ... @overload def __call__(self, attr: Literal["close"]) -> Callable[[], None]: ... @@ -301,7 +307,7 @@ class ServerProxy: def __call__(self, attr: str) -> Callable[[], None] | Transport: ... def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> None: ... def __close(self) -> None: ... # undocumented def __request(self, methodname: str, params: tuple[_Marshallable, ...]) -> tuple[_Marshallable, ...]: ... # undocumented diff --git a/mypy/typeshed/stdlib/xmlrpc/server.pyi b/mypy/typeshed/stdlib/xmlrpc/server.pyi index 48105d1461f02..2ed0b03c71513 100644 --- a/mypy/typeshed/stdlib/xmlrpc/server.pyi +++ b/mypy/typeshed/stdlib/xmlrpc/server.pyi @@ -3,11 +3,11 @@ import pydoc import socketserver import sys from datetime import datetime -from typing import Any, Callable, Iterable, Mapping, Pattern, Protocol, Type, Union +from typing import Any, Callable, Iterable, Mapping, Pattern, Protocol from xmlrpc.client import Fault # TODO: Recursive type on tuple, list, dict -_Marshallable = Union[None, bool, int, float, str, bytes, tuple[Any, ...], list[Any], dict[Any, Any], datetime] +_Marshallable = None | bool | int | float | str | bytes | tuple[Any, ...] | list[Any] | dict[Any, Any] | datetime # The dispatch accepts anywhere from 0 to N arguments, no easy way to allow this in mypy class _DispatchArity0(Protocol): @@ -30,7 +30,7 @@ class _DispatchArity4(Protocol): class _DispatchArityN(Protocol): def __call__(self, *args: _Marshallable) -> _Marshallable: ... -_DispatchProtocol = Union[_DispatchArity0, _DispatchArity1, _DispatchArity2, _DispatchArity3, _DispatchArity4, _DispatchArityN] +_DispatchProtocol = _DispatchArity0 | _DispatchArity1 | _DispatchArity2 | _DispatchArity3 | _DispatchArity4 | _DispatchArityN def resolve_dotted_attribute(obj: Any, attr: str, allow_dotted_names: bool = ...) -> Any: ... # undocumented def list_public_methods(obj: Any) -> list[str]: ... # undocumented @@ -48,6 +48,7 @@ class SimpleXMLRPCDispatcher: # undocumented def register_function(self, function: _DispatchProtocol | None = ..., name: str | None = ...) -> Callable[..., Any]: ... else: def register_function(self, function: _DispatchProtocol, name: str | None = ...) -> Callable[..., Any]: ... + def register_introspection_functions(self) -> None: ... def register_multicall_functions(self) -> None: ... def _marshaled_dispatch( @@ -81,7 +82,7 @@ class SimpleXMLRPCServer(socketserver.TCPServer, SimpleXMLRPCDispatcher): def __init__( self, addr: tuple[str, int], - requestHandler: Type[SimpleXMLRPCRequestHandler] = ..., + requestHandler: type[SimpleXMLRPCRequestHandler] = ..., logRequests: bool = ..., allow_none: bool = ..., encoding: str | None = ..., @@ -97,7 +98,7 @@ class MultiPathXMLRPCServer(SimpleXMLRPCServer): # undocumented def __init__( self, addr: tuple[str, int], - requestHandler: Type[SimpleXMLRPCRequestHandler] = ..., + requestHandler: type[SimpleXMLRPCRequestHandler] = ..., logRequests: bool = ..., allow_none: bool = ..., encoding: str | None = ..., @@ -150,7 +151,7 @@ class DocXMLRPCServer(SimpleXMLRPCServer, XMLRPCDocGenerator): def __init__( self, addr: tuple[str, int], - requestHandler: Type[SimpleXMLRPCRequestHandler] = ..., + requestHandler: type[SimpleXMLRPCRequestHandler] = ..., logRequests: bool = ..., allow_none: bool = ..., encoding: str | None = ..., diff --git a/mypy/typeshed/stdlib/xxlimited.pyi b/mypy/typeshed/stdlib/xxlimited.pyi index 0dddbb876638c..b2fb72ad2c0b8 100644 --- a/mypy/typeshed/stdlib/xxlimited.pyi +++ b/mypy/typeshed/stdlib/xxlimited.pyi @@ -1,8 +1,10 @@ import sys from typing import Any +from typing_extensions import final class Str: ... +@final class Xxo: def demo(self) -> None: ... @@ -15,4 +17,5 @@ if sys.version_info >= (3, 10): else: class error: ... class Null: ... + def roj(__b: Any) -> None: ... diff --git a/mypy/typeshed/stdlib/zipapp.pyi b/mypy/typeshed/stdlib/zipapp.pyi index 581d2b72a6648..c3cf8321dbc47 100644 --- a/mypy/typeshed/stdlib/zipapp.pyi +++ b/mypy/typeshed/stdlib/zipapp.pyi @@ -1,8 +1,10 @@ import sys from pathlib import Path -from typing import BinaryIO, Callable, Union +from typing import BinaryIO, Callable -_Path = Union[str, Path, BinaryIO] +__all__ = ["ZipAppError", "create_archive", "get_interpreter"] + +_Path = str | Path | BinaryIO class ZipAppError(ValueError): ... diff --git a/mypy/typeshed/stdlib/zipfile.pyi b/mypy/typeshed/stdlib/zipfile.pyi index c64690ba8ca9a..b837528d7dfa8 100644 --- a/mypy/typeshed/stdlib/zipfile.pyi +++ b/mypy/typeshed/stdlib/zipfile.pyi @@ -1,11 +1,43 @@ import io import sys -from _typeshed import Self, StrPath +from _typeshed import Self, StrOrBytesPath, StrPath from os import PathLike from types import TracebackType -from typing import IO, Any, Callable, Iterable, Iterator, Protocol, Sequence, Type, overload +from typing import IO, Any, Callable, Iterable, Iterator, Protocol, Sequence, overload from typing_extensions import Literal +if sys.version_info >= (3, 8): + __all__ = [ + "BadZipFile", + "BadZipfile", + "error", + "ZIP_STORED", + "ZIP_DEFLATED", + "ZIP_BZIP2", + "ZIP_LZMA", + "is_zipfile", + "ZipInfo", + "ZipFile", + "PyZipFile", + "LargeZipFile", + "Path", + ] +else: + __all__ = [ + "BadZipFile", + "BadZipfile", + "error", + "ZIP_STORED", + "ZIP_DEFLATED", + "ZIP_BZIP2", + "ZIP_LZMA", + "is_zipfile", + "ZipInfo", + "ZipFile", + "PyZipFile", + "LargeZipFile", + ] + _DateTuple = tuple[int, int, int, int, int, int] _ReadWriteMode = Literal["r", "w"] _ReadWriteBinaryMode = Literal["r", "w", "rb", "wb"] @@ -25,6 +57,12 @@ class _ZipStream(Protocol): # def tell(self) -> int: ... # def seek(self, __n: int) -> object: ... +# Stream shape as required by _EndRecData() and _EndRecData64(). +class _SupportsReadSeekTell(Protocol): + def read(self, __n: int = ...) -> bytes: ... + def seek(self, __cookie: int, __whence: int) -> object: ... + def tell(self) -> int: ... + class _ClosableZipStream(_ZipStream, Protocol): def close(self) -> object: ... @@ -96,9 +134,9 @@ class ZipExtFile(io.BufferedIOBase): decrypter: Callable[[Sequence[int]], bytes] | None = ..., close_fileobj: Literal[False] = ..., ) -> None: ... + def read(self, n: int | None = ...) -> bytes: ... def readline(self, limit: int = ...) -> bytes: ... # type: ignore[override] - def __repr__(self) -> str: ... def peek(self, n: int = ...) -> bytes: ... def read1(self, n: int | None) -> bytes: ... # type: ignore[override] if sys.version_info >= (3, 7): @@ -143,9 +181,10 @@ class ZipFile: def __init__( self, file: StrPath | IO[bytes], mode: _ZipFileMode = ..., compression: int = ..., allowZip64: bool = ... ) -> None: ... + def __enter__(self: Self) -> Self: ... def __exit__( - self, exc_type: Type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + self, type: type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None ) -> None: ... def close(self) -> None: ... def getinfo(self, name: str) -> ZipInfo: ... @@ -211,10 +250,13 @@ class ZipInfo: def __init__(self, filename: str = ..., date_time: _DateTuple = ...) -> None: ... if sys.version_info >= (3, 8): @classmethod - def from_file(cls, filename: StrPath, arcname: StrPath | None = ..., *, strict_timestamps: bool = ...) -> ZipInfo: ... + def from_file( + cls: type[Self], filename: StrPath, arcname: StrPath | None = ..., *, strict_timestamps: bool = ... + ) -> Self: ... else: @classmethod - def from_file(cls, filename: StrPath, arcname: StrPath | None = ...) -> ZipInfo: ... + def from_file(cls: type[Self], filename: StrPath, arcname: StrPath | None = ...) -> Self: ... + def is_dir(self) -> bool: ... def FileHeader(self, zip64: bool | None = ...) -> bytes: ... @@ -230,12 +272,14 @@ if sys.version_info >= (3, 8): if sys.version_info >= (3, 10): @property def filename(self) -> PathLike[str]: ... # undocumented + def __init__(self, root: ZipFile | StrPath | IO[bytes], at: str = ...) -> None: ... if sys.version_info >= (3, 9): def open(self, mode: _ReadWriteBinaryMode = ..., *args: Any, pwd: bytes | None = ..., **kwargs: Any) -> IO[bytes]: ... else: @property def open(self) -> _PathOpenProtocol: ... + def iterdir(self) -> Iterator[Path]: ... def is_dir(self) -> bool: ... def is_file(self) -> bool: ... @@ -253,9 +297,10 @@ if sys.version_info >= (3, 8): def joinpath(self, *other: StrPath) -> Path: ... else: def joinpath(self, add: StrPath) -> Path: ... # undocumented + def __truediv__(self, add: StrPath) -> Path: ... -def is_zipfile(filename: StrPath | IO[bytes]) -> bool: ... +def is_zipfile(filename: StrOrBytesPath | _SupportsReadSeekTell) -> bool: ... ZIP_STORED: int ZIP_DEFLATED: int diff --git a/mypy/typeshed/stdlib/zipimport.pyi b/mypy/typeshed/stdlib/zipimport.pyi index 3435092a47220..a0e6d9e258dc1 100644 --- a/mypy/typeshed/stdlib/zipimport.pyi +++ b/mypy/typeshed/stdlib/zipimport.pyi @@ -7,6 +7,9 @@ from typing import Any if sys.version_info >= (3, 7): from importlib.abc import ResourceReader +if sys.version_info >= (3, 8): + __all__ = ["ZipImportError", "zipimporter"] + class ZipImportError(ImportError): ... class zipimporter: @@ -20,6 +23,7 @@ class zipimporter: def get_filename(self, fullname: str) -> str: ... if sys.version_info >= (3, 7): def get_resource_reader(self, fullname: str) -> ResourceReader | None: ... # undocumented + def get_source(self, fullname: str) -> str | None: ... def is_package(self, fullname: str) -> bool: ... def load_module(self, fullname: str) -> ModuleType: ... diff --git a/mypy/typeshed/stdlib/zlib.pyi b/mypy/typeshed/stdlib/zlib.pyi index 646c96bd2bef2..cfd6784bb7713 100644 --- a/mypy/typeshed/stdlib/zlib.pyi +++ b/mypy/typeshed/stdlib/zlib.pyi @@ -1,29 +1,30 @@ +import sys from array import array from typing import Any from typing_extensions import Literal -DEFLATED: int -DEF_MEM_LEVEL: int +DEFLATED: Literal[8] +DEF_MEM_LEVEL: int # can change +DEF_BUF_SIZE: Literal[16384] MAX_WBITS: int -ZLIB_VERSION: str +ZLIB_VERSION: str # can change +ZLIB_RUNTIME_VERSION: str # can change Z_NO_COMPRESSION: Literal[0] Z_PARTIAL_FLUSH: Literal[1] -Z_BEST_COMPRESSION: int -Z_BEST_SPEED: int +Z_BEST_COMPRESSION: Literal[9] +Z_BEST_SPEED: Literal[1] Z_BLOCK: Literal[5] -Z_DEFAULT_COMPRESSION: int -Z_DEFAULT_STRATEGY: int -Z_FILTERED: int -Z_FINISH: int -Z_FIXED: int -Z_FULL_FLUSH: int -Z_HUFFMAN_ONLY: int -Z_NO_FLUSH: int -Z_RLE: int -Z_SYNC_FLUSH: int +Z_DEFAULT_COMPRESSION: Literal[-1] +Z_DEFAULT_STRATEGY: Literal[0] +Z_FILTERED: Literal[1] +Z_FINISH: Literal[4] +Z_FIXED: Literal[4] +Z_FULL_FLUSH: Literal[3] +Z_HUFFMAN_ONLY: Literal[2] +Z_NO_FLUSH: Literal[0] +Z_RLE: Literal[3] +Z_SYNC_FLUSH: Literal[2] Z_TREES: Literal[6] -DEF_BUF_SIZE: int -ZLIB_RUNTIME_VERSION: str class error(Exception): ... @@ -41,7 +42,13 @@ class _Decompress: def copy(self) -> _Decompress: ... def adler32(__data: bytes, __value: int = ...) -> int: ... -def compress(__data: bytes, level: int = ...) -> bytes: ... + +if sys.version_info >= (3, 11): + def compress(__data: bytes, level: int = ..., wbits: int = ...) -> bytes: ... + +else: + def compress(__data: bytes, level: int = ...) -> bytes: ... + def compressobj( level: int = ..., method: int = ..., wbits: int = ..., memLevel: int = ..., strategy: int = ..., zdict: bytes | None = ... ) -> _Compress: ... diff --git a/mypy/typeshed/stdlib/zoneinfo/__init__.pyi b/mypy/typeshed/stdlib/zoneinfo/__init__.pyi index 4f924e0cc4bf4..d766eab6b7efa 100644 --- a/mypy/typeshed/stdlib/zoneinfo/__init__.pyi +++ b/mypy/typeshed/stdlib/zoneinfo/__init__.pyi @@ -1,9 +1,8 @@ -import typing -from _typeshed import StrPath +from _typeshed import Self, StrPath from datetime import tzinfo -from typing import Any, Iterable, Protocol, Sequence, Type +from typing import Any, Iterable, Protocol, Sequence -_T = typing.TypeVar("_T", bound="ZoneInfo") +__all__ = ["ZoneInfo", "reset_tzpath", "available_timezones", "TZPATH", "ZoneInfoNotFoundError", "InvalidTZPathWarning"] class _IOBytes(Protocol): def read(self, __size: int) -> bytes: ... @@ -14,9 +13,9 @@ class ZoneInfo(tzinfo): def key(self) -> str: ... def __init__(self, key: str) -> None: ... @classmethod - def no_cache(cls: Type[_T], key: str) -> _T: ... + def no_cache(cls: type[Self], key: str) -> Self: ... @classmethod - def from_file(cls: Type[_T], __fobj: _IOBytes, key: str | None = ...) -> _T: ... + def from_file(cls: type[Self], __fobj: _IOBytes, key: str | None = ...) -> Self: ... @classmethod def clear_cache(cls, *, only_keys: Iterable[str] = ...) -> None: ... diff --git a/mypy/typeshed/stubs/mypy-extensions/mypy_extensions.pyi b/mypy/typeshed/stubs/mypy-extensions/mypy_extensions.pyi index dd182c485177b..33b47244d3856 100644 --- a/mypy/typeshed/stubs/mypy-extensions/mypy_extensions.pyi +++ b/mypy/typeshed/stubs/mypy-extensions/mypy_extensions.pyi @@ -1,19 +1,20 @@ import abc import sys -from typing import Any, Callable, Generic, ItemsView, KeysView, Mapping, Type, TypeVar, ValuesView +from _typeshed import Self +from typing import Any, Callable, Generic, ItemsView, KeysView, Mapping, TypeVar, ValuesView _T = TypeVar("_T") _U = TypeVar("_U") # Internal mypy fallback type for all typed dicts (does not exist at runtime) class _TypedDict(Mapping[str, object], metaclass=abc.ABCMeta): - def copy(self: _T) -> _T: ... + def copy(self: Self) -> Self: ... # Using NoReturn so that only calls using mypy plugin hook that specialize the signature # can go through. def setdefault(self, k: NoReturn, default: object) -> object: ... # Mypy plugin hook for 'pop' expects that 'default' has a type variable type. def pop(self, k: NoReturn, default: _T = ...) -> object: ... # type: ignore - def update(self: _T, __m: _T) -> None: ... + def update(self: Self, __m: Self) -> None: ... if sys.version_info >= (3, 0): def items(self) -> ItemsView[str, object]: ... def keys(self) -> KeysView[str]: ... @@ -23,9 +24,10 @@ class _TypedDict(Mapping[str, object], metaclass=abc.ABCMeta): def viewitems(self) -> ItemsView[str, object]: ... def viewkeys(self) -> KeysView[str]: ... def viewvalues(self) -> ValuesView[object]: ... + def __delitem__(self, k: NoReturn) -> None: ... -def TypedDict(typename: str, fields: dict[str, Type[Any]], total: bool = ...) -> Type[dict[str, Any]]: ... +def TypedDict(typename: str, fields: dict[str, type[Any]], total: bool = ...) -> type[dict[str, Any]]: ... def Arg(type: _T = ..., name: str | None = ...) -> _T: ... def DefaultArg(type: _T = ..., name: str | None = ...) -> _T: ... def NamedArg(type: _T = ..., name: str | None = ...) -> _T: ... @@ -37,9 +39,10 @@ def KwArg(type: _T = ...) -> _T: ... # Deprecated: Use typing.NoReturn instead. class NoReturn: ... -# This is intended as a class decorator, but mypy rejects abstract classes -# when a Type[_T] is expected, so we can't give it the type we want -def trait(cls: Any) -> Any: ... +# This is consistent with implementation. Usage intends for this as +# a class decorator, but mypy does not support type[_T] for abstract +# classes until this issue is resolved, https://github.com/python/mypy/issues/4717. +def trait(cls: _T) -> _T: ... def mypyc_attr(*attrs: str, **kwattrs: object) -> Callable[[_T], _T]: ... class FlexibleAlias(Generic[_T, _U]): ... diff --git a/test-data/unit/check-flags.test b/test-data/unit/check-flags.test index a204135777769..5cda01fab855a 100644 --- a/test-data/unit/check-flags.test +++ b/test-data/unit/check-flags.test @@ -1378,6 +1378,16 @@ p: Future # E: Missing type parameters for generic type "Future" \ # N: Subscripting classes that are not generic at runtime may require escaping, see https://mypy.readthedocs.io/en/stable/runtime_troubles.html#not-generic-runtime q: Queue # E: Missing type parameters for generic type "Queue" \ # N: Subscripting classes that are not generic at runtime may require escaping, see https://mypy.readthedocs.io/en/stable/runtime_troubles.html#not-generic-runtime +[file asyncio/__init__.pyi] +from asyncio.futures import Future as Future +[file asyncio/futures.pyi] +from typing import TypeVar, Generic +_T = TypeVar('_T') +class Future(Generic[_T]): ... +[file queue.pyi] +from typing import TypeVar, Generic +_T = TypeVar('_T') +class Queue(Generic[_T]): ... [builtins fixtures/async_await.pyi] [typing fixtures/typing-full.pyi] diff --git a/test-data/unit/check-functools.test b/test-data/unit/check-functools.test index 33653c8d3fbc1..5f9159ab9c524 100644 --- a/test-data/unit/check-functools.test +++ b/test-data/unit/check-functools.test @@ -126,4 +126,9 @@ reveal_type(Child().f) # N: Revealed type is "builtins.str" reveal_type(Child().g) # N: Revealed type is "builtins.int" Child().f = "Hello World" Child().g = "invalid" # E: Incompatible types in assignment (expression has type "str", variable has type "int") +[file functools.pyi] +import sys +from typing import TypeVar, Generic +_T = TypeVar('_T') +class cached_property(Generic[_T]): ... [builtins fixtures/property.pyi] diff --git a/test-data/unit/check-generic-alias.test b/test-data/unit/check-generic-alias.test index bba3f5f9bd047..574a57607d11c 100644 --- a/test-data/unit/check-generic-alias.test +++ b/test-data/unit/check-generic-alias.test @@ -199,14 +199,6 @@ t23: collections.abc.ValuesView[str] [builtins fixtures/tuple.pyi] -[case testGenericAliasImportRe] -# flags: --python-version 3.9 -from re import Pattern, Match -t1: Pattern[str] -t2: Match[str] -[builtins fixtures/tuple.pyi] - - [case testGenericBuiltinTupleTyping] # flags: --python-version 3.6 from typing import Tuple diff --git a/test-data/unit/pythoneval.test b/test-data/unit/pythoneval.test index bba2885bf77be..a3f44fff5e333 100644 --- a/test-data/unit/pythoneval.test +++ b/test-data/unit/pythoneval.test @@ -850,7 +850,7 @@ MyDDict(dict)[0] _program.py:6: error: Argument 1 to "defaultdict" has incompatible type "Type[List[Any]]"; expected "Callable[[], str]" _program.py:9: error: Invalid index type "str" for "defaultdict[int, str]"; expected type "int" _program.py:9: error: Incompatible types in assignment (expression has type "int", target has type "str") -_program.py:19: error: Dict entry 0 has incompatible type "str": "List[]"; expected "int": "List[]" +_program.py:19: error: Argument 1 to "tst" has incompatible type "defaultdict[str, List[]]"; expected "defaultdict[int, List[]]" _program.py:23: error: Invalid index type "str" for "MyDDict[Dict[_KT, _VT]]"; expected type "int" [case testNoSubcriptionOfStdlibCollections] @@ -1084,8 +1084,8 @@ _testTypedDictGet.py:8: note: Revealed type is "builtins.str" _testTypedDictGet.py:9: note: Revealed type is "builtins.object" _testTypedDictGet.py:10: error: All overload variants of "get" of "Mapping" require at least one argument _testTypedDictGet.py:10: note: Possible overload variants: -_testTypedDictGet.py:10: note: def get(self, key: str) -> object -_testTypedDictGet.py:10: note: def [_T] get(self, str, object) -> object +_testTypedDictGet.py:10: note: def get(self, str) -> object +_testTypedDictGet.py:10: note: def [_T] get(self, str, default: object) -> object _testTypedDictGet.py:12: note: Revealed type is "builtins.object" [case testTypedDictMappingMethods] From 92b1f566c3d4d07962d20223d255dc66265c0dbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Ogam?= Date: Fri, 8 Apr 2022 18:25:33 +0200 Subject: [PATCH 224/377] Fix a documentation error (KeysView instead of ItemsView) (#12549) --- docs/source/getting_started.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst index f9b21d8dbf60f..124edd650d27e 100644 --- a/docs/source/getting_started.rst +++ b/docs/source/getting_started.rst @@ -157,7 +157,7 @@ Arguments with default values can be annotated like so: # 'kwargs' has type 'dict[str, float]' (a dict of strs to floats) for arg in args: print(arg) - for key, value in kwargs: + for key, value in kwargs.items(): print(key, value) Additional types, and the typing module From 588545f501ab4542cc2e70c64f2630b2786c1dbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Ogam?= Date: Fri, 8 Apr 2022 18:25:49 +0200 Subject: [PATCH 225/377] Fix a documentation error (issubtype instead of issubclass) (#12552) --- docs/source/type_narrowing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/type_narrowing.rst b/docs/source/type_narrowing.rst index b5f297d283c0c..806835ed33a50 100644 --- a/docs/source/type_narrowing.rst +++ b/docs/source/type_narrowing.rst @@ -100,7 +100,7 @@ for better type inference when working with types and metaclasses: t = type(o) # We must use a variable here reveal_type(t) # Revealed type is "builtins.type" - if issubtype(t, MyCalcMeta): # `issubtype(type(o), MyCalcMeta)` won't work + if issubclass(t, MyCalcMeta): # `issubclass(type(o), MyCalcMeta)` won't work reveal_type(t) # Revealed type is "Type[MyCalcMeta]" t.calc() # Okay From 965c6c975441e35612d6c9351dee8a2e0c9bb4a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Ogam?= Date: Fri, 8 Apr 2022 22:17:27 +0200 Subject: [PATCH 226/377] README.md: avoid horizontal scrollbar in code snippet (#12551) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 86a92df18d1d9..98f6d48cd982a 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ Here is a small example to whet your appetite: ```python number = input("What is your favourite number?") -print("Well, my favourite number is: ", number + 1) # error: Unsupported operand types for + ("str" and "int") +print("It is", number + 1) # error: Unsupported operand types for + ("str" and "int") ``` See [the documentation](https://mypy.readthedocs.io/en/stable/introduction.html) for more examples. From 6a24e1de5beae5d15ca997b3a4fcb994d26c705a Mon Sep 17 00:00:00 2001 From: Akuli Date: Sun, 10 Apr 2022 06:05:13 +0300 Subject: [PATCH 227/377] Add tests for decorating ParamSpec (#12555) --- .../unit/check-parameter-specification.test | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test-data/unit/check-parameter-specification.test b/test-data/unit/check-parameter-specification.test index fe2354612fbb9..be296b243019a 100644 --- a/test-data/unit/check-parameter-specification.test +++ b/test-data/unit/check-parameter-specification.test @@ -997,6 +997,29 @@ a3 = f2 a3 = f1 [builtins fixtures/tuple.pyi] +[case testDecoratingClassesThatUseParamSpec] +from typing import Generic, TypeVar, Callable, Any +from typing_extensions import ParamSpec + +_P = ParamSpec("_P") +_T = TypeVar("_T") +_F = TypeVar("_F", bound=Callable[..., Any]) + +def f(x: _F) -> _F: ... + +@f # Should be ok +class OnlyParamSpec(Generic[_P]): + pass + +@f # Should be ok +class MixedWithTypeVar1(Generic[_P, _T]): + pass + +@f # Should be ok +class MixedWithTypeVar2(Generic[_T, _P]): + pass +[builtins fixtures/dict.pyi] + [case testGenericsInInferredParamspec] from typing import Callable, TypeVar, Generic from typing_extensions import ParamSpec From 74df7fb1172993af3b2456765fb8368481ef0ab9 Mon Sep 17 00:00:00 2001 From: Shubham SInghal Date: Mon, 11 Apr 2022 21:12:34 +0530 Subject: [PATCH 228/377] Fix Stubgen's behavior for Instance Variables in C extensions (#12524) It is not necessary for instance variables to have the fget attrbute (e.g. instance variable in a C class in an extension) but inspect.isdatadescriptor return True as expected, hence we update the 'is_c_property' check. Since special attributes (like __dict__ etc) also passes 'is_c_property' check, we ignore all such special attributes in 'generate_c_property_stub' while creating the contents of stub file. Also, 'is_c_property_readonly' assumed that the property would always have 'fset' attribute which again is not true for instance variables in C extension. Hence make the check defensive by first checking if 'fset' attribute even exists or not. Fixes #12150. --- mypy/stubgenc.py | 8 +++-- mypy/test/teststubgen.py | 34 ++++++++++++++++--- .../stubgen/pybind11_mypy_demo/basics.pyi | 4 --- 3 files changed, 36 insertions(+), 10 deletions(-) diff --git a/mypy/stubgenc.py b/mypy/stubgenc.py index 0eeb39f102dcb..4b0bd4a62552a 100755 --- a/mypy/stubgenc.py +++ b/mypy/stubgenc.py @@ -121,11 +121,11 @@ def is_c_classmethod(obj: object) -> bool: def is_c_property(obj: object) -> bool: - return inspect.isdatadescriptor(obj) and hasattr(obj, 'fget') + return inspect.isdatadescriptor(obj) or hasattr(obj, 'fget') def is_c_property_readonly(prop: Any) -> bool: - return prop.fset is None + return hasattr(prop, 'fset') and prop.fset is None def is_c_type(obj: object) -> bool: @@ -287,6 +287,10 @@ def infer_prop_type(docstr: Optional[str]) -> Optional[str]: else: return None + # Ignore special properties/attributes. + if name.startswith('__') and name.endswith('__'): + return + inferred = infer_prop_type(getattr(obj, '__doc__', None)) if not inferred: fget = getattr(obj, 'fget', None) diff --git a/mypy/test/teststubgen.py b/mypy/test/teststubgen.py index c999e3c826436..625ec3f30685f 100644 --- a/mypy/test/teststubgen.py +++ b/mypy/test/teststubgen.py @@ -20,7 +20,8 @@ ) from mypy.stubutil import walk_packages, remove_misplaced_type_comments, common_dir_prefix from mypy.stubgenc import ( - generate_c_type_stub, infer_method_sig, generate_c_function_stub, generate_c_property_stub + generate_c_type_stub, infer_method_sig, generate_c_function_stub, generate_c_property_stub, + is_c_property_readonly ) from mypy.stubdoc import ( parse_signature, parse_all_signatures, build_signature, find_unique_signatures, @@ -868,9 +869,34 @@ def get_attribute(self) -> None: pass attribute = property(get_attribute, doc="") - output: List[str] = [] - generate_c_property_stub('attribute', TestClass.attribute, [], [], output, readonly=True) - assert_equal(output, ['@property', 'def attribute(self) -> str: ...']) + readwrite_properties: List[str] = [] + readonly_properties: List[str] = [] + generate_c_property_stub('attribute', TestClass.attribute, [], + readwrite_properties, readonly_properties, + is_c_property_readonly(TestClass.attribute)) + assert_equal(readwrite_properties, []) + assert_equal(readonly_properties, ['@property', 'def attribute(self) -> str: ...']) + + def test_generate_c_property_with_rw_property(self) -> None: + class TestClass: + def __init__(self) -> None: + self._attribute = 0 + + @property + def attribute(self) -> int: + return self._attribute + + @attribute.setter + def attribute(self, value: int) -> None: + self._attribute = value + + readwrite_properties: List[str] = [] + readonly_properties: List[str] = [] + generate_c_property_stub("attribute", type(TestClass.attribute), [], + readwrite_properties, readonly_properties, + is_c_property_readonly(TestClass.attribute)) + assert_equal(readwrite_properties, ['attribute: Any']) + assert_equal(readonly_properties, []) def test_generate_c_type_with_single_arg_generic(self) -> None: class TestClass: diff --git a/test-data/stubgen/pybind11_mypy_demo/basics.pyi b/test-data/stubgen/pybind11_mypy_demo/basics.pyi index 7c83f4ad2256b..99093fd6087a6 100644 --- a/test-data/stubgen/pybind11_mypy_demo/basics.pyi +++ b/test-data/stubgen/pybind11_mypy_demo/basics.pyi @@ -5,8 +5,6 @@ PI: float class Point: class AngleUnit: - __doc__: ClassVar[str] = ... # read-only - __members__: ClassVar[dict] = ... # read-only __entries: ClassVar[dict] = ... degree: ClassVar[Point.AngleUnit] = ... radian: ClassVar[Point.AngleUnit] = ... @@ -22,8 +20,6 @@ class Point: def name(self) -> str: ... class LengthUnit: - __doc__: ClassVar[str] = ... # read-only - __members__: ClassVar[dict] = ... # read-only __entries: ClassVar[dict] = ... inch: ClassVar[Point.LengthUnit] = ... mm: ClassVar[Point.LengthUnit] = ... From 1cccb0b9d95ea01e54efe8932b2f12aabf7eec31 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Wed, 13 Apr 2022 15:52:18 +0100 Subject: [PATCH 229/377] Typeshed cherry-pick: Drop some literal types from argparse (add_argument) (#7614) (#12576) From python/typeshed#7614. --- mypy/typeshed/stdlib/argparse.pyi | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/mypy/typeshed/stdlib/argparse.pyi b/mypy/typeshed/stdlib/argparse.pyi index ad54660cc45d4..0a56aa4f4b59a 100644 --- a/mypy/typeshed/stdlib/argparse.pyi +++ b/mypy/typeshed/stdlib/argparse.pyi @@ -62,6 +62,15 @@ _T = TypeVar("_T") _ActionT = TypeVar("_ActionT", bound=Action) _ArgumentParserT = TypeVar("_ArgumentParserT", bound=ArgumentParser) _N = TypeVar("_N") +# more precisely, Literal["store", "store_const", "store_true", +# "store_false", "append", "append_const", "count", "help", "version", +# "extend"], but using this would make it hard to annotate callers +# that don't use a literal argument +_ActionStr = str +# more precisely, Literal["?", "*", "+", "...", "A...", +# "==SUPPRESS=="], but using this would make it hard to annotate +# callers that don't use a literal argument +_NArgsStr = str ONE_OR_MORE: Literal["+"] OPTIONAL: Literal["?"] @@ -106,11 +115,8 @@ class _ActionsContainer: def add_argument( self, *name_or_flags: str, - action: Literal[ - "store", "store_const", "store_true", "store_false", "append", "append_const", "count", "help", "version", "extend" - ] - | type[Action] = ..., - nargs: int | Literal["?", "*", "+", "...", "A...", "==SUPPRESS=="] | _SUPPRESS_T = ..., + action: _ActionStr | type[Action] = ..., + nargs: int | _NArgsStr | _SUPPRESS_T = ..., const: Any = ..., default: Any = ..., type: Callable[[str], _T] | FileType = ..., From f8ca2332eca0f242a3b1d1b99e795c790b044138 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Wed, 13 Apr 2022 07:56:00 -0700 Subject: [PATCH 230/377] Recognise LiteralString as str (#12559) Linking #12554 Co-authored-by: hauntsaninja <> --- mypy/nodes.py | 7 +++++++ test-data/unit/check-type-aliases.test | 18 ++++++++++++++++++ test-data/unit/fixtures/typing-medium.pyi | 1 + 3 files changed, 26 insertions(+) diff --git a/mypy/nodes.py b/mypy/nodes.py index 7fcf5d85673cf..ff9276213ddca 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -123,6 +123,8 @@ def get_column(self) -> int: 'typing.DefaultDict': 'collections.defaultdict', 'typing.Deque': 'collections.deque', 'typing.OrderedDict': 'collections.OrderedDict', + # HACK: a lie in lieu of actual support for PEP 675 + 'typing.LiteralString': 'builtins.str', } # This keeps track of the oldest supported Python version where the corresponding @@ -137,12 +139,15 @@ def get_column(self) -> int: 'typing.DefaultDict': (2, 7), 'typing.Deque': (2, 7), 'typing.OrderedDict': (3, 7), + 'typing.LiteralString': (3, 11), } # This keeps track of aliases in `typing_extensions`, which we treat specially. typing_extensions_aliases: Final = { # See: https://github.com/python/mypy/issues/11528 'typing_extensions.OrderedDict': 'collections.OrderedDict', + # HACK: a lie in lieu of actual support for PEP 675 + 'typing_extensions.LiteralString': 'builtins.str', } reverse_builtin_aliases: Final = { @@ -156,6 +161,8 @@ def get_column(self) -> int: _nongen_builtins.update((name, alias) for alias, name in type_aliases.items()) # Drop OrderedDict from this for backward compatibility del _nongen_builtins['collections.OrderedDict'] +# HACK: consequence of hackily treating LiteralString as an alias for str +del _nongen_builtins['builtins.str'] def get_nongen_builtins(python_version: Tuple[int, int]) -> Dict[str, str]: diff --git a/test-data/unit/check-type-aliases.test b/test-data/unit/check-type-aliases.test index 61d53870d7242..111743e9235e9 100644 --- a/test-data/unit/check-type-aliases.test +++ b/test-data/unit/check-type-aliases.test @@ -752,3 +752,21 @@ from typing_extensions import TypeAlias A: TypeAlias = str [builtins fixtures/bool.pyi] [out] + + +[case testLiteralStringPep675] +# flags: --python-version 3.11 +from typing import LiteralString as tpLS +from typing_extensions import LiteralString as tpxLS + +def f(a: tpLS, b: tpxLS) -> None: + reveal_type(a) # N: Revealed type is "builtins.str" + reveal_type(b) # N: Revealed type is "builtins.str" + +# This isn't the correct behaviour, but should unblock use of LiteralString in typeshed +f("asdf", "asdf") +string: str +f(string, string) + +[builtins fixtures/tuple.pyi] +[typing fixtures/typing-medium.pyi] diff --git a/test-data/unit/fixtures/typing-medium.pyi b/test-data/unit/fixtures/typing-medium.pyi index 923ede2f0c008..568fe057c4cf4 100644 --- a/test-data/unit/fixtures/typing-medium.pyi +++ b/test-data/unit/fixtures/typing-medium.pyi @@ -27,6 +27,7 @@ TypedDict = 0 NoReturn = 0 NewType = 0 TypeAlias = 0 +LiteralString = 0 T = TypeVar('T') T_co = TypeVar('T_co', covariant=True) From 7cc138822cd348be223d298740dbd7194dfa9596 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Wed, 13 Apr 2022 16:38:16 +0100 Subject: [PATCH 231/377] Update version to 0.960+dev (#12578) --- mypy/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/version.py b/mypy/version.py index b59c826eab6b3..c7b4e30f24202 100644 --- a/mypy/version.py +++ b/mypy/version.py @@ -5,7 +5,7 @@ # - Release versions have the form "0.NNN". # - Dev versions have the form "0.NNN+dev" (PLUS sign to conform to PEP 440). # - For 1.0 we'll switch back to 1.2.3 form. -__version__ = '0.950+dev' +__version__ = '0.960+dev' base_version = __version__ mypy_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) From 0c6b29073b2bf7439b9efbb958c403574111ac15 Mon Sep 17 00:00:00 2001 From: Vincent Vanlaer <13833860+VincentVanlaer@users.noreply.github.com> Date: Thu, 14 Apr 2022 01:11:00 +0200 Subject: [PATCH 232/377] Change install from git link in README to https (#12581) GitHub has dropped support for the unauthenticated git protocol. See https://github.blog/2021-09-01-improving-git-protocol-security-github/ --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 98f6d48cd982a..c8f4df995f3ab 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ Mypy can be installed using pip: If you want to run the latest version of the code, you can install from git: - python3 -m pip install -U git+git://github.com/python/mypy.git + python3 -m pip install -U git+https://github.com/python/mypy.git Now you can type-check the [statically typed parts] of a program like this: From 44993e6a18f852a9296786267ecf26ea730b4f31 Mon Sep 17 00:00:00 2001 From: EXPLOSION Date: Thu, 14 Apr 2022 17:49:51 +0900 Subject: [PATCH 233/377] Fix propagated Any constraint (#12548) Fixes #12542. This allows parameters to constrain to Any. --- mypy/constraints.py | 4 ++++ test-data/unit/check-parameter-specification.test | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/mypy/constraints.py b/mypy/constraints.py index 0b2217b21ae0c..b7ed1492e5f3b 100644 --- a/mypy/constraints.py +++ b/mypy/constraints.py @@ -407,6 +407,10 @@ def visit_unpack_type(self, template: UnpackType) -> List[Constraint]: raise NotImplementedError def visit_parameters(self, template: Parameters) -> List[Constraint]: + # constraining Any against C[P] turns into infer_against_any([P], Any) + # ... which seems like the only case this can happen. Better to fail loudly. + if isinstance(self.actual, AnyType): + return self.infer_against_any(template.arg_types, self.actual) raise RuntimeError("Parameters cannot be constrained to") # Non-leaf types diff --git a/test-data/unit/check-parameter-specification.test b/test-data/unit/check-parameter-specification.test index be296b243019a..2242b79d4b643 100644 --- a/test-data/unit/check-parameter-specification.test +++ b/test-data/unit/check-parameter-specification.test @@ -1049,3 +1049,17 @@ P = ParamSpec("P") def x(f: Callable[Concatenate[int, Concatenate[int, P]], None]) -> None: ... # E: Nested Concatenates are invalid [builtins fixtures/tuple.pyi] + +[case testPropagatedAnyConstraintsAreOK] +from typing import Any, Callable, Generic, TypeVar +from typing_extensions import ParamSpec + +T = TypeVar("T") +P = ParamSpec("P") + +def callback(func: Callable[[Any], Any]) -> None: ... +class Job(Generic[P]): ... + +@callback +def run_job(job: Job[...]) -> T: ... +[builtins fixtures/tuple.pyi] From 875774769922c11094541eec20bd85bb1b87a70c Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Thu, 14 Apr 2022 20:53:33 -0700 Subject: [PATCH 234/377] Add support for assert_type (#12584) See python/cpython#30843. The implementation mostly follows that of cast(). It relies on `mypy.sametypes.is_same_type()`. --- mypy/checkexpr.py | 10 +++++++++- mypy/errorcodes.py | 3 +++ mypy/literals.py | 6 +++++- mypy/messages.py | 5 +++++ mypy/mixedtraverser.py | 6 +++++- mypy/nodes.py | 16 ++++++++++++++++ mypy/semanal.py | 23 +++++++++++++++++++++-- mypy/server/astmerge.py | 6 +++++- mypy/server/deps.py | 7 ++++++- mypy/server/subexpr.py | 6 +++++- mypy/strconv.py | 3 +++ mypy/traverser.py | 5 ++++- mypy/treetransform.py | 5 ++++- mypy/types.py | 5 +++++ mypy/visitor.py | 7 +++++++ mypyc/irbuild/expression.py | 5 ++++- mypyc/irbuild/visitor.py | 5 ++++- mypyc/test-data/irbuild-basic.test | 11 +++++++++++ test-data/unit/check-expressions.test | 12 ++++++++++++ test-data/unit/fixtures/typing-full.pyi | 1 + test-data/unit/lib-stub/typing.pyi | 1 + test-data/unit/semanal-errors.test | 9 +++++++++ test-data/unit/semanal-types.test | 11 +++++++++++ test-data/unit/typexport-basic.test | 19 +++++++++++++++++++ 24 files changed, 175 insertions(+), 12 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 45d5818d4eeba..32fa391bb0e2d 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -23,7 +23,7 @@ get_proper_types, flatten_nested_unions, LITERAL_TYPE_NAMES, ) from mypy.nodes import ( - NameExpr, RefExpr, Var, FuncDef, OverloadedFuncDef, TypeInfo, CallExpr, + AssertTypeExpr, NameExpr, RefExpr, Var, FuncDef, OverloadedFuncDef, TypeInfo, CallExpr, MemberExpr, IntExpr, StrExpr, BytesExpr, UnicodeExpr, FloatExpr, OpExpr, UnaryExpr, IndexExpr, CastExpr, RevealExpr, TypeApplication, ListExpr, TupleExpr, DictExpr, LambdaExpr, SuperExpr, SliceExpr, Context, Expression, @@ -3144,6 +3144,14 @@ def visit_cast_expr(self, expr: CastExpr) -> Type: context=expr) return target_type + def visit_assert_type_expr(self, expr: AssertTypeExpr) -> Type: + source_type = self.accept(expr.expr, type_context=AnyType(TypeOfAny.special_form), + allow_none_return=True, always_allow_any=True) + target_type = expr.type + if not is_same_type(source_type, target_type): + self.msg.assert_type_fail(source_type, target_type, expr) + return source_type + def visit_reveal_expr(self, expr: RevealExpr) -> Type: """Type check a reveal_type expression.""" if expr.kind == REVEAL_TYPE: diff --git a/mypy/errorcodes.py b/mypy/errorcodes.py index 31f1a2fb73eae..85d6d9dd41594 100644 --- a/mypy/errorcodes.py +++ b/mypy/errorcodes.py @@ -113,6 +113,9 @@ def __str__(self) -> str: REDUNDANT_CAST: Final = ErrorCode( "redundant-cast", "Check that cast changes type of expression", "General" ) +ASSERT_TYPE: Final = ErrorCode( + "assert-type", "Check that assert_type() call succeeds", "General" +) COMPARISON_OVERLAP: Final = ErrorCode( "comparison-overlap", "Check that types in comparisons and 'in' expressions overlap", "General" ) diff --git a/mypy/literals.py b/mypy/literals.py index 00cf5916bec2a..b11c07d91a915 100644 --- a/mypy/literals.py +++ b/mypy/literals.py @@ -8,7 +8,8 @@ ConditionalExpr, EllipsisExpr, YieldFromExpr, YieldExpr, RevealExpr, SuperExpr, TypeApplication, LambdaExpr, ListComprehension, SetComprehension, DictionaryComprehension, GeneratorExpr, BackquoteExpr, TypeVarExpr, TypeAliasExpr, NamedTupleExpr, EnumCallExpr, - TypedDictExpr, NewTypeExpr, PromoteExpr, AwaitExpr, TempNode, AssignmentExpr, ParamSpecExpr + TypedDictExpr, NewTypeExpr, PromoteExpr, AwaitExpr, TempNode, AssignmentExpr, ParamSpecExpr, + AssertTypeExpr, ) from mypy.visitor import ExpressionVisitor @@ -175,6 +176,9 @@ def visit_slice_expr(self, e: SliceExpr) -> None: def visit_cast_expr(self, e: CastExpr) -> None: return None + def visit_assert_type_expr(self, e: AssertTypeExpr) -> None: + return None + def visit_conditional_expr(self, e: ConditionalExpr) -> None: return None diff --git a/mypy/messages.py b/mypy/messages.py index 0e9a59ea40160..23ab172f54995 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -1213,6 +1213,11 @@ def redundant_cast(self, typ: Type, context: Context) -> None: self.fail('Redundant cast to {}'.format(format_type(typ)), context, code=codes.REDUNDANT_CAST) + def assert_type_fail(self, source_type: Type, target_type: Type, context: Context) -> None: + self.fail(f"Expression is of type {format_type(source_type)}, " + f"not {format_type(target_type)}", context, + code=codes.ASSERT_TYPE) + def unimported_type_becomes_any(self, prefix: str, typ: Type, ctx: Context) -> None: self.fail("{} becomes {} due to an unfollowed import".format(prefix, format_type(typ)), ctx, code=codes.NO_ANY_UNIMPORTED) diff --git a/mypy/mixedtraverser.py b/mypy/mixedtraverser.py index 57fdb28e0e451..c14648cdf6541 100644 --- a/mypy/mixedtraverser.py +++ b/mypy/mixedtraverser.py @@ -1,7 +1,7 @@ from typing import Optional from mypy.nodes import ( - Var, FuncItem, ClassDef, AssignmentStmt, ForStmt, WithStmt, + AssertTypeExpr, Var, FuncItem, ClassDef, AssignmentStmt, ForStmt, WithStmt, CastExpr, TypeApplication, TypeAliasExpr, TypeVarExpr, TypedDictExpr, NamedTupleExpr, PromoteExpr, NewTypeExpr ) @@ -79,6 +79,10 @@ def visit_cast_expr(self, o: CastExpr) -> None: super().visit_cast_expr(o) o.type.accept(self) + def visit_assert_type_expr(self, o: AssertTypeExpr) -> None: + super().visit_assert_type_expr(o) + o.type.accept(self) + def visit_type_application(self, o: TypeApplication) -> None: super().visit_type_application(o) for t in o.types: diff --git a/mypy/nodes.py b/mypy/nodes.py index ff9276213ddca..30bb2c6aa10a0 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -1945,6 +1945,22 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: return visitor.visit_cast_expr(self) +class AssertTypeExpr(Expression): + """Represents a typing.assert_type(expr, type) call.""" + __slots__ = ('expr', 'type') + + expr: Expression + type: "mypy.types.Type" + + def __init__(self, expr: Expression, typ: 'mypy.types.Type') -> None: + super().__init__() + self.expr = expr + self.type = typ + + def accept(self, visitor: ExpressionVisitor[T]) -> T: + return visitor.visit_assert_type_expr(self) + + class RevealExpr(Expression): """Reveal type expression reveal_type(expr) or reveal_locals() expression.""" diff --git a/mypy/semanal.py b/mypy/semanal.py index 44ece06747321..3ffc20cead773 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -56,7 +56,7 @@ from typing_extensions import Final, TypeAlias as _TypeAlias from mypy.nodes import ( - MypyFile, TypeInfo, Node, AssignmentStmt, FuncDef, OverloadedFuncDef, + AssertTypeExpr, MypyFile, TypeInfo, Node, AssignmentStmt, FuncDef, OverloadedFuncDef, ClassDef, Var, GDEF, FuncItem, Import, Expression, Lvalue, ImportFrom, ImportAll, Block, LDEF, NameExpr, MemberExpr, IndexExpr, TupleExpr, ListExpr, ExpressionStmt, ReturnStmt, @@ -99,7 +99,7 @@ TypeTranslator, TypeOfAny, TypeType, NoneType, PlaceholderType, TPDICT_NAMES, ProperType, get_proper_type, get_proper_types, TypeAliasType, TypeVarLikeType, Parameters, ParamSpecType, PROTOCOL_NAMES, TYPE_ALIAS_NAMES, FINAL_TYPE_NAMES, FINAL_DECORATOR_NAMES, REVEAL_TYPE_NAMES, - is_named_instance, + ASSERT_TYPE_NAMES, is_named_instance, ) from mypy.typeops import function_type, get_type_vars from mypy.type_visitor import TypeQuery @@ -3897,6 +3897,19 @@ def visit_call_expr(self, expr: CallExpr) -> None: expr.analyzed.line = expr.line expr.analyzed.column = expr.column expr.analyzed.accept(self) + elif refers_to_fullname(expr.callee, ASSERT_TYPE_NAMES): + if not self.check_fixed_args(expr, 2, 'assert_type'): + return + # Translate second argument to an unanalyzed type. + try: + target = self.expr_to_unanalyzed_type(expr.args[1]) + except TypeTranslationError: + self.fail('assert_type() type is not a type', expr) + return + expr.analyzed = AssertTypeExpr(expr.args[0], target) + expr.analyzed.line = expr.line + expr.analyzed.column = expr.column + expr.analyzed.accept(self) elif refers_to_fullname(expr.callee, REVEAL_TYPE_NAMES): if not self.check_fixed_args(expr, 1, 'reveal_type'): return @@ -4200,6 +4213,12 @@ def visit_cast_expr(self, expr: CastExpr) -> None: if analyzed is not None: expr.type = analyzed + def visit_assert_type_expr(self, expr: AssertTypeExpr) -> None: + expr.expr.accept(self) + analyzed = self.anal_type(expr.type) + if analyzed is not None: + expr.type = analyzed + def visit_reveal_expr(self, expr: RevealExpr) -> None: if expr.kind == REVEAL_TYPE: if expr.expr is not None: diff --git a/mypy/server/astmerge.py b/mypy/server/astmerge.py index deaf7a6e21b71..d8f1d5a191557 100644 --- a/mypy/server/astmerge.py +++ b/mypy/server/astmerge.py @@ -51,7 +51,7 @@ MypyFile, SymbolTable, Block, AssignmentStmt, NameExpr, MemberExpr, RefExpr, TypeInfo, FuncDef, ClassDef, NamedTupleExpr, SymbolNode, Var, Statement, SuperExpr, NewTypeExpr, OverloadedFuncDef, LambdaExpr, TypedDictExpr, EnumCallExpr, FuncBase, TypeAliasExpr, CallExpr, - CastExpr, TypeAlias, + CastExpr, TypeAlias, AssertTypeExpr, MDEF ) from mypy.traverser import TraverserVisitor @@ -226,6 +226,10 @@ def visit_cast_expr(self, node: CastExpr) -> None: super().visit_cast_expr(node) self.fixup_type(node.type) + def visit_assert_type_expr(self, node: AssertTypeExpr) -> None: + super().visit_assert_type_expr(node) + self.fixup_type(node.type) + def visit_super_expr(self, node: SuperExpr) -> None: super().visit_super_expr(node) if node.info is not None: diff --git a/mypy/server/deps.py b/mypy/server/deps.py index 646a024340482..da4960ba1934f 100644 --- a/mypy/server/deps.py +++ b/mypy/server/deps.py @@ -89,7 +89,8 @@ class 'mod.Cls'. This can also refer to an attribute inherited from a ComparisonExpr, GeneratorExpr, DictionaryComprehension, StarExpr, PrintStmt, ForStmt, WithStmt, TupleExpr, OperatorAssignmentStmt, DelStmt, YieldFromExpr, Decorator, Block, TypeInfo, FuncBase, OverloadedFuncDef, RefExpr, SuperExpr, Var, NamedTupleExpr, TypedDictExpr, - LDEF, MDEF, GDEF, TypeAliasExpr, NewTypeExpr, ImportAll, EnumCallExpr, AwaitExpr + LDEF, MDEF, GDEF, TypeAliasExpr, NewTypeExpr, ImportAll, EnumCallExpr, AwaitExpr, + AssertTypeExpr, ) from mypy.operators import ( op_methods, reverse_op_methods, ops_with_inplace_method, unary_op_methods @@ -686,6 +687,10 @@ def visit_cast_expr(self, e: CastExpr) -> None: super().visit_cast_expr(e) self.add_type_dependencies(e.type) + def visit_assert_type_expr(self, e: AssertTypeExpr) -> None: + super().visit_assert_type_expr(e) + self.add_type_dependencies(e.type) + def visit_type_application(self, e: TypeApplication) -> None: super().visit_type_application(e) for typ in e.types: diff --git a/mypy/server/subexpr.py b/mypy/server/subexpr.py index 2fb0ef4ffaf1e..4078c4170fcfd 100644 --- a/mypy/server/subexpr.py +++ b/mypy/server/subexpr.py @@ -7,7 +7,7 @@ SliceExpr, CastExpr, RevealExpr, UnaryExpr, ListExpr, TupleExpr, DictExpr, SetExpr, IndexExpr, GeneratorExpr, ListComprehension, SetComprehension, DictionaryComprehension, ConditionalExpr, TypeApplication, LambdaExpr, StarExpr, BackquoteExpr, AwaitExpr, - AssignmentExpr, + AssignmentExpr, AssertTypeExpr, ) from mypy.traverser import TraverserVisitor @@ -99,6 +99,10 @@ def visit_cast_expr(self, e: CastExpr) -> None: self.add(e) super().visit_cast_expr(e) + def visit_assert_type_expr(self, e: AssertTypeExpr) -> None: + self.add(e) + super().visit_assert_type_expr(e) + def visit_reveal_expr(self, e: RevealExpr) -> None: self.add(e) super().visit_reveal_expr(e) diff --git a/mypy/strconv.py b/mypy/strconv.py index 22534a44971d4..46ac4b10363cc 100644 --- a/mypy/strconv.py +++ b/mypy/strconv.py @@ -431,6 +431,9 @@ def visit_comparison_expr(self, o: 'mypy.nodes.ComparisonExpr') -> str: def visit_cast_expr(self, o: 'mypy.nodes.CastExpr') -> str: return self.dump([o.expr, o.type], o) + def visit_assert_type_expr(self, o: 'mypy.nodes.AssertTypeExpr') -> str: + return self.dump([o.expr, o.type], o) + def visit_reveal_expr(self, o: 'mypy.nodes.RevealExpr') -> str: if o.kind == mypy.nodes.REVEAL_TYPE: return self.dump([o.expr], o) diff --git a/mypy/traverser.py b/mypy/traverser.py index 996f752f4c32a..d9681bdd81baa 100644 --- a/mypy/traverser.py +++ b/mypy/traverser.py @@ -9,7 +9,7 @@ ) from mypy.visitor import NodeVisitor from mypy.nodes import ( - Block, MypyFile, FuncBase, FuncItem, CallExpr, ClassDef, Decorator, FuncDef, + AssertTypeExpr, Block, MypyFile, FuncBase, FuncItem, CallExpr, ClassDef, Decorator, FuncDef, ExpressionStmt, AssignmentStmt, OperatorAssignmentStmt, WhileStmt, ForStmt, ReturnStmt, AssertStmt, DelStmt, IfStmt, RaiseStmt, TryStmt, WithStmt, MatchStmt, NameExpr, MemberExpr, OpExpr, SliceExpr, CastExpr, @@ -205,6 +205,9 @@ def visit_slice_expr(self, o: SliceExpr) -> None: def visit_cast_expr(self, o: CastExpr) -> None: o.expr.accept(self) + def visit_assert_type_expr(self, o: AssertTypeExpr) -> None: + o.expr.accept(self) + def visit_reveal_expr(self, o: RevealExpr) -> None: if o.kind == REVEAL_TYPE: assert o.expr is not None diff --git a/mypy/treetransform.py b/mypy/treetransform.py index cdd4f604be865..62d5f6d72cbca 100644 --- a/mypy/treetransform.py +++ b/mypy/treetransform.py @@ -6,7 +6,7 @@ from typing import List, Dict, cast, Optional, Iterable from mypy.nodes import ( - MypyFile, Import, Node, ImportAll, ImportFrom, FuncItem, FuncDef, + AssertTypeExpr, MypyFile, Import, Node, ImportAll, ImportFrom, FuncItem, FuncDef, OverloadedFuncDef, ClassDef, Decorator, Block, Var, OperatorAssignmentStmt, ExpressionStmt, AssignmentStmt, ReturnStmt, RaiseStmt, AssertStmt, DelStmt, BreakStmt, ContinueStmt, @@ -407,6 +407,9 @@ def visit_cast_expr(self, node: CastExpr) -> CastExpr: return CastExpr(self.expr(node.expr), self.type(node.type)) + def visit_assert_type_expr(self, node: AssertTypeExpr) -> AssertTypeExpr: + return AssertTypeExpr(self.expr(node.expr), self.type(node.type)) + def visit_reveal_expr(self, node: RevealExpr) -> RevealExpr: if node.kind == REVEAL_TYPE: assert node.expr is not None diff --git a/mypy/types.py b/mypy/types.py index b423350961986..1d0274f38330e 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -132,6 +132,11 @@ 'typing_extensions.reveal_type', ) +ASSERT_TYPE_NAMES: Final = ( + 'typing.assert_type', + 'typing_extensions.assert_type', +) + # Attributes that can optionally be defined in the body of a subclass of # enum.Enum but are removed from the class __dict__ by EnumMeta. ENUM_REMOVED_PROPS: Final = ( diff --git a/mypy/visitor.py b/mypy/visitor.py index 9d3ebb6818b4f..7339111c7a05e 100644 --- a/mypy/visitor.py +++ b/mypy/visitor.py @@ -81,6 +81,10 @@ def visit_comparison_expr(self, o: 'mypy.nodes.ComparisonExpr') -> T: def visit_cast_expr(self, o: 'mypy.nodes.CastExpr') -> T: pass + @abstractmethod + def visit_assert_type_expr(self, o: 'mypy.nodes.AssertTypeExpr') -> T: + pass + @abstractmethod def visit_reveal_expr(self, o: 'mypy.nodes.RevealExpr') -> T: pass @@ -523,6 +527,9 @@ def visit_comparison_expr(self, o: 'mypy.nodes.ComparisonExpr') -> T: def visit_cast_expr(self, o: 'mypy.nodes.CastExpr') -> T: pass + def visit_assert_type_expr(self, o: 'mypy.nodes.AssertTypeExpr') -> T: + pass + def visit_reveal_expr(self, o: 'mypy.nodes.RevealExpr') -> T: pass diff --git a/mypyc/irbuild/expression.py b/mypyc/irbuild/expression.py index 71e497f9e368f..1a74d71c3b27f 100644 --- a/mypyc/irbuild/expression.py +++ b/mypyc/irbuild/expression.py @@ -11,7 +11,7 @@ ConditionalExpr, ComparisonExpr, IntExpr, FloatExpr, ComplexExpr, StrExpr, BytesExpr, EllipsisExpr, ListExpr, TupleExpr, DictExpr, SetExpr, ListComprehension, SetComprehension, DictionaryComprehension, SliceExpr, GeneratorExpr, CastExpr, StarExpr, - AssignmentExpr, + AssignmentExpr, AssertTypeExpr, Var, RefExpr, MypyFile, TypeInfo, TypeApplication, LDEF, ARG_POS ) from mypy.types import TupleType, Instance, TypeType, ProperType, get_proper_type @@ -203,6 +203,9 @@ def transform_super_expr(builder: IRBuilder, o: SuperExpr) -> Value: def transform_call_expr(builder: IRBuilder, expr: CallExpr) -> Value: if isinstance(expr.analyzed, CastExpr): return translate_cast_expr(builder, expr.analyzed) + elif isinstance(expr.analyzed, AssertTypeExpr): + # Compile to a no-op. + return builder.accept(expr.analyzed.expr) callee = expr.callee if isinstance(callee, IndexExpr) and isinstance(callee.analyzed, TypeApplication): diff --git a/mypyc/irbuild/visitor.py b/mypyc/irbuild/visitor.py index 43cfd457667dc..3a1883cca50bb 100644 --- a/mypyc/irbuild/visitor.py +++ b/mypyc/irbuild/visitor.py @@ -6,7 +6,7 @@ from typing_extensions import NoReturn from mypy.nodes import ( - MypyFile, FuncDef, ReturnStmt, AssignmentStmt, OpExpr, + AssertTypeExpr, MypyFile, FuncDef, ReturnStmt, AssignmentStmt, OpExpr, IntExpr, NameExpr, Var, IfStmt, UnaryExpr, ComparisonExpr, WhileStmt, CallExpr, IndexExpr, Block, ListExpr, ExpressionStmt, MemberExpr, ForStmt, BreakStmt, ContinueStmt, ConditionalExpr, OperatorAssignmentStmt, TupleExpr, ClassDef, @@ -327,6 +327,9 @@ def visit_var(self, o: Var) -> None: def visit_cast_expr(self, o: CastExpr) -> Value: assert False, "CastExpr should have been handled in CallExpr" + def visit_assert_type_expr(self, o: AssertTypeExpr) -> Value: + assert False, "AssertTypeExpr should have been handled in CallExpr" + def visit_star_expr(self, o: StarExpr) -> Value: assert False, "should have been handled in Tuple/List/Set/DictExpr or CallExpr" diff --git a/mypyc/test-data/irbuild-basic.test b/mypyc/test-data/irbuild-basic.test index ecce9248a4c8a..d3403addecfb1 100644 --- a/mypyc/test-data/irbuild-basic.test +++ b/mypyc/test-data/irbuild-basic.test @@ -876,6 +876,17 @@ L0: o = r3 return 1 +[case testAssertType] +from typing import assert_type +def f(x: int) -> None: + y = assert_type(x, int) +[out] +def f(x): + x, y :: int +L0: + y = x + return 1 + [case testDownCast] from typing import cast, List, Tuple class A: pass diff --git a/test-data/unit/check-expressions.test b/test-data/unit/check-expressions.test index 46f0cf02a125b..84b6105170bd1 100644 --- a/test-data/unit/check-expressions.test +++ b/test-data/unit/check-expressions.test @@ -1036,6 +1036,18 @@ class B: pass [out] main:3: error: "A" not callable +-- assert_type() + +[case testAssertType] +from typing import assert_type, Any +from typing_extensions import Literal +a: int = 1 +returned = assert_type(a, int) +reveal_type(returned) # N: Revealed type is "builtins.int" +assert_type(a, str) # E: Expression is of type "int", not "str" +assert_type(a, Any) # E: Expression is of type "int", not "Any" +assert_type(a, Literal[1]) # E: Expression is of type "int", not "Literal[1]" +[builtins fixtures/tuple.pyi] -- None return type -- ---------------- diff --git a/test-data/unit/fixtures/typing-full.pyi b/test-data/unit/fixtures/typing-full.pyi index 739bf703f3e7a..66b02638ebc78 100644 --- a/test-data/unit/fixtures/typing-full.pyi +++ b/test-data/unit/fixtures/typing-full.pyi @@ -11,6 +11,7 @@ from abc import abstractmethod, ABCMeta class GenericMeta(type): pass def cast(t, o): ... +def assert_type(o, t): ... overload = 0 Any = 0 Union = 0 diff --git a/test-data/unit/lib-stub/typing.pyi b/test-data/unit/lib-stub/typing.pyi index 57563fc9d2f60..0a1bb42b936ca 100644 --- a/test-data/unit/lib-stub/typing.pyi +++ b/test-data/unit/lib-stub/typing.pyi @@ -9,6 +9,7 @@ # the stubs under fixtures/. cast = 0 +assert_type = 0 overload = 0 Any = 0 Union = 0 diff --git a/test-data/unit/semanal-errors.test b/test-data/unit/semanal-errors.test index 34ec4f3c5b63e..ea937b8678f18 100644 --- a/test-data/unit/semanal-errors.test +++ b/test-data/unit/semanal-errors.test @@ -839,6 +839,15 @@ cast(str, *None) # E: "cast" must be called with 2 positional arguments cast(str, target=None) # E: "cast" must be called with 2 positional arguments [out] +[case testInvalidAssertType] +from typing import assert_type +assert_type(1, type=int) # E: "assert_type" must be called with 2 positional arguments +assert_type(1, *int) # E: "assert_type" must be called with 2 positional arguments +assert_type() # E: "assert_type" expects 2 arguments +assert_type(1, int, "hello") # E: "assert_type" expects 2 arguments +assert_type(int, 1) # E: Invalid type: try using Literal[1] instead? +assert_type(1, int[int]) # E: "int" expects no type arguments, but 1 given + [case testInvalidAnyCall] from typing import Any Any(str, None) # E: Any(...) is no longer supported. Use cast(Any, ...) instead diff --git a/test-data/unit/semanal-types.test b/test-data/unit/semanal-types.test index 1a2eca64a9f2d..3ce289b52ae24 100644 --- a/test-data/unit/semanal-types.test +++ b/test-data/unit/semanal-types.test @@ -390,6 +390,17 @@ MypyFile:1( IntExpr(1) builtins.int))) +[case testAssertType] +from typing import assert_type +assert_type(1, int) +[out] +MypyFile:1( + ImportFrom:1(typing, [assert_type]) + ExpressionStmt:2( + AssertTypeExpr:2( + IntExpr(1) + builtins.int))) + [case testFunctionTypeVariable] from typing import TypeVar t = TypeVar('t') diff --git a/test-data/unit/typexport-basic.test b/test-data/unit/typexport-basic.test index 7a0115f17e9cc..bdefb49e30382 100644 --- a/test-data/unit/typexport-basic.test +++ b/test-data/unit/typexport-basic.test @@ -101,6 +101,25 @@ NameExpr(8) : B CastExpr(9) : B NameExpr(9) : B +[case testAssertTypeExpr] +## AssertTypeExpr|[a-z] +from typing import Any, assert_type +d = None # type: Any +a = None # type: A +b = None # type: B +class A: pass +class B(A): pass +assert_type(d, Any) +assert_type(a, A) +assert_type(b, B) +[out] +AssertTypeExpr(8) : Any +NameExpr(8) : Any +AssertTypeExpr(9) : A +NameExpr(9) : A +AssertTypeExpr(10) : B +NameExpr(10) : B + [case testArithmeticOps] ## OpExpr import typing From ce858a6a0c85206ff877faf702293a9b67fae750 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Fri, 15 Apr 2022 16:45:02 -0700 Subject: [PATCH 235/377] Sync typeshed (#12596) Source commit: https://github.com/python/typeshed/commit/d09689f8115173e3b0b04365f5233164014a7a69 Co-authored-by: hauntsaninja <> --- mypy/typeshed/stdlib/_pydecimal.pyi | 82 +++++++++++++++++++ mypy/typeshed/stdlib/asyncio/streams.pyi | 4 +- mypy/typeshed/stdlib/asyncio/transports.pyi | 3 + mypy/typeshed/stdlib/base64.pyi | 41 +++++----- mypy/typeshed/stdlib/builtins.pyi | 47 ++++++++--- mypy/typeshed/stdlib/calendar.pyi | 87 +++++++++++++++------ mypy/typeshed/stdlib/datetime.pyi | 82 ++++++------------- mypy/typeshed/stdlib/linecache.pyi | 2 +- mypy/typeshed/stdlib/poplib.pyi | 6 +- mypy/typeshed/stdlib/tty.pyi | 2 + mypy/typeshed/stdlib/typing_extensions.pyi | 77 +++++++++++++++--- 11 files changed, 300 insertions(+), 133 deletions(-) diff --git a/mypy/typeshed/stdlib/_pydecimal.pyi b/mypy/typeshed/stdlib/_pydecimal.pyi index 56fbddfffa5cd..c15a4a41747e5 100644 --- a/mypy/typeshed/stdlib/_pydecimal.pyi +++ b/mypy/typeshed/stdlib/_pydecimal.pyi @@ -1,3 +1,85 @@ +import sys + # This is a slight lie, the implementations aren't exactly identical # However, in all likelihood, the differences are inconsequential from decimal import * + +if sys.version_info >= (3, 7): + __all__ = [ + "Decimal", + "Context", + "DecimalTuple", + "DefaultContext", + "BasicContext", + "ExtendedContext", + "DecimalException", + "Clamped", + "InvalidOperation", + "DivisionByZero", + "Inexact", + "Rounded", + "Subnormal", + "Overflow", + "Underflow", + "FloatOperation", + "DivisionImpossible", + "InvalidContext", + "ConversionSyntax", + "DivisionUndefined", + "ROUND_DOWN", + "ROUND_HALF_UP", + "ROUND_HALF_EVEN", + "ROUND_CEILING", + "ROUND_FLOOR", + "ROUND_UP", + "ROUND_HALF_DOWN", + "ROUND_05UP", + "setcontext", + "getcontext", + "localcontext", + "MAX_PREC", + "MAX_EMAX", + "MIN_EMIN", + "MIN_ETINY", + "HAVE_THREADS", + "HAVE_CONTEXTVAR", + ] +else: + __all__ = [ + "Decimal", + "Context", + "DecimalTuple", + "DefaultContext", + "BasicContext", + "ExtendedContext", + "DecimalException", + "Clamped", + "InvalidOperation", + "DivisionByZero", + "Inexact", + "Rounded", + "Subnormal", + "Overflow", + "Underflow", + "FloatOperation", + "DivisionImpossible", + "InvalidContext", + "ConversionSyntax", + "DivisionUndefined", + "ROUND_DOWN", + "ROUND_HALF_UP", + "ROUND_HALF_EVEN", + "ROUND_CEILING", + "ROUND_FLOOR", + "ROUND_UP", + "ROUND_HALF_DOWN", + "ROUND_05UP", + "setcontext", + "getcontext", + "localcontext", + "MAX_PREC", + "MAX_EMAX", + "MIN_EMIN", + "MIN_ETINY", + "HAVE_THREADS", + ] diff --git a/mypy/typeshed/stdlib/asyncio/streams.pyi b/mypy/typeshed/stdlib/asyncio/streams.pyi index 98349222d5a29..666862cc7b7d2 100644 --- a/mypy/typeshed/stdlib/asyncio/streams.pyi +++ b/mypy/typeshed/stdlib/asyncio/streams.pyi @@ -159,13 +159,13 @@ class StreamReaderProtocol(FlowControlMixin, protocols.Protocol): class StreamWriter: def __init__( self, - transport: transports.BaseTransport, + transport: transports.WriteTransport, protocol: protocols.BaseProtocol, reader: StreamReader | None, loop: events.AbstractEventLoop, ) -> None: ... @property - def transport(self) -> transports.BaseTransport: ... + def transport(self) -> transports.WriteTransport: ... def write(self, data: bytes) -> None: ... def writelines(self, data: Iterable[bytes]) -> None: ... def write_eof(self) -> None: ... diff --git a/mypy/typeshed/stdlib/asyncio/transports.pyi b/mypy/typeshed/stdlib/asyncio/transports.pyi index c24ded49cfb86..90e54b547a873 100644 --- a/mypy/typeshed/stdlib/asyncio/transports.pyi +++ b/mypy/typeshed/stdlib/asyncio/transports.pyi @@ -27,6 +27,9 @@ class ReadTransport(BaseTransport): class WriteTransport(BaseTransport): def set_write_buffer_limits(self, high: int | None = ..., low: int | None = ...) -> None: ... def get_write_buffer_size(self) -> int: ... + if sys.version_info >= (3, 9): + def get_write_buffer_limits(self) -> tuple[int, int]: ... + def write(self, data: Any) -> None: ... def writelines(self, list_of_data: list[Any]) -> None: ... def write_eof(self) -> None: ... diff --git a/mypy/typeshed/stdlib/base64.pyi b/mypy/typeshed/stdlib/base64.pyi index 70fe642923280..ceed7d018d82d 100644 --- a/mypy/typeshed/stdlib/base64.pyi +++ b/mypy/typeshed/stdlib/base64.pyi @@ -1,4 +1,5 @@ import sys +from _typeshed import ReadableBuffer from typing import IO if sys.version_info >= (3, 10): @@ -46,30 +47,30 @@ else: "urlsafe_b64decode", ] -def b64encode(s: bytes, altchars: bytes | None = ...) -> bytes: ... -def b64decode(s: str | bytes, altchars: bytes | None = ..., validate: bool = ...) -> bytes: ... -def standard_b64encode(s: bytes) -> bytes: ... -def standard_b64decode(s: str | bytes) -> bytes: ... -def urlsafe_b64encode(s: bytes) -> bytes: ... -def urlsafe_b64decode(s: str | bytes) -> bytes: ... -def b32encode(s: bytes) -> bytes: ... -def b32decode(s: str | bytes, casefold: bool = ..., map01: bytes | None = ...) -> bytes: ... -def b16encode(s: bytes) -> bytes: ... -def b16decode(s: str | bytes, casefold: bool = ...) -> bytes: ... +def b64encode(s: ReadableBuffer, altchars: ReadableBuffer | None = ...) -> bytes: ... +def b64decode(s: str | ReadableBuffer, altchars: ReadableBuffer | None = ..., validate: bool = ...) -> bytes: ... +def standard_b64encode(s: ReadableBuffer) -> bytes: ... +def standard_b64decode(s: str | ReadableBuffer) -> bytes: ... +def urlsafe_b64encode(s: ReadableBuffer) -> bytes: ... +def urlsafe_b64decode(s: str | ReadableBuffer) -> bytes: ... +def b32encode(s: ReadableBuffer) -> bytes: ... +def b32decode(s: str | ReadableBuffer, casefold: bool = ..., map01: bytes | None = ...) -> bytes: ... +def b16encode(s: ReadableBuffer) -> bytes: ... +def b16decode(s: str | ReadableBuffer, casefold: bool = ...) -> bytes: ... if sys.version_info >= (3, 10): - def b32hexencode(s: bytes) -> bytes: ... - def b32hexdecode(s: str | bytes, casefold: bool = ...) -> bytes: ... + def b32hexencode(s: ReadableBuffer) -> bytes: ... + def b32hexdecode(s: str | ReadableBuffer, casefold: bool = ...) -> bytes: ... -def a85encode(b: bytes, *, foldspaces: bool = ..., wrapcol: int = ..., pad: bool = ..., adobe: bool = ...) -> bytes: ... -def a85decode(b: str | bytes, *, foldspaces: bool = ..., adobe: bool = ..., ignorechars: str | bytes = ...) -> bytes: ... -def b85encode(b: bytes, pad: bool = ...) -> bytes: ... -def b85decode(b: str | bytes) -> bytes: ... +def a85encode(b: ReadableBuffer, *, foldspaces: bool = ..., wrapcol: int = ..., pad: bool = ..., adobe: bool = ...) -> bytes: ... +def a85decode(b: str | ReadableBuffer, *, foldspaces: bool = ..., adobe: bool = ..., ignorechars: str | bytes = ...) -> bytes: ... +def b85encode(b: ReadableBuffer, pad: bool = ...) -> bytes: ... +def b85decode(b: str | ReadableBuffer) -> bytes: ... def decode(input: IO[bytes], output: IO[bytes]) -> None: ... def encode(input: IO[bytes], output: IO[bytes]) -> None: ... -def encodebytes(s: bytes) -> bytes: ... -def decodebytes(s: bytes) -> bytes: ... +def encodebytes(s: ReadableBuffer) -> bytes: ... +def decodebytes(s: ReadableBuffer) -> bytes: ... if sys.version_info < (3, 9): - def encodestring(s: bytes) -> bytes: ... - def decodestring(s: bytes) -> bytes: ... + def encodestring(s: ReadableBuffer) -> bytes: ... + def decodestring(s: ReadableBuffer) -> bytes: ... diff --git a/mypy/typeshed/stdlib/builtins.pyi b/mypy/typeshed/stdlib/builtins.pyi index ce2042bcac631..9c5dfcfef22f6 100644 --- a/mypy/typeshed/stdlib/builtins.pyi +++ b/mypy/typeshed/stdlib/builtins.pyi @@ -52,7 +52,6 @@ from typing import ( SupportsInt, SupportsRound, TypeVar, - Union, overload, ) from typing_extensions import Literal, SupportsIndex, TypeGuard, final @@ -1747,19 +1746,45 @@ if sys.version_info >= (3, 10): class EncodingWarning(Warning): ... if sys.version_info >= (3, 11): - _SplitCondition = Union[type[BaseException], tuple[type[BaseException], ...], Callable[[BaseException], bool]] + _BaseExceptionT_co = TypeVar("_BaseExceptionT_co", bound=BaseException, covariant=True) + _BaseExceptionT = TypeVar("_BaseExceptionT", bound=BaseException) + _ExceptionT_co = TypeVar("_ExceptionT_co", bound=Exception, covariant=True) + _ExceptionT = TypeVar("_ExceptionT", bound=Exception) - class BaseExceptionGroup(BaseException): - def __new__(cls: type[Self], __message: str, __exceptions: Sequence[BaseException]) -> Self: ... + class BaseExceptionGroup(BaseException, Generic[_BaseExceptionT_co]): + def __new__(cls: type[Self], __message: str, __exceptions: Sequence[_BaseExceptionT_co]) -> Self: ... @property def message(self) -> str: ... @property - def exceptions(self) -> tuple[BaseException, ...]: ... - def subgroup(self: Self, __condition: _SplitCondition) -> Self | None: ... - def split(self: Self, __condition: _SplitCondition) -> tuple[Self | None, Self | None]: ... - def derive(self: Self, __excs: Sequence[BaseException]) -> Self: ... + def exceptions(self) -> tuple[_BaseExceptionT_co | BaseExceptionGroup[_BaseExceptionT_co], ...]: ... + @overload + def subgroup( + self, __condition: type[_BaseExceptionT] | tuple[type[_BaseExceptionT], ...] + ) -> BaseExceptionGroup[_BaseExceptionT] | None: ... + @overload + def subgroup(self: Self, __condition: Callable[[_BaseExceptionT_co], bool]) -> Self | None: ... + @overload + def split( + self: Self, __condition: type[_BaseExceptionT] | tuple[type[_BaseExceptionT], ...] + ) -> tuple[BaseExceptionGroup[_BaseExceptionT] | None, Self | None]: ... + @overload + def split(self: Self, __condition: Callable[[_BaseExceptionT_co], bool]) -> tuple[Self | None, Self | None]: ... + def derive(self: Self, __excs: Sequence[_BaseExceptionT_co]) -> Self: ... - class ExceptionGroup(BaseExceptionGroup, Exception): - def __new__(cls: type[Self], __message: str, __exceptions: Sequence[Exception]) -> Self: ... + class ExceptionGroup(BaseExceptionGroup[_ExceptionT_co], Exception): + def __new__(cls: type[Self], __message: str, __exceptions: Sequence[_ExceptionT_co]) -> Self: ... @property - def exceptions(self) -> tuple[Exception, ...]: ... + def exceptions(self) -> tuple[_ExceptionT_co | ExceptionGroup[_ExceptionT_co], ...]: ... + # We accept a narrower type, but that's OK. + @overload # type: ignore[override] + def subgroup( + self, __condition: type[_ExceptionT] | tuple[type[_ExceptionT], ...] + ) -> ExceptionGroup[_ExceptionT] | None: ... + @overload + def subgroup(self: Self, __condition: Callable[[_ExceptionT_co], bool]) -> Self | None: ... + @overload # type: ignore[override] + def split( + self: Self, __condition: type[_ExceptionT] | tuple[type[_ExceptionT], ...] + ) -> tuple[ExceptionGroup[_ExceptionT] | None, Self | None]: ... + @overload + def split(self: Self, __condition: Callable[[_ExceptionT_co], bool]) -> tuple[Self | None, Self | None]: ... diff --git a/mypy/typeshed/stdlib/calendar.pyi b/mypy/typeshed/stdlib/calendar.pyi index 05ceca4a3ae02..f106eb1213f19 100644 --- a/mypy/typeshed/stdlib/calendar.pyi +++ b/mypy/typeshed/stdlib/calendar.pyi @@ -4,32 +4,67 @@ from collections.abc import Iterable, Sequence from time import struct_time from typing_extensions import Literal -__all__ = [ - "IllegalMonthError", - "IllegalWeekdayError", - "setfirstweekday", - "firstweekday", - "isleap", - "leapdays", - "weekday", - "monthrange", - "monthcalendar", - "prmonth", - "month", - "prcal", - "calendar", - "timegm", - "month_name", - "month_abbr", - "day_name", - "day_abbr", - "Calendar", - "TextCalendar", - "HTMLCalendar", - "LocaleTextCalendar", - "LocaleHTMLCalendar", - "weekheader", -] +if sys.version_info >= (3, 10): + __all__ = [ + "IllegalMonthError", + "IllegalWeekdayError", + "setfirstweekday", + "firstweekday", + "isleap", + "leapdays", + "weekday", + "monthrange", + "monthcalendar", + "prmonth", + "month", + "prcal", + "calendar", + "timegm", + "month_name", + "month_abbr", + "day_name", + "day_abbr", + "Calendar", + "TextCalendar", + "HTMLCalendar", + "LocaleTextCalendar", + "LocaleHTMLCalendar", + "weekheader", + "FRIDAY", + "MONDAY", + "SATURDAY", + "SUNDAY", + "THURSDAY", + "TUESDAY", + "WEDNESDAY", + ] +else: + __all__ = [ + "IllegalMonthError", + "IllegalWeekdayError", + "setfirstweekday", + "firstweekday", + "isleap", + "leapdays", + "weekday", + "monthrange", + "monthcalendar", + "prmonth", + "month", + "prcal", + "calendar", + "timegm", + "month_name", + "month_abbr", + "day_name", + "day_abbr", + "Calendar", + "TextCalendar", + "HTMLCalendar", + "LocaleTextCalendar", + "LocaleHTMLCalendar", + "weekheader", + ] _LocaleType = tuple[str | None, str | None] diff --git a/mypy/typeshed/stdlib/datetime.pyi b/mypy/typeshed/stdlib/datetime.pyi index 18a4d2dd28567..220e07e25fe01 100644 --- a/mypy/typeshed/stdlib/datetime.pyi +++ b/mypy/typeshed/stdlib/datetime.pyi @@ -65,12 +65,7 @@ class date: def isoformat(self) -> str: ... def timetuple(self) -> struct_time: ... def toordinal(self) -> int: ... - if sys.version_info >= (3, 6): - def replace(self: Self, year: int = ..., month: int = ..., day: int = ...) -> Self: ... - else: - # Prior to Python 3.6, the `replace` method always returned `date`, even in subclasses - def replace(self, year: int = ..., month: int = ..., day: int = ...) -> date: ... - + def replace(self: Self, year: int = ..., month: int = ..., day: int = ...) -> Self: ... def __le__(self, __other: date) -> bool: ... def __lt__(self, __other: date) -> bool: ... def __ge__(self, __other: date) -> bool: ... @@ -144,29 +139,16 @@ class time: def utcoffset(self) -> timedelta | None: ... def tzname(self) -> str | None: ... def dst(self) -> timedelta | None: ... - if sys.version_info >= (3, 6): - def replace( - self: Self, - hour: int = ..., - minute: int = ..., - second: int = ..., - microsecond: int = ..., - tzinfo: _tzinfo | None = ..., - *, - fold: int = ..., - ) -> Self: ... - else: - # Prior to Python 3.6, the `replace` method always returned `time`, even in subclasses - def replace( - self, - hour: int = ..., - minute: int = ..., - second: int = ..., - microsecond: int = ..., - tzinfo: _tzinfo | None = ..., - *, - fold: int = ..., - ) -> time: ... + def replace( + self: Self, + hour: int = ..., + minute: int = ..., + second: int = ..., + microsecond: int = ..., + tzinfo: _tzinfo | None = ..., + *, + fold: int = ..., + ) -> Self: ... _date = date _time = time @@ -278,35 +260,19 @@ class datetime(date): def date(self) -> _date: ... def time(self) -> _time: ... def timetz(self) -> _time: ... - if sys.version_info >= (3, 6): - def replace( - self: Self, - year: int = ..., - month: int = ..., - day: int = ..., - hour: int = ..., - minute: int = ..., - second: int = ..., - microsecond: int = ..., - tzinfo: _tzinfo | None = ..., - *, - fold: int = ..., - ) -> Self: ... - else: - # Prior to Python 3.6, the `replace` method always returned `datetime`, even in subclasses - def replace( - self, - year: int = ..., - month: int = ..., - day: int = ..., - hour: int = ..., - minute: int = ..., - second: int = ..., - microsecond: int = ..., - tzinfo: _tzinfo | None = ..., - *, - fold: int = ..., - ) -> datetime: ... + def replace( + self: Self, + year: int = ..., + month: int = ..., + day: int = ..., + hour: int = ..., + minute: int = ..., + second: int = ..., + microsecond: int = ..., + tzinfo: _tzinfo | None = ..., + *, + fold: int = ..., + ) -> Self: ... if sys.version_info >= (3, 8): def astimezone(self: Self, tz: _tzinfo | None = ...) -> Self: ... else: diff --git a/mypy/typeshed/stdlib/linecache.pyi b/mypy/typeshed/stdlib/linecache.pyi index 6b3761f4a0c94..d72d678b5e186 100644 --- a/mypy/typeshed/stdlib/linecache.pyi +++ b/mypy/typeshed/stdlib/linecache.pyi @@ -7,7 +7,7 @@ else: __all__ = ["getline", "clearcache", "checkcache"] _ModuleGlobals = dict[str, Any] -_ModuleMetadata = tuple[int, float, list[str], str] +_ModuleMetadata = tuple[int, float | None, list[str], str] class _SourceLoader(Protocol): def __call__(self) -> str | None: ... diff --git a/mypy/typeshed/stdlib/poplib.pyi b/mypy/typeshed/stdlib/poplib.pyi index 111e5c4ca76ab..6b651e98e41f6 100644 --- a/mypy/typeshed/stdlib/poplib.pyi +++ b/mypy/typeshed/stdlib/poplib.pyi @@ -1,13 +1,9 @@ import socket import ssl -import sys from typing import Any, BinaryIO, NoReturn, Pattern, overload from typing_extensions import Literal -if sys.version_info >= (3, 10): - __all__ = ["POP3", "error_proto", "POP3_SSL"] -else: - __all__ = ["POP3", "error_proto"] +__all__ = ["POP3", "error_proto", "POP3_SSL"] _LongResp = tuple[bytes, list[bytes], int] diff --git a/mypy/typeshed/stdlib/tty.pyi b/mypy/typeshed/stdlib/tty.pyi index 63f594a8fbb14..08c93f6f2e847 100644 --- a/mypy/typeshed/stdlib/tty.pyi +++ b/mypy/typeshed/stdlib/tty.pyi @@ -2,6 +2,8 @@ import sys from typing import IO if sys.platform != "win32": + __all__ = ["setraw", "setcbreak"] + _FD = int | IO[str] # XXX: Undocumented integer constants diff --git a/mypy/typeshed/stdlib/typing_extensions.pyi b/mypy/typeshed/stdlib/typing_extensions.pyi index 892218f682837..70f395446b0b3 100644 --- a/mypy/typeshed/stdlib/typing_extensions.pyi +++ b/mypy/typeshed/stdlib/typing_extensions.pyi @@ -30,6 +30,57 @@ from typing import ( # noqa: Y022,Y027 overload as overload, ) +__all__ = [ + "ClassVar", + "Concatenate", + "Final", + "LiteralString", + "ParamSpec", + "Self", + "Type", + "TypeVarTuple", + "Unpack", + "Awaitable", + "AsyncIterator", + "AsyncIterable", + "Coroutine", + "AsyncGenerator", + "AsyncContextManager", + "ChainMap", + "ContextManager", + "Counter", + "Deque", + "DefaultDict", + "OrderedDict", + "TypedDict", + "SupportsIndex", + "Annotated", + "assert_never", + "assert_type", + "dataclass_transform", + "final", + "IntVar", + "is_typeddict", + "Literal", + "NewType", + "overload", + "Protocol", + "reveal_type", + "runtime", + "runtime_checkable", + "Text", + "TypeAlias", + "TypeGuard", + "TYPE_CHECKING", + "Never", + "NoReturn", + "Required", + "NotRequired", + "get_args", + "get_origin", + "get_type_hints", +] + _T = TypeVar("_T") _F = TypeVar("_F", bound=Callable[..., Any]) _TC = TypeVar("_TC", bound=Type[object]) @@ -82,15 +133,14 @@ TypedDict: object OrderedDict = _Alias() -if sys.version_info >= (3, 7): - def get_type_hints( - obj: Callable[..., Any], - globalns: dict[str, Any] | None = ..., - localns: dict[str, Any] | None = ..., - include_extras: bool = ..., - ) -> dict[str, Any]: ... - def get_args(tp: Any) -> tuple[Any, ...]: ... - def get_origin(tp: Any) -> Any | None: ... +def get_type_hints( + obj: Callable[..., Any], + globalns: dict[str, Any] | None = ..., + localns: dict[str, Any] | None = ..., + include_extras: bool = ..., +) -> dict[str, Any]: ... +def get_args(tp: Any) -> tuple[Any, ...]: ... +def get_origin(tp: Any) -> Any | None: ... Annotated: _SpecialForm _AnnotatedAlias: Any # undocumented @@ -137,12 +187,19 @@ else: # New things in 3.11 if sys.version_info >= (3, 11): - from typing import Never as Never, Self as Self, assert_never as assert_never, reveal_type as reveal_type + from typing import ( + Never as Never, + Self as Self, + assert_never as assert_never, + assert_type as assert_type, + reveal_type as reveal_type, + ) else: Self: _SpecialForm Never: _SpecialForm def reveal_type(__obj: _T) -> _T: ... def assert_never(__arg: NoReturn) -> NoReturn: ... + def assert_type(__val: _T, __typ: Any) -> _T: ... # Experimental (hopefully these will be in 3.11) Required: _SpecialForm From 10ba5c1aa14e01be1cfacb322136e22751617d26 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Sat, 16 Apr 2022 16:37:25 +0100 Subject: [PATCH 236/377] Docs: Use PEP 585 syntax in "The type of class objects" (#12516) --- docs/source/kinds_of_types.rst | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/source/kinds_of_types.rst b/docs/source/kinds_of_types.rst index dd19d7fc06220..51f54ab0e1e6b 100644 --- a/docs/source/kinds_of_types.rst +++ b/docs/source/kinds_of_types.rst @@ -615,10 +615,11 @@ The type of class objects <484#the-type-of-class-objects>`.) Sometimes you want to talk about class objects that inherit from a -given class. This can be spelled as :py:class:`Type[C] ` where ``C`` is a +given class. This can be spelled as ``type[C]`` (or, on Python 3.8 and lower, +:py:class:`typing.Type[C] `) where ``C`` is a class. In other words, when ``C`` is the name of a class, using ``C`` to annotate an argument declares that the argument is an instance of -``C`` (or of a subclass of ``C``), but using :py:class:`Type[C] ` as an +``C`` (or of a subclass of ``C``), but using ``type[C]`` as an argument annotation declares that the argument is a class object deriving from ``C`` (or ``C`` itself). @@ -649,7 +650,7 @@ you pass it the right class object: # (Here we could write the user object to a database) return user -How would we annotate this function? Without :py:class:`~typing.Type` the best we +How would we annotate this function? Without the ability to parameterize ``type``, the best we could do would be: .. code-block:: python @@ -665,14 +666,14 @@ doesn't see that the ``buyer`` variable has type ``ProUser``: buyer = new_user(ProUser) buyer.pay() # Rejected, not a method on User -However, using :py:class:`~typing.Type` and a type variable with an upper bound (see +However, using the ``type[C]`` syntax and a type variable with an upper bound (see :ref:`type-variable-upper-bound`) we can do better: .. code-block:: python U = TypeVar('U', bound=User) - def new_user(user_class: Type[U]) -> U: + def new_user(user_class: type[U]) -> U: # Same implementation as before Now mypy will infer the correct type of the result when we call @@ -685,12 +686,12 @@ Now mypy will infer the correct type of the result when we call .. note:: - The value corresponding to :py:class:`Type[C] ` must be an actual class + The value corresponding to ``type[C]`` must be an actual class object that's a subtype of ``C``. Its constructor must be compatible with the constructor of ``C``. If ``C`` is a type variable, its upper bound must be a class object. -For more details about ``Type[]`` see :pep:`PEP 484: The type of +For more details about ``type[]`` and :py:class:`typing.Type[] `, see :pep:`PEP 484: The type of class objects <484#the-type-of-class-objects>`. .. _text-and-anystr: From 0df8cf532918f888610a5afd7bb88192712de984 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Sat, 16 Apr 2022 13:48:20 -0700 Subject: [PATCH 237/377] Support typing_extensions.overload (#12602) This always existed in typing_extensions, but was an alias for typing.overload. With python/typing#1140, it will actually make a difference at runtime which one you use. Note that this shouldn't change mypy's behaviour, since we alias typing_extensions.overload to typing.overload in typeshed, but this makes the logic less fragile. --- mypy/checker.py | 5 +- mypy/semanal.py | 4 +- mypy/stubgen.py | 23 +++--- mypy/stubtest.py | 3 +- mypy/types.py | 5 ++ test-data/unit/check-overloading.test | 18 +++++ test-data/unit/lib-stub/typing_extensions.pyi | 2 +- test-data/unit/stubgen.test | 79 ++++++++++++++++++- 8 files changed, 122 insertions(+), 17 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index e53e306a7e5d0..24f101421ff46 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -37,7 +37,8 @@ UnionType, TypeVarId, TypeVarType, PartialType, DeletedType, UninhabitedType, is_named_instance, union_items, TypeQuery, LiteralType, is_optional, remove_optional, TypeTranslator, StarType, get_proper_type, ProperType, - get_proper_types, is_literal_type, TypeAliasType, TypeGuardedType, ParamSpecType + get_proper_types, is_literal_type, TypeAliasType, TypeGuardedType, ParamSpecType, + OVERLOAD_NAMES, ) from mypy.sametypes import is_same_type from mypy.messages import ( @@ -3981,7 +3982,7 @@ def visit_decorator(self, e: Decorator) -> None: # may be different from the declared signature. sig: Type = self.function_type(e.func) for d in reversed(e.decorators): - if refers_to_fullname(d, 'typing.overload'): + if refers_to_fullname(d, OVERLOAD_NAMES): self.fail(message_registry.MULTIPLE_OVERLOADS_REQUIRED, e) continue dec = self.expr_checker.accept(d) diff --git a/mypy/semanal.py b/mypy/semanal.py index 3ffc20cead773..1ec37309ce8e6 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -99,7 +99,7 @@ TypeTranslator, TypeOfAny, TypeType, NoneType, PlaceholderType, TPDICT_NAMES, ProperType, get_proper_type, get_proper_types, TypeAliasType, TypeVarLikeType, Parameters, ParamSpecType, PROTOCOL_NAMES, TYPE_ALIAS_NAMES, FINAL_TYPE_NAMES, FINAL_DECORATOR_NAMES, REVEAL_TYPE_NAMES, - ASSERT_TYPE_NAMES, is_named_instance, + ASSERT_TYPE_NAMES, OVERLOAD_NAMES, is_named_instance, ) from mypy.typeops import function_type, get_type_vars from mypy.type_visitor import TypeQuery @@ -835,7 +835,7 @@ def analyze_overload_sigs_and_impl( if isinstance(item, Decorator): callable = function_type(item.func, self.named_type('builtins.function')) assert isinstance(callable, CallableType) - if not any(refers_to_fullname(dec, 'typing.overload') + if not any(refers_to_fullname(dec, OVERLOAD_NAMES) for dec in item.decorators): if i == len(defn.items) - 1 and not self.is_stub_file: # Last item outside a stub is impl diff --git a/mypy/stubgen.py b/mypy/stubgen.py index 5d8e6a57c2121..eade0bbdc363a 100755 --- a/mypy/stubgen.py +++ b/mypy/stubgen.py @@ -54,7 +54,7 @@ from collections import defaultdict from typing import ( - List, Dict, Tuple, Iterable, Mapping, Optional, Set, cast, + List, Dict, Tuple, Iterable, Mapping, Optional, Set, Union, cast, ) from typing_extensions import Final @@ -84,7 +84,7 @@ from mypy.options import Options as MypyOptions from mypy.types import ( Type, TypeStrVisitor, CallableType, UnboundType, NoneType, TupleType, TypeList, Instance, - AnyType, get_proper_type + AnyType, get_proper_type, OVERLOAD_NAMES ) from mypy.visitor import NodeVisitor from mypy.find_sources import create_source_list, InvalidSourceList @@ -93,6 +93,10 @@ from mypy.traverser import all_yield_expressions, has_return_statement, has_yield_expression from mypy.moduleinspect import ModuleInspect +TYPING_MODULE_NAMES: Final = ( + 'typing', + 'typing_extensions', +) # Common ways of naming package containing vendored modules. VENDOR_PACKAGES: Final = [ @@ -768,13 +772,15 @@ def process_name_expr_decorator(self, expr: NameExpr, context: Decorator) -> Tup self.add_decorator('property') self.add_decorator('abc.abstractmethod') is_abstract = True - elif self.refers_to_fullname(name, 'typing.overload'): + elif self.refers_to_fullname(name, OVERLOAD_NAMES): self.add_decorator(name) self.add_typing_import('overload') is_overload = True return is_abstract, is_overload - def refers_to_fullname(self, name: str, fullname: str) -> bool: + def refers_to_fullname(self, name: str, fullname: Union[str, Tuple[str, ...]]) -> bool: + if isinstance(fullname, tuple): + return any(self.refers_to_fullname(name, fname) for fname in fullname) module, short = fullname.rsplit('.', 1) return (self.import_tracker.module_for.get(name) == module and (name == short or @@ -825,8 +831,8 @@ def process_member_expr_decorator(self, expr: MemberExpr, context: Decorator) -> expr.expr.name + '.coroutine', expr.expr.name) elif (isinstance(expr.expr, NameExpr) and - (expr.expr.name == 'typing' or - self.import_tracker.reverse_alias.get(expr.expr.name) == 'typing') and + (expr.expr.name in TYPING_MODULE_NAMES or + self.import_tracker.reverse_alias.get(expr.expr.name) in TYPING_MODULE_NAMES) and expr.name == 'overload'): self.import_tracker.require_name(expr.expr.name) self.add_decorator('%s.%s' % (expr.expr.name, 'overload')) @@ -1060,7 +1066,7 @@ def visit_import_from(self, o: ImportFrom) -> None: and name not in self.referenced_names and (not self._all_ or name in IGNORED_DUNDERS) and not is_private - and module not in ('abc', 'typing', 'asyncio')): + and module not in ('abc', 'asyncio') + TYPING_MODULE_NAMES): # An imported name that is never referenced in the module is assumed to be # exported, unless there is an explicit __all__. Note that we need to special # case 'abc' since some references are deleted during semantic analysis. @@ -1118,8 +1124,7 @@ def get_init(self, lvalue: str, rvalue: Expression, typename = self.print_annotation(annotation) if (isinstance(annotation, UnboundType) and not annotation.args and annotation.name == 'Final' and - self.import_tracker.module_for.get('Final') in ('typing', - 'typing_extensions')): + self.import_tracker.module_for.get('Final') in TYPING_MODULE_NAMES): # Final without type argument is invalid in stubs. final_arg = self.get_str_type_of_node(rvalue) typename += '[{}]'.format(final_arg) diff --git a/mypy/stubtest.py b/mypy/stubtest.py index 582c467ee2b01..7fa0f5937f99a 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -912,9 +912,8 @@ def apply_decorator_to_funcitem( return None if decorator.fullname in ( "builtins.staticmethod", - "typing.overload", "abc.abstractmethod", - ): + ) or decorator.fullname in mypy.types.OVERLOAD_NAMES: return func if decorator.fullname == "builtins.classmethod": assert func.arguments[0].variable.name in ("cls", "metacls") diff --git a/mypy/types.py b/mypy/types.py index 1d0274f38330e..213d8de7d8bb9 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -137,6 +137,11 @@ 'typing_extensions.assert_type', ) +OVERLOAD_NAMES: Final = ( + 'typing.overload', + 'typing_extensions.overload', +) + # Attributes that can optionally be defined in the body of a subclass of # enum.Enum but are removed from the class __dict__ by EnumMeta. ENUM_REMOVED_PROPS: Final = ( diff --git a/test-data/unit/check-overloading.test b/test-data/unit/check-overloading.test index 0376b62ab2027..e2a87ea62a929 100644 --- a/test-data/unit/check-overloading.test +++ b/test-data/unit/check-overloading.test @@ -40,6 +40,24 @@ class A: pass class B: pass [builtins fixtures/isinstance.pyi] +[case testTypingExtensionsOverload] +from typing import Any +from typing_extensions import overload +@overload +def f(x: 'A') -> 'B': ... +@overload +def f(x: 'B') -> 'A': ... + +def f(x: Any) -> Any: + pass + +reveal_type(f(A())) # N: Revealed type is "__main__.B" +reveal_type(f(B())) # N: Revealed type is "__main__.A" + +class A: pass +class B: pass +[builtins fixtures/isinstance.pyi] + [case testOverloadNeedsImplementation] from typing import overload, Any @overload # E: An overloaded function outside a stub file must have an implementation diff --git a/test-data/unit/lib-stub/typing_extensions.pyi b/test-data/unit/lib-stub/typing_extensions.pyi index 7ad334d6a24eb..95f45f3b8947c 100644 --- a/test-data/unit/lib-stub/typing_extensions.pyi +++ b/test-data/unit/lib-stub/typing_extensions.pyi @@ -1,6 +1,6 @@ from typing import TypeVar, Any, Mapping, Iterator, NoReturn as NoReturn, Dict, Type from typing import TYPE_CHECKING as TYPE_CHECKING -from typing import NewType as NewType +from typing import NewType as NewType, overload as overload import sys diff --git a/test-data/unit/stubgen.test b/test-data/unit/stubgen.test index cbce46b356059..927cc5617c756 100644 --- a/test-data/unit/stubgen.test +++ b/test-data/unit/stubgen.test @@ -2461,6 +2461,50 @@ class A: def f(self, x: Tuple[int, int]) -> int: ... +@overload +def f(x: int, y: int) -> int: ... +@overload +def f(x: Tuple[int, int]) -> int: ... + +[case testOverload_fromTypingExtensionsImport] +from typing import Tuple, Union +from typing_extensions import overload + +class A: + @overload + def f(self, x: int, y: int) -> int: + ... + + @overload + def f(self, x: Tuple[int, int]) -> int: + ... + + def f(self, *args: Union[int, Tuple[int, int]]) -> int: + pass + +@overload +def f(x: int, y: int) -> int: + ... + +@overload +def f(x: Tuple[int, int]) -> int: + ... + +def f(*args: Union[int, Tuple[int, int]]) -> int: + pass + + +[out] +from typing import Tuple +from typing_extensions import overload + +class A: + @overload + def f(self, x: int, y: int) -> int: ... + @overload + def f(self, x: Tuple[int, int]) -> int: ... + + @overload def f(x: int, y: int) -> int: ... @overload @@ -2468,6 +2512,7 @@ def f(x: Tuple[int, int]) -> int: ... [case testOverload_importTyping] import typing +import typing_extensions class A: @typing.overload @@ -2506,9 +2551,21 @@ def f(x: typing.Tuple[int, int]) -> int: def f(*args: typing.Union[int, typing.Tuple[int, int]]) -> int: pass +@typing_extensions.overload +def g(x: int, y: int) -> int: + ... + +@typing_extensions.overload +def g(x: typing.Tuple[int, int]) -> int: + ... + +def g(*args: typing.Union[int, typing.Tuple[int, int]]) -> int: + pass + [out] import typing +import typing_extensions class A: @typing.overload @@ -2527,10 +2584,14 @@ class A: def f(x: int, y: int) -> int: ... @typing.overload def f(x: typing.Tuple[int, int]) -> int: ... - +@typing_extensions.overload +def g(x: int, y: int) -> int: ... +@typing_extensions.overload +def g(x: typing.Tuple[int, int]) -> int: ... [case testOverload_importTypingAs] import typing as t +import typing_extensions as te class A: @t.overload @@ -2570,8 +2631,20 @@ def f(*args: t.Union[int, t.Tuple[int, int]]) -> int: pass +@te.overload +def g(x: int, y: int) -> int: + ... + +@te.overload +def g(x: t.Tuple[int, int]) -> int: + ... + +def g(*args: t.Union[int, t.Tuple[int, int]]) -> int: + pass + [out] import typing as t +import typing_extensions as te class A: @t.overload @@ -2590,6 +2663,10 @@ class A: def f(x: int, y: int) -> int: ... @t.overload def f(x: t.Tuple[int, int]) -> int: ... +@te.overload +def g(x: int, y: int) -> int: ... +@te.overload +def g(x: t.Tuple[int, int]) -> int: ... [case testProtocol_semanal] from typing import Protocol, TypeVar From f501cf649d7976077a7196e3548d773d67340a8c Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Sun, 17 Apr 2022 18:07:56 -0700 Subject: [PATCH 238/377] Fix type context for assert_type() (#12612) Noticed in python/typeshed#7655 that it was incorrectly inferring list[Any] in all cases. This is because I incorrectly put Any as the type context in the assert_type implementation. Use the current context instead, like for reveal_type(). --- mypy/checkexpr.py | 2 +- test-data/unit/check-expressions.test | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 32fa391bb0e2d..7383a2b696104 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -3145,7 +3145,7 @@ def visit_cast_expr(self, expr: CastExpr) -> Type: return target_type def visit_assert_type_expr(self, expr: AssertTypeExpr) -> Type: - source_type = self.accept(expr.expr, type_context=AnyType(TypeOfAny.special_form), + source_type = self.accept(expr.expr, type_context=self.type_context[-1], allow_none_return=True, always_allow_any=True) target_type = expr.type if not is_same_type(source_type, target_type): diff --git a/test-data/unit/check-expressions.test b/test-data/unit/check-expressions.test index 84b6105170bd1..fd10b82cc5585 100644 --- a/test-data/unit/check-expressions.test +++ b/test-data/unit/check-expressions.test @@ -1049,6 +1049,20 @@ assert_type(a, Any) # E: Expression is of type "int", not "Any" assert_type(a, Literal[1]) # E: Expression is of type "int", not "Literal[1]" [builtins fixtures/tuple.pyi] +[case testAssertTypeGeneric] +from typing import assert_type, TypeVar, Generic +from typing_extensions import Literal +T = TypeVar("T") +def f(x: T) -> T: return x +assert_type(f(1), int) +class Gen(Generic[T]): + def __new__(cls, obj: T) -> Gen[T]: ... +assert_type(Gen(1), Gen[int]) +# With type context, it infers Gen[Literal[1]] instead. +y: Gen[Literal[1]] = assert_type(Gen(1), Gen[Literal[1]]) + +[builtins fixtures/tuple.pyi] + -- None return type -- ---------------- From 9cab2964a186d7e71567a1528fcc956f9eecebac Mon Sep 17 00:00:00 2001 From: Hugues Date: Mon, 18 Apr 2022 07:54:02 -0700 Subject: [PATCH 239/377] more enum-related speedups (#12032) As a followup to #9394 address a few more O(n**2) behaviors caused by decomposing enums into unions of literals. --- mypy/meet.py | 30 ++++++++++++++++++++++++ mypy/sametypes.py | 34 ++++++++++++++++++++++----- mypy/subtypes.py | 59 +++++++++++++++++++++++++++++++++++++++-------- mypy/typeops.py | 9 ++++++++ 4 files changed, 116 insertions(+), 16 deletions(-) diff --git a/mypy/meet.py b/mypy/meet.py index 535e48bc3a23a..5ee64416490d6 100644 --- a/mypy/meet.py +++ b/mypy/meet.py @@ -64,6 +64,8 @@ def narrow_declared_type(declared: Type, narrowed: Type) -> Type: if isinstance(declared, UnionType): return make_simplified_union([narrow_declared_type(x, narrowed) for x in declared.relevant_items()]) + if is_enum_overlapping_union(declared, narrowed): + return narrowed elif not is_overlapping_types(declared, narrowed, prohibit_none_typevar_overlap=True): if state.strict_optional: @@ -137,6 +139,22 @@ def get_possible_variants(typ: Type) -> List[Type]: return [typ] +def is_enum_overlapping_union(x: ProperType, y: ProperType) -> bool: + """Return True if x is an Enum, and y is an Union with at least one Literal from x""" + return ( + isinstance(x, Instance) and x.type.is_enum and + isinstance(y, UnionType) and + any(isinstance(p, LiteralType) and x.type == p.fallback.type + for p in (get_proper_type(z) for z in y.relevant_items())) + ) + + +def is_literal_in_union(x: ProperType, y: ProperType) -> bool: + """Return True if x is a Literal and y is an Union that includes x""" + return (isinstance(x, LiteralType) and isinstance(y, UnionType) and + any(x == get_proper_type(z) for z in y.items)) + + def is_overlapping_types(left: Type, right: Type, ignore_promotions: bool = False, @@ -198,6 +216,18 @@ def _is_overlapping_types(left: Type, right: Type) -> bool: # # These checks will also handle the NoneType and UninhabitedType cases for us. + # enums are sometimes expanded into an Union of Literals + # when that happens we want to make sure we treat the two as overlapping + # and crucially, we want to do that *fast* in case the enum is large + # so we do it before expanding variants below to avoid O(n**2) behavior + if ( + is_enum_overlapping_union(left, right) + or is_enum_overlapping_union(right, left) + or is_literal_in_union(left, right) + or is_literal_in_union(right, left) + ): + return True + if (is_proper_subtype(left, right, ignore_promotions=ignore_promotions) or is_proper_subtype(right, left, ignore_promotions=ignore_promotions)): return True diff --git a/mypy/sametypes.py b/mypy/sametypes.py index 46798018410d2..1c22c32f8b064 100644 --- a/mypy/sametypes.py +++ b/mypy/sametypes.py @@ -1,4 +1,4 @@ -from typing import Sequence +from typing import Sequence, Tuple, Set, List from mypy.types import ( Type, UnboundType, AnyType, NoneType, TupleType, TypedDictType, @@ -6,7 +6,7 @@ Overloaded, PartialType, DeletedType, UninhabitedType, TypeType, LiteralType, ProperType, get_proper_type, TypeAliasType, ParamSpecType, Parameters, UnpackType ) -from mypy.typeops import tuple_fallback, make_simplified_union +from mypy.typeops import tuple_fallback, make_simplified_union, is_simple_literal def is_same_type(left: Type, right: Type) -> bool: @@ -49,6 +49,22 @@ def is_same_types(a1: Sequence[Type], a2: Sequence[Type]) -> bool: return True +def _extract_literals(u: UnionType) -> Tuple[Set[Type], List[Type]]: + """Given a UnionType, separate out its items into a set of simple literals and a remainder list + This is a useful helper to avoid O(n**2) behavior when comparing large unions, which can often + result from large enums in contexts where type narrowing removes a small subset of entries. + """ + lit: Set[Type] = set() + rem: List[Type] = [] + for i in u.relevant_items(): + i = get_proper_type(i) + if is_simple_literal(i): + lit.add(i) + else: + rem.append(i) + return lit, rem + + class SameTypeVisitor(TypeVisitor[bool]): """Visitor for checking whether two types are the 'same' type.""" @@ -153,14 +169,20 @@ def visit_literal_type(self, left: LiteralType) -> bool: def visit_union_type(self, left: UnionType) -> bool: if isinstance(self.right, UnionType): + left_lit, left_rem = _extract_literals(left) + right_lit, right_rem = _extract_literals(self.right) + + if left_lit != right_lit: + return False + # Check that everything in left is in right - for left_item in left.items: - if not any(is_same_type(left_item, right_item) for right_item in self.right.items): + for left_item in left_rem: + if not any(is_same_type(left_item, right_item) for right_item in right_rem): return False # Check that everything in right is in left - for right_item in self.right.items: - if not any(is_same_type(right_item, left_item) for left_item in left.items): + for right_item in right_rem: + if not any(is_same_type(right_item, left_item) for left_item in left_rem): return False return True diff --git a/mypy/subtypes.py b/mypy/subtypes.py index af35821d7ef4d..d977a114bf2f2 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -535,6 +535,20 @@ def visit_overloaded(self, left: Overloaded) -> bool: return False def visit_union_type(self, left: UnionType) -> bool: + if isinstance(self.right, Instance): + literal_types: Set[Instance] = set() + # avoid redundant check for union of literals + for item in left.relevant_items(): + item = get_proper_type(item) + lit_type = mypy.typeops.simple_literal_type(item) + if lit_type is not None: + if lit_type in literal_types: + continue + literal_types.add(lit_type) + item = lit_type + if not self._is_subtype(item, self.orig_right): + return False + return True return all(self._is_subtype(item, self.orig_right) for item in left.items) def visit_partial_type(self, left: PartialType) -> bool: @@ -1199,6 +1213,27 @@ def report(*args: Any) -> None: return applied +def try_restrict_literal_union(t: UnionType, s: Type) -> Optional[List[Type]]: + """Return the items of t, excluding any occurrence of s, if and only if + - t only contains simple literals + - s is a simple literal + + Otherwise, returns None + """ + ps = get_proper_type(s) + if not mypy.typeops.is_simple_literal(ps): + return None + + new_items: List[Type] = [] + for i in t.relevant_items(): + pi = get_proper_type(i) + if not mypy.typeops.is_simple_literal(pi): + return None + if pi != ps: + new_items.append(i) + return new_items + + def restrict_subtype_away(t: Type, s: Type, *, ignore_promotions: bool = False) -> Type: """Return t minus s for runtime type assertions. @@ -1212,10 +1247,14 @@ def restrict_subtype_away(t: Type, s: Type, *, ignore_promotions: bool = False) s = get_proper_type(s) if isinstance(t, UnionType): - new_items = [restrict_subtype_away(item, s, ignore_promotions=ignore_promotions) - for item in t.relevant_items() - if (isinstance(get_proper_type(item), AnyType) or - not covers_at_runtime(item, s, ignore_promotions))] + new_items = try_restrict_literal_union(t, s) + if new_items is None: + new_items = [ + restrict_subtype_away(item, s, ignore_promotions=ignore_promotions) + for item in t.relevant_items() + if (isinstance(get_proper_type(item), AnyType) or + not covers_at_runtime(item, s, ignore_promotions)) + ] return UnionType.make_union(new_items) elif covers_at_runtime(t, s, ignore_promotions): return UninhabitedType() @@ -1285,11 +1324,11 @@ def _is_proper_subtype(left: Type, right: Type, *, right = get_proper_type(right) if isinstance(right, UnionType) and not isinstance(left, UnionType): - return any([is_proper_subtype(orig_left, item, - ignore_promotions=ignore_promotions, - erase_instances=erase_instances, - keep_erased_types=keep_erased_types) - for item in right.items]) + return any(is_proper_subtype(orig_left, item, + ignore_promotions=ignore_promotions, + erase_instances=erase_instances, + keep_erased_types=keep_erased_types) + for item in right.items) return left.accept(ProperSubtypeVisitor(orig_right, ignore_promotions=ignore_promotions, erase_instances=erase_instances, @@ -1495,7 +1534,7 @@ def visit_overloaded(self, left: Overloaded) -> bool: return False def visit_union_type(self, left: UnionType) -> bool: - return all([self._is_proper_subtype(item, self.orig_right) for item in left.items]) + return all(self._is_proper_subtype(item, self.orig_right) for item in left.items) def visit_partial_type(self, left: PartialType) -> bool: # TODO: What's the right thing to do here? diff --git a/mypy/typeops.py b/mypy/typeops.py index bb5d8c291b124..9eb2c9bee18f4 100644 --- a/mypy/typeops.py +++ b/mypy/typeops.py @@ -318,6 +318,15 @@ def simple_literal_value_key(t: ProperType) -> Optional[Tuple[str, ...]]: return None +def simple_literal_type(t: ProperType) -> Optional[Instance]: + """Extract the underlying fallback Instance type for a simple Literal""" + if isinstance(t, Instance) and t.last_known_value is not None: + t = t.last_known_value + if isinstance(t, LiteralType): + return t.fallback + return None + + def is_simple_literal(t: ProperType) -> bool: """Fast way to check if simple_literal_value_key() would return a non-None value.""" if isinstance(t, LiteralType): From 9e9de71cc7d896829f503f6a35171d906eeef5da Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Mon, 18 Apr 2022 21:26:41 +0100 Subject: [PATCH 240/377] stubtest: error if type alias doesn't exist at runtime (#12608) Co-authored-by: hauntsaninja <> Co-authored-by: Shantanu <12621235+hauntsaninja@users.noreply.github.com> --- mypy/stubtest.py | 7 +++++-- mypy/test/teststubtest.py | 12 ++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/mypy/stubtest.py b/mypy/stubtest.py index 7fa0f5937f99a..d3bc40bc27e8a 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -955,10 +955,13 @@ def verify_decorator( def verify_typealias( stub: nodes.TypeAlias, runtime: MaybeMissing[Any], object_path: List[str] ) -> Iterator[Error]: + stub_target = mypy.types.get_proper_type(stub.target) if isinstance(runtime, Missing): - # ignore type aliases that don't have a runtime counterpart + yield Error( + object_path, "is not present at runtime", stub, runtime, + stub_desc=f"Type alias for: {stub_target}" + ) return - stub_target = mypy.types.get_proper_type(stub.target) if isinstance(stub_target, mypy.types.Instance): yield from verify(stub_target.type, runtime, object_path) return diff --git a/mypy/test/teststubtest.py b/mypy/test/teststubtest.py index 1cdcd34c666c8..869d2e110a66b 100644 --- a/mypy/test/teststubtest.py +++ b/mypy/test/teststubtest.py @@ -712,6 +712,18 @@ class Y: ... runtime="A = (int, str)", error="A", ) + # Error if an alias isn't present at runtime... + yield Case( + stub="B = str", + runtime="", + error="B" + ) + # ... but only if the alias isn't private + yield Case( + stub="_C = int", + runtime="", + error=None + ) @collect_cases def test_enum(self) -> Iterator[Case]: From cf6a48c865cc5aff23b08e651f41e1bf7b397f98 Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Tue, 19 Apr 2022 04:36:20 +0200 Subject: [PATCH 241/377] Fix nested overload merging (#12607) Closes #12606 --- mypy/fastparse.py | 69 +++++++++---- test-data/unit/check-overloading.test | 139 ++++++++++++++++++++++++++ 2 files changed, 190 insertions(+), 18 deletions(-) diff --git a/mypy/fastparse.py b/mypy/fastparse.py index 077d287655fbe..0b3322db2af3d 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -496,18 +496,9 @@ def fix_function_overloads(self, stmts: List[Statement]) -> List[Statement]: if_overload_name: Optional[str] = None if_block_with_overload: Optional[Block] = None if_unknown_truth_value: Optional[IfStmt] = None - if ( - isinstance(stmt, IfStmt) - and len(stmt.body[0].body) == 1 - and seen_unconditional_func_def is False - and ( - isinstance(stmt.body[0].body[0], (Decorator, OverloadedFuncDef)) - or current_overload_name is not None - and isinstance(stmt.body[0].body[0], FuncDef) - ) - ): + if isinstance(stmt, IfStmt) and seen_unconditional_func_def is False: # Check IfStmt block to determine if function overloads can be merged - if_overload_name = self._check_ifstmt_for_overloads(stmt) + if_overload_name = self._check_ifstmt_for_overloads(stmt, current_overload_name) if if_overload_name is not None: if_block_with_overload, if_unknown_truth_value = \ self._get_executable_if_block_with_overloads(stmt) @@ -553,8 +544,11 @@ def fix_function_overloads(self, stmts: List[Statement]) -> List[Statement]: else: current_overload.append(last_if_overload) last_if_stmt, last_if_overload = None, None - if isinstance(if_block_with_overload.body[0], OverloadedFuncDef): - current_overload.extend(if_block_with_overload.body[0].items) + if isinstance(if_block_with_overload.body[-1], OverloadedFuncDef): + skipped_if_stmts.extend( + cast(List[IfStmt], if_block_with_overload.body[:-1]) + ) + current_overload.extend(if_block_with_overload.body[-1].items) else: current_overload.append( cast(Union[Decorator, FuncDef], if_block_with_overload.body[0]) @@ -600,9 +594,12 @@ def fix_function_overloads(self, stmts: List[Statement]) -> List[Statement]: last_if_stmt = stmt last_if_stmt_overload_name = None if if_block_with_overload is not None: + skipped_if_stmts.extend( + cast(List[IfStmt], if_block_with_overload.body[:-1]) + ) last_if_overload = cast( Union[Decorator, FuncDef, OverloadedFuncDef], - if_block_with_overload.body[0] + if_block_with_overload.body[-1] ) last_if_unknown_truth_value = if_unknown_truth_value else: @@ -620,11 +617,15 @@ def fix_function_overloads(self, stmts: List[Statement]) -> List[Statement]: ret.append(current_overload[0]) elif len(current_overload) > 1: ret.append(OverloadedFuncDef(current_overload)) + elif last_if_overload is not None: + ret.append(last_if_overload) elif last_if_stmt is not None: ret.append(last_if_stmt) return ret - def _check_ifstmt_for_overloads(self, stmt: IfStmt) -> Optional[str]: + def _check_ifstmt_for_overloads( + self, stmt: IfStmt, current_overload_name: Optional[str] = None + ) -> Optional[str]: """Check if IfStmt contains only overloads with the same name. Return overload_name if found, None otherwise. """ @@ -632,11 +633,22 @@ def _check_ifstmt_for_overloads(self, stmt: IfStmt) -> Optional[str]: # Multiple overloads have already been merged as OverloadedFuncDef. if not ( len(stmt.body[0].body) == 1 - and isinstance(stmt.body[0].body[0], (Decorator, FuncDef, OverloadedFuncDef)) + and ( + isinstance(stmt.body[0].body[0], (Decorator, OverloadedFuncDef)) + or current_overload_name is not None + and isinstance(stmt.body[0].body[0], FuncDef) + ) + or len(stmt.body[0].body) > 1 + and isinstance(stmt.body[0].body[-1], OverloadedFuncDef) + and all( + self._is_stripped_if_stmt(if_stmt) + for if_stmt in stmt.body[0].body[:-1] + ) ): return None - overload_name = stmt.body[0].body[0].name + overload_name = cast( + Union[Decorator, FuncDef, OverloadedFuncDef], stmt.body[0].body[-1]).name if stmt.else_body is None: return overload_name @@ -649,7 +661,9 @@ def _check_ifstmt_for_overloads(self, stmt: IfStmt) -> Optional[str]: return overload_name if ( isinstance(stmt.else_body.body[0], IfStmt) - and self._check_ifstmt_for_overloads(stmt.else_body.body[0]) == overload_name + and self._check_ifstmt_for_overloads( + stmt.else_body.body[0], current_overload_name + ) == overload_name ): return overload_name @@ -704,6 +718,25 @@ def _strip_contents_from_if_stmt(self, stmt: IfStmt) -> None: else: stmt.else_body.body = [] + def _is_stripped_if_stmt(self, stmt: Statement) -> bool: + """Check stmt to make sure it is a stripped IfStmt. + + See also: _strip_contents_from_if_stmt + """ + if not isinstance(stmt, IfStmt): + return False + + if not (len(stmt.body) == 1 and len(stmt.body[0].body) == 0): + # Body not empty + return False + + if not stmt.else_body or len(stmt.else_body.body) == 0: + # No or empty else_body + return True + + # For elif, IfStmt are stored recursively in else_body + return self._is_stripped_if_stmt(stmt.else_body.body[0]) + def in_method_scope(self) -> bool: return self.class_and_function_stack[-2:] == ['C', 'F'] diff --git a/test-data/unit/check-overloading.test b/test-data/unit/check-overloading.test index e2a87ea62a929..8259f2754bce8 100644 --- a/test-data/unit/check-overloading.test +++ b/test-data/unit/check-overloading.test @@ -6367,3 +6367,142 @@ def g(x: int) -> str: ... def g(x: int = 0) -> int: # E: Overloaded function implementation cannot produce return type of signature 2 return x + +[case testOverloadIfNestedOk] +# flags: --always-true True --always-false False +from typing import overload + +class A: ... +class B: ... +class C: ... +class D: ... + +@overload +def f1(g: A) -> A: ... +if True: + @overload + def f1(g: B) -> B: ... + if True: + @overload + def f1(g: C) -> C: ... + @overload + def f1(g: D) -> D: ... +def f1(g): ... +reveal_type(f1(A())) # N: Revealed type is "__main__.A" +reveal_type(f1(B())) # N: Revealed type is "__main__.B" +reveal_type(f1(C())) # N: Revealed type is "__main__.C" +reveal_type(f1(D())) # N: Revealed type is "__main__.D" + +@overload +def f2(g: A) -> A: ... +if True: + @overload + def f2(g: B) -> B: ... + if True: + @overload + def f2(g: C) -> C: ... + if True: + @overload + def f2(g: D) -> D: ... +def f2(g): ... +reveal_type(f2(A())) # N: Revealed type is "__main__.A" +reveal_type(f2(B())) # N: Revealed type is "__main__.B" +reveal_type(f2(C())) # N: Revealed type is "__main__.C" +reveal_type(f2(D())) # N: Revealed type is "__main__.D" + +@overload +def f3(g: A) -> A: ... +if True: + if True: + @overload + def f3(g: B) -> B: ... + if True: + @overload + def f3(g: C) -> C: ... +def f3(g): ... +reveal_type(f3(A())) # N: Revealed type is "__main__.A" +reveal_type(f3(B())) # N: Revealed type is "__main__.B" +reveal_type(f3(C())) # N: Revealed type is "__main__.C" + +@overload +def f4(g: A) -> A: ... +if True: + if False: + @overload + def f4(g: B) -> B: ... + else: + @overload + def f4(g: C) -> C: ... +def f4(g): ... +reveal_type(f4(A())) # N: Revealed type is "__main__.A" +reveal_type(f4(B())) # E: No overload variant of "f4" matches argument type "B" \ + # N: Possible overload variants: \ + # N: def f4(g: A) -> A \ + # N: def f4(g: C) -> C \ + # N: Revealed type is "Any" +reveal_type(f4(C())) # N: Revealed type is "__main__.C" + +@overload +def f5(g: A) -> A: ... +if True: + if False: + @overload + def f5(g: B) -> B: ... + elif True: + @overload + def f5(g: C) -> C: ... +def f5(g): ... +reveal_type(f5(A())) # N: Revealed type is "__main__.A" +reveal_type(f5(B())) # E: No overload variant of "f5" matches argument type "B" \ + # N: Possible overload variants: \ + # N: def f5(g: A) -> A \ + # N: def f5(g: C) -> C \ + # N: Revealed type is "Any" +reveal_type(f5(C())) # N: Revealed type is "__main__.C" + +[case testOverloadIfNestedFailure] +# flags: --always-true True --always-false False +from typing import overload + +class A: ... +class B: ... +class C: ... +class D: ... + +@overload # E: Single overload definition, multiple required +def f1(g: A) -> A: ... +if True: + @overload # E: Single overload definition, multiple required + def f1(g: B) -> B: ... + if maybe_true: # E: Condition cannot be inferred, unable to merge overloads \ + # E: Name "maybe_true" is not defined + @overload + def f1(g: C) -> C: ... + @overload + def f1(g: D) -> D: ... +def f1(g): ... # E: Name "f1" already defined on line 9 + +@overload # E: Single overload definition, multiple required +def f2(g: A) -> A: ... +if True: + if False: + @overload + def f2(g: B) -> B: ... + elif maybe_true: # E: Name "maybe_true" is not defined + @overload # E: Single overload definition, multiple required + def f2(g: C) -> C: ... +def f2(g): ... # E: Name "f2" already defined on line 21 + +@overload # E: Single overload definition, multiple required +def f3(g: A) -> A: ... +if True: + @overload # E: Single overload definition, multiple required + def f3(g: B) -> B: ... + if True: + pass # Some other node + @overload # E: Name "f3" already defined on line 32 \ + # E: An overloaded function outside a stub file must have an implementation + def f3(g: C) -> C: ... + @overload + def f3(g: D) -> D: ... +def f3(g): ... # E: Name "f3" already defined on line 32 From 20b0b9b460cd11a4755f70ae08823fa6a8f5fbd4 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Tue, 19 Apr 2022 11:50:25 +0100 Subject: [PATCH 242/377] Use class name as namespace for type variables (#12590) This avoids confusion between type variables of two classes, which can happen at least in some edge cases. Type variables are only the same if both the numeric id and namespace match (plus meta level). Fixes #12588 (though the textual presentation of type variables doesn't take the namespace into consideration yet). --- mypy/checkpattern.py | 3 +-- mypy/semanal.py | 3 ++- mypy/tvar_scope.py | 15 ++++++++++----- mypy/types.py | 16 +++++++++++---- test-data/unit/check-selftype.test | 31 +++++++++++++++++++++++++++++- 5 files changed, 55 insertions(+), 13 deletions(-) diff --git a/mypy/checkpattern.py b/mypy/checkpattern.py index 0fedec24cc372..e1d4f9fe285e7 100644 --- a/mypy/checkpattern.py +++ b/mypy/checkpattern.py @@ -396,8 +396,7 @@ def visit_mapping_pattern(self, o: MappingPattern) -> PatternType: if is_subtype(current_type, mapping) and isinstance(current_type, Instance): mapping_inst = map_instance_to_supertype(current_type, mapping.type) dict_typeinfo = self.chk.lookup_typeinfo("builtins.dict") - dict_type = fill_typevars(dict_typeinfo) - rest_type = expand_type_by_instance(dict_type, mapping_inst) + rest_type = Instance(dict_typeinfo, mapping_inst.args) else: object_type = self.chk.named_type("builtins.object") rest_type = self.chk.named_generic_type("builtins.dict", diff --git a/mypy/semanal.py b/mypy/semanal.py index 1ec37309ce8e6..5b6b7ebd78c0d 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -1116,7 +1116,8 @@ def check_decorated_function_is_method(self, decorator: str, def visit_class_def(self, defn: ClassDef) -> None: self.statement = defn self.incomplete_type_stack.append(not defn.info) - with self.tvar_scope_frame(self.tvar_scope.class_frame()): + namespace = self.qualified_name(defn.name) + with self.tvar_scope_frame(self.tvar_scope.class_frame(namespace)): self.analyze_class(defn) self.incomplete_type_stack.pop() diff --git a/mypy/tvar_scope.py b/mypy/tvar_scope.py index 0d8be7845e525..ac82a7708f0e8 100644 --- a/mypy/tvar_scope.py +++ b/mypy/tvar_scope.py @@ -1,5 +1,5 @@ from typing import Optional, Dict, Union -from mypy.types import TypeVarLikeType, TypeVarType, ParamSpecType, ParamSpecFlavor +from mypy.types import TypeVarLikeType, TypeVarType, ParamSpecType, ParamSpecFlavor, TypeVarId from mypy.nodes import ParamSpecExpr, TypeVarExpr, TypeVarLikeExpr, SymbolTableNode @@ -12,7 +12,8 @@ class TypeVarLikeScope: def __init__(self, parent: 'Optional[TypeVarLikeScope]' = None, is_class_scope: bool = False, - prohibited: 'Optional[TypeVarLikeScope]' = None) -> None: + prohibited: 'Optional[TypeVarLikeScope]' = None, + namespace: str = '') -> None: """Initializer for TypeVarLikeScope Parameters: @@ -27,6 +28,7 @@ def __init__(self, self.class_id = 0 self.is_class_scope = is_class_scope self.prohibited = prohibited + self.namespace = namespace if parent is not None: self.func_id = parent.func_id self.class_id = parent.class_id @@ -51,22 +53,25 @@ def method_frame(self) -> 'TypeVarLikeScope': """A new scope frame for binding a method""" return TypeVarLikeScope(self, False, None) - def class_frame(self) -> 'TypeVarLikeScope': + def class_frame(self, namespace: str) -> 'TypeVarLikeScope': """A new scope frame for binding a class. Prohibits *this* class's tvars""" - return TypeVarLikeScope(self.get_function_scope(), True, self) + return TypeVarLikeScope(self.get_function_scope(), True, self, namespace=namespace) def bind_new(self, name: str, tvar_expr: TypeVarLikeExpr) -> TypeVarLikeType: if self.is_class_scope: self.class_id += 1 i = self.class_id + namespace = self.namespace else: self.func_id -= 1 i = self.func_id + # TODO: Consider also using namespaces for functions + namespace = '' if isinstance(tvar_expr, TypeVarExpr): tvar_def: TypeVarLikeType = TypeVarType( name, tvar_expr.fullname, - i, + TypeVarId(i, namespace=namespace), values=tvar_expr.values, upper_bound=tvar_expr.upper_bound, variance=tvar_expr.variance, diff --git a/mypy/types.py b/mypy/types.py index 213d8de7d8bb9..49e0aa1d85ecf 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -426,9 +426,15 @@ class TypeVarId: # Class variable used for allocating fresh ids for metavariables. next_raw_id: ClassVar[int] = 1 - def __init__(self, raw_id: int, meta_level: int = 0) -> None: + # Fullname of class (or potentially function in the future) which + # declares this type variable (not the fullname of the TypeVar + # definition!), or '' + namespace: str + + def __init__(self, raw_id: int, meta_level: int = 0, *, namespace: str = '') -> None: self.raw_id = raw_id self.meta_level = meta_level + self.namespace = namespace @staticmethod def new(meta_level: int) -> 'TypeVarId': @@ -442,7 +448,8 @@ def __repr__(self) -> str: def __eq__(self, other: object) -> bool: if isinstance(other, TypeVarId): return (self.raw_id == other.raw_id and - self.meta_level == other.meta_level) + self.meta_level == other.meta_level and + self.namespace == other.namespace) else: return False @@ -450,7 +457,7 @@ def __ne__(self, other: object) -> bool: return not (self == other) def __hash__(self) -> int: - return hash((self.raw_id, self.meta_level)) + return hash((self.raw_id, self.meta_level, self.namespace)) def is_meta_var(self) -> bool: return self.meta_level > 0 @@ -524,6 +531,7 @@ def serialize(self) -> JsonDict: 'name': self.name, 'fullname': self.fullname, 'id': self.id.raw_id, + 'namespace': self.id.namespace, 'values': [v.serialize() for v in self.values], 'upper_bound': self.upper_bound.serialize(), 'variance': self.variance, @@ -535,7 +543,7 @@ def deserialize(cls, data: JsonDict) -> 'TypeVarType': return TypeVarType( data['name'], data['fullname'], - data['id'], + TypeVarId(data['id'], namespace=data['namespace']), [deserialize_type(v) for v in data['values']], deserialize_type(data['upper_bound']), data['variance'], diff --git a/test-data/unit/check-selftype.test b/test-data/unit/check-selftype.test index b59c22dfae062..085c522c3013b 100644 --- a/test-data/unit/check-selftype.test +++ b/test-data/unit/check-selftype.test @@ -893,11 +893,14 @@ from typing import Generic, TypeVar, Tuple T = TypeVar('T') S = TypeVar('S') U = TypeVar('U') +V = TypeVar('V') class C(Generic[T]): def magic(self: C[Tuple[S, U]]) -> Tuple[T, S, U]: ... -reveal_type(C[Tuple[int, str]]().magic()) # N: Revealed type is "Tuple[Tuple[builtins.int, builtins.str], builtins.int, builtins.str]" +class D(Generic[V]): + def f(self) -> None: + reveal_type(C[Tuple[V, str]]().magic()) # N: Revealed type is "Tuple[Tuple[V`1, builtins.str], V`1, builtins.str]" [builtins fixtures/tuple.pyi] [case testSelfTypeOnUnion] @@ -1167,3 +1170,29 @@ def build_wrapper_non_gen(descriptor: Descriptor[int]) -> BaseWrapper[str]: def build_sub_wrapper_non_gen(descriptor: Descriptor[int]) -> SubWrapper[str]: return SubWrapper.create_wrapper(descriptor) # E: Argument 1 to "create_wrapper" of "BaseWrapper" has incompatible type "Descriptor[int]"; expected "Descriptor[str]" [builtins fixtures/classmethod.pyi] + +[case testSelfTypeInGenericClassUsedFromAnotherGenericClass1] +from typing import TypeVar, Generic, Iterator, List, Tuple + +_T_co = TypeVar("_T_co", covariant=True) +_T1 = TypeVar("_T1") +_T2 = TypeVar("_T2") +S = TypeVar("S") + +class Z(Iterator[_T_co]): + def __new__(cls, + __iter1: List[_T1], + __iter2: List[_T2]) -> Z[Tuple[_T1, _T2]]: ... + def __iter__(self: S) -> S: ... + def __next__(self) -> _T_co: ... + +T = TypeVar('T') + +class C(Generic[T]): + a: List[T] + b: List[str] + + def f(self) -> None: + for x, y in Z(self.a, self.b): + reveal_type((x, y)) # N: Revealed type is "Tuple[T`1, builtins.str]" +[builtins fixtures/tuple.pyi] From cf146f4b5a578597ea5d81a31476fbf5b6a2ef62 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Tue, 19 Apr 2022 21:00:37 +0100 Subject: [PATCH 243/377] Add test case for recently fixed `enumerate` regression (#12627) --- test-data/unit/check-selftype.test | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test-data/unit/check-selftype.test b/test-data/unit/check-selftype.test index 085c522c3013b..ef3d5289ddfd1 100644 --- a/test-data/unit/check-selftype.test +++ b/test-data/unit/check-selftype.test @@ -1196,3 +1196,27 @@ class C(Generic[T]): for x, y in Z(self.a, self.b): reveal_type((x, y)) # N: Revealed type is "Tuple[T`1, builtins.str]" [builtins fixtures/tuple.pyi] + +[case testEnumerateReturningSelfFromIter] +from typing import Generic, Iterable, Iterator, TypeVar, Tuple + +T = TypeVar("T") +KT = TypeVar("KT") +VT = TypeVar("VT") +Self = TypeVar("Self") + +class enumerate(Iterator[Tuple[int, T]], Generic[T]): + def __init__(self, iterable: Iterable[T]) -> None: ... + def __iter__(self: Self) -> Self: ... + def __next__(self) -> Tuple[int, T]: ... + +class Dict(Generic[KT, VT]): + def update(self, __m: Iterable[Tuple[KT, VT]]) -> None: ... + +class ThingCollection(Generic[T]): + collection: Iterable[Tuple[float, T]] + index: Dict[int, T] + + def do_thing(self) -> None: + self.index.update((idx, c) for idx, (k, c) in enumerate(self.collection)) +[builtins fixtures/tuple.pyi] From 0bcca591b49cbc9349d55ba4d38b85f9bc222566 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Wed, 20 Apr 2022 09:11:30 +0100 Subject: [PATCH 244/377] Add overlapping type variables test case (#12623) This was originally written by @A5rocks in #11657. Related to #12590. --- test-data/unit/check-generics.test | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test-data/unit/check-generics.test b/test-data/unit/check-generics.test index 9c5f3a332dab5..6a89f6fb200c2 100644 --- a/test-data/unit/check-generics.test +++ b/test-data/unit/check-generics.test @@ -2504,3 +2504,23 @@ b: I[I[Any]] reveal_type([a, b]) # N: Revealed type is "builtins.list[__main__.I[__main__.I[Any]]]" reveal_type([b, a]) # N: Revealed type is "builtins.list[__main__.I[__main__.I[Any]]]" [builtins fixtures/list.pyi] + +[case testOverlappingTypeVarIds] +from typing import TypeVar, Generic + +class A: ... +class B: ... + +T = TypeVar("T", bound=A) +V = TypeVar("V", bound=B) +S = TypeVar("S") + +class Whatever(Generic[T]): + def something(self: S) -> S: + return self + +# the "V" here had the same id as "T" and so mypy used to think it could expand one into another. +# this test is here to make sure that doesn't happen! +class WhateverPartTwo(Whatever[A], Generic[V]): + def something(self: S) -> S: + return self From 8b1a8109796c0a32d02de147d3371d381593fbe0 Mon Sep 17 00:00:00 2001 From: Hugues Date: Wed, 20 Apr 2022 04:47:33 -0700 Subject: [PATCH 245/377] make_simplified_union: simpler and faster (#12630) Recent attempts at speedup introduced some convoluted logic that both reduced accuracy and caused performance regressions. Fix this and add more comments to clarify the reasoning behind the optimization. --- mypy/typeops.py | 47 ++++++++++++++++++++++------------------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/mypy/typeops.py b/mypy/typeops.py index 9eb2c9bee18f4..e9127aee0060f 100644 --- a/mypy/typeops.py +++ b/mypy/typeops.py @@ -410,26 +410,29 @@ def _remove_redundant_union_items(items: List[ProperType], keep_erased: bool) -> # Keep track of the truishness info for deleted subtypes which can be relevant cbt = cbf = False - num_items = len(items) for j, tj in enumerate(items): - if i != j: - # NB: The first check below is an optimization to - # avoid very expensive computations with large - # unions involving literals. We approximate the - # results for unions with many items. This is - # "fine" since simplifying these union items is - # (almost) always optional. - if ( - (num_items < 5 - or is_likely_literal_supertype(item) - or not is_simple_literal(tj)) - and is_proper_subtype(tj, item, keep_erased_types=keep_erased) - and is_redundant_literal_instance(item, tj) # XXX? - ): - # We found a redundant item in the union. - removed.add(j) - cbt = cbt or tj.can_be_true - cbf = cbf or tj.can_be_false + if ( + i == j + # avoid further checks if this item was already marked redundant. + or j in removed + # if the current item is a simple literal then this simplification loop can + # safely skip all other simple literals as two literals will only ever be + # subtypes of each other if they are equal, which is already handled above. + # However, if the current item is not a literal, it might plausibly be a + # supertype of other literals in the union, so we must check them again. + # This is an important optimization as is_proper_subtype is pretty expensive. + or (k is not None and is_simple_literal(tj)) + ): + continue + # actual redundancy checks + if ( + is_redundant_literal_instance(item, tj) # XXX? + and is_proper_subtype(tj, item, keep_erased_types=keep_erased) + ): + # We found a redundant item in the union. + removed.add(j) + cbt = cbt or tj.can_be_true + cbf = cbf or tj.can_be_false # if deleted subtypes had more general truthiness, use that if not item.can_be_true and cbt: items[i] = true_or_false(item) @@ -439,12 +442,6 @@ def _remove_redundant_union_items(items: List[ProperType], keep_erased: bool) -> return [items[i] for i in range(len(items)) if i not in removed] -def is_likely_literal_supertype(t: ProperType) -> bool: - """Is the type likely to cause simplification of literal types in unions?""" - return isinstance(t, Instance) and t.type.fullname in ('builtins.object', - 'builtins.str') - - def _get_type_special_method_bool_ret_type(t: Type) -> Optional[Type]: t = get_proper_type(t) From 50213b520b131fc1dd037dfcc1938beba1f4e177 Mon Sep 17 00:00:00 2001 From: jhance Date: Wed, 20 Apr 2022 12:56:02 -0700 Subject: [PATCH 246/377] Add TypeVarTupleExpr node (#12481) This adds minimal support for a TypeVarTupleExpr node, gated behind the flag to enable incomplete features. It is modeled after paramspec, including the part where we don't support the various arguments that have no behavior defined in PEP646. We also include TypeVarTuple in the typing_extensions stubs for test data and add some very basic semanal tests to verify the basic things work. --- mypy/checkexpr.py | 5 ++- mypy/literals.py | 5 ++- mypy/nodes.py | 33 ++++++++++++++- mypy/semanal.py | 41 ++++++++++++++++++- mypy/strconv.py | 12 ++++++ mypy/test/testtransform.py | 5 ++- mypy/treetransform.py | 7 +++- mypy/visitor.py | 7 ++++ mypyc/irbuild/visitor.py | 5 ++- test-data/unit/lib-stub/typing_extensions.pyi | 1 + test-data/unit/semanal-errors.test | 10 +++++ test-data/unit/semanal-types.test | 10 +++++ 12 files changed, 134 insertions(+), 7 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 7383a2b696104..c6f4d24c1815f 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -32,7 +32,7 @@ DictionaryComprehension, ComplexExpr, EllipsisExpr, StarExpr, AwaitExpr, YieldExpr, YieldFromExpr, TypedDictExpr, PromoteExpr, NewTypeExpr, NamedTupleExpr, TypeVarExpr, TypeAliasExpr, BackquoteExpr, EnumCallExpr, TypeAlias, SymbolNode, PlaceholderNode, - ParamSpecExpr, + ParamSpecExpr, TypeVarTupleExpr, ArgKind, ARG_POS, ARG_NAMED, ARG_STAR, ARG_STAR2, LITERAL_TYPE, REVEAL_TYPE, ) from mypy.literals import literal @@ -4186,6 +4186,9 @@ def visit_type_var_expr(self, e: TypeVarExpr) -> Type: def visit_paramspec_expr(self, e: ParamSpecExpr) -> Type: return AnyType(TypeOfAny.special_form) + def visit_type_var_tuple_expr(self, e: TypeVarTupleExpr) -> Type: + return AnyType(TypeOfAny.special_form) + def visit_newtype_expr(self, e: NewTypeExpr) -> Type: return AnyType(TypeOfAny.special_form) diff --git a/mypy/literals.py b/mypy/literals.py index b11c07d91a915..e20e37412ab27 100644 --- a/mypy/literals.py +++ b/mypy/literals.py @@ -9,7 +9,7 @@ TypeApplication, LambdaExpr, ListComprehension, SetComprehension, DictionaryComprehension, GeneratorExpr, BackquoteExpr, TypeVarExpr, TypeAliasExpr, NamedTupleExpr, EnumCallExpr, TypedDictExpr, NewTypeExpr, PromoteExpr, AwaitExpr, TempNode, AssignmentExpr, ParamSpecExpr, - AssertTypeExpr, + AssertTypeExpr, TypeVarTupleExpr, ) from mypy.visitor import ExpressionVisitor @@ -224,6 +224,9 @@ def visit_type_var_expr(self, e: TypeVarExpr) -> None: def visit_paramspec_expr(self, e: ParamSpecExpr) -> None: return None + def visit_type_var_tuple_expr(self, e: TypeVarTupleExpr) -> None: + return None + def visit_type_alias_expr(self, e: TypeAliasExpr) -> None: return None diff --git a/mypy/nodes.py b/mypy/nodes.py index 30bb2c6aa10a0..f25d3abab7bc3 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -2233,7 +2233,10 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: class TypeVarLikeExpr(SymbolNode, Expression): - """Base class for TypeVarExpr and ParamSpecExpr.""" + """Base class for TypeVarExpr, ParamSpecExpr and TypeVarTupleExpr. + + Note that they are constructed by the semantic analyzer. + """ __slots__ = ('_name', '_fullname', 'upper_bound', 'variance') @@ -2339,6 +2342,34 @@ def deserialize(cls, data: JsonDict) -> 'ParamSpecExpr': ) +class TypeVarTupleExpr(TypeVarLikeExpr): + """Type variable tuple expression TypeVarTuple(...).""" + + __slots__ = () + + def accept(self, visitor: ExpressionVisitor[T]) -> T: + return visitor.visit_type_var_tuple_expr(self) + + def serialize(self) -> JsonDict: + return { + '.class': 'TypeVarTupleExpr', + 'name': self._name, + 'fullname': self._fullname, + 'upper_bound': self.upper_bound.serialize(), + 'variance': self.variance, + } + + @classmethod + def deserialize(cls, data: JsonDict) -> 'TypeVarTupleExpr': + assert data['.class'] == 'TypeVarTupleExpr' + return TypeVarTupleExpr( + data['name'], + data['fullname'], + mypy.types.deserialize_type(data['upper_bound']), + data['variance'] + ) + + class TypeAliasExpr(Expression): """Type alias expression (rvalue).""" diff --git a/mypy/semanal.py b/mypy/semanal.py index 5b6b7ebd78c0d..985d5217cc08a 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -78,7 +78,7 @@ typing_extensions_aliases, EnumCallExpr, RUNTIME_PROTOCOL_DECOS, FakeExpression, Statement, AssignmentExpr, ParamSpecExpr, EllipsisExpr, TypeVarLikeExpr, implicit_module_attrs, - MatchStmt, FuncBase + MatchStmt, FuncBase, TypeVarTupleExpr ) from mypy.patterns import ( AsPattern, OrPattern, ValuePattern, SequencePattern, @@ -2074,6 +2074,8 @@ def visit_assignment_stmt(self, s: AssignmentStmt) -> None: special_form = True elif self.process_paramspec_declaration(s): special_form = True + elif self.process_typevartuple_declaration(s): + special_form = True # * type constructors elif self.analyze_namedtuple_assign(s): special_form = True @@ -3332,6 +3334,43 @@ def process_paramspec_declaration(self, s: AssignmentStmt) -> bool: self.add_symbol(name, call.analyzed, s) return True + def process_typevartuple_declaration(self, s: AssignmentStmt) -> bool: + """Checks if s declares a TypeVarTuple; if yes, store it in symbol table. + + Return True if this looks like a TypeVarTuple (maybe with errors), otherwise return False. + """ + call = self.get_typevarlike_declaration( + s, ("typing_extensions.TypeVarTuple", "typing.TypeVarTuple") + ) + if not call: + return False + + if len(call.args) > 1: + self.fail( + "Only the first argument to TypeVarTuple has defined semantics", + s, + ) + + if not self.options.enable_incomplete_features: + self.fail('"TypeVarTuple" is not supported by mypy yet', s) + return False + + name = self.extract_typevarlike_name(s, call) + if name is None: + return False + + # PEP 646 does not specify the behavior of variance, constraints, or bounds. + if not call.analyzed: + typevartuple_var = TypeVarTupleExpr( + name, self.qualified_name(name), self.object_type(), INVARIANT + ) + typevartuple_var.line = call.line + call.analyzed = typevartuple_var + else: + assert isinstance(call.analyzed, TypeVarTupleExpr) + self.add_symbol(name, call.analyzed, s) + return True + def basic_new_typeinfo(self, name: str, basetype_or_fallback: Instance, line: int) -> TypeInfo: diff --git a/mypy/strconv.py b/mypy/strconv.py index 46ac4b10363cc..1a08423b41648 100644 --- a/mypy/strconv.py +++ b/mypy/strconv.py @@ -496,6 +496,18 @@ def visit_paramspec_expr(self, o: 'mypy.nodes.ParamSpecExpr') -> str: a += ['UpperBound({})'.format(o.upper_bound)] return self.dump(a, o) + def visit_type_var_tuple_expr(self, o: 'mypy.nodes.TypeVarTupleExpr') -> str: + import mypy.types + + a: List[Any] = [] + if o.variance == mypy.nodes.COVARIANT: + a += ['Variance(COVARIANT)'] + if o.variance == mypy.nodes.CONTRAVARIANT: + a += ['Variance(CONTRAVARIANT)'] + if not mypy.types.is_named_instance(o.upper_bound, 'builtins.object'): + a += ['UpperBound({})'.format(o.upper_bound)] + return self.dump(a, o) + def visit_type_alias_expr(self, o: 'mypy.nodes.TypeAliasExpr') -> str: return 'TypeAliasExpr({})'.format(o.type) diff --git a/mypy/test/testtransform.py b/mypy/test/testtransform.py index d884fe9137ab4..e1e3b6ab63ed5 100644 --- a/mypy/test/testtransform.py +++ b/mypy/test/testtransform.py @@ -38,6 +38,7 @@ def test_transform(testcase: DataDrivenTestCase) -> None: options = parse_options(src, testcase, 1) options.use_builtins_fixtures = True options.semantic_analysis_only = True + options.enable_incomplete_features = True options.show_traceback = True result = build.build(sources=[BuildSource('main', None, src)], options=options, @@ -54,8 +55,10 @@ def test_transform(testcase: DataDrivenTestCase) -> None: # path. # TODO the test is not reliable if (not f.path.endswith((os.sep + 'builtins.pyi', + 'typing_extensions.pyi', 'typing.pyi', - 'abc.pyi')) + 'abc.pyi', + 'sys.pyi')) and not os.path.basename(f.path).startswith('_') and not os.path.splitext( os.path.basename(f.path))[0].endswith('_')): diff --git a/mypy/treetransform.py b/mypy/treetransform.py index 62d5f6d72cbca..0bc72274354ad 100644 --- a/mypy/treetransform.py +++ b/mypy/treetransform.py @@ -20,7 +20,7 @@ YieldFromExpr, NamedTupleExpr, TypedDictExpr, NonlocalDecl, SetComprehension, DictionaryComprehension, ComplexExpr, TypeAliasExpr, EllipsisExpr, YieldExpr, ExecStmt, Argument, BackquoteExpr, AwaitExpr, AssignmentExpr, - OverloadPart, EnumCallExpr, REVEAL_TYPE, GDEF + OverloadPart, EnumCallExpr, REVEAL_TYPE, GDEF, TypeVarTupleExpr ) from mypy.types import Type, FunctionLike, ProperType from mypy.traverser import TraverserVisitor @@ -515,6 +515,11 @@ def visit_paramspec_expr(self, node: ParamSpecExpr) -> ParamSpecExpr: node.name, node.fullname, self.type(node.upper_bound), variance=node.variance ) + def visit_type_var_tuple_expr(self, node: TypeVarTupleExpr) -> TypeVarTupleExpr: + return TypeVarTupleExpr( + node.name, node.fullname, self.type(node.upper_bound), variance=node.variance + ) + def visit_type_alias_expr(self, node: TypeAliasExpr) -> TypeAliasExpr: return TypeAliasExpr(node.node) diff --git a/mypy/visitor.py b/mypy/visitor.py index 7339111c7a05e..94fde0b113191 100644 --- a/mypy/visitor.py +++ b/mypy/visitor.py @@ -165,6 +165,10 @@ def visit_type_var_expr(self, o: 'mypy.nodes.TypeVarExpr') -> T: def visit_paramspec_expr(self, o: 'mypy.nodes.ParamSpecExpr') -> T: pass + @abstractmethod + def visit_type_var_tuple_expr(self, o: 'mypy.nodes.TypeVarTupleExpr') -> T: + pass + @abstractmethod def visit_type_alias_expr(self, o: 'mypy.nodes.TypeAliasExpr') -> T: pass @@ -590,6 +594,9 @@ def visit_type_var_expr(self, o: 'mypy.nodes.TypeVarExpr') -> T: def visit_paramspec_expr(self, o: 'mypy.nodes.ParamSpecExpr') -> T: pass + def visit_type_var_tuple_expr(self, o: 'mypy.nodes.TypeVarTupleExpr') -> T: + pass + def visit_type_alias_expr(self, o: 'mypy.nodes.TypeAliasExpr') -> T: pass diff --git a/mypyc/irbuild/visitor.py b/mypyc/irbuild/visitor.py index 3a1883cca50bb..15ac08d9c9739 100644 --- a/mypyc/irbuild/visitor.py +++ b/mypyc/irbuild/visitor.py @@ -17,7 +17,7 @@ NamedTupleExpr, NewTypeExpr, NonlocalDecl, OverloadedFuncDef, PrintStmt, RaiseStmt, RevealExpr, SetExpr, SliceExpr, StarExpr, SuperExpr, TryStmt, TypeAliasExpr, TypeApplication, TypeVarExpr, TypedDictExpr, UnicodeExpr, WithStmt, YieldFromExpr, YieldExpr, ParamSpecExpr, - MatchStmt + MatchStmt, TypeVarTupleExpr ) from mypyc.ir.ops import Value @@ -315,6 +315,9 @@ def visit_type_var_expr(self, o: TypeVarExpr) -> Value: def visit_paramspec_expr(self, o: ParamSpecExpr) -> Value: assert False, "can't compile analysis-only expressions" + def visit_type_var_tuple_expr(self, o: TypeVarTupleExpr) -> Value: + assert False, "can't compile analysis-only expressions" + def visit_typeddict_expr(self, o: TypedDictExpr) -> Value: assert False, "can't compile analysis-only expressions" diff --git a/test-data/unit/lib-stub/typing_extensions.pyi b/test-data/unit/lib-stub/typing_extensions.pyi index 95f45f3b8947c..d4c3244cf0836 100644 --- a/test-data/unit/lib-stub/typing_extensions.pyi +++ b/test-data/unit/lib-stub/typing_extensions.pyi @@ -29,6 +29,7 @@ TypeAlias: _SpecialForm TypeGuard: _SpecialForm Never: _SpecialForm +TypeVarTuple: _SpecialForm Unpack: _SpecialForm # Fallback type for all typed dicts (does not exist at runtime). diff --git a/test-data/unit/semanal-errors.test b/test-data/unit/semanal-errors.test index ea937b8678f18..5a1c487721909 100644 --- a/test-data/unit/semanal-errors.test +++ b/test-data/unit/semanal-errors.test @@ -1460,3 +1460,13 @@ heterogenous_tuple: Tuple[Unpack[Tuple[int, str]]] homogenous_tuple: Tuple[Unpack[Tuple[int, ...]]] bad: Tuple[Unpack[int]] # E: builtins.int cannot be unpacked (must be tuple or TypeVarTuple) [builtins fixtures/tuple.pyi] + +[case testTypeVarTuple] +from typing_extensions import TypeVarTuple + +TVariadic = TypeVarTuple('TVariadic') +TP = TypeVarTuple('?') # E: String argument 1 "?" to TypeVarTuple(...) does not match variable name "TP" +TP2: int = TypeVarTuple('TP2') # E: Cannot declare the type of a TypeVar or similar construct +TP3 = TypeVarTuple() # E: Too few arguments for TypeVarTuple() +TP4 = TypeVarTuple('TP4', 'TP4') # E: Only the first argument to TypeVarTuple has defined semantics +TP5 = TypeVarTuple(t='TP5') # E: TypeVarTuple() expects a string literal as first argument diff --git a/test-data/unit/semanal-types.test b/test-data/unit/semanal-types.test index 3ce289b52ae24..f2cd737b1a6cd 100644 --- a/test-data/unit/semanal-types.test +++ b/test-data/unit/semanal-types.test @@ -1548,3 +1548,13 @@ MypyFile:1( AssignmentStmt:2( NameExpr(P* [__main__.P]) ParamSpecExpr:2())) + +[case testTypeVarTuple] +from typing_extensions import TypeVarTuple +TV = TypeVarTuple("TV") +[out] +MypyFile:1( + ImportFrom:1(typing_extensions, [TypeVarTuple]) + AssignmentStmt:2( + NameExpr(TV* [__main__.TV]) + TypeVarTupleExpr:2())) From c56046c5d963b501b69cb76221189aa4cf5ccbac Mon Sep 17 00:00:00 2001 From: 97littleleaf11 <11172084+97littleleaf11@users.noreply.github.com> Date: Thu, 21 Apr 2022 13:27:38 +0800 Subject: [PATCH 247/377] Fix typos (#12635) Improve docs and fix typos --- mypy/typeops.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/mypy/typeops.py b/mypy/typeops.py index e9127aee0060f..dbfeebe42f14d 100644 --- a/mypy/typeops.py +++ b/mypy/typeops.py @@ -107,7 +107,7 @@ def class_callable(init_type: CallableType, info: TypeInfo, type_type: Instance, explicit_type = init_ret_type if is_new else orig_self_type if ( isinstance(explicit_type, (Instance, TupleType)) - # We have to skip protocols, because it can can be a subtype of a return type + # We have to skip protocols, because it can be a subtype of a return type # by accident. Like `Hashable` is a subtype of `object`. See #11799 and isinstance(default_ret_type, Instance) and not default_ret_type.type.is_protocol @@ -354,10 +354,17 @@ def make_simplified_union(items: Sequence[Type], Note: This must NOT be used during semantic analysis, since TypeInfos may not be fully initialized. + The keep_erased flag is used for type inference against union types containing type variables. If set to True, keep all ErasedType items. + + The contract_literals flag indicates whether we need to contract literal types + back into a sum type. Set it to False when called by try_expanding_sum_type_ + to_union(). """ items = get_proper_types(items) + + # Step 1: expand all nested unions while any(isinstance(typ, UnionType) for typ in items): all_items: List[ProperType] = [] for typ in items: @@ -367,10 +374,11 @@ def make_simplified_union(items: Sequence[Type], all_items.append(typ) items = all_items + # Step 2: remove redundant unions simplified_set = _remove_redundant_union_items(items, keep_erased) - # If more than one literal exists in the union, try to simplify - if (contract_literals and sum(isinstance(item, LiteralType) for item in simplified_set) > 1): + # Step 3: If more than one literal exists in the union, try to simplify + if contract_literals and sum(isinstance(item, LiteralType) for item in simplified_set) > 1: simplified_set = try_contracting_literals_in_union(simplified_set) return UnionType.make_union(simplified_set, line, column) @@ -384,7 +392,7 @@ def _remove_redundant_union_items(items: List[ProperType], keep_erased: bool) -> # NB: having a separate fast path for Union of Literal and slow path for other things # would arguably be cleaner, however it breaks down when simplifying the Union of two - # different enum types as try_expanding_enum_to_union works recursively and will + # different enum types as try_expanding_sum_type_to_union works recursively and will # trigger intermediate simplifications that would render the fast path useless for i, item in enumerate(items): if i in removed: @@ -408,7 +416,7 @@ def _remove_redundant_union_items(items: List[ProperType], keep_erased: bool) -> if safe_skip: continue - # Keep track of the truishness info for deleted subtypes which can be relevant + # Keep track of the truthiness info for deleted subtypes which can be relevant cbt = cbf = False for j, tj in enumerate(items): if ( @@ -609,7 +617,7 @@ def try_getting_str_literals(expr: Expression, typ: Type) -> Optional[List[str]] Otherwise, returns None. Specifically, this function is guaranteed to return a list with - one or more strings if one one the following is true: + one or more strings if one of the following is true: 1. 'expr' is a StrExpr 2. 'typ' is a LiteralType containing a string @@ -651,7 +659,7 @@ def try_getting_literals_from_type(typ: Type, target_literal_type: TypingType[T], target_fullname: str) -> Optional[List[T]]: """If the given expression or type corresponds to a Literal or - union of Literals where the underlying values corresponds to the given + union of Literals where the underlying values correspond to the given target type, returns a list of those underlying values. Otherwise, returns None. """ From a16c414809714c2872ee9a063c28cde6d4398021 Mon Sep 17 00:00:00 2001 From: jhance Date: Thu, 21 Apr 2022 01:57:29 -0700 Subject: [PATCH 248/377] Add TypeVarTupleType type node (#12632) This adds the TypeVarTupleType type node and basic semanal/glue. Type checking involving it will be added in a subsequent PR to keep each PR smaller. This PR is mostly consisting of modifying all the visitors, but not all of them are implemented. --- mypy/constraints.py | 5 +++- mypy/erasetype.py | 8 ++++-- mypy/expandtype.py | 5 +++- mypy/fixup.py | 5 +++- mypy/indirection.py | 3 ++ mypy/join.py | 7 ++++- mypy/meet.py | 8 +++++- mypy/sametypes.py | 7 ++++- mypy/semanal_typeargs.py | 9 +++++- mypy/server/astdiff.py | 8 +++++- mypy/server/astmerge.py | 5 +++- mypy/server/deps.py | 9 +++++- mypy/subtypes.py | 20 ++++++++++++- mypy/tvar_scope.py | 17 +++++++++-- mypy/type_visitor.py | 13 ++++++++- mypy/typeanal.py | 30 ++++++++++++++++++-- mypy/types.py | 45 ++++++++++++++++++++++++++++++ mypy/typetraverser.py | 5 +++- test-data/unit/semanal-errors.test | 5 +++- 19 files changed, 193 insertions(+), 21 deletions(-) diff --git a/mypy/constraints.py b/mypy/constraints.py index b7ed1492e5f3b..06feddc0d3cea 100644 --- a/mypy/constraints.py +++ b/mypy/constraints.py @@ -8,7 +8,7 @@ TupleType, TypedDictType, UnionType, Overloaded, ErasedType, PartialType, DeletedType, UninhabitedType, TypeType, TypeVarId, TypeQuery, is_named_instance, TypeOfAny, LiteralType, ProperType, ParamSpecType, get_proper_type, TypeAliasType, is_union_with_any, - UnpackType, callable_with_ellipsis, Parameters, TUPLE_LIKE_INSTANCE_NAMES, + UnpackType, callable_with_ellipsis, Parameters, TUPLE_LIKE_INSTANCE_NAMES, TypeVarTupleType, ) from mypy.maptype import map_instance_to_supertype import mypy.subtypes @@ -403,6 +403,9 @@ def visit_param_spec(self, template: ParamSpecType) -> List[Constraint]: # Can't infer ParamSpecs from component values (only via Callable[P, T]). return [] + def visit_type_var_tuple(self, template: TypeVarTupleType) -> List[Constraint]: + raise NotImplementedError + def visit_unpack_type(self, template: UnpackType) -> List[Constraint]: raise NotImplementedError diff --git a/mypy/erasetype.py b/mypy/erasetype.py index ff0ef6c0784ee..21ca5771b32ed 100644 --- a/mypy/erasetype.py +++ b/mypy/erasetype.py @@ -4,7 +4,8 @@ Type, TypeVisitor, UnboundType, AnyType, NoneType, TypeVarId, Instance, TypeVarType, CallableType, TupleType, TypedDictType, UnionType, Overloaded, ErasedType, PartialType, DeletedType, TypeTranslator, UninhabitedType, TypeType, TypeOfAny, LiteralType, ProperType, - get_proper_type, get_proper_types, TypeAliasType, ParamSpecType, Parameters, UnpackType + get_proper_type, get_proper_types, TypeAliasType, ParamSpecType, Parameters, UnpackType, + TypeVarTupleType ) from mypy.nodes import ARG_STAR, ARG_STAR2 @@ -62,8 +63,11 @@ def visit_param_spec(self, t: ParamSpecType) -> ProperType: def visit_parameters(self, t: Parameters) -> ProperType: raise RuntimeError("Parameters should have been bound to a class") + def visit_type_var_tuple(self, t: TypeVarTupleType) -> ProperType: + return AnyType(TypeOfAny.special_form) + def visit_unpack_type(self, t: UnpackType) -> ProperType: - raise NotImplementedError + return AnyType(TypeOfAny.special_form) def visit_callable_type(self, t: CallableType) -> ProperType: # We must preserve the fallback type for overload resolution to work. diff --git a/mypy/expandtype.py b/mypy/expandtype.py index 39606c263f6b7..eef841c9387ec 100644 --- a/mypy/expandtype.py +++ b/mypy/expandtype.py @@ -6,7 +6,7 @@ ErasedType, PartialType, DeletedType, UninhabitedType, TypeType, TypeVarId, FunctionLike, TypeVarType, LiteralType, get_proper_type, ProperType, TypeAliasType, ParamSpecType, TypeVarLikeType, Parameters, ParamSpecFlavor, - UnpackType + UnpackType, TypeVarTupleType ) @@ -131,6 +131,9 @@ def visit_param_spec(self, t: ParamSpecType) -> Type: # TODO: should this branch be removed? better not to fail silently return repl + def visit_type_var_tuple(self, t: TypeVarTupleType) -> Type: + raise NotImplementedError + def visit_unpack_type(self, t: UnpackType) -> Type: raise NotImplementedError diff --git a/mypy/fixup.py b/mypy/fixup.py index 302bd38097b30..11f07b1d4655a 100644 --- a/mypy/fixup.py +++ b/mypy/fixup.py @@ -11,7 +11,7 @@ CallableType, Instance, Overloaded, TupleType, TypedDictType, TypeVarType, UnboundType, UnionType, TypeVisitor, LiteralType, TypeType, NOT_READY, TypeAliasType, AnyType, TypeOfAny, ParamSpecType, - Parameters, UnpackType, + Parameters, UnpackType, TypeVarTupleType ) from mypy.visitor import NodeVisitor from mypy.lookup import lookup_fully_qualified @@ -252,6 +252,9 @@ def visit_type_var(self, tvt: TypeVarType) -> None: def visit_param_spec(self, p: ParamSpecType) -> None: p.upper_bound.accept(self) + def visit_type_var_tuple(self, t: TypeVarTupleType) -> None: + t.upper_bound.accept(self) + def visit_unpack_type(self, u: UnpackType) -> None: u.type.accept(self) diff --git a/mypy/indirection.py b/mypy/indirection.py index 0888c2afad209..56c1f97928f2e 100644 --- a/mypy/indirection.py +++ b/mypy/indirection.py @@ -67,6 +67,9 @@ def visit_type_var(self, t: types.TypeVarType) -> Set[str]: def visit_param_spec(self, t: types.ParamSpecType) -> Set[str]: return set() + def visit_type_var_tuple(self, t: types.TypeVarTupleType) -> Set[str]: + return self._visit(t.upper_bound) + def visit_unpack_type(self, t: types.UnpackType) -> Set[str]: return t.type.accept(self) diff --git a/mypy/join.py b/mypy/join.py index 7e8fd5d61491c..78f280411622d 100644 --- a/mypy/join.py +++ b/mypy/join.py @@ -8,7 +8,7 @@ TupleType, TypedDictType, ErasedType, UnionType, FunctionLike, Overloaded, LiteralType, PartialType, DeletedType, UninhabitedType, TypeType, TypeOfAny, get_proper_type, ProperType, get_proper_types, TypeAliasType, PlaceholderType, ParamSpecType, Parameters, - UnpackType + UnpackType, TypeVarTupleType, ) from mypy.maptype import map_instance_to_supertype from mypy.subtypes import ( @@ -257,6 +257,11 @@ def visit_param_spec(self, t: ParamSpecType) -> ProperType: return t return self.default(self.s) + def visit_type_var_tuple(self, t: TypeVarTupleType) -> ProperType: + if self.s == t: + return t + return self.default(self.s) + def visit_unpack_type(self, t: UnpackType) -> UnpackType: raise NotImplementedError diff --git a/mypy/meet.py b/mypy/meet.py index 5ee64416490d6..ad77251828386 100644 --- a/mypy/meet.py +++ b/mypy/meet.py @@ -6,7 +6,7 @@ TupleType, TypedDictType, ErasedType, UnionType, PartialType, DeletedType, UninhabitedType, TypeType, TypeOfAny, Overloaded, FunctionLike, LiteralType, ProperType, get_proper_type, get_proper_types, TypeAliasType, TypeGuardedType, - ParamSpecType, Parameters, UnpackType, + ParamSpecType, Parameters, UnpackType, TypeVarTupleType, ) from mypy.subtypes import is_equivalent, is_subtype, is_callable_compatible, is_proper_subtype from mypy.erasetype import erase_type @@ -536,6 +536,12 @@ def visit_param_spec(self, t: ParamSpecType) -> ProperType: else: return self.default(self.s) + def visit_type_var_tuple(self, t: TypeVarTupleType) -> ProperType: + if self.s == t: + return self.s + else: + return self.default(self.s) + def visit_unpack_type(self, t: UnpackType) -> ProperType: raise NotImplementedError diff --git a/mypy/sametypes.py b/mypy/sametypes.py index 1c22c32f8b064..4fbc9bfc48018 100644 --- a/mypy/sametypes.py +++ b/mypy/sametypes.py @@ -4,7 +4,8 @@ Type, UnboundType, AnyType, NoneType, TupleType, TypedDictType, UnionType, CallableType, TypeVarType, Instance, TypeVisitor, ErasedType, Overloaded, PartialType, DeletedType, UninhabitedType, TypeType, LiteralType, - ProperType, get_proper_type, TypeAliasType, ParamSpecType, Parameters, UnpackType + ProperType, get_proper_type, TypeAliasType, ParamSpecType, Parameters, + UnpackType, TypeVarTupleType, ) from mypy.typeops import tuple_fallback, make_simplified_union, is_simple_literal @@ -118,6 +119,10 @@ def visit_param_spec(self, left: ParamSpecType) -> bool: return (isinstance(self.right, ParamSpecType) and left.id == self.right.id and left.flavor == self.right.flavor) + def visit_type_var_tuple(self, left: TypeVarTupleType) -> bool: + return (isinstance(self.right, TypeVarTupleType) and + left.id == self.right.id) + def visit_unpack_type(self, left: UnpackType) -> bool: return (isinstance(self.right, UnpackType) and is_same_type(left.type, self.right.type)) diff --git a/mypy/semanal_typeargs.py b/mypy/semanal_typeargs.py index 0e885f46a7a51..f8e14d28661ac 100644 --- a/mypy/semanal_typeargs.py +++ b/mypy/semanal_typeargs.py @@ -10,7 +10,7 @@ from mypy.nodes import TypeInfo, Context, MypyFile, FuncItem, ClassDef, Block, FakeInfo from mypy.types import ( Type, Instance, TypeVarType, AnyType, get_proper_types, TypeAliasType, ParamSpecType, - UnpackType, TupleType, get_proper_type + UnpackType, TupleType, TypeVarTupleType, TypeOfAny, get_proper_type ) from mypy.mixedtraverser import MixedTraverserVisitor from mypy.subtypes import is_subtype @@ -99,8 +99,15 @@ def visit_unpack_type(self, typ: UnpackType) -> None: proper_type = get_proper_type(typ.type) if isinstance(proper_type, TupleType): return + if isinstance(proper_type, TypeVarTupleType): + return if isinstance(proper_type, Instance) and proper_type.type.fullname == "builtins.tuple": return + if isinstance(proper_type, AnyType) and proper_type.type_of_any == TypeOfAny.from_error: + return + + # TODO: Infer something when it can't be unpacked to allow rest of + # typechecking to work. self.fail(message_registry.INVALID_UNPACK.format(proper_type), typ) def check_type_var_values(self, type: TypeInfo, actuals: List[Type], arg_name: str, diff --git a/mypy/server/astdiff.py b/mypy/server/astdiff.py index 437cb777c8d53..f41a54752fee2 100644 --- a/mypy/server/astdiff.py +++ b/mypy/server/astdiff.py @@ -60,7 +60,7 @@ class level -- these are handled at attribute level (say, 'mod.Cls.method' Type, TypeVisitor, UnboundType, AnyType, NoneType, UninhabitedType, ErasedType, DeletedType, Instance, TypeVarType, CallableType, TupleType, TypedDictType, UnionType, Overloaded, PartialType, TypeType, LiteralType, TypeAliasType, ParamSpecType, - Parameters, UnpackType, + Parameters, UnpackType, TypeVarTupleType, ) from mypy.util import get_prefix @@ -318,6 +318,12 @@ def visit_param_spec(self, typ: ParamSpecType) -> SnapshotItem: typ.flavor, snapshot_type(typ.upper_bound)) + def visit_type_var_tuple(self, typ: TypeVarTupleType) -> SnapshotItem: + return ('TypeVarTupleType', + typ.id.raw_id, + typ.id.meta_level, + snapshot_type(typ.upper_bound)) + def visit_unpack_type(self, typ: UnpackType) -> SnapshotItem: return ('UnpackType', snapshot_type(typ.type)) diff --git a/mypy/server/astmerge.py b/mypy/server/astmerge.py index d8f1d5a191557..4d684e226b21b 100644 --- a/mypy/server/astmerge.py +++ b/mypy/server/astmerge.py @@ -60,7 +60,7 @@ TupleType, TypeType, TypedDictType, UnboundType, UninhabitedType, UnionType, Overloaded, TypeVarType, TypeList, CallableArgument, EllipsisType, StarType, LiteralType, RawExpressionType, PartialType, PlaceholderType, TypeAliasType, ParamSpecType, Parameters, - UnpackType + UnpackType, TypeVarTupleType, ) from mypy.util import get_prefix, replace_object_state from mypy.typestate import TypeState @@ -416,6 +416,9 @@ def visit_type_var(self, typ: TypeVarType) -> None: def visit_param_spec(self, typ: ParamSpecType) -> None: pass + def visit_type_var_tuple(self, typ: TypeVarTupleType) -> None: + typ.upper_bound.accept(self) + def visit_unpack_type(self, typ: UnpackType) -> None: typ.type.accept(self) diff --git a/mypy/server/deps.py b/mypy/server/deps.py index da4960ba1934f..c7623ff26c7f8 100644 --- a/mypy/server/deps.py +++ b/mypy/server/deps.py @@ -100,7 +100,7 @@ class 'mod.Cls'. This can also refer to an attribute inherited from a Type, Instance, AnyType, NoneType, TypeVisitor, CallableType, DeletedType, PartialType, TupleType, TypeType, TypeVarType, TypedDictType, UnboundType, UninhabitedType, UnionType, FunctionLike, Overloaded, TypeOfAny, LiteralType, ErasedType, get_proper_type, ProperType, - TypeAliasType, ParamSpecType, Parameters, UnpackType + TypeAliasType, ParamSpecType, Parameters, UnpackType, TypeVarTupleType, ) from mypy.server.trigger import make_trigger, make_wildcard_trigger from mypy.util import correct_relative_import @@ -966,6 +966,13 @@ def visit_param_spec(self, typ: ParamSpecType) -> List[str]: triggers.extend(self.get_type_triggers(typ.upper_bound)) return triggers + def visit_type_var_tuple(self, typ: TypeVarTupleType) -> List[str]: + triggers = [] + if typ.fullname: + triggers.append(make_trigger(typ.fullname)) + triggers.extend(self.get_type_triggers(typ.upper_bound)) + return triggers + def visit_unpack_type(self, typ: UnpackType) -> List[str]: return typ.type.accept(self) diff --git a/mypy/subtypes.py b/mypy/subtypes.py index d977a114bf2f2..809f457ab2a2f 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -8,7 +8,7 @@ Instance, TypeVarType, CallableType, TupleType, TypedDictType, UnionType, Overloaded, ErasedType, PartialType, DeletedType, UninhabitedType, TypeType, is_named_instance, FunctionLike, TypeOfAny, LiteralType, get_proper_type, TypeAliasType, ParamSpecType, - Parameters, UnpackType, TUPLE_LIKE_INSTANCE_NAMES, + Parameters, UnpackType, TUPLE_LIKE_INSTANCE_NAMES, TypeVarTupleType, ) import mypy.applytype import mypy.constraints @@ -340,6 +340,15 @@ def visit_param_spec(self, left: ParamSpecType) -> bool: return True return self._is_subtype(left.upper_bound, self.right) + def visit_type_var_tuple(self, left: TypeVarTupleType) -> bool: + right = self.right + if ( + isinstance(right, TypeVarTupleType) + and right.id == left.id + ): + return True + return self._is_subtype(left.upper_bound, self.right) + def visit_unpack_type(self, left: UnpackType) -> bool: raise NotImplementedError @@ -1463,6 +1472,15 @@ def visit_param_spec(self, left: ParamSpecType) -> bool: return True return self._is_proper_subtype(left.upper_bound, self.right) + def visit_type_var_tuple(self, left: TypeVarTupleType) -> bool: + right = self.right + if ( + isinstance(right, TypeVarTupleType) + and right.id == left.id + ): + return True + return self._is_proper_subtype(left.upper_bound, self.right) + def visit_unpack_type(self, left: UnpackType) -> bool: raise NotImplementedError diff --git a/mypy/tvar_scope.py b/mypy/tvar_scope.py index ac82a7708f0e8..c1fe1cd6be356 100644 --- a/mypy/tvar_scope.py +++ b/mypy/tvar_scope.py @@ -1,6 +1,10 @@ from typing import Optional, Dict, Union -from mypy.types import TypeVarLikeType, TypeVarType, ParamSpecType, ParamSpecFlavor, TypeVarId -from mypy.nodes import ParamSpecExpr, TypeVarExpr, TypeVarLikeExpr, SymbolTableNode +from mypy.types import ( + TypeVarLikeType, TypeVarType, ParamSpecType, ParamSpecFlavor, TypeVarId, TypeVarTupleType, +) +from mypy.nodes import ( + ParamSpecExpr, TypeVarExpr, TypeVarLikeExpr, SymbolTableNode, TypeVarTupleExpr, +) class TypeVarLikeScope: @@ -88,6 +92,15 @@ def bind_new(self, name: str, tvar_expr: TypeVarLikeExpr) -> TypeVarLikeType: line=tvar_expr.line, column=tvar_expr.column ) + elif isinstance(tvar_expr, TypeVarTupleExpr): + tvar_def = TypeVarTupleType( + name, + tvar_expr.fullname, + i, + upper_bound=tvar_expr.upper_bound, + line=tvar_expr.line, + column=tvar_expr.column + ) else: assert False self.scope[tvar_expr.fullname] = tvar_def diff --git a/mypy/type_visitor.py b/mypy/type_visitor.py index 05688a1e5071e..85701a51f1280 100644 --- a/mypy/type_visitor.py +++ b/mypy/type_visitor.py @@ -23,7 +23,8 @@ Parameters, RawExpressionType, Instance, NoneType, TypeType, UnionType, TypeVarType, PartialType, DeletedType, UninhabitedType, TypeVarLikeType, UnboundType, ErasedType, StarType, EllipsisType, TypeList, CallableArgument, - PlaceholderType, TypeAliasType, ParamSpecType, UnpackType, get_proper_type + PlaceholderType, TypeAliasType, ParamSpecType, UnpackType, TypeVarTupleType, + get_proper_type ) @@ -71,6 +72,10 @@ def visit_param_spec(self, t: ParamSpecType) -> T: def visit_parameters(self, t: Parameters) -> T: pass + @abstractmethod + def visit_type_var_tuple(self, t: TypeVarTupleType) -> T: + pass + @abstractmethod def visit_instance(self, t: Instance) -> T: pass @@ -197,6 +202,9 @@ def visit_param_spec(self, t: ParamSpecType) -> Type: def visit_parameters(self, t: Parameters) -> Type: return t.copy_modified(arg_types=self.translate_types(t.arg_types)) + def visit_type_var_tuple(self, t: TypeVarTupleType) -> Type: + return t + def visit_partial_type(self, t: PartialType) -> Type: return t @@ -315,6 +323,9 @@ def visit_type_var(self, t: TypeVarType) -> T: def visit_param_spec(self, t: ParamSpecType) -> T: return self.strategy([]) + def visit_type_var_tuple(self, t: TypeVarTupleType) -> T: + return self.strategy([]) + def visit_unpack_type(self, t: UnpackType) -> T: return self.query_types([t.type]) diff --git a/mypy/typeanal.py b/mypy/typeanal.py index 276e46df03ee4..eee8a43c25f35 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -17,7 +17,7 @@ StarType, PartialType, EllipsisType, UninhabitedType, TypeType, CallableArgument, Parameters, TypeQuery, union_items, TypeOfAny, LiteralType, RawExpressionType, PlaceholderType, Overloaded, get_proper_type, TypeAliasType, RequiredType, - TypeVarLikeType, ParamSpecType, ParamSpecFlavor, UnpackType, + TypeVarLikeType, ParamSpecType, ParamSpecFlavor, UnpackType, TypeVarTupleType, callable_with_ellipsis, TYPE_ALIAS_NAMES, FINAL_TYPE_NAMES, LITERAL_TYPE_NAMES, ANNOTATED_TYPE_NAMES, ) @@ -26,7 +26,8 @@ TypeInfo, Context, SymbolTableNode, Var, Expression, get_nongen_builtins, check_arg_names, check_arg_kinds, ArgKind, ARG_POS, ARG_NAMED, ARG_OPT, ARG_NAMED_OPT, ARG_STAR, ARG_STAR2, TypeVarExpr, TypeVarLikeExpr, ParamSpecExpr, - TypeAlias, PlaceholderNode, SYMBOL_FUNCBASE_TYPES, Decorator, MypyFile + TypeAlias, PlaceholderNode, SYMBOL_FUNCBASE_TYPES, Decorator, MypyFile, + TypeVarTupleExpr ) from mypy.typetraverser import TypeTraverserVisitor from mypy.tvar_scope import TypeVarLikeScope @@ -236,6 +237,24 @@ def visit_unbound_type_nonoptional(self, t: UnboundType, defining_literal: bool) tvar_def.name, tvar_def.fullname, tvar_def.id, tvar_def.values, tvar_def.upper_bound, tvar_def.variance, line=t.line, column=t.column, ) + if isinstance(sym.node, TypeVarTupleExpr) and ( + tvar_def is not None and self.defining_alias + ): + self.fail('Can\'t use bound type variable "{}"' + ' to define generic alias'.format(t.name), t) + return AnyType(TypeOfAny.from_error) + if isinstance(sym.node, TypeVarTupleExpr): + if tvar_def is None: + self.fail('TypeVarTuple "{}" is unbound'.format(t.name), t) + return AnyType(TypeOfAny.from_error) + assert isinstance(tvar_def, TypeVarTupleType) + if len(t.args) > 0: + self.fail('Type variable "{}" used with arguments'.format(t.name), t) + # Change the line number + return TypeVarTupleType( + tvar_def.name, tvar_def.fullname, tvar_def.id, + tvar_def.upper_bound, line=t.line, column=t.column, + ) special = self.try_analyze_special_unbound_type(t, fullname) if special is not None: return special @@ -514,7 +533,7 @@ def analyze_unbound_type_without_type_info(self, t: UnboundType, sym: SymbolTabl # Option 2: # Unbound type variable. Currently these may be still valid, # for example when defining a generic type alias. - unbound_tvar = (isinstance(sym.node, TypeVarExpr) and + unbound_tvar = (isinstance(sym.node, (TypeVarExpr, TypeVarTupleExpr)) and self.tvar_scope.get_binding(sym) is None) if self.allow_unbound_tvars and unbound_tvar: return t @@ -630,6 +649,9 @@ def visit_type_var(self, t: TypeVarType) -> Type: def visit_param_spec(self, t: ParamSpecType) -> Type: return t + def visit_type_var_tuple(self, t: TypeVarTupleType) -> Type: + return t + def visit_unpack_type(self, t: UnpackType) -> Type: raise NotImplementedError @@ -1180,6 +1202,8 @@ def anal_var_def(self, var_def: TypeVarLikeType) -> TypeVarLikeType: var_def.variance, var_def.line ) + elif isinstance(var_def, TypeVarTupleType): + raise NotImplementedError else: return var_def diff --git a/mypy/types.py b/mypy/types.py index 49e0aa1d85ecf..e43b73f093b89 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -661,6 +661,42 @@ def deserialize(cls, data: JsonDict) -> 'ParamSpecType': ) +class TypeVarTupleType(TypeVarLikeType): + """Type that refers to a TypeVarTuple. + + See PEP646 for more information. + """ + def serialize(self) -> JsonDict: + assert not self.id.is_meta_var() + return {'.class': 'TypeVarTupleType', + 'name': self.name, + 'fullname': self.fullname, + 'id': self.id.raw_id, + 'upper_bound': self.upper_bound.serialize(), + } + + @classmethod + def deserialize(cls, data: JsonDict) -> 'TypeVarTupleType': + assert data['.class'] == 'TypeVarTupleType' + return TypeVarTupleType( + data['name'], + data['fullname'], + data['id'], + deserialize_type(data['upper_bound']), + ) + + def accept(self, visitor: 'TypeVisitor[T]') -> T: + return visitor.visit_type_var_tuple(self) + + def __hash__(self) -> int: + return hash(self.id) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, TypeVarTupleType): + return NotImplemented + return self.id == other.id + + class UnboundType(ProperType): """Instance type that has not been bound during semantic analysis.""" @@ -2657,6 +2693,15 @@ def visit_parameters(self, t: Parameters) -> str: return f'[{s}]' + def visit_type_var_tuple(self, t: TypeVarTupleType) -> str: + if t.name is None: + # Anonymous type variable type (only numeric id). + s = f'`{t.id}' + else: + # Named type variable type. + s = f'{t.name}`{t.id}' + return s + def visit_callable_type(self, t: CallableType) -> str: param_spec = t.param_spec() if param_spec is not None: diff --git a/mypy/typetraverser.py b/mypy/typetraverser.py index 94eeee79be93c..7d959c97b66ba 100644 --- a/mypy/typetraverser.py +++ b/mypy/typetraverser.py @@ -7,7 +7,7 @@ TypeVarType, LiteralType, Instance, CallableType, TupleType, TypedDictType, UnionType, Overloaded, TypeType, CallableArgument, UnboundType, TypeList, StarType, EllipsisType, PlaceholderType, PartialType, RawExpressionType, TypeAliasType, ParamSpecType, Parameters, - UnpackType + UnpackType, TypeVarTupleType, ) @@ -44,6 +44,9 @@ def visit_param_spec(self, t: ParamSpecType) -> None: def visit_parameters(self, t: Parameters) -> None: self.traverse_types(t.arg_types) + def visit_type_var_tuple(self, t: TypeVarTupleType) -> None: + pass + def visit_literal_type(self, t: LiteralType) -> None: t.fallback.accept(self) diff --git a/test-data/unit/semanal-errors.test b/test-data/unit/semanal-errors.test index 5a1c487721909..14bc24f03a7b2 100644 --- a/test-data/unit/semanal-errors.test +++ b/test-data/unit/semanal-errors.test @@ -1462,7 +1462,7 @@ bad: Tuple[Unpack[int]] # E: builtins.int cannot be unpacked (must be tuple or [builtins fixtures/tuple.pyi] [case testTypeVarTuple] -from typing_extensions import TypeVarTuple +from typing_extensions import TypeVarTuple, Unpack TVariadic = TypeVarTuple('TVariadic') TP = TypeVarTuple('?') # E: String argument 1 "?" to TypeVarTuple(...) does not match variable name "TP" @@ -1470,3 +1470,6 @@ TP2: int = TypeVarTuple('TP2') # E: Cannot declare the type of a TypeVar or sim TP3 = TypeVarTuple() # E: Too few arguments for TypeVarTuple() TP4 = TypeVarTuple('TP4', 'TP4') # E: Only the first argument to TypeVarTuple has defined semantics TP5 = TypeVarTuple(t='TP5') # E: TypeVarTuple() expects a string literal as first argument + +x: TVariadic # E: TypeVarTuple "TVariadic" is unbound +y: Unpack[TVariadic] # E: TypeVarTuple "TVariadic" is unbound From 00a981518fe1a5ee0a26cf110fcc8bb9649d487e Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 21 Apr 2022 17:28:01 +0100 Subject: [PATCH 249/377] Fix slots and deleted attributes in incremental mode (#12645) They weren't serialized before. Manually written serialization code is a pain to keep up-to-date. --- mypy/nodes.py | 4 ++++ mypyc/ir/class_ir.py | 2 ++ mypyc/test-data/fixtures/ir.py | 2 +- mypyc/test-data/run-multimodule.test | 22 ++++++++++++++++++++++ test-data/unit/check-incremental.test | 25 +++++++++++++++++++++++++ 5 files changed, 54 insertions(+), 1 deletion(-) diff --git a/mypy/nodes.py b/mypy/nodes.py index f25d3abab7bc3..5a27783e97e1e 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -2907,6 +2907,8 @@ def serialize(self) -> JsonDict: None if self.typeddict_type is None else self.typeddict_type.serialize(), 'flags': get_flags(self, TypeInfo.FLAGS), 'metadata': self.metadata, + 'slots': list(sorted(self.slots)) if self.slots is not None else None, + 'deletable_attributes': self.deletable_attributes, } return data @@ -2944,6 +2946,8 @@ def deserialize(cls, data: JsonDict) -> 'TypeInfo': ti.typeddict_type = (None if data['typeddict_type'] is None else mypy.types.TypedDictType.deserialize(data['typeddict_type'])) ti.metadata = data['metadata'] + ti.slots = set(data['slots']) if data['slots'] is not None else None + ti.deletable_attributes = data['deletable_attributes'] set_flags(ti, data['flags']) return ti diff --git a/mypyc/ir/class_ir.py b/mypyc/ir/class_ir.py index ade04f39edcb9..d6407610e2bcf 100644 --- a/mypyc/ir/class_ir.py +++ b/mypyc/ir/class_ir.py @@ -325,6 +325,7 @@ def serialize(self) -> JsonDict: 'children': [ cir.fullname for cir in self.children ] if self.children is not None else None, + 'deletable': self.deletable, } @classmethod @@ -373,6 +374,7 @@ def deserialize(cls, data: JsonDict, ctx: 'DeserMaps') -> 'ClassIR': ir.mro = [ctx.classes[s] for s in data['mro']] ir.base_mro = [ctx.classes[s] for s in data['base_mro']] ir.children = data['children'] and [ctx.classes[s] for s in data['children']] + ir.deletable = data['deletable'] return ir diff --git a/mypyc/test-data/fixtures/ir.py b/mypyc/test-data/fixtures/ir.py index a661067845ac5..a6914ccc36e56 100644 --- a/mypyc/test-data/fixtures/ir.py +++ b/mypyc/test-data/fixtures/ir.py @@ -294,7 +294,7 @@ def next(i: Iterator[T]) -> T: pass def next(i: Iterator[T], default: T) -> T: pass def hash(o: object) -> int: ... def globals() -> Dict[str, Any]: ... -def getattr(obj: object, name: str) -> Any: ... +def getattr(obj: object, name: str, default: Any = None) -> Any: ... def setattr(obj: object, name: str, value: Any) -> None: ... def enumerate(x: Iterable[T]) -> Iterator[Tuple[int, T]]: ... @overload diff --git a/mypyc/test-data/run-multimodule.test b/mypyc/test-data/run-multimodule.test index 20c9002cdf1d9..6ffa166c57a1c 100644 --- a/mypyc/test-data/run-multimodule.test +++ b/mypyc/test-data/run-multimodule.test @@ -798,3 +798,25 @@ def foo() -> int: return 10 import native [rechecked native, other_a] + +[case testIncrementalCompilationWithDeletable] +import other_a +[file other_a.py] +from other_b import C +[file other_a.py.2] +from other_b import C +c = C() +print(getattr(c, 'x', None)) +del c.x +print(getattr(c, 'x', None)) +[file other_b.py] +class C: + __deletable__ = ['x'] + def __init__(self) -> None: + self.x = 0 +[file driver.py] +import native +[out] +[out2] +0 +None diff --git a/test-data/unit/check-incremental.test b/test-data/unit/check-incremental.test index c990f52e74c83..caba9b73e5943 100644 --- a/test-data/unit/check-incremental.test +++ b/test-data/unit/check-incremental.test @@ -5633,3 +5633,28 @@ main:5: error: Cannot override final attribute "x" (previously declared in base main:3: error: Cannot override writable attribute "x" with a final one main:4: error: Cannot extend enum with existing members: "FinalEnum" main:5: error: Cannot override final attribute "x" (previously declared in base class "FinalEnum") + +[case testSlotsSerialization] +import a +[file a.py] +from b import C + +class D(C): + pass +[file b.py] +class C: + __slots__ = ('x',) +[file a.py.2] +from b import C + +class D(C): + __slots__ = ('y',) + + def __init__(self) -> None: + self.x = 1 + self.y = 2 + self.z = 3 +[builtins fixtures/tuple.pyi] +[out] +[out2] +tmp/a.py:9: error: Trying to assign name "z" that is not in "__slots__" of type "a.D" From 9477bd8965e4bbfbb754b7fd2076e1dbe1e26432 Mon Sep 17 00:00:00 2001 From: Ethan Smith Date: Thu, 21 Apr 2022 11:04:01 -0700 Subject: [PATCH 250/377] Update typed_ast types for build (#12638) --- build-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build-requirements.txt b/build-requirements.txt index b4d024ee7f389..a46926fb3220b 100644 --- a/build-requirements.txt +++ b/build-requirements.txt @@ -1,2 +1,2 @@ -r mypy-requirements.txt -types-typed-ast>=1.4.0,<1.5.0 +types-typed-ast>=1.5.0,<1.6.0 From 6eac2403f68e33e317c9f17b434d322291e60543 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Thu, 21 Apr 2022 20:53:30 +0100 Subject: [PATCH 251/377] Add regression test for recently fixed `deque.copy()` bug (#12648) --- test-data/unit/check-selftype.test | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test-data/unit/check-selftype.test b/test-data/unit/check-selftype.test index ef3d5289ddfd1..f86e32905752b 100644 --- a/test-data/unit/check-selftype.test +++ b/test-data/unit/check-selftype.test @@ -1220,3 +1220,21 @@ class ThingCollection(Generic[T]): def do_thing(self) -> None: self.index.update((idx, c) for idx, (k, c) in enumerate(self.collection)) [builtins fixtures/tuple.pyi] + +[case testDequeReturningSelfFromCopy] +# Tests a bug with generic self types identified in issue #12641 +from typing import Generic, Sequence, TypeVar + +T = TypeVar("T") +Self = TypeVar("Self") + +class deque(Sequence[T]): + def copy(self: Self) -> Self: ... + +class List(Sequence[T]): ... + +class Test(Generic[T]): + def test(self) -> None: + a: deque[List[T]] + # previously this failed with 'Incompatible types in assignment (expression has type "deque[List[List[T]]]", variable has type "deque[List[T]]")' + b: deque[List[T]] = a.copy() From 09dbdf6c1020aac533e0a7e71eeb97f1f1dd00f9 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Fri, 22 Apr 2022 05:21:47 +0100 Subject: [PATCH 252/377] Add test case for fixed bug regarding nested generic classes (#12652) Closes #5551 (the bug in that issue was fixed by #12590) --- test-data/unit/check-generics.test | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test-data/unit/check-generics.test b/test-data/unit/check-generics.test index 6a89f6fb200c2..b228e76a32d11 100644 --- a/test-data/unit/check-generics.test +++ b/test-data/unit/check-generics.test @@ -1506,6 +1506,22 @@ class Outer(Generic[T]): def g(self) -> None: y: T # E: Invalid type "__main__.T" +[case testGenericClassInsideOtherGenericClass] +from typing import TypeVar, Generic +T = TypeVar("T") +K = TypeVar("K") + +class C(Generic[T]): + def __init__(self, t: T) -> None: ... + class F(Generic[K]): + def __init__(self, k: K) -> None: ... + def foo(self) -> K: ... + +reveal_type(C.F(17).foo()) # N: Revealed type is "builtins.int" +reveal_type(C("").F(17).foo()) # N: Revealed type is "builtins.int" +reveal_type(C.F) # N: Revealed type is "def [K] (k: K`1) -> __main__.C.F[K`1]" +reveal_type(C("").F) # N: Revealed type is "def [K] (k: K`1) -> __main__.C.F[K`1]" + -- Callable subtyping with generic functions -- ----------------------------------------- From 07ea0f612ea2e755cc403b1b11e8ef058a59e4fe Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 22 Apr 2022 12:05:40 +0100 Subject: [PATCH 253/377] Attempt to fix issue with ParamSpec serialization (#12654) I've seen crashes like this, which might be caused by not fixing up some FakeInfos: ``` File "mypy/checkexpr.py", line 3981, in accept File "mypy/nodes.py", line 1753, in accept File "mypy/checkexpr.py", line 288, in visit_call_expr File "mypy/checkexpr.py", line 371, in visit_call_expr_inner File "mypy/checkexpr.py", line 880, in check_call_expr_with_callee_type File "mypy/checkexpr.py", line 940, in check_call File "mypy/checkexpr.py", line 1027, in check_callable_call File "mypy/checkexpr.py", line 1269, in infer_function_type_arguments File "mypy/checkexpr.py", line 1324, in infer_function_type_arguments_pass2 File "mypy/infer.py", line 47, in infer_function_type_arguments File "mypy/constraints.py", line 72, in infer_constraints_for_callable File "mypy/constraints.py", line 108, in infer_constraints File "mypy/constraints.py", line 181, in _infer_constraints File "mypy/types.py", line 1576, in accept File "mypy/constraints.py", line 663, in visit_callable_type File "mypy/constraints.py", line 685, in infer_against_overloaded File "mypy/constraints.py", line 775, in find_matching_overload_item File "mypy/subtypes.py", line 942, in is_callable_compatible File "mypy/subtypes.py", line 1209, in unify_generic_callable File "mypy/applytype.py", line 86, in apply_generic_arguments File "mypy/applytype.py", line 50, in get_target_type File "mypy/subtypes.py", line 97, in is_subtype File "mypy/subtypes.py", line 158, in _is_subtype File "mypy/types.py", line 615, in accept File "mypy/subtypes.py", line 341, in visit_param_spec File "mypy/subtypes.py", line 217, in _is_subtype File "mypy/subtypes.py", line 97, in is_subtype File "mypy/subtypes.py", line 158, in _is_subtype File "mypy/types.py", line 1127, in accept File "mypy/subtypes.py", line 257, in visit_instance AttributeError: attribute 'fallback_to_any' of 'TypeInfo' undefined ``` I don't have a small reproducer to I couldn't add a test case, unfortunately. --- mypy/fixup.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/mypy/fixup.py b/mypy/fixup.py index 11f07b1d4655a..ec979e4e1927c 100644 --- a/mypy/fixup.py +++ b/mypy/fixup.py @@ -188,11 +188,7 @@ def visit_callable_type(self, ct: CallableType) -> None: if ct.ret_type is not None: ct.ret_type.accept(self) for v in ct.variables: - if isinstance(v, TypeVarType): - if v.values: - for val in v.values: - val.accept(self) - v.upper_bound.accept(self) + v.accept(self) for arg in ct.bound_args: if arg: arg.accept(self) @@ -262,6 +258,8 @@ def visit_parameters(self, p: Parameters) -> None: for argt in p.arg_types: if argt is not None: argt.accept(self) + for var in p.variables: + var.accept(self) def visit_unbound_type(self, o: UnboundType) -> None: for a in o.args: From d1c061689a330a4fa993f3cadf5cd8bc06756698 Mon Sep 17 00:00:00 2001 From: Ikko Ashimine Date: Fri, 22 Apr 2022 23:32:58 +0900 Subject: [PATCH 254/377] Fix spelling of "GitHub" in error message (#12655) --- mypy/errors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/errors.py b/mypy/errors.py index 60abb739ba847..20e43fa810f90 100644 --- a/mypy/errors.py +++ b/mypy/errors.py @@ -877,7 +877,7 @@ def report_internal_error(err: Exception, # Print "INTERNAL ERROR" message. print('{}error: INTERNAL ERROR --'.format(prefix), - 'Please try using mypy master on Github:\n' + 'Please try using mypy master on GitHub:\n' 'https://mypy.readthedocs.io/en/stable/common_issues.html' '#using-a-development-mypy-build', file=stderr) From 40bbfb5f2539f6fc3ea8c9b4de6b62d167bb003f Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sat, 23 Apr 2022 14:45:13 -0700 Subject: [PATCH 255/377] Sync typeshed (#12663) * Sync typeshed Source commit: https://github.com/python/typeshed/commit/5dad506bf20ed5b3ddf945407c31ec6d4abc3c67 * Fix tests Co-authored-by: hauntsaninja <> --- mypy/test/teststubtest.py | 2 +- mypy/typeshed/stdlib/VERSIONS | 1 + mypy/typeshed/stdlib/_ast.pyi | 18 +- mypy/typeshed/stdlib/_bisect.pyi | 3 +- mypy/typeshed/stdlib/_codecs.pyi | 8 +- mypy/typeshed/stdlib/_collections_abc.pyi | 2 +- mypy/typeshed/stdlib/_compression.pyi | 3 +- mypy/typeshed/stdlib/_csv.pyi | 7 +- mypy/typeshed/stdlib/_curses.pyi | 4 +- mypy/typeshed/stdlib/_decimal.pyi | 264 +++++++++++- mypy/typeshed/stdlib/_dummy_thread.pyi | 3 +- mypy/typeshed/stdlib/_dummy_threading.pyi | 8 +- mypy/typeshed/stdlib/_json.pyi | 3 +- mypy/typeshed/stdlib/_operator.pyi | 22 +- mypy/typeshed/stdlib/_osx_support.pyi | 3 +- mypy/typeshed/stdlib/_posixsubprocess.pyi | 2 +- mypy/typeshed/stdlib/_pydecimal.pyi | 2 +- mypy/typeshed/stdlib/_random.pyi | 4 +- mypy/typeshed/stdlib/_sitebuiltins.pyi | 3 +- mypy/typeshed/stdlib/_socket.pyi | 13 +- mypy/typeshed/stdlib/_thread.pyi | 3 +- mypy/typeshed/stdlib/_threading_local.pyi | 9 +- mypy/typeshed/stdlib/_tracemalloc.pyi | 2 +- mypy/typeshed/stdlib/_typeshed/__init__.pyi | 9 +- mypy/typeshed/stdlib/_typeshed/wsgi.pyi | 58 +-- mypy/typeshed/stdlib/_weakref.pyi | 11 +- mypy/typeshed/stdlib/_weakrefset.pyi | 3 +- mypy/typeshed/stdlib/_winapi.pyi | 3 +- mypy/typeshed/stdlib/aifc.pyi | 6 +- mypy/typeshed/stdlib/argparse.pyi | 23 +- mypy/typeshed/stdlib/array.pyi | 15 +- mypy/typeshed/stdlib/ast.pyi | 30 +- mypy/typeshed/stdlib/asyncio/base_events.pyi | 14 +- mypy/typeshed/stdlib/asyncio/base_futures.pyi | 3 +- .../stdlib/asyncio/base_subprocess.pyi | 6 +- mypy/typeshed/stdlib/asyncio/events.pyi | 13 +- .../stdlib/asyncio/format_helpers.pyi | 6 +- mypy/typeshed/stdlib/asyncio/futures.pyi | 3 +- mypy/typeshed/stdlib/asyncio/locks.pyi | 3 +- .../stdlib/asyncio/proactor_events.pyi | 3 +- mypy/typeshed/stdlib/asyncio/runners.pyi | 3 +- mypy/typeshed/stdlib/asyncio/sslproto.pyi | 3 +- mypy/typeshed/stdlib/asyncio/staggered.pyi | 3 +- mypy/typeshed/stdlib/asyncio/streams.pyi | 10 +- mypy/typeshed/stdlib/asyncio/subprocess.pyi | 9 +- mypy/typeshed/stdlib/asyncio/taskgroups.pyi | 3 +- mypy/typeshed/stdlib/asyncio/tasks.pyi | 10 +- mypy/typeshed/stdlib/asyncio/threads.pyi | 3 +- mypy/typeshed/stdlib/asyncio/transports.pyi | 3 +- mypy/typeshed/stdlib/asyncio/trsock.pyi | 12 +- mypy/typeshed/stdlib/asyncio/unix_events.pyi | 3 +- .../stdlib/asyncio/windows_events.pyi | 3 +- .../typeshed/stdlib/asyncio/windows_utils.pyi | 3 +- mypy/typeshed/stdlib/asyncore.pyi | 5 +- mypy/typeshed/stdlib/atexit.pyi | 3 +- mypy/typeshed/stdlib/audioop.pyi | 14 +- mypy/typeshed/stdlib/bdb.pyi | 14 +- mypy/typeshed/stdlib/binascii.pyi | 44 +- mypy/typeshed/stdlib/binhex.pyi | 6 +- mypy/typeshed/stdlib/builtins.pyi | 193 +++++---- mypy/typeshed/stdlib/bz2.pyi | 13 +- mypy/typeshed/stdlib/cProfile.pyi | 7 +- mypy/typeshed/stdlib/calendar.pyi | 4 +- mypy/typeshed/stdlib/cgi.pyi | 4 +- mypy/typeshed/stdlib/cgitb.pyi | 15 +- mypy/typeshed/stdlib/cmath.pyi | 5 +- mypy/typeshed/stdlib/cmd.pyi | 3 +- mypy/typeshed/stdlib/code.pyi | 3 +- mypy/typeshed/stdlib/codecs.pyi | 9 +- mypy/typeshed/stdlib/collections/__init__.pyi | 2 +- .../stdlib/concurrent/futures/_base.pyi | 4 +- .../stdlib/concurrent/futures/process.pyi | 4 +- .../stdlib/concurrent/futures/thread.pyi | 4 +- mypy/typeshed/stdlib/configparser.pyi | 14 +- mypy/typeshed/stdlib/contextlib.pyi | 23 +- mypy/typeshed/stdlib/contextvars.pyi | 3 +- mypy/typeshed/stdlib/copyreg.pyi | 8 +- mypy/typeshed/stdlib/ctypes/__init__.pyi | 12 +- mypy/typeshed/stdlib/ctypes/wintypes.pyi | 101 ++--- mypy/typeshed/stdlib/curses/__init__.pyi | 3 +- mypy/typeshed/stdlib/curses/textpad.pyi | 2 +- mypy/typeshed/stdlib/dataclasses.pyi | 3 +- mypy/typeshed/stdlib/datetime.pyi | 8 +- mypy/typeshed/stdlib/dbm/__init__.pyi | 10 +- mypy/typeshed/stdlib/dbm/dumb.pyi | 7 +- mypy/typeshed/stdlib/dbm/gnu.pyi | 5 +- mypy/typeshed/stdlib/dbm/ndbm.pyi | 5 +- mypy/typeshed/stdlib/decimal.pyi | 264 +----------- mypy/typeshed/stdlib/difflib.pyi | 3 +- mypy/typeshed/stdlib/dis.pyi | 90 ++++- mypy/typeshed/stdlib/distutils/ccompiler.pyi | 6 +- mypy/typeshed/stdlib/distutils/cmd.pyi | 3 +- mypy/typeshed/stdlib/distutils/core.pyi | 3 +- mypy/typeshed/stdlib/distutils/dist.pyi | 3 +- .../stdlib/distutils/fancy_getopt.pyi | 8 +- mypy/typeshed/stdlib/distutils/file_util.pyi | 2 +- mypy/typeshed/stdlib/distutils/filelist.pyi | 3 +- mypy/typeshed/stdlib/distutils/sysconfig.pyi | 2 +- mypy/typeshed/stdlib/doctest.pyi | 14 +- mypy/typeshed/stdlib/email/__init__.pyi | 9 +- .../stdlib/email/_header_value_parser.pyi | 3 +- mypy/typeshed/stdlib/email/charset.pyi | 2 +- mypy/typeshed/stdlib/email/contentmanager.pyi | 3 +- mypy/typeshed/stdlib/email/feedparser.pyi | 6 +- mypy/typeshed/stdlib/email/iterators.pyi | 2 +- mypy/typeshed/stdlib/email/message.pyi | 10 +- mypy/typeshed/stdlib/email/parser.pyi | 9 +- mypy/typeshed/stdlib/email/policy.pyi | 3 +- mypy/typeshed/stdlib/email/utils.pyi | 3 +- mypy/typeshed/stdlib/enum.pyi | 4 +- mypy/typeshed/stdlib/errno.pyi | 2 +- mypy/typeshed/stdlib/filecmp.pyi | 3 +- mypy/typeshed/stdlib/fileinput.pyi | 3 +- mypy/typeshed/stdlib/fnmatch.pyi | 3 +- mypy/typeshed/stdlib/formatter.pyi | 8 +- mypy/typeshed/stdlib/fractions.pyi | 4 +- mypy/typeshed/stdlib/ftplib.pyi | 3 +- mypy/typeshed/stdlib/functools.pyi | 9 +- mypy/typeshed/stdlib/gc.pyi | 7 +- mypy/typeshed/stdlib/genericpath.pyi | 3 +- mypy/typeshed/stdlib/gettext.pyi | 26 +- mypy/typeshed/stdlib/glob.pyi | 3 +- mypy/typeshed/stdlib/graphlib.pyi | 3 +- mypy/typeshed/stdlib/gzip.pyi | 8 +- mypy/typeshed/stdlib/hashlib.pyi | 78 +++- mypy/typeshed/stdlib/heapq.pyi | 3 +- mypy/typeshed/stdlib/hmac.pyi | 8 +- mypy/typeshed/stdlib/http/client.pyi | 6 +- mypy/typeshed/stdlib/http/cookiejar.pyi | 3 +- mypy/typeshed/stdlib/http/cookies.pyi | 6 +- mypy/typeshed/stdlib/http/server.pyi | 3 +- mypy/typeshed/stdlib/imaplib.pyi | 12 +- mypy/typeshed/stdlib/imghdr.pyi | 3 +- mypy/typeshed/stdlib/importlib/__init__.pyi | 2 +- mypy/typeshed/stdlib/importlib/abc.pyi | 7 +- mypy/typeshed/stdlib/importlib/machinery.pyi | 3 +- .../stdlib/importlib/metadata/__init__.pyi | 4 +- .../stdlib/importlib/metadata/_meta.pyi | 3 +- mypy/typeshed/stdlib/importlib/resources.pyi | 8 +- mypy/typeshed/stdlib/importlib/util.pyi | 3 +- mypy/typeshed/stdlib/inspect.pyi | 15 +- mypy/typeshed/stdlib/io.pyi | 3 +- mypy/typeshed/stdlib/ipaddress.pyi | 9 +- mypy/typeshed/stdlib/itertools.pyi | 114 +++++- mypy/typeshed/stdlib/json/__init__.pyi | 3 +- mypy/typeshed/stdlib/json/decoder.pyi | 3 +- mypy/typeshed/stdlib/json/encoder.pyi | 3 +- mypy/typeshed/stdlib/keyword.pyi | 2 +- mypy/typeshed/stdlib/lib2to3/pgen2/driver.pyi | 3 +- .../typeshed/stdlib/lib2to3/pgen2/grammar.pyi | 7 +- mypy/typeshed/stdlib/lib2to3/pgen2/parse.pyi | 6 +- mypy/typeshed/stdlib/lib2to3/pgen2/pgen.pyi | 3 +- .../stdlib/lib2to3/pgen2/tokenize.pyi | 9 +- mypy/typeshed/stdlib/lib2to3/pytree.pyi | 14 +- mypy/typeshed/stdlib/lib2to3/refactor.pyi | 5 +- mypy/typeshed/stdlib/linecache.pyi | 5 +- mypy/typeshed/stdlib/locale.pyi | 3 +- mypy/typeshed/stdlib/logging/__init__.pyi | 14 +- mypy/typeshed/stdlib/logging/config.pyi | 9 +- mypy/typeshed/stdlib/lzma.pyi | 13 +- mypy/typeshed/stdlib/mailbox.pyi | 7 +- mypy/typeshed/stdlib/mailcap.pyi | 5 +- mypy/typeshed/stdlib/math.pyi | 9 +- mypy/typeshed/stdlib/mimetypes.pyi | 3 +- mypy/typeshed/stdlib/mmap.pyi | 3 +- mypy/typeshed/stdlib/modulefinder.pyi | 3 +- mypy/typeshed/stdlib/msilib/__init__.pyi | 3 +- mypy/typeshed/stdlib/msilib/sequence.pyi | 3 +- .../stdlib/multiprocessing/__init__.pyi | 27 +- .../stdlib/multiprocessing/connection.pyi | 7 +- .../stdlib/multiprocessing/context.pyi | 4 +- .../stdlib/multiprocessing/dummy/__init__.pyi | 3 +- .../multiprocessing/dummy/connection.pyi | 3 +- .../stdlib/multiprocessing/managers.pyi | 15 +- mypy/typeshed/stdlib/multiprocessing/pool.pyi | 3 +- .../stdlib/multiprocessing/shared_memory.pyi | 3 +- .../typeshed/stdlib/multiprocessing/spawn.pyi | 3 +- .../stdlib/multiprocessing/synchronize.pyi | 6 +- mypy/typeshed/stdlib/netrc.pyi | 3 +- mypy/typeshed/stdlib/nntplib.pyi | 10 +- mypy/typeshed/stdlib/optparse.pyi | 3 +- mypy/typeshed/stdlib/os/__init__.pyi | 38 +- mypy/typeshed/stdlib/parser.pyi | 3 +- mypy/typeshed/stdlib/pathlib.pyi | 3 +- mypy/typeshed/stdlib/pdb.pyi | 3 +- mypy/typeshed/stdlib/pickle.pyi | 25 +- mypy/typeshed/stdlib/pickletools.pyi | 6 +- mypy/typeshed/stdlib/pkgutil.pyi | 3 +- mypy/typeshed/stdlib/plistlib.pyi | 3 +- mypy/typeshed/stdlib/poplib.pyi | 7 +- mypy/typeshed/stdlib/posixpath.pyi | 3 +- mypy/typeshed/stdlib/profile.pyi | 7 +- mypy/typeshed/stdlib/pstats.pyi | 9 +- mypy/typeshed/stdlib/pty.pyi | 6 +- mypy/typeshed/stdlib/pydoc.pyi | 13 +- mypy/typeshed/stdlib/pyexpat/__init__.pyi | 7 +- mypy/typeshed/stdlib/random.pyi | 5 +- mypy/typeshed/stdlib/re.pyi | 6 +- mypy/typeshed/stdlib/readline.pyi | 7 +- mypy/typeshed/stdlib/reprlib.pyi | 6 +- mypy/typeshed/stdlib/sched.pyi | 3 +- mypy/typeshed/stdlib/select.pyi | 3 +- mypy/typeshed/stdlib/selectors.pyi | 6 +- mypy/typeshed/stdlib/shlex.pyi | 3 +- mypy/typeshed/stdlib/shutil.pyi | 8 +- mypy/typeshed/stdlib/signal.pyi | 9 +- mypy/typeshed/stdlib/site.pyi | 2 +- mypy/typeshed/stdlib/smtpd.pyi | 3 +- mypy/typeshed/stdlib/smtplib.pyi | 10 +- mypy/typeshed/stdlib/socketserver.pyi | 8 +- mypy/typeshed/stdlib/sqlite3/dbapi2.pyi | 377 ++++++++++++++---- mypy/typeshed/stdlib/sre_parse.pyi | 24 +- mypy/typeshed/stdlib/ssl.pyi | 23 +- mypy/typeshed/stdlib/statistics.pyi | 7 +- mypy/typeshed/stdlib/string.pyi | 3 +- mypy/typeshed/stdlib/struct.pyi | 3 +- mypy/typeshed/stdlib/subprocess.pyi | 17 +- mypy/typeshed/stdlib/sunau.pyi | 4 +- mypy/typeshed/stdlib/symtable.pyi | 3 +- mypy/typeshed/stdlib/sys.pyi | 29 +- mypy/typeshed/stdlib/tabnanny.pyi | 2 +- mypy/typeshed/stdlib/tarfile.pyi | 4 +- mypy/typeshed/stdlib/telnetlib.pyi | 3 +- mypy/typeshed/stdlib/tempfile.pyi | 7 +- mypy/typeshed/stdlib/termios.pyi | 3 +- mypy/typeshed/stdlib/textwrap.pyi | 3 +- mypy/typeshed/stdlib/threading.pyi | 8 +- mypy/typeshed/stdlib/time.pyi | 4 +- mypy/typeshed/stdlib/timeit.pyi | 8 +- mypy/typeshed/stdlib/tkinter/__init__.pyi | 45 ++- mypy/typeshed/stdlib/tkinter/commondialog.pyi | 3 +- mypy/typeshed/stdlib/tkinter/dialog.pyi | 3 +- mypy/typeshed/stdlib/tkinter/filedialog.pyi | 3 +- mypy/typeshed/stdlib/tkinter/font.pyi | 4 +- mypy/typeshed/stdlib/tkinter/ttk.pyi | 9 +- mypy/typeshed/stdlib/tokenize.pyi | 8 +- mypy/typeshed/stdlib/trace.pyi | 9 +- mypy/typeshed/stdlib/traceback.pyi | 7 +- mypy/typeshed/stdlib/tracemalloc.pyi | 11 +- mypy/typeshed/stdlib/tty.pyi | 3 +- mypy/typeshed/stdlib/turtle.pyi | 16 +- mypy/typeshed/stdlib/types.pyi | 15 +- mypy/typeshed/stdlib/typing.pyi | 16 +- mypy/typeshed/stdlib/typing_extensions.pyi | 35 +- mypy/typeshed/stdlib/unittest/async_case.pyi | 2 +- mypy/typeshed/stdlib/unittest/case.pyi | 19 +- mypy/typeshed/stdlib/unittest/loader.pyi | 8 +- mypy/typeshed/stdlib/unittest/main.pyi | 3 +- mypy/typeshed/stdlib/unittest/mock.pyi | 19 +- mypy/typeshed/stdlib/unittest/result.pyi | 15 +- mypy/typeshed/stdlib/unittest/runner.pyi | 6 +- mypy/typeshed/stdlib/unittest/signals.pyi | 3 +- mypy/typeshed/stdlib/unittest/suite.pyi | 5 +- mypy/typeshed/stdlib/unittest/util.pyi | 6 +- mypy/typeshed/stdlib/urllib/parse.pyi | 6 +- mypy/typeshed/stdlib/urllib/request.pyi | 8 +- mypy/typeshed/stdlib/urllib/response.pyi | 3 +- mypy/typeshed/stdlib/urllib/robotparser.pyi | 3 +- mypy/typeshed/stdlib/uu.pyi | 3 +- mypy/typeshed/stdlib/uuid.pyi | 7 +- mypy/typeshed/stdlib/venv/__init__.pyi | 2 +- mypy/typeshed/stdlib/warnings.pyi | 7 +- mypy/typeshed/stdlib/wave.pyi | 4 +- mypy/typeshed/stdlib/weakref.pyi | 3 +- mypy/typeshed/stdlib/webbrowser.pyi | 2 +- mypy/typeshed/stdlib/winreg.pyi | 4 +- mypy/typeshed/stdlib/wsgiref/handlers.pyi | 13 +- mypy/typeshed/stdlib/wsgiref/headers.pyi | 3 +- .../typeshed/stdlib/wsgiref/simple_server.pyi | 2 +- mypy/typeshed/stdlib/wsgiref/types.pyi | 33 +- mypy/typeshed/stdlib/wsgiref/util.pyi | 6 +- mypy/typeshed/stdlib/wsgiref/validate.pyi | 3 +- mypy/typeshed/stdlib/xdrlib.pyi | 3 +- mypy/typeshed/stdlib/xml/dom/domreg.pyi | 2 +- mypy/typeshed/stdlib/xml/dom/minicompat.pyi | 3 +- mypy/typeshed/stdlib/xml/dom/pulldom.pyi | 11 +- mypy/typeshed/stdlib/xml/dom/xmlbuilder.pyi | 10 +- .../stdlib/xml/etree/ElementInclude.pyi | 2 +- .../typeshed/stdlib/xml/etree/ElementPath.pyi | 10 +- .../typeshed/stdlib/xml/etree/ElementTree.pyi | 26 +- mypy/typeshed/stdlib/xml/sax/__init__.pyi | 3 +- mypy/typeshed/stdlib/xml/sax/saxutils.pyi | 2 +- mypy/typeshed/stdlib/xml/sax/xmlreader.pyi | 2 +- mypy/typeshed/stdlib/xmlrpc/client.pyi | 13 +- mypy/typeshed/stdlib/xmlrpc/server.pyi | 10 +- mypy/typeshed/stdlib/zipapp.pyi | 6 +- mypy/typeshed/stdlib/zipfile.pyi | 13 +- mypy/typeshed/stdlib/zoneinfo/__init__.pyi | 3 +- test-data/unit/plugins/decimal_to_int.py | 2 +- 289 files changed, 2086 insertions(+), 1454 deletions(-) diff --git a/mypy/test/teststubtest.py b/mypy/test/teststubtest.py index 869d2e110a66b..2983c23d51500 100644 --- a/mypy/test/teststubtest.py +++ b/mypy/test/teststubtest.py @@ -1174,7 +1174,7 @@ def test_config_file(self) -> None: output = run_stubtest(stub=stub, runtime=runtime, options=[]) assert remove_color_code(output) == ( "error: test_module.temp variable differs from runtime type Literal[5]\n" - "Stub: at line 2\ndecimal.Decimal\nRuntime:\n5\n\n" + "Stub: at line 2\n_decimal.Decimal\nRuntime:\n5\n\n" ) output = run_stubtest(stub=stub, runtime=runtime, options=[], config_file=config_file) assert output == "" diff --git a/mypy/typeshed/stdlib/VERSIONS b/mypy/typeshed/stdlib/VERSIONS index d3ba459dd9e36..eefc7b895436f 100644 --- a/mypy/typeshed/stdlib/VERSIONS +++ b/mypy/typeshed/stdlib/VERSIONS @@ -286,6 +286,7 @@ webbrowser: 2.7- winreg: 3.0- winsound: 2.7- wsgiref: 2.7- +wsgiref.types: 3.11- xdrlib: 2.7- xml: 2.7- xmlrpc: 3.0- diff --git a/mypy/typeshed/stdlib/_ast.pyi b/mypy/typeshed/stdlib/_ast.pyi index f801b5deb0d97..cb13c74520813 100644 --- a/mypy/typeshed/stdlib/_ast.pyi +++ b/mypy/typeshed/stdlib/_ast.pyi @@ -1,13 +1,13 @@ import sys from typing import Any, ClassVar -from typing_extensions import Literal +from typing_extensions import Literal, TypeAlias PyCF_ONLY_AST: Literal[1024] if sys.version_info >= (3, 8): PyCF_TYPE_COMMENTS: Literal[4096] PyCF_ALLOW_TOP_LEVEL_AWAIT: Literal[8192] -_identifier = str +_identifier: TypeAlias = str class AST: if sys.version_info >= (3, 10): @@ -172,6 +172,14 @@ class Try(stmt): orelse: list[stmt] finalbody: list[stmt] +if sys.version_info >= (3, 11): + class TryStar(stmt): + __match_args__ = ("body", "handlers", "orelse", "finalbody") + body: list[stmt] + handlers: list[ExceptHandler] + orelse: list[stmt] + finalbody: list[stmt] + class Assert(stmt): if sys.version_info >= (3, 10): __match_args__ = ("test", "msg") @@ -358,10 +366,10 @@ class Attribute(expr): ctx: expr_context if sys.version_info >= (3, 9): - _SliceT = expr + _SliceT: TypeAlias = expr else: class slice(AST): ... - _SliceT = slice + _SliceT: TypeAlias = slice class Slice(_SliceT): if sys.version_info >= (3, 10): @@ -516,7 +524,7 @@ if sys.version_info >= (3, 10): class pattern(AST): ... # Without the alias, Pyright complains variables named pattern are recursively defined - _pattern = pattern + _pattern: TypeAlias = pattern class match_case(AST): __match_args__ = ("pattern", "guard", "body") diff --git a/mypy/typeshed/stdlib/_bisect.pyi b/mypy/typeshed/stdlib/_bisect.pyi index 5608094ccbd6b..d902e1eea7d44 100644 --- a/mypy/typeshed/stdlib/_bisect.pyi +++ b/mypy/typeshed/stdlib/_bisect.pyi @@ -1,6 +1,7 @@ import sys from _typeshed import SupportsRichComparisonT -from typing import Callable, MutableSequence, Sequence, TypeVar, overload +from collections.abc import Callable, MutableSequence, Sequence +from typing import TypeVar, overload _T = TypeVar("_T") diff --git a/mypy/typeshed/stdlib/_codecs.pyi b/mypy/typeshed/stdlib/_codecs.pyi index 1781a2418ca05..e335f6d5119a6 100644 --- a/mypy/typeshed/stdlib/_codecs.pyi +++ b/mypy/typeshed/stdlib/_codecs.pyi @@ -1,13 +1,15 @@ import codecs import sys -from typing import Any, Callable +from collections.abc import Callable +from typing import Any +from typing_extensions import TypeAlias # This type is not exposed; it is defined in unicodeobject.c class _EncodingMap: def size(self) -> int: ... -_MapT = dict[int, int] | _EncodingMap -_Handler = Callable[[Exception], tuple[str, int]] +_MapT: TypeAlias = dict[int, int] | _EncodingMap +_Handler: TypeAlias = Callable[[Exception], tuple[str, int]] def register(__search_function: Callable[[str], Any]) -> None: ... def register_error(__errors: str, __handler: _Handler) -> None: ... diff --git a/mypy/typeshed/stdlib/_collections_abc.pyi b/mypy/typeshed/stdlib/_collections_abc.pyi index bd8d35641b375..8373fe836330b 100644 --- a/mypy/typeshed/stdlib/_collections_abc.pyi +++ b/mypy/typeshed/stdlib/_collections_abc.pyi @@ -1,6 +1,6 @@ import sys from types import MappingProxyType -from typing import ( +from typing import ( # noqa: Y027,Y038 AbstractSet as Set, AsyncGenerator as AsyncGenerator, AsyncIterable as AsyncIterable, diff --git a/mypy/typeshed/stdlib/_compression.pyi b/mypy/typeshed/stdlib/_compression.pyi index e71f7d14bd2b0..ec3c7fe708566 100644 --- a/mypy/typeshed/stdlib/_compression.pyi +++ b/mypy/typeshed/stdlib/_compression.pyi @@ -1,6 +1,7 @@ from _typeshed import WriteableBuffer +from collections.abc import Callable from io import DEFAULT_BUFFER_SIZE, BufferedIOBase, RawIOBase -from typing import Any, Callable, Protocol +from typing import Any, Protocol BUFFER_SIZE = DEFAULT_BUFFER_SIZE diff --git a/mypy/typeshed/stdlib/_csv.pyi b/mypy/typeshed/stdlib/_csv.pyi index 161a89778de8d..ae9031df6e818 100644 --- a/mypy/typeshed/stdlib/_csv.pyi +++ b/mypy/typeshed/stdlib/_csv.pyi @@ -1,5 +1,6 @@ -from typing import Any, Iterable, Iterator, Protocol, Union -from typing_extensions import Literal +from collections.abc import Iterable, Iterator +from typing import Any, Protocol, Union +from typing_extensions import Literal, TypeAlias __version__: str @@ -21,7 +22,7 @@ class Dialect: strict: int def __init__(self) -> None: ... -_DialectLike = Union[str, Dialect, type[Dialect]] +_DialectLike: TypeAlias = Union[str, Dialect, type[Dialect]] class _reader(Iterator[list[str]]): dialect: Dialect diff --git a/mypy/typeshed/stdlib/_curses.pyi b/mypy/typeshed/stdlib/_curses.pyi index e193759bdc6eb..95a128a322569 100644 --- a/mypy/typeshed/stdlib/_curses.pyi +++ b/mypy/typeshed/stdlib/_curses.pyi @@ -1,10 +1,10 @@ import sys from _typeshed import SupportsRead from typing import IO, Any, NamedTuple, overload -from typing_extensions import final +from typing_extensions import TypeAlias, final if sys.platform != "win32": - _chtype = str | bytes | int + _chtype: TypeAlias = str | bytes | int # ACS codes are only initialized after initscr is called ACS_BBSS: int diff --git a/mypy/typeshed/stdlib/_decimal.pyi b/mypy/typeshed/stdlib/_decimal.pyi index de49a787283d6..fdeca8f7c42fd 100644 --- a/mypy/typeshed/stdlib/_decimal.pyi +++ b/mypy/typeshed/stdlib/_decimal.pyi @@ -1,3 +1,265 @@ -from decimal import * +import numbers +import sys +from _typeshed import Self +from collections.abc import Container, Sequence +from types import TracebackType +from typing import Any, NamedTuple, Union, overload +from typing_extensions import TypeAlias +_Decimal: TypeAlias = Decimal | int +_DecimalNew: TypeAlias = Union[Decimal, float, str, tuple[int, Sequence[int], int]] +_ComparableNum: TypeAlias = Decimal | float | numbers.Rational + +__version__: str __libmpdec_version__: str + +class DecimalTuple(NamedTuple): + sign: int + digits: tuple[int, ...] + exponent: int + +ROUND_DOWN: str +ROUND_HALF_UP: str +ROUND_HALF_EVEN: str +ROUND_CEILING: str +ROUND_FLOOR: str +ROUND_UP: str +ROUND_HALF_DOWN: str +ROUND_05UP: str + +if sys.version_info >= (3, 7): + HAVE_CONTEXTVAR: bool +HAVE_THREADS: bool +MAX_EMAX: int +MAX_PREC: int +MIN_EMIN: int +MIN_ETINY: int + +class DecimalException(ArithmeticError): ... +class Clamped(DecimalException): ... +class InvalidOperation(DecimalException): ... +class ConversionSyntax(InvalidOperation): ... +class DivisionByZero(DecimalException, ZeroDivisionError): ... +class DivisionImpossible(InvalidOperation): ... +class DivisionUndefined(InvalidOperation, ZeroDivisionError): ... +class Inexact(DecimalException): ... +class InvalidContext(InvalidOperation): ... +class Rounded(DecimalException): ... +class Subnormal(DecimalException): ... +class Overflow(Inexact, Rounded): ... +class Underflow(Inexact, Rounded, Subnormal): ... +class FloatOperation(DecimalException, TypeError): ... + +def setcontext(__context: Context) -> None: ... +def getcontext() -> Context: ... +def localcontext(ctx: Context | None = ...) -> _ContextManager: ... + +class Decimal: + def __new__(cls: type[Self], value: _DecimalNew = ..., context: Context | None = ...) -> Self: ... + @classmethod + def from_float(cls: type[Self], __f: float) -> Self: ... + def __bool__(self) -> bool: ... + def compare(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def __hash__(self) -> int: ... + def as_tuple(self) -> DecimalTuple: ... + def as_integer_ratio(self) -> tuple[int, int]: ... + def to_eng_string(self, context: Context | None = ...) -> str: ... + def __abs__(self) -> Decimal: ... + def __add__(self, __other: _Decimal) -> Decimal: ... + def __divmod__(self, __other: _Decimal) -> tuple[Decimal, Decimal]: ... + def __eq__(self, __other: object) -> bool: ... + def __floordiv__(self, __other: _Decimal) -> Decimal: ... + def __ge__(self, __other: _ComparableNum) -> bool: ... + def __gt__(self, __other: _ComparableNum) -> bool: ... + def __le__(self, __other: _ComparableNum) -> bool: ... + def __lt__(self, __other: _ComparableNum) -> bool: ... + def __mod__(self, __other: _Decimal) -> Decimal: ... + def __mul__(self, __other: _Decimal) -> Decimal: ... + def __neg__(self) -> Decimal: ... + def __pos__(self) -> Decimal: ... + def __pow__(self, __other: _Decimal, __modulo: _Decimal | None = ...) -> Decimal: ... + def __radd__(self, __other: _Decimal) -> Decimal: ... + def __rdivmod__(self, __other: _Decimal) -> tuple[Decimal, Decimal]: ... + def __rfloordiv__(self, __other: _Decimal) -> Decimal: ... + def __rmod__(self, __other: _Decimal) -> Decimal: ... + def __rmul__(self, __other: _Decimal) -> Decimal: ... + def __rsub__(self, __other: _Decimal) -> Decimal: ... + def __rtruediv__(self, __other: _Decimal) -> Decimal: ... + def __sub__(self, __other: _Decimal) -> Decimal: ... + def __truediv__(self, __other: _Decimal) -> Decimal: ... + def remainder_near(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def __float__(self) -> float: ... + def __int__(self) -> int: ... + def __trunc__(self) -> int: ... + @property + def real(self) -> Decimal: ... + @property + def imag(self) -> Decimal: ... + def conjugate(self) -> Decimal: ... + def __complex__(self) -> complex: ... + @overload + def __round__(self) -> int: ... + @overload + def __round__(self, __ndigits: int) -> Decimal: ... + def __floor__(self) -> int: ... + def __ceil__(self) -> int: ... + def fma(self, other: _Decimal, third: _Decimal, context: Context | None = ...) -> Decimal: ... + def __rpow__(self, __other: _Decimal, __context: Context | None = ...) -> Decimal: ... + def normalize(self, context: Context | None = ...) -> Decimal: ... + def quantize(self, exp: _Decimal, rounding: str | None = ..., context: Context | None = ...) -> Decimal: ... + def same_quantum(self, other: _Decimal, context: Context | None = ...) -> bool: ... + def to_integral_exact(self, rounding: str | None = ..., context: Context | None = ...) -> Decimal: ... + def to_integral_value(self, rounding: str | None = ..., context: Context | None = ...) -> Decimal: ... + def to_integral(self, rounding: str | None = ..., context: Context | None = ...) -> Decimal: ... + def sqrt(self, context: Context | None = ...) -> Decimal: ... + def max(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def min(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def adjusted(self) -> int: ... + def canonical(self) -> Decimal: ... + def compare_signal(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def compare_total(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def compare_total_mag(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def copy_abs(self) -> Decimal: ... + def copy_negate(self) -> Decimal: ... + def copy_sign(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def exp(self, context: Context | None = ...) -> Decimal: ... + def is_canonical(self) -> bool: ... + def is_finite(self) -> bool: ... + def is_infinite(self) -> bool: ... + def is_nan(self) -> bool: ... + def is_normal(self, context: Context | None = ...) -> bool: ... + def is_qnan(self) -> bool: ... + def is_signed(self) -> bool: ... + def is_snan(self) -> bool: ... + def is_subnormal(self, context: Context | None = ...) -> bool: ... + def is_zero(self) -> bool: ... + def ln(self, context: Context | None = ...) -> Decimal: ... + def log10(self, context: Context | None = ...) -> Decimal: ... + def logb(self, context: Context | None = ...) -> Decimal: ... + def logical_and(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def logical_invert(self, context: Context | None = ...) -> Decimal: ... + def logical_or(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def logical_xor(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def max_mag(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def min_mag(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def next_minus(self, context: Context | None = ...) -> Decimal: ... + def next_plus(self, context: Context | None = ...) -> Decimal: ... + def next_toward(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def number_class(self, context: Context | None = ...) -> str: ... + def radix(self) -> Decimal: ... + def rotate(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def scaleb(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def shift(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... + def __reduce__(self: Self) -> tuple[type[Self], tuple[str]]: ... + def __copy__(self: Self) -> Self: ... + def __deepcopy__(self: Self, __memo: Any) -> Self: ... + def __format__(self, __specifier: str, __context: Context | None = ...) -> str: ... + +class _ContextManager: + new_context: Context + saved_context: Context + def __init__(self, new_context: Context) -> None: ... + def __enter__(self) -> Context: ... + def __exit__(self, t: type[BaseException] | None, v: BaseException | None, tb: TracebackType | None) -> None: ... + +_TrapType: TypeAlias = type[DecimalException] + +class Context: + prec: int + rounding: str + Emin: int + Emax: int + capitals: int + clamp: int + traps: dict[_TrapType, bool] + flags: dict[_TrapType, bool] + def __init__( + self, + prec: int | None = ..., + rounding: str | None = ..., + Emin: int | None = ..., + Emax: int | None = ..., + capitals: int | None = ..., + clamp: int | None = ..., + flags: None | dict[_TrapType, bool] | Container[_TrapType] = ..., + traps: None | dict[_TrapType, bool] | Container[_TrapType] = ..., + _ignored_flags: list[_TrapType] | None = ..., + ) -> None: ... + # __setattr__() only allows to set a specific set of attributes, + # already defined above. + def __delattr__(self, __name: str) -> None: ... + def __reduce__(self: Self) -> tuple[type[Self], tuple[Any, ...]]: ... + def clear_flags(self) -> None: ... + def clear_traps(self) -> None: ... + def copy(self) -> Context: ... + def __copy__(self) -> Context: ... + __hash__: Any + def Etiny(self) -> int: ... + def Etop(self) -> int: ... + def create_decimal(self, __num: _DecimalNew = ...) -> Decimal: ... + def create_decimal_from_float(self, __f: float) -> Decimal: ... + def abs(self, __x: _Decimal) -> Decimal: ... + def add(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def canonical(self, __x: Decimal) -> Decimal: ... + def compare(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def compare_signal(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def compare_total(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def compare_total_mag(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def copy_abs(self, __x: _Decimal) -> Decimal: ... + def copy_decimal(self, __x: _Decimal) -> Decimal: ... + def copy_negate(self, __x: _Decimal) -> Decimal: ... + def copy_sign(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def divide(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def divide_int(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def divmod(self, __x: _Decimal, __y: _Decimal) -> tuple[Decimal, Decimal]: ... + def exp(self, __x: _Decimal) -> Decimal: ... + def fma(self, __x: _Decimal, __y: _Decimal, __z: _Decimal) -> Decimal: ... + def is_canonical(self, __x: _Decimal) -> bool: ... + def is_finite(self, __x: _Decimal) -> bool: ... + def is_infinite(self, __x: _Decimal) -> bool: ... + def is_nan(self, __x: _Decimal) -> bool: ... + def is_normal(self, __x: _Decimal) -> bool: ... + def is_qnan(self, __x: _Decimal) -> bool: ... + def is_signed(self, __x: _Decimal) -> bool: ... + def is_snan(self, __x: _Decimal) -> bool: ... + def is_subnormal(self, __x: _Decimal) -> bool: ... + def is_zero(self, __x: _Decimal) -> bool: ... + def ln(self, __x: _Decimal) -> Decimal: ... + def log10(self, __x: _Decimal) -> Decimal: ... + def logb(self, __x: _Decimal) -> Decimal: ... + def logical_and(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def logical_invert(self, __x: _Decimal) -> Decimal: ... + def logical_or(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def logical_xor(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def max(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def max_mag(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def min(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def min_mag(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def minus(self, __x: _Decimal) -> Decimal: ... + def multiply(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def next_minus(self, __x: _Decimal) -> Decimal: ... + def next_plus(self, __x: _Decimal) -> Decimal: ... + def next_toward(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def normalize(self, __x: _Decimal) -> Decimal: ... + def number_class(self, __x: _Decimal) -> str: ... + def plus(self, __x: _Decimal) -> Decimal: ... + def power(self, a: _Decimal, b: _Decimal, modulo: _Decimal | None = ...) -> Decimal: ... + def quantize(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def radix(self) -> Decimal: ... + def remainder(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def remainder_near(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def rotate(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def same_quantum(self, __x: _Decimal, __y: _Decimal) -> bool: ... + def scaleb(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def shift(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def sqrt(self, __x: _Decimal) -> Decimal: ... + def subtract(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... + def to_eng_string(self, __x: _Decimal) -> str: ... + def to_sci_string(self, __x: _Decimal) -> str: ... + def to_integral_exact(self, __x: _Decimal) -> Decimal: ... + def to_integral_value(self, __x: _Decimal) -> Decimal: ... + def to_integral(self, __x: _Decimal) -> Decimal: ... + +DefaultContext: Context +BasicContext: Context +ExtendedContext: Context diff --git a/mypy/typeshed/stdlib/_dummy_thread.pyi b/mypy/typeshed/stdlib/_dummy_thread.pyi index 97ba17ae497d4..f257b758eeab3 100644 --- a/mypy/typeshed/stdlib/_dummy_thread.pyi +++ b/mypy/typeshed/stdlib/_dummy_thread.pyi @@ -1,5 +1,6 @@ +from collections.abc import Callable from types import TracebackType -from typing import Any, Callable, NoReturn +from typing import Any, NoReturn TIMEOUT_MAX: int error = RuntimeError diff --git a/mypy/typeshed/stdlib/_dummy_threading.pyi b/mypy/typeshed/stdlib/_dummy_threading.pyi index 1cbb8f1ee8c8a..2daceaedd4add 100644 --- a/mypy/typeshed/stdlib/_dummy_threading.pyi +++ b/mypy/typeshed/stdlib/_dummy_threading.pyi @@ -1,11 +1,13 @@ import sys +from collections.abc import Callable, Iterable, Mapping from types import FrameType, TracebackType -from typing import Any, Callable, Iterable, Mapping, TypeVar +from typing import Any, TypeVar +from typing_extensions import TypeAlias # TODO recursive type -_TF = Callable[[FrameType, str, Any], Callable[..., Any] | None] +_TF: TypeAlias = Callable[[FrameType, str, Any], Callable[..., Any] | None] -_PF = Callable[[FrameType, str, Any], None] +_PF: TypeAlias = Callable[[FrameType, str, Any], None] _T = TypeVar("_T") if sys.version_info >= (3, 8): diff --git a/mypy/typeshed/stdlib/_json.pyi b/mypy/typeshed/stdlib/_json.pyi index 962fa9ec257ad..130f7ab92e976 100644 --- a/mypy/typeshed/stdlib/_json.pyi +++ b/mypy/typeshed/stdlib/_json.pyi @@ -1,4 +1,5 @@ -from typing import Any, Callable +from collections.abc import Callable +from typing import Any from typing_extensions import final @final diff --git a/mypy/typeshed/stdlib/_operator.pyi b/mypy/typeshed/stdlib/_operator.pyi index 375d8e4ddfbfb..92e04d0f499d8 100644 --- a/mypy/typeshed/stdlib/_operator.pyi +++ b/mypy/typeshed/stdlib/_operator.pyi @@ -1,21 +1,7 @@ import sys -from typing import ( - Any, - AnyStr, - Callable, - Container, - Generic, - Iterable, - Mapping, - MutableMapping, - MutableSequence, - Protocol, - Sequence, - SupportsAbs, - TypeVar, - overload, -) -from typing_extensions import ParamSpec, SupportsIndex, final +from collections.abc import Callable, Container, Iterable, Mapping, MutableMapping, MutableSequence, Sequence +from typing import Any, AnyStr, Generic, Protocol, SupportsAbs, TypeVar, overload +from typing_extensions import ParamSpec, SupportsIndex, TypeAlias, final _R = TypeVar("_R") _T = TypeVar("_T") @@ -40,7 +26,7 @@ class _SupportsDunderLE(Protocol): class _SupportsDunderGE(Protocol): def __ge__(self, __other: Any) -> Any: ... -_SupportsComparison = _SupportsDunderLE | _SupportsDunderGE | _SupportsDunderGT | _SupportsDunderLT +_SupportsComparison: TypeAlias = _SupportsDunderLE | _SupportsDunderGE | _SupportsDunderGT | _SupportsDunderLT class _SupportsInversion(Protocol[_T_co]): def __invert__(self) -> _T_co: ... diff --git a/mypy/typeshed/stdlib/_osx_support.pyi b/mypy/typeshed/stdlib/_osx_support.pyi index cb43fa93bb808..7fd0ee922ca6f 100644 --- a/mypy/typeshed/stdlib/_osx_support.pyi +++ b/mypy/typeshed/stdlib/_osx_support.pyi @@ -1,5 +1,6 @@ import sys -from typing import Iterable, Sequence, TypeVar +from collections.abc import Iterable, Sequence +from typing import TypeVar _T = TypeVar("_T") _K = TypeVar("_K") diff --git a/mypy/typeshed/stdlib/_posixsubprocess.pyi b/mypy/typeshed/stdlib/_posixsubprocess.pyi index 5481100cacfc9..2d221c4896f6a 100644 --- a/mypy/typeshed/stdlib/_posixsubprocess.pyi +++ b/mypy/typeshed/stdlib/_posixsubprocess.pyi @@ -1,5 +1,5 @@ import sys -from typing import Callable, Sequence +from collections.abc import Callable, Sequence if sys.platform != "win32": def cloexec_pipe() -> tuple[int, int]: ... diff --git a/mypy/typeshed/stdlib/_pydecimal.pyi b/mypy/typeshed/stdlib/_pydecimal.pyi index c15a4a41747e5..90dbef1dc2e2d 100644 --- a/mypy/typeshed/stdlib/_pydecimal.pyi +++ b/mypy/typeshed/stdlib/_pydecimal.pyi @@ -2,7 +2,7 @@ import sys # This is a slight lie, the implementations aren't exactly identical # However, in all likelihood, the differences are inconsequential -from decimal import * +from _decimal import * if sys.version_info >= (3, 7): __all__ = [ diff --git a/mypy/typeshed/stdlib/_random.pyi b/mypy/typeshed/stdlib/_random.pyi index 9aff4b3cb0260..c4b235f0cd5b6 100644 --- a/mypy/typeshed/stdlib/_random.pyi +++ b/mypy/typeshed/stdlib/_random.pyi @@ -1,5 +1,7 @@ +from typing_extensions import TypeAlias + # Actually Tuple[(int,) * 625] -_State = tuple[int, ...] +_State: TypeAlias = tuple[int, ...] class Random: def __init__(self, seed: object = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/_sitebuiltins.pyi b/mypy/typeshed/stdlib/_sitebuiltins.pyi index a71364b8db656..4a35921e1ef7a 100644 --- a/mypy/typeshed/stdlib/_sitebuiltins.pyi +++ b/mypy/typeshed/stdlib/_sitebuiltins.pyi @@ -1,4 +1,5 @@ -from typing import ClassVar, Iterable, NoReturn +from collections.abc import Iterable +from typing import ClassVar, NoReturn from typing_extensions import Literal class Quitter: diff --git a/mypy/typeshed/stdlib/_socket.pyi b/mypy/typeshed/stdlib/_socket.pyi index a8cf16823d4e2..2366412050cdc 100644 --- a/mypy/typeshed/stdlib/_socket.pyi +++ b/mypy/typeshed/stdlib/_socket.pyi @@ -2,21 +2,22 @@ import sys from _typeshed import ReadableBuffer, WriteableBuffer from collections.abc import Iterable from typing import Any, SupportsInt, overload +from typing_extensions import TypeAlias if sys.version_info >= (3, 8): from typing import SupportsIndex - _FD = SupportsIndex + _FD: TypeAlias = SupportsIndex else: - _FD = SupportsInt + _FD: TypeAlias = SupportsInt -_CMSG = tuple[int, int, bytes] -_CMSGArg = tuple[int, int, ReadableBuffer] +_CMSG: TypeAlias = tuple[int, int, bytes] +_CMSGArg: TypeAlias = tuple[int, int, ReadableBuffer] # Addresses can be either tuples of varying lengths (AF_INET, AF_INET6, # AF_NETLINK, AF_TIPC) or strings (AF_UNIX). -_Address = tuple[Any, ...] | str -_RetAddress = Any +_Address: TypeAlias = tuple[Any, ...] | str +_RetAddress: TypeAlias = Any # TODO Most methods allow bytes as address objects # ----- Constants ----- diff --git a/mypy/typeshed/stdlib/_thread.pyi b/mypy/typeshed/stdlib/_thread.pyi index 04abf8dc869cd..c5da8ccf3a900 100644 --- a/mypy/typeshed/stdlib/_thread.pyi +++ b/mypy/typeshed/stdlib/_thread.pyi @@ -1,8 +1,9 @@ import sys from _typeshed import structseq +from collections.abc import Callable from threading import Thread from types import TracebackType -from typing import Any, Callable, NoReturn +from typing import Any, NoReturn from typing_extensions import Final, final error = RuntimeError diff --git a/mypy/typeshed/stdlib/_threading_local.pyi b/mypy/typeshed/stdlib/_threading_local.pyi index 2ad77a177c371..def996fba1177 100644 --- a/mypy/typeshed/stdlib/_threading_local.pyi +++ b/mypy/typeshed/stdlib/_threading_local.pyi @@ -1,15 +1,16 @@ from typing import Any +from typing_extensions import TypeAlias from weakref import ReferenceType __all__ = ["local"] -localdict = dict[Any, Any] +_localdict: TypeAlias = dict[Any, Any] class _localimpl: key: str - dicts: dict[int, tuple[ReferenceType[Any], localdict]] + dicts: dict[int, tuple[ReferenceType[Any], _localdict]] def __init__(self) -> None: ... - def get_dict(self) -> localdict: ... - def create_dict(self) -> localdict: ... + def get_dict(self) -> _localdict: ... + def create_dict(self) -> _localdict: ... class local: def __getattribute__(self, name: str) -> Any: ... diff --git a/mypy/typeshed/stdlib/_tracemalloc.pyi b/mypy/typeshed/stdlib/_tracemalloc.pyi index fd159dc586cb6..6e3c4e59a07a9 100644 --- a/mypy/typeshed/stdlib/_tracemalloc.pyi +++ b/mypy/typeshed/stdlib/_tracemalloc.pyi @@ -1,6 +1,6 @@ import sys +from collections.abc import Sequence from tracemalloc import _FrameTupleT, _TraceTupleT -from typing import Sequence def _get_object_traceback(__obj: object) -> Sequence[_FrameTupleT] | None: ... def _get_traces() -> Sequence[_TraceTupleT]: ... diff --git a/mypy/typeshed/stdlib/_typeshed/__init__.pyi b/mypy/typeshed/stdlib/_typeshed/__init__.pyi index b348a329522bc..a80ea0702f772 100644 --- a/mypy/typeshed/stdlib/_typeshed/__init__.pyi +++ b/mypy/typeshed/stdlib/_typeshed/__init__.pyi @@ -6,8 +6,10 @@ import array import ctypes import mmap import sys +from collections.abc import Awaitable, Container, Iterable, Set as AbstractSet from os import PathLike -from typing import AbstractSet, Any, Awaitable, Container, Generic, Iterable, Protocol, TypeVar +from types import TracebackType +from typing import Any, Generic, Protocol, TypeVar, Union from typing_extensions import Final, Literal, TypeAlias, final _KT = TypeVar("_KT") @@ -99,7 +101,7 @@ StrPath: TypeAlias = str | PathLike[str] # stable BytesPath: TypeAlias = bytes | PathLike[bytes] # stable StrOrBytesPath: TypeAlias = str | bytes | PathLike[str] | PathLike[bytes] # stable -OpenTextModeUpdating = Literal[ +OpenTextModeUpdating: TypeAlias = Literal[ "r+", "+r", "rt+", @@ -197,6 +199,9 @@ WriteableBuffer: TypeAlias = bytearray | memoryview | array.array[Any] | mmap.mm # Same as _WriteableBuffer, but also includes read-only buffer types (like bytes). ReadableBuffer: TypeAlias = ReadOnlyBuffer | WriteableBuffer # stable +ExcInfo: TypeAlias = tuple[type[BaseException], BaseException, TracebackType] +OptExcInfo: TypeAlias = Union[ExcInfo, tuple[None, None, None]] + # stable if sys.version_info >= (3, 10): from types import NoneType as NoneType diff --git a/mypy/typeshed/stdlib/_typeshed/wsgi.pyi b/mypy/typeshed/stdlib/_typeshed/wsgi.pyi index 9f036d8f2d336..81ca12910bd97 100644 --- a/mypy/typeshed/stdlib/_typeshed/wsgi.pyi +++ b/mypy/typeshed/stdlib/_typeshed/wsgi.pyi @@ -1,36 +1,44 @@ # Types to support PEP 3333 (WSGI) # +# Obsolete since Python 3.11: Use wsgiref.types instead. +# # See the README.md file in this directory for more information. -from sys import _OptExcInfo -from typing import Any, Callable, Iterable, Protocol +import sys +from _typeshed import OptExcInfo +from collections.abc import Callable, Iterable +from typing import Any, Protocol from typing_extensions import TypeAlias -# stable -class StartResponse(Protocol): - def __call__( - self, status: str, headers: list[tuple[str, str]], exc_info: _OptExcInfo | None = ... - ) -> Callable[[bytes], Any]: ... +class _Readable(Protocol): + def read(self, size: int = ...) -> bytes: ... + # Optional: def close(self) -> object: ... -WSGIEnvironment: TypeAlias = dict[str, Any] # stable -WSGIApplication: TypeAlias = Callable[[WSGIEnvironment, StartResponse], Iterable[bytes]] # stable +if sys.version_info >= (3, 11): + from wsgiref.types import * +else: + # stable + class StartResponse(Protocol): + def __call__( + self, __status: str, __headers: list[tuple[str, str]], __exc_info: OptExcInfo | None = ... + ) -> Callable[[bytes], object]: ... -# WSGI input streams per PEP 3333, stable -class InputStream(Protocol): - def read(self, size: int = ...) -> bytes: ... - def readline(self, size: int = ...) -> bytes: ... - def readlines(self, hint: int = ...) -> list[bytes]: ... - def __iter__(self) -> Iterable[bytes]: ... + WSGIEnvironment: TypeAlias = dict[str, Any] # stable + WSGIApplication: TypeAlias = Callable[[WSGIEnvironment, StartResponse], Iterable[bytes]] # stable -# WSGI error streams per PEP 3333, stable -class ErrorStream(Protocol): - def flush(self) -> None: ... - def write(self, s: str) -> None: ... - def writelines(self, seq: list[str]) -> None: ... + # WSGI input streams per PEP 3333, stable + class InputStream(Protocol): + def read(self, __size: int = ...) -> bytes: ... + def readline(self, __size: int = ...) -> bytes: ... + def readlines(self, __hint: int = ...) -> list[bytes]: ... + def __iter__(self) -> Iterable[bytes]: ... -class _Readable(Protocol): - def read(self, size: int = ...) -> bytes: ... + # WSGI error streams per PEP 3333, stable + class ErrorStream(Protocol): + def flush(self) -> object: ... + def write(self, __s: str) -> object: ... + def writelines(self, __seq: list[str]) -> object: ... -# Optional file wrapper in wsgi.file_wrapper -class FileWrapper(Protocol): - def __call__(self, file: _Readable, block_size: int = ...) -> Iterable[bytes]: ... + # Optional file wrapper in wsgi.file_wrapper + class FileWrapper(Protocol): + def __call__(self, __file: _Readable, __block_size: int = ...) -> Iterable[bytes]: ... diff --git a/mypy/typeshed/stdlib/_weakref.pyi b/mypy/typeshed/stdlib/_weakref.pyi index 00dc2d5114b8f..2d3faec1fa682 100644 --- a/mypy/typeshed/stdlib/_weakref.pyi +++ b/mypy/typeshed/stdlib/_weakref.pyi @@ -1,5 +1,6 @@ import sys -from typing import Any, Callable, Generic, TypeVar, overload +from collections.abc import Callable +from typing import Any, Generic, TypeVar, overload from typing_extensions import final if sys.version_info >= (3, 9): @@ -28,10 +29,10 @@ class ReferenceType(Generic[_T]): ref = ReferenceType def getweakrefcount(__object: Any) -> int: ... -def getweakrefs(object: Any) -> list[Any]: ... -@overload -def proxy(object: _C, callback: Callable[[_C], Any] | None = ...) -> CallableProxyType[_C]: ... +def getweakrefs(__object: Any) -> list[Any]: ... # Return CallableProxyType if object is callable, ProxyType otherwise @overload -def proxy(object: _T, callback: Callable[[_T], Any] | None = ...) -> Any: ... +def proxy(__object: _C, __callback: Callable[[_C], Any] | None = ...) -> CallableProxyType[_C]: ... +@overload +def proxy(__object: _T, __callback: Callable[[_T], Any] | None = ...) -> Any: ... diff --git a/mypy/typeshed/stdlib/_weakrefset.pyi b/mypy/typeshed/stdlib/_weakrefset.pyi index b0c22a5ecc135..382dbdeb6c8a0 100644 --- a/mypy/typeshed/stdlib/_weakrefset.pyi +++ b/mypy/typeshed/stdlib/_weakrefset.pyi @@ -1,6 +1,7 @@ import sys from _typeshed import Self -from typing import Any, Generic, Iterable, Iterator, MutableSet, TypeVar +from collections.abc import Iterable, Iterator, MutableSet +from typing import Any, Generic, TypeVar if sys.version_info >= (3, 9): from types import GenericAlias diff --git a/mypy/typeshed/stdlib/_winapi.pyi b/mypy/typeshed/stdlib/_winapi.pyi index 1e8c514770839..77e7714454e76 100644 --- a/mypy/typeshed/stdlib/_winapi.pyi +++ b/mypy/typeshed/stdlib/_winapi.pyi @@ -1,5 +1,6 @@ import sys -from typing import Any, NoReturn, Sequence, overload +from collections.abc import Sequence +from typing import Any, NoReturn, overload from typing_extensions import Literal, final if sys.platform == "win32": diff --git a/mypy/typeshed/stdlib/aifc.pyi b/mypy/typeshed/stdlib/aifc.pyi index db3d8d9910295..14e824f3d22e7 100644 --- a/mypy/typeshed/stdlib/aifc.pyi +++ b/mypy/typeshed/stdlib/aifc.pyi @@ -2,7 +2,7 @@ import sys from _typeshed import Self from types import TracebackType from typing import IO, Any, NamedTuple, overload -from typing_extensions import Literal +from typing_extensions import Literal, TypeAlias if sys.version_info >= (3, 9): __all__ = ["Error", "open"] @@ -19,8 +19,8 @@ class _aifc_params(NamedTuple): comptype: bytes compname: bytes -_File = str | IO[bytes] -_Marker = tuple[int, int, bytes] +_File: TypeAlias = str | IO[bytes] +_Marker: TypeAlias = tuple[int, int, bytes] class Aifc_read: def __init__(self, f: _File) -> None: ... diff --git a/mypy/typeshed/stdlib/argparse.pyi b/mypy/typeshed/stdlib/argparse.pyi index 0a56aa4f4b59a..759027d3a8900 100644 --- a/mypy/typeshed/stdlib/argparse.pyi +++ b/mypy/typeshed/stdlib/argparse.pyi @@ -1,20 +1,7 @@ import sys -from typing import ( - IO, - Any, - Callable, - Generator, - Generic, - Iterable, - NewType, - NoReturn, - Pattern, - Protocol, - Sequence, - TypeVar, - overload, -) -from typing_extensions import Literal +from collections.abc import Callable, Generator, Iterable, Sequence +from typing import IO, Any, Generic, NewType, NoReturn, Pattern, Protocol, TypeVar, overload +from typing_extensions import Literal, TypeAlias if sys.version_info >= (3, 9): __all__ = [ @@ -66,11 +53,11 @@ _N = TypeVar("_N") # "store_false", "append", "append_const", "count", "help", "version", # "extend"], but using this would make it hard to annotate callers # that don't use a literal argument -_ActionStr = str +_ActionStr: TypeAlias = str # more precisely, Literal["?", "*", "+", "...", "A...", # "==SUPPRESS=="], but using this would make it hard to annotate # callers that don't use a literal argument -_NArgsStr = str +_NArgsStr: TypeAlias = str ONE_OR_MORE: Literal["+"] OPTIONAL: Literal["?"] diff --git a/mypy/typeshed/stdlib/array.pyi b/mypy/typeshed/stdlib/array.pyi index 69b4d35d9fe9e..d69f02d338cf4 100644 --- a/mypy/typeshed/stdlib/array.pyi +++ b/mypy/typeshed/stdlib/array.pyi @@ -1,12 +1,15 @@ import sys from _typeshed import Self -from typing import Any, BinaryIO, Generic, Iterable, MutableSequence, TypeVar, overload -from typing_extensions import Literal, SupportsIndex +from collections.abc import Iterable -_IntTypeCode = Literal["b", "B", "h", "H", "i", "I", "l", "L", "q", "Q"] -_FloatTypeCode = Literal["f", "d"] -_UnicodeTypeCode = Literal["u"] -_TypeCode = _IntTypeCode | _FloatTypeCode | _UnicodeTypeCode +# pytype crashes if array inherits from collections.abc.MutableSequence instead of typing.MutableSequence +from typing import Any, BinaryIO, Generic, MutableSequence, TypeVar, overload # noqa: Y027 +from typing_extensions import Literal, SupportsIndex, TypeAlias + +_IntTypeCode: TypeAlias = Literal["b", "B", "h", "H", "i", "I", "l", "L", "q", "Q"] +_FloatTypeCode: TypeAlias = Literal["f", "d"] +_UnicodeTypeCode: TypeAlias = Literal["u"] +_TypeCode: TypeAlias = _IntTypeCode | _FloatTypeCode | _UnicodeTypeCode _T = TypeVar("_T", int, float, str) diff --git a/mypy/typeshed/stdlib/ast.pyi b/mypy/typeshed/stdlib/ast.pyi index 5a86d6888b2f9..199e4f2acb68a 100644 --- a/mypy/typeshed/stdlib/ast.pyi +++ b/mypy/typeshed/stdlib/ast.pyi @@ -1,15 +1,7 @@ -# Rename typing to _typing, as not to conflict with typing imported -# from _ast below when loaded in an unorthodox way by the Dropbox -# internal Bazel integration. - -# The same unorthodox Bazel integration causes issues with sys, which -# is imported in both modules. unfortunately we can't just rename sys, -# since mypy only supports version checks with a sys that is named -# sys. import sys -import typing as _typing from _ast import * -from typing import Any, Iterator, TypeVar, overload +from collections.abc import Iterator +from typing import Any, TypeVar, overload from typing_extensions import Literal if sys.version_info >= (3, 8): @@ -166,7 +158,7 @@ if sys.version_info >= (3, 8): mode: Literal["exec"] = ..., *, type_comments: bool = ..., - feature_version: None | int | _typing.Tuple[int, int] = ..., + feature_version: None | int | tuple[int, int] = ..., ) -> Module: ... @overload def parse( @@ -175,7 +167,7 @@ if sys.version_info >= (3, 8): mode: Literal["eval"], *, type_comments: bool = ..., - feature_version: None | int | _typing.Tuple[int, int] = ..., + feature_version: None | int | tuple[int, int] = ..., ) -> Expression: ... @overload def parse( @@ -184,7 +176,7 @@ if sys.version_info >= (3, 8): mode: Literal["func_type"], *, type_comments: bool = ..., - feature_version: None | int | _typing.Tuple[int, int] = ..., + feature_version: None | int | tuple[int, int] = ..., ) -> FunctionType: ... @overload def parse( @@ -193,7 +185,7 @@ if sys.version_info >= (3, 8): mode: Literal["single"], *, type_comments: bool = ..., - feature_version: None | int | _typing.Tuple[int, int] = ..., + feature_version: None | int | tuple[int, int] = ..., ) -> Interactive: ... @overload def parse( @@ -201,7 +193,7 @@ if sys.version_info >= (3, 8): *, mode: Literal["eval"], type_comments: bool = ..., - feature_version: None | int | _typing.Tuple[int, int] = ..., + feature_version: None | int | tuple[int, int] = ..., ) -> Expression: ... @overload def parse( @@ -209,7 +201,7 @@ if sys.version_info >= (3, 8): *, mode: Literal["func_type"], type_comments: bool = ..., - feature_version: None | int | _typing.Tuple[int, int] = ..., + feature_version: None | int | tuple[int, int] = ..., ) -> FunctionType: ... @overload def parse( @@ -217,7 +209,7 @@ if sys.version_info >= (3, 8): *, mode: Literal["single"], type_comments: bool = ..., - feature_version: None | int | _typing.Tuple[int, int] = ..., + feature_version: None | int | tuple[int, int] = ..., ) -> Interactive: ... @overload def parse( @@ -226,7 +218,7 @@ if sys.version_info >= (3, 8): mode: str = ..., *, type_comments: bool = ..., - feature_version: None | int | _typing.Tuple[int, int] = ..., + feature_version: None | int | tuple[int, int] = ..., ) -> AST: ... else: @@ -260,7 +252,7 @@ def fix_missing_locations(node: _T) -> _T: ... def get_docstring(node: AST, clean: bool = ...) -> str | None: ... def increment_lineno(node: _T, n: int = ...) -> _T: ... def iter_child_nodes(node: AST) -> Iterator[AST]: ... -def iter_fields(node: AST) -> Iterator[_typing.Tuple[str, Any]]: ... +def iter_fields(node: AST) -> Iterator[tuple[str, Any]]: ... def literal_eval(node_or_string: str | AST) -> Any: ... if sys.version_info >= (3, 8): diff --git a/mypy/typeshed/stdlib/asyncio/base_events.pyi b/mypy/typeshed/stdlib/asyncio/base_events.pyi index 71e4487baf997..7742651fea2ab 100644 --- a/mypy/typeshed/stdlib/asyncio/base_events.pyi +++ b/mypy/typeshed/stdlib/asyncio/base_events.pyi @@ -6,10 +6,10 @@ from asyncio.futures import Future from asyncio.protocols import BaseProtocol from asyncio.tasks import Task from asyncio.transports import BaseTransport, ReadTransport, SubprocessTransport, WriteTransport -from collections.abc import Iterable +from collections.abc import Awaitable, Callable, Coroutine, Generator, Iterable, Sequence from socket import AddressFamily, SocketKind, _Address, _RetAddress, socket -from typing import IO, Any, Awaitable, Callable, Coroutine, Generator, Sequence, TypeVar, overload -from typing_extensions import Literal +from typing import IO, Any, TypeVar, overload +from typing_extensions import Literal, TypeAlias if sys.version_info >= (3, 7): from contextvars import Context @@ -23,10 +23,10 @@ else: _T = TypeVar("_T") _ProtocolT = TypeVar("_ProtocolT", bound=BaseProtocol) -_Context = dict[str, Any] -_ExceptionHandler = Callable[[AbstractEventLoop, _Context], Any] -_ProtocolFactory = Callable[[], BaseProtocol] -_SSLContext = bool | None | ssl.SSLContext +_Context: TypeAlias = dict[str, Any] +_ExceptionHandler: TypeAlias = Callable[[AbstractEventLoop, _Context], Any] +_ProtocolFactory: TypeAlias = Callable[[], BaseProtocol] +_SSLContext: TypeAlias = bool | None | ssl.SSLContext class Server(AbstractServer): if sys.version_info >= (3, 7): diff --git a/mypy/typeshed/stdlib/asyncio/base_futures.pyi b/mypy/typeshed/stdlib/asyncio/base_futures.pyi index 1b7fe4671ca82..8a973d1618f48 100644 --- a/mypy/typeshed/stdlib/asyncio/base_futures.pyi +++ b/mypy/typeshed/stdlib/asyncio/base_futures.pyi @@ -1,5 +1,6 @@ import sys -from typing import Any, Callable, Sequence +from collections.abc import Callable, Sequence +from typing import Any from typing_extensions import Literal if sys.version_info >= (3, 7): diff --git a/mypy/typeshed/stdlib/asyncio/base_subprocess.pyi b/mypy/typeshed/stdlib/asyncio/base_subprocess.pyi index 21c56bde1eac7..963cfa93de283 100644 --- a/mypy/typeshed/stdlib/asyncio/base_subprocess.pyi +++ b/mypy/typeshed/stdlib/asyncio/base_subprocess.pyi @@ -1,10 +1,12 @@ import subprocess from collections import deque -from typing import IO, Any, Callable, Sequence +from collections.abc import Callable, Sequence +from typing import IO, Any +from typing_extensions import TypeAlias from . import events, futures, protocols, transports -_File = int | IO[Any] | None +_File: TypeAlias = int | IO[Any] | None class BaseSubprocessTransport(transports.SubprocessTransport): diff --git a/mypy/typeshed/stdlib/asyncio/events.pyi b/mypy/typeshed/stdlib/asyncio/events.pyi index cc0391f92bc4a..ae566234160b4 100644 --- a/mypy/typeshed/stdlib/asyncio/events.pyi +++ b/mypy/typeshed/stdlib/asyncio/events.pyi @@ -2,9 +2,10 @@ import ssl import sys from _typeshed import FileDescriptorLike, Self from abc import ABCMeta, abstractmethod +from collections.abc import Awaitable, Callable, Coroutine, Generator, Sequence from socket import AddressFamily, SocketKind, _Address, _RetAddress, socket -from typing import IO, Any, Awaitable, Callable, Coroutine, Generator, Sequence, TypeVar, overload -from typing_extensions import Literal +from typing import IO, Any, TypeVar, overload +from typing_extensions import Literal, TypeAlias from .base_events import Server from .futures import Future @@ -75,10 +76,10 @@ else: _T = TypeVar("_T") _ProtocolT = TypeVar("_ProtocolT", bound=BaseProtocol) -_Context = dict[str, Any] -_ExceptionHandler = Callable[[AbstractEventLoop, _Context], Any] -_ProtocolFactory = Callable[[], BaseProtocol] -_SSLContext = bool | None | ssl.SSLContext +_Context: TypeAlias = dict[str, Any] +_ExceptionHandler: TypeAlias = Callable[[AbstractEventLoop, _Context], Any] +_ProtocolFactory: TypeAlias = Callable[[], BaseProtocol] +_SSLContext: TypeAlias = bool | None | ssl.SSLContext class Handle: _cancelled: bool diff --git a/mypy/typeshed/stdlib/asyncio/format_helpers.pyi b/mypy/typeshed/stdlib/asyncio/format_helpers.pyi index 5e483a578c3ee..4e2ef8d3f2748 100644 --- a/mypy/typeshed/stdlib/asyncio/format_helpers.pyi +++ b/mypy/typeshed/stdlib/asyncio/format_helpers.pyi @@ -1,12 +1,14 @@ import functools import traceback +from collections.abc import Iterable from types import FrameType, FunctionType -from typing import Any, Iterable, overload +from typing import Any, overload +from typing_extensions import TypeAlias class _HasWrapper: __wrapper__: _HasWrapper | FunctionType -_FuncType = FunctionType | _HasWrapper | functools.partial[Any] | functools.partialmethod[Any] +_FuncType: TypeAlias = FunctionType | _HasWrapper | functools.partial[Any] | functools.partialmethod[Any] @overload def _get_function_source(func: _FuncType) -> tuple[str, int]: ... diff --git a/mypy/typeshed/stdlib/asyncio/futures.pyi b/mypy/typeshed/stdlib/asyncio/futures.pyi index 2b0b93a096383..692d263f673ba 100644 --- a/mypy/typeshed/stdlib/asyncio/futures.pyi +++ b/mypy/typeshed/stdlib/asyncio/futures.pyi @@ -1,7 +1,8 @@ import sys from _typeshed import Self +from collections.abc import Awaitable, Callable, Generator, Iterable from concurrent.futures._base import Error, Future as _ConcurrentFuture -from typing import Any, Awaitable, Callable, Generator, Iterable, TypeVar +from typing import Any, TypeVar from typing_extensions import Literal, TypeGuard from .events import AbstractEventLoop diff --git a/mypy/typeshed/stdlib/asyncio/locks.pyi b/mypy/typeshed/stdlib/asyncio/locks.pyi index 01b1c5b4591d6..2758e0c469196 100644 --- a/mypy/typeshed/stdlib/asyncio/locks.pyi +++ b/mypy/typeshed/stdlib/asyncio/locks.pyi @@ -1,7 +1,8 @@ import sys from collections import deque +from collections.abc import Callable, Generator from types import TracebackType -from typing import Any, Callable, Generator, TypeVar +from typing import Any, TypeVar from typing_extensions import Literal from .events import AbstractEventLoop diff --git a/mypy/typeshed/stdlib/asyncio/proactor_events.pyi b/mypy/typeshed/stdlib/asyncio/proactor_events.pyi index 4ffb401604202..21247401c9bab 100644 --- a/mypy/typeshed/stdlib/asyncio/proactor_events.pyi +++ b/mypy/typeshed/stdlib/asyncio/proactor_events.pyi @@ -1,6 +1,7 @@ import sys +from collections.abc import Mapping from socket import socket -from typing import Any, Mapping, Protocol +from typing import Any, Protocol from typing_extensions import Literal from . import base_events, constants, events, futures, streams, transports diff --git a/mypy/typeshed/stdlib/asyncio/runners.pyi b/mypy/typeshed/stdlib/asyncio/runners.pyi index 7e799dd22fd8e..32cd839f2f797 100644 --- a/mypy/typeshed/stdlib/asyncio/runners.pyi +++ b/mypy/typeshed/stdlib/asyncio/runners.pyi @@ -1,5 +1,6 @@ import sys -from typing import Awaitable, TypeVar +from collections.abc import Awaitable +from typing import TypeVar __all__ = ("run",) _T = TypeVar("_T") diff --git a/mypy/typeshed/stdlib/asyncio/sslproto.pyi b/mypy/typeshed/stdlib/asyncio/sslproto.pyi index 4ecd7a11dd56f..619e329bfb436 100644 --- a/mypy/typeshed/stdlib/asyncio/sslproto.pyi +++ b/mypy/typeshed/stdlib/asyncio/sslproto.pyi @@ -1,7 +1,8 @@ import ssl import sys from collections import deque -from typing import Any, Callable, ClassVar +from collections.abc import Callable +from typing import Any, ClassVar from typing_extensions import Literal from . import constants, events, futures, protocols, transports diff --git a/mypy/typeshed/stdlib/asyncio/staggered.pyi b/mypy/typeshed/stdlib/asyncio/staggered.pyi index fc4bfad769845..610d6f70b614a 100644 --- a/mypy/typeshed/stdlib/asyncio/staggered.pyi +++ b/mypy/typeshed/stdlib/asyncio/staggered.pyi @@ -1,4 +1,5 @@ -from typing import Any, Awaitable, Callable, Iterable +from collections.abc import Awaitable, Callable, Iterable +from typing import Any from . import events diff --git a/mypy/typeshed/stdlib/asyncio/streams.pyi b/mypy/typeshed/stdlib/asyncio/streams.pyi index 666862cc7b7d2..14a6d2c4d8fe8 100644 --- a/mypy/typeshed/stdlib/asyncio/streams.pyi +++ b/mypy/typeshed/stdlib/asyncio/streams.pyi @@ -1,6 +1,8 @@ import sys from _typeshed import Self, StrPath -from typing import Any, AsyncIterator, Awaitable, Callable, Iterable, Sequence +from collections.abc import AsyncIterator, Awaitable, Callable, Iterable, Sequence +from typing import Any +from typing_extensions import TypeAlias from . import events, protocols, transports from .base_events import Server @@ -64,7 +66,7 @@ else: "start_unix_server", ] -_ClientConnectedCallback = Callable[[StreamReader, StreamWriter], Awaitable[None] | None] +_ClientConnectedCallback: TypeAlias = Callable[[StreamReader, StreamWriter], Awaitable[None] | None] if sys.version_info < (3, 8): class IncompleteReadError(EOFError): @@ -118,9 +120,9 @@ else: if sys.platform != "win32": if sys.version_info >= (3, 7): - _PathType = StrPath + _PathType: TypeAlias = StrPath else: - _PathType = str + _PathType: TypeAlias = str if sys.version_info >= (3, 10): async def open_unix_connection( path: _PathType | None = ..., *, limit: int = ..., **kwds: Any diff --git a/mypy/typeshed/stdlib/asyncio/subprocess.pyi b/mypy/typeshed/stdlib/asyncio/subprocess.pyi index 3a617d6fb6281..55093a3ebd9fd 100644 --- a/mypy/typeshed/stdlib/asyncio/subprocess.pyi +++ b/mypy/typeshed/stdlib/asyncio/subprocess.pyi @@ -2,8 +2,9 @@ import subprocess import sys from _typeshed import StrOrBytesPath from asyncio import events, protocols, streams, transports -from typing import IO, Any, Callable -from typing_extensions import Literal +from collections.abc import Callable +from typing import IO, Any +from typing_extensions import Literal, TypeAlias if sys.version_info >= (3, 7): __all__ = ("create_subprocess_exec", "create_subprocess_shell") @@ -11,9 +12,9 @@ else: __all__ = ["create_subprocess_exec", "create_subprocess_shell"] if sys.version_info >= (3, 8): - _ExecArg = StrOrBytesPath + _ExecArg: TypeAlias = StrOrBytesPath else: - _ExecArg = str | bytes + _ExecArg: TypeAlias = str | bytes PIPE: int STDOUT: int diff --git a/mypy/typeshed/stdlib/asyncio/taskgroups.pyi b/mypy/typeshed/stdlib/asyncio/taskgroups.pyi index ef04614c3c15e..58e3d41e53f11 100644 --- a/mypy/typeshed/stdlib/asyncio/taskgroups.pyi +++ b/mypy/typeshed/stdlib/asyncio/taskgroups.pyi @@ -1,8 +1,9 @@ # This only exists in 3.11+. See VERSIONS. from _typeshed import Self +from collections.abc import Coroutine, Generator from types import TracebackType -from typing import Any, Coroutine, Generator, TypeVar +from typing import Any, TypeVar from .tasks import Task diff --git a/mypy/typeshed/stdlib/asyncio/tasks.pyi b/mypy/typeshed/stdlib/asyncio/tasks.pyi index 885688065ddc5..4a8e565afb2fc 100644 --- a/mypy/typeshed/stdlib/asyncio/tasks.pyi +++ b/mypy/typeshed/stdlib/asyncio/tasks.pyi @@ -1,9 +1,9 @@ import concurrent.futures import sys -from collections.abc import Awaitable, Generator, Iterable, Iterator +from collections.abc import Awaitable, Coroutine, Generator, Iterable, Iterator from types import FrameType -from typing import Any, Coroutine, Generic, TextIO, TypeVar, overload -from typing_extensions import Literal +from typing import Any, Generic, TextIO, TypeVar, overload +from typing_extensions import Literal, TypeAlias from .events import AbstractEventLoop from .futures import Future @@ -56,8 +56,8 @@ _T3 = TypeVar("_T3") _T4 = TypeVar("_T4") _T5 = TypeVar("_T5") _FT = TypeVar("_FT", bound=Future[Any]) -_FutureT = Future[_T] | Generator[Any, None, _T] | Awaitable[_T] -_TaskYieldType = Future[object] | None +_FutureT: TypeAlias = Future[_T] | Generator[Any, None, _T] | Awaitable[_T] +_TaskYieldType: TypeAlias = Future[object] | None FIRST_COMPLETED = concurrent.futures.FIRST_COMPLETED FIRST_EXCEPTION = concurrent.futures.FIRST_EXCEPTION diff --git a/mypy/typeshed/stdlib/asyncio/threads.pyi b/mypy/typeshed/stdlib/asyncio/threads.pyi index ac3a5c56b222d..88c4fddcaa3f1 100644 --- a/mypy/typeshed/stdlib/asyncio/threads.pyi +++ b/mypy/typeshed/stdlib/asyncio/threads.pyi @@ -1,4 +1,5 @@ -from typing import Callable, TypeVar +from collections.abc import Callable +from typing import TypeVar from typing_extensions import ParamSpec __all__ = ("to_thread",) diff --git a/mypy/typeshed/stdlib/asyncio/transports.pyi b/mypy/typeshed/stdlib/asyncio/transports.pyi index 90e54b547a873..a8cd753c2af8f 100644 --- a/mypy/typeshed/stdlib/asyncio/transports.pyi +++ b/mypy/typeshed/stdlib/asyncio/transports.pyi @@ -1,8 +1,9 @@ import sys from asyncio.events import AbstractEventLoop from asyncio.protocols import BaseProtocol +from collections.abc import Mapping from socket import _Address -from typing import Any, Mapping +from typing import Any if sys.version_info >= (3, 7): __all__ = ("BaseTransport", "ReadTransport", "WriteTransport", "Transport", "DatagramTransport", "SubprocessTransport") diff --git a/mypy/typeshed/stdlib/asyncio/trsock.pyi b/mypy/typeshed/stdlib/asyncio/trsock.pyi index 3fe1e19d1311d..20df2a78a5abb 100644 --- a/mypy/typeshed/stdlib/asyncio/trsock.pyi +++ b/mypy/typeshed/stdlib/asyncio/trsock.pyi @@ -1,14 +1,16 @@ import socket import sys from builtins import type as Type # alias to avoid name clashes with property named "type" +from collections.abc import Iterable from types import TracebackType -from typing import Any, BinaryIO, Iterable, NoReturn, overload +from typing import Any, BinaryIO, NoReturn, overload +from typing_extensions import TypeAlias # These are based in socket, maybe move them out into _typeshed.pyi or such -_Address = tuple[Any, ...] | str -_RetAddress = Any -_WriteBuffer = bytearray | memoryview -_CMSG = tuple[int, int, bytes] +_Address: TypeAlias = tuple[Any, ...] | str +_RetAddress: TypeAlias = Any +_WriteBuffer: TypeAlias = bytearray | memoryview +_CMSG: TypeAlias = tuple[int, int, bytes] class TransportSocket: def __init__(self, sock: socket.socket) -> None: ... diff --git a/mypy/typeshed/stdlib/asyncio/unix_events.pyi b/mypy/typeshed/stdlib/asyncio/unix_events.pyi index 78d87dc4e9e94..ca28ee04125a2 100644 --- a/mypy/typeshed/stdlib/asyncio/unix_events.pyi +++ b/mypy/typeshed/stdlib/asyncio/unix_events.pyi @@ -2,8 +2,9 @@ import sys import types from _typeshed import Self from abc import ABCMeta, abstractmethod +from collections.abc import Callable from socket import socket -from typing import Any, Callable +from typing import Any from typing_extensions import Literal from .base_events import Server diff --git a/mypy/typeshed/stdlib/asyncio/windows_events.pyi b/mypy/typeshed/stdlib/asyncio/windows_events.pyi index 1e4d286386c87..d33210bc1297a 100644 --- a/mypy/typeshed/stdlib/asyncio/windows_events.pyi +++ b/mypy/typeshed/stdlib/asyncio/windows_events.pyi @@ -1,7 +1,8 @@ import socket import sys from _typeshed import WriteableBuffer -from typing import IO, Any, Callable, ClassVar, NoReturn +from collections.abc import Callable +from typing import IO, Any, ClassVar, NoReturn from typing_extensions import Literal from . import events, futures, proactor_events, selector_events, streams, windows_utils diff --git a/mypy/typeshed/stdlib/asyncio/windows_utils.pyi b/mypy/typeshed/stdlib/asyncio/windows_utils.pyi index 1156f905659e8..0a79635b3d4e1 100644 --- a/mypy/typeshed/stdlib/asyncio/windows_utils.pyi +++ b/mypy/typeshed/stdlib/asyncio/windows_utils.pyi @@ -1,8 +1,9 @@ import subprocess import sys from _typeshed import Self +from collections.abc import Callable from types import TracebackType -from typing import Any, AnyStr, Callable, Protocol +from typing import Any, AnyStr, Protocol from typing_extensions import Literal if sys.platform == "win32": diff --git a/mypy/typeshed/stdlib/asyncore.pyi b/mypy/typeshed/stdlib/asyncore.pyi index 8f77e0e45c44f..a4a7742823438 100644 --- a/mypy/typeshed/stdlib/asyncore.pyi +++ b/mypy/typeshed/stdlib/asyncore.pyi @@ -2,10 +2,11 @@ import sys from _typeshed import FileDescriptorLike from socket import socket from typing import Any, overload +from typing_extensions import TypeAlias # cyclic dependence with asynchat -_maptype = dict[int, Any] -_socket = socket +_maptype: TypeAlias = dict[int, Any] +_socket: TypeAlias = socket socket_map: _maptype # undocumented diff --git a/mypy/typeshed/stdlib/atexit.pyi b/mypy/typeshed/stdlib/atexit.pyi index ba0c7dfaf6b1f..095ab5f9b26d3 100644 --- a/mypy/typeshed/stdlib/atexit.pyi +++ b/mypy/typeshed/stdlib/atexit.pyi @@ -1,4 +1,5 @@ -from typing import Any, Callable, TypeVar +from collections.abc import Callable +from typing import Any, TypeVar from typing_extensions import ParamSpec _T = TypeVar("_T") diff --git a/mypy/typeshed/stdlib/audioop.pyi b/mypy/typeshed/stdlib/audioop.pyi index b08731b85b0ba..62b54ced9127d 100644 --- a/mypy/typeshed/stdlib/audioop.pyi +++ b/mypy/typeshed/stdlib/audioop.pyi @@ -1,10 +1,12 @@ -AdpcmState = tuple[int, int] -RatecvState = tuple[int, tuple[tuple[int, int], ...]] +from typing_extensions import TypeAlias + +_AdpcmState: TypeAlias = tuple[int, int] +_RatecvState: TypeAlias = tuple[int, tuple[tuple[int, int], ...]] class error(Exception): ... def add(__fragment1: bytes, __fragment2: bytes, __width: int) -> bytes: ... -def adpcm2lin(__fragment: bytes, __width: int, __state: AdpcmState | None) -> tuple[bytes, AdpcmState]: ... +def adpcm2lin(__fragment: bytes, __width: int, __state: _AdpcmState | None) -> tuple[bytes, _AdpcmState]: ... def alaw2lin(__fragment: bytes, __width: int) -> bytes: ... def avg(__fragment: bytes, __width: int) -> int: ... def avgpp(__fragment: bytes, __width: int) -> int: ... @@ -15,7 +17,7 @@ def findfactor(__fragment: bytes, __reference: bytes) -> float: ... def findfit(__fragment: bytes, __reference: bytes) -> tuple[int, float]: ... def findmax(__fragment: bytes, __length: int) -> int: ... def getsample(__fragment: bytes, __width: int, __index: int) -> int: ... -def lin2adpcm(__fragment: bytes, __width: int, __state: AdpcmState | None) -> tuple[bytes, AdpcmState]: ... +def lin2adpcm(__fragment: bytes, __width: int, __state: _AdpcmState | None) -> tuple[bytes, _AdpcmState]: ... def lin2alaw(__fragment: bytes, __width: int) -> bytes: ... def lin2lin(__fragment: bytes, __width: int, __newwidth: int) -> bytes: ... def lin2ulaw(__fragment: bytes, __width: int) -> bytes: ... @@ -29,10 +31,10 @@ def ratecv( __nchannels: int, __inrate: int, __outrate: int, - __state: RatecvState | None, + __state: _RatecvState | None, __weightA: int = ..., __weightB: int = ..., -) -> tuple[bytes, RatecvState]: ... +) -> tuple[bytes, _RatecvState]: ... def reverse(__fragment: bytes, __width: int) -> bytes: ... def rms(__fragment: bytes, __width: int) -> int: ... def tomono(__fragment: bytes, __width: int, __lfactor: float, __rfactor: float) -> bytes: ... diff --git a/mypy/typeshed/stdlib/bdb.pyi b/mypy/typeshed/stdlib/bdb.pyi index 8f61433e0cb88..bbd0f20af6c80 100644 --- a/mypy/typeshed/stdlib/bdb.pyi +++ b/mypy/typeshed/stdlib/bdb.pyi @@ -1,20 +1,20 @@ +from _typeshed import ExcInfo +from collections.abc import Callable, Iterable, Mapping from types import CodeType, FrameType, TracebackType -from typing import IO, Any, Callable, Iterable, Mapping, SupportsInt, TypeVar -from typing_extensions import Literal, ParamSpec +from typing import IO, Any, SupportsInt, TypeVar +from typing_extensions import Literal, ParamSpec, TypeAlias __all__ = ["BdbQuit", "Bdb", "Breakpoint"] _T = TypeVar("_T") _P = ParamSpec("_P") -_TraceDispatch = Callable[[FrameType, str, Any], Any] # TODO: Recursive type -_ExcInfo = tuple[type[BaseException], BaseException, FrameType] +_TraceDispatch: TypeAlias = Callable[[FrameType, str, Any], Any] # TODO: Recursive type GENERATOR_AND_COROUTINE_FLAGS: Literal[672] class BdbQuit(Exception): ... class Bdb: - skip: set[str] | None breaks: dict[str, list[int]] fncache: dict[str, str] @@ -31,7 +31,7 @@ class Bdb: def dispatch_line(self, frame: FrameType) -> _TraceDispatch: ... def dispatch_call(self, frame: FrameType, arg: None) -> _TraceDispatch: ... def dispatch_return(self, frame: FrameType, arg: Any) -> _TraceDispatch: ... - def dispatch_exception(self, frame: FrameType, arg: _ExcInfo) -> _TraceDispatch: ... + def dispatch_exception(self, frame: FrameType, arg: ExcInfo) -> _TraceDispatch: ... def is_skipped_module(self, module_name: str) -> bool: ... def stop_here(self, frame: FrameType) -> bool: ... def break_here(self, frame: FrameType) -> bool: ... @@ -40,7 +40,7 @@ class Bdb: def user_call(self, frame: FrameType, argument_list: None) -> None: ... def user_line(self, frame: FrameType) -> None: ... def user_return(self, frame: FrameType, return_value: Any) -> None: ... - def user_exception(self, frame: FrameType, exc_info: _ExcInfo) -> None: ... + def user_exception(self, frame: FrameType, exc_info: ExcInfo) -> None: ... def set_until(self, frame: FrameType, lineno: int | None = ...) -> None: ... def set_step(self) -> None: ... def set_next(self, frame: FrameType) -> None: ... diff --git a/mypy/typeshed/stdlib/binascii.pyi b/mypy/typeshed/stdlib/binascii.pyi index 317bb9979b923..53f72ad6a88f8 100644 --- a/mypy/typeshed/stdlib/binascii.pyi +++ b/mypy/typeshed/stdlib/binascii.pyi @@ -1,36 +1,44 @@ import sys +from _typeshed import ReadableBuffer +from typing_extensions import TypeAlias -def a2b_uu(__data: str | bytes) -> bytes: ... +# Many functions in binascii accept buffer objects +# or ASCII-only strings. +_AsciiBuffer: TypeAlias = str | ReadableBuffer + +def a2b_uu(__data: _AsciiBuffer) -> bytes: ... if sys.version_info >= (3, 7): - def b2a_uu(__data: bytes, *, backtick: bool = ...) -> bytes: ... + def b2a_uu(__data: ReadableBuffer, *, backtick: bool = ...) -> bytes: ... else: - def b2a_uu(__data: bytes) -> bytes: ... + def b2a_uu(__data: ReadableBuffer) -> bytes: ... -def a2b_base64(__data: str | bytes) -> bytes: ... -def b2a_base64(__data: bytes, *, newline: bool = ...) -> bytes: ... -def a2b_qp(data: str | bytes, header: bool = ...) -> bytes: ... -def b2a_qp(data: bytes, quotetabs: bool = ..., istext: bool = ..., header: bool = ...) -> bytes: ... +def a2b_base64(__data: _AsciiBuffer) -> bytes: ... +def b2a_base64(__data: ReadableBuffer, *, newline: bool = ...) -> bytes: ... +def a2b_qp(data: _AsciiBuffer, header: bool = ...) -> bytes: ... +def b2a_qp(data: ReadableBuffer, quotetabs: bool = ..., istext: bool = ..., header: bool = ...) -> bytes: ... if sys.version_info < (3, 11): - def a2b_hqx(__data: str | bytes) -> bytes: ... - def rledecode_hqx(__data: bytes) -> bytes: ... - def rlecode_hqx(__data: bytes) -> bytes: ... - def b2a_hqx(__data: bytes) -> bytes: ... + def a2b_hqx(__data: _AsciiBuffer) -> bytes: ... + def rledecode_hqx(__data: ReadableBuffer) -> bytes: ... + def rlecode_hqx(__data: ReadableBuffer) -> bytes: ... + def b2a_hqx(__data: ReadableBuffer) -> bytes: ... -def crc_hqx(__data: bytes, __crc: int) -> int: ... -def crc32(__data: bytes, __crc: int = ...) -> int: ... -def b2a_hex(__data: bytes) -> bytes: ... +def crc_hqx(__data: ReadableBuffer, __crc: int) -> int: ... +def crc32(__data: ReadableBuffer, __crc: int = ...) -> int: ... if sys.version_info >= (3, 8): - def hexlify(data: bytes, sep: str | bytes = ..., bytes_per_sep: int = ...) -> bytes: ... + # sep must be str or bytes, not bytearray or any other buffer + def b2a_hex(data: ReadableBuffer, sep: str | bytes = ..., bytes_per_sep: int = ...) -> bytes: ... + def hexlify(data: ReadableBuffer, sep: str | bytes = ..., bytes_per_sep: int = ...) -> bytes: ... else: - def hexlify(__data: bytes) -> bytes: ... + def b2a_hex(__data: ReadableBuffer) -> bytes: ... + def hexlify(__data: ReadableBuffer) -> bytes: ... -def a2b_hex(__hexstr: str | bytes) -> bytes: ... -def unhexlify(__hexstr: str | bytes) -> bytes: ... +def a2b_hex(__hexstr: _AsciiBuffer) -> bytes: ... +def unhexlify(__hexstr: _AsciiBuffer) -> bytes: ... class Error(ValueError): ... class Incomplete(Exception): ... diff --git a/mypy/typeshed/stdlib/binhex.pyi b/mypy/typeshed/stdlib/binhex.pyi index db002503c75fc..27aa379f134d6 100644 --- a/mypy/typeshed/stdlib/binhex.pyi +++ b/mypy/typeshed/stdlib/binhex.pyi @@ -1,5 +1,5 @@ from typing import IO, Any -from typing_extensions import Literal +from typing_extensions import Literal, TypeAlias __all__ = ["binhex", "hexbin", "Error"] @@ -15,8 +15,8 @@ class FInfo: Creator: str Flags: int -_FileInfoTuple = tuple[str, FInfo, int, int] -_FileHandleUnion = str | IO[bytes] +_FileInfoTuple: TypeAlias = tuple[str, FInfo, int, int] +_FileHandleUnion: TypeAlias = str | IO[bytes] def getfileinfo(name: str) -> _FileInfoTuple: ... diff --git a/mypy/typeshed/stdlib/builtins.pyi b/mypy/typeshed/stdlib/builtins.pyi index 9c5dfcfef22f6..bf1e6cde2c089 100644 --- a/mypy/typeshed/stdlib/builtins.pyi +++ b/mypy/typeshed/stdlib/builtins.pyi @@ -22,29 +22,24 @@ from _typeshed import ( SupportsTrunc, SupportsWrite, ) -from collections.abc import Callable +from collections.abc import Awaitable, Callable, Iterable, Iterator, MutableSet, Reversible, Set as AbstractSet, Sized from io import BufferedRandom, BufferedReader, BufferedWriter, FileIO, TextIOWrapper from types import CodeType, TracebackType, _Cell -from typing import ( + +# mypy crashes if any of {ByteString, Sequence, MutableSequence, Mapping, MutableMapping} are imported from collections.abc in builtins.pyi +from typing import ( # noqa: Y027 IO, - AbstractSet, Any, - Awaitable, BinaryIO, ByteString, ClassVar, Generic, - Iterable, - Iterator, Mapping, MutableMapping, MutableSequence, - MutableSet, NoReturn, Protocol, - Reversible, Sequence, - Sized, SupportsAbs, SupportsBytes, SupportsComplex, @@ -54,7 +49,7 @@ from typing import ( TypeVar, overload, ) -from typing_extensions import Literal, SupportsIndex, TypeGuard, final +from typing_extensions import Literal, SupportsIndex, TypeAlias, TypeGuard, final if sys.version_info >= (3, 9): from types import GenericAlias @@ -194,12 +189,12 @@ class super: @overload def __init__(self) -> None: ... -_PositiveInteger = Literal[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25] -_NegativeInteger = Literal[-1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16, -17, -18, -19, -20] +_PositiveInteger: TypeAlias = Literal[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25] +_NegativeInteger: TypeAlias = Literal[-1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16, -17, -18, -19, -20] class int: @overload - def __new__(cls: type[Self], __x: str | bytes | SupportsInt | SupportsIndex | SupportsTrunc = ...) -> Self: ... + def __new__(cls: type[Self], __x: str | ReadableBuffer | SupportsInt | SupportsIndex | SupportsTrunc = ...) -> Self: ... @overload def __new__(cls: type[Self], __x: str | bytes | bytearray, base: SupportsIndex) -> Self: ... if sys.version_info >= (3, 8): @@ -218,15 +213,29 @@ class int: if sys.version_info >= (3, 10): def bit_count(self) -> int: ... - def to_bytes(self, length: SupportsIndex, byteorder: Literal["little", "big"], *, signed: bool = ...) -> bytes: ... - @classmethod - def from_bytes( - cls: type[Self], - bytes: Iterable[SupportsIndex] | SupportsBytes, # TODO buffer object argument - byteorder: Literal["little", "big"], - *, - signed: bool = ..., - ) -> Self: ... + if sys.version_info >= (3, 11): + def to_bytes( + self, length: SupportsIndex = ..., byteorder: Literal["little", "big"] = ..., *, signed: bool = ... + ) -> bytes: ... + @classmethod + def from_bytes( + cls: type[Self], + bytes: Iterable[SupportsIndex] | SupportsBytes | ReadableBuffer, + byteorder: Literal["little", "big"] = ..., + *, + signed: bool = ..., + ) -> Self: ... + else: + def to_bytes(self, length: SupportsIndex, byteorder: Literal["little", "big"], *, signed: bool = ...) -> bytes: ... + @classmethod + def from_bytes( + cls: type[Self], + bytes: Iterable[SupportsIndex] | SupportsBytes | ReadableBuffer, + byteorder: Literal["little", "big"], + *, + signed: bool = ..., + ) -> Self: ... + def __add__(self, __x: int) -> int: ... def __sub__(self, __x: int) -> int: ... def __mul__(self, __x: int) -> int: ... @@ -288,7 +297,7 @@ class int: def __index__(self) -> int: ... class float: - def __new__(cls: type[Self], x: SupportsFloat | SupportsIndex | str | bytes | bytearray = ...) -> Self: ... + def __new__(cls: type[Self], x: SupportsFloat | SupportsIndex | str | ReadableBuffer = ...) -> Self: ... def as_integer_ratio(self) -> tuple[int, int]: ... def hex(self) -> str: ... def is_integer(self) -> bool: ... @@ -382,7 +391,7 @@ class str(Sequence[str]): @overload def __new__(cls: type[Self], object: object = ...) -> Self: ... @overload - def __new__(cls: type[Self], object: bytes, encoding: str = ..., errors: str = ...) -> Self: ... + def __new__(cls: type[Self], object: ReadableBuffer, encoding: str = ..., errors: str = ...) -> Self: ... def capitalize(self) -> str: ... def casefold(self) -> str: ... def center(self, __width: SupportsIndex, __fillchar: str = ...) -> str: ... @@ -479,11 +488,14 @@ class bytes(ByteString): def capitalize(self) -> bytes: ... def center(self, __width: SupportsIndex, __fillchar: bytes = ...) -> bytes: ... def count( - self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... + self, __sub: ReadableBuffer | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> int: ... def decode(self, encoding: str = ..., errors: str = ...) -> str: ... def endswith( - self, __suffix: bytes | tuple[bytes, ...], __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... + self, + __suffix: ReadableBuffer | tuple[ReadableBuffer, ...], + __start: SupportsIndex | None = ..., + __end: SupportsIndex | None = ..., ) -> bool: ... if sys.version_info >= (3, 8): def expandtabs(self, tabsize: SupportsIndex = ...) -> bytes: ... @@ -491,7 +503,7 @@ class bytes(ByteString): def expandtabs(self, tabsize: int = ...) -> bytes: ... def find( - self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... + self, __sub: ReadableBuffer | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> int: ... if sys.version_info >= (3, 8): def hex(self, sep: str | bytes = ..., bytes_per_sep: SupportsIndex = ...) -> str: ... @@ -499,7 +511,7 @@ class bytes(ByteString): def hex(self) -> str: ... def index( - self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... + self, __sub: ReadableBuffer | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> int: ... def isalnum(self) -> bool: ... def isalpha(self) -> bool: ... @@ -511,41 +523,44 @@ class bytes(ByteString): def isspace(self) -> bool: ... def istitle(self) -> bool: ... def isupper(self) -> bool: ... - def join(self, __iterable_of_bytes: Iterable[ByteString | memoryview]) -> bytes: ... - def ljust(self, __width: SupportsIndex, __fillchar: bytes = ...) -> bytes: ... + def join(self, __iterable_of_bytes: Iterable[ReadableBuffer]) -> bytes: ... + def ljust(self, __width: SupportsIndex, __fillchar: bytes | bytearray = ...) -> bytes: ... def lower(self) -> bytes: ... - def lstrip(self, __bytes: bytes | None = ...) -> bytes: ... - def partition(self, __sep: bytes) -> tuple[bytes, bytes, bytes]: ... - def replace(self, __old: bytes, __new: bytes, __count: SupportsIndex = ...) -> bytes: ... + def lstrip(self, __bytes: ReadableBuffer | None = ...) -> bytes: ... + def partition(self, __sep: ReadableBuffer) -> tuple[bytes, bytes, bytes]: ... + def replace(self, __old: ReadableBuffer, __new: ReadableBuffer, __count: SupportsIndex = ...) -> bytes: ... if sys.version_info >= (3, 9): - def removeprefix(self, __prefix: bytes) -> bytes: ... - def removesuffix(self, __suffix: bytes) -> bytes: ... + def removeprefix(self, __prefix: ReadableBuffer) -> bytes: ... + def removesuffix(self, __suffix: ReadableBuffer) -> bytes: ... def rfind( - self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... + self, __sub: ReadableBuffer | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> int: ... def rindex( - self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... + self, __sub: ReadableBuffer | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> int: ... - def rjust(self, __width: SupportsIndex, __fillchar: bytes = ...) -> bytes: ... - def rpartition(self, __sep: bytes) -> tuple[bytes, bytes, bytes]: ... - def rsplit(self, sep: bytes | None = ..., maxsplit: SupportsIndex = ...) -> list[bytes]: ... - def rstrip(self, __bytes: bytes | None = ...) -> bytes: ... - def split(self, sep: bytes | None = ..., maxsplit: SupportsIndex = ...) -> list[bytes]: ... + def rjust(self, __width: SupportsIndex, __fillchar: bytes | bytearray = ...) -> bytes: ... + def rpartition(self, __sep: ReadableBuffer) -> tuple[bytes, bytes, bytes]: ... + def rsplit(self, sep: ReadableBuffer | None = ..., maxsplit: SupportsIndex = ...) -> list[bytes]: ... + def rstrip(self, __bytes: ReadableBuffer | None = ...) -> bytes: ... + def split(self, sep: ReadableBuffer | None = ..., maxsplit: SupportsIndex = ...) -> list[bytes]: ... def splitlines(self, keepends: bool = ...) -> list[bytes]: ... def startswith( - self, __prefix: bytes | tuple[bytes, ...], __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... + self, + __prefix: ReadableBuffer | tuple[ReadableBuffer, ...], + __start: SupportsIndex | None = ..., + __end: SupportsIndex | None = ..., ) -> bool: ... - def strip(self, __bytes: bytes | None = ...) -> bytes: ... + def strip(self, __bytes: ReadableBuffer | None = ...) -> bytes: ... def swapcase(self) -> bytes: ... def title(self) -> bytes: ... - def translate(self, __table: bytes | None, delete: bytes = ...) -> bytes: ... + def translate(self, __table: ReadableBuffer | None, delete: bytes = ...) -> bytes: ... def upper(self) -> bytes: ... def zfill(self, __width: SupportsIndex) -> bytes: ... @classmethod def fromhex(cls: type[Self], __s: str) -> Self: ... @staticmethod - def maketrans(__frm: bytes, __to: bytes) -> bytes: ... + def maketrans(__frm: ReadableBuffer, __to: ReadableBuffer) -> bytes: ... def __len__(self) -> int: ... def __iter__(self) -> Iterator[int]: ... def __hash__(self) -> int: ... @@ -553,7 +568,7 @@ class bytes(ByteString): def __getitem__(self, __i: SupportsIndex) -> int: ... @overload def __getitem__(self, __s: slice) -> bytes: ... - def __add__(self, __s: bytes) -> bytes: ... + def __add__(self, __s: ReadableBuffer) -> bytes: ... def __mul__(self, __n: SupportsIndex) -> bytes: ... def __rmul__(self, __n: SupportsIndex) -> bytes: ... def __mod__(self, __value: Any) -> bytes: ... @@ -582,12 +597,15 @@ class bytearray(MutableSequence[int], ByteString): def capitalize(self) -> bytearray: ... def center(self, __width: SupportsIndex, __fillchar: bytes = ...) -> bytearray: ... def count( - self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... + self, __sub: ReadableBuffer | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> int: ... def copy(self) -> bytearray: ... def decode(self, encoding: str = ..., errors: str = ...) -> str: ... def endswith( - self, __suffix: bytes | tuple[bytes, ...], __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... + self, + __suffix: ReadableBuffer | tuple[ReadableBuffer, ...], + __start: SupportsIndex | None = ..., + __end: SupportsIndex | None = ..., ) -> bool: ... if sys.version_info >= (3, 8): def expandtabs(self, tabsize: SupportsIndex = ...) -> bytearray: ... @@ -596,7 +614,7 @@ class bytearray(MutableSequence[int], ByteString): def extend(self, __iterable_of_ints: Iterable[SupportsIndex]) -> None: ... def find( - self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... + self, __sub: ReadableBuffer | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> int: ... if sys.version_info >= (3, 8): def hex(self, sep: str | bytes = ..., bytes_per_sep: SupportsIndex = ...) -> str: ... @@ -604,7 +622,7 @@ class bytearray(MutableSequence[int], ByteString): def hex(self) -> str: ... def index( - self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... + self, __sub: ReadableBuffer | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> int: ... def insert(self, __index: SupportsIndex, __item: SupportsIndex) -> None: ... def isalnum(self) -> bool: ... @@ -617,43 +635,46 @@ class bytearray(MutableSequence[int], ByteString): def isspace(self) -> bool: ... def istitle(self) -> bool: ... def isupper(self) -> bool: ... - def join(self, __iterable_of_bytes: Iterable[ByteString | memoryview]) -> bytearray: ... - def ljust(self, __width: SupportsIndex, __fillchar: bytes = ...) -> bytearray: ... + def join(self, __iterable_of_bytes: Iterable[ReadableBuffer]) -> bytearray: ... + def ljust(self, __width: SupportsIndex, __fillchar: bytes | bytearray = ...) -> bytearray: ... def lower(self) -> bytearray: ... - def lstrip(self, __bytes: bytes | None = ...) -> bytearray: ... - def partition(self, __sep: bytes) -> tuple[bytearray, bytearray, bytearray]: ... + def lstrip(self, __bytes: ReadableBuffer | None = ...) -> bytearray: ... + def partition(self, __sep: ReadableBuffer) -> tuple[bytearray, bytearray, bytearray]: ... def pop(self, __index: int = ...) -> int: ... def remove(self, __value: int) -> None: ... if sys.version_info >= (3, 9): - def removeprefix(self, __prefix: bytes) -> bytearray: ... - def removesuffix(self, __suffix: bytes) -> bytearray: ... + def removeprefix(self, __prefix: ReadableBuffer) -> bytearray: ... + def removesuffix(self, __suffix: ReadableBuffer) -> bytearray: ... - def replace(self, __old: bytes, __new: bytes, __count: SupportsIndex = ...) -> bytearray: ... + def replace(self, __old: ReadableBuffer, __new: ReadableBuffer, __count: SupportsIndex = ...) -> bytearray: ... def rfind( - self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... + self, __sub: ReadableBuffer | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> int: ... def rindex( - self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... + self, __sub: ReadableBuffer | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> int: ... - def rjust(self, __width: SupportsIndex, __fillchar: bytes = ...) -> bytearray: ... - def rpartition(self, __sep: bytes) -> tuple[bytearray, bytearray, bytearray]: ... - def rsplit(self, sep: bytes | None = ..., maxsplit: SupportsIndex = ...) -> list[bytearray]: ... - def rstrip(self, __bytes: bytes | None = ...) -> bytearray: ... - def split(self, sep: bytes | None = ..., maxsplit: SupportsIndex = ...) -> list[bytearray]: ... + def rjust(self, __width: SupportsIndex, __fillchar: bytes | bytearray = ...) -> bytearray: ... + def rpartition(self, __sep: ReadableBuffer) -> tuple[bytearray, bytearray, bytearray]: ... + def rsplit(self, sep: ReadableBuffer | None = ..., maxsplit: SupportsIndex = ...) -> list[bytearray]: ... + def rstrip(self, __bytes: ReadableBuffer | None = ...) -> bytearray: ... + def split(self, sep: ReadableBuffer | None = ..., maxsplit: SupportsIndex = ...) -> list[bytearray]: ... def splitlines(self, keepends: bool = ...) -> list[bytearray]: ... def startswith( - self, __prefix: bytes | tuple[bytes, ...], __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... + self, + __prefix: ReadableBuffer | tuple[ReadableBuffer, ...], + __start: SupportsIndex | None = ..., + __end: SupportsIndex | None = ..., ) -> bool: ... - def strip(self, __bytes: bytes | None = ...) -> bytearray: ... + def strip(self, __bytes: ReadableBuffer | None = ...) -> bytearray: ... def swapcase(self) -> bytearray: ... def title(self) -> bytearray: ... - def translate(self, __table: bytes | None, delete: bytes = ...) -> bytearray: ... + def translate(self, __table: ReadableBuffer | None, delete: bytes = ...) -> bytearray: ... def upper(self) -> bytearray: ... def zfill(self, __width: SupportsIndex) -> bytearray: ... @classmethod def fromhex(cls: type[Self], __string: str) -> Self: ... @staticmethod - def maketrans(__frm: bytes, __to: bytes) -> bytes: ... + def maketrans(__frm: ReadableBuffer, __to: ReadableBuffer) -> bytes: ... def __len__(self) -> int: ... def __iter__(self) -> Iterator[int]: ... __hash__: ClassVar[None] # type: ignore[assignment] @@ -666,14 +687,15 @@ class bytearray(MutableSequence[int], ByteString): @overload def __setitem__(self, __s: slice, __x: Iterable[SupportsIndex] | bytes) -> None: ... def __delitem__(self, __i: SupportsIndex | slice) -> None: ... - def __add__(self, __s: bytes) -> bytearray: ... - def __iadd__(self: Self, __s: Iterable[int]) -> Self: ... + def __add__(self, __s: ReadableBuffer) -> bytearray: ... + # The superclass wants us to accept Iterable[int], but that fails at runtime. + def __iadd__(self: Self, __s: ReadableBuffer) -> Self: ... # type: ignore[override] def __mul__(self, __n: SupportsIndex) -> bytearray: ... def __rmul__(self, __n: SupportsIndex) -> bytearray: ... def __imul__(self: Self, __n: SupportsIndex) -> Self: ... def __mod__(self, __value: Any) -> bytes: ... # Incompatible with Sequence.__contains__ - def __contains__(self, __o: SupportsIndex | bytes) -> bool: ... # type: ignore[override] + def __contains__(self, __o: SupportsIndex | ReadableBuffer) -> bool: ... # type: ignore[override] def __eq__(self, __x: object) -> bool: ... def __ne__(self, __x: object) -> bool: ... def __lt__(self, __x: bytes) -> bool: ... @@ -722,7 +744,7 @@ class memoryview(Sized, Sequence[int]): def __iter__(self) -> Iterator[int]: ... def __len__(self) -> int: ... @overload - def __setitem__(self, __s: slice, __o: bytes) -> None: ... + def __setitem__(self, __s: slice, __o: ReadableBuffer) -> None: ... @overload def __setitem__(self, __i: SupportsIndex, __o: SupportsIndex) -> None: ... if sys.version_info >= (3, 8): @@ -1086,8 +1108,8 @@ if sys.version_info >= (3, 10): # TODO: `compile` has a more precise return type in reality; work on a way of expressing that? if sys.version_info >= (3, 8): def compile( - source: str | bytes | AST, - filename: str | bytes | _PathLike[Any], + source: str | ReadableBuffer | AST, + filename: str | ReadableBuffer | _PathLike[Any], mode: str, flags: int = ..., dont_inherit: int = ..., @@ -1098,8 +1120,8 @@ if sys.version_info >= (3, 8): else: def compile( - source: str | bytes | AST, - filename: str | bytes | _PathLike[Any], + source: str | ReadableBuffer | AST, + filename: str | ReadableBuffer | _PathLike[Any], mode: str, flags: int = ..., dont_inherit: int = ..., @@ -1118,12 +1140,12 @@ def divmod(__x: _T_contra, __y: SupportsRDivMod[_T_contra, _T_co]) -> _T_co: ... # The `globals` argument to `eval` has to be `dict[str, Any]` rather than `dict[str, object]` due to invariance. # (The `globals` argument has to be a "real dict", rather than any old mapping, unlike the `locals` argument.) def eval( - __source: str | bytes | CodeType, __globals: dict[str, Any] | None = ..., __locals: Mapping[str, object] | None = ... + __source: str | ReadableBuffer | CodeType, __globals: dict[str, Any] | None = ..., __locals: Mapping[str, object] | None = ... ) -> Any: ... # Comment above regarding `eval` applies to `exec` as well def exec( - __source: str | bytes | CodeType, __globals: dict[str, Any] | None = ..., __locals: Mapping[str, object] | None = ... + __source: str | ReadableBuffer | CodeType, __globals: dict[str, Any] | None = ..., __locals: Mapping[str, object] | None = ... ) -> None: ... def exit(code: object = ...) -> NoReturn: ... @@ -1262,8 +1284,8 @@ def next(__i: SupportsNext[_T]) -> _T: ... def next(__i: SupportsNext[_T], __default: _VT) -> _T | _VT: ... def oct(__number: int | SupportsIndex) -> str: ... -_OpenFile = StrOrBytesPath | int -_Opener = Callable[[str, int], int] +_OpenFile = StrOrBytesPath | int # noqa: Y026 # TODO: Use TypeAlias once mypy bugs are fixed +_Opener: TypeAlias = Callable[[str, int], int] # Text mode: always returns a TextIOWrapper @overload @@ -1351,7 +1373,7 @@ def open( closefd: bool = ..., opener: _Opener | None = ..., ) -> IO[Any]: ... -def ord(__c: str | bytes) -> int: ... +def ord(__c: str | bytes | bytearray) -> int: ... class _SupportsWriteAndFlush(SupportsWrite[_T_contra], Protocol[_T_contra]): def flush(self) -> None: ... @@ -1381,7 +1403,9 @@ class _SupportsPow3NoneOnly(Protocol[_E, _T_co]): class _SupportsPow3(Protocol[_E, _M, _T_co]): def __pow__(self, __other: _E, __modulo: _M) -> _T_co: ... -_SupportsSomeKindOfPow = _SupportsPow2[Any, Any] | _SupportsPow3NoneOnly[Any, Any] | _SupportsPow3[Any, Any, Any] +_SupportsSomeKindOfPow = ( # noqa: Y026 # TODO: Use TypeAlias once mypy bugs are fixed + _SupportsPow2[Any, Any] | _SupportsPow3NoneOnly[Any, Any] | _SupportsPow3[Any, Any, Any] +) if sys.version_info >= (3, 8): @overload @@ -1712,7 +1736,7 @@ class UnicodeDecodeError(UnicodeError): start: int end: int reason: str - def __init__(self, __encoding: str, __object: bytes, __start: int, __end: int, __reason: str) -> None: ... + def __init__(self, __encoding: str, __object: ReadableBuffer, __start: int, __end: int, __reason: str) -> None: ... class UnicodeEncodeError(UnicodeError): encoding: str @@ -1770,6 +1794,7 @@ if sys.version_info >= (3, 11): @overload def split(self: Self, __condition: Callable[[_BaseExceptionT_co], bool]) -> tuple[Self | None, Self | None]: ... def derive(self: Self, __excs: Sequence[_BaseExceptionT_co]) -> Self: ... + def __class_getitem__(cls, __item: Any) -> GenericAlias: ... class ExceptionGroup(BaseExceptionGroup[_ExceptionT_co], Exception): def __new__(cls: type[Self], __message: str, __exceptions: Sequence[_ExceptionT_co]) -> Self: ... diff --git a/mypy/typeshed/stdlib/bz2.pyi b/mypy/typeshed/stdlib/bz2.pyi index f1467acadd103..cea317e280371 100644 --- a/mypy/typeshed/stdlib/bz2.pyi +++ b/mypy/typeshed/stdlib/bz2.pyi @@ -2,8 +2,9 @@ import _compression import sys from _compression import BaseStream from _typeshed import ReadableBuffer, Self, StrOrBytesPath, WriteableBuffer -from typing import IO, Any, Iterable, Protocol, TextIO, overload -from typing_extensions import Literal, SupportsIndex, final +from collections.abc import Iterable +from typing import IO, Any, Protocol, TextIO, overload +from typing_extensions import Literal, SupportsIndex, TypeAlias, final __all__ = ["BZ2File", "BZ2Compressor", "BZ2Decompressor", "open", "compress", "decompress"] @@ -21,10 +22,10 @@ class _WritableFileobj(Protocol): def compress(data: bytes, compresslevel: int = ...) -> bytes: ... def decompress(data: bytes) -> bytes: ... -_ReadBinaryMode = Literal["", "r", "rb"] -_WriteBinaryMode = Literal["w", "wb", "x", "xb", "a", "ab"] -_ReadTextMode = Literal["rt"] -_WriteTextMode = Literal["wt", "xt", "at"] +_ReadBinaryMode: TypeAlias = Literal["", "r", "rb"] +_WriteBinaryMode: TypeAlias = Literal["w", "wb", "x", "xb", "a", "ab"] +_ReadTextMode: TypeAlias = Literal["rt"] +_WriteTextMode: TypeAlias = Literal["wt", "xt", "at"] @overload def open( diff --git a/mypy/typeshed/stdlib/cProfile.pyi b/mypy/typeshed/stdlib/cProfile.pyi index 6f15e461e007f..6e21fc92ade54 100644 --- a/mypy/typeshed/stdlib/cProfile.pyi +++ b/mypy/typeshed/stdlib/cProfile.pyi @@ -1,8 +1,9 @@ import sys from _typeshed import Self, StrOrBytesPath +from collections.abc import Callable from types import CodeType -from typing import Any, Callable, TypeVar -from typing_extensions import ParamSpec +from typing import Any, TypeVar +from typing_extensions import ParamSpec, TypeAlias __all__ = ["run", "runctx", "Profile"] @@ -13,7 +14,7 @@ def runctx( _T = TypeVar("_T") _P = ParamSpec("_P") -_Label = tuple[str, int, str] +_Label: TypeAlias = tuple[str, int, str] class Profile: stats: dict[_Label, tuple[int, int, int, int, dict[_Label, tuple[int, int, int, int]]]] # undocumented diff --git a/mypy/typeshed/stdlib/calendar.pyi b/mypy/typeshed/stdlib/calendar.pyi index f106eb1213f19..c7e0a6b4606f2 100644 --- a/mypy/typeshed/stdlib/calendar.pyi +++ b/mypy/typeshed/stdlib/calendar.pyi @@ -2,7 +2,7 @@ import datetime import sys from collections.abc import Iterable, Sequence from time import struct_time -from typing_extensions import Literal +from typing_extensions import Literal, TypeAlias if sys.version_info >= (3, 10): __all__ = [ @@ -66,7 +66,7 @@ else: "weekheader", ] -_LocaleType = tuple[str | None, str | None] +_LocaleType: TypeAlias = tuple[str | None, str | None] class IllegalMonthError(ValueError): def __init__(self, month: int) -> None: ... diff --git a/mypy/typeshed/stdlib/cgi.pyi b/mypy/typeshed/stdlib/cgi.pyi index 0bd4e515ce51b..5e7bebc2a7f8a 100644 --- a/mypy/typeshed/stdlib/cgi.pyi +++ b/mypy/typeshed/stdlib/cgi.pyi @@ -1,6 +1,6 @@ import sys from _typeshed import Self, SupportsGetItem, SupportsItemAccess -from builtins import type as _type +from builtins import list as _list, type as _type from collections.abc import Iterable, Iterator, Mapping from types import TracebackType from typing import IO, Any, Protocol @@ -87,8 +87,6 @@ class MiniFieldStorage: value: Any def __init__(self, name: Any, value: Any) -> None: ... -_list = list - class FieldStorage: FieldStorageClass: _type | None keep_blank_values: int diff --git a/mypy/typeshed/stdlib/cgitb.pyi b/mypy/typeshed/stdlib/cgitb.pyi index 2db108ce75ec1..ea5a8341bc5e3 100644 --- a/mypy/typeshed/stdlib/cgitb.pyi +++ b/mypy/typeshed/stdlib/cgitb.pyi @@ -1,8 +1,7 @@ -from _typeshed import StrOrBytesPath +from _typeshed import OptExcInfo, StrOrBytesPath +from collections.abc import Callable from types import FrameType, TracebackType -from typing import IO, Any, Callable - -_ExcInfo = tuple[type[BaseException] | None, BaseException | None, TracebackType | None] +from typing import IO, Any __UNDEF__: object # undocumented sentinel @@ -14,8 +13,8 @@ def lookup(name: str, frame: FrameType, locals: dict[str, Any]) -> tuple[str | N def scanvars( reader: Callable[[], bytes], frame: FrameType, locals: dict[str, Any] ) -> list[tuple[str, str | None, Any]]: ... # undocumented -def html(einfo: _ExcInfo, context: int = ...) -> str: ... -def text(einfo: _ExcInfo, context: int = ...) -> str: ... +def html(einfo: OptExcInfo, context: int = ...) -> str: ... +def text(einfo: OptExcInfo, context: int = ...) -> str: ... class Hook: # undocumented def __init__( @@ -27,7 +26,7 @@ class Hook: # undocumented format: str = ..., ) -> None: ... def __call__(self, etype: type[BaseException] | None, evalue: BaseException | None, etb: TracebackType | None) -> None: ... - def handle(self, info: _ExcInfo | None = ...) -> None: ... + def handle(self, info: OptExcInfo | None = ...) -> None: ... -def handler(info: _ExcInfo | None = ...) -> None: ... +def handler(info: OptExcInfo | None = ...) -> None: ... def enable(display: int = ..., logdir: StrOrBytesPath | None = ..., context: int = ..., format: str = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/cmath.pyi b/mypy/typeshed/stdlib/cmath.pyi index ee51861fdaa06..30ada5d5b5efc 100644 --- a/mypy/typeshed/stdlib/cmath.pyi +++ b/mypy/typeshed/stdlib/cmath.pyi @@ -1,5 +1,6 @@ import sys from typing import SupportsComplex, SupportsFloat +from typing_extensions import TypeAlias if sys.version_info >= (3, 8): from typing import SupportsIndex @@ -13,9 +14,9 @@ nanj: complex tau: float if sys.version_info >= (3, 8): - _C = SupportsFloat | SupportsComplex | SupportsIndex | complex + _C: TypeAlias = SupportsFloat | SupportsComplex | SupportsIndex | complex else: - _C = SupportsFloat | SupportsComplex | complex + _C: TypeAlias = SupportsFloat | SupportsComplex | complex def acos(__z: _C) -> complex: ... def acosh(__z: _C) -> complex: ... diff --git a/mypy/typeshed/stdlib/cmd.pyi b/mypy/typeshed/stdlib/cmd.pyi index d1166db0f507e..ddefff2edf055 100644 --- a/mypy/typeshed/stdlib/cmd.pyi +++ b/mypy/typeshed/stdlib/cmd.pyi @@ -1,4 +1,5 @@ -from typing import IO, Any, Callable +from collections.abc import Callable +from typing import IO, Any from typing_extensions import Literal __all__ = ["Cmd"] diff --git a/mypy/typeshed/stdlib/code.pyi b/mypy/typeshed/stdlib/code.pyi index 185c15853b826..59318aa353e2e 100644 --- a/mypy/typeshed/stdlib/code.pyi +++ b/mypy/typeshed/stdlib/code.pyi @@ -1,6 +1,7 @@ from codeop import CommandCompiler +from collections.abc import Callable, Mapping from types import CodeType -from typing import Any, Callable, Mapping +from typing import Any __all__ = ["InteractiveInterpreter", "InteractiveConsole", "interact", "compile_command"] diff --git a/mypy/typeshed/stdlib/codecs.pyi b/mypy/typeshed/stdlib/codecs.pyi index 8fa93961d9d09..bba7703c7d330 100644 --- a/mypy/typeshed/stdlib/codecs.pyi +++ b/mypy/typeshed/stdlib/codecs.pyi @@ -2,8 +2,9 @@ import sys import types from _typeshed import Self from abc import abstractmethod -from typing import IO, Any, BinaryIO, Callable, Generator, Iterable, Iterator, Protocol, TextIO, overload -from typing_extensions import Literal +from collections.abc import Callable, Generator, Iterable, Iterator +from typing import IO, Any, BinaryIO, Protocol, TextIO, overload +from typing_extensions import Literal, TypeAlias __all__ = [ "register", @@ -83,7 +84,7 @@ class _IncrementalDecoder(Protocol): # The type ignore on `encode` and `decode` is to avoid issues with overlapping overloads, for more details, see #300 # https://docs.python.org/3/library/codecs.html#binary-transforms -_BytesToBytesEncoding = Literal[ +_BytesToBytesEncoding: TypeAlias = Literal[ "base64", "base_64", "base64_codec", @@ -102,7 +103,7 @@ _BytesToBytesEncoding = Literal[ "zlib_codec", ] # https://docs.python.org/3/library/codecs.html#text-transforms -_StrToStrEncoding = Literal["rot13", "rot_13"] +_StrToStrEncoding: TypeAlias = Literal["rot13", "rot_13"] @overload def encode(obj: bytes, encoding: _BytesToBytesEncoding, errors: str = ...) -> bytes: ... diff --git a/mypy/typeshed/stdlib/collections/__init__.pyi b/mypy/typeshed/stdlib/collections/__init__.pyi index e534c13c026b5..2e88c0d8f4743 100644 --- a/mypy/typeshed/stdlib/collections/__init__.pyi +++ b/mypy/typeshed/stdlib/collections/__init__.pyi @@ -8,7 +8,7 @@ if sys.version_info >= (3, 9): from types import GenericAlias if sys.version_info >= (3, 10): - from typing import Callable, Iterable, Iterator, Mapping, MutableMapping, MutableSequence, Reversible, Sequence + from collections.abc import Callable, Iterable, Iterator, Mapping, MutableMapping, MutableSequence, Reversible, Sequence else: from _collections_abc import * diff --git a/mypy/typeshed/stdlib/concurrent/futures/_base.pyi b/mypy/typeshed/stdlib/concurrent/futures/_base.pyi index 4967d01f90dc3..5b756d87d118c 100644 --- a/mypy/typeshed/stdlib/concurrent/futures/_base.pyi +++ b/mypy/typeshed/stdlib/concurrent/futures/_base.pyi @@ -2,10 +2,10 @@ import sys import threading from _typeshed import Self from abc import abstractmethod -from collections.abc import Container, Iterable, Iterator, Sequence +from collections.abc import Callable, Container, Iterable, Iterator, Sequence from logging import Logger from types import TracebackType -from typing import Any, Callable, Generic, Protocol, TypeVar, overload +from typing import Any, Generic, Protocol, TypeVar, overload from typing_extensions import Literal, ParamSpec, SupportsIndex if sys.version_info >= (3, 9): diff --git a/mypy/typeshed/stdlib/concurrent/futures/process.pyi b/mypy/typeshed/stdlib/concurrent/futures/process.pyi index 0c6c403949adb..4cfa8276897f0 100644 --- a/mypy/typeshed/stdlib/concurrent/futures/process.pyi +++ b/mypy/typeshed/stdlib/concurrent/futures/process.pyi @@ -1,11 +1,11 @@ import sys -from collections.abc import Generator, Iterable, Mapping, MutableMapping, MutableSequence +from collections.abc import Callable, Generator, Iterable, Mapping, MutableMapping, MutableSequence from multiprocessing.connection import Connection from multiprocessing.context import BaseContext, Process from multiprocessing.queues import Queue, SimpleQueue from threading import Lock, Semaphore, Thread from types import TracebackType -from typing import Any, Callable, Generic, TypeVar +from typing import Any, Generic, TypeVar from weakref import ref from ._base import Executor, Future diff --git a/mypy/typeshed/stdlib/concurrent/futures/thread.pyi b/mypy/typeshed/stdlib/concurrent/futures/thread.pyi index 46ca681c54fc6..e10254531788d 100644 --- a/mypy/typeshed/stdlib/concurrent/futures/thread.pyi +++ b/mypy/typeshed/stdlib/concurrent/futures/thread.pyi @@ -1,8 +1,8 @@ import queue import sys -from collections.abc import Iterable, Mapping, Set as AbstractSet +from collections.abc import Callable, Iterable, Mapping, Set as AbstractSet from threading import Lock, Semaphore, Thread -from typing import Any, Callable, Generic, TypeVar +from typing import Any, Generic, TypeVar from weakref import ref from ._base import Executor, Future diff --git a/mypy/typeshed/stdlib/configparser.pyi b/mypy/typeshed/stdlib/configparser.pyi index 55df2ce58de70..5ffac353ab31a 100644 --- a/mypy/typeshed/stdlib/configparser.pyi +++ b/mypy/typeshed/stdlib/configparser.pyi @@ -2,7 +2,7 @@ import sys from _typeshed import StrOrBytesPath, StrPath, SupportsWrite from collections.abc import Callable, ItemsView, Iterable, Iterator, Mapping, MutableMapping, Sequence from typing import Any, ClassVar, Pattern, TypeVar, overload -from typing_extensions import Literal +from typing_extensions import Literal, TypeAlias __all__ = [ "NoSectionError", @@ -29,16 +29,16 @@ __all__ = [ ] # Internal type aliases -_section = Mapping[str, str] -_parser = MutableMapping[str, _section] -_converter = Callable[[str], Any] -_converters = dict[str, _converter] +_section: TypeAlias = Mapping[str, str] +_parser: TypeAlias = MutableMapping[str, _section] +_converter: TypeAlias = Callable[[str], Any] +_converters: TypeAlias = dict[str, _converter] _T = TypeVar("_T") if sys.version_info >= (3, 7): - _Path = StrOrBytesPath + _Path: TypeAlias = StrOrBytesPath else: - _Path = StrPath + _Path: TypeAlias = StrPath DEFAULTSECT: Literal["DEFAULT"] MAX_INTERPOLATION_DEPTH: Literal[10] diff --git a/mypy/typeshed/stdlib/contextlib.pyi b/mypy/typeshed/stdlib/contextlib.pyi index a60f8811e0acc..c93eeac3b44f7 100644 --- a/mypy/typeshed/stdlib/contextlib.pyi +++ b/mypy/typeshed/stdlib/contextlib.pyi @@ -1,22 +1,9 @@ import sys from _typeshed import Self, StrOrBytesPath +from collections.abc import AsyncGenerator, AsyncIterator, Awaitable, Callable, Generator, Iterator from types import TracebackType -from typing import ( # noqa: Y027 - IO, - Any, - AsyncGenerator, - AsyncIterator, - Awaitable, - Callable, - ContextManager, - Generator, - Generic, - Iterator, - Protocol, - TypeVar, - overload, -) -from typing_extensions import ParamSpec +from typing import IO, Any, ContextManager, Generic, Protocol, TypeVar, overload # noqa: Y027 +from typing_extensions import ParamSpec, TypeAlias if sys.version_info >= (3, 11): __all__ = [ @@ -90,7 +77,7 @@ _T_io = TypeVar("_T_io", bound=IO[str] | None) _F = TypeVar("_F", bound=Callable[..., Any]) _P = ParamSpec("_P") -_ExitFunc = Callable[[type[BaseException] | None, BaseException | None, TracebackType | None], bool | None] +_ExitFunc: TypeAlias = Callable[[type[BaseException] | None, BaseException | None, TracebackType | None], bool | None] _CM_EF = TypeVar("_CM_EF", AbstractContextManager[Any], _ExitFunc) class ContextDecorator: @@ -189,7 +176,7 @@ class ExitStack(AbstractContextManager[ExitStack]): ) -> bool: ... if sys.version_info >= (3, 7): - _ExitCoroFunc = Callable[[type[BaseException] | None, BaseException | None, TracebackType | None], Awaitable[bool]] + _ExitCoroFunc: TypeAlias = Callable[[type[BaseException] | None, BaseException | None, TracebackType | None], Awaitable[bool]] _ACM_EF = TypeVar("_ACM_EF", AbstractAsyncContextManager[Any], _ExitCoroFunc) class AsyncExitStack(AbstractAsyncContextManager[AsyncExitStack]): diff --git a/mypy/typeshed/stdlib/contextvars.pyi b/mypy/typeshed/stdlib/contextvars.pyi index 6b5661dd69eb6..341cd8491caf0 100644 --- a/mypy/typeshed/stdlib/contextvars.pyi +++ b/mypy/typeshed/stdlib/contextvars.pyi @@ -1,5 +1,6 @@ import sys -from typing import Any, Callable, ClassVar, Generic, Iterator, Mapping, TypeVar, overload +from collections.abc import Callable, Iterator, Mapping +from typing import Any, ClassVar, Generic, TypeVar, overload from typing_extensions import ParamSpec, final if sys.version_info >= (3, 9): diff --git a/mypy/typeshed/stdlib/copyreg.pyi b/mypy/typeshed/stdlib/copyreg.pyi index 4844a8028c5c4..4403550b587ee 100644 --- a/mypy/typeshed/stdlib/copyreg.pyi +++ b/mypy/typeshed/stdlib/copyreg.pyi @@ -1,7 +1,9 @@ -from typing import Any, Callable, Hashable, SupportsInt, TypeVar, Union +from collections.abc import Callable, Hashable +from typing import Any, SupportsInt, TypeVar, Union +from typing_extensions import TypeAlias _T = TypeVar("_T") -_Reduce = Union[tuple[Callable[..., _T], tuple[Any, ...]], tuple[Callable[..., _T], tuple[Any, ...], Any | None]] +_Reduce: TypeAlias = Union[tuple[Callable[..., _T], tuple[Any, ...]], tuple[Callable[..., _T], tuple[Any, ...], Any | None]] __all__ = ["pickle", "constructor", "add_extension", "remove_extension", "clear_extension_cache"] @@ -15,5 +17,5 @@ def add_extension(module: Hashable, name: Hashable, code: SupportsInt) -> None: def remove_extension(module: Hashable, name: Hashable, code: int) -> None: ... def clear_extension_cache() -> None: ... -_DispatchTableType = dict[type, Callable[[Any], str | _Reduce[Any]]] # imported by multiprocessing.reduction +_DispatchTableType: TypeAlias = dict[type, Callable[[Any], str | _Reduce[Any]]] # imported by multiprocessing.reduction dispatch_table: _DispatchTableType # undocumented diff --git a/mypy/typeshed/stdlib/ctypes/__init__.pyi b/mypy/typeshed/stdlib/ctypes/__init__.pyi index 4a03886e8dd25..53a382ec0e718 100644 --- a/mypy/typeshed/stdlib/ctypes/__init__.pyi +++ b/mypy/typeshed/stdlib/ctypes/__init__.pyi @@ -1,7 +1,9 @@ import sys from _typeshed import ReadableBuffer, Self, WriteableBuffer from abc import abstractmethod -from typing import Any, Callable, ClassVar, Generic, Iterable, Iterator, Mapping, Sequence, TypeVar, Union as _UnionT, overload +from collections.abc import Callable, Iterable, Iterator, Mapping, Sequence +from typing import Any, ClassVar, Generic, TypeVar, Union as _UnionT, overload +from typing_extensions import TypeAlias if sys.version_info >= (3, 9): from types import GenericAlias @@ -84,8 +86,8 @@ class _CData(metaclass=_CDataMeta): class _CanCastTo(_CData): ... class _PointerLike(_CanCastTo): ... -_ECT = Callable[[type[_CData] | None, _FuncPointer, tuple[_CData, ...]], _CData] -_PF = _UnionT[tuple[int], tuple[int, str], tuple[int, str, Any]] +_ECT: TypeAlias = Callable[[type[_CData] | None, _FuncPointer, tuple[_CData, ...]], _CData] +_PF: TypeAlias = _UnionT[tuple[int], tuple[int, str], tuple[int, str, Any]] class _FuncPointer(_PointerLike, _CData): restype: type[_CData] | Callable[[int], Any] | None @@ -121,12 +123,12 @@ class _CArgObject: ... # Any type that can be implicitly converted to c_void_p when passed as a C function argument. # (bytes is not included here, see below.) -_CVoidPLike = _PointerLike | Array[Any] | _CArgObject | int +_CVoidPLike: TypeAlias = _PointerLike | Array[Any] | _CArgObject | int # Same as above, but including types known to be read-only (i. e. bytes). # This distinction is not strictly necessary (ctypes doesn't differentiate between const # and non-const pointers), but it catches errors like memmove(b'foo', buf, 4) # when memmove(buf, b'foo', 4) was intended. -_CVoidConstPLike = _CVoidPLike | bytes +_CVoidConstPLike: TypeAlias = _CVoidPLike | bytes def addressof(obj: _CData) -> int: ... def alignment(obj_or_type: _CData | type[_CData]) -> int: ... diff --git a/mypy/typeshed/stdlib/ctypes/wintypes.pyi b/mypy/typeshed/stdlib/ctypes/wintypes.pyi index c178a9bdf9365..9536114b786a4 100644 --- a/mypy/typeshed/stdlib/ctypes/wintypes.pyi +++ b/mypy/typeshed/stdlib/ctypes/wintypes.pyi @@ -20,6 +20,7 @@ from ctypes import ( c_wchar_p, pointer, ) +from typing_extensions import TypeAlias BYTE = c_byte WORD = c_ushort @@ -182,53 +183,53 @@ class WIN32_FIND_DATAW(Structure): # These pointer type definitions use pointer[...] instead of POINTER(...), to allow them # to be used in type annotations. -PBOOL = pointer[BOOL] -LPBOOL = pointer[BOOL] -PBOOLEAN = pointer[BOOLEAN] -PBYTE = pointer[BYTE] -LPBYTE = pointer[BYTE] -PCHAR = pointer[CHAR] -LPCOLORREF = pointer[COLORREF] -PDWORD = pointer[DWORD] -LPDWORD = pointer[DWORD] -PFILETIME = pointer[FILETIME] -LPFILETIME = pointer[FILETIME] -PFLOAT = pointer[FLOAT] -PHANDLE = pointer[HANDLE] -LPHANDLE = pointer[HANDLE] -PHKEY = pointer[HKEY] -LPHKL = pointer[HKL] -PINT = pointer[INT] -LPINT = pointer[INT] -PLARGE_INTEGER = pointer[LARGE_INTEGER] -PLCID = pointer[LCID] -PLONG = pointer[LONG] -LPLONG = pointer[LONG] -PMSG = pointer[MSG] -LPMSG = pointer[MSG] -PPOINT = pointer[POINT] -LPPOINT = pointer[POINT] -PPOINTL = pointer[POINTL] -PRECT = pointer[RECT] -LPRECT = pointer[RECT] -PRECTL = pointer[RECTL] -LPRECTL = pointer[RECTL] -LPSC_HANDLE = pointer[SC_HANDLE] -PSHORT = pointer[SHORT] -PSIZE = pointer[SIZE] -LPSIZE = pointer[SIZE] -PSIZEL = pointer[SIZEL] -LPSIZEL = pointer[SIZEL] -PSMALL_RECT = pointer[SMALL_RECT] -PUINT = pointer[UINT] -LPUINT = pointer[UINT] -PULARGE_INTEGER = pointer[ULARGE_INTEGER] -PULONG = pointer[ULONG] -PUSHORT = pointer[USHORT] -PWCHAR = pointer[WCHAR] -PWIN32_FIND_DATAA = pointer[WIN32_FIND_DATAA] -LPWIN32_FIND_DATAA = pointer[WIN32_FIND_DATAA] -PWIN32_FIND_DATAW = pointer[WIN32_FIND_DATAW] -LPWIN32_FIND_DATAW = pointer[WIN32_FIND_DATAW] -PWORD = pointer[WORD] -LPWORD = pointer[WORD] +PBOOL: TypeAlias = pointer[BOOL] +LPBOOL: TypeAlias = pointer[BOOL] +PBOOLEAN: TypeAlias = pointer[BOOLEAN] +PBYTE: TypeAlias = pointer[BYTE] +LPBYTE: TypeAlias = pointer[BYTE] +PCHAR: TypeAlias = pointer[CHAR] +LPCOLORREF: TypeAlias = pointer[COLORREF] +PDWORD: TypeAlias = pointer[DWORD] +LPDWORD: TypeAlias = pointer[DWORD] +PFILETIME: TypeAlias = pointer[FILETIME] +LPFILETIME: TypeAlias = pointer[FILETIME] +PFLOAT: TypeAlias = pointer[FLOAT] +PHANDLE: TypeAlias = pointer[HANDLE] +LPHANDLE: TypeAlias = pointer[HANDLE] +PHKEY: TypeAlias = pointer[HKEY] +LPHKL: TypeAlias = pointer[HKL] +PINT: TypeAlias = pointer[INT] +LPINT: TypeAlias = pointer[INT] +PLARGE_INTEGER: TypeAlias = pointer[LARGE_INTEGER] +PLCID: TypeAlias = pointer[LCID] +PLONG: TypeAlias = pointer[LONG] +LPLONG: TypeAlias = pointer[LONG] +PMSG: TypeAlias = pointer[MSG] +LPMSG: TypeAlias = pointer[MSG] +PPOINT: TypeAlias = pointer[POINT] +LPPOINT: TypeAlias = pointer[POINT] +PPOINTL: TypeAlias = pointer[POINTL] +PRECT: TypeAlias = pointer[RECT] +LPRECT: TypeAlias = pointer[RECT] +PRECTL: TypeAlias = pointer[RECTL] +LPRECTL: TypeAlias = pointer[RECTL] +LPSC_HANDLE: TypeAlias = pointer[SC_HANDLE] +PSHORT: TypeAlias = pointer[SHORT] +PSIZE: TypeAlias = pointer[SIZE] +LPSIZE: TypeAlias = pointer[SIZE] +PSIZEL: TypeAlias = pointer[SIZEL] +LPSIZEL: TypeAlias = pointer[SIZEL] +PSMALL_RECT: TypeAlias = pointer[SMALL_RECT] +PUINT: TypeAlias = pointer[UINT] +LPUINT: TypeAlias = pointer[UINT] +PULARGE_INTEGER: TypeAlias = pointer[ULARGE_INTEGER] +PULONG: TypeAlias = pointer[ULONG] +PUSHORT: TypeAlias = pointer[USHORT] +PWCHAR: TypeAlias = pointer[WCHAR] +PWIN32_FIND_DATAA: TypeAlias = pointer[WIN32_FIND_DATAA] +LPWIN32_FIND_DATAA: TypeAlias = pointer[WIN32_FIND_DATAA] +PWIN32_FIND_DATAW: TypeAlias = pointer[WIN32_FIND_DATAW] +LPWIN32_FIND_DATAW: TypeAlias = pointer[WIN32_FIND_DATAW] +PWORD: TypeAlias = pointer[WORD] +LPWORD: TypeAlias = pointer[WORD] diff --git a/mypy/typeshed/stdlib/curses/__init__.pyi b/mypy/typeshed/stdlib/curses/__init__.pyi index ee74c13b6b50f..f80ed442ea9c4 100644 --- a/mypy/typeshed/stdlib/curses/__init__.pyi +++ b/mypy/typeshed/stdlib/curses/__init__.pyi @@ -1,5 +1,6 @@ import sys -from typing import Any, Callable, TypeVar +from collections.abc import Callable +from typing import Any, TypeVar if sys.platform != "win32": from _curses import * diff --git a/mypy/typeshed/stdlib/curses/textpad.pyi b/mypy/typeshed/stdlib/curses/textpad.pyi index b8a9c843f4021..ad9983431fc70 100644 --- a/mypy/typeshed/stdlib/curses/textpad.pyi +++ b/mypy/typeshed/stdlib/curses/textpad.pyi @@ -1,5 +1,5 @@ import sys -from typing import Callable +from collections.abc import Callable if sys.platform != "win32": from _curses import _CursesWindow diff --git a/mypy/typeshed/stdlib/dataclasses.pyi b/mypy/typeshed/stdlib/dataclasses.pyi index d82e9a2bb5266..f58c6f9f1460b 100644 --- a/mypy/typeshed/stdlib/dataclasses.pyi +++ b/mypy/typeshed/stdlib/dataclasses.pyi @@ -2,7 +2,8 @@ import enum import sys import types from builtins import type as Type # alias to avoid name clashes with fields named "type" -from typing import Any, Callable, Generic, Iterable, Mapping, Protocol, TypeVar, overload +from collections.abc import Callable, Iterable, Mapping +from typing import Any, Generic, Protocol, TypeVar, overload from typing_extensions import Literal if sys.version_info >= (3, 9): diff --git a/mypy/typeshed/stdlib/datetime.pyi b/mypy/typeshed/stdlib/datetime.pyi index 220e07e25fe01..113c679743fd6 100644 --- a/mypy/typeshed/stdlib/datetime.pyi +++ b/mypy/typeshed/stdlib/datetime.pyi @@ -2,7 +2,7 @@ import sys from _typeshed import Self from time import struct_time from typing import ClassVar, NamedTuple, NoReturn, SupportsAbs, TypeVar, overload -from typing_extensions import Literal, final +from typing_extensions import Literal, TypeAlias, final if sys.version_info >= (3, 9): __all__ = ("date", "datetime", "time", "timedelta", "timezone", "tzinfo", "MINYEAR", "MAXYEAR") @@ -19,7 +19,7 @@ class tzinfo: def fromutc(self, __dt: datetime) -> datetime: ... # Alias required to avoid name conflicts with date(time).tzinfo. -_tzinfo = tzinfo +_tzinfo: TypeAlias = tzinfo @final class timezone(tzinfo): @@ -150,8 +150,8 @@ class time: fold: int = ..., ) -> Self: ... -_date = date -_time = time +_date: TypeAlias = date +_time: TypeAlias = time class timedelta(SupportsAbs[timedelta]): min: ClassVar[timedelta] diff --git a/mypy/typeshed/stdlib/dbm/__init__.pyi b/mypy/typeshed/stdlib/dbm/__init__.pyi index d43a2415caffc..9e99f0d5e74cd 100644 --- a/mypy/typeshed/stdlib/dbm/__init__.pyi +++ b/mypy/typeshed/stdlib/dbm/__init__.pyi @@ -1,13 +1,13 @@ from _typeshed import Self +from collections.abc import Iterator, MutableMapping from types import TracebackType -from typing import Iterator, MutableMapping -from typing_extensions import Literal +from typing_extensions import Literal, TypeAlias __all__ = ["open", "whichdb", "error"] -_KeyType = str | bytes -_ValueType = str | bytes -_TFlags = Literal[ +_KeyType: TypeAlias = str | bytes +_ValueType: TypeAlias = str | bytes +_TFlags: TypeAlias = Literal[ "r", "w", "c", diff --git a/mypy/typeshed/stdlib/dbm/dumb.pyi b/mypy/typeshed/stdlib/dbm/dumb.pyi index 5af95ace72ad8..4fd199f197288 100644 --- a/mypy/typeshed/stdlib/dbm/dumb.pyi +++ b/mypy/typeshed/stdlib/dbm/dumb.pyi @@ -1,11 +1,12 @@ from _typeshed import Self +from collections.abc import Iterator, MutableMapping from types import TracebackType -from typing import Iterator, MutableMapping +from typing_extensions import TypeAlias __all__ = ["error", "open"] -_KeyType = str | bytes -_ValueType = str | bytes +_KeyType: TypeAlias = str | bytes +_ValueType: TypeAlias = str | bytes error = OSError diff --git a/mypy/typeshed/stdlib/dbm/gnu.pyi b/mypy/typeshed/stdlib/dbm/gnu.pyi index 9a603228a6916..561206c4e0be0 100644 --- a/mypy/typeshed/stdlib/dbm/gnu.pyi +++ b/mypy/typeshed/stdlib/dbm/gnu.pyi @@ -2,11 +2,12 @@ import sys from _typeshed import Self from types import TracebackType from typing import TypeVar, overload +from typing_extensions import TypeAlias if sys.platform != "win32": _T = TypeVar("_T") - _KeyType = str | bytes - _ValueType = str | bytes + _KeyType: TypeAlias = str | bytes + _ValueType: TypeAlias = str | bytes open_flags: str diff --git a/mypy/typeshed/stdlib/dbm/ndbm.pyi b/mypy/typeshed/stdlib/dbm/ndbm.pyi index 8405bec2bcf21..f1032bf3cae77 100644 --- a/mypy/typeshed/stdlib/dbm/ndbm.pyi +++ b/mypy/typeshed/stdlib/dbm/ndbm.pyi @@ -2,11 +2,12 @@ import sys from _typeshed import Self from types import TracebackType from typing import TypeVar, overload +from typing_extensions import TypeAlias if sys.platform != "win32": _T = TypeVar("_T") - _KeyType = str | bytes - _ValueType = str | bytes + _KeyType: TypeAlias = str | bytes + _ValueType: TypeAlias = str | bytes class error(OSError): ... library: str diff --git a/mypy/typeshed/stdlib/decimal.pyi b/mypy/typeshed/stdlib/decimal.pyi index 819ed1641448c..35fc4405f11b5 100644 --- a/mypy/typeshed/stdlib/decimal.pyi +++ b/mypy/typeshed/stdlib/decimal.pyi @@ -1,262 +1,2 @@ -import numbers -import sys -from _typeshed import Self -from types import TracebackType -from typing import Any, Container, NamedTuple, Sequence, Union, overload - -_Decimal = Decimal | int -_DecimalNew = Union[Decimal, float, str, tuple[int, Sequence[int], int]] -_ComparableNum = Decimal | float | numbers.Rational - -__libmpdec_version__: str - -class DecimalTuple(NamedTuple): - sign: int - digits: tuple[int, ...] - exponent: int - -ROUND_DOWN: str -ROUND_HALF_UP: str -ROUND_HALF_EVEN: str -ROUND_CEILING: str -ROUND_FLOOR: str -ROUND_UP: str -ROUND_HALF_DOWN: str -ROUND_05UP: str - -if sys.version_info >= (3, 7): - HAVE_CONTEXTVAR: bool -HAVE_THREADS: bool -MAX_EMAX: int -MAX_PREC: int -MIN_EMIN: int -MIN_ETINY: int - -class DecimalException(ArithmeticError): ... -class Clamped(DecimalException): ... -class InvalidOperation(DecimalException): ... -class ConversionSyntax(InvalidOperation): ... -class DivisionByZero(DecimalException, ZeroDivisionError): ... -class DivisionImpossible(InvalidOperation): ... -class DivisionUndefined(InvalidOperation, ZeroDivisionError): ... -class Inexact(DecimalException): ... -class InvalidContext(InvalidOperation): ... -class Rounded(DecimalException): ... -class Subnormal(DecimalException): ... -class Overflow(Inexact, Rounded): ... -class Underflow(Inexact, Rounded, Subnormal): ... -class FloatOperation(DecimalException, TypeError): ... - -def setcontext(__context: Context) -> None: ... -def getcontext() -> Context: ... -def localcontext(ctx: Context | None = ...) -> _ContextManager: ... - -class Decimal: - def __new__(cls: type[Self], value: _DecimalNew = ..., context: Context | None = ...) -> Self: ... - @classmethod - def from_float(cls: type[Self], __f: float) -> Self: ... - def __bool__(self) -> bool: ... - def compare(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... - def __hash__(self) -> int: ... - def as_tuple(self) -> DecimalTuple: ... - def as_integer_ratio(self) -> tuple[int, int]: ... - def to_eng_string(self, context: Context | None = ...) -> str: ... - def __abs__(self) -> Decimal: ... - def __add__(self, __other: _Decimal) -> Decimal: ... - def __divmod__(self, __other: _Decimal) -> tuple[Decimal, Decimal]: ... - def __eq__(self, __other: object) -> bool: ... - def __floordiv__(self, __other: _Decimal) -> Decimal: ... - def __ge__(self, __other: _ComparableNum) -> bool: ... - def __gt__(self, __other: _ComparableNum) -> bool: ... - def __le__(self, __other: _ComparableNum) -> bool: ... - def __lt__(self, __other: _ComparableNum) -> bool: ... - def __mod__(self, __other: _Decimal) -> Decimal: ... - def __mul__(self, __other: _Decimal) -> Decimal: ... - def __neg__(self) -> Decimal: ... - def __pos__(self) -> Decimal: ... - def __pow__(self, __other: _Decimal, __modulo: _Decimal | None = ...) -> Decimal: ... - def __radd__(self, __other: _Decimal) -> Decimal: ... - def __rdivmod__(self, __other: _Decimal) -> tuple[Decimal, Decimal]: ... - def __rfloordiv__(self, __other: _Decimal) -> Decimal: ... - def __rmod__(self, __other: _Decimal) -> Decimal: ... - def __rmul__(self, __other: _Decimal) -> Decimal: ... - def __rsub__(self, __other: _Decimal) -> Decimal: ... - def __rtruediv__(self, __other: _Decimal) -> Decimal: ... - def __sub__(self, __other: _Decimal) -> Decimal: ... - def __truediv__(self, __other: _Decimal) -> Decimal: ... - def remainder_near(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... - def __float__(self) -> float: ... - def __int__(self) -> int: ... - def __trunc__(self) -> int: ... - @property - def real(self) -> Decimal: ... - @property - def imag(self) -> Decimal: ... - def conjugate(self) -> Decimal: ... - def __complex__(self) -> complex: ... - @overload - def __round__(self) -> int: ... - @overload - def __round__(self, __ndigits: int) -> Decimal: ... - def __floor__(self) -> int: ... - def __ceil__(self) -> int: ... - def fma(self, other: _Decimal, third: _Decimal, context: Context | None = ...) -> Decimal: ... - def __rpow__(self, __other: _Decimal, __context: Context | None = ...) -> Decimal: ... - def normalize(self, context: Context | None = ...) -> Decimal: ... - def quantize(self, exp: _Decimal, rounding: str | None = ..., context: Context | None = ...) -> Decimal: ... - def same_quantum(self, other: _Decimal, context: Context | None = ...) -> bool: ... - def to_integral_exact(self, rounding: str | None = ..., context: Context | None = ...) -> Decimal: ... - def to_integral_value(self, rounding: str | None = ..., context: Context | None = ...) -> Decimal: ... - def to_integral(self, rounding: str | None = ..., context: Context | None = ...) -> Decimal: ... - def sqrt(self, context: Context | None = ...) -> Decimal: ... - def max(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... - def min(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... - def adjusted(self) -> int: ... - def canonical(self) -> Decimal: ... - def compare_signal(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... - def compare_total(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... - def compare_total_mag(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... - def copy_abs(self) -> Decimal: ... - def copy_negate(self) -> Decimal: ... - def copy_sign(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... - def exp(self, context: Context | None = ...) -> Decimal: ... - def is_canonical(self) -> bool: ... - def is_finite(self) -> bool: ... - def is_infinite(self) -> bool: ... - def is_nan(self) -> bool: ... - def is_normal(self, context: Context | None = ...) -> bool: ... - def is_qnan(self) -> bool: ... - def is_signed(self) -> bool: ... - def is_snan(self) -> bool: ... - def is_subnormal(self, context: Context | None = ...) -> bool: ... - def is_zero(self) -> bool: ... - def ln(self, context: Context | None = ...) -> Decimal: ... - def log10(self, context: Context | None = ...) -> Decimal: ... - def logb(self, context: Context | None = ...) -> Decimal: ... - def logical_and(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... - def logical_invert(self, context: Context | None = ...) -> Decimal: ... - def logical_or(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... - def logical_xor(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... - def max_mag(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... - def min_mag(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... - def next_minus(self, context: Context | None = ...) -> Decimal: ... - def next_plus(self, context: Context | None = ...) -> Decimal: ... - def next_toward(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... - def number_class(self, context: Context | None = ...) -> str: ... - def radix(self) -> Decimal: ... - def rotate(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... - def scaleb(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... - def shift(self, other: _Decimal, context: Context | None = ...) -> Decimal: ... - def __reduce__(self: Self) -> tuple[type[Self], tuple[str]]: ... - def __copy__(self: Self) -> Self: ... - def __deepcopy__(self: Self, __memo: Any) -> Self: ... - def __format__(self, __specifier: str, __context: Context | None = ...) -> str: ... - -class _ContextManager: - new_context: Context - saved_context: Context - def __init__(self, new_context: Context) -> None: ... - def __enter__(self) -> Context: ... - def __exit__(self, t: type[BaseException] | None, v: BaseException | None, tb: TracebackType | None) -> None: ... - -_TrapType = type[DecimalException] - -class Context: - prec: int - rounding: str - Emin: int - Emax: int - capitals: int - clamp: int - traps: dict[_TrapType, bool] - flags: dict[_TrapType, bool] - def __init__( - self, - prec: int | None = ..., - rounding: str | None = ..., - Emin: int | None = ..., - Emax: int | None = ..., - capitals: int | None = ..., - clamp: int | None = ..., - flags: None | dict[_TrapType, bool] | Container[_TrapType] = ..., - traps: None | dict[_TrapType, bool] | Container[_TrapType] = ..., - _ignored_flags: list[_TrapType] | None = ..., - ) -> None: ... - # __setattr__() only allows to set a specific set of attributes, - # already defined above. - def __delattr__(self, __name: str) -> None: ... - def __reduce__(self: Self) -> tuple[type[Self], tuple[Any, ...]]: ... - def clear_flags(self) -> None: ... - def clear_traps(self) -> None: ... - def copy(self) -> Context: ... - def __copy__(self) -> Context: ... - __hash__: Any - def Etiny(self) -> int: ... - def Etop(self) -> int: ... - def create_decimal(self, __num: _DecimalNew = ...) -> Decimal: ... - def create_decimal_from_float(self, __f: float) -> Decimal: ... - def abs(self, __x: _Decimal) -> Decimal: ... - def add(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... - def canonical(self, __x: Decimal) -> Decimal: ... - def compare(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... - def compare_signal(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... - def compare_total(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... - def compare_total_mag(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... - def copy_abs(self, __x: _Decimal) -> Decimal: ... - def copy_decimal(self, __x: _Decimal) -> Decimal: ... - def copy_negate(self, __x: _Decimal) -> Decimal: ... - def copy_sign(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... - def divide(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... - def divide_int(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... - def divmod(self, __x: _Decimal, __y: _Decimal) -> tuple[Decimal, Decimal]: ... - def exp(self, __x: _Decimal) -> Decimal: ... - def fma(self, __x: _Decimal, __y: _Decimal, __z: _Decimal) -> Decimal: ... - def is_canonical(self, __x: _Decimal) -> bool: ... - def is_finite(self, __x: _Decimal) -> bool: ... - def is_infinite(self, __x: _Decimal) -> bool: ... - def is_nan(self, __x: _Decimal) -> bool: ... - def is_normal(self, __x: _Decimal) -> bool: ... - def is_qnan(self, __x: _Decimal) -> bool: ... - def is_signed(self, __x: _Decimal) -> bool: ... - def is_snan(self, __x: _Decimal) -> bool: ... - def is_subnormal(self, __x: _Decimal) -> bool: ... - def is_zero(self, __x: _Decimal) -> bool: ... - def ln(self, __x: _Decimal) -> Decimal: ... - def log10(self, __x: _Decimal) -> Decimal: ... - def logb(self, __x: _Decimal) -> Decimal: ... - def logical_and(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... - def logical_invert(self, __x: _Decimal) -> Decimal: ... - def logical_or(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... - def logical_xor(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... - def max(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... - def max_mag(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... - def min(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... - def min_mag(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... - def minus(self, __x: _Decimal) -> Decimal: ... - def multiply(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... - def next_minus(self, __x: _Decimal) -> Decimal: ... - def next_plus(self, __x: _Decimal) -> Decimal: ... - def next_toward(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... - def normalize(self, __x: _Decimal) -> Decimal: ... - def number_class(self, __x: _Decimal) -> str: ... - def plus(self, __x: _Decimal) -> Decimal: ... - def power(self, a: _Decimal, b: _Decimal, modulo: _Decimal | None = ...) -> Decimal: ... - def quantize(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... - def radix(self) -> Decimal: ... - def remainder(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... - def remainder_near(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... - def rotate(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... - def same_quantum(self, __x: _Decimal, __y: _Decimal) -> bool: ... - def scaleb(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... - def shift(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... - def sqrt(self, __x: _Decimal) -> Decimal: ... - def subtract(self, __x: _Decimal, __y: _Decimal) -> Decimal: ... - def to_eng_string(self, __x: _Decimal) -> str: ... - def to_sci_string(self, __x: _Decimal) -> str: ... - def to_integral_exact(self, __x: _Decimal) -> Decimal: ... - def to_integral_value(self, __x: _Decimal) -> Decimal: ... - def to_integral(self, __x: _Decimal) -> Decimal: ... - -DefaultContext: Context -BasicContext: Context -ExtendedContext: Context +from _decimal import * +from _decimal import __libmpdec_version__ as __libmpdec_version__, __version__ as __version__ diff --git a/mypy/typeshed/stdlib/difflib.pyi b/mypy/typeshed/stdlib/difflib.pyi index a572430155e94..87e3768034bf3 100644 --- a/mypy/typeshed/stdlib/difflib.pyi +++ b/mypy/typeshed/stdlib/difflib.pyi @@ -1,5 +1,6 @@ import sys -from typing import Any, AnyStr, Callable, Generic, Iterable, Iterator, NamedTuple, Sequence, TypeVar, overload +from collections.abc import Callable, Iterable, Iterator, Sequence +from typing import Any, AnyStr, Generic, NamedTuple, TypeVar, overload if sys.version_info >= (3, 9): from types import GenericAlias diff --git a/mypy/typeshed/stdlib/dis.pyi b/mypy/typeshed/stdlib/dis.pyi index 910458c08e005..9a99d44986688 100644 --- a/mypy/typeshed/stdlib/dis.pyi +++ b/mypy/typeshed/stdlib/dis.pyi @@ -1,8 +1,10 @@ import sys import types from _typeshed import Self +from collections.abc import Callable, Iterator from opcode import * # `dis` re-exports it as a part of public API -from typing import IO, Any, Callable, Iterator, NamedTuple +from typing import IO, Any, NamedTuple +from typing_extensions import TypeAlias __all__ = [ "code_info", @@ -34,28 +36,63 @@ __all__ = [ # Strictly this should not have to include Callable, but mypy doesn't use FunctionType # for functions (python/mypy#3171) -_HaveCodeType = types.MethodType | types.FunctionType | types.CodeType | type | Callable[..., Any] -_HaveCodeOrStringType = _HaveCodeType | str | bytes +_HaveCodeType: TypeAlias = types.MethodType | types.FunctionType | types.CodeType | type | Callable[..., Any] +_HaveCodeOrStringType: TypeAlias = _HaveCodeType | str | bytes -class Instruction(NamedTuple): - opname: str - opcode: int - arg: int | None - argval: Any - argrepr: str - offset: int - starts_line: int | None - is_jump_target: bool +if sys.version_info >= (3, 11): + class Positions(NamedTuple): + lineno: int | None = ... + end_lineno: int | None = ... + col_offset: int | None = ... + end_col_offset: int | None = ... + +if sys.version_info >= (3, 11): + class Instruction(NamedTuple): + opname: str + opcode: int + arg: int | None + argval: Any + argrepr: str + offset: int + starts_line: int | None + is_jump_target: bool + positions: Positions | None = ... + +else: + class Instruction(NamedTuple): + opname: str + opcode: int + arg: int | None + argval: Any + argrepr: str + offset: int + starts_line: int | None + is_jump_target: bool class Bytecode: codeobj: types.CodeType first_line: int - def __init__(self, x: _HaveCodeOrStringType, *, first_line: int | None = ..., current_offset: int | None = ...) -> None: ... + if sys.version_info >= (3, 11): + def __init__( + self, + x: _HaveCodeOrStringType, + *, + first_line: int | None = ..., + current_offset: int | None = ..., + show_caches: bool = ..., + ) -> None: ... + @classmethod + def from_traceback(cls: type[Self], tb: types.TracebackType, *, show_caches: bool = ...) -> Self: ... + else: + def __init__( + self, x: _HaveCodeOrStringType, *, first_line: int | None = ..., current_offset: int | None = ... + ) -> None: ... + @classmethod + def from_traceback(cls: type[Self], tb: types.TracebackType) -> Self: ... + def __iter__(self) -> Iterator[Instruction]: ... def info(self) -> str: ... def dis(self) -> str: ... - @classmethod - def from_traceback(cls: type[Self], tb: types.TracebackType) -> Self: ... COMPILER_FLAG_NAMES: dict[int, str] @@ -64,14 +101,27 @@ def findlinestarts(code: _HaveCodeType) -> Iterator[tuple[int, int]]: ... def pretty_flags(flags: int) -> str: ... def code_info(x: _HaveCodeOrStringType) -> str: ... -if sys.version_info >= (3, 7): +if sys.version_info >= (3, 11): + def dis( + x: _HaveCodeOrStringType | None = ..., *, file: IO[str] | None = ..., depth: int | None = ..., show_caches: bool = ... + ) -> None: ... + +elif sys.version_info >= (3, 7): def dis(x: _HaveCodeOrStringType | None = ..., *, file: IO[str] | None = ..., depth: int | None = ...) -> None: ... else: def dis(x: _HaveCodeOrStringType | None = ..., *, file: IO[str] | None = ...) -> None: ... -def distb(tb: types.TracebackType | None = ..., *, file: IO[str] | None = ...) -> None: ... -def disassemble(co: _HaveCodeType, lasti: int = ..., *, file: IO[str] | None = ...) -> None: ... -def disco(co: _HaveCodeType, lasti: int = ..., *, file: IO[str] | None = ...) -> None: ... +if sys.version_info >= (3, 11): + def disassemble(co: _HaveCodeType, lasti: int = ..., *, file: IO[str] | None = ..., show_caches: bool = ...) -> None: ... + def disco(co: _HaveCodeType, lasti: int = ..., *, file: IO[str] | None = ..., show_caches: bool = ...) -> None: ... + def distb(tb: types.TracebackType | None = ..., *, file: IO[str] | None = ..., show_caches: bool = ...) -> None: ... + def get_instructions(x: _HaveCodeType, *, first_line: int | None = ..., show_caches: bool = ...) -> Iterator[Instruction]: ... + +else: + def disassemble(co: _HaveCodeType, lasti: int = ..., *, file: IO[str] | None = ...) -> None: ... + def disco(co: _HaveCodeType, lasti: int = ..., *, file: IO[str] | None = ...) -> None: ... + def distb(tb: types.TracebackType | None = ..., *, file: IO[str] | None = ...) -> None: ... + def get_instructions(x: _HaveCodeType, *, first_line: int | None = ...) -> Iterator[Instruction]: ... + def show_code(co: _HaveCodeType, *, file: IO[str] | None = ...) -> None: ... -def get_instructions(x: _HaveCodeType, *, first_line: int | None = ...) -> Iterator[Instruction]: ... diff --git a/mypy/typeshed/stdlib/distutils/ccompiler.pyi b/mypy/typeshed/stdlib/distutils/ccompiler.pyi index 4cdc62ce3bae4..ed823f7c070ff 100644 --- a/mypy/typeshed/stdlib/distutils/ccompiler.pyi +++ b/mypy/typeshed/stdlib/distutils/ccompiler.pyi @@ -1,6 +1,8 @@ -from typing import Any, Callable, Union +from collections.abc import Callable +from typing import Any, Union +from typing_extensions import TypeAlias -_Macro = Union[tuple[str], tuple[str, str | None]] +_Macro: TypeAlias = Union[tuple[str], tuple[str, str | None]] def gen_lib_options( compiler: CCompiler, library_dirs: list[str], runtime_library_dirs: list[str], libraries: list[str] diff --git a/mypy/typeshed/stdlib/distutils/cmd.pyi b/mypy/typeshed/stdlib/distutils/cmd.pyi index 96a048c93f41a..8163ae78fd8ff 100644 --- a/mypy/typeshed/stdlib/distutils/cmd.pyi +++ b/mypy/typeshed/stdlib/distutils/cmd.pyi @@ -1,6 +1,7 @@ from abc import abstractmethod +from collections.abc import Callable, Iterable from distutils.dist import Distribution -from typing import Any, Callable, Iterable +from typing import Any class Command: sub_commands: list[tuple[str, Callable[[Command], bool] | None]] diff --git a/mypy/typeshed/stdlib/distutils/core.pyi b/mypy/typeshed/stdlib/distutils/core.pyi index 6564c9a86ded8..199a4d70a9534 100644 --- a/mypy/typeshed/stdlib/distutils/core.pyi +++ b/mypy/typeshed/stdlib/distutils/core.pyi @@ -1,7 +1,8 @@ +from collections.abc import Mapping from distutils.cmd import Command as Command from distutils.dist import Distribution as Distribution from distutils.extension import Extension as Extension -from typing import Any, Mapping +from typing import Any def setup( *, diff --git a/mypy/typeshed/stdlib/distutils/dist.pyi b/mypy/typeshed/stdlib/distutils/dist.pyi index c5b3afe7cc3bd..ef47e4e4d15a7 100644 --- a/mypy/typeshed/stdlib/distutils/dist.pyi +++ b/mypy/typeshed/stdlib/distutils/dist.pyi @@ -1,6 +1,7 @@ from _typeshed import StrOrBytesPath, SupportsWrite +from collections.abc import Iterable, Mapping from distutils.cmd import Command -from typing import IO, Any, Iterable, Mapping +from typing import IO, Any class DistributionMetadata: def __init__(self, path: int | StrOrBytesPath | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/distutils/fancy_getopt.pyi b/mypy/typeshed/stdlib/distutils/fancy_getopt.pyi index c2a5bd4c20a14..6a7124bd15ade 100644 --- a/mypy/typeshed/stdlib/distutils/fancy_getopt.pyi +++ b/mypy/typeshed/stdlib/distutils/fancy_getopt.pyi @@ -1,7 +1,9 @@ -from typing import Any, Iterable, Mapping, overload +from collections.abc import Iterable, Mapping +from typing import Any, overload +from typing_extensions import TypeAlias -_Option = tuple[str, str | None, str] -_GR = tuple[list[str], OptionDummy] +_Option: TypeAlias = tuple[str, str | None, str] +_GR: TypeAlias = tuple[list[str], OptionDummy] def fancy_getopt( options: list[_Option], negative_opt: Mapping[_Option, _Option], object: Any, args: list[str] | None diff --git a/mypy/typeshed/stdlib/distutils/file_util.pyi b/mypy/typeshed/stdlib/distutils/file_util.pyi index a7f24105a6788..b3127841bce8e 100644 --- a/mypy/typeshed/stdlib/distutils/file_util.pyi +++ b/mypy/typeshed/stdlib/distutils/file_util.pyi @@ -1,4 +1,4 @@ -from typing import Sequence +from collections.abc import Sequence def copy_file( src: str, diff --git a/mypy/typeshed/stdlib/distutils/filelist.pyi b/mypy/typeshed/stdlib/distutils/filelist.pyi index 2b436938f13ee..361cb13f0c478 100644 --- a/mypy/typeshed/stdlib/distutils/filelist.pyi +++ b/mypy/typeshed/stdlib/distutils/filelist.pyi @@ -1,4 +1,5 @@ -from typing import Iterable, Pattern, overload +from collections.abc import Iterable +from typing import Pattern, overload from typing_extensions import Literal # class is entirely undocumented diff --git a/mypy/typeshed/stdlib/distutils/sysconfig.pyi b/mypy/typeshed/stdlib/distutils/sysconfig.pyi index 3f579be40882e..bf7db9c8f06b0 100644 --- a/mypy/typeshed/stdlib/distutils/sysconfig.pyi +++ b/mypy/typeshed/stdlib/distutils/sysconfig.pyi @@ -1,5 +1,5 @@ +from collections.abc import Mapping from distutils.ccompiler import CCompiler -from typing import Mapping PREFIX: str EXEC_PREFIX: str diff --git a/mypy/typeshed/stdlib/doctest.pyi b/mypy/typeshed/stdlib/doctest.pyi index 651e1b298aafe..c767436c2be82 100644 --- a/mypy/typeshed/stdlib/doctest.pyi +++ b/mypy/typeshed/stdlib/doctest.pyi @@ -1,6 +1,9 @@ import types import unittest -from typing import Any, Callable, NamedTuple +from _typeshed import ExcInfo +from collections.abc import Callable +from typing import Any, NamedTuple +from typing_extensions import TypeAlias __all__ = [ "register_optionflag", @@ -123,8 +126,7 @@ class DocTestFinder: extraglobs: dict[str, Any] | None = ..., ) -> list[DocTest]: ... -_Out = Callable[[str], Any] -_ExcInfo = tuple[type[BaseException], BaseException, types.TracebackType] +_Out: TypeAlias = Callable[[str], Any] class DocTestRunner: DIVIDER: str @@ -137,7 +139,7 @@ class DocTestRunner: def report_start(self, out: _Out, test: DocTest, example: Example) -> None: ... def report_success(self, out: _Out, test: DocTest, example: Example, got: str) -> None: ... def report_failure(self, out: _Out, test: DocTest, example: Example, got: str) -> None: ... - def report_unexpected_exception(self, out: _Out, test: DocTest, example: Example, exc_info: _ExcInfo) -> None: ... + def report_unexpected_exception(self, out: _Out, test: DocTest, example: Example, exc_info: ExcInfo) -> None: ... def run( self, test: DocTest, compileflags: int | None = ..., out: _Out | None = ..., clear_globs: bool = ... ) -> TestResults: ... @@ -157,8 +159,8 @@ class DocTestFailure(Exception): class UnexpectedException(Exception): test: DocTest example: Example - exc_info: _ExcInfo - def __init__(self, test: DocTest, example: Example, exc_info: _ExcInfo) -> None: ... + exc_info: ExcInfo + def __init__(self, test: DocTest, example: Example, exc_info: ExcInfo) -> None: ... class DebugRunner(DocTestRunner): ... diff --git a/mypy/typeshed/stdlib/email/__init__.pyi b/mypy/typeshed/stdlib/email/__init__.pyi index 49e18ccb8c2ef..78368a2cf4a0c 100644 --- a/mypy/typeshed/stdlib/email/__init__.pyi +++ b/mypy/typeshed/stdlib/email/__init__.pyi @@ -1,11 +1,12 @@ +from collections.abc import Callable from email.message import Message from email.policy import Policy -from typing import IO, Callable, TypeVar, Union +from typing import IO, Union +from typing_extensions import TypeAlias # Definitions imported by multiple submodules in typeshed -_MessageT = TypeVar("_MessageT", bound=Message) # noqa: Y018 -_ParamType = Union[str, tuple[str | None, str | None, str]] -_ParamsType = Union[str, None, tuple[str, str | None, str]] +_ParamType: TypeAlias = Union[str, tuple[str | None, str | None, str]] +_ParamsType: TypeAlias = Union[str, None, tuple[str, str | None, str]] def message_from_string(s: str, _class: Callable[[], Message] = ..., *, policy: Policy = ...) -> Message: ... def message_from_bytes(s: bytes, _class: Callable[[], Message] = ..., *, policy: Policy = ...) -> Message: ... diff --git a/mypy/typeshed/stdlib/email/_header_value_parser.pyi b/mypy/typeshed/stdlib/email/_header_value_parser.pyi index 749b6454a8f8a..abe6ec63abb13 100644 --- a/mypy/typeshed/stdlib/email/_header_value_parser.pyi +++ b/mypy/typeshed/stdlib/email/_header_value_parser.pyi @@ -1,8 +1,9 @@ import sys from _typeshed import Self +from collections.abc import Iterable, Iterator from email.errors import HeaderParseError, MessageDefect from email.policy import Policy -from typing import Any, Iterable, Iterator, Pattern +from typing import Any, Pattern from typing_extensions import Final WSP: Final[set[str]] diff --git a/mypy/typeshed/stdlib/email/charset.pyi b/mypy/typeshed/stdlib/email/charset.pyi index fd3de9ceace27..236908537f83c 100644 --- a/mypy/typeshed/stdlib/email/charset.pyi +++ b/mypy/typeshed/stdlib/email/charset.pyi @@ -1,4 +1,4 @@ -from typing import Iterator +from collections.abc import Iterator __all__ = ["Charset", "add_alias", "add_charset", "add_codec"] diff --git a/mypy/typeshed/stdlib/email/contentmanager.pyi b/mypy/typeshed/stdlib/email/contentmanager.pyi index 68fe99c8c09f9..3ac665eaa7bff 100644 --- a/mypy/typeshed/stdlib/email/contentmanager.pyi +++ b/mypy/typeshed/stdlib/email/contentmanager.pyi @@ -1,5 +1,6 @@ +from collections.abc import Callable from email.message import Message -from typing import Any, Callable +from typing import Any class ContentManager: def __init__(self) -> None: ... diff --git a/mypy/typeshed/stdlib/email/feedparser.pyi b/mypy/typeshed/stdlib/email/feedparser.pyi index b1c7e0f7d1276..c535c353daade 100644 --- a/mypy/typeshed/stdlib/email/feedparser.pyi +++ b/mypy/typeshed/stdlib/email/feedparser.pyi @@ -1,10 +1,12 @@ -from email import _MessageT +from collections.abc import Callable from email.message import Message from email.policy import Policy -from typing import Callable, Generic, overload +from typing import Generic, TypeVar, overload __all__ = ["FeedParser", "BytesFeedParser"] +_MessageT = TypeVar("_MessageT", bound=Message) + class FeedParser(Generic[_MessageT]): @overload def __init__(self: FeedParser[Message], _factory: None = ..., *, policy: Policy = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/email/iterators.pyi b/mypy/typeshed/stdlib/email/iterators.pyi index ad5517712d256..29068819ac158 100644 --- a/mypy/typeshed/stdlib/email/iterators.pyi +++ b/mypy/typeshed/stdlib/email/iterators.pyi @@ -1,6 +1,6 @@ from _typeshed import SupportsWrite +from collections.abc import Iterator from email.message import Message -from typing import Iterator __all__ = ["body_line_iterator", "typed_subpart_iterator", "walk"] diff --git a/mypy/typeshed/stdlib/email/message.pyi b/mypy/typeshed/stdlib/email/message.pyi index 97de1cf5daf63..6544f8fc23859 100644 --- a/mypy/typeshed/stdlib/email/message.pyi +++ b/mypy/typeshed/stdlib/email/message.pyi @@ -1,17 +1,19 @@ +from collections.abc import Generator, Iterator, Sequence from email import _ParamsType, _ParamType from email.charset import Charset from email.contentmanager import ContentManager from email.errors import MessageDefect from email.policy import Policy -from typing import Any, Generator, Iterator, Sequence, TypeVar +from typing import Any, TypeVar +from typing_extensions import TypeAlias __all__ = ["Message", "EmailMessage"] _T = TypeVar("_T") -_PayloadType = list[Message] | str | bytes -_CharsetType = Charset | str | None -_HeaderType = Any +_PayloadType: TypeAlias = list[Message] | str | bytes +_CharsetType: TypeAlias = Charset | str | None +_HeaderType: TypeAlias = Any class Message: policy: Policy # undocumented diff --git a/mypy/typeshed/stdlib/email/parser.pyi b/mypy/typeshed/stdlib/email/parser.pyi index 1846bdcc36b2b..dcd346c1b46d9 100644 --- a/mypy/typeshed/stdlib/email/parser.pyi +++ b/mypy/typeshed/stdlib/email/parser.pyi @@ -1,14 +1,11 @@ -import email.feedparser -from email import _MessageT +from collections.abc import Callable +from email.feedparser import BytesFeedParser as BytesFeedParser, FeedParser as FeedParser from email.message import Message from email.policy import Policy -from typing import BinaryIO, Callable, TextIO +from typing import BinaryIO, TextIO __all__ = ["Parser", "HeaderParser", "BytesParser", "BytesHeaderParser", "FeedParser", "BytesFeedParser"] -FeedParser = email.feedparser.FeedParser[_MessageT] -BytesFeedParser = email.feedparser.BytesFeedParser[_MessageT] - class Parser: def __init__(self, _class: Callable[[], Message] | None = ..., *, policy: Policy = ...) -> None: ... def parse(self, fp: TextIO, headersonly: bool = ...) -> Message: ... diff --git a/mypy/typeshed/stdlib/email/policy.pyi b/mypy/typeshed/stdlib/email/policy.pyi index d4ebb1fd5e371..4df3c1e48b07c 100644 --- a/mypy/typeshed/stdlib/email/policy.pyi +++ b/mypy/typeshed/stdlib/email/policy.pyi @@ -1,9 +1,10 @@ from abc import ABCMeta, abstractmethod +from collections.abc import Callable from email.contentmanager import ContentManager from email.errors import MessageDefect from email.header import Header from email.message import Message -from typing import Any, Callable +from typing import Any __all__ = ["Compat32", "compat32", "Policy", "EmailPolicy", "default", "strict", "SMTP", "HTTP"] diff --git a/mypy/typeshed/stdlib/email/utils.pyi b/mypy/typeshed/stdlib/email/utils.pyi index aeffb0ef19817..480c5f79549d9 100644 --- a/mypy/typeshed/stdlib/email/utils.pyi +++ b/mypy/typeshed/stdlib/email/utils.pyi @@ -3,6 +3,7 @@ import sys from email import _ParamType from email.charset import Charset from typing import overload +from typing_extensions import TypeAlias __all__ = [ "collapse_rfc2231_value", @@ -22,7 +23,7 @@ __all__ = [ "unquote", ] -_PDTZ = tuple[int, int, int, int, int, int, int, int, int, int | None] +_PDTZ: TypeAlias = tuple[int, int, int, int, int, int, int, int, int, int | None] def quote(str: str) -> str: ... def unquote(str: str) -> str: ... diff --git a/mypy/typeshed/stdlib/enum.pyi b/mypy/typeshed/stdlib/enum.pyi index f49bcd7a00e01..a7c84c5b1c0d4 100644 --- a/mypy/typeshed/stdlib/enum.pyi +++ b/mypy/typeshed/stdlib/enum.pyi @@ -5,7 +5,7 @@ from abc import ABCMeta from builtins import property as _builtins_property from collections.abc import Iterable, Iterator, Mapping from typing import Any, TypeVar, overload -from typing_extensions import Literal +from typing_extensions import Literal, TypeAlias if sys.version_info >= (3, 11): __all__ = [ @@ -52,7 +52,7 @@ _EnumerationT = TypeVar("_EnumerationT", bound=type[Enum]) # # >>> Enum('Foo', names={'RED': 1, 'YELLOW': 2}) # -_EnumNames = str | Iterable[str] | Iterable[Iterable[str | Any]] | Mapping[str, Any] +_EnumNames: TypeAlias = str | Iterable[str] | Iterable[Iterable[str | Any]] | Mapping[str, Any] class _EnumDict(dict[str, Any]): def __init__(self) -> None: ... diff --git a/mypy/typeshed/stdlib/errno.pyi b/mypy/typeshed/stdlib/errno.pyi index 12410af23e714..9ef1fe6e76182 100644 --- a/mypy/typeshed/stdlib/errno.pyi +++ b/mypy/typeshed/stdlib/errno.pyi @@ -1,4 +1,4 @@ -from typing import Mapping +from collections.abc import Mapping errorcode: Mapping[int, str] diff --git a/mypy/typeshed/stdlib/filecmp.pyi b/mypy/typeshed/stdlib/filecmp.pyi index 7c606af407918..a6747dd504a33 100644 --- a/mypy/typeshed/stdlib/filecmp.pyi +++ b/mypy/typeshed/stdlib/filecmp.pyi @@ -1,7 +1,8 @@ import sys from _typeshed import StrOrBytesPath +from collections.abc import Callable, Iterable, Sequence from os import PathLike -from typing import Any, AnyStr, Callable, Generic, Iterable, Sequence +from typing import Any, AnyStr, Generic from typing_extensions import Literal if sys.version_info >= (3, 9): diff --git a/mypy/typeshed/stdlib/fileinput.pyi b/mypy/typeshed/stdlib/fileinput.pyi index a3b62948ca205..0ef8c14ddaac1 100644 --- a/mypy/typeshed/stdlib/fileinput.pyi +++ b/mypy/typeshed/stdlib/fileinput.pyi @@ -1,7 +1,8 @@ import sys from _typeshed import Self, StrOrBytesPath +from collections.abc import Callable, Iterable, Iterator from types import TracebackType -from typing import IO, Any, AnyStr, Callable, Generic, Iterable, Iterator +from typing import IO, Any, AnyStr, Generic __all__ = [ "input", diff --git a/mypy/typeshed/stdlib/fnmatch.pyi b/mypy/typeshed/stdlib/fnmatch.pyi index 8351fce59ebb4..7051c999c4305 100644 --- a/mypy/typeshed/stdlib/fnmatch.pyi +++ b/mypy/typeshed/stdlib/fnmatch.pyi @@ -1,4 +1,5 @@ -from typing import AnyStr, Iterable +from collections.abc import Iterable +from typing import AnyStr __all__ = ["filter", "fnmatch", "fnmatchcase", "translate"] diff --git a/mypy/typeshed/stdlib/formatter.pyi b/mypy/typeshed/stdlib/formatter.pyi index f5d8348d08a1d..0aac0a5f918cc 100644 --- a/mypy/typeshed/stdlib/formatter.pyi +++ b/mypy/typeshed/stdlib/formatter.pyi @@ -1,8 +1,10 @@ -from typing import IO, Any, Iterable +from collections.abc import Iterable +from typing import IO, Any +from typing_extensions import TypeAlias AS_IS: None -_FontType = tuple[str, bool, bool, bool] -_StylesType = tuple[Any, ...] +_FontType: TypeAlias = tuple[str, bool, bool, bool] +_StylesType: TypeAlias = tuple[Any, ...] class NullFormatter: writer: NullWriter | None diff --git a/mypy/typeshed/stdlib/fractions.pyi b/mypy/typeshed/stdlib/fractions.pyi index 00989fb1fc029..0d787a011f5b1 100644 --- a/mypy/typeshed/stdlib/fractions.pyi +++ b/mypy/typeshed/stdlib/fractions.pyi @@ -3,9 +3,9 @@ from _typeshed import Self from decimal import Decimal from numbers import Integral, Rational, Real from typing import Any, overload -from typing_extensions import Literal +from typing_extensions import Literal, TypeAlias -_ComparableNum = int | float | Decimal | Real +_ComparableNum: TypeAlias = int | float | Decimal | Real if sys.version_info >= (3, 9): __all__ = ["Fraction"] diff --git a/mypy/typeshed/stdlib/ftplib.pyi b/mypy/typeshed/stdlib/ftplib.pyi index 4a5dad0dd14ff..925ad5884700d 100644 --- a/mypy/typeshed/stdlib/ftplib.pyi +++ b/mypy/typeshed/stdlib/ftplib.pyi @@ -1,9 +1,10 @@ import sys from _typeshed import Self, SupportsRead, SupportsReadline +from collections.abc import Callable, Iterable, Iterator from socket import socket from ssl import SSLContext from types import TracebackType -from typing import Any, Callable, Iterable, Iterator, TextIO +from typing import Any, TextIO from typing_extensions import Literal __all__ = ["FTP", "error_reply", "error_temp", "error_perm", "error_proto", "all_errors", "FTP_TLS"] diff --git a/mypy/typeshed/stdlib/functools.pyi b/mypy/typeshed/stdlib/functools.pyi index 741a53ed82a28..44feeed63f6ac 100644 --- a/mypy/typeshed/stdlib/functools.pyi +++ b/mypy/typeshed/stdlib/functools.pyi @@ -1,8 +1,9 @@ import sys import types from _typeshed import Self, SupportsAllComparisons, SupportsItems -from typing import Any, Callable, Generic, Hashable, Iterable, NamedTuple, Sequence, Sized, TypeVar, overload -from typing_extensions import Literal, final +from collections.abc import Callable, Hashable, Iterable, Sequence, Sized +from typing import Any, Generic, NamedTuple, TypeVar, overload +from typing_extensions import Literal, TypeAlias, final if sys.version_info >= (3, 9): from types import GenericAlias @@ -54,7 +55,7 @@ else: "singledispatch", ] -_AnyCallable = Callable[..., Any] +_AnyCallable: TypeAlias = Callable[..., Any] _T = TypeVar("_T") _S = TypeVar("_S") @@ -111,7 +112,7 @@ class partial(Generic[_T]): def __class_getitem__(cls, item: Any) -> GenericAlias: ... # With protocols, this could change into a generic protocol that defines __get__ and returns _T -_Descriptor = Any +_Descriptor: TypeAlias = Any class partialmethod(Generic[_T]): func: Callable[..., _T] | _Descriptor diff --git a/mypy/typeshed/stdlib/gc.pyi b/mypy/typeshed/stdlib/gc.pyi index 7c15e0f5b0a23..98b92e109f82e 100644 --- a/mypy/typeshed/stdlib/gc.pyi +++ b/mypy/typeshed/stdlib/gc.pyi @@ -1,6 +1,7 @@ import sys -from typing import Any, Callable -from typing_extensions import Literal +from collections.abc import Callable +from typing import Any +from typing_extensions import Literal, TypeAlias DEBUG_COLLECTABLE: Literal[2] DEBUG_LEAK: Literal[38] @@ -8,7 +9,7 @@ DEBUG_SAVEALL: Literal[32] DEBUG_STATS: Literal[1] DEBUG_UNCOLLECTABLE: Literal[4] -_CallbackType = Callable[[Literal["start", "stop"], dict[str, int]], object] +_CallbackType: TypeAlias = Callable[[Literal["start", "stop"], dict[str, int]], object] callbacks: list[_CallbackType] garbage: list[Any] diff --git a/mypy/typeshed/stdlib/genericpath.pyi b/mypy/typeshed/stdlib/genericpath.pyi index 3abedda262ea4..984d0c3cf51e5 100644 --- a/mypy/typeshed/stdlib/genericpath.pyi +++ b/mypy/typeshed/stdlib/genericpath.pyi @@ -1,6 +1,7 @@ import os from _typeshed import BytesPath, StrOrBytesPath, StrPath, SupportsRichComparisonT -from typing import Sequence, overload +from collections.abc import Sequence +from typing import overload from typing_extensions import Literal __all__ = [ diff --git a/mypy/typeshed/stdlib/gettext.pyi b/mypy/typeshed/stdlib/gettext.pyi index 1f3ef67ab0f34..d02dda5350b79 100644 --- a/mypy/typeshed/stdlib/gettext.pyi +++ b/mypy/typeshed/stdlib/gettext.pyi @@ -1,7 +1,8 @@ import sys from _typeshed import StrPath -from typing import IO, Any, Container, Iterable, Sequence, TypeVar, overload -from typing_extensions import Literal +from collections.abc import Container, Iterable, Sequence +from typing import Any, Protocol, TypeVar, overload +from typing_extensions import Final, Literal if sys.version_info >= (3, 11): __all__ = [ @@ -67,9 +68,14 @@ else: "ngettext", ] +class _TranslationsReader(Protocol): + def read(self) -> bytes: ... + # optional: + # name: str + class NullTranslations: - def __init__(self, fp: IO[str] | None = ...) -> None: ... - def _parse(self, fp: IO[str]) -> None: ... + def __init__(self, fp: _TranslationsReader | None = ...) -> None: ... + def _parse(self, fp: _TranslationsReader) -> None: ... def add_fallback(self, fallback: NullTranslations) -> None: ... def gettext(self, message: str) -> str: ... def lgettext(self, message: str) -> str: ... @@ -79,18 +85,18 @@ class NullTranslations: def pgettext(self, context: str, message: str) -> str: ... def npgettext(self, context: str, msgid1: str, msgid2: str, n: int) -> str: ... - def info(self) -> Any: ... - def charset(self) -> Any: ... + def info(self) -> dict[str, str]: ... + def charset(self) -> str | None: ... if sys.version_info < (3, 11): - def output_charset(self) -> Any: ... + def output_charset(self) -> str | None: ... def set_output_charset(self, charset: str) -> None: ... def install(self, names: Container[str] | None = ...) -> None: ... class GNUTranslations(NullTranslations): - LE_MAGIC: int - BE_MAGIC: int - CONTEXT: str + LE_MAGIC: Final[int] + BE_MAGIC: Final[int] + CONTEXT: Final[str] VERSIONS: Sequence[int] @overload # ignores incompatible overloads diff --git a/mypy/typeshed/stdlib/glob.pyi b/mypy/typeshed/stdlib/glob.pyi index ced0ceceb205a..c63563d19f580 100644 --- a/mypy/typeshed/stdlib/glob.pyi +++ b/mypy/typeshed/stdlib/glob.pyi @@ -1,6 +1,7 @@ import sys from _typeshed import StrOrBytesPath -from typing import AnyStr, Iterator +from collections.abc import Iterator +from typing import AnyStr __all__ = ["escape", "glob", "iglob"] diff --git a/mypy/typeshed/stdlib/graphlib.pyi b/mypy/typeshed/stdlib/graphlib.pyi index cae2a07e95c6b..2fca402bf9068 100644 --- a/mypy/typeshed/stdlib/graphlib.pyi +++ b/mypy/typeshed/stdlib/graphlib.pyi @@ -1,6 +1,7 @@ import sys from _typeshed import SupportsItems -from typing import Any, Generic, Iterable, TypeVar +from collections.abc import Iterable +from typing import Any, Generic, TypeVar __all__ = ["TopologicalSorter", "CycleError"] diff --git a/mypy/typeshed/stdlib/gzip.pyi b/mypy/typeshed/stdlib/gzip.pyi index 7347949ae865f..abf12925aea25 100644 --- a/mypy/typeshed/stdlib/gzip.pyi +++ b/mypy/typeshed/stdlib/gzip.pyi @@ -4,16 +4,16 @@ import zlib from _typeshed import ReadableBuffer, StrOrBytesPath from io import FileIO from typing import Any, Protocol, TextIO, overload -from typing_extensions import Literal +from typing_extensions import Literal, TypeAlias if sys.version_info >= (3, 8): __all__ = ["BadGzipFile", "GzipFile", "open", "compress", "decompress"] else: __all__ = ["GzipFile", "open", "compress", "decompress"] -_ReadBinaryMode = Literal["r", "rb"] -_WriteBinaryMode = Literal["a", "ab", "w", "wb", "x", "xb"] -_OpenTextMode = Literal["rt", "at", "wt", "xt"] +_ReadBinaryMode: TypeAlias = Literal["r", "rb"] +_WriteBinaryMode: TypeAlias = Literal["a", "ab", "w", "wb", "x", "xb"] +_OpenTextMode: TypeAlias = Literal["rt", "at", "wt", "xt"] READ: Literal[1] WRITE: Literal[2] diff --git a/mypy/typeshed/stdlib/hashlib.pyi b/mypy/typeshed/stdlib/hashlib.pyi index 4332153d281cc..2a417364b1711 100644 --- a/mypy/typeshed/stdlib/hashlib.pyi +++ b/mypy/typeshed/stdlib/hashlib.pyi @@ -1,28 +1,52 @@ import sys from _typeshed import ReadableBuffer, Self -from typing import AbstractSet +from collections.abc import Callable, Set as AbstractSet +from typing import Protocol from typing_extensions import final -__all__ = ( - "md5", - "sha1", - "sha224", - "sha256", - "sha384", - "sha512", - "blake2b", - "blake2s", - "sha3_224", - "sha3_256", - "sha3_384", - "sha3_512", - "shake_128", - "shake_256", - "new", - "algorithms_guaranteed", - "algorithms_available", - "pbkdf2_hmac", -) +if sys.version_info >= (3, 11): + __all__ = ( + "md5", + "sha1", + "sha224", + "sha256", + "sha384", + "sha512", + "blake2b", + "blake2s", + "sha3_224", + "sha3_256", + "sha3_384", + "sha3_512", + "shake_128", + "shake_256", + "new", + "algorithms_guaranteed", + "algorithms_available", + "pbkdf2_hmac", + "file_digest", + ) +else: + __all__ = ( + "md5", + "sha1", + "sha224", + "sha256", + "sha384", + "sha512", + "blake2b", + "blake2s", + "sha3_224", + "sha3_256", + "sha3_384", + "sha3_512", + "shake_128", + "shake_256", + "new", + "algorithms_guaranteed", + "algorithms_available", + "pbkdf2_hmac", + ) class _Hash: @property @@ -143,3 +167,15 @@ class _BlakeHash(_Hash): blake2b = _BlakeHash blake2s = _BlakeHash + +if sys.version_info >= (3, 11): + class _BytesIOLike(Protocol): + def getbuffer(self) -> ReadableBuffer: ... + + class _FileDigestFileObj(Protocol): + def readinto(self, __buf: bytearray) -> int: ... + def readable(self) -> bool: ... + + def file_digest( + __fileobj: _BytesIOLike | _FileDigestFileObj, __digest: str | Callable[[], _Hash], *, _bufsize: int = ... + ) -> _Hash: ... diff --git a/mypy/typeshed/stdlib/heapq.pyi b/mypy/typeshed/stdlib/heapq.pyi index a7a787d44e626..f07afc7af7061 100644 --- a/mypy/typeshed/stdlib/heapq.pyi +++ b/mypy/typeshed/stdlib/heapq.pyi @@ -1,6 +1,7 @@ from _heapq import * from _typeshed import SupportsRichComparison -from typing import Any, Callable, Iterable, TypeVar +from collections.abc import Callable, Iterable +from typing import Any, TypeVar __all__ = ["heappush", "heappop", "heapify", "heapreplace", "merge", "nlargest", "nsmallest", "heappushpop"] diff --git a/mypy/typeshed/stdlib/hmac.pyi b/mypy/typeshed/stdlib/hmac.pyi index 6d355147f51ef..858e46a71b681 100644 --- a/mypy/typeshed/stdlib/hmac.pyi +++ b/mypy/typeshed/stdlib/hmac.pyi @@ -1,11 +1,13 @@ import sys from _typeshed import ReadableBuffer +from collections.abc import Callable from types import ModuleType -from typing import Any, AnyStr, Callable, overload +from typing import Any, AnyStr, overload +from typing_extensions import TypeAlias # TODO more precise type for object of hashlib -_Hash = Any -_DigestMod = str | Callable[[], _Hash] | ModuleType +_Hash: TypeAlias = Any +_DigestMod: TypeAlias = str | Callable[[], _Hash] | ModuleType trans_5C: bytes trans_36: bytes diff --git a/mypy/typeshed/stdlib/http/client.pyi b/mypy/typeshed/stdlib/http/client.pyi index 801a195c9fb37..235b6d6b49516 100644 --- a/mypy/typeshed/stdlib/http/client.pyi +++ b/mypy/typeshed/stdlib/http/client.pyi @@ -4,8 +4,10 @@ import ssl import sys import types from _typeshed import Self, WriteableBuffer +from collections.abc import Callable, Iterable, Iterator, Mapping from socket import socket -from typing import IO, Any, BinaryIO, Callable, Iterable, Iterator, Mapping, Protocol, TypeVar, overload +from typing import IO, Any, BinaryIO, Protocol, TypeVar, overload +from typing_extensions import TypeAlias __all__ = [ "HTTPResponse", @@ -29,7 +31,7 @@ __all__ = [ "HTTPSConnection", ] -_DataType = bytes | IO[Any] | Iterable[bytes] | str +_DataType: TypeAlias = bytes | IO[Any] | Iterable[bytes] | str _T = TypeVar("_T") HTTP_PORT: int diff --git a/mypy/typeshed/stdlib/http/cookiejar.pyi b/mypy/typeshed/stdlib/http/cookiejar.pyi index 4fb1c38c6ab81..83da7faaf0fc3 100644 --- a/mypy/typeshed/stdlib/http/cookiejar.pyi +++ b/mypy/typeshed/stdlib/http/cookiejar.pyi @@ -1,7 +1,8 @@ import sys from _typeshed import StrPath +from collections.abc import Iterable, Iterator, Sequence from http.client import HTTPResponse -from typing import ClassVar, Iterable, Iterator, Pattern, Sequence, TypeVar, overload +from typing import ClassVar, Pattern, TypeVar, overload from urllib.request import Request __all__ = [ diff --git a/mypy/typeshed/stdlib/http/cookies.pyi b/mypy/typeshed/stdlib/http/cookies.pyi index 2cc05961a3034..e5aa2c1609db5 100644 --- a/mypy/typeshed/stdlib/http/cookies.pyi +++ b/mypy/typeshed/stdlib/http/cookies.pyi @@ -1,12 +1,14 @@ import sys -from typing import Any, Generic, Iterable, Mapping, TypeVar, overload +from collections.abc import Iterable, Mapping +from typing import Any, Generic, TypeVar, overload +from typing_extensions import TypeAlias if sys.version_info >= (3, 9): from types import GenericAlias __all__ = ["CookieError", "BaseCookie", "SimpleCookie"] -_DataType = str | Mapping[str, str | Morsel[Any]] +_DataType: TypeAlias = str | Mapping[str, str | Morsel[Any]] _T = TypeVar("_T") @overload diff --git a/mypy/typeshed/stdlib/http/server.pyi b/mypy/typeshed/stdlib/http/server.pyi index 53159b65ec14d..ad314cec15415 100644 --- a/mypy/typeshed/stdlib/http/server.pyi +++ b/mypy/typeshed/stdlib/http/server.pyi @@ -3,7 +3,8 @@ import io import socketserver import sys from _typeshed import StrPath, SupportsRead, SupportsWrite -from typing import Any, AnyStr, BinaryIO, ClassVar, Mapping, Sequence +from collections.abc import Mapping, Sequence +from typing import Any, AnyStr, BinaryIO, ClassVar if sys.version_info >= (3, 7): __all__ = ["HTTPServer", "ThreadingHTTPServer", "BaseHTTPRequestHandler", "SimpleHTTPRequestHandler", "CGIHTTPRequestHandler"] diff --git a/mypy/typeshed/stdlib/imaplib.pyi b/mypy/typeshed/stdlib/imaplib.pyi index ab6490cea570b..eef1c19577695 100644 --- a/mypy/typeshed/stdlib/imaplib.pyi +++ b/mypy/typeshed/stdlib/imaplib.pyi @@ -2,21 +2,21 @@ import subprocess import sys import time from _typeshed import Self +from builtins import list as _list # conflicts with a method named "list" +from collections.abc import Callable from socket import socket as _socket from ssl import SSLContext, SSLSocket from types import TracebackType -from typing import IO, Any, Callable, Pattern -from typing_extensions import Literal +from typing import IO, Any, Pattern +from typing_extensions import Literal, TypeAlias __all__ = ["IMAP4", "IMAP4_stream", "Internaldate2tuple", "Int2AP", "ParseFlags", "Time2Internaldate", "IMAP4_SSL"] # TODO: Commands should use their actual return types, not this type alias. # E.g. Tuple[Literal["OK"], List[bytes]] -_CommandResults = tuple[str, list[Any]] +_CommandResults: TypeAlias = tuple[str, list[Any]] -_AnyResponseData = list[None] | list[bytes | tuple[bytes, bytes]] - -_list = list # conflicts with a method named "list" +_AnyResponseData: TypeAlias = list[None] | list[bytes | tuple[bytes, bytes]] class IMAP4: error: type[Exception] diff --git a/mypy/typeshed/stdlib/imghdr.pyi b/mypy/typeshed/stdlib/imghdr.pyi index af046e899326a..5f439779a69c6 100644 --- a/mypy/typeshed/stdlib/imghdr.pyi +++ b/mypy/typeshed/stdlib/imghdr.pyi @@ -1,5 +1,6 @@ from _typeshed import StrPath -from typing import Any, BinaryIO, Callable, Protocol, overload +from collections.abc import Callable +from typing import Any, BinaryIO, Protocol, overload __all__ = ["what"] diff --git a/mypy/typeshed/stdlib/importlib/__init__.pyi b/mypy/typeshed/stdlib/importlib/__init__.pyi index 0e99786775b0b..42401a00bdebf 100644 --- a/mypy/typeshed/stdlib/importlib/__init__.pyi +++ b/mypy/typeshed/stdlib/importlib/__init__.pyi @@ -1,6 +1,6 @@ +from collections.abc import Mapping, Sequence from importlib.abc import Loader from types import ModuleType -from typing import Mapping, Sequence __all__ = ["__import__", "import_module", "invalidate_caches", "reload"] diff --git a/mypy/typeshed/stdlib/importlib/abc.pyi b/mypy/typeshed/stdlib/importlib/abc.pyi index 877f8ff1a65c8..63fd02f7b3d51 100644 --- a/mypy/typeshed/stdlib/importlib/abc.pyi +++ b/mypy/typeshed/stdlib/importlib/abc.pyi @@ -10,12 +10,13 @@ from _typeshed import ( StrPath, ) from abc import ABCMeta, abstractmethod +from collections.abc import Iterator, Mapping, Sequence from importlib.machinery import ModuleSpec from io import BufferedRandom, BufferedReader, BufferedWriter, FileIO, TextIOWrapper -from typing import IO, Any, BinaryIO, Iterator, Mapping, NoReturn, Protocol, Sequence, overload, runtime_checkable -from typing_extensions import Literal +from typing import IO, Any, BinaryIO, NoReturn, Protocol, overload, runtime_checkable +from typing_extensions import Literal, TypeAlias -_Path = bytes | str +_Path: TypeAlias = bytes | str class Finder(metaclass=ABCMeta): ... diff --git a/mypy/typeshed/stdlib/importlib/machinery.pyi b/mypy/typeshed/stdlib/importlib/machinery.pyi index f15ac48af5c51..09abdc6f34fdf 100644 --- a/mypy/typeshed/stdlib/importlib/machinery.pyi +++ b/mypy/typeshed/stdlib/importlib/machinery.pyi @@ -1,7 +1,8 @@ import importlib.abc import sys import types -from typing import Any, Callable, Iterable, Sequence +from collections.abc import Callable, Iterable, Sequence +from typing import Any if sys.version_info >= (3, 8): from importlib.metadata import DistributionFinder, PathDistribution diff --git a/mypy/typeshed/stdlib/importlib/metadata/__init__.pyi b/mypy/typeshed/stdlib/importlib/metadata/__init__.pyi index 52c5547a6128d..1f32f0770b375 100644 --- a/mypy/typeshed/stdlib/importlib/metadata/__init__.pyi +++ b/mypy/typeshed/stdlib/importlib/metadata/__init__.pyi @@ -2,12 +2,12 @@ import abc import pathlib import sys from _typeshed import Self, StrPath -from collections.abc import Mapping +from collections.abc import Iterable, Mapping from email.message import Message from importlib.abc import MetaPathFinder from os import PathLike from pathlib import Path -from typing import Any, ClassVar, Iterable, NamedTuple, Pattern, overload +from typing import Any, ClassVar, NamedTuple, Pattern, overload if sys.version_info >= (3, 10): __all__ = [ diff --git a/mypy/typeshed/stdlib/importlib/metadata/_meta.pyi b/mypy/typeshed/stdlib/importlib/metadata/_meta.pyi index a5e5733396d73..a1101df0d5ced 100644 --- a/mypy/typeshed/stdlib/importlib/metadata/_meta.pyi +++ b/mypy/typeshed/stdlib/importlib/metadata/_meta.pyi @@ -1,4 +1,5 @@ -from typing import Any, Iterator, Protocol, TypeVar +from collections.abc import Iterator +from typing import Any, Protocol, TypeVar _T = TypeVar("_T") diff --git a/mypy/typeshed/stdlib/importlib/resources.pyi b/mypy/typeshed/stdlib/importlib/resources.pyi index e6e3035e5daca..04d7e8dcc967f 100644 --- a/mypy/typeshed/stdlib/importlib/resources.pyi +++ b/mypy/typeshed/stdlib/importlib/resources.pyi @@ -1,9 +1,11 @@ import os import sys +from collections.abc import Iterator from contextlib import AbstractContextManager from pathlib import Path from types import ModuleType -from typing import Any, BinaryIO, Iterator, TextIO +from typing import Any, BinaryIO, TextIO +from typing_extensions import TypeAlias if sys.version_info >= (3, 10): __all__ = [ @@ -37,8 +39,8 @@ elif sys.version_info >= (3, 9): else: __all__ = ["Package", "Resource", "contents", "is_resource", "open_binary", "open_text", "path", "read_binary", "read_text"] -Package = str | ModuleType -Resource = str | os.PathLike[Any] +Package: TypeAlias = str | ModuleType +Resource: TypeAlias = str | os.PathLike[Any] def open_binary(package: Package, resource: Resource) -> BinaryIO: ... def open_text(package: Package, resource: Resource, encoding: str = ..., errors: str = ...) -> TextIO: ... diff --git a/mypy/typeshed/stdlib/importlib/util.pyi b/mypy/typeshed/stdlib/importlib/util.pyi index c759d7def5bed..2546c2c7882fe 100644 --- a/mypy/typeshed/stdlib/importlib/util.pyi +++ b/mypy/typeshed/stdlib/importlib/util.pyi @@ -3,7 +3,8 @@ import importlib.machinery import sys import types from _typeshed import StrOrBytesPath -from typing import Any, Callable +from collections.abc import Callable +from typing import Any from typing_extensions import ParamSpec _P = ParamSpec("_P") diff --git a/mypy/typeshed/stdlib/inspect.pyi b/mypy/typeshed/stdlib/inspect.pyi index f87cd0e55acb0..7ca9c9bb3fc48 100644 --- a/mypy/typeshed/stdlib/inspect.pyi +++ b/mypy/typeshed/stdlib/inspect.pyi @@ -3,7 +3,7 @@ import sys import types from _typeshed import Self from collections import OrderedDict -from collections.abc import Awaitable, Callable, Generator, Mapping, Sequence, Set as AbstractSet +from collections.abc import Awaitable, Callable, Coroutine, Generator, Mapping, Sequence, Set as AbstractSet from types import ( AsyncGeneratorType, BuiltinFunctionType, @@ -19,6 +19,7 @@ from types import ( ModuleType, TracebackType, ) +from typing_extensions import TypeAlias if sys.version_info >= (3, 7): from types import ( @@ -29,7 +30,7 @@ if sys.version_info >= (3, 7): MethodWrapperType, ) -from typing import Any, ClassVar, Coroutine, NamedTuple, Protocol, TypeVar, Union +from typing import Any, ClassVar, NamedTuple, Protocol, TypeVar, Union from typing_extensions import Literal, ParamSpec, TypeGuard if sys.version_info >= (3, 11): @@ -165,8 +166,8 @@ TPFLAGS_IS_ABSTRACT: Literal[1048576] modulesbyfile: dict[str, Any] -_GetMembersPredicate = Callable[[Any], bool] -_GetMembersReturn = list[tuple[str, Any]] +_GetMembersPredicate: TypeAlias = Callable[[Any], bool] +_GetMembersReturn: TypeAlias = list[tuple[str, Any]] def getmembers(object: object, predicate: _GetMembersPredicate | None = ...) -> _GetMembersReturn: ... @@ -242,7 +243,9 @@ def isdatadescriptor(object: object) -> TypeGuard[_SupportsSet[Any, Any] | _Supp # # Retrieving source code # -_SourceObjectType = Union[ModuleType, type[Any], MethodType, FunctionType, TracebackType, FrameType, CodeType, Callable[..., Any]] +_SourceObjectType: TypeAlias = Union[ + ModuleType, type[Any], MethodType, FunctionType, TracebackType, FrameType, CodeType, Callable[..., Any] +] def findsource(object: _SourceObjectType) -> tuple[list[str], int]: ... def getabsfile(object: _SourceObjectType, _filename: str | None = ...) -> str: ... @@ -511,7 +514,7 @@ def getcoroutinelocals(coroutine: Coroutine[Any, Any, Any]) -> dict[str, Any]: . # Create private type alias to avoid conflict with symbol of same # name created in Attribute class. -_Object = object +_Object: TypeAlias = object class Attribute(NamedTuple): name: str diff --git a/mypy/typeshed/stdlib/io.pyi b/mypy/typeshed/stdlib/io.pyi index ef4789251cc30..327fd0d94a4d2 100644 --- a/mypy/typeshed/stdlib/io.pyi +++ b/mypy/typeshed/stdlib/io.pyi @@ -2,9 +2,10 @@ import builtins import codecs import sys from _typeshed import ReadableBuffer, Self, StrOrBytesPath, WriteableBuffer +from collections.abc import Callable, Iterable, Iterator from os import _Opener from types import TracebackType -from typing import IO, Any, BinaryIO, Callable, Iterable, Iterator, TextIO +from typing import IO, Any, BinaryIO, TextIO from typing_extensions import Literal if sys.version_info >= (3, 8): diff --git a/mypy/typeshed/stdlib/ipaddress.pyi b/mypy/typeshed/stdlib/ipaddress.pyi index d777cef74597d..1fdc6c57d8a88 100644 --- a/mypy/typeshed/stdlib/ipaddress.pyi +++ b/mypy/typeshed/stdlib/ipaddress.pyi @@ -1,7 +1,8 @@ import sys from _typeshed import Self -from typing import Any, Container, Generic, Iterable, Iterator, SupportsInt, TypeVar, overload -from typing_extensions import Literal +from collections.abc import Container, Iterable, Iterator +from typing import Any, Generic, SupportsInt, TypeVar, overload +from typing_extensions import Literal, TypeAlias # Undocumented length constants IPV4LENGTH: Literal[32] @@ -10,8 +11,8 @@ IPV6LENGTH: Literal[128] _A = TypeVar("_A", IPv4Address, IPv6Address) _N = TypeVar("_N", IPv4Network, IPv6Network) -_RawIPAddress = int | str | bytes | IPv4Address | IPv6Address -_RawNetworkPart = IPv4Network | IPv6Network | IPv4Interface | IPv6Interface +_RawIPAddress: TypeAlias = int | str | bytes | IPv4Address | IPv6Address +_RawNetworkPart: TypeAlias = IPv4Network | IPv6Network | IPv4Interface | IPv6Interface def ip_address(address: _RawIPAddress) -> IPv4Address | IPv6Address: ... def ip_network(address: _RawIPAddress | _RawNetworkPart, strict: bool = ...) -> IPv4Network | IPv6Network: ... diff --git a/mypy/typeshed/stdlib/itertools.pyi b/mypy/typeshed/stdlib/itertools.pyi index bec03b1876ac3..43a0e8038d692 100644 --- a/mypy/typeshed/stdlib/itertools.pyi +++ b/mypy/typeshed/stdlib/itertools.pyi @@ -1,7 +1,8 @@ import sys -from _typeshed import Self, _T_co -from typing import Any, Callable, Generic, Iterable, Iterator, SupportsComplex, SupportsFloat, SupportsInt, TypeVar, overload -from typing_extensions import Literal, SupportsIndex +from _typeshed import Self +from collections.abc import Callable, Iterable, Iterator +from typing import Any, Generic, SupportsComplex, SupportsFloat, SupportsInt, TypeVar, overload +from typing_extensions import Literal, SupportsIndex, TypeAlias if sys.version_info >= (3, 9): from types import GenericAlias @@ -9,9 +10,17 @@ if sys.version_info >= (3, 9): _T = TypeVar("_T") _S = TypeVar("_S") _N = TypeVar("_N", int, float, SupportsFloat, SupportsInt, SupportsIndex, SupportsComplex) -_Step = int | float | SupportsFloat | SupportsInt | SupportsIndex | SupportsComplex +_T_co = TypeVar("_T_co", covariant=True) +_T1 = TypeVar("_T1") +_T2 = TypeVar("_T2") +_T3 = TypeVar("_T3") +_T4 = TypeVar("_T4") +_T5 = TypeVar("_T5") +_T6 = TypeVar("_T6") + +_Step: TypeAlias = int | float | SupportsFloat | SupportsInt | SupportsIndex | SupportsComplex -Predicate = Callable[[_T], object] +_Predicate: TypeAlias = Callable[[_T], object] # Technically count can take anything that implements a number protocol and has an add method # but we can't enforce the add method @@ -67,18 +76,15 @@ class compress(Iterator[_T], Generic[_T]): def __next__(self) -> _T: ... class dropwhile(Iterator[_T], Generic[_T]): - def __init__(self, __predicate: Predicate[_T], __iterable: Iterable[_T]) -> None: ... + def __init__(self, __predicate: _Predicate[_T], __iterable: Iterable[_T]) -> None: ... def __iter__(self: Self) -> Self: ... def __next__(self) -> _T: ... class filterfalse(Iterator[_T], Generic[_T]): - def __init__(self, __predicate: Predicate[_T] | None, __iterable: Iterable[_T]) -> None: ... + def __init__(self, __predicate: _Predicate[_T] | None, __iterable: Iterable[_T]) -> None: ... def __iter__(self: Self) -> Self: ... def __next__(self) -> _T: ... -_T1 = TypeVar("_T1") -_T2 = TypeVar("_T2") - class groupby(Iterator[tuple[_T, Iterator[_S]]], Generic[_T, _S]): @overload def __new__(cls, iterable: Iterable[_T1], key: None = ...) -> groupby[_T1, _T1]: ... @@ -101,21 +107,91 @@ class starmap(Iterator[_T], Generic[_T]): def __next__(self) -> _T: ... class takewhile(Iterator[_T], Generic[_T]): - def __init__(self, __predicate: Predicate[_T], __iterable: Iterable[_T]) -> None: ... + def __init__(self, __predicate: _Predicate[_T], __iterable: Iterable[_T]) -> None: ... def __iter__(self: Self) -> Self: ... def __next__(self) -> _T: ... def tee(__iterable: Iterable[_T], __n: int = ...) -> tuple[Iterator[_T], ...]: ... -class zip_longest(Iterator[Any]): - def __init__(self, *p: Iterable[Any], fillvalue: Any = ...) -> None: ... +class zip_longest(Iterator[_T_co], Generic[_T_co]): + # one iterable (fillvalue doesn't matter) + @overload + def __new__(cls, __iter1: Iterable[_T1], *, fillvalue: object = ...) -> zip_longest[tuple[_T1]]: ... + # two iterables + @overload + # In the overloads without fillvalue, all of the tuple members could theoretically be None, + # but we return Any instead to avoid false positives for code where we know one of the iterables + # is longer. + def __new__(cls, __iter1: Iterable[_T1], __iter2: Iterable[_T2]) -> zip_longest[tuple[_T1 | Any, _T2 | Any]]: ... + @overload + def __new__( + cls, __iter1: Iterable[_T1], __iter2: Iterable[_T2], *, fillvalue: _T + ) -> zip_longest[tuple[_T1 | _T, _T2 | _T]]: ... + # three iterables + @overload + def __new__( + cls, __iter1: Iterable[_T1], __iter2: Iterable[_T2], __iter3: Iterable[_T3] + ) -> zip_longest[tuple[_T1 | Any, _T2 | Any, _T3 | Any]]: ... + @overload + def __new__( + cls, __iter1: Iterable[_T1], __iter2: Iterable[_T2], __iter3: Iterable[_T3], *, fillvalue: _T + ) -> zip_longest[tuple[_T1 | _T, _T2 | _T, _T3 | _T]]: ... + # four iterables + @overload + def __new__( + cls, __iter1: Iterable[_T1], __iter2: Iterable[_T2], __iter3: Iterable[_T3], __iter4: Iterable[_T4] + ) -> zip_longest[tuple[_T1 | Any, _T2 | Any, _T3 | Any, _T4 | Any]]: ... + @overload + def __new__( + cls, __iter1: Iterable[_T1], __iter2: Iterable[_T2], __iter3: Iterable[_T3], __iter4: Iterable[_T4], *, fillvalue: _T + ) -> zip_longest[tuple[_T1 | _T, _T2 | _T, _T3 | _T, _T4 | _T]]: ... + # five iterables + @overload + def __new__( + cls, + __iter1: Iterable[_T1], + __iter2: Iterable[_T2], + __iter3: Iterable[_T3], + __iter4: Iterable[_T4], + __iter5: Iterable[_T5], + ) -> zip_longest[tuple[_T1 | Any, _T2 | Any, _T3 | Any, _T4 | Any, _T5 | Any]]: ... + @overload + def __new__( + cls, + __iter1: Iterable[_T1], + __iter2: Iterable[_T2], + __iter3: Iterable[_T3], + __iter4: Iterable[_T4], + __iter5: Iterable[_T5], + *, + fillvalue: _T, + ) -> zip_longest[tuple[_T1 | _T, _T2 | _T, _T3 | _T, _T4 | _T, _T5 | _T]]: ... + # six or more iterables + @overload + def __new__( + cls, + __iter1: Iterable[_T], + __iter2: Iterable[_T], + __iter3: Iterable[_T], + __iter4: Iterable[_T], + __iter5: Iterable[_T], + __iter6: Iterable[_T], + *iterables: Iterable[_T], + ) -> zip_longest[tuple[_T | Any, ...]]: ... + @overload + def __new__( + cls, + __iter1: Iterable[_T], + __iter2: Iterable[_T], + __iter3: Iterable[_T], + __iter4: Iterable[_T], + __iter5: Iterable[_T], + __iter6: Iterable[_T], + *iterables: Iterable[_T], + fillvalue: _T, + ) -> zip_longest[tuple[_T, ...]]: ... def __iter__(self: Self) -> Self: ... - def __next__(self) -> Any: ... - -_T3 = TypeVar("_T3") -_T4 = TypeVar("_T4") -_T5 = TypeVar("_T5") -_T6 = TypeVar("_T6") + def __next__(self) -> _T_co: ... class product(Iterator[_T_co], Generic[_T_co]): @overload diff --git a/mypy/typeshed/stdlib/json/__init__.pyi b/mypy/typeshed/stdlib/json/__init__.pyi index 8e1a36756398e..2fd87622e1fe9 100644 --- a/mypy/typeshed/stdlib/json/__init__.pyi +++ b/mypy/typeshed/stdlib/json/__init__.pyi @@ -1,5 +1,6 @@ from _typeshed import SupportsRead -from typing import IO, Any, Callable +from collections.abc import Callable +from typing import IO, Any from .decoder import JSONDecodeError as JSONDecodeError, JSONDecoder as JSONDecoder from .encoder import JSONEncoder as JSONEncoder diff --git a/mypy/typeshed/stdlib/json/decoder.pyi b/mypy/typeshed/stdlib/json/decoder.pyi index 8668367585451..2060cf17dd05e 100644 --- a/mypy/typeshed/stdlib/json/decoder.pyi +++ b/mypy/typeshed/stdlib/json/decoder.pyi @@ -1,4 +1,5 @@ -from typing import Any, Callable +from collections.abc import Callable +from typing import Any __all__ = ["JSONDecoder", "JSONDecodeError"] diff --git a/mypy/typeshed/stdlib/json/encoder.pyi b/mypy/typeshed/stdlib/json/encoder.pyi index 6dd74896e5a09..ecd1fa78ad990 100644 --- a/mypy/typeshed/stdlib/json/encoder.pyi +++ b/mypy/typeshed/stdlib/json/encoder.pyi @@ -1,4 +1,5 @@ -from typing import Any, Callable, Iterator, Pattern +from collections.abc import Callable, Iterator +from typing import Any, Pattern ESCAPE: Pattern[str] ESCAPE_ASCII: Pattern[str] diff --git a/mypy/typeshed/stdlib/keyword.pyi b/mypy/typeshed/stdlib/keyword.pyi index e9a9877d57dab..c17c58012fd1b 100644 --- a/mypy/typeshed/stdlib/keyword.pyi +++ b/mypy/typeshed/stdlib/keyword.pyi @@ -1,5 +1,5 @@ import sys -from typing import Sequence +from collections.abc import Sequence if sys.version_info >= (3, 9): __all__ = ["iskeyword", "issoftkeyword", "kwlist", "softkwlist"] diff --git a/mypy/typeshed/stdlib/lib2to3/pgen2/driver.pyi b/mypy/typeshed/stdlib/lib2to3/pgen2/driver.pyi index 4ecba031942c7..61ec90b4d5822 100644 --- a/mypy/typeshed/stdlib/lib2to3/pgen2/driver.pyi +++ b/mypy/typeshed/stdlib/lib2to3/pgen2/driver.pyi @@ -1,8 +1,9 @@ from _typeshed import StrPath +from collections.abc import Iterable from lib2to3.pgen2.grammar import Grammar from lib2to3.pytree import _NL, _Convert from logging import Logger -from typing import IO, Any, Iterable +from typing import IO, Any __all__ = ["Driver", "load_grammar"] diff --git a/mypy/typeshed/stdlib/lib2to3/pgen2/grammar.pyi b/mypy/typeshed/stdlib/lib2to3/pgen2/grammar.pyi index b5836e1b90c59..4d298ec6972c4 100644 --- a/mypy/typeshed/stdlib/lib2to3/pgen2/grammar.pyi +++ b/mypy/typeshed/stdlib/lib2to3/pgen2/grammar.pyi @@ -1,8 +1,9 @@ from _typeshed import Self, StrPath +from typing_extensions import TypeAlias -_Label = tuple[int, str | None] -_DFA = list[list[tuple[int, int]]] -_DFAS = tuple[_DFA, dict[int, int]] +_Label: TypeAlias = tuple[int, str | None] +_DFA: TypeAlias = list[list[tuple[int, int]]] +_DFAS: TypeAlias = tuple[_DFA, dict[int, int]] class Grammar: symbol2number: dict[str, int] diff --git a/mypy/typeshed/stdlib/lib2to3/pgen2/parse.pyi b/mypy/typeshed/stdlib/lib2to3/pgen2/parse.pyi index e776ed1e5a614..14d6004d34230 100644 --- a/mypy/typeshed/stdlib/lib2to3/pgen2/parse.pyi +++ b/mypy/typeshed/stdlib/lib2to3/pgen2/parse.pyi @@ -1,8 +1,10 @@ +from collections.abc import Sequence from lib2to3.pgen2.grammar import _DFAS, Grammar from lib2to3.pytree import _NL, _Convert, _RawNode -from typing import Any, Sequence +from typing import Any +from typing_extensions import TypeAlias -_Context = Sequence[Any] +_Context: TypeAlias = Sequence[Any] class ParseError(Exception): msg: str diff --git a/mypy/typeshed/stdlib/lib2to3/pgen2/pgen.pyi b/mypy/typeshed/stdlib/lib2to3/pgen2/pgen.pyi index 2628e1223fb42..e3ea07432d700 100644 --- a/mypy/typeshed/stdlib/lib2to3/pgen2/pgen.pyi +++ b/mypy/typeshed/stdlib/lib2to3/pgen2/pgen.pyi @@ -1,7 +1,8 @@ from _typeshed import StrPath +from collections.abc import Iterable, Iterator from lib2to3.pgen2 import grammar from lib2to3.pgen2.tokenize import _TokenInfo -from typing import IO, Any, Iterable, Iterator, NoReturn +from typing import IO, Any, NoReturn class PgenGrammar(grammar.Grammar): ... diff --git a/mypy/typeshed/stdlib/lib2to3/pgen2/tokenize.pyi b/mypy/typeshed/stdlib/lib2to3/pgen2/tokenize.pyi index c1b5a91df9e65..a998ad5fe49e3 100644 --- a/mypy/typeshed/stdlib/lib2to3/pgen2/tokenize.pyi +++ b/mypy/typeshed/stdlib/lib2to3/pgen2/tokenize.pyi @@ -1,6 +1,7 @@ import sys +from collections.abc import Callable, Iterable, Iterator from lib2to3.pgen2.token import * -from typing import Callable, Iterable, Iterator +from typing_extensions import TypeAlias if sys.version_info >= (3, 8): __all__ = [ @@ -146,9 +147,9 @@ else: "untokenize", ] -_Coord = tuple[int, int] -_TokenEater = Callable[[int, str, _Coord, _Coord, str], None] -_TokenInfo = tuple[int, str, _Coord, _Coord, str] +_Coord: TypeAlias = tuple[int, int] +_TokenEater: TypeAlias = Callable[[int, str, _Coord, _Coord, str], None] +_TokenInfo: TypeAlias = tuple[int, str, _Coord, _Coord, str] class TokenError(Exception): ... class StopTokenizing(Exception): ... diff --git a/mypy/typeshed/stdlib/lib2to3/pytree.pyi b/mypy/typeshed/stdlib/lib2to3/pytree.pyi index 68e5d8ba13236..fa0cb9e34f752 100644 --- a/mypy/typeshed/stdlib/lib2to3/pytree.pyi +++ b/mypy/typeshed/stdlib/lib2to3/pytree.pyi @@ -1,12 +1,14 @@ from _typeshed import Self +from collections.abc import Callable, Iterator from lib2to3.pgen2.grammar import Grammar -from typing import Any, Callable, Iterator +from typing import Any +from typing_extensions import TypeAlias -_NL = Node | Leaf -_Context = tuple[str, int, int] -_Results = dict[str, _NL] -_RawNode = tuple[int, str, _Context, list[_NL] | None] -_Convert = Callable[[Grammar, _RawNode], Any] +_NL: TypeAlias = Node | Leaf +_Context: TypeAlias = tuple[str, int, int] +_Results: TypeAlias = dict[str, _NL] +_RawNode: TypeAlias = tuple[int, str, _Context, list[_NL] | None] +_Convert: TypeAlias = Callable[[Grammar, _RawNode], Any] HUGE: int diff --git a/mypy/typeshed/stdlib/lib2to3/refactor.pyi b/mypy/typeshed/stdlib/lib2to3/refactor.pyi index 6687092d862c2..3aaea0e519d98 100644 --- a/mypy/typeshed/stdlib/lib2to3/refactor.pyi +++ b/mypy/typeshed/stdlib/lib2to3/refactor.pyi @@ -1,11 +1,12 @@ from collections.abc import Container, Generator, Iterable, Mapping from logging import Logger from typing import Any, ClassVar, NoReturn +from typing_extensions import TypeAlias from .pgen2.grammar import Grammar -_Driver = Any # really lib2to3.driver.Driver -_BottomMatcher = Any # really lib2to3.btm_matcher.BottomMatcher +_Driver: TypeAlias = Any # really lib2to3.driver.Driver +_BottomMatcher: TypeAlias = Any # really lib2to3.btm_matcher.BottomMatcher def get_all_fix_names(fixer_pkg: str, remove_prefix: bool = ...) -> list[str]: ... def get_fixers_from_package(pkg_name: str) -> list[str]: ... diff --git a/mypy/typeshed/stdlib/linecache.pyi b/mypy/typeshed/stdlib/linecache.pyi index d72d678b5e186..df54fd80aea70 100644 --- a/mypy/typeshed/stdlib/linecache.pyi +++ b/mypy/typeshed/stdlib/linecache.pyi @@ -1,13 +1,14 @@ import sys from typing import Any, Protocol +from typing_extensions import TypeAlias if sys.version_info >= (3, 9): __all__ = ["getline", "clearcache", "checkcache", "lazycache"] else: __all__ = ["getline", "clearcache", "checkcache"] -_ModuleGlobals = dict[str, Any] -_ModuleMetadata = tuple[int, float | None, list[str], str] +_ModuleGlobals: TypeAlias = dict[str, Any] +_ModuleMetadata: TypeAlias = tuple[int, float | None, list[str], str] class _SourceLoader(Protocol): def __call__(self) -> str | None: ... diff --git a/mypy/typeshed/stdlib/locale.pyi b/mypy/typeshed/stdlib/locale.pyi index e5227beca149b..959054e847a8c 100644 --- a/mypy/typeshed/stdlib/locale.pyi +++ b/mypy/typeshed/stdlib/locale.pyi @@ -1,5 +1,6 @@ import sys from _typeshed import StrPath +from collections.abc import Callable, Iterable, Mapping __all__ = [ "getlocale", @@ -32,7 +33,7 @@ __all__ = [ # as a type annotation or type alias. from builtins import str as _str from decimal import Decimal -from typing import Any, Callable, Iterable, Mapping +from typing import Any CODESET: int D_T_FMT: int diff --git a/mypy/typeshed/stdlib/logging/__init__.pyi b/mypy/typeshed/stdlib/logging/__init__.pyi index 8de4d0d88260a..edb15061a5886 100644 --- a/mypy/typeshed/stdlib/logging/__init__.pyi +++ b/mypy/typeshed/stdlib/logging/__init__.pyi @@ -7,7 +7,7 @@ from string import Template from time import struct_time from types import FrameType, TracebackType from typing import Any, ClassVar, Generic, Pattern, TextIO, TypeVar, Union, overload -from typing_extensions import Literal +from typing_extensions import Literal, TypeAlias __all__ = [ "BASIC_FORMAT", @@ -54,12 +54,12 @@ __all__ = [ "raiseExceptions", ] -_SysExcInfoType = Union[tuple[type[BaseException], BaseException, TracebackType | None], tuple[None, None, None]] -_ExcInfoType = None | bool | _SysExcInfoType | BaseException -_ArgsType = tuple[object, ...] | Mapping[str, object] -_FilterType = Filter | Callable[[LogRecord], int] -_Level = int | str -_FormatStyle = Literal["%", "{", "$"] +_SysExcInfoType: TypeAlias = Union[tuple[type[BaseException], BaseException, TracebackType | None], tuple[None, None, None]] +_ExcInfoType: TypeAlias = None | bool | _SysExcInfoType | BaseException +_ArgsType: TypeAlias = tuple[object, ...] | Mapping[str, object] +_FilterType: TypeAlias = Filter | Callable[[LogRecord], int] +_Level: TypeAlias = int | str +_FormatStyle: TypeAlias = Literal["%", "{", "$"] raiseExceptions: bool logThreads: bool diff --git a/mypy/typeshed/stdlib/logging/config.pyi b/mypy/typeshed/stdlib/logging/config.pyi index 8ee9e7b339b57..5993ba97df4b2 100644 --- a/mypy/typeshed/stdlib/logging/config.pyi +++ b/mypy/typeshed/stdlib/logging/config.pyi @@ -1,9 +1,10 @@ import sys from _typeshed import StrOrBytesPath, StrPath -from collections.abc import Callable +from collections.abc import Callable, Sequence from configparser import RawConfigParser from threading import Thread -from typing import IO, Any, Pattern, Sequence +from typing import IO, Any, Pattern +from typing_extensions import TypeAlias from . import _Level @@ -13,9 +14,9 @@ else: from typing_extensions import Literal, TypedDict if sys.version_info >= (3, 7): - _Path = StrOrBytesPath + _Path: TypeAlias = StrOrBytesPath else: - _Path = StrPath + _Path: TypeAlias = StrPath DEFAULT_LOGGING_CONFIG_PORT: int RESET_ERROR: int # undocumented diff --git a/mypy/typeshed/stdlib/lzma.pyi b/mypy/typeshed/stdlib/lzma.pyi index 45bf24b3ef6de..d4c7977b8d0aa 100644 --- a/mypy/typeshed/stdlib/lzma.pyi +++ b/mypy/typeshed/stdlib/lzma.pyi @@ -1,7 +1,8 @@ import io from _typeshed import ReadableBuffer, Self, StrOrBytesPath -from typing import IO, Any, Mapping, Sequence, TextIO, overload -from typing_extensions import Literal, final +from collections.abc import Mapping, Sequence +from typing import IO, Any, TextIO, overload +from typing_extensions import Literal, TypeAlias, final __all__ = [ "CHECK_NONE", @@ -42,12 +43,12 @@ __all__ = [ "is_check_supported", ] -_OpenBinaryWritingMode = Literal["w", "wb", "x", "xb", "a", "ab"] -_OpenTextWritingMode = Literal["wt", "xt", "at"] +_OpenBinaryWritingMode: TypeAlias = Literal["w", "wb", "x", "xb", "a", "ab"] +_OpenTextWritingMode: TypeAlias = Literal["wt", "xt", "at"] -_PathOrFile = StrOrBytesPath | IO[bytes] +_PathOrFile: TypeAlias = StrOrBytesPath | IO[bytes] -_FilterChain = Sequence[Mapping[str, Any]] +_FilterChain: TypeAlias = Sequence[Mapping[str, Any]] FORMAT_AUTO: Literal[0] FORMAT_XZ: Literal[1] diff --git a/mypy/typeshed/stdlib/mailbox.pyi b/mypy/typeshed/stdlib/mailbox.pyi index 143891d3240bf..64183cd0b3a41 100644 --- a/mypy/typeshed/stdlib/mailbox.pyi +++ b/mypy/typeshed/stdlib/mailbox.pyi @@ -2,9 +2,10 @@ import email.message import sys from _typeshed import Self, StrOrBytesPath from abc import ABCMeta, abstractmethod +from collections.abc import Callable, Iterable, Iterator, Mapping, Sequence from types import TracebackType -from typing import IO, Any, AnyStr, Callable, Generic, Iterable, Iterator, Mapping, Protocol, Sequence, TypeVar, overload -from typing_extensions import Literal +from typing import IO, Any, AnyStr, Generic, Protocol, TypeVar, overload +from typing_extensions import Literal, TypeAlias if sys.version_info >= (3, 9): from types import GenericAlias @@ -31,7 +32,7 @@ __all__ = [ _T = TypeVar("_T") _MessageT = TypeVar("_MessageT", bound=Message) -_MessageData = email.message.Message | bytes | str | IO[str] | IO[bytes] +_MessageData: TypeAlias = email.message.Message | bytes | str | IO[str] | IO[bytes] class _HasIteritems(Protocol): def iteritems(self) -> Iterator[tuple[str, _MessageData]]: ... diff --git a/mypy/typeshed/stdlib/mailcap.pyi b/mypy/typeshed/stdlib/mailcap.pyi index 232ab99c314d7..e1637ad6e7be4 100644 --- a/mypy/typeshed/stdlib/mailcap.pyi +++ b/mypy/typeshed/stdlib/mailcap.pyi @@ -1,6 +1,7 @@ -from typing import Mapping, Sequence +from collections.abc import Mapping, Sequence +from typing_extensions import TypeAlias -_Cap = dict[str, str | int] +_Cap: TypeAlias = dict[str, str | int] __all__ = ["getcaps", "findmatch"] diff --git a/mypy/typeshed/stdlib/math.pyi b/mypy/typeshed/stdlib/math.pyi index e4ab311990be1..ada510d629ed2 100644 --- a/mypy/typeshed/stdlib/math.pyi +++ b/mypy/typeshed/stdlib/math.pyi @@ -1,12 +1,13 @@ import sys from _typeshed import SupportsTrunc -from typing import Iterable, SupportsFloat, overload -from typing_extensions import SupportsIndex +from collections.abc import Iterable +from typing import SupportsFloat, overload +from typing_extensions import SupportsIndex, TypeAlias if sys.version_info >= (3, 8): - _SupportsFloatOrIndex = SupportsFloat | SupportsIndex + _SupportsFloatOrIndex: TypeAlias = SupportsFloat | SupportsIndex else: - _SupportsFloatOrIndex = SupportsFloat + _SupportsFloatOrIndex: TypeAlias = SupportsFloat e: float pi: float diff --git a/mypy/typeshed/stdlib/mimetypes.pyi b/mypy/typeshed/stdlib/mimetypes.pyi index e51b7cdf37bde..c2b6ff20281a7 100644 --- a/mypy/typeshed/stdlib/mimetypes.pyi +++ b/mypy/typeshed/stdlib/mimetypes.pyi @@ -1,6 +1,7 @@ import sys from _typeshed import StrPath -from typing import IO, Sequence +from collections.abc import Sequence +from typing import IO __all__ = [ "knownfiles", diff --git a/mypy/typeshed/stdlib/mmap.pyi b/mypy/typeshed/stdlib/mmap.pyi index 7448881724792..96bb01a271fc7 100644 --- a/mypy/typeshed/stdlib/mmap.pyi +++ b/mypy/typeshed/stdlib/mmap.pyi @@ -1,6 +1,7 @@ import sys from _typeshed import ReadableBuffer, Self -from typing import Iterable, Iterator, NoReturn, Sized, overload +from collections.abc import Iterable, Iterator, Sized +from typing import NoReturn, overload ACCESS_DEFAULT: int ACCESS_READ: int diff --git a/mypy/typeshed/stdlib/modulefinder.pyi b/mypy/typeshed/stdlib/modulefinder.pyi index 9efe032cfd29b..cd01e0e1381fb 100644 --- a/mypy/typeshed/stdlib/modulefinder.pyi +++ b/mypy/typeshed/stdlib/modulefinder.pyi @@ -1,6 +1,7 @@ import sys +from collections.abc import Container, Iterable, Iterator, Sequence from types import CodeType -from typing import IO, Any, Container, Iterable, Iterator, Sequence +from typing import IO, Any LOAD_CONST: int # undocumented IMPORT_NAME: int # undocumented diff --git a/mypy/typeshed/stdlib/msilib/__init__.pyi b/mypy/typeshed/stdlib/msilib/__init__.pyi index c512489be34d1..968efbec7a6c8 100644 --- a/mypy/typeshed/stdlib/msilib/__init__.pyi +++ b/mypy/typeshed/stdlib/msilib/__init__.pyi @@ -1,6 +1,7 @@ import sys +from collections.abc import Container, Iterable, Sequence from types import ModuleType -from typing import Any, Container, Iterable, Sequence +from typing import Any from typing_extensions import Literal if sys.platform == "win32": diff --git a/mypy/typeshed/stdlib/msilib/sequence.pyi b/mypy/typeshed/stdlib/msilib/sequence.pyi index 30346aba33673..9cc1e0eaec01e 100644 --- a/mypy/typeshed/stdlib/msilib/sequence.pyi +++ b/mypy/typeshed/stdlib/msilib/sequence.pyi @@ -1,8 +1,9 @@ import sys +from typing_extensions import TypeAlias if sys.platform == "win32": - _SequenceType = list[tuple[str, str | None, int]] + _SequenceType: TypeAlias = list[tuple[str, str | None, int]] AdminExecuteSequence: _SequenceType AdminUISequence: _SequenceType diff --git a/mypy/typeshed/stdlib/multiprocessing/__init__.pyi b/mypy/typeshed/stdlib/multiprocessing/__init__.pyi index 3a8a382b8a275..87ceda10573d0 100644 --- a/mypy/typeshed/stdlib/multiprocessing/__init__.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/__init__.pyi @@ -20,8 +20,8 @@ from multiprocessing.process import active_children as active_children, current_ # multiprocessing.queues or the aliases defined below. See #4266 for discussion. from multiprocessing.queues import JoinableQueue as JoinableQueue, Queue as Queue, SimpleQueue as SimpleQueue from multiprocessing.spawn import freeze_support as freeze_support -from typing import Any, overload -from typing_extensions import Literal +from typing import Any, TypeVar, overload +from typing_extensions import Literal, TypeAlias if sys.version_info >= (3, 8): from multiprocessing.process import parent_process as parent_process @@ -118,23 +118,24 @@ else: # from multiprocessing import _LockType # lock: _LockType = Lock() -_QueueType = Queue -_SimpleQueueType = SimpleQueue -_JoinableQueueType = JoinableQueue -_BarrierType = synchronize.Barrier -_BoundedSemaphoreType = synchronize.BoundedSemaphore -_ConditionType = synchronize.Condition -_EventType = synchronize.Event -_LockType = synchronize.Lock -_RLockType = synchronize.RLock -_SemaphoreType = synchronize.Semaphore +_T = TypeVar("_T") +_QueueType: TypeAlias = Queue[_T] +_SimpleQueueType: TypeAlias = SimpleQueue[_T] +_JoinableQueueType: TypeAlias = JoinableQueue[_T] +_BarrierType: TypeAlias = synchronize.Barrier +_BoundedSemaphoreType: TypeAlias = synchronize.BoundedSemaphore +_ConditionType: TypeAlias = synchronize.Condition +_EventType: TypeAlias = synchronize.Event +_LockType: TypeAlias = synchronize.Lock +_RLockType: TypeAlias = synchronize.RLock +_SemaphoreType: TypeAlias = synchronize.Semaphore # N.B. The functions below are generated at runtime by partially applying # multiprocessing.context.BaseContext's methods, so the two signatures should # be identical (modulo self). # Synchronization primitives -_LockLike = synchronize.Lock | synchronize.RLock +_LockLike: TypeAlias = synchronize.Lock | synchronize.RLock RawValue = context._default_context.RawValue RawArray = context._default_context.RawArray Value = context._default_context.Value diff --git a/mypy/typeshed/stdlib/multiprocessing/connection.pyi b/mypy/typeshed/stdlib/multiprocessing/connection.pyi index 5db6fa4cda7e0..7b227a697abec 100644 --- a/mypy/typeshed/stdlib/multiprocessing/connection.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/connection.pyi @@ -2,13 +2,14 @@ import socket import sys import types from _typeshed import Self -from typing import Any, Iterable, Union -from typing_extensions import SupportsIndex +from collections.abc import Iterable +from typing import Any, Union +from typing_extensions import SupportsIndex, TypeAlias __all__ = ["Client", "Listener", "Pipe", "wait"] # https://docs.python.org/3/library/multiprocessing.html#address-formats -_Address = Union[str, tuple[str, int]] +_Address: TypeAlias = Union[str, tuple[str, int]] class _ConnectionBase: def __init__(self, handle: SupportsIndex, readable: bool = ..., writable: bool = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/multiprocessing/context.pyi b/mypy/typeshed/stdlib/multiprocessing/context.pyi index 315918a04b985..d618d10281124 100644 --- a/mypy/typeshed/stdlib/multiprocessing/context.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/context.pyi @@ -9,14 +9,14 @@ from multiprocessing.pool import Pool as _Pool from multiprocessing.process import BaseProcess from multiprocessing.sharedctypes import SynchronizedArray, SynchronizedBase from typing import Any, ClassVar, TypeVar, overload -from typing_extensions import Literal +from typing_extensions import Literal, TypeAlias if sys.version_info >= (3, 8): __all__ = () else: __all__: list[str] = [] -_LockLike = synchronize.Lock | synchronize.RLock +_LockLike: TypeAlias = synchronize.Lock | synchronize.RLock _CT = TypeVar("_CT", bound=_CData) class ProcessError(Exception): ... diff --git a/mypy/typeshed/stdlib/multiprocessing/dummy/__init__.pyi b/mypy/typeshed/stdlib/multiprocessing/dummy/__init__.pyi index 48f42999866a2..bbddfd16ded7f 100644 --- a/mypy/typeshed/stdlib/multiprocessing/dummy/__init__.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/dummy/__init__.pyi @@ -1,8 +1,9 @@ import array import threading import weakref +from collections.abc import Callable, Iterable, Mapping, Sequence from queue import Queue as Queue -from typing import Any, Callable, Iterable, Mapping, Sequence +from typing import Any from typing_extensions import Literal from .connection import Pipe as Pipe diff --git a/mypy/typeshed/stdlib/multiprocessing/dummy/connection.pyi b/mypy/typeshed/stdlib/multiprocessing/dummy/connection.pyi index c61617cd91d4f..fd909d0d32e1d 100644 --- a/mypy/typeshed/stdlib/multiprocessing/dummy/connection.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/dummy/connection.pyi @@ -2,12 +2,13 @@ from _typeshed import Self from queue import Queue from types import TracebackType from typing import Any, Union +from typing_extensions import TypeAlias __all__ = ["Client", "Listener", "Pipe"] families: list[None] -_Address = Union[str, tuple[str, int]] +_Address: TypeAlias = Union[str, tuple[str, int]] class Connection: _in: Any diff --git a/mypy/typeshed/stdlib/multiprocessing/managers.pyi b/mypy/typeshed/stdlib/multiprocessing/managers.pyi index a0f76b636c4b2..234660cc4f806 100644 --- a/mypy/typeshed/stdlib/multiprocessing/managers.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/managers.pyi @@ -2,19 +2,20 @@ import queue import sys import threading from _typeshed import Self +from builtins import dict as _dict, list as _list # Conflicts with method names +from collections.abc import Callable, Iterable, Mapping, Sequence from types import TracebackType -from typing import Any, AnyStr, Callable, Generic, Iterable, Mapping, Sequence, TypeVar +from typing import Any, AnyStr, Generic, TypeVar +from typing_extensions import TypeAlias from .connection import Connection from .context import BaseContext if sys.version_info >= (3, 8): - from .shared_memory import _SLT, ShareableList, SharedMemory + from .shared_memory import _SLT, ShareableList as _ShareableList, SharedMemory as _SharedMemory __all__ = ["BaseManager", "SyncManager", "BaseProxy", "Token", "SharedMemoryManager"] - _SharedMemory = SharedMemory - _ShareableList = ShareableList else: __all__ = ["BaseManager", "SyncManager", "BaseProxy", "Token"] @@ -30,7 +31,7 @@ class Namespace: def __getattr__(self, __name: str) -> Any: ... def __setattr__(self, __name: str, __value: Any) -> None: ... -_Namespace = Namespace +_Namespace: TypeAlias = Namespace class Token: typeid: str | bytes | None @@ -100,10 +101,6 @@ class BaseManager: self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> None: ... -# Conflicts with method names -_dict = dict -_list = list - class SyncManager(BaseManager): def BoundedSemaphore(self, value: Any = ...) -> threading.BoundedSemaphore: ... def Condition(self, lock: Any = ...) -> threading.Condition: ... diff --git a/mypy/typeshed/stdlib/multiprocessing/pool.pyi b/mypy/typeshed/stdlib/multiprocessing/pool.pyi index 5e38e01618342..c0d01e98dfae8 100644 --- a/mypy/typeshed/stdlib/multiprocessing/pool.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/pool.pyi @@ -1,7 +1,8 @@ import sys from _typeshed import Self +from collections.abc import Callable, Iterable, Iterator, Mapping from types import TracebackType -from typing import Any, Callable, Generic, Iterable, Iterator, Mapping, TypeVar +from typing import Any, Generic, TypeVar from typing_extensions import Literal if sys.version_info >= (3, 9): diff --git a/mypy/typeshed/stdlib/multiprocessing/shared_memory.pyi b/mypy/typeshed/stdlib/multiprocessing/shared_memory.pyi index a4c4fd071c5f5..76ccedaf478e9 100644 --- a/mypy/typeshed/stdlib/multiprocessing/shared_memory.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/shared_memory.pyi @@ -1,6 +1,7 @@ import sys from _typeshed import Self -from typing import Any, Generic, Iterable, TypeVar +from collections.abc import Iterable +from typing import Any, Generic, TypeVar if sys.version_info >= (3, 9): from types import GenericAlias diff --git a/mypy/typeshed/stdlib/multiprocessing/spawn.pyi b/mypy/typeshed/stdlib/multiprocessing/spawn.pyi index 4f981ea467c48..50570ff3717bf 100644 --- a/mypy/typeshed/stdlib/multiprocessing/spawn.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/spawn.pyi @@ -1,5 +1,6 @@ +from collections.abc import Mapping, Sequence from types import ModuleType -from typing import Any, Mapping, Sequence +from typing import Any __all__ = [ "_main", diff --git a/mypy/typeshed/stdlib/multiprocessing/synchronize.pyi b/mypy/typeshed/stdlib/multiprocessing/synchronize.pyi index 0cfc815b2d824..e93d6c58b5cfa 100644 --- a/mypy/typeshed/stdlib/multiprocessing/synchronize.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/synchronize.pyi @@ -1,13 +1,15 @@ import sys import threading +from collections.abc import Callable from contextlib import AbstractContextManager from multiprocessing.context import BaseContext from types import TracebackType -from typing import Any, Callable +from typing import Any +from typing_extensions import TypeAlias __all__ = ["Lock", "RLock", "Semaphore", "BoundedSemaphore", "Condition", "Event"] -_LockLike = Lock | RLock +_LockLike: TypeAlias = Lock | RLock class Barrier(threading.Barrier): def __init__( diff --git a/mypy/typeshed/stdlib/netrc.pyi b/mypy/typeshed/stdlib/netrc.pyi index 45f6cfbeda7bf..803c780733485 100644 --- a/mypy/typeshed/stdlib/netrc.pyi +++ b/mypy/typeshed/stdlib/netrc.pyi @@ -1,4 +1,5 @@ from _typeshed import StrOrBytesPath +from typing_extensions import TypeAlias __all__ = ["netrc", "NetrcParseError"] @@ -9,7 +10,7 @@ class NetrcParseError(Exception): def __init__(self, msg: str, filename: StrOrBytesPath | None = ..., lineno: int | None = ...) -> None: ... # (login, account, password) tuple -_NetrcTuple = tuple[str, str | None, str | None] +_NetrcTuple: TypeAlias = tuple[str, str | None, str | None] class netrc: hosts: dict[str, _NetrcTuple] diff --git a/mypy/typeshed/stdlib/nntplib.pyi b/mypy/typeshed/stdlib/nntplib.pyi index cc48cb83ae4c2..aa5bcba5726c0 100644 --- a/mypy/typeshed/stdlib/nntplib.pyi +++ b/mypy/typeshed/stdlib/nntplib.pyi @@ -3,8 +3,10 @@ import socket import ssl import sys from _typeshed import Self -from typing import IO, Any, Iterable, NamedTuple -from typing_extensions import Literal +from builtins import list as _list # conflicts with a method named "list" +from collections.abc import Iterable +from typing import IO, Any, NamedTuple +from typing_extensions import Literal, TypeAlias __all__ = [ "NNTP", @@ -18,7 +20,7 @@ __all__ = [ "NNTP_SSL", ] -_File = IO[bytes] | bytes | str | None +_File: TypeAlias = IO[bytes] | bytes | str | None class NNTPError(Exception): response: str @@ -45,8 +47,6 @@ class ArticleInfo(NamedTuple): def decode_header(header_str: str) -> str: ... -_list = list # conflicts with a method named "list" - class NNTP: encoding: str errors: str diff --git a/mypy/typeshed/stdlib/optparse.pyi b/mypy/typeshed/stdlib/optparse.pyi index 7aedf583e556f..1e7428f59a950 100644 --- a/mypy/typeshed/stdlib/optparse.pyi +++ b/mypy/typeshed/stdlib/optparse.pyi @@ -1,5 +1,6 @@ from abc import abstractmethod -from typing import IO, Any, AnyStr, Callable, Iterable, Mapping, Sequence, overload +from collections.abc import Callable, Iterable, Mapping, Sequence +from typing import IO, Any, AnyStr, overload __all__ = [ "Option", diff --git a/mypy/typeshed/stdlib/os/__init__.pyi b/mypy/typeshed/stdlib/os/__init__.pyi index 2ef781bbe2886..76c114591d323 100644 --- a/mypy/typeshed/stdlib/os/__init__.pyi +++ b/mypy/typeshed/stdlib/os/__init__.pyi @@ -14,28 +14,12 @@ from _typeshed import ( ) from abc import abstractmethod from builtins import OSError +from collections.abc import Callable, Iterable, Iterator, Mapping, MutableMapping, Sequence from contextlib import AbstractContextManager from io import BufferedRandom, BufferedReader, BufferedWriter, FileIO, TextIOWrapper as _TextIOWrapper from subprocess import Popen -from typing import ( - IO, - Any, - AnyStr, - BinaryIO, - Callable, - Generic, - Iterable, - Iterator, - Mapping, - MutableMapping, - NoReturn, - Protocol, - Sequence, - TypeVar, - overload, - runtime_checkable, -) -from typing_extensions import Final, Literal, final +from typing import IO, Any, AnyStr, BinaryIO, Generic, NoReturn, Protocol, TypeVar, overload, runtime_checkable +from typing_extensions import Final, Literal, TypeAlias, final from . import path as _path @@ -211,7 +195,7 @@ R_OK: int W_OK: int X_OK: int -_EnvironCodeFunc = Callable[[AnyStr], AnyStr] +_EnvironCodeFunc: TypeAlias = Callable[[AnyStr], AnyStr] class _Environ(MutableMapping[AnyStr, AnyStr], Generic[AnyStr]): encodekey: _EnvironCodeFunc[AnyStr] @@ -383,7 +367,7 @@ def listdir(path: BytesPath) -> list[bytes]: ... @overload def listdir(path: int) -> list[str]: ... -_FdOrAnyPath = int | StrOrBytesPath +_FdOrAnyPath: TypeAlias = int | StrOrBytesPath @final class DirEntry(Generic[AnyStr]): @@ -404,9 +388,9 @@ class DirEntry(Generic[AnyStr]): def __class_getitem__(cls, item: Any) -> GenericAlias: ... if sys.version_info >= (3, 7): - _StatVfsTuple = tuple[int, int, int, int, int, int, int, int, int, int, int] + _StatVfsTuple: TypeAlias = tuple[int, int, int, int, int, int, int, int, int, int, int] else: - _StatVfsTuple = tuple[int, int, int, int, int, int, int, int, int, int] + _StatVfsTuple: TypeAlias = tuple[int, int, int, int, int, int, int, int, int, int] @final class statvfs_result(structseq[int], _StatVfsTuple): @@ -527,7 +511,7 @@ def putenv(__name: bytes | str, __value: bytes | str) -> None: ... if sys.platform != "win32" or sys.version_info >= (3, 9): def unsetenv(__name: bytes | str) -> None: ... -_Opener = Callable[[str, int], int] +_Opener: TypeAlias = Callable[[str, int], int] @overload def fdopen( @@ -787,7 +771,7 @@ def utime( follow_symlinks: bool = ..., ) -> None: ... -_OnError = Callable[[OSError], Any] +_OnError: TypeAlias = Callable[[OSError], Any] def walk( top: AnyStr | PathLike[AnyStr], topdown: bool = ..., onerror: _OnError | None = ..., followlinks: bool = ... @@ -845,7 +829,7 @@ def execlpe(file: StrOrBytesPath, __arg0: StrOrBytesPath, *args: Any) -> NoRetur # Not separating out PathLike[str] and PathLike[bytes] here because it doesn't make much difference # in practice, and doing so would explode the number of combinations in this already long union. # All these combinations are necessary due to list being invariant. -_ExecVArgs = ( +_ExecVArgs: TypeAlias = ( tuple[StrOrBytesPath, ...] | list[bytes] | list[str] @@ -855,7 +839,7 @@ _ExecVArgs = ( | list[str | PathLike[Any]] | list[bytes | str | PathLike[Any]] ) -_ExecEnv = Mapping[bytes, bytes | str] | Mapping[str, bytes | str] +_ExecEnv: TypeAlias = Mapping[bytes, bytes | str] | Mapping[str, bytes | str] def execv(__path: StrOrBytesPath, __argv: _ExecVArgs) -> NoReturn: ... def execve(path: _FdOrAnyPath, argv: _ExecVArgs, env: _ExecEnv) -> NoReturn: ... diff --git a/mypy/typeshed/stdlib/parser.pyi b/mypy/typeshed/stdlib/parser.pyi index 95e770b572568..cce8594eac58b 100644 --- a/mypy/typeshed/stdlib/parser.pyi +++ b/mypy/typeshed/stdlib/parser.pyi @@ -1,6 +1,7 @@ from _typeshed import StrOrBytesPath +from collections.abc import Sequence from types import CodeType -from typing import Any, Sequence +from typing import Any from typing_extensions import final def expr(source: str) -> STType: ... diff --git a/mypy/typeshed/stdlib/pathlib.pyi b/mypy/typeshed/stdlib/pathlib.pyi index 45917ce59f8f1..65aead6cb4de8 100644 --- a/mypy/typeshed/stdlib/pathlib.pyi +++ b/mypy/typeshed/stdlib/pathlib.pyi @@ -8,10 +8,11 @@ from _typeshed import ( Self, StrPath, ) +from collections.abc import Generator, Sequence from io import BufferedRandom, BufferedReader, BufferedWriter, FileIO, TextIOWrapper from os import PathLike, stat_result from types import TracebackType -from typing import IO, Any, BinaryIO, Generator, Sequence, overload +from typing import IO, Any, BinaryIO, overload from typing_extensions import Literal if sys.version_info >= (3, 9): diff --git a/mypy/typeshed/stdlib/pdb.pyi b/mypy/typeshed/stdlib/pdb.pyi index c1cba5e8d23ba..e787b4a4c4160 100644 --- a/mypy/typeshed/stdlib/pdb.pyi +++ b/mypy/typeshed/stdlib/pdb.pyi @@ -3,9 +3,10 @@ import sys from _typeshed import Self from bdb import Bdb from cmd import Cmd +from collections.abc import Callable, Iterable, Mapping, Sequence from inspect import _SourceObjectType from types import CodeType, FrameType, TracebackType -from typing import IO, Any, Callable, ClassVar, Iterable, Mapping, Sequence, TypeVar +from typing import IO, Any, ClassVar, TypeVar from typing_extensions import ParamSpec __all__ = ["run", "pm", "Pdb", "runeval", "runctx", "runcall", "set_trace", "post_mortem", "help"] diff --git a/mypy/typeshed/stdlib/pickle.pyi b/mypy/typeshed/stdlib/pickle.pyi index 26ee94ca26829..d58cf8ed9d504 100644 --- a/mypy/typeshed/stdlib/pickle.pyi +++ b/mypy/typeshed/stdlib/pickle.pyi @@ -1,6 +1,8 @@ import sys -from typing import Any, Callable, ClassVar, Iterable, Iterator, Mapping, Protocol, Union -from typing_extensions import final +from _typeshed import ReadableBuffer +from collections.abc import Callable, Iterable, Iterator, Mapping +from typing import Any, ClassVar, Protocol, SupportsBytes, Union +from typing_extensions import SupportsIndex, TypeAlias, final if sys.version_info >= (3, 8): __all__ = [ @@ -182,14 +184,12 @@ class _WritableFileobj(Protocol): def write(self, __b: bytes) -> Any: ... if sys.version_info >= (3, 8): - # TODO: holistic design for buffer interface (typing.Buffer?) @final class PickleBuffer: - # buffer must be a buffer-providing object - def __init__(self, buffer: Any) -> None: ... + def __init__(self, buffer: ReadableBuffer) -> None: ... def raw(self) -> memoryview: ... def release(self) -> None: ... - _BufferCallback = Callable[[PickleBuffer], Any] | None + _BufferCallback: TypeAlias = Callable[[PickleBuffer], Any] | None def dump( obj: Any, file: _WritableFileobj, @@ -210,20 +210,25 @@ if sys.version_info >= (3, 8): buffers: Iterable[Any] | None = ..., ) -> Any: ... def loads( - __data: bytes, *, fix_imports: bool = ..., encoding: str = ..., errors: str = ..., buffers: Iterable[Any] | None = ... + __data: ReadableBuffer, + *, + fix_imports: bool = ..., + encoding: str = ..., + errors: str = ..., + buffers: Iterable[Any] | None = ..., ) -> Any: ... else: def dump(obj: Any, file: _WritableFileobj, protocol: int | None = ..., *, fix_imports: bool = ...) -> None: ... def dumps(obj: Any, protocol: int | None = ..., *, fix_imports: bool = ...) -> bytes: ... def load(file: _ReadableFileobj, *, fix_imports: bool = ..., encoding: str = ..., errors: str = ...) -> Any: ... - def loads(data: bytes, *, fix_imports: bool = ..., encoding: str = ..., errors: str = ...) -> Any: ... + def loads(data: ReadableBuffer, *, fix_imports: bool = ..., encoding: str = ..., errors: str = ...) -> Any: ... class PickleError(Exception): ... class PicklingError(PickleError): ... class UnpicklingError(PickleError): ... -_reducedtype = Union[ +_reducedtype: TypeAlias = Union[ str, tuple[Callable[..., Any], tuple[Any, ...]], tuple[Callable[..., Any], tuple[Any, ...], Any], @@ -358,7 +363,7 @@ if sys.version_info >= (3, 8): READONLY_BUFFER: bytes def encode_long(x: int) -> bytes: ... # undocumented -def decode_long(data: bytes) -> int: ... # undocumented +def decode_long(data: Iterable[SupportsIndex] | SupportsBytes | ReadableBuffer) -> int: ... # undocumented # pure-Python implementations _Pickler = Pickler # undocumented diff --git a/mypy/typeshed/stdlib/pickletools.pyi b/mypy/typeshed/stdlib/pickletools.pyi index 7b79ddcff347b..c78848464237c 100644 --- a/mypy/typeshed/stdlib/pickletools.pyi +++ b/mypy/typeshed/stdlib/pickletools.pyi @@ -1,8 +1,10 @@ -from typing import IO, Any, Callable, Iterator, MutableMapping +from collections.abc import Callable, Iterator, MutableMapping +from typing import IO, Any +from typing_extensions import TypeAlias __all__ = ["dis", "genops", "optimize"] -_Reader = Callable[[IO[bytes]], Any] +_Reader: TypeAlias = Callable[[IO[bytes]], Any] bytes_types: tuple[type[Any], ...] UP_TO_NEWLINE: int diff --git a/mypy/typeshed/stdlib/pkgutil.pyi b/mypy/typeshed/stdlib/pkgutil.pyi index 7c27f6702a7e1..5a93a9f868120 100644 --- a/mypy/typeshed/stdlib/pkgutil.pyi +++ b/mypy/typeshed/stdlib/pkgutil.pyi @@ -1,7 +1,8 @@ import sys from _typeshed import SupportsRead +from collections.abc import Callable, Iterable, Iterator from importlib.abc import Loader, MetaPathFinder, PathEntryFinder -from typing import IO, Any, Callable, Iterable, Iterator, NamedTuple, TypeVar +from typing import IO, Any, NamedTuple, TypeVar __all__ = [ "get_importer", diff --git a/mypy/typeshed/stdlib/plistlib.pyi b/mypy/typeshed/stdlib/plistlib.pyi index 67d1611de8282..de5fe1b75ca04 100644 --- a/mypy/typeshed/stdlib/plistlib.pyi +++ b/mypy/typeshed/stdlib/plistlib.pyi @@ -1,8 +1,9 @@ import sys from _typeshed import Self +from collections.abc import Mapping, MutableMapping from datetime import datetime from enum import Enum -from typing import IO, Any, Mapping, MutableMapping +from typing import IO, Any if sys.version_info >= (3, 9): __all__ = ["InvalidFileException", "FMT_XML", "FMT_BINARY", "load", "dump", "loads", "dumps", "UID"] diff --git a/mypy/typeshed/stdlib/poplib.pyi b/mypy/typeshed/stdlib/poplib.pyi index 6b651e98e41f6..487a7266694ca 100644 --- a/mypy/typeshed/stdlib/poplib.pyi +++ b/mypy/typeshed/stdlib/poplib.pyi @@ -1,11 +1,12 @@ import socket import ssl +from builtins import list as _list # conflicts with a method named "list" from typing import Any, BinaryIO, NoReturn, Pattern, overload -from typing_extensions import Literal +from typing_extensions import Literal, TypeAlias __all__ = ["POP3", "error_proto", "POP3_SSL"] -_LongResp = tuple[bytes, list[bytes], int] +_LongResp: TypeAlias = tuple[bytes, list[bytes], int] class error_proto(Exception): ... @@ -16,8 +17,6 @@ LF: Literal[b"\n"] CRLF: Literal[b"\r\n"] HAVE_SSL: bool -_list = list # conflicts with a method named "list" - class POP3: encoding: str host: str diff --git a/mypy/typeshed/stdlib/posixpath.pyi b/mypy/typeshed/stdlib/posixpath.pyi index c72ba8a99bdde..4cec7c770ea3b 100644 --- a/mypy/typeshed/stdlib/posixpath.pyi +++ b/mypy/typeshed/stdlib/posixpath.pyi @@ -1,5 +1,6 @@ import sys from _typeshed import BytesPath, StrOrBytesPath, StrPath +from collections.abc import Sequence from genericpath import ( commonprefix as commonprefix, exists as exists, @@ -14,7 +15,7 @@ from genericpath import ( samestat as samestat, ) from os import PathLike -from typing import AnyStr, Sequence, overload +from typing import AnyStr, overload __all__ = [ "normcase", diff --git a/mypy/typeshed/stdlib/profile.pyi b/mypy/typeshed/stdlib/profile.pyi index 982bcabad4011..4b3f832d3224a 100644 --- a/mypy/typeshed/stdlib/profile.pyi +++ b/mypy/typeshed/stdlib/profile.pyi @@ -1,6 +1,7 @@ from _typeshed import Self, StrOrBytesPath -from typing import Any, Callable, TypeVar -from typing_extensions import ParamSpec +from collections.abc import Callable +from typing import Any, TypeVar +from typing_extensions import ParamSpec, TypeAlias __all__ = ["run", "runctx", "Profile"] @@ -11,7 +12,7 @@ def runctx( _T = TypeVar("_T") _P = ParamSpec("_P") -_Label = tuple[str, int, str] +_Label: TypeAlias = tuple[str, int, str] class Profile: bias: int diff --git a/mypy/typeshed/stdlib/pstats.pyi b/mypy/typeshed/stdlib/pstats.pyi index a7b8bebe4066b..7868512e5ab91 100644 --- a/mypy/typeshed/stdlib/pstats.pyi +++ b/mypy/typeshed/stdlib/pstats.pyi @@ -1,9 +1,10 @@ import sys from _typeshed import Self, StrOrBytesPath +from collections.abc import Iterable from cProfile import Profile as _cProfile from profile import Profile -from typing import IO, Any, Iterable, overload -from typing_extensions import Literal +from typing import IO, Any, overload +from typing_extensions import Literal, TypeAlias if sys.version_info >= (3, 9): __all__ = ["Stats", "SortKey", "FunctionProfile", "StatsProfile"] @@ -12,7 +13,7 @@ elif sys.version_info >= (3, 7): else: __all__ = ["Stats"] -_Selector = str | float | int +_Selector: TypeAlias = str | float | int if sys.version_info >= (3, 7): from enum import Enum @@ -45,7 +46,7 @@ if sys.version_info >= (3, 9): total_tt: float func_profiles: dict[str, FunctionProfile] -_SortArgDict = dict[str, tuple[tuple[tuple[int, int], ...], str]] +_SortArgDict: TypeAlias = dict[str, tuple[tuple[tuple[int, int], ...], str]] class Stats: sort_arg_dict_default: _SortArgDict diff --git a/mypy/typeshed/stdlib/pty.pyi b/mypy/typeshed/stdlib/pty.pyi index 73c6ddfbd0c4e..a6a2d8fabb693 100644 --- a/mypy/typeshed/stdlib/pty.pyi +++ b/mypy/typeshed/stdlib/pty.pyi @@ -1,10 +1,10 @@ import sys -from typing import Callable, Iterable -from typing_extensions import Literal +from collections.abc import Callable, Iterable +from typing_extensions import Literal, TypeAlias if sys.platform != "win32": __all__ = ["openpty", "fork", "spawn"] - _Reader = Callable[[int], bytes] + _Reader: TypeAlias = Callable[[int], bytes] STDIN_FILENO: Literal[0] STDOUT_FILENO: Literal[1] diff --git a/mypy/typeshed/stdlib/pydoc.pyi b/mypy/typeshed/stdlib/pydoc.pyi index b4fa66c601558..6e5d3e818f838 100644 --- a/mypy/typeshed/stdlib/pydoc.pyi +++ b/mypy/typeshed/stdlib/pydoc.pyi @@ -1,14 +1,13 @@ -from _typeshed import SupportsWrite +from _typeshed import OptExcInfo, SupportsWrite from abc import abstractmethod +from builtins import list as _list # "list" conflicts with method name +from collections.abc import Callable, Container, Mapping, MutableMapping from reprlib import Repr from types import MethodType, ModuleType, TracebackType -from typing import IO, Any, AnyStr, Callable, Container, Mapping, MutableMapping, NoReturn, TypeVar +from typing import IO, Any, AnyStr, NoReturn, TypeVar __all__ = ["help"] -# the return type of sys.exc_info(), used by ErrorDuringImport.__init__ -_Exc_Info = tuple[type[BaseException] | None, BaseException | None, TracebackType | None] - _T = TypeVar("_T") __author__: str @@ -36,7 +35,7 @@ class ErrorDuringImport(Exception): exc: type[BaseException] | None value: BaseException | None tb: TracebackType | None - def __init__(self, filename: str, exc_info: _Exc_Info) -> None: ... + def __init__(self, filename: str, exc_info: OptExcInfo) -> None: ... def importfile(path: str) -> ModuleType: ... def safeimport(path: str, forceload: bool = ..., cache: MutableMapping[str, ModuleType] = ...) -> ModuleType: ... @@ -195,8 +194,6 @@ def doc(thing: str | object, title: str = ..., forceload: bool = ..., output: Su def writedoc(thing: str | object, forceload: bool = ...) -> None: ... def writedocs(dir: str, pkgpath: str = ..., done: Any | None = ...) -> None: ... -_list = list # "list" conflicts with method name - class Helper: keywords: dict[str, str | tuple[str, str]] symbols: dict[str, str] diff --git a/mypy/typeshed/stdlib/pyexpat/__init__.pyi b/mypy/typeshed/stdlib/pyexpat/__init__.pyi index 24c93965b21f2..2fe76a3d61b6f 100644 --- a/mypy/typeshed/stdlib/pyexpat/__init__.pyi +++ b/mypy/typeshed/stdlib/pyexpat/__init__.pyi @@ -1,8 +1,9 @@ import pyexpat.errors as errors import pyexpat.model as model from _typeshed import SupportsRead -from typing import Any, Callable -from typing_extensions import final +from collections.abc import Callable +from typing import Any +from typing_extensions import TypeAlias, final EXPAT_VERSION: str # undocumented version_info: tuple[int, int, int] # undocumented @@ -20,7 +21,7 @@ XML_PARAM_ENTITY_PARSING_NEVER: int XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE: int XML_PARAM_ENTITY_PARSING_ALWAYS: int -_Model = tuple[int, int, str | None, tuple[Any, ...]] +_Model: TypeAlias = tuple[int, int, str | None, tuple[Any, ...]] @final class XMLParserType: diff --git a/mypy/typeshed/stdlib/random.pyi b/mypy/typeshed/stdlib/random.pyi index 612a54cb95b03..255436dc377d8 100644 --- a/mypy/typeshed/stdlib/random.pyi +++ b/mypy/typeshed/stdlib/random.pyi @@ -89,7 +89,10 @@ class Random(_random.Random): cum_weights: Sequence[float | Fraction] | None = ..., k: int = ..., ) -> list[_T]: ... - def shuffle(self, x: MutableSequence[Any], random: Callable[[], float] | None = ...) -> None: ... + if sys.version_info >= (3, 11): + def shuffle(self, x: MutableSequence[Any]) -> None: ... + else: + def shuffle(self, x: MutableSequence[Any], random: Callable[[], float] | None = ...) -> None: ... if sys.version_info >= (3, 11): def sample(self, population: Sequence[_T], k: int, *, counts: Iterable[int] | None = ...) -> list[_T]: ... elif sys.version_info >= (3, 9): diff --git a/mypy/typeshed/stdlib/re.pyi b/mypy/typeshed/stdlib/re.pyi index 57dab8eb820f4..ff2a55fb4e616 100644 --- a/mypy/typeshed/stdlib/re.pyi +++ b/mypy/typeshed/stdlib/re.pyi @@ -1,8 +1,10 @@ import enum import sre_compile import sys +from collections.abc import Callable, Iterator from sre_constants import error as error -from typing import Any, AnyStr, Callable, Iterator, overload +from typing import Any, AnyStr, overload +from typing_extensions import TypeAlias # ----- re variables and constants ----- if sys.version_info >= (3, 7): @@ -147,7 +149,7 @@ T = RegexFlag.T TEMPLATE = RegexFlag.TEMPLATE if sys.version_info >= (3, 11): NOFLAG = RegexFlag.NOFLAG -_FlagsType = int | RegexFlag +_FlagsType: TypeAlias = int | RegexFlag if sys.version_info < (3, 7): # undocumented diff --git a/mypy/typeshed/stdlib/readline.pyi b/mypy/typeshed/stdlib/readline.pyi index df08a3cc25ff6..ceca2e32f2216 100644 --- a/mypy/typeshed/stdlib/readline.pyi +++ b/mypy/typeshed/stdlib/readline.pyi @@ -1,10 +1,11 @@ import sys from _typeshed import StrOrBytesPath -from typing import Callable, Sequence +from collections.abc import Callable, Sequence +from typing_extensions import TypeAlias if sys.platform != "win32": - _Completer = Callable[[str, int], str | None] - _CompDisp = Callable[[str, Sequence[str], int], None] + _Completer: TypeAlias = Callable[[str, int], str | None] + _CompDisp: TypeAlias = Callable[[str, Sequence[str], int], None] def parse_and_bind(__string: str) -> None: ... def read_init_file(__filename: StrOrBytesPath | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/reprlib.pyi b/mypy/typeshed/stdlib/reprlib.pyi index 2d114a7c4f26c..d5554344c494f 100644 --- a/mypy/typeshed/stdlib/reprlib.pyi +++ b/mypy/typeshed/stdlib/reprlib.pyi @@ -1,10 +1,12 @@ from array import array from collections import deque -from typing import Any, Callable +from collections.abc import Callable +from typing import Any +from typing_extensions import TypeAlias __all__ = ["Repr", "repr", "recursive_repr"] -_ReprFunc = Callable[[Any], str] +_ReprFunc: TypeAlias = Callable[[Any], str] def recursive_repr(fillvalue: str = ...) -> Callable[[_ReprFunc], _ReprFunc]: ... diff --git a/mypy/typeshed/stdlib/sched.pyi b/mypy/typeshed/stdlib/sched.pyi index dff781b0c1763..709d6f47ff65c 100644 --- a/mypy/typeshed/stdlib/sched.pyi +++ b/mypy/typeshed/stdlib/sched.pyi @@ -1,5 +1,6 @@ import sys -from typing import Any, Callable, NamedTuple +from collections.abc import Callable +from typing import Any, NamedTuple __all__ = ["scheduler"] diff --git a/mypy/typeshed/stdlib/select.pyi b/mypy/typeshed/stdlib/select.pyi index d4a3656e110e9..7cfea9ea0fc1e 100644 --- a/mypy/typeshed/stdlib/select.pyi +++ b/mypy/typeshed/stdlib/select.pyi @@ -1,7 +1,8 @@ import sys from _typeshed import FileDescriptorLike, Self +from collections.abc import Iterable from types import TracebackType -from typing import Any, Iterable +from typing import Any from typing_extensions import final if sys.platform != "win32": diff --git a/mypy/typeshed/stdlib/selectors.pyi b/mypy/typeshed/stdlib/selectors.pyi index 23a94a29a74d2..95dfaa41a5c08 100644 --- a/mypy/typeshed/stdlib/selectors.pyi +++ b/mypy/typeshed/stdlib/selectors.pyi @@ -1,9 +1,11 @@ import sys from _typeshed import FileDescriptor, FileDescriptorLike, Self from abc import ABCMeta, abstractmethod -from typing import Any, Mapping, NamedTuple +from collections.abc import Mapping +from typing import Any, NamedTuple +from typing_extensions import TypeAlias -_EventMask = int +_EventMask: TypeAlias = int EVENT_READ: _EventMask EVENT_WRITE: _EventMask diff --git a/mypy/typeshed/stdlib/shlex.pyi b/mypy/typeshed/stdlib/shlex.pyi index 6385011575a47..fe0f80ba26c15 100644 --- a/mypy/typeshed/stdlib/shlex.pyi +++ b/mypy/typeshed/stdlib/shlex.pyi @@ -1,6 +1,7 @@ import sys from _typeshed import Self -from typing import Iterable, TextIO +from collections.abc import Iterable +from typing import TextIO if sys.version_info >= (3, 8): __all__ = ["shlex", "split", "quote", "join"] diff --git a/mypy/typeshed/stdlib/shutil.pyi b/mypy/typeshed/stdlib/shutil.pyi index 5fa5f6669f1b1..b367a46fe5722 100644 --- a/mypy/typeshed/stdlib/shutil.pyi +++ b/mypy/typeshed/stdlib/shutil.pyi @@ -1,7 +1,9 @@ import os import sys from _typeshed import BytesPath, StrOrBytesPath, StrPath, SupportsRead, SupportsWrite -from typing import Any, AnyStr, Callable, Iterable, NamedTuple, Sequence, TypeVar, overload +from collections.abc import Callable, Iterable, Sequence +from typing import Any, AnyStr, NamedTuple, TypeVar, overload +from typing_extensions import TypeAlias __all__ = [ "copyfileobj", @@ -36,7 +38,7 @@ _StrOrBytesPathT = TypeVar("_StrOrBytesPathT", bound=StrOrBytesPath) _StrPathT = TypeVar("_StrPathT", bound=StrPath) # Return value of some functions that may either return a path-like object that was passed in or # a string -_PathReturn = Any +_PathReturn: TypeAlias = Any class Error(OSError): ... class SameFileError(Error): ... @@ -82,7 +84,7 @@ else: def rmtree(path: StrOrBytesPath, ignore_errors: bool = ..., onerror: Callable[[Any, Any, Any], Any] | None = ...) -> None: ... -_CopyFn = Callable[[str, str], None] | Callable[[StrPath, StrPath], None] +_CopyFn: TypeAlias = Callable[[str, str], None] | Callable[[StrPath, StrPath], None] # N.B. shutil.move appears to take bytes arguments, however, # this does not work when dst is (or is within) an existing directory. diff --git a/mypy/typeshed/stdlib/signal.pyi b/mypy/typeshed/stdlib/signal.pyi index 2defe79959913..893d9d45e4b19 100644 --- a/mypy/typeshed/stdlib/signal.pyi +++ b/mypy/typeshed/stdlib/signal.pyi @@ -1,9 +1,10 @@ import sys from _typeshed import structseq +from collections.abc import Callable, Iterable from enum import IntEnum from types import FrameType -from typing import Any, Callable, Iterable, Union -from typing_extensions import Final, final +from typing import Any, Union +from typing_extensions import Final, TypeAlias, final NSIG: int @@ -60,8 +61,8 @@ class Handlers(IntEnum): SIG_DFL: Handlers SIG_IGN: Handlers -_SIGNUM = int | Signals -_HANDLER = Union[Callable[[int, FrameType | None], Any], int, Handlers, None] +_SIGNUM: TypeAlias = int | Signals +_HANDLER: TypeAlias = Union[Callable[[int, FrameType | None], Any], int, Handlers, None] def default_int_handler(__signalnum: int, __frame: FrameType | None) -> None: ... diff --git a/mypy/typeshed/stdlib/site.pyi b/mypy/typeshed/stdlib/site.pyi index a73d188a7e5cf..53199db0eaf32 100644 --- a/mypy/typeshed/stdlib/site.pyi +++ b/mypy/typeshed/stdlib/site.pyi @@ -1,5 +1,5 @@ from _typeshed import StrPath -from typing import Iterable +from collections.abc import Iterable PREFIXES: list[str] ENABLE_USER_SITE: bool | None diff --git a/mypy/typeshed/stdlib/smtpd.pyi b/mypy/typeshed/stdlib/smtpd.pyi index 037f62a8d6e1b..fc5a1cb62b16d 100644 --- a/mypy/typeshed/stdlib/smtpd.pyi +++ b/mypy/typeshed/stdlib/smtpd.pyi @@ -4,13 +4,14 @@ import socket import sys from collections import defaultdict from typing import Any +from typing_extensions import TypeAlias if sys.version_info >= (3, 11): __all__ = ["SMTPChannel", "SMTPServer", "DebuggingServer", "PureProxy"] else: __all__ = ["SMTPChannel", "SMTPServer", "DebuggingServer", "PureProxy", "MailmanProxy"] -_Address = tuple[str, int] # (host, port) +_Address: TypeAlias = tuple[str, int] # (host, port) class SMTPChannel(asynchat.async_chat): COMMAND: int diff --git a/mypy/typeshed/stdlib/smtplib.pyi b/mypy/typeshed/stdlib/smtplib.pyi index 3136667dcd119..d90c744c504ac 100644 --- a/mypy/typeshed/stdlib/smtplib.pyi +++ b/mypy/typeshed/stdlib/smtplib.pyi @@ -1,10 +1,12 @@ import sys from _typeshed import Self +from collections.abc import Sequence from email.message import Message as _Message from socket import socket from ssl import SSLContext from types import TracebackType -from typing import Any, Pattern, Protocol, Sequence, overload +from typing import Any, Pattern, Protocol, overload +from typing_extensions import TypeAlias if sys.version_info >= (3, 7): __all__ = [ @@ -40,10 +42,10 @@ else: "SMTP_SSL", ] -_Reply = tuple[int, bytes] -_SendErrs = dict[str, _Reply] +_Reply: TypeAlias = tuple[int, bytes] +_SendErrs: TypeAlias = dict[str, _Reply] # Should match source_address for socket.create_connection -_SourceAddress = tuple[bytearray | bytes | str, int] +_SourceAddress: TypeAlias = tuple[bytearray | bytes | str, int] SMTP_PORT: int SMTP_SSL_PORT: int diff --git a/mypy/typeshed/stdlib/socketserver.pyi b/mypy/typeshed/stdlib/socketserver.pyi index 9bdd8ccfe31f7..20ff5daa718ea 100644 --- a/mypy/typeshed/stdlib/socketserver.pyi +++ b/mypy/typeshed/stdlib/socketserver.pyi @@ -1,8 +1,10 @@ import sys import types from _typeshed import Self +from collections.abc import Callable from socket import socket as _socket -from typing import Any, BinaryIO, Callable, ClassVar, Union +from typing import Any, BinaryIO, ClassVar, Union +from typing_extensions import TypeAlias if sys.platform == "win32": __all__ = [ @@ -36,8 +38,8 @@ else: "ThreadingUnixDatagramServer", ] -_RequestType = Union[_socket, tuple[bytes, _socket]] -_AddressType = Union[tuple[str, int], str] +_RequestType: TypeAlias = Union[_socket, tuple[bytes, _socket]] +_AddressType: TypeAlias = Union[tuple[str, int], str] # This can possibly be generic at some point: class BaseServer: diff --git a/mypy/typeshed/stdlib/sqlite3/dbapi2.pyi b/mypy/typeshed/stdlib/sqlite3/dbapi2.pyi index 05e5a176d8ff2..87e843c5fb266 100644 --- a/mypy/typeshed/stdlib/sqlite3/dbapi2.pyi +++ b/mypy/typeshed/stdlib/sqlite3/dbapi2.pyi @@ -1,11 +1,23 @@ +import sqlite3 import sys -from _typeshed import Self, StrOrBytesPath +from _typeshed import ReadableBuffer, Self, StrOrBytesPath, SupportsLenAndGetItem +from collections.abc import Callable, Generator, Iterable, Iterator, Mapping from datetime import date, datetime, time from types import TracebackType -from typing import Any, Callable, Generator, Iterable, Iterator, Protocol, TypeVar -from typing_extensions import Literal, final +from typing import Any, Generic, Protocol, TypeVar, overload +from typing_extensions import Literal, SupportsIndex, TypeAlias, final _T = TypeVar("_T") +_T_co = TypeVar("_T_co", covariant=True) +_CursorT = TypeVar("_CursorT", bound=Cursor) +_SqliteData: TypeAlias = str | ReadableBuffer | int | float | None +# Data that is passed through adapters can be of any type accepted by an adapter. +_AdaptedInputData: TypeAlias = _SqliteData | Any +# The Mapping must really be a dict, but making it invariant is too annoying. +_Parameters: TypeAlias = SupportsLenAndGetItem[_AdaptedInputData] | Mapping[str, _AdaptedInputData] +_SqliteOutputData: TypeAlias = str | bytes | int | float | None +_Adapter: TypeAlias = Callable[[_T], _SqliteData] +_Converter: TypeAlias = Callable[[bytes], Any] paramstyle: str threadsafety: int @@ -80,43 +92,144 @@ if sys.version_info >= (3, 7): SQLITE_SELECT: int SQLITE_TRANSACTION: int SQLITE_UPDATE: int -adapters: Any -converters: Any +adapters: dict[tuple[type[Any], type[Any]], _Adapter[Any]] +converters: dict[str, _Converter] sqlite_version: str version: str -# TODO: adapt needs to get probed -def adapt(obj, protocol, alternate): ... +if sys.version_info >= (3, 11): + SQLITE_ABORT: int + SQLITE_ABORT_ROLLBACK: int + SQLITE_AUTH: int + SQLITE_AUTH_USER: int + SQLITE_BUSY: int + SQLITE_BUSY_RECOVERY: int + SQLITE_BUSY_SNAPSHOT: int + SQLITE_BUSY_TIMEOUT: int + SQLITE_CANTOPEN: int + SQLITE_CANTOPEN_CONVPATH: int + SQLITE_CANTOPEN_DIRTYWAL: int + SQLITE_CANTOPEN_FULLPATH: int + SQLITE_CANTOPEN_ISDIR: int + SQLITE_CANTOPEN_NOTEMPDIR: int + SQLITE_CANTOPEN_SYMLINK: int + SQLITE_CONSTRAINT: int + SQLITE_CONSTRAINT_CHECK: int + SQLITE_CONSTRAINT_COMMITHOOK: int + SQLITE_CONSTRAINT_FOREIGNKEY: int + SQLITE_CONSTRAINT_FUNCTION: int + SQLITE_CONSTRAINT_NOTNULL: int + SQLITE_CONSTRAINT_PINNED: int + SQLITE_CONSTRAINT_PRIMARYKEY: int + SQLITE_CONSTRAINT_ROWID: int + SQLITE_CONSTRAINT_TRIGGER: int + SQLITE_CONSTRAINT_UNIQUE: int + SQLITE_CONSTRAINT_VTAB: int + SQLITE_CORRUPT: int + SQLITE_CORRUPT_INDEX: int + SQLITE_CORRUPT_SEQUENCE: int + SQLITE_CORRUPT_VTAB: int + SQLITE_EMPTY: int + SQLITE_ERROR: int + SQLITE_ERROR_MISSING_COLLSEQ: int + SQLITE_ERROR_RETRY: int + SQLITE_ERROR_SNAPSHOT: int + SQLITE_FORMAT: int + SQLITE_FULL: int + SQLITE_INTERNAL: int + SQLITE_INTERRUPT: int + SQLITE_IOERR: int + SQLITE_IOERR_ACCESS: int + SQLITE_IOERR_AUTH: int + SQLITE_IOERR_BEGIN_ATOMIC: int + SQLITE_IOERR_BLOCKED: int + SQLITE_IOERR_CHECKRESERVEDLOCK: int + SQLITE_IOERR_CLOSE: int + SQLITE_IOERR_COMMIT_ATOMIC: int + SQLITE_IOERR_CONVPATH: int + SQLITE_IOERR_CORRUPTFS: int + SQLITE_IOERR_DATA: int + SQLITE_IOERR_DELETE: int + SQLITE_IOERR_DELETE_NOENT: int + SQLITE_IOERR_DIR_CLOSE: int + SQLITE_IOERR_DIR_FSYNC: int + SQLITE_IOERR_FSTAT: int + SQLITE_IOERR_FSYNC: int + SQLITE_IOERR_GETTEMPPATH: int + SQLITE_IOERR_LOCK: int + SQLITE_IOERR_MMAP: int + SQLITE_IOERR_NOMEM: int + SQLITE_IOERR_RDLOCK: int + SQLITE_IOERR_READ: int + SQLITE_IOERR_ROLLBACK_ATOMIC: int + SQLITE_IOERR_SEEK: int + SQLITE_IOERR_SHMLOCK: int + SQLITE_IOERR_SHMMAP: int + SQLITE_IOERR_SHMOPEN: int + SQLITE_IOERR_SHMSIZE: int + SQLITE_IOERR_SHORT_READ: int + SQLITE_IOERR_TRUNCATE: int + SQLITE_IOERR_UNLOCK: int + SQLITE_IOERR_VNODE: int + SQLITE_IOERR_WRITE: int + SQLITE_LOCKED: int + SQLITE_LOCKED_SHAREDCACHE: int + SQLITE_LOCKED_VTAB: int + SQLITE_MISMATCH: int + SQLITE_MISUSE: int + SQLITE_NOLFS: int + SQLITE_NOMEM: int + SQLITE_NOTADB: int + SQLITE_NOTFOUND: int + SQLITE_NOTICE: int + SQLITE_NOTICE_RECOVER_ROLLBACK: int + SQLITE_NOTICE_RECOVER_WAL: int + SQLITE_OK_LOAD_PERMANENTLY: int + SQLITE_OK_SYMLINK: int + SQLITE_PERM: int + SQLITE_PROTOCOL: int + SQLITE_RANGE: int + SQLITE_READONLY: int + SQLITE_READONLY_CANTINIT: int + SQLITE_READONLY_CANTLOCK: int + SQLITE_READONLY_DBMOVED: int + SQLITE_READONLY_DIRECTORY: int + SQLITE_READONLY_RECOVERY: int + SQLITE_READONLY_ROLLBACK: int + SQLITE_ROW: int + SQLITE_SCHEMA: int + SQLITE_TOOBIG: int + SQLITE_WARNING: int + SQLITE_WARNING_AUTOINDEX: int + +# Can take or return anything depending on what's in the registry. +@overload +def adapt(__obj: Any, __proto: Any) -> Any: ... +@overload +def adapt(__obj: Any, __proto: Any, __alt: _T) -> Any | _T: ... def complete_statement(statement: str) -> bool: ... if sys.version_info >= (3, 7): - def connect( - database: StrOrBytesPath, - timeout: float = ..., - detect_types: int = ..., - isolation_level: str | None = ..., - check_same_thread: bool = ..., - factory: type[Connection] | None = ..., - cached_statements: int = ..., - uri: bool = ..., - ) -> Connection: ... - + _DatabaseArg: TypeAlias = StrOrBytesPath else: - def connect( - database: bytes | str, - timeout: float = ..., - detect_types: int = ..., - isolation_level: str | None = ..., - check_same_thread: bool = ..., - factory: type[Connection] | None = ..., - cached_statements: int = ..., - uri: bool = ..., - ) -> Connection: ... + _DatabaseArg: TypeAlias = bytes | str +def connect( + database: _DatabaseArg, + timeout: float = ..., + detect_types: int = ..., + isolation_level: str | None = ..., + check_same_thread: bool = ..., + factory: type[Connection] | None = ..., + cached_statements: int = ..., + uri: bool = ..., +) -> Connection: ... def enable_callback_tracebacks(__enable: bool) -> None: ... + +# takes a pos-or-keyword argument because there is a C wrapper def enable_shared_cache(enable: int) -> None: ... -def register_adapter(__type: type[_T], __caster: Callable[[_T], int | float | str | bytes]) -> None: ... -def register_converter(__name: str, __converter: Callable[[bytes], Any]) -> None: ... +def register_adapter(__type: type[_T], __caster: _Adapter[_T]) -> None: ... +def register_converter(__name: str, __converter: _Converter) -> None: ... if sys.version_info < (3, 8): class Cache: @@ -125,40 +238,104 @@ if sys.version_info < (3, 8): def get(self, *args, **kwargs) -> None: ... class _AggregateProtocol(Protocol): - def step(self, value: int) -> None: ... + def step(self, __value: int) -> object: ... def finalize(self) -> int: ... +class _SingleParamWindowAggregateClass(Protocol): + def step(self, __param: Any) -> object: ... + def inverse(self, __param: Any) -> object: ... + def value(self) -> _SqliteData: ... + def finalize(self) -> _SqliteData: ... + +class _AnyParamWindowAggregateClass(Protocol): + def step(self, *args: Any) -> object: ... + def inverse(self, *args: Any) -> object: ... + def value(self) -> _SqliteData: ... + def finalize(self) -> _SqliteData: ... + +class _WindowAggregateClass(Protocol): + step: Callable[..., object] + inverse: Callable[..., object] + def value(self) -> _SqliteData: ... + def finalize(self) -> _SqliteData: ... + class Connection: - DataError: Any - DatabaseError: Any - Error: Any - IntegrityError: Any - InterfaceError: Any - InternalError: Any - NotSupportedError: Any - OperationalError: Any - ProgrammingError: Any - Warning: Any - in_transaction: Any - isolation_level: Any + @property + def DataError(self) -> type[sqlite3.DataError]: ... + @property + def DatabaseError(self) -> type[sqlite3.DatabaseError]: ... + @property + def Error(self) -> type[sqlite3.Error]: ... + @property + def IntegrityError(self) -> type[sqlite3.IntegrityError]: ... + @property + def InterfaceError(self) -> type[sqlite3.InterfaceError]: ... + @property + def InternalError(self) -> type[sqlite3.InternalError]: ... + @property + def NotSupportedError(self) -> type[sqlite3.NotSupportedError]: ... + @property + def OperationalError(self) -> type[sqlite3.OperationalError]: ... + @property + def ProgrammingError(self) -> type[sqlite3.ProgrammingError]: ... + @property + def Warning(self) -> type[sqlite3.Warning]: ... + @property + def in_transaction(self) -> bool: ... + isolation_level: str | None # one of '', 'DEFERRED', 'IMMEDIATE' or 'EXCLUSIVE' + @property + def total_changes(self) -> int: ... row_factory: Any text_factory: Any - total_changes: Any - def __init__(self, *args: Any, **kwargs: Any) -> None: ... + def __init__( + self, + database: _DatabaseArg, + timeout: float = ..., + detect_types: int = ..., + isolation_level: str | None = ..., + check_same_thread: bool = ..., + factory: type[Connection] | None = ..., + cached_statements: int = ..., + uri: bool = ..., + ) -> None: ... def close(self) -> None: ... + if sys.version_info >= (3, 11): + def blobopen(self, __table: str, __column: str, __row: int, *, readonly: bool = ..., name: str = ...) -> Blob: ... + def commit(self) -> None: ... def create_aggregate(self, name: str, n_arg: int, aggregate_class: Callable[[], _AggregateProtocol]) -> None: ... - def create_collation(self, __name: str, __callback: Any) -> None: ... + if sys.version_info >= (3, 11): + # num_params determines how many params will be passed to the aggregate class. We provide an overload + # for the case where num_params = 1, which is expected to be the common case. + @overload + def create_window_function( + self, __name: str, __num_params: Literal[1], __aggregate_class: Callable[[], _SingleParamWindowAggregateClass] | None + ) -> None: ... + # And for num_params = -1, which means the aggregate must accept any number of parameters. + @overload + def create_window_function( + self, __name: str, __num_params: Literal[-1], __aggregate_class: Callable[[], _AnyParamWindowAggregateClass] | None + ) -> None: ... + @overload + def create_window_function( + self, __name: str, __num_params: int, __aggregate_class: Callable[[], _WindowAggregateClass] | None + ) -> None: ... + + def create_collation(self, __name: str, __callback: Callable[[str, str], int | SupportsIndex] | None) -> None: ... if sys.version_info >= (3, 8): - def create_function(self, name: str, narg: int, func: Any, *, deterministic: bool = ...) -> None: ... + def create_function( + self, name: str, narg: int, func: Callable[..., _SqliteData], *, deterministic: bool = ... + ) -> None: ... else: - def create_function(self, name: str, num_params: int, func: Any) -> None: ... + def create_function(self, name: str, num_params: int, func: Callable[..., _SqliteData]) -> None: ... - def cursor(self, cursorClass: type | None = ...) -> Cursor: ... - def execute(self, sql: str, parameters: Iterable[Any] = ...) -> Cursor: ... - # TODO: please check in executemany() if seq_of_parameters type is possible like this - def executemany(self, __sql: str, __parameters: Iterable[Iterable[Any]]) -> Cursor: ... - def executescript(self, __sql_script: bytes | str) -> Cursor: ... + @overload + def cursor(self, cursorClass: None = ...) -> Cursor: ... + @overload + def cursor(self, cursorClass: Callable[[], _CursorT]) -> _CursorT: ... + def execute(self, sql: str, parameters: _Parameters = ...) -> Cursor: ... + def executemany(self, __sql: str, __parameters: Iterable[_Parameters]) -> Cursor: ... + def executescript(self, __sql_script: str) -> Cursor: ... def interrupt(self) -> None: ... def iterdump(self) -> Generator[str, None, None]: ... def rollback(self) -> None: ... @@ -169,8 +346,8 @@ class Connection: def set_trace_callback(self, trace_callback: Callable[[str], object] | None) -> None: ... # enable_load_extension and load_extension is not available on python distributions compiled # without sqlite3 loadable extension support. see footnotes https://docs.python.org/3/library/sqlite3.html#f1 - def enable_load_extension(self, enabled: bool) -> None: ... - def load_extension(self, path: str) -> None: ... + def enable_load_extension(self, __enabled: bool) -> None: ... + def load_extension(self, __name: str) -> None: ... if sys.version_info >= (3, 7): def backup( self, @@ -181,30 +358,38 @@ class Connection: name: str = ..., sleep: float = ..., ) -> None: ... + if sys.version_info >= (3, 11): + def setlimit(self, __category: int, __limit: int) -> int: ... + def getlimit(self, __category: int) -> int: ... + def serialize(self, *, name: str = ...) -> bytes: ... + def deserialize(self, __data: ReadableBuffer, *, name: str = ...) -> None: ... - def __call__(self, *args: Any, **kwargs: Any) -> Any: ... + def __call__(self, __sql: str) -> _Statement: ... def __enter__(self: Self) -> Self: ... def __exit__( self, __type: type[BaseException] | None, __value: BaseException | None, __traceback: TracebackType | None ) -> Literal[False]: ... class Cursor(Iterator[Any]): - arraysize: Any - connection: Any - description: Any - lastrowid: Any - row_factory: Any - rowcount: int - # TODO: Cursor class accepts exactly 1 argument - # required type is sqlite3.Connection (which is imported as _Connection) - # however, the name of the __init__ variable is unknown - def __init__(self, *args: Any, **kwargs: Any) -> None: ... + arraysize: int + @property + def connection(self) -> Connection: ... + @property + def description(self) -> tuple[tuple[str, None, None, None, None, None, None], ...] | None: ... + @property + def lastrowid(self) -> int | None: ... + row_factory: Callable[[Cursor, Row[Any]], object] | None + @property + def rowcount(self) -> int: ... + def __init__(self, __cursor: Connection) -> None: ... def close(self) -> None: ... - def execute(self, __sql: str, __parameters: Iterable[Any] = ...) -> Cursor: ... - def executemany(self, __sql: str, __seq_of_parameters: Iterable[Iterable[Any]]) -> Cursor: ... - def executescript(self, __sql_script: bytes | str) -> Cursor: ... + def execute(self: Self, __sql: str, __parameters: _Parameters = ...) -> Self: ... + def executemany(self: Self, __sql: str, __seq_of_parameters: Iterable[_Parameters]) -> Self: ... + def executescript(self, __sql_script: str) -> Cursor: ... def fetchall(self) -> list[Any]: ... def fetchmany(self, size: int | None = ...) -> list[Any]: ... + # Returns either a row (as created by the row_factory) or None, but + # putting None in the return annotation causes annoying false positives. def fetchone(self) -> Any: ... def setinputsizes(self, __sizes: object) -> None: ... # does nothing def setoutputsize(self, __size: object, __column: object = ...) -> None: ... # does nothing @@ -225,31 +410,53 @@ class InternalError(DatabaseError): ... class NotSupportedError(DatabaseError): ... class OperationalError(DatabaseError): ... -OptimizedUnicode = str +if sys.version_info < (3, 10): + OptimizedUnicode = str @final class PrepareProtocol: - def __init__(self, *args: Any, **kwargs: Any) -> None: ... + def __init__(self, *args: object, **kwargs: object) -> None: ... class ProgrammingError(DatabaseError): ... -class Row: - def __init__(self, *args: Any, **kwargs: Any) -> None: ... - def keys(self): ... - def __eq__(self, __other): ... - def __ge__(self, __other): ... - def __getitem__(self, __index): ... - def __gt__(self, __other): ... - def __hash__(self): ... - def __iter__(self): ... - def __le__(self, __other): ... - def __len__(self): ... - def __lt__(self, __other): ... - def __ne__(self, __other): ... +class Row(Generic[_T_co]): + def __init__(self, __cursor: Cursor, __data: tuple[_T_co, ...]) -> None: ... + def keys(self) -> list[str]: ... + @overload + def __getitem__(self, __index: int | str) -> _T_co: ... + @overload + def __getitem__(self, __index: slice) -> tuple[_T_co, ...]: ... + def __hash__(self) -> int: ... + def __iter__(self) -> Iterator[_T_co]: ... + def __len__(self) -> int: ... + # These return NotImplemented for anything that is not a Row. + def __eq__(self, __other: object) -> bool: ... + def __ge__(self, __other: object) -> bool: ... + def __gt__(self, __other: object) -> bool: ... + def __le__(self, __other: object) -> bool: ... + def __lt__(self, __other: object) -> bool: ... + def __ne__(self, __other: object) -> bool: ... -if sys.version_info < (3, 8): +if sys.version_info >= (3, 8): + @final + class _Statement: ... + +else: @final class Statement: def __init__(self, *args, **kwargs): ... + _Statement: TypeAlias = Statement class Warning(Exception): ... + +if sys.version_info >= (3, 11): + class Blob: + def close(self) -> None: ... + def read(self, __length: int = ...) -> bytes: ... + def write(self, __data: bytes) -> None: ... + def tell(self) -> int: ... + # whence must be one of os.SEEK_SET, os.SEEK_CUR, os.SEEK_END + def seek(self, __offset: int, __whence: int = ...) -> None: ... + def __len__(self) -> int: ... + def __enter__(self: Self) -> Self: ... + def __exit__(self, __typ: object, __val: object, __tb: object) -> Literal[False]: ... diff --git a/mypy/typeshed/stdlib/sre_parse.pyi b/mypy/typeshed/stdlib/sre_parse.pyi index 05e71c255967d..0958e73f5176e 100644 --- a/mypy/typeshed/stdlib/sre_parse.pyi +++ b/mypy/typeshed/stdlib/sre_parse.pyi @@ -1,7 +1,9 @@ import sys +from collections.abc import Iterable from sre_constants import * from sre_constants import _NamedIntConstant as _NIC, error as _Error -from typing import Any, Iterable, Match, Pattern as _Pattern, overload +from typing import Any, Match, Pattern as _Pattern, overload +from typing_extensions import TypeAlias SPECIAL_CHARS: str REPEAT_CHARS: str @@ -33,16 +35,16 @@ class _State: def checklookbehindgroup(self, gid: int, source: Tokenizer) -> None: ... if sys.version_info >= (3, 8): - State = _State + State: TypeAlias = _State else: - Pattern = _State + Pattern: TypeAlias = _State -_OpSubpatternType = tuple[int | None, int, int, SubPattern] -_OpGroupRefExistsType = tuple[int, SubPattern, SubPattern] -_OpInType = list[tuple[_NIC, int]] -_OpBranchType = tuple[None, list[SubPattern]] -_AvType = _OpInType | _OpBranchType | Iterable[SubPattern] | _OpGroupRefExistsType | _OpSubpatternType -_CodeType = tuple[_NIC, _AvType] +_OpSubpatternType: TypeAlias = tuple[int | None, int, int, SubPattern] +_OpGroupRefExistsType: TypeAlias = tuple[int, SubPattern, SubPattern] +_OpInType: TypeAlias = list[tuple[_NIC, int]] +_OpBranchType: TypeAlias = tuple[None, list[SubPattern]] +_AvType: TypeAlias = _OpInType | _OpBranchType | Iterable[SubPattern] | _OpGroupRefExistsType | _OpSubpatternType +_CodeType: TypeAlias = tuple[_NIC, _AvType] class SubPattern: data: list[_CodeType] @@ -87,8 +89,8 @@ class Tokenizer: def fix_flags(src: str | bytes, flags: int) -> int: ... -_TemplateType = tuple[list[tuple[int, int]], list[str | None]] -_TemplateByteType = tuple[list[tuple[int, int]], list[bytes | None]] +_TemplateType: TypeAlias = tuple[list[tuple[int, int]], list[str | None]] +_TemplateByteType: TypeAlias = tuple[list[tuple[int, int]], list[bytes | None]] if sys.version_info >= (3, 8): def parse(str: str, flags: int = ..., state: State | None = ...) -> SubPattern: ... @overload diff --git a/mypy/typeshed/stdlib/ssl.pyi b/mypy/typeshed/stdlib/ssl.pyi index b7fe6914db0ed..8445435fa3465 100644 --- a/mypy/typeshed/stdlib/ssl.pyi +++ b/mypy/typeshed/stdlib/ssl.pyi @@ -2,17 +2,18 @@ import enum import socket import sys from _typeshed import ReadableBuffer, Self, StrOrBytesPath, WriteableBuffer -from typing import Any, Callable, Iterable, NamedTuple, Union, overload -from typing_extensions import Literal, TypedDict, final - -_PCTRTT = tuple[tuple[str, str], ...] -_PCTRTTT = tuple[_PCTRTT, ...] -_PeerCertRetDictType = dict[str, str | _PCTRTTT | _PCTRTT] -_PeerCertRetType = _PeerCertRetDictType | bytes | None -_EnumRetType = list[tuple[bytes, str, set[str] | bool]] -_PasswordType = Union[Callable[[], str | bytes], str, bytes] - -_SrvnmeCbType = Callable[[SSLSocket | SSLObject, str | None, SSLSocket], int | None] +from collections.abc import Callable, Iterable +from typing import Any, NamedTuple, Union, overload +from typing_extensions import Literal, TypeAlias, TypedDict, final + +_PCTRTT: TypeAlias = tuple[tuple[str, str], ...] +_PCTRTTT: TypeAlias = tuple[_PCTRTT, ...] +_PeerCertRetDictType: TypeAlias = dict[str, str | _PCTRTTT | _PCTRTT] +_PeerCertRetType: TypeAlias = _PeerCertRetDictType | bytes | None +_EnumRetType: TypeAlias = list[tuple[bytes, str, set[str] | bool]] +_PasswordType: TypeAlias = Union[Callable[[], str | bytes], str, bytes] + +_SrvnmeCbType: TypeAlias = Callable[[SSLSocket | SSLObject, str | None, SSLSocket], int | None] class _Cipher(TypedDict): aead: bool diff --git a/mypy/typeshed/stdlib/statistics.pyi b/mypy/typeshed/stdlib/statistics.pyi index 446a778794f16..540ccfcaaa8cf 100644 --- a/mypy/typeshed/stdlib/statistics.pyi +++ b/mypy/typeshed/stdlib/statistics.pyi @@ -1,9 +1,10 @@ import sys from _typeshed import Self, SupportsRichComparisonT +from collections.abc import Hashable, Iterable, Sequence from decimal import Decimal from fractions import Fraction -from typing import Any, Hashable, Iterable, NamedTuple, Sequence, SupportsFloat, TypeVar -from typing_extensions import Literal +from typing import Any, NamedTuple, SupportsFloat, TypeVar +from typing_extensions import Literal, TypeAlias if sys.version_info >= (3, 10): __all__ = [ @@ -65,7 +66,7 @@ else: ] # Most functions in this module accept homogeneous collections of one of these types -_Number = float | Decimal | Fraction +_Number: TypeAlias = float | Decimal | Fraction _NumberT = TypeVar("_NumberT", float, Decimal, Fraction) # Used in mode, multimode diff --git a/mypy/typeshed/stdlib/string.pyi b/mypy/typeshed/stdlib/string.pyi index 535f38545132c..4404bde8bc4f4 100644 --- a/mypy/typeshed/stdlib/string.pyi +++ b/mypy/typeshed/stdlib/string.pyi @@ -1,6 +1,7 @@ import sys +from collections.abc import Iterable, Mapping, Sequence from re import RegexFlag -from typing import Any, Iterable, Mapping, Sequence +from typing import Any if sys.version_info >= (3, 8): from re import Pattern diff --git a/mypy/typeshed/stdlib/struct.pyi b/mypy/typeshed/stdlib/struct.pyi index 1f6c45a23c0a6..59c66ad2f1674 100644 --- a/mypy/typeshed/stdlib/struct.pyi +++ b/mypy/typeshed/stdlib/struct.pyi @@ -1,6 +1,7 @@ import sys from _typeshed import ReadableBuffer, WriteableBuffer -from typing import Any, Iterator +from collections.abc import Iterator +from typing import Any __all__ = ["calcsize", "pack", "pack_into", "unpack", "unpack_from", "iter_unpack", "Struct", "error"] diff --git a/mypy/typeshed/stdlib/subprocess.pyi b/mypy/typeshed/stdlib/subprocess.pyi index ced2e708f8ffd..98bbf7d33f904 100644 --- a/mypy/typeshed/stdlib/subprocess.pyi +++ b/mypy/typeshed/stdlib/subprocess.pyi @@ -1,8 +1,9 @@ import sys from _typeshed import Self, StrOrBytesPath +from collections.abc import Callable, Iterable, Mapping, Sequence from types import TracebackType -from typing import IO, Any, AnyStr, Callable, Generic, Iterable, Mapping, Sequence, TypeVar, overload -from typing_extensions import Literal +from typing import IO, Any, AnyStr, Generic, TypeVar, overload +from typing_extensions import Literal, TypeAlias if sys.version_info >= (3, 9): from types import GenericAlias @@ -102,18 +103,18 @@ else: # reveal_type(x) # bytes, based on the overloads # except TimeoutError as e: # reveal_type(e.cmd) # Any, but morally is _CMD -_FILE = None | int | IO[Any] -_TXT = bytes | str +_FILE: TypeAlias = None | int | IO[Any] +_TXT: TypeAlias = bytes | str if sys.version_info >= (3, 8): - _CMD = StrOrBytesPath | Sequence[StrOrBytesPath] + _CMD: TypeAlias = StrOrBytesPath | Sequence[StrOrBytesPath] else: # Python 3.6 doesn't support _CMD being a single PathLike. # See: https://bugs.python.org/issue31961 - _CMD = _TXT | Sequence[StrOrBytesPath] + _CMD: TypeAlias = _TXT | Sequence[StrOrBytesPath] if sys.platform == "win32": - _ENV = Mapping[str, str] + _ENV: TypeAlias = Mapping[str, str] else: - _ENV = Mapping[bytes, StrOrBytesPath] | Mapping[str, StrOrBytesPath] + _ENV: TypeAlias = Mapping[bytes, StrOrBytesPath] | Mapping[str, StrOrBytesPath] _T = TypeVar("_T") diff --git a/mypy/typeshed/stdlib/sunau.pyi b/mypy/typeshed/stdlib/sunau.pyi index 73aa8999caa10..5b21cb03d4a3f 100644 --- a/mypy/typeshed/stdlib/sunau.pyi +++ b/mypy/typeshed/stdlib/sunau.pyi @@ -1,9 +1,9 @@ import sys from _typeshed import Self from typing import IO, Any, NamedTuple, NoReturn, overload -from typing_extensions import Literal +from typing_extensions import Literal, TypeAlias -_File = str | IO[bytes] +_File: TypeAlias = str | IO[bytes] class Error(Exception): ... diff --git a/mypy/typeshed/stdlib/symtable.pyi b/mypy/typeshed/stdlib/symtable.pyi index 91e95270901ed..7a95fe5e445f0 100644 --- a/mypy/typeshed/stdlib/symtable.pyi +++ b/mypy/typeshed/stdlib/symtable.pyi @@ -1,5 +1,6 @@ import sys -from typing import Any, Sequence +from collections.abc import Sequence +from typing import Any __all__ = ["symtable", "SymbolTable", "Class", "Function", "Symbol"] diff --git a/mypy/typeshed/stdlib/sys.pyi b/mypy/typeshed/stdlib/sys.pyi index 4fca35a2c82d9..92b806e044209 100644 --- a/mypy/typeshed/stdlib/sys.pyi +++ b/mypy/typeshed/stdlib/sys.pyi @@ -1,18 +1,17 @@ import sys -from _typeshed import structseq +from _typeshed import OptExcInfo, structseq from builtins import object as _object +from collections.abc import AsyncGenerator, Callable, Coroutine, Sequence from importlib.abc import PathEntryFinder from importlib.machinery import ModuleSpec from io import TextIOWrapper from types import FrameType, ModuleType, TracebackType -from typing import Any, AsyncGenerator, Callable, Coroutine, NoReturn, Protocol, Sequence, TextIO, TypeVar, Union, overload -from typing_extensions import Literal, final +from typing import Any, NoReturn, Protocol, TextIO, TypeVar, overload +from typing_extensions import Literal, TypeAlias, final _T = TypeVar("_T") -# The following type alias are stub-only and do not exist during runtime -_ExcInfo = tuple[type[BaseException], BaseException, TracebackType] -_OptExcInfo = Union[_ExcInfo, tuple[None, None, None]] +_OptExcInfo: TypeAlias = OptExcInfo # TODO: obsolete, remove fall 2022 or later # Intentionally omits one deprecated and one optional method of `importlib.abc.MetaPathFinder` class _MetaPathFinder(Protocol): @@ -76,16 +75,16 @@ _xoptions: dict[Any, Any] # Type alias used as a mixin for structseq classes that cannot be instantiated at runtime # This can't be represented in the type system, so we just use `structseq[Any]` -_uninstantiable_structseq = structseq[Any] +_uninstantiable_structseq: TypeAlias = structseq[Any] flags: _flags if sys.version_info >= (3, 10): - _FlagTuple = tuple[int, int, int, int, int, int, int, int, int, int, int, int, int, bool, int, int] + _FlagTuple: TypeAlias = tuple[int, int, int, int, int, int, int, int, int, int, int, int, int, bool, int, int] elif sys.version_info >= (3, 7): - _FlagTuple = tuple[int, int, int, int, int, int, int, int, int, int, int, int, int, bool, int] + _FlagTuple: TypeAlias = tuple[int, int, int, int, int, int, int, int, int, int, int, int, int, bool, int] else: - _FlagTuple = tuple[int, int, int, int, int, int, int, int, int, int, int, int, int] + _FlagTuple: TypeAlias = tuple[int, int, int, int, int, int, int, int, int, int, int, int, int] @final class _flags(_uninstantiable_structseq, _FlagTuple): @@ -217,7 +216,7 @@ def _getframe(__depth: int = ...) -> FrameType: ... def _debugmallocstats() -> None: ... def __displayhook__(__value: object) -> None: ... def __excepthook__(__exctype: type[BaseException], __value: BaseException, __traceback: TracebackType | None) -> None: ... -def exc_info() -> _OptExcInfo: ... +def exc_info() -> OptExcInfo: ... # sys.exit() accepts an optional argument of anything printable def exit(__status: object = ...) -> NoReturn: ... @@ -237,12 +236,12 @@ def getsizeof(obj: object) -> int: ... def getsizeof(obj: object, default: int) -> int: ... def getswitchinterval() -> float: ... -_ProfileFunc = Callable[[FrameType, str, Any], Any] +_ProfileFunc: TypeAlias = Callable[[FrameType, str, Any], Any] def getprofile() -> _ProfileFunc | None: ... def setprofile(profilefunc: _ProfileFunc | None) -> None: ... -_TraceFunc = Callable[[FrameType, str, Any], Callable[[FrameType, str, Any], Any] | None] +_TraceFunc: TypeAlias = Callable[[FrameType, str, Any], Callable[[FrameType, str, Any], Any] | None] def gettrace() -> _TraceFunc | None: ... def settrace(tracefunc: _TraceFunc | None) -> None: ... @@ -309,7 +308,7 @@ if sys.version_info >= (3, 8): def addaudithook(hook: Callable[[str, tuple[Any, ...]], Any]) -> None: ... def audit(__event: str, *args: Any) -> None: ... -_AsyncgenHook = Callable[[AsyncGenerator[Any, Any]], None] | None +_AsyncgenHook: TypeAlias = Callable[[AsyncGenerator[Any, Any]], None] | None @final class _asyncgen_hooks(structseq[_AsyncgenHook], tuple[_AsyncgenHook, _AsyncgenHook]): @@ -330,6 +329,6 @@ if sys.version_info >= (3, 7): def set_coroutine_origin_tracking_depth(depth: int) -> None: ... if sys.version_info < (3, 8): - _CoroWrapper = Callable[[Coroutine[Any, Any, Any]], Any] + _CoroWrapper: TypeAlias = Callable[[Coroutine[Any, Any, Any]], Any] def set_coroutine_wrapper(__wrapper: _CoroWrapper) -> None: ... def get_coroutine_wrapper() -> _CoroWrapper: ... diff --git a/mypy/typeshed/stdlib/tabnanny.pyi b/mypy/typeshed/stdlib/tabnanny.pyi index 020100031c14c..8a8592f441242 100644 --- a/mypy/typeshed/stdlib/tabnanny.pyi +++ b/mypy/typeshed/stdlib/tabnanny.pyi @@ -1,5 +1,5 @@ from _typeshed import StrOrBytesPath -from typing import Iterable +from collections.abc import Iterable __all__ = ["check", "NannyNag", "process_tokens"] diff --git a/mypy/typeshed/stdlib/tarfile.pyi b/mypy/typeshed/stdlib/tarfile.pyi index 2837c46e1d217..364bcad0683fe 100644 --- a/mypy/typeshed/stdlib/tarfile.pyi +++ b/mypy/typeshed/stdlib/tarfile.pyi @@ -2,7 +2,7 @@ import bz2 import io import sys from _typeshed import Self, StrOrBytesPath, StrPath -from builtins import type as Type # alias to avoid name clashes with fields named "type" +from builtins import list as _list, type as Type # aliases to avoid name clashes with fields named "type" or "list" from collections.abc import Callable, Iterable, Iterator, Mapping from gzip import _ReadableFileobj as _GzipReadableFileobj, _WritableFileobj as _GzipWritableFileobj from types import TracebackType @@ -109,8 +109,6 @@ def open( class ExFileObject(io.BufferedReader): def __init__(self, tarfile: TarFile, tarinfo: TarInfo) -> None: ... -_list = list # conflicts with method name - class TarFile: OPEN_METH: Mapping[str, str] name: StrOrBytesPath | None diff --git a/mypy/typeshed/stdlib/telnetlib.pyi b/mypy/typeshed/stdlib/telnetlib.pyi index 359be6e497813..8edbd155f61c0 100644 --- a/mypy/typeshed/stdlib/telnetlib.pyi +++ b/mypy/typeshed/stdlib/telnetlib.pyi @@ -1,7 +1,8 @@ import socket from _typeshed import Self +from collections.abc import Callable, Sequence from types import TracebackType -from typing import Any, Callable, Match, Pattern, Sequence +from typing import Any, Match, Pattern __all__ = ["Telnet"] diff --git a/mypy/typeshed/stdlib/tempfile.pyi b/mypy/typeshed/stdlib/tempfile.pyi index 19a4dbee2ee7e..4f2b4a545ff7a 100644 --- a/mypy/typeshed/stdlib/tempfile.pyi +++ b/mypy/typeshed/stdlib/tempfile.pyi @@ -1,9 +1,10 @@ import os import sys from _typeshed import Self +from collections.abc import Iterable, Iterator from types import TracebackType -from typing import IO, Any, AnyStr, Generic, Iterable, Iterator, overload -from typing_extensions import Literal +from typing import IO, Any, AnyStr, Generic, overload +from typing_extensions import Literal, TypeAlias if sys.version_info >= (3, 9): from types import GenericAlias @@ -29,7 +30,7 @@ TMP_MAX: int tempdir: str | None template: str -_DirT = AnyStr | os.PathLike[AnyStr] +_DirT: TypeAlias = AnyStr | os.PathLike[AnyStr] if sys.version_info >= (3, 8): @overload diff --git a/mypy/typeshed/stdlib/termios.pyi b/mypy/typeshed/stdlib/termios.pyi index c6a90df31b591..b2423304b9302 100644 --- a/mypy/typeshed/stdlib/termios.pyi +++ b/mypy/typeshed/stdlib/termios.pyi @@ -1,9 +1,10 @@ import sys from _typeshed import FileDescriptorLike from typing import Any +from typing_extensions import TypeAlias if sys.platform != "win32": - _Attr = list[int | list[bytes | int]] + _Attr: TypeAlias = list[int | list[bytes | int]] # TODO constants not really documented B0: int diff --git a/mypy/typeshed/stdlib/textwrap.pyi b/mypy/typeshed/stdlib/textwrap.pyi index aeb1d87141bea..5a61dfedb380a 100644 --- a/mypy/typeshed/stdlib/textwrap.pyi +++ b/mypy/typeshed/stdlib/textwrap.pyi @@ -1,4 +1,5 @@ -from typing import Callable, Pattern +from collections.abc import Callable +from typing import Pattern __all__ = ["TextWrapper", "wrap", "fill", "dedent", "indent", "shorten"] diff --git a/mypy/typeshed/stdlib/threading.pyi b/mypy/typeshed/stdlib/threading.pyi index c3fa57fafa7cb..231018ca731a1 100644 --- a/mypy/typeshed/stdlib/threading.pyi +++ b/mypy/typeshed/stdlib/threading.pyi @@ -1,11 +1,13 @@ import sys +from collections.abc import Callable, Iterable, Mapping from types import FrameType, TracebackType -from typing import Any, Callable, Iterable, Mapping, TypeVar +from typing import Any, TypeVar +from typing_extensions import TypeAlias # TODO recursive type -_TF = Callable[[FrameType, str, Any], Callable[..., Any] | None] +_TF: TypeAlias = Callable[[FrameType, str, Any], Callable[..., Any] | None] -_PF = Callable[[FrameType, str, Any], None] +_PF: TypeAlias = Callable[[FrameType, str, Any], None] _T = TypeVar("_T") if sys.version_info >= (3, 10): diff --git a/mypy/typeshed/stdlib/time.pyi b/mypy/typeshed/stdlib/time.pyi index 25f8d7056cd87..cceb7c8ca8741 100644 --- a/mypy/typeshed/stdlib/time.pyi +++ b/mypy/typeshed/stdlib/time.pyi @@ -1,9 +1,9 @@ import sys from _typeshed import structseq from typing import Any, Protocol -from typing_extensions import Final, Literal, final +from typing_extensions import Final, Literal, TypeAlias, final -_TimeTuple = tuple[int, int, int, int, int, int, int, int, int] +_TimeTuple: TypeAlias = tuple[int, int, int, int, int, int, int, int, int] altzone: int daylight: int diff --git a/mypy/typeshed/stdlib/timeit.pyi b/mypy/typeshed/stdlib/timeit.pyi index bfaea728ff423..076b2c54f9916 100644 --- a/mypy/typeshed/stdlib/timeit.pyi +++ b/mypy/typeshed/stdlib/timeit.pyi @@ -1,9 +1,11 @@ -from typing import IO, Any, Callable, Sequence +from collections.abc import Callable, Sequence +from typing import IO, Any +from typing_extensions import TypeAlias __all__ = ["Timer", "timeit", "repeat", "default_timer"] -_Timer = Callable[[], float] -_Stmt = str | Callable[[], Any] +_Timer: TypeAlias = Callable[[], float] +_Stmt: TypeAlias = str | Callable[[], Any] default_timer: _Timer diff --git a/mypy/typeshed/stdlib/tkinter/__init__.pyi b/mypy/typeshed/stdlib/tkinter/__init__.pyi index 2a6172ba46a3a..66c52107067d4 100644 --- a/mypy/typeshed/stdlib/tkinter/__init__.pyi +++ b/mypy/typeshed/stdlib/tkinter/__init__.pyi @@ -1,12 +1,13 @@ import _tkinter import sys from _typeshed import StrOrBytesPath +from collections.abc import Callable, Mapping, Sequence from enum import Enum from tkinter.constants import * from tkinter.font import _FontDescription from types import TracebackType -from typing import Any, Callable, Generic, Mapping, Protocol, Sequence, TypeVar, Union, overload -from typing_extensions import Literal, TypedDict +from typing import Any, Generic, Protocol, TypeVar, Union, overload +from typing_extensions import Literal, TypeAlias, TypedDict if sys.version_info >= (3, 9): __all__ = [ @@ -171,29 +172,31 @@ EXCEPTION = _tkinter.EXCEPTION # Some widgets have an option named -compound that accepts different values # than the _Compound defined here. Many other options have similar things. -_Anchor = Literal["nw", "n", "ne", "w", "center", "e", "sw", "s", "se"] # manual page: Tk_GetAnchor -_Bitmap = str # manual page: Tk_GetBitmap -_ButtonCommand = str | Callable[[], Any] # accepts string of tcl code, return value is returned from Button.invoke() -_CanvasItemId = int -_Color = str # typically '#rrggbb', '#rgb' or color names. -_Compound = Literal["top", "left", "center", "right", "bottom", "none"] # -compound in manual page named 'options' -_Cursor = Union[str, tuple[str], tuple[str, str], tuple[str, str, str], tuple[str, str, str, str]] # manual page: Tk_GetCursor -_EntryValidateCommand = ( +_Anchor: TypeAlias = Literal["nw", "n", "ne", "w", "center", "e", "sw", "s", "se"] # manual page: Tk_GetAnchor +_Bitmap: TypeAlias = str # manual page: Tk_GetBitmap +_ButtonCommand: TypeAlias = str | Callable[[], Any] # accepts string of tcl code, return value is returned from Button.invoke() +_CanvasItemId: TypeAlias = int +_Color: TypeAlias = str # typically '#rrggbb', '#rgb' or color names. +_Compound: TypeAlias = Literal["top", "left", "center", "right", "bottom", "none"] # -compound in manual page named 'options' +_Cursor: TypeAlias = Union[ + str, tuple[str], tuple[str, str], tuple[str, str, str], tuple[str, str, str, str] +] # manual page: Tk_GetCursor +_EntryValidateCommand: TypeAlias = ( str | list[str] | tuple[str, ...] | Callable[[], bool] ) # example when it's sequence: entry['invalidcommand'] = [entry.register(print), '%P'] -_GridIndex = int | str | Literal["all"] -_ImageSpec = _Image | str # str can be from e.g. tkinter.image_names() -_Padding = Union[ +_GridIndex: TypeAlias = int | str | Literal["all"] +_ImageSpec: TypeAlias = _Image | str # str can be from e.g. tkinter.image_names() +_Padding: TypeAlias = Union[ _ScreenUnits, tuple[_ScreenUnits], tuple[_ScreenUnits, _ScreenUnits], tuple[_ScreenUnits, _ScreenUnits, _ScreenUnits], tuple[_ScreenUnits, _ScreenUnits, _ScreenUnits, _ScreenUnits], ] -_Relief = Literal["raised", "sunken", "flat", "ridge", "solid", "groove"] # manual page: Tk_GetRelief -_ScreenUnits = str | float # Often the right type instead of int. Manual page: Tk_GetPixels -_XYScrollCommand = str | Callable[[float, float], Any] # -xscrollcommand and -yscrollcommand in 'options' manual page -_TakeFocusValue = Union[int, Literal[""], Callable[[str], bool | None]] # -takefocus in manual page named 'options' +_Relief: TypeAlias = Literal["raised", "sunken", "flat", "ridge", "solid", "groove"] # manual page: Tk_GetRelief +_ScreenUnits: TypeAlias = str | float # Often the right type instead of int. Manual page: Tk_GetPixels +_XYScrollCommand: TypeAlias = str | Callable[[float, float], Any] # -xscrollcommand and -yscrollcommand in 'options' manual page +_TakeFocusValue: TypeAlias = Union[int, Literal[""], Callable[[str], bool | None]] # -takefocus in manual page named 'options' class EventType(str, Enum): Activate: str @@ -263,7 +266,7 @@ class Event(Generic[_W_co]): def NoDefaultRoot() -> None: ... -_TraceMode = Literal["array", "read", "write", "unset"] +_TraceMode: TypeAlias = Literal["array", "read", "write", "unset"] class Variable: def __init__(self, master: Misc | None = ..., value: Any | None = ..., name: str | None = ...) -> None: ... @@ -1696,7 +1699,7 @@ class Checkbutton(Widget): def select(self) -> None: ... def toggle(self) -> None: ... -_EntryIndex = str | int # "INDICES" in manual page +_EntryIndex: TypeAlias = str | int # "INDICES" in manual page class Entry(Widget, XView): def __init__( @@ -2054,7 +2057,7 @@ class Listbox(Widget, XView, YView): def itemconfigure(self, index, cnf: Any | None = ..., **kw): ... itemconfig: Any -_MenuIndex = str | int +_MenuIndex: TypeAlias = str | int class Menu(Widget): def __init__( @@ -2740,7 +2743,7 @@ class Scrollbar(Widget): def get(self) -> tuple[float, float, float, float] | tuple[float, float]: ... def set(self, first: float, last: float) -> None: ... -_TextIndex = _tkinter.Tcl_Obj | str | float | Misc +_TextIndex: TypeAlias = _tkinter.Tcl_Obj | str | float | Misc class Text(Widget, XView, YView): def __init__( diff --git a/mypy/typeshed/stdlib/tkinter/commondialog.pyi b/mypy/typeshed/stdlib/tkinter/commondialog.pyi index 1c5fb0f537065..faebcc33955eb 100644 --- a/mypy/typeshed/stdlib/tkinter/commondialog.pyi +++ b/mypy/typeshed/stdlib/tkinter/commondialog.pyi @@ -1,5 +1,6 @@ import sys -from typing import Any, ClassVar, Mapping +from collections.abc import Mapping +from typing import Any, ClassVar if sys.version_info >= (3, 9): __all__ = ["Dialog"] diff --git a/mypy/typeshed/stdlib/tkinter/dialog.pyi b/mypy/typeshed/stdlib/tkinter/dialog.pyi index f9c8487c44a93..9ced7a2088082 100644 --- a/mypy/typeshed/stdlib/tkinter/dialog.pyi +++ b/mypy/typeshed/stdlib/tkinter/dialog.pyi @@ -1,6 +1,7 @@ import sys +from collections.abc import Mapping from tkinter import Widget -from typing import Any, Mapping +from typing import Any if sys.version_info >= (3, 9): __all__ = ["Dialog"] diff --git a/mypy/typeshed/stdlib/tkinter/filedialog.pyi b/mypy/typeshed/stdlib/tkinter/filedialog.pyi index dc0e01a6d1d1e..2815289e81c37 100644 --- a/mypy/typeshed/stdlib/tkinter/filedialog.pyi +++ b/mypy/typeshed/stdlib/tkinter/filedialog.pyi @@ -1,7 +1,8 @@ import sys from _typeshed import StrOrBytesPath +from collections.abc import Iterable from tkinter import Button, Entry, Frame, Listbox, Misc, Scrollbar, StringVar, Toplevel, commondialog -from typing import IO, Any, ClassVar, Iterable +from typing import IO, Any, ClassVar from typing_extensions import Literal if sys.version_info >= (3, 9): diff --git a/mypy/typeshed/stdlib/tkinter/font.pyi b/mypy/typeshed/stdlib/tkinter/font.pyi index 4b0101b327880..dff84e9fac781 100644 --- a/mypy/typeshed/stdlib/tkinter/font.pyi +++ b/mypy/typeshed/stdlib/tkinter/font.pyi @@ -2,7 +2,7 @@ import _tkinter import sys import tkinter from typing import Any, overload -from typing_extensions import Literal, TypedDict +from typing_extensions import Literal, TypeAlias, TypedDict if sys.version_info >= (3, 9): __all__ = ["NORMAL", "ROMAN", "BOLD", "ITALIC", "nametofont", "Font", "families", "names"] @@ -12,7 +12,7 @@ ROMAN: Literal["roman"] BOLD: Literal["bold"] ITALIC: Literal["italic"] -_FontDescription = ( +_FontDescription: TypeAlias = ( str # "Helvetica 12" | Font # A font object constructed in Python | list[Any] # ("Helvetica", 12, BOLD) diff --git a/mypy/typeshed/stdlib/tkinter/ttk.pyi b/mypy/typeshed/stdlib/tkinter/ttk.pyi index c48b5cd7aa0da..7ca8f9b800ce6 100644 --- a/mypy/typeshed/stdlib/tkinter/ttk.pyi +++ b/mypy/typeshed/stdlib/tkinter/ttk.pyi @@ -1,9 +1,10 @@ import _tkinter import sys import tkinter +from collections.abc import Callable from tkinter.font import _FontDescription -from typing import Any, Callable, overload -from typing_extensions import Literal, TypedDict +from typing import Any, overload +from typing_extensions import Literal, TypeAlias, TypedDict if sys.version_info >= (3, 7): __all__ = [ @@ -65,7 +66,7 @@ def tclobjs_to_py(adict: dict[Any, Any]) -> dict[Any, Any]: ... def setup_master(master: Any | None = ...): ... # from ttk_widget (aka ttk::widget) manual page, differs from tkinter._Compound -_TtkCompound = Literal["text", "image", tkinter._Compound] +_TtkCompound: TypeAlias = Literal["text", "image", tkinter._Compound] class Style: master: Any @@ -972,7 +973,7 @@ class _TreeviewColumnDict(TypedDict): anchor: tkinter._Anchor id: str -_TreeviewColumnId = int | str # manual page: "COLUMN IDENTIFIERS" +_TreeviewColumnId: TypeAlias = int | str # manual page: "COLUMN IDENTIFIERS" class Treeview(Widget, tkinter.XView, tkinter.YView): def __init__( diff --git a/mypy/typeshed/stdlib/tokenize.pyi b/mypy/typeshed/stdlib/tokenize.pyi index 7b17e8de6153f..dea83263b550a 100644 --- a/mypy/typeshed/stdlib/tokenize.pyi +++ b/mypy/typeshed/stdlib/tokenize.pyi @@ -1,8 +1,10 @@ import sys from _typeshed import StrOrBytesPath from builtins import open as _builtin_open +from collections.abc import Callable, Generator, Iterable, Sequence from token import * -from typing import Any, Callable, Generator, Iterable, NamedTuple, Pattern, Sequence, TextIO +from typing import Any, NamedTuple, Pattern, TextIO +from typing_extensions import TypeAlias if sys.version_info >= (3, 10): __all__ = [ @@ -317,7 +319,7 @@ if sys.version_info < (3, 7): cookie_re: Pattern[str] blank_re: Pattern[bytes] -_Position = tuple[int, int] +_Position: TypeAlias = tuple[int, int] class _TokenInfo(NamedTuple): type: int @@ -331,7 +333,7 @@ class TokenInfo(_TokenInfo): def exact_type(self) -> int: ... # Backwards compatible tokens can be sequences of a shorter length too -_Token = TokenInfo | Sequence[int | str | _Position] +_Token: TypeAlias = TokenInfo | Sequence[int | str | _Position] class TokenError(Exception): ... class StopTokenizing(Exception): ... # undocumented diff --git a/mypy/typeshed/stdlib/trace.pyi b/mypy/typeshed/stdlib/trace.pyi index 6128064478bcb..3640cb11a878f 100644 --- a/mypy/typeshed/stdlib/trace.pyi +++ b/mypy/typeshed/stdlib/trace.pyi @@ -1,15 +1,16 @@ import sys import types from _typeshed import StrPath -from typing import Any, Callable, Mapping, Sequence, TypeVar -from typing_extensions import ParamSpec +from collections.abc import Callable, Mapping, Sequence +from typing import Any, TypeVar +from typing_extensions import ParamSpec, TypeAlias __all__ = ["Trace", "CoverageResults"] _T = TypeVar("_T") _P = ParamSpec("_P") -_localtrace = Callable[[types.FrameType, str, Any], Callable[..., Any]] -_fileModuleFunction = tuple[str, str | None, str] +_localtrace: TypeAlias = Callable[[types.FrameType, str, Any], Callable[..., Any]] +_fileModuleFunction: TypeAlias = tuple[str, str | None, str] class CoverageResults: def __init__( diff --git a/mypy/typeshed/stdlib/traceback.pyi b/mypy/typeshed/stdlib/traceback.pyi index 859bfef646228..5c4d323a2d9ff 100644 --- a/mypy/typeshed/stdlib/traceback.pyi +++ b/mypy/typeshed/stdlib/traceback.pyi @@ -1,8 +1,9 @@ import sys from _typeshed import Self, SupportsWrite +from collections.abc import Generator, Iterable, Iterator, Mapping from types import FrameType, TracebackType -from typing import IO, Any, Generator, Iterable, Iterator, Mapping, overload -from typing_extensions import Literal +from typing import IO, Any, overload +from typing_extensions import Literal, TypeAlias __all__ = [ "extract_stack", @@ -26,7 +27,7 @@ __all__ = [ "walk_tb", ] -_PT = tuple[str, int, str, str | None] +_PT: TypeAlias = tuple[str, int, str, str | None] def print_tb(tb: TracebackType | None, limit: int | None = ..., file: IO[str] | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/tracemalloc.pyi b/mypy/typeshed/stdlib/tracemalloc.pyi index e2e6800cbab42..193a4acc7c2db 100644 --- a/mypy/typeshed/stdlib/tracemalloc.pyi +++ b/mypy/typeshed/stdlib/tracemalloc.pyi @@ -1,7 +1,8 @@ import sys from _tracemalloc import * -from typing import Any, Sequence, Union, overload -from typing_extensions import SupportsIndex +from collections.abc import Sequence +from typing import Any, Union, overload +from typing_extensions import SupportsIndex, TypeAlias def get_object_traceback(obj: object) -> Traceback | None: ... def take_snapshot() -> Snapshot: ... @@ -41,7 +42,7 @@ class StatisticDiff: def __init__(self, traceback: Traceback, size: int, size_diff: int, count: int, count_diff: int) -> None: ... def __eq__(self, other: object) -> bool: ... -_FrameTupleT = tuple[str, int] +_FrameTupleT: TypeAlias = tuple[str, int] class Frame: @property @@ -61,9 +62,9 @@ class Frame: def __le__(self, other: Frame, NotImplemented: Any = ...) -> bool: ... if sys.version_info >= (3, 9): - _TraceTupleT = Union[tuple[int, int, Sequence[_FrameTupleT], int | None], tuple[int, int, Sequence[_FrameTupleT]]] + _TraceTupleT: TypeAlias = Union[tuple[int, int, Sequence[_FrameTupleT], int | None], tuple[int, int, Sequence[_FrameTupleT]]] else: - _TraceTupleT = tuple[int, int, Sequence[_FrameTupleT]] + _TraceTupleT: TypeAlias = tuple[int, int, Sequence[_FrameTupleT]] class Trace: @property diff --git a/mypy/typeshed/stdlib/tty.pyi b/mypy/typeshed/stdlib/tty.pyi index 08c93f6f2e847..8edae9ec2debd 100644 --- a/mypy/typeshed/stdlib/tty.pyi +++ b/mypy/typeshed/stdlib/tty.pyi @@ -1,10 +1,11 @@ import sys from typing import IO +from typing_extensions import TypeAlias if sys.platform != "win32": __all__ = ["setraw", "setcbreak"] - _FD = int | IO[str] + _FD: TypeAlias = int | IO[str] # XXX: Undocumented integer constants IFLAG: int diff --git a/mypy/typeshed/stdlib/turtle.pyi b/mypy/typeshed/stdlib/turtle.pyi index 2ff965465be6a..3e91a5eb0ebf3 100644 --- a/mypy/typeshed/stdlib/turtle.pyi +++ b/mypy/typeshed/stdlib/turtle.pyi @@ -1,6 +1,8 @@ from _typeshed import Self +from collections.abc import Callable, Sequence from tkinter import Canvas, Frame, Misc, PhotoImage, Scrollbar -from typing import Any, Callable, ClassVar, Sequence, Union, overload +from typing import Any, ClassVar, Union, overload +from typing_extensions import TypeAlias __all__ = [ "ScrolledCanvas", @@ -131,18 +133,18 @@ __all__ = [ # alias we use for return types. Really, these two aliases should be the # same, but as per the "no union returns" typeshed policy, we'll return # Any instead. -_Color = Union[str, tuple[float, float, float]] -_AnyColor = Any +_Color: TypeAlias = Union[str, tuple[float, float, float]] +_AnyColor: TypeAlias = Any # TODO: Replace this with a TypedDict once it becomes standardized. -_PenState = dict[str, Any] +_PenState: TypeAlias = dict[str, Any] -_Speed = str | float -_PolygonCoords = Sequence[tuple[float, float]] +_Speed: TypeAlias = str | float +_PolygonCoords: TypeAlias = Sequence[tuple[float, float]] # TODO: Type this more accurately # Vec2D is actually a custom subclass of 'tuple'. -Vec2D = tuple[float, float] +Vec2D: TypeAlias = tuple[float, float] # Does not actually inherit from Canvas, but dynamically gets all methods of Canvas class ScrolledCanvas(Canvas, Frame): # type: ignore[misc] diff --git a/mypy/typeshed/stdlib/types.pyi b/mypy/typeshed/stdlib/types.pyi index 9b2fa1f4a2aad..872ed57a7c76c 100644 --- a/mypy/typeshed/stdlib/types.pyi +++ b/mypy/typeshed/stdlib/types.pyi @@ -1,26 +1,23 @@ import sys from _typeshed import SupportsKeysAndGetItem -from importlib.abc import _LoaderProtocol -from importlib.machinery import ModuleSpec -from typing import ( - Any, +from collections.abc import ( AsyncGenerator, Awaitable, Callable, - ClassVar, Coroutine, Generator, - Generic, ItemsView, Iterable, Iterator, KeysView, - Mapping, MutableSequence, - TypeVar, ValuesView, - overload, ) +from importlib.abc import _LoaderProtocol +from importlib.machinery import ModuleSpec + +# pytype crashes if types.MappingProxyType inherits from collections.abc.Mapping instead of typing.Mapping +from typing import Any, ClassVar, Generic, Mapping, TypeVar, overload # noqa: Y027 from typing_extensions import Literal, ParamSpec, final if sys.version_info >= (3, 10): diff --git a/mypy/typeshed/stdlib/typing.pyi b/mypy/typeshed/stdlib/typing.pyi index 4ad3ab3da274e..28b588d79c9bb 100644 --- a/mypy/typeshed/stdlib/typing.pyi +++ b/mypy/typeshed/stdlib/typing.pyi @@ -22,9 +22,12 @@ if sys.version_info >= (3, 11): "ForwardRef", "Generic", "Literal", + "LiteralString", + "NotRequired", "Optional", "ParamSpec", "Protocol", + "Required", "Tuple", "Type", "TypeVar", @@ -84,9 +87,11 @@ if sys.version_info >= (3, 11): "assert_never", "assert_type", "cast", + "clear_overloads", "final", "get_args", "get_origin", + "get_overloads", "get_type_hints", "is_typeddict", "Never", @@ -528,6 +533,9 @@ if sys.version_info >= (3, 11): Self: _SpecialForm Never: _SpecialForm = ... Unpack: _SpecialForm + Required: _SpecialForm + NotRequired: _SpecialForm + LiteralString: _SpecialForm class TypeVarTuple: __name__: str @@ -1138,7 +1146,7 @@ class Pattern(Generic[AnyStr]): # Functions if sys.version_info >= (3, 7): - _get_type_hints_obj_allowed_types = ( + _get_type_hints_obj_allowed_types = ( # noqa: Y026 # TODO: Use TypeAlias once mypy bugs are fixed object | Callable[..., Any] | FunctionType @@ -1150,7 +1158,9 @@ if sys.version_info >= (3, 7): | MethodDescriptorType ) else: - _get_type_hints_obj_allowed_types = object | Callable[..., Any] | FunctionType | BuiltinFunctionType | MethodType | ModuleType + _get_type_hints_obj_allowed_types = ( # noqa: Y026 # TODO: Use TypeAlias once mypy bugs are fixed + object | Callable[..., Any] | FunctionType | BuiltinFunctionType | MethodType | ModuleType + ) if sys.version_info >= (3, 9): def get_type_hints( @@ -1180,6 +1190,8 @@ if sys.version_info >= (3, 11): def reveal_type(__obj: _T) -> _T: ... def assert_never(__arg: Never) -> Never: ... def assert_type(__val: _T, __typ: Any) -> _T: ... + def clear_overloads() -> None: ... + def get_overloads(func: Callable[..., object]) -> Sequence[Callable[..., object]]: ... # Type constructors diff --git a/mypy/typeshed/stdlib/typing_extensions.pyi b/mypy/typeshed/stdlib/typing_extensions.pyi index 70f395446b0b3..1c75ec38e75c8 100644 --- a/mypy/typeshed/stdlib/typing_extensions.pyi +++ b/mypy/typeshed/stdlib/typing_extensions.pyi @@ -22,6 +22,7 @@ from typing import ( # noqa: Y022,Y027 Mapping, NewType as NewType, NoReturn as NoReturn, + Sequence, Text as Text, Type as Type, TypeVar, @@ -76,8 +77,10 @@ __all__ = [ "NoReturn", "Required", "NotRequired", + "clear_overloads", "get_args", "get_origin", + "get_overloads", "get_type_hints", ] @@ -188,10 +191,17 @@ else: # New things in 3.11 if sys.version_info >= (3, 11): from typing import ( + LiteralString as LiteralString, Never as Never, + NotRequired as NotRequired, + Required as Required, Self as Self, + TypeVarTuple as TypeVarTuple, + Unpack as Unpack, assert_never as assert_never, assert_type as assert_type, + clear_overloads as clear_overloads, + get_overloads as get_overloads, reveal_type as reveal_type, ) else: @@ -200,23 +210,26 @@ else: def reveal_type(__obj: _T) -> _T: ... def assert_never(__arg: NoReturn) -> NoReturn: ... def assert_type(__val: _T, __typ: Any) -> _T: ... + def clear_overloads() -> None: ... + def get_overloads(func: Callable[..., object]) -> Sequence[Callable[..., object]]: ... -# Experimental (hopefully these will be in 3.11) -Required: _SpecialForm -NotRequired: _SpecialForm -LiteralString: _SpecialForm -Unpack: _SpecialForm + Required: _SpecialForm + NotRequired: _SpecialForm + LiteralString: _SpecialForm + Unpack: _SpecialForm -@final -class TypeVarTuple: - __name__: str - def __init__(self, name: str) -> None: ... - def __iter__(self) -> Any: ... # Unpack[Self] + @final + class TypeVarTuple: + __name__: str + def __init__(self, name: str) -> None: ... + def __iter__(self) -> Any: ... # Unpack[Self] +# Experimental (hopefully these will be in 3.11) def dataclass_transform( *, eq_default: bool = ..., order_default: bool = ..., kw_only_default: bool = ..., - field_descriptors: tuple[type[Any] | Callable[..., Any], ...] = ..., + field_specifiers: tuple[type[Any] | Callable[..., Any], ...] = ..., + **kwargs: object, ) -> Callable[[_T], _T]: ... diff --git a/mypy/typeshed/stdlib/unittest/async_case.pyi b/mypy/typeshed/stdlib/unittest/async_case.pyi index 0442ec4445595..55407ec3f1c8f 100644 --- a/mypy/typeshed/stdlib/unittest/async_case.pyi +++ b/mypy/typeshed/stdlib/unittest/async_case.pyi @@ -1,4 +1,4 @@ -from typing import Awaitable, Callable +from collections.abc import Awaitable, Callable from typing_extensions import ParamSpec from .case import TestCase diff --git a/mypy/typeshed/stdlib/unittest/case.pyi b/mypy/typeshed/stdlib/unittest/case.pyi index 87441920fe501..578bd6d6f271d 100644 --- a/mypy/typeshed/stdlib/unittest/case.pyi +++ b/mypy/typeshed/stdlib/unittest/case.pyi @@ -3,25 +3,10 @@ import logging import sys import unittest.result from _typeshed import Self -from collections.abc import Set as AbstractSet +from collections.abc import Callable, Container, Iterable, Mapping, Sequence, Set as AbstractSet from contextlib import AbstractContextManager from types import TracebackType -from typing import ( - Any, - AnyStr, - Callable, - ClassVar, - Container, - Generic, - Iterable, - Mapping, - NamedTuple, - NoReturn, - Pattern, - Sequence, - TypeVar, - overload, -) +from typing import Any, AnyStr, ClassVar, Generic, NamedTuple, NoReturn, Pattern, TypeVar, overload from typing_extensions import ParamSpec from warnings import WarningMessage diff --git a/mypy/typeshed/stdlib/unittest/loader.pyi b/mypy/typeshed/stdlib/unittest/loader.pyi index 8b3c82233cec7..76c60f4803f5d 100644 --- a/mypy/typeshed/stdlib/unittest/loader.pyi +++ b/mypy/typeshed/stdlib/unittest/loader.pyi @@ -2,11 +2,13 @@ import sys import unittest.case import unittest.result import unittest.suite +from collections.abc import Callable, Sequence from types import ModuleType -from typing import Any, Callable, Pattern, Sequence +from typing import Any, Pattern +from typing_extensions import TypeAlias -_SortComparisonMethod = Callable[[str, str], int] -_SuiteClass = Callable[[list[unittest.case.TestCase]], unittest.suite.TestSuite] +_SortComparisonMethod: TypeAlias = Callable[[str, str], int] +_SuiteClass: TypeAlias = Callable[[list[unittest.case.TestCase]], unittest.suite.TestSuite] VALID_MODULE_NAME: Pattern[str] diff --git a/mypy/typeshed/stdlib/unittest/main.pyi b/mypy/typeshed/stdlib/unittest/main.pyi index d3c0ca722f4dc..31853676b011c 100644 --- a/mypy/typeshed/stdlib/unittest/main.pyi +++ b/mypy/typeshed/stdlib/unittest/main.pyi @@ -3,8 +3,9 @@ import unittest.case import unittest.loader import unittest.result import unittest.suite +from collections.abc import Iterable from types import ModuleType -from typing import Any, Iterable, Protocol +from typing import Any, Protocol MAIN_EXAMPLES: str MODULE_EXAMPLES: str diff --git a/mypy/typeshed/stdlib/unittest/mock.pyi b/mypy/typeshed/stdlib/unittest/mock.pyi index f5cd4218cea0b..400bdaac3b41e 100644 --- a/mypy/typeshed/stdlib/unittest/mock.pyi +++ b/mypy/typeshed/stdlib/unittest/mock.pyi @@ -1,9 +1,10 @@ import sys from _typeshed import Self +from collections.abc import Awaitable, Callable, Iterable, Mapping, Sequence from contextlib import _GeneratorContextManager from types import TracebackType -from typing import Any, Awaitable, Callable, Generic, Iterable, Mapping, Sequence, TypeVar, overload -from typing_extensions import Literal +from typing import Any, Generic, TypeVar, overload +from typing_extensions import Literal, TypeAlias _T = TypeVar("_T") _TT = TypeVar("_TT", bound=type[Any]) @@ -77,9 +78,9 @@ class _Sentinel: sentinel: Any DEFAULT: Any -_ArgsKwargs = tuple[tuple[Any, ...], Mapping[str, Any]] -_NameArgsKwargs = tuple[str, tuple[Any, ...], Mapping[str, Any]] -_CallValue = str | tuple[Any, ...] | Mapping[str, Any] | _ArgsKwargs | _NameArgsKwargs +_ArgsKwargs: TypeAlias = tuple[tuple[Any, ...], Mapping[str, Any]] +_NameArgsKwargs: TypeAlias = tuple[str, tuple[Any, ...], Mapping[str, Any]] +_CallValue: TypeAlias = str | tuple[Any, ...] | Mapping[str, Any] | _ArgsKwargs | _NameArgsKwargs class _Call(tuple[Any, ...]): def __new__( @@ -283,9 +284,9 @@ class _patch_dict: stop: Any if sys.version_info >= (3, 8): - _Mock = MagicMock | AsyncMock + _Mock: TypeAlias = MagicMock | AsyncMock else: - _Mock = MagicMock + _Mock: TypeAlias = MagicMock class _patcher: TEST_PREFIX: str @@ -296,7 +297,7 @@ class _patcher: @overload def __call__( # type: ignore[misc] self, - target: Any, + target: str, new: _T, spec: Any | None = ..., create: bool = ..., @@ -308,7 +309,7 @@ class _patcher: @overload def __call__( self, - target: Any, + target: str, *, spec: Any | None = ..., create: bool = ..., diff --git a/mypy/typeshed/stdlib/unittest/result.pyi b/mypy/typeshed/stdlib/unittest/result.pyi index 1c79f8ab648c7..5dfec13cb52cd 100644 --- a/mypy/typeshed/stdlib/unittest/result.pyi +++ b/mypy/typeshed/stdlib/unittest/result.pyi @@ -1,8 +1,7 @@ import unittest.case -from types import TracebackType -from typing import Any, Callable, TextIO, TypeVar, Union - -_SysExcInfoType = Union[tuple[type[BaseException], BaseException, TracebackType], tuple[None, None, None]] +from _typeshed import OptExcInfo +from collections.abc import Callable +from typing import Any, TextIO, TypeVar _F = TypeVar("_F", bound=Callable[..., Any]) @@ -31,10 +30,10 @@ class TestResult: def stopTest(self, test: unittest.case.TestCase) -> None: ... def startTestRun(self) -> None: ... def stopTestRun(self) -> None: ... - def addError(self, test: unittest.case.TestCase, err: _SysExcInfoType) -> None: ... - def addFailure(self, test: unittest.case.TestCase, err: _SysExcInfoType) -> None: ... + def addError(self, test: unittest.case.TestCase, err: OptExcInfo) -> None: ... + def addFailure(self, test: unittest.case.TestCase, err: OptExcInfo) -> None: ... def addSuccess(self, test: unittest.case.TestCase) -> None: ... def addSkip(self, test: unittest.case.TestCase, reason: str) -> None: ... - def addExpectedFailure(self, test: unittest.case.TestCase, err: _SysExcInfoType) -> None: ... + def addExpectedFailure(self, test: unittest.case.TestCase, err: OptExcInfo) -> None: ... def addUnexpectedSuccess(self, test: unittest.case.TestCase) -> None: ... - def addSubTest(self, test: unittest.case.TestCase, subtest: unittest.case.TestCase, err: _SysExcInfoType | None) -> None: ... + def addSubTest(self, test: unittest.case.TestCase, subtest: unittest.case.TestCase, err: OptExcInfo | None) -> None: ... diff --git a/mypy/typeshed/stdlib/unittest/runner.pyi b/mypy/typeshed/stdlib/unittest/runner.pyi index 479a9f2c304c1..1f1b89bc1beee 100644 --- a/mypy/typeshed/stdlib/unittest/runner.pyi +++ b/mypy/typeshed/stdlib/unittest/runner.pyi @@ -1,9 +1,11 @@ import unittest.case import unittest.result import unittest.suite -from typing import Callable, Iterable, TextIO +from collections.abc import Callable, Iterable +from typing import TextIO +from typing_extensions import TypeAlias -_ResultClassType = Callable[[TextIO, bool, int], unittest.result.TestResult] +_ResultClassType: TypeAlias = Callable[[TextIO, bool, int], unittest.result.TestResult] class TextTestResult(unittest.result.TestResult): descriptions: bool # undocumented diff --git a/mypy/typeshed/stdlib/unittest/signals.pyi b/mypy/typeshed/stdlib/unittest/signals.pyi index e6f5f95e1eb1b..89e108d926a66 100644 --- a/mypy/typeshed/stdlib/unittest/signals.pyi +++ b/mypy/typeshed/stdlib/unittest/signals.pyi @@ -1,5 +1,6 @@ import unittest.result -from typing import Callable, TypeVar, overload +from collections.abc import Callable +from typing import TypeVar, overload from typing_extensions import ParamSpec _P = ParamSpec("_P") diff --git a/mypy/typeshed/stdlib/unittest/suite.pyi b/mypy/typeshed/stdlib/unittest/suite.pyi index ca483b06ac9f1..26bef658f1cd4 100644 --- a/mypy/typeshed/stdlib/unittest/suite.pyi +++ b/mypy/typeshed/stdlib/unittest/suite.pyi @@ -1,8 +1,9 @@ import unittest.case import unittest.result -from typing import Iterable, Iterator +from collections.abc import Iterable, Iterator +from typing_extensions import TypeAlias -_TestType = unittest.case.TestCase | TestSuite +_TestType: TypeAlias = unittest.case.TestCase | TestSuite class BaseTestSuite(Iterable[_TestType]): _tests: list[unittest.case.TestCase] diff --git a/mypy/typeshed/stdlib/unittest/util.pyi b/mypy/typeshed/stdlib/unittest/util.pyi index 30ab6061b1009..f62c728760ff8 100644 --- a/mypy/typeshed/stdlib/unittest/util.pyi +++ b/mypy/typeshed/stdlib/unittest/util.pyi @@ -1,7 +1,9 @@ -from typing import Any, Sequence, TypeVar +from collections.abc import Sequence +from typing import Any, TypeVar +from typing_extensions import TypeAlias _T = TypeVar("_T") -_Mismatch = tuple[_T, _T, int] +_Mismatch: TypeAlias = tuple[_T, _T, int] _MAX_LENGTH: int _PLACEHOLDER_LEN: int diff --git a/mypy/typeshed/stdlib/urllib/parse.pyi b/mypy/typeshed/stdlib/urllib/parse.pyi index a45e23dd9084b..c6a6836e6e958 100644 --- a/mypy/typeshed/stdlib/urllib/parse.pyi +++ b/mypy/typeshed/stdlib/urllib/parse.pyi @@ -1,5 +1,7 @@ import sys -from typing import Any, AnyStr, Callable, Generic, Mapping, NamedTuple, Sequence, overload +from collections.abc import Callable, Mapping, Sequence +from typing import Any, AnyStr, Generic, NamedTuple, overload +from typing_extensions import TypeAlias if sys.version_info >= (3, 9): from types import GenericAlias @@ -28,7 +30,7 @@ __all__ = [ "SplitResultBytes", ] -_Str = bytes | str +_Str: TypeAlias = bytes | str uses_relative: list[str] uses_netloc: list[str] diff --git a/mypy/typeshed/stdlib/urllib/request.pyi b/mypy/typeshed/stdlib/urllib/request.pyi index 265ef21967158..5e6dde01480ab 100644 --- a/mypy/typeshed/stdlib/urllib/request.pyi +++ b/mypy/typeshed/stdlib/urllib/request.pyi @@ -1,10 +1,12 @@ import ssl import sys from _typeshed import StrOrBytesPath, SupportsRead +from collections.abc import Callable, Iterable, Mapping, MutableMapping, Sequence from email.message import Message from http.client import HTTPMessage, HTTPResponse, _HTTPConnectionProtocol from http.cookiejar import CookieJar -from typing import IO, Any, Callable, ClassVar, Iterable, Mapping, MutableMapping, NoReturn, Pattern, Sequence, TypeVar, overload +from typing import IO, Any, ClassVar, NoReturn, Pattern, TypeVar, overload +from typing_extensions import TypeAlias from urllib.error import HTTPError from urllib.response import addclosehook, addinfourl @@ -46,8 +48,8 @@ __all__ = [ ] _T = TypeVar("_T") -_UrlopenRet = Any -_DataType = bytes | SupportsRead[bytes] | Iterable[bytes] | None +_UrlopenRet: TypeAlias = Any +_DataType: TypeAlias = bytes | SupportsRead[bytes] | Iterable[bytes] | None def urlopen( url: str | Request, diff --git a/mypy/typeshed/stdlib/urllib/response.pyi b/mypy/typeshed/stdlib/urllib/response.pyi index 2efec0d47d44f..8c9a600f3c486 100644 --- a/mypy/typeshed/stdlib/urllib/response.pyi +++ b/mypy/typeshed/stdlib/urllib/response.pyi @@ -1,8 +1,9 @@ import sys from _typeshed import Self +from collections.abc import Callable, Iterable from email.message import Message from types import TracebackType -from typing import IO, Any, BinaryIO, Callable, Iterable +from typing import IO, Any, BinaryIO __all__ = ["addbase", "addclosehook", "addinfo", "addinfourl"] diff --git a/mypy/typeshed/stdlib/urllib/robotparser.pyi b/mypy/typeshed/stdlib/urllib/robotparser.pyi index d1d69546db427..795cf83fcecde 100644 --- a/mypy/typeshed/stdlib/urllib/robotparser.pyi +++ b/mypy/typeshed/stdlib/urllib/robotparser.pyi @@ -1,5 +1,6 @@ import sys -from typing import Iterable, NamedTuple +from collections.abc import Iterable +from typing import NamedTuple __all__ = ["RobotFileParser"] diff --git a/mypy/typeshed/stdlib/uu.pyi b/mypy/typeshed/stdlib/uu.pyi index d75df67a1f76d..4ebb12be88584 100644 --- a/mypy/typeshed/stdlib/uu.pyi +++ b/mypy/typeshed/stdlib/uu.pyi @@ -1,9 +1,10 @@ import sys from typing import BinaryIO +from typing_extensions import TypeAlias __all__ = ["Error", "encode", "decode"] -_File = str | BinaryIO +_File: TypeAlias = str | BinaryIO class Error(Exception): ... diff --git a/mypy/typeshed/stdlib/uuid.pyi b/mypy/typeshed/stdlib/uuid.pyi index 4d46e89beddd3..fd7f1334e52a0 100644 --- a/mypy/typeshed/stdlib/uuid.pyi +++ b/mypy/typeshed/stdlib/uuid.pyi @@ -1,9 +1,10 @@ import sys +from typing_extensions import TypeAlias # Because UUID has properties called int and bytes we need to rename these temporarily. -_Int = int -_Bytes = bytes -_FieldsType = tuple[int, int, int, int, int, int] +_Int: TypeAlias = int +_Bytes: TypeAlias = bytes +_FieldsType: TypeAlias = tuple[int, int, int, int, int, int] if sys.version_info >= (3, 7): from enum import Enum diff --git a/mypy/typeshed/stdlib/venv/__init__.pyi b/mypy/typeshed/stdlib/venv/__init__.pyi index 815490a205abc..6afe328ac90da 100644 --- a/mypy/typeshed/stdlib/venv/__init__.pyi +++ b/mypy/typeshed/stdlib/venv/__init__.pyi @@ -1,7 +1,7 @@ +from collections.abc import Sequence import sys from _typeshed import StrOrBytesPath from types import SimpleNamespace -from typing import Sequence if sys.version_info >= (3, 9): CORE_VENV_DEPS: tuple[str, ...] diff --git a/mypy/typeshed/stdlib/warnings.pyi b/mypy/typeshed/stdlib/warnings.pyi index 1799d69f5ba67..bd7afb2d7cba6 100644 --- a/mypy/typeshed/stdlib/warnings.pyi +++ b/mypy/typeshed/stdlib/warnings.pyi @@ -1,7 +1,8 @@ from _warnings import warn as warn, warn_explicit as warn_explicit +from collections.abc import Sequence from types import ModuleType, TracebackType -from typing import Any, Sequence, TextIO, overload -from typing_extensions import Literal +from typing import Any, TextIO, overload +from typing_extensions import Literal, TypeAlias __all__ = [ "warn", @@ -14,7 +15,7 @@ __all__ = [ "catch_warnings", ] -_ActionKind = Literal["default", "error", "ignore", "always", "module", "once"] +_ActionKind: TypeAlias = Literal["default", "error", "ignore", "always", "module", "once"] filters: Sequence[tuple[str, str | None, type[Warning], str | None, int]] # undocumented, do not mutate diff --git a/mypy/typeshed/stdlib/wave.pyi b/mypy/typeshed/stdlib/wave.pyi index de20c6c4f5d41..689282f69ee74 100644 --- a/mypy/typeshed/stdlib/wave.pyi +++ b/mypy/typeshed/stdlib/wave.pyi @@ -1,14 +1,14 @@ import sys from _typeshed import ReadableBuffer, Self from typing import IO, Any, BinaryIO, NamedTuple, NoReturn, overload -from typing_extensions import Literal +from typing_extensions import Literal, TypeAlias if sys.version_info >= (3, 9): __all__ = ["open", "Error", "Wave_read", "Wave_write"] else: __all__ = ["open", "openfp", "Error", "Wave_read", "Wave_write"] -_File = str | IO[bytes] +_File: TypeAlias = str | IO[bytes] class Error(Exception): ... diff --git a/mypy/typeshed/stdlib/weakref.pyi b/mypy/typeshed/stdlib/weakref.pyi index 8204885291436..03dd89c8e210d 100644 --- a/mypy/typeshed/stdlib/weakref.pyi +++ b/mypy/typeshed/stdlib/weakref.pyi @@ -1,7 +1,8 @@ import sys from _typeshed import Self, SupportsKeysAndGetItem from _weakrefset import WeakSet as WeakSet -from typing import Any, Callable, Generic, Iterable, Iterator, Mapping, MutableMapping, TypeVar, overload +from collections.abc import Callable, Iterable, Iterator, Mapping, MutableMapping +from typing import Any, Generic, TypeVar, overload from typing_extensions import ParamSpec from _weakref import ( diff --git a/mypy/typeshed/stdlib/webbrowser.pyi b/mypy/typeshed/stdlib/webbrowser.pyi index ce8fca262d2d4..a5b04a262596c 100644 --- a/mypy/typeshed/stdlib/webbrowser.pyi +++ b/mypy/typeshed/stdlib/webbrowser.pyi @@ -1,6 +1,6 @@ import sys from abc import abstractmethod -from typing import Callable, Sequence +from collections.abc import Callable, Sequence from typing_extensions import Literal __all__ = ["Error", "open", "open_new", "open_new_tab", "get", "register"] diff --git a/mypy/typeshed/stdlib/winreg.pyi b/mypy/typeshed/stdlib/winreg.pyi index 5dc7e4363d6f2..2cc42318f1a4f 100644 --- a/mypy/typeshed/stdlib/winreg.pyi +++ b/mypy/typeshed/stdlib/winreg.pyi @@ -2,10 +2,10 @@ import sys from _typeshed import Self from types import TracebackType from typing import Any -from typing_extensions import Literal, final +from typing_extensions import Literal, TypeAlias, final if sys.platform == "win32": - _KeyType = HKEYType | int + _KeyType: TypeAlias = HKEYType | int def CloseKey(__hkey: _KeyType) -> None: ... def ConnectRegistry(__computer_name: str | None, __key: _KeyType) -> HKEYType: ... def CreateKey(__key: _KeyType, __sub_key: str | None) -> HKEYType: ... diff --git a/mypy/typeshed/stdlib/wsgiref/handlers.pyi b/mypy/typeshed/stdlib/wsgiref/handlers.pyi index 9e2153788cacc..655fba6685980 100644 --- a/mypy/typeshed/stdlib/wsgiref/handlers.pyi +++ b/mypy/typeshed/stdlib/wsgiref/handlers.pyi @@ -1,15 +1,14 @@ +from _typeshed import OptExcInfo +from _typeshed.wsgi import ErrorStream, InputStream, StartResponse, WSGIApplication, WSGIEnvironment from abc import abstractmethod -from types import TracebackType -from typing import IO, Callable, MutableMapping +from collections.abc import Callable, MutableMapping +from typing import IO from .headers import Headers -from .types import ErrorStream, InputStream, StartResponse, WSGIApplication, WSGIEnvironment from .util import FileWrapper __all__ = ["BaseHandler", "SimpleHandler", "BaseCGIHandler", "CGIHandler", "IISCGIHandler", "read_environ"] -_exc_info = tuple[type[BaseException] | None, BaseException | None, TracebackType | None] - def format_date_time(timestamp: float | None) -> str: ... # undocumented def read_environ() -> dict[str, str]: ... @@ -39,7 +38,7 @@ class BaseHandler: def set_content_length(self) -> None: ... def cleanup_headers(self) -> None: ... def start_response( - self, status: str, headers: list[tuple[str, str]], exc_info: _exc_info | None = ... + self, status: str, headers: list[tuple[str, str]], exc_info: OptExcInfo | None = ... ) -> Callable[[bytes], None]: ... def send_preamble(self) -> None: ... def write(self, data: bytes) -> None: ... @@ -49,7 +48,7 @@ class BaseHandler: def send_headers(self) -> None: ... def result_is_file(self) -> bool: ... def client_is_modern(self) -> bool: ... - def log_exception(self, exc_info: _exc_info) -> None: ... + def log_exception(self, exc_info: OptExcInfo) -> None: ... def handle_error(self) -> None: ... def error_output(self, environ: WSGIEnvironment, start_response: StartResponse) -> list[bytes]: ... @abstractmethod diff --git a/mypy/typeshed/stdlib/wsgiref/headers.pyi b/mypy/typeshed/stdlib/wsgiref/headers.pyi index b62124a2a9368..cde0227a78306 100644 --- a/mypy/typeshed/stdlib/wsgiref/headers.pyi +++ b/mypy/typeshed/stdlib/wsgiref/headers.pyi @@ -1,6 +1,7 @@ from typing import Pattern, overload +from typing_extensions import TypeAlias -_HeaderList = list[tuple[str, str]] +_HeaderList: TypeAlias = list[tuple[str, str]] tspecials: Pattern[str] # undocumented diff --git a/mypy/typeshed/stdlib/wsgiref/simple_server.pyi b/mypy/typeshed/stdlib/wsgiref/simple_server.pyi index 389d30c22db26..1dc84e9fbebed 100644 --- a/mypy/typeshed/stdlib/wsgiref/simple_server.pyi +++ b/mypy/typeshed/stdlib/wsgiref/simple_server.pyi @@ -1,8 +1,8 @@ +from _typeshed.wsgi import ErrorStream, StartResponse, WSGIApplication, WSGIEnvironment from http.server import BaseHTTPRequestHandler, HTTPServer from typing import TypeVar, overload from .handlers import SimpleHandler -from .types import ErrorStream, StartResponse, WSGIApplication, WSGIEnvironment __all__ = ["WSGIServer", "WSGIRequestHandler", "demo_app", "make_server"] diff --git a/mypy/typeshed/stdlib/wsgiref/types.pyi b/mypy/typeshed/stdlib/wsgiref/types.pyi index c272ae67c391d..b8ece8d57a9da 100644 --- a/mypy/typeshed/stdlib/wsgiref/types.pyi +++ b/mypy/typeshed/stdlib/wsgiref/types.pyi @@ -1,3 +1,32 @@ -# Obsolete, use _typeshed.wsgi directly. +from collections.abc import Callable, Iterable +from sys import _OptExcInfo +from typing import Any, Protocol +from typing_extensions import TypeAlias -from _typeshed.wsgi import * +__all__ = ["StartResponse", "WSGIEnvironment", "WSGIApplication", "InputStream", "ErrorStream", "FileWrapper"] + +class StartResponse(Protocol): + def __call__( + self, __status: str, __headers: list[tuple[str, str]], __exc_info: _OptExcInfo | None = ... + ) -> Callable[[bytes], object]: ... + +WSGIEnvironment: TypeAlias = dict[str, Any] +WSGIApplication: TypeAlias = Callable[[WSGIEnvironment, StartResponse], Iterable[bytes]] + +class InputStream(Protocol): + def read(self, __size: int = ...) -> bytes: ... + def readline(self, __size: int = ...) -> bytes: ... + def readlines(self, __hint: int = ...) -> list[bytes]: ... + def __iter__(self) -> Iterable[bytes]: ... + +class ErrorStream(Protocol): + def flush(self) -> object: ... + def write(self, __s: str) -> object: ... + def writelines(self, __seq: list[str]) -> object: ... + +class _Readable(Protocol): + def read(self, __size: int = ...) -> bytes: ... + # Optional: def close(self) -> object: ... + +class FileWrapper(Protocol): + def __call__(self, __file: _Readable, __block_size: int = ...) -> Iterable[bytes]: ... diff --git a/mypy/typeshed/stdlib/wsgiref/util.pyi b/mypy/typeshed/stdlib/wsgiref/util.pyi index f2c3135df786e..36e5c1e69676c 100644 --- a/mypy/typeshed/stdlib/wsgiref/util.pyi +++ b/mypy/typeshed/stdlib/wsgiref/util.pyi @@ -1,7 +1,7 @@ import sys -from typing import IO, Any, Callable - -from .types import WSGIEnvironment +from _typeshed.wsgi import WSGIEnvironment +from collections.abc import Callable +from typing import IO, Any __all__ = ["FileWrapper", "guess_scheme", "application_uri", "request_uri", "shift_path_info", "setup_testing_defaults"] diff --git a/mypy/typeshed/stdlib/wsgiref/validate.pyi b/mypy/typeshed/stdlib/wsgiref/validate.pyi index 35491756c2884..ada2283a6af05 100644 --- a/mypy/typeshed/stdlib/wsgiref/validate.pyi +++ b/mypy/typeshed/stdlib/wsgiref/validate.pyi @@ -1,5 +1,6 @@ from _typeshed.wsgi import ErrorStream, InputStream, WSGIApplication -from typing import Any, Callable, Iterable, Iterator, NoReturn +from collections.abc import Callable, Iterable, Iterator +from typing import Any, NoReturn __all__ = ["validator"] diff --git a/mypy/typeshed/stdlib/xdrlib.pyi b/mypy/typeshed/stdlib/xdrlib.pyi index e9716e29014d3..e6b78d5542bed 100644 --- a/mypy/typeshed/stdlib/xdrlib.pyi +++ b/mypy/typeshed/stdlib/xdrlib.pyi @@ -1,4 +1,5 @@ -from typing import Callable, Sequence, TypeVar +from collections.abc import Callable, Sequence +from typing import TypeVar __all__ = ["Error", "Packer", "Unpacker", "ConversionError"] diff --git a/mypy/typeshed/stdlib/xml/dom/domreg.pyi b/mypy/typeshed/stdlib/xml/dom/domreg.pyi index b9e2dd9eb2631..5a276ae5f561d 100644 --- a/mypy/typeshed/stdlib/xml/dom/domreg.pyi +++ b/mypy/typeshed/stdlib/xml/dom/domreg.pyi @@ -1,5 +1,5 @@ from _typeshed.xml import DOMImplementation -from typing import Callable, Iterable +from collections.abc import Callable, Iterable well_known_implementations: dict[str, str] registered: dict[str, Callable[[], DOMImplementation]] diff --git a/mypy/typeshed/stdlib/xml/dom/minicompat.pyi b/mypy/typeshed/stdlib/xml/dom/minicompat.pyi index 411401d11ccd4..4507b3d98ee76 100644 --- a/mypy/typeshed/stdlib/xml/dom/minicompat.pyi +++ b/mypy/typeshed/stdlib/xml/dom/minicompat.pyi @@ -1,4 +1,5 @@ -from typing import Any, Iterable, TypeVar +from collections.abc import Iterable +from typing import Any, TypeVar __all__ = ["NodeList", "EmptyNodeList", "StringTypes", "defproperty"] diff --git a/mypy/typeshed/stdlib/xml/dom/pulldom.pyi b/mypy/typeshed/stdlib/xml/dom/pulldom.pyi index b2bec64fd1dc5..07f220ddd3471 100644 --- a/mypy/typeshed/stdlib/xml/dom/pulldom.pyi +++ b/mypy/typeshed/stdlib/xml/dom/pulldom.pyi @@ -1,7 +1,8 @@ import sys from _typeshed import SupportsRead -from typing import Any, Sequence -from typing_extensions import Literal +from collections.abc import Sequence +from typing import Any +from typing_extensions import Literal, TypeAlias from xml.dom.minidom import Document, DOMImplementation, Element, Text from xml.sax.handler import ContentHandler from xml.sax.xmlreader import XMLReader @@ -15,10 +16,10 @@ PROCESSING_INSTRUCTION: Literal["PROCESSING_INSTRUCTION"] IGNORABLE_WHITESPACE: Literal["IGNORABLE_WHITESPACE"] CHARACTERS: Literal["CHARACTERS"] -_DocumentFactory = DOMImplementation | None -_Node = Document | Element | Text +_DocumentFactory: TypeAlias = DOMImplementation | None +_Node: TypeAlias = Document | Element | Text -_Event = tuple[ +_Event: TypeAlias = tuple[ Literal[ Literal["START_ELEMENT"], Literal["END_ELEMENT"], diff --git a/mypy/typeshed/stdlib/xml/dom/xmlbuilder.pyi b/mypy/typeshed/stdlib/xml/dom/xmlbuilder.pyi index ec47ec134e085..f6afd8aa27860 100644 --- a/mypy/typeshed/stdlib/xml/dom/xmlbuilder.pyi +++ b/mypy/typeshed/stdlib/xml/dom/xmlbuilder.pyi @@ -1,5 +1,5 @@ from typing import Any, NoReturn -from typing_extensions import Literal +from typing_extensions import Literal, TypeAlias from urllib.request import OpenerDirector from xml.dom.expatbuilder import ExpatBuilder, ExpatBuilderNS from xml.dom.minidom import Node @@ -18,13 +18,13 @@ __all__ = ["DOMBuilder", "DOMEntityResolver", "DOMInputSource"] # probably the same as `Options.errorHandler`? # Maybe `xml.sax.handler.ErrorHandler`? -_DOMBuilderErrorHandlerType = Any | None +_DOMBuilderErrorHandlerType: TypeAlias = Any | None # probably some kind of IO... -_DOMInputSourceCharacterStreamType = Any | None +_DOMInputSourceCharacterStreamType: TypeAlias = Any | None # probably a string?? -_DOMInputSourceStringDataType = Any | None +_DOMInputSourceStringDataType: TypeAlias = Any | None # probably a string?? -_DOMInputSourceEncodingType = Any | None +_DOMInputSourceEncodingType: TypeAlias = Any | None class Options: namespaces: int diff --git a/mypy/typeshed/stdlib/xml/etree/ElementInclude.pyi b/mypy/typeshed/stdlib/xml/etree/ElementInclude.pyi index 5cd85cc217535..7bb78d0628ce7 100644 --- a/mypy/typeshed/stdlib/xml/etree/ElementInclude.pyi +++ b/mypy/typeshed/stdlib/xml/etree/ElementInclude.pyi @@ -1,5 +1,5 @@ import sys -from typing import Callable +from collections.abc import Callable from xml.etree.ElementTree import Element XINCLUDE: str diff --git a/mypy/typeshed/stdlib/xml/etree/ElementPath.pyi b/mypy/typeshed/stdlib/xml/etree/ElementPath.pyi index 5a2dd69c1beea..e5b8223aab343 100644 --- a/mypy/typeshed/stdlib/xml/etree/ElementPath.pyi +++ b/mypy/typeshed/stdlib/xml/etree/ElementPath.pyi @@ -1,11 +1,13 @@ -from typing import Callable, Generator, Pattern, TypeVar +from collections.abc import Callable, Generator +from typing import Pattern, TypeVar +from typing_extensions import TypeAlias from xml.etree.ElementTree import Element xpath_tokenizer_re: Pattern[str] -_token = tuple[str, str] -_next = Callable[[], _token] -_callback = Callable[[_SelectorContext, list[Element]], Generator[Element, None, None]] +_token: TypeAlias = tuple[str, str] +_next: TypeAlias = Callable[[], _token] +_callback: TypeAlias = Callable[[_SelectorContext, list[Element]], Generator[Element, None, None]] def xpath_tokenizer(pattern: str, namespaces: dict[str, str] | None = ...) -> Generator[_token, None, None]: ... def get_parent_map(context: _SelectorContext) -> dict[Element, Element]: ... diff --git a/mypy/typeshed/stdlib/xml/etree/ElementTree.pyi b/mypy/typeshed/stdlib/xml/etree/ElementTree.pyi index 7b50b42790216..414530b0a34c0 100644 --- a/mypy/typeshed/stdlib/xml/etree/ElementTree.pyi +++ b/mypy/typeshed/stdlib/xml/etree/ElementTree.pyi @@ -1,20 +1,8 @@ import sys from _typeshed import FileDescriptor, StrOrBytesPath, SupportsRead, SupportsWrite -from typing import ( - Any, - Callable, - Generator, - ItemsView, - Iterable, - Iterator, - KeysView, - Mapping, - MutableSequence, - Sequence, - TypeVar, - overload, -) -from typing_extensions import Literal, SupportsIndex, TypeGuard +from collections.abc import Callable, Generator, ItemsView, Iterable, Iterator, KeysView, Mapping, MutableSequence, Sequence +from typing import Any, TypeVar, overload +from typing_extensions import Literal, SupportsIndex, TypeAlias, TypeGuard if sys.version_info >= (3, 9): __all__ = [ @@ -101,9 +89,9 @@ else: ] _T = TypeVar("_T") -_FileRead = StrOrBytesPath | FileDescriptor | SupportsRead[bytes] | SupportsRead[str] -_FileWriteC14N = StrOrBytesPath | FileDescriptor | SupportsWrite[bytes] -_FileWrite = _FileWriteC14N | SupportsWrite[str] +_FileRead: TypeAlias = StrOrBytesPath | FileDescriptor | SupportsRead[bytes] | SupportsRead[str] +_FileWriteC14N: TypeAlias = StrOrBytesPath | FileDescriptor | SupportsWrite[bytes] +_FileWrite: TypeAlias = _FileWriteC14N | SupportsWrite[str] VERSION: str @@ -352,7 +340,7 @@ def fromstringlist(sequence: Sequence[str | bytes], parser: XMLParser | None = . # TreeBuilder is called by client code (they could pass strs, bytes or whatever); # but we don't want to use a too-broad type, or it would be too hard to write # elementfactories. -_ElementFactory = Callable[[Any, dict[Any, Any]], Element] +_ElementFactory: TypeAlias = Callable[[Any, dict[Any, Any]], Element] class TreeBuilder: if sys.version_info >= (3, 8): diff --git a/mypy/typeshed/stdlib/xml/sax/__init__.pyi b/mypy/typeshed/stdlib/xml/sax/__init__.pyi index 418164aa887f7..22a2764a699f2 100644 --- a/mypy/typeshed/stdlib/xml/sax/__init__.pyi +++ b/mypy/typeshed/stdlib/xml/sax/__init__.pyi @@ -1,6 +1,7 @@ import sys from _typeshed import SupportsRead, _T_co -from typing import Any, Iterable, NoReturn, Protocol +from collections.abc import Iterable +from typing import Any, NoReturn, Protocol from xml.sax.handler import ContentHandler, ErrorHandler from xml.sax.xmlreader import Locator, XMLReader diff --git a/mypy/typeshed/stdlib/xml/sax/saxutils.pyi b/mypy/typeshed/stdlib/xml/sax/saxutils.pyi index c7304f4b52616..1361949d0c3e9 100644 --- a/mypy/typeshed/stdlib/xml/sax/saxutils.pyi +++ b/mypy/typeshed/stdlib/xml/sax/saxutils.pyi @@ -1,7 +1,7 @@ from _typeshed import SupportsWrite from codecs import StreamReaderWriter, StreamWriter +from collections.abc import Mapping from io import RawIOBase, TextIOBase -from typing import Mapping from xml.sax import handler, xmlreader def escape(data: str, entities: Mapping[str, str] = ...) -> str: ... diff --git a/mypy/typeshed/stdlib/xml/sax/xmlreader.pyi b/mypy/typeshed/stdlib/xml/sax/xmlreader.pyi index 684e9cef1f421..d7d4db5b0a160 100644 --- a/mypy/typeshed/stdlib/xml/sax/xmlreader.pyi +++ b/mypy/typeshed/stdlib/xml/sax/xmlreader.pyi @@ -1,4 +1,4 @@ -from typing import Mapping +from collections.abc import Mapping class XMLReader: def __init__(self) -> None: ... diff --git a/mypy/typeshed/stdlib/xmlrpc/client.pyi b/mypy/typeshed/stdlib/xmlrpc/client.pyi index a59be37f9e812..d4e82d5e40dab 100644 --- a/mypy/typeshed/stdlib/xmlrpc/client.pyi +++ b/mypy/typeshed/stdlib/xmlrpc/client.pyi @@ -3,21 +3,22 @@ import http.client import sys import time from _typeshed import Self, SupportsRead, SupportsWrite +from collections.abc import Callable, Iterable, Mapping from datetime import datetime from io import BytesIO from types import TracebackType -from typing import Any, Callable, Iterable, Mapping, Protocol, Union, overload -from typing_extensions import Literal +from typing import Any, Protocol, Union, overload +from typing_extensions import Literal, TypeAlias class _SupportsTimeTuple(Protocol): def timetuple(self) -> time.struct_time: ... -_DateTimeComparable = DateTime | datetime | str | _SupportsTimeTuple -_Marshallable = ( +_DateTimeComparable: TypeAlias = DateTime | datetime | str | _SupportsTimeTuple +_Marshallable: TypeAlias = ( bool | int | float | str | bytes | None | tuple[Any, ...] | list[Any] | dict[Any, Any] | datetime | DateTime | Binary ) -_XMLDate = int | datetime | tuple[int, ...] | time.struct_time -_HostType = Union[tuple[str, dict[str, str]], str] +_XMLDate: TypeAlias = int | datetime | tuple[int, ...] | time.struct_time +_HostType: TypeAlias = Union[tuple[str, dict[str, str]], str] def escape(s: str) -> str: ... # undocumented diff --git a/mypy/typeshed/stdlib/xmlrpc/server.pyi b/mypy/typeshed/stdlib/xmlrpc/server.pyi index 2ed0b03c71513..371f1821b29d4 100644 --- a/mypy/typeshed/stdlib/xmlrpc/server.pyi +++ b/mypy/typeshed/stdlib/xmlrpc/server.pyi @@ -2,12 +2,14 @@ import http.server import pydoc import socketserver import sys +from collections.abc import Callable, Iterable, Mapping from datetime import datetime -from typing import Any, Callable, Iterable, Mapping, Pattern, Protocol +from typing import Any, Pattern, Protocol +from typing_extensions import TypeAlias from xmlrpc.client import Fault # TODO: Recursive type on tuple, list, dict -_Marshallable = None | bool | int | float | str | bytes | tuple[Any, ...] | list[Any] | dict[Any, Any] | datetime +_Marshallable: TypeAlias = None | bool | int | float | str | bytes | tuple[Any, ...] | list[Any] | dict[Any, Any] | datetime # The dispatch accepts anywhere from 0 to N arguments, no easy way to allow this in mypy class _DispatchArity0(Protocol): @@ -30,7 +32,9 @@ class _DispatchArity4(Protocol): class _DispatchArityN(Protocol): def __call__(self, *args: _Marshallable) -> _Marshallable: ... -_DispatchProtocol = _DispatchArity0 | _DispatchArity1 | _DispatchArity2 | _DispatchArity3 | _DispatchArity4 | _DispatchArityN +_DispatchProtocol: TypeAlias = ( + _DispatchArity0 | _DispatchArity1 | _DispatchArity2 | _DispatchArity3 | _DispatchArity4 | _DispatchArityN +) def resolve_dotted_attribute(obj: Any, attr: str, allow_dotted_names: bool = ...) -> Any: ... # undocumented def list_public_methods(obj: Any) -> list[str]: ... # undocumented diff --git a/mypy/typeshed/stdlib/zipapp.pyi b/mypy/typeshed/stdlib/zipapp.pyi index c3cf8321dbc47..d426401416204 100644 --- a/mypy/typeshed/stdlib/zipapp.pyi +++ b/mypy/typeshed/stdlib/zipapp.pyi @@ -1,10 +1,12 @@ import sys +from collections.abc import Callable from pathlib import Path -from typing import BinaryIO, Callable +from typing import BinaryIO +from typing_extensions import TypeAlias __all__ = ["ZipAppError", "create_archive", "get_interpreter"] -_Path = str | Path | BinaryIO +_Path: TypeAlias = str | Path | BinaryIO class ZipAppError(ValueError): ... diff --git a/mypy/typeshed/stdlib/zipfile.pyi b/mypy/typeshed/stdlib/zipfile.pyi index b837528d7dfa8..d5255b15c3c0b 100644 --- a/mypy/typeshed/stdlib/zipfile.pyi +++ b/mypy/typeshed/stdlib/zipfile.pyi @@ -1,10 +1,11 @@ import io import sys from _typeshed import Self, StrOrBytesPath, StrPath +from collections.abc import Callable, Iterable, Iterator, Sequence from os import PathLike from types import TracebackType -from typing import IO, Any, Callable, Iterable, Iterator, Protocol, Sequence, overload -from typing_extensions import Literal +from typing import IO, Any, Protocol, overload +from typing_extensions import Literal, TypeAlias if sys.version_info >= (3, 8): __all__ = [ @@ -38,10 +39,10 @@ else: "LargeZipFile", ] -_DateTuple = tuple[int, int, int, int, int, int] -_ReadWriteMode = Literal["r", "w"] -_ReadWriteBinaryMode = Literal["r", "w", "rb", "wb"] -_ZipFileMode = Literal["r", "w", "x", "a"] +_DateTuple: TypeAlias = tuple[int, int, int, int, int, int] +_ReadWriteMode: TypeAlias = Literal["r", "w"] +_ReadWriteBinaryMode: TypeAlias = Literal["r", "w", "rb", "wb"] +_ZipFileMode: TypeAlias = Literal["r", "w", "x", "a"] class BadZipFile(Exception): ... diff --git a/mypy/typeshed/stdlib/zoneinfo/__init__.pyi b/mypy/typeshed/stdlib/zoneinfo/__init__.pyi index d766eab6b7efa..0e898cb29740c 100644 --- a/mypy/typeshed/stdlib/zoneinfo/__init__.pyi +++ b/mypy/typeshed/stdlib/zoneinfo/__init__.pyi @@ -1,6 +1,7 @@ from _typeshed import Self, StrPath +from collections.abc import Iterable, Sequence from datetime import tzinfo -from typing import Any, Iterable, Protocol, Sequence +from typing import Any, Protocol __all__ = ["ZoneInfo", "reset_tzpath", "available_timezones", "TZPATH", "ZoneInfoNotFoundError", "InvalidTZPathWarning"] diff --git a/test-data/unit/plugins/decimal_to_int.py b/test-data/unit/plugins/decimal_to_int.py index 21fd3b518b7d2..597010f9a6d14 100644 --- a/test-data/unit/plugins/decimal_to_int.py +++ b/test-data/unit/plugins/decimal_to_int.py @@ -4,7 +4,7 @@ class MyPlugin(Plugin): def get_type_analyze_hook(self, fullname): - if fullname == "decimal.Decimal": + if fullname in ("decimal.Decimal", "_decimal.Decimal"): return decimal_to_int_hook return None From cb6581a8f1f41bf784eebb6a1d2c8a32fb9b43f0 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Mon, 25 Apr 2022 19:12:28 +0100 Subject: [PATCH 256/377] Fix types of inherited attributes in generic dataclasses (#12656) Fixes #12633. --- mypy/plugins/dataclasses.py | 13 ++++--- test-data/unit/check-dataclasses.test | 51 +++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 5 deletions(-) diff --git a/mypy/plugins/dataclasses.py b/mypy/plugins/dataclasses.py index 18caed8bbb8e4..5827a21e8ccf8 100644 --- a/mypy/plugins/dataclasses.py +++ b/mypy/plugins/dataclasses.py @@ -19,6 +19,7 @@ get_proper_type, AnyType, TypeOfAny, ) from mypy.server.trigger import make_wildcard_trigger +from mypy.state import state # The set of decorators that generate dataclasses. dataclass_makers: Final = { @@ -101,10 +102,8 @@ def deserialize( def expand_typevar_from_subtype(self, sub_type: TypeInfo) -> None: """Expands type vars in the context of a subtype when an attribute is inherited from a generic super type.""" - if not isinstance(self.type, TypeVarType): - return - - self.type = map_type_from_supertype(self.type, sub_type, self.info) + if self.type is not None: + self.type = map_type_from_supertype(self.type, sub_type, self.info) class DataclassTransformer: @@ -402,7 +401,11 @@ def collect_attributes(self) -> Optional[List[DataclassAttribute]]: name: str = data["name"] if name not in known_attrs: attr = DataclassAttribute.deserialize(info, data, ctx.api) - attr.expand_typevar_from_subtype(ctx.cls.info) + # TODO: We shouldn't be performing type operations during the main + # semantic analysis pass, since some TypeInfo attributes might + # still be in flux. This should be performed in a later phase. + with state.strict_optional_set(ctx.api.options.strict_optional): + attr.expand_typevar_from_subtype(ctx.cls.info) known_attrs.add(name) super_attrs.append(attr) elif all_attrs: diff --git a/test-data/unit/check-dataclasses.test b/test-data/unit/check-dataclasses.test index 594df103841cf..bce1ee24a31a4 100644 --- a/test-data/unit/check-dataclasses.test +++ b/test-data/unit/check-dataclasses.test @@ -1568,3 +1568,54 @@ class B: class Derived(A, B): pass [builtins fixtures/dataclasses.pyi] + +[case testDataclassGenericInheritance2] +# flags: --python-version 3.7 +from dataclasses import dataclass +from typing import Any, Callable, Generic, TypeVar, List + +T = TypeVar("T") +S = TypeVar("S") + +@dataclass +class Parent(Generic[T]): + f: Callable[[T], Any] + +@dataclass +class Child(Parent[T]): ... + +class A: ... +def func(obj: A) -> bool: ... + +reveal_type(Child[A](func).f) # N: Revealed type is "def (__main__.A) -> Any" + +@dataclass +class Parent2(Generic[T]): + a: List[T] + +@dataclass +class Child2(Generic[T, S], Parent2[S]): + b: List[T] + +reveal_type(Child2([A()], [1]).a) # N: Revealed type is "builtins.list[__main__.A]" +reveal_type(Child2[int, A]([A()], [1]).b) # N: Revealed type is "builtins.list[builtins.int]" +[builtins fixtures/dataclasses.pyi] + +[case testDataclassInheritOptionalType] +# flags: --python-version 3.7 --strict-optional +from dataclasses import dataclass +from typing import Any, Callable, Generic, TypeVar, List, Optional + +T = TypeVar("T") + +@dataclass +class Parent(Generic[T]): + x: Optional[str] +@dataclass +class Child(Parent): + y: Optional[int] +Child(x=1, y=1) # E: Argument "x" to "Child" has incompatible type "int"; expected "Optional[str]" +Child(x='', y='') # E: Argument "y" to "Child" has incompatible type "str"; expected "Optional[int]" +Child(x='', y=1) +Child(x=None, y=None) +[builtins fixtures/dataclasses.pyi] From ee78afe325800f9266ccc0d143b49b8c0b29d8a3 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Wed, 27 Apr 2022 14:58:45 +0100 Subject: [PATCH 257/377] Various documentation updates (mostly about error codes) (#12680) Document some additional error codes and some general doc updates for the 0.950 release. --- docs/source/command_line.rst | 10 ++++---- docs/source/error_code_list.rst | 37 +++++++++++++++++++++++++++++ docs/source/error_code_list2.rst | 38 ++++++++++++++++++++++++++---- docs/source/error_codes.rst | 21 ++++++++++++----- docs/source/installed_packages.rst | 8 +++++++ 5 files changed, 100 insertions(+), 14 deletions(-) diff --git a/docs/source/command_line.rst b/docs/source/command_line.rst index 36c13910c21a3..43c5444ed7bea 100644 --- a/docs/source/command_line.rst +++ b/docs/source/command_line.rst @@ -616,6 +616,7 @@ of the above sections. .. option:: --disable-error-code This flag allows disabling one or multiple error codes globally. + See :ref:`error-codes` for more information. .. code-block:: python @@ -623,20 +624,21 @@ of the above sections. x = 'a string' x.trim() # error: "str" has no attribute "trim" [attr-defined] - # --disable-error-code attr-defined + # When using --disable-error-code attr-defined x = 'a string' x.trim() .. option:: --enable-error-code This flag allows enabling one or multiple error codes globally. + See :ref:`error-codes` for more information. - Note: This flag will override disabled error codes from the --disable-error-code - flag + Note: This flag will override disabled error codes from the + :option:`--disable-error-code ` flag. .. code-block:: python - # --disable-error-code attr-defined + # When using --disable-error-code attr-defined x = 'a string' x.trim() diff --git a/docs/source/error_code_list.rst b/docs/source/error_code_list.rst index e655cae3c45df..5c1f0bedb9805 100644 --- a/docs/source/error_code_list.rst +++ b/docs/source/error_code_list.rst @@ -679,6 +679,43 @@ implementation. def func(value): pass # actual implementation +Check that coroutine return value is used [unused-coroutine] +------------------------------------------------------------ + +Mypy ensures that return values of async def functions are not +ignored, as this is usually a programming error, as the coroutine +won't be executed at the call site. + +.. code-block:: python + + async def f() -> None: + ... + + async def g() -> None: + f() # Error: missing await + await f() # OK + +You can work around this error by assigning the result to a temporary, +otherwise unused variable: + +.. code-block:: python + + _ = f() # No error + +Check types in assert_type [assert-type] +---------------------------------------- + +The inferred type for an expression passed to ``assert_type`` must match +the provided type. + +.. code-block:: python + + from typing_extensions import assert_type + + assert_type([1], list[int]) # OK + + assert_type([1], list[str]) # Error + Report syntax errors [syntax] ----------------------------- diff --git a/docs/source/error_code_list2.rst b/docs/source/error_code_list2.rst index c55643ad6181e..3938669edafcf 100644 --- a/docs/source/error_code_list2.rst +++ b/docs/source/error_code_list2.rst @@ -200,7 +200,7 @@ mypy generates an error if it thinks that an expression is redundant. .. code-block:: python - # mypy: enable-error-code redundant-expr + # Use "mypy --enable-error-code redundant-expr ..." def example(x: int) -> None: # Error: Left operand of "and" is always true [redundant-expr] @@ -222,7 +222,7 @@ since unless implemented by a sub-type, the expression will always evaluate to t .. code-block:: python - # mypy: enable-error-code truthy-bool + # Use "mypy --enable-error-code truthy-bool ..." class Foo: pass @@ -237,7 +237,8 @@ This check might falsely imply an error. For example, ``Iterable`` does not impl .. code-block:: python - # mypy: enable-error-code truthy-bool + # Use "mypy -enable-error-code truthy-bool ..." + from typing import Iterable def transform(items: Iterable[int]) -> Iterable[int]: @@ -270,7 +271,7 @@ Example: .. code-block:: python - # mypy: enable-error-code ignore-without-code + # Use "mypy --enable-error-code ignore-without-code ..." class Foo: def __init__(self, name: str) -> None: @@ -288,3 +289,32 @@ Example: # This line warns correctly about the typo in the attribute name # Error: "Foo" has no attribute "nme"; maybe "name"? f.nme = 42 # type: ignore[assignment] + +Check that awaitable return value is used [unused-awaitable] +------------------------------------------------------------ + +If you use :option:`--enable-error-code unused-awaitable `, +mypy generates an error if you don't use a returned value that defines ``__await__``. + +Example: + +.. code-block:: python + + # Use "mypy --enable-error-code unused-awaitable ..." + + import asyncio + + async def f() -> int: ... + + async def g() -> None: + # Error: Value of type "Task[int]" must be used + # Are you missing an await? + asyncio.create_task(f()) + +You can assign the value to a temporary, otherwise unused to variable to +silence the error: + +.. code-block:: python + + async def g() -> None: + _ = asyncio.create_task(f()) # No error diff --git a/docs/source/error_codes.rst b/docs/source/error_codes.rst index 08d56c59fba20..bed73abc379f4 100644 --- a/docs/source/error_codes.rst +++ b/docs/source/error_codes.rst @@ -24,7 +24,7 @@ Displaying error codes ---------------------- Error codes are not displayed by default. Use :option:`--show-error-codes ` -or config `show_error_codes = True` to display error codes. Error codes are shown inside square brackets: +or config ``show_error_codes = True`` to display error codes. Error codes are shown inside square brackets: .. code-block:: text @@ -46,11 +46,8 @@ line. This can be used even if you have not configured mypy to show error codes. Currently it's only possible to disable arbitrary error codes on individual lines using this comment. -.. note:: - - There are command-line flags and config file settings for enabling - certain optional error codes, such as :option:`--disallow-untyped-defs `, - which enables the ``no-untyped-def`` error code. +You can also use :option:`--disable-error-code ` +to disable specific error codes globally. This example shows how to ignore an error about an imported name mypy thinks is undefined: @@ -60,3 +57,15 @@ thinks is undefined: # 'foo' is defined in 'foolib', even though mypy can't see the # definition. from foolib import foo # type: ignore[attr-defined] + + +Enabling specific error codes +----------------------------- + +There are command-line flags and config file settings for enabling +certain optional error codes, such as :option:`--disallow-untyped-defs `, +which enables the ``no-untyped-def`` error code. + +You can use :option:`--enable-error-code ` to +enable specific error codes that don't have a dedicated command-line +flag or config file setting. diff --git a/docs/source/installed_packages.rst b/docs/source/installed_packages.rst index 8db113e4ba9e4..8e5bff04ea72c 100644 --- a/docs/source/installed_packages.rst +++ b/docs/source/installed_packages.rst @@ -25,6 +25,14 @@ you can create such packages. :pep:`561` specifies how a package can declare that it supports type checking. +.. note:: + + New versions of stub packages often use type system features not + supported by older, and even fairly recent mypy versions. If you + pin to an older version of mypy (using ``requirements.txt``, for + example), it is recommended that you also pin the versions of all + your stub package dependencies. + Using installed packages with mypy (PEP 561) ******************************************** From 3460717a11576d84b5f83cd62282480416c240b2 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Thu, 28 Apr 2022 21:03:22 -0600 Subject: [PATCH 258/377] Remove most mentions of type comments from docs (#12683) --- docs/source/cheat_sheet_py3.rst | 9 +---- docs/source/class_basics.rst | 13 ------- docs/source/command_line.rst | 4 +- docs/source/dynamic_typing.rst | 2 +- docs/source/generics.rst | 6 +-- docs/source/getting_started.rst | 3 -- docs/source/kinds_of_types.rst | 19 ++-------- docs/source/more_types.rst | 8 ++-- .../source/type_inference_and_annotations.rst | 38 ------------------- 9 files changed, 14 insertions(+), 88 deletions(-) diff --git a/docs/source/cheat_sheet_py3.rst b/docs/source/cheat_sheet_py3.rst index e14cde7d50df1..b4847932db50b 100644 --- a/docs/source/cheat_sheet_py3.rst +++ b/docs/source/cheat_sheet_py3.rst @@ -25,10 +25,6 @@ and we use it in most examples. # This is how you declare the type of a variable type in Python 3.6 age: int = 1 - # In Python 3.5 and earlier you can use a type comment instead - # (equivalent to the previous definition) - age = 1 # type: int - # You don't need to initialize a variable to annotate it a: int # Ok (no value at runtime until assigned) @@ -45,7 +41,7 @@ Built-in types .. code-block:: python - + from typing import List, Set, Dict, Tuple, Optional # For simple built-in types, just use the name of the type @@ -65,9 +61,6 @@ Built-in types x: List[int] = [1] x: Set[int] = {6, 7} - # Same as above, but with type comment syntax (Python 3.5 and earlier) - x = [1] # type: List[int] - # For mappings, we need the types of both keys and values x: dict[str, float] = {"field": 2.0} # Python 3.9+ x: Dict[str, float] = {"field": 2.0} diff --git a/docs/source/class_basics.rst b/docs/source/class_basics.rst index 3c12b4b06d9b1..a7f57afee4e73 100644 --- a/docs/source/class_basics.rst +++ b/docs/source/class_basics.rst @@ -42,19 +42,6 @@ As in Python generally, a variable defined in the class body can be used as a class or an instance variable. (As discussed in the next section, you can override this with a :py:data:`~typing.ClassVar` annotation.) -Type comments work as well, if you need to support Python versions earlier -than 3.6: - -.. code-block:: python - - class A: - x = None # type: list[int] # Declare attribute 'x' of type list[int] - -Note that attribute definitions in the class body that use a type comment -are special: a ``None`` value is valid as the initializer, even though -the declared type is not optional. This should be used sparingly, as this can -result in ``None``-related runtime errors that mypy can't detect. - Similarly, you can give explicit types to instance variables defined in a method: diff --git a/docs/source/command_line.rst b/docs/source/command_line.rst index 43c5444ed7bea..1a35d81a7ee9e 100644 --- a/docs/source/command_line.rst +++ b/docs/source/command_line.rst @@ -548,11 +548,11 @@ of the above sections. from typing import Optional a = None # Need type annotation here if using --local-partial-types - b = None # type: Optional[int] + b: Optional[int] = None class Foo: bar = None # Need type annotation here if using --local-partial-types - baz = None # type: Optional[int] + baz: Optional[int] = None def __init__(self) -> None: self.bar = 1 diff --git a/docs/source/dynamic_typing.rst b/docs/source/dynamic_typing.rst index add4450096667..390bc52d9e2ca 100644 --- a/docs/source/dynamic_typing.rst +++ b/docs/source/dynamic_typing.rst @@ -77,7 +77,7 @@ operations: o.foo() # Error! o + 2 # Error! open(o) # Error! - n = 1 # type: int + n: int = 1 n = o # Error! You can use different :ref:`type narrowing ` diff --git a/docs/source/generics.rst b/docs/source/generics.rst index 7730bd0e5c108..bf34c286d8414 100644 --- a/docs/source/generics.rst +++ b/docs/source/generics.rst @@ -295,8 +295,8 @@ In this way, for example, you can typecheck chaining of setter methods: self.width = w return self - circle = Circle().set_scale(0.5).set_radius(2.7) # type: Circle - square = Square().set_scale(0.5).set_width(3.2) # type: Square + circle: Circle = Circle().set_scale(0.5).set_radius(2.7) + square: Square = Square().set_scale(0.5).set_width(3.2) Without using generic ``self``, the last two lines could not be type-checked properly. @@ -310,7 +310,7 @@ For class methods, you can also define generic ``cls``, using :py:class:`Type[T] T = TypeVar('T', bound='Friend') class Friend: - other = None # type: Friend + other: "Friend" = None @classmethod def make_pair(cls: Type[T]) -> tuple[T, T]: diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst index 124edd650d27e..ee102ad8b6398 100644 --- a/docs/source/getting_started.rst +++ b/docs/source/getting_started.rst @@ -317,9 +317,6 @@ syntax like so: # If you're using Python 3.6+ my_global_dict: Dict[int, float] = {} - # If you want compatibility with even older versions of Python - my_global_dict = {} # type: Dict[int, float] - .. _stubs-intro: Library stubs and typeshed diff --git a/docs/source/kinds_of_types.rst b/docs/source/kinds_of_types.rst index 51f54ab0e1e6b..806dc571d45ac 100644 --- a/docs/source/kinds_of_types.rst +++ b/docs/source/kinds_of_types.rst @@ -347,23 +347,13 @@ This also works for attributes defined within methods: def __init__(self) -> None: self.count: Optional[int] = None -As a special case, you can use a non-optional type when initializing an -attribute to ``None`` inside a class body *and* using a type comment, -since when using a type comment, an initializer is syntactically required, -and ``None`` is used as a dummy, placeholder initializer: +This is not a problem when using variable annotations, since no initial +value is needed: .. code-block:: python class Container: - items = None # type: list[str] # OK (only with type comment) - -This is not a problem when using variable annotations, since no initializer -is needed: - -.. code-block:: python - - class Container: - items: list[str] # No initializer + items: list[str] # No initial value Mypy generally uses the first assignment to a variable to infer the type of the variable. However, if you assign both a ``None`` @@ -421,9 +411,6 @@ the runtime with some limitations (see :ref:`runtime_troubles`). t2: int | None # equivalent to Optional[int] - # Usable in type comments - t3 = 42 # type: int | str - .. _no_strict_optional: Disabling strict optional checking diff --git a/docs/source/more_types.rst b/docs/source/more_types.rst index dd688cab7e17b..c04cefe311913 100644 --- a/docs/source/more_types.rst +++ b/docs/source/more_types.rst @@ -120,7 +120,7 @@ implicitly casting from ``UserId`` where ``int`` is expected. Examples: name_by_id(42) # Fails type check name_by_id(UserId(42)) # OK - num = UserId(5) + 1 # type: int + num: int = UserId(5) + 1 :py:func:`NewType ` accepts exactly two arguments. The first argument must be a string literal containing the name of the new type and must equal the name of the variable to which the new @@ -985,7 +985,7 @@ dictionary value depends on the key: Movie = TypedDict('Movie', {'name': str, 'year': int}) - movie = {'name': 'Blade Runner', 'year': 1982} # type: Movie + movie: Movie = {'name': 'Blade Runner', 'year': 1982} ``Movie`` is a ``TypedDict`` type with two items: ``'name'`` (with type ``str``) and ``'year'`` (with type ``int``). Note that we used an explicit type @@ -1080,7 +1080,7 @@ keys. This will be flagged as an error: .. code-block:: python # Error: 'year' missing - toy_story = {'name': 'Toy Story'} # type: Movie + toy_story: Movie = {'name': 'Toy Story'} Sometimes you want to allow keys to be left out when creating a ``TypedDict`` object. You can provide the ``total=False`` argument to @@ -1090,7 +1090,7 @@ Sometimes you want to allow keys to be left out when creating a GuiOptions = TypedDict( 'GuiOptions', {'language': str, 'color': str}, total=False) - options = {} # type: GuiOptions # Okay + options: GuiOptions = {} # Okay options['language'] = 'en' You may need to use :py:meth:`~dict.get` to access items of a partial (non-total) diff --git a/docs/source/type_inference_and_annotations.rst b/docs/source/type_inference_and_annotations.rst index 8150f88e579e4..040961d40a401 100644 --- a/docs/source/type_inference_and_annotations.rst +++ b/docs/source/type_inference_and_annotations.rst @@ -44,23 +44,6 @@ type: x: Union[int, str] = 1.1 # Error! -The variable annotation syntax is available starting from Python 3.6. -In earlier Python versions, you can use a special comment after an -assignment statement to declare the type of a variable: - -.. code-block:: python - - x = 1 # type: Union[int, str] - -We'll use both syntax variants in examples. The syntax variants are -mostly interchangeable, but the variable annotation syntax allows -defining the type of a variable without initialization, which is not -possible with the comment syntax: - -.. code-block:: python - - x: str # Declare type of 'x' without initialization - .. note:: The best way to think about this is that the type annotation sets the @@ -182,27 +165,6 @@ Working around the issue is easy by adding a type annotation: a: list[int] = [] # OK foo(a) -Declaring multiple variable types at a time -******************************************* - -You can declare more than a single variable at a time, but only with -a type comment. In order to nicely work with multiple assignment, you -must give each variable a type separately: - -.. code-block:: python - - i, found = 0, False # type: int, bool - -You can optionally use parentheses around the types, assignment targets -and assigned expression: - -.. code-block:: python - - i, found = 0, False # type: (int, bool) # OK - (i, found) = 0, False # type: int, bool # OK - i, found = (0, False) # type: int, bool # OK - (i, found) = (0, False) # type: (int, bool) # OK - Starred expressions ******************* From a3abd3644c5f2c84d2fa65fb621327a6c6a0e695 Mon Sep 17 00:00:00 2001 From: Hugues Date: Fri, 29 Apr 2022 07:21:22 -0700 Subject: [PATCH 259/377] errors: speedup for large error counts and improve error filtering (#12631) * errors: speedup for large error counts We have a legacy codebase with many errors across many files ``` Found 7995 errors in 2218 files (checked 21364 source files) ``` For historical reasons, it hasn't been practical to fix all of these yet, and we've been slowly chipping at them over time. Profiling shows that `is_blockers` is the biggest single hotspot, taking roughly 1min, and `total_errors` account for another 11s. Instead of computing those values on read by iterating over all errors, update auxiliary variables appropriately every time a new error is recorded. * errors: unify and optimize error filtering Instead of maintaining two separate mechanism to filter out errors (boolean flag in MessageBuilder and explicit copy of MessageBuilder/Errors) expand ErrorWatcher to support all relevant usage patterns and update all usages accordingly. This is both cleaner and more robust than the previous approach, and should also offer a slight performance improvement by reducing allocations. --- mypy/checker.py | 51 +++++------ mypy/checkexpr.py | 188 +++++++++++++++++++---------------------- mypy/checkmember.py | 17 ++-- mypy/checkpattern.py | 77 ++++++++--------- mypy/checkstrformat.py | 4 +- mypy/errors.py | 105 ++++++++++++++++++++--- mypy/messages.py | 75 +++++----------- 7 files changed, 277 insertions(+), 240 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 24f101421ff46..002f28d4db6cb 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -2196,7 +2196,7 @@ def is_raising_or_empty(self, s: Statement) -> bool: if isinstance(s.expr, EllipsisExpr): return True elif isinstance(s.expr, CallExpr): - with self.expr_checker.msg.disable_errors(): + with self.expr_checker.msg.filter_errors(): typ = get_proper_type(self.expr_checker.accept( s.expr, allow_none_return=True, always_allow_any=True)) @@ -3377,7 +3377,7 @@ def check_member_assignment(self, instance_type: Type, attribute_type: Type, # For non-overloaded setters, the result should be type-checked like a regular assignment. # Hence, we first only try to infer the type by using the rvalue as type context. type_context = rvalue - with self.msg.disable_errors(): + with self.msg.filter_errors(): _, inferred_dunder_set_type = self.expr_checker.check_call( dunder_set_type, [TempNode(instance_type, context=context), type_context], @@ -4312,9 +4312,6 @@ def _make_fake_typeinfo_and_full_name( ) return info_, full_name_ - old_msg = self.msg - new_msg = old_msg.clean_copy() - self.msg = new_msg base_classes = _get_base_classes(instances) # We use the pretty_names_list for error messages but can't # use it for the real name that goes into the symbol table @@ -4322,24 +4319,22 @@ def _make_fake_typeinfo_and_full_name( pretty_names_list = pretty_seq(format_type_distinctly(*base_classes, bare=True), "and") try: info, full_name = _make_fake_typeinfo_and_full_name(base_classes, curr_module) - self.check_multiple_inheritance(info) - if new_msg.is_errors(): + with self.msg.filter_errors() as local_errors: + self.check_multiple_inheritance(info) + if local_errors.has_new_errors(): # "class A(B, C)" unsafe, now check "class A(C, B)": - new_msg = new_msg.clean_copy() - self.msg = new_msg base_classes = _get_base_classes(instances[::-1]) info, full_name = _make_fake_typeinfo_and_full_name(base_classes, curr_module) - self.check_multiple_inheritance(info) + with self.msg.filter_errors() as local_errors: + self.check_multiple_inheritance(info) info.is_intersection = True except MroError: if self.should_report_unreachable_issues(): - old_msg.impossible_intersection( + self.msg.impossible_intersection( pretty_names_list, "inconsistent method resolution order", ctx) return None - finally: - self.msg = old_msg - if new_msg.is_errors(): + if local_errors.has_new_errors(): if self.should_report_unreachable_issues(): self.msg.impossible_intersection( pretty_names_list, "incompatible method signatures", ctx) @@ -4974,20 +4969,20 @@ def refine_parent_types(self, member_name = expr.name def replay_lookup(new_parent_type: ProperType) -> Optional[Type]: - msg_copy = self.msg.clean_copy() - member_type = analyze_member_access( - name=member_name, - typ=new_parent_type, - context=parent_expr, - is_lvalue=False, - is_super=False, - is_operator=False, - msg=msg_copy, - original_type=new_parent_type, - chk=self, - in_literal_context=False, - ) - if msg_copy.is_errors(): + with self.msg.filter_errors() as w: + member_type = analyze_member_access( + name=member_name, + typ=new_parent_type, + context=parent_expr, + is_lvalue=False, + is_super=False, + is_operator=False, + msg=self.msg, + original_type=new_parent_type, + chk=self, + in_literal_context=False, + ) + if w.has_new_errors(): return None else: return member_type diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index c6f4d24c1815f..f6aef2e361cce 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -1,6 +1,6 @@ """Expression type checker. This file is conceptually part of TypeChecker.""" -from mypy.backports import OrderedDict, nullcontext +from mypy.backports import OrderedDict from contextlib import contextmanager import itertools from typing import ( @@ -8,7 +8,7 @@ ) from typing_extensions import ClassVar, Final, overload, TypeAlias as _TypeAlias -from mypy.errors import report_internal_error +from mypy.errors import report_internal_error, ErrorWatcher from mypy.typeanal import ( has_any_from_unimported_type, check_for_explicit_any, set_any_tvars, expand_type_alias, make_optional_type, @@ -887,7 +887,7 @@ def check_union_call_expr(self, e: CallExpr, object_type: UnionType, member: str res: List[Type] = [] for typ in object_type.relevant_items(): # Member access errors are already reported when visiting the member expression. - with self.msg.disable_errors(): + with self.msg.filter_errors(): item = analyze_member_access(member, typ, e, False, False, False, self.msg, original_type=object_type, chk=self.chk, in_literal_context=self.is_literal_context(), @@ -1244,7 +1244,7 @@ def infer_function_type_arguments(self, callee_type: CallableType, # due to partial available context information at this time, but # these errors can be safely ignored as the arguments will be # inferred again later. - with self.msg.disable_errors(): + with self.msg.filter_errors(): arg_types = self.infer_arg_types_in_context( callee_type, args, arg_kinds, formal_to_actual) @@ -1594,13 +1594,13 @@ def check_overload_call(self, unioned_result: Optional[Tuple[Type, Type]] = None union_interrupted = False # did we try all union combinations? if any(self.real_union(arg) for arg in arg_types): - unioned_errors = arg_messages.clean_copy() try: - unioned_return = self.union_overload_result(plausible_targets, args, - arg_types, arg_kinds, arg_names, - callable_name, object_type, - context, - arg_messages=unioned_errors) + with arg_messages.filter_errors(): + unioned_return = self.union_overload_result(plausible_targets, args, + arg_types, arg_kinds, arg_names, + callable_name, object_type, + context, + arg_messages=arg_messages) except TooManyUnions: union_interrupted = True else: @@ -1751,29 +1751,18 @@ def infer_overload_return_type(self, args_contain_any = any(map(has_any_type, arg_types)) for typ in plausible_targets: - overload_messages = self.msg.clean_copy() - prev_messages = self.msg assert self.msg is self.chk.msg - self.msg = overload_messages - self.chk.msg = overload_messages - try: - # Passing `overload_messages` as the `arg_messages` parameter doesn't - # seem to reliably catch all possible errors. - # TODO: Figure out why + with self.msg.filter_errors() as w: ret_type, infer_type = self.check_call( callee=typ, args=args, arg_kinds=arg_kinds, arg_names=arg_names, context=context, - arg_messages=overload_messages, + arg_messages=self.msg, callable_name=callable_name, object_type=object_type) - finally: - self.chk.msg = prev_messages - self.msg = prev_messages - - is_match = not overload_messages.is_errors() + is_match = not w.has_new_errors() if is_match: # Return early if possible; otherwise record info so we can # check for ambiguity due to 'Any' below. @@ -2254,15 +2243,15 @@ def visit_comparison_expr(self, e: ComparisonExpr) -> Type: # Keep track of whether we get type check errors (these won't be reported, they # are just to verify whether something is valid typing wise). - local_errors = self.msg.clean_copy() - _, method_type = self.check_method_call_by_name( - method='__contains__', - base_type=right_type, - args=[left], - arg_kinds=[ARG_POS], - context=e, - local_errors=local_errors, - ) + with self.msg.filter_errors(save_filtered_errors=True) as local_errors: + _, method_type = self.check_method_call_by_name( + method='__contains__', + base_type=right_type, + args=[left], + arg_kinds=[ARG_POS], + context=e, + ) + sub_result = self.bool_type() # Container item type for strict type overlap checks. Note: we need to only # check for nominal type, because a usual "Unsupported operands for in" @@ -2272,7 +2261,7 @@ def visit_comparison_expr(self, e: ComparisonExpr) -> Type: if isinstance(right_type, PartialType): # We don't really know if this is an error or not, so just shut up. pass - elif (local_errors.is_errors() and + elif (local_errors.has_new_errors() and # is_valid_var_arg is True for any Iterable self.is_valid_var_arg(right_type)): _, itertype = self.chk.analyze_iterable_item_type(right) @@ -2285,20 +2274,22 @@ def visit_comparison_expr(self, e: ComparisonExpr) -> Type: if not is_subtype(left_type, itertype): self.msg.unsupported_operand_types('in', left_type, right_type, e) # Only show dangerous overlap if there are no other errors. - elif (not local_errors.is_errors() and cont_type and + elif (not local_errors.has_new_errors() and cont_type and self.dangerous_comparison(left_type, cont_type, original_container=right_type)): self.msg.dangerous_comparison(left_type, cont_type, 'container', e) else: - self.msg.add_errors(local_errors) + self.msg.add_errors(local_errors.filtered_errors()) elif operator in operators.op_methods: method = self.get_operator_method(operator) - err_count = self.msg.errors.total_errors() - sub_result, method_type = self.check_op(method, left_type, right, e, - allow_reverse=True) + + with ErrorWatcher(self.msg.errors) as w: + sub_result, method_type = self.check_op(method, left_type, right, e, + allow_reverse=True) + # Only show dangerous overlap if there are no other errors. See # testCustomEqCheckStrictEquality for an example. - if self.msg.errors.total_errors() == err_count and operator in ('==', '!='): + if not w.has_new_errors() and operator in ('==', '!='): right_type = self.accept(right) # We suppress the error if there is a custom __eq__() method on either # side. User defined (or even standard library) classes can define this @@ -2525,24 +2516,20 @@ def lookup_operator(op_name: str, base_type: Type) -> Optional[Type]: if not self.has_member(base_type, op_name): return None - local_errors = msg.clean_copy() - - member = analyze_member_access( - name=op_name, - typ=base_type, - is_lvalue=False, - is_super=False, - is_operator=True, - original_type=base_type, - context=context, - msg=local_errors, - chk=self.chk, - in_literal_context=self.is_literal_context() - ) - if local_errors.is_errors(): - return None - else: - return member + with self.msg.filter_errors() as w: + member = analyze_member_access( + name=op_name, + typ=base_type, + is_lvalue=False, + is_super=False, + is_operator=True, + original_type=base_type, + context=context, + msg=self.msg, + chk=self.chk, + in_literal_context=self.is_literal_context() + ) + return None if w.has_new_errors() else member def lookup_definer(typ: Instance, attr_name: str) -> Optional[str]: """Returns the name of the class that contains the actual definition of attr_name. @@ -2656,11 +2643,11 @@ def lookup_definer(typ: Instance, attr_name: str) -> Optional[str]: errors = [] results = [] for method, obj, arg in variants: - local_errors = msg.clean_copy() - result = self.check_method_call( - op_name, obj, method, [arg], [ARG_POS], context, local_errors) - if local_errors.is_errors(): - errors.append(local_errors) + with self.msg.filter_errors(save_filtered_errors=True) as local_errors: + result = self.check_method_call( + op_name, obj, method, [arg], [ARG_POS], context) + if local_errors.has_new_errors(): + errors.append(local_errors.filtered_errors()) results.append(result) else: return result @@ -2678,12 +2665,12 @@ def lookup_definer(typ: Instance, attr_name: str) -> Optional[str]: # call the __op__ method (even though it's missing). if not variants: - local_errors = msg.clean_copy() - result = self.check_method_call_by_name( - op_name, left_type, [right_expr], [ARG_POS], context, local_errors) + with self.msg.filter_errors(save_filtered_errors=True) as local_errors: + result = self.check_method_call_by_name( + op_name, left_type, [right_expr], [ARG_POS], context) - if local_errors.is_errors(): - errors.append(local_errors) + if local_errors.has_new_errors(): + errors.append(local_errors.filtered_errors()) results.append(result) else: # In theory, we should never enter this case, but it seems @@ -2724,23 +2711,23 @@ def check_op(self, method: str, base_type: Type, # Step 1: We first try leaving the right arguments alone and destructure # just the left ones. (Mypy can sometimes perform some more precise inference # if we leave the right operands a union -- see testOperatorWithEmptyListAndSum.) - msg = self.msg.clean_copy() all_results = [] all_inferred = [] - for left_possible_type in left_variants: - result, inferred = self.check_op_reversible( - op_name=method, - left_type=left_possible_type, - left_expr=TempNode(left_possible_type, context=context), - right_type=right_type, - right_expr=arg, - context=context, - msg=msg) - all_results.append(result) - all_inferred.append(inferred) + with self.msg.filter_errors() as local_errors: + for left_possible_type in left_variants: + result, inferred = self.check_op_reversible( + op_name=method, + left_type=left_possible_type, + left_expr=TempNode(left_possible_type, context=context), + right_type=right_type, + right_expr=arg, + context=context, + msg=self.msg) + all_results.append(result) + all_inferred.append(inferred) - if not msg.is_errors(): + if not local_errors.has_new_errors(): results_final = make_simplified_union(all_results) inferred_final = make_simplified_union(all_inferred) return results_final, inferred_final @@ -2765,27 +2752,30 @@ def check_op(self, method: str, base_type: Type, handle_type_alias_type=True) ] - msg = self.msg.clean_copy() all_results = [] all_inferred = [] - for left_possible_type in left_variants: - for right_possible_type, right_expr in right_variants: - result, inferred = self.check_op_reversible( - op_name=method, - left_type=left_possible_type, - left_expr=TempNode(left_possible_type, context=context), - right_type=right_possible_type, - right_expr=right_expr, - context=context, - msg=msg) - all_results.append(result) - all_inferred.append(inferred) - - if msg.is_errors(): - self.msg.add_errors(msg) + with self.msg.filter_errors(save_filtered_errors=True) as local_errors: + for left_possible_type in left_variants: + for right_possible_type, right_expr in right_variants: + result, inferred = self.check_op_reversible( + op_name=method, + left_type=left_possible_type, + left_expr=TempNode(left_possible_type, context=context), + right_type=right_possible_type, + right_expr=right_expr, + context=context, + msg=self.msg) + all_results.append(result) + all_inferred.append(inferred) + + if local_errors.has_new_errors(): + self.msg.add_errors(local_errors.filtered_errors()) # Point any notes to the same location as an existing message. - recent_context = msg.most_recent_context() + err = local_errors.filtered_errors()[-1] + recent_context = TempNode(NoneType()) + recent_context.line = err.line + recent_context.column = err.column if len(left_variants) >= 2 and len(right_variants) >= 2: self.msg.warn_both_operands_are_from_unions(recent_context) elif len(left_variants) >= 2: @@ -2864,7 +2854,7 @@ def check_boolean_op(self, e: OpExpr, context: Context) -> Type: # If right_map is None then we know mypy considers the right branch # to be unreachable and therefore any errors found in the right branch # should be suppressed. - with (self.msg.disable_errors() if right_map is None else nullcontext()): + with self.msg.filter_errors(filter_errors=right_map is None): right_type = self.analyze_cond_branch(right_map, e.right, expanded_left_type) if left_map is None and right_map is None: diff --git a/mypy/checkmember.py b/mypy/checkmember.py index 16bd0e074c3f3..2659ad18ed6e4 100644 --- a/mypy/checkmember.py +++ b/mypy/checkmember.py @@ -273,13 +273,11 @@ def analyze_type_type_member_access(name: str, # Similar to analyze_type_callable_attribute_access. item = None fallback = mx.named_type('builtins.type') - ignore_messages = mx.msg.copy() - ignore_messages.disable_errors().__enter__() if isinstance(typ.item, Instance): item = typ.item elif isinstance(typ.item, AnyType): - mx = mx.copy_modified(messages=ignore_messages) - return _analyze_member_access(name, fallback, mx, override_info) + with mx.msg.filter_errors(): + return _analyze_member_access(name, fallback, mx, override_info) elif isinstance(typ.item, TypeVarType): upper_bound = get_proper_type(typ.item.upper_bound) if isinstance(upper_bound, Instance): @@ -287,8 +285,8 @@ def analyze_type_type_member_access(name: str, elif isinstance(upper_bound, TupleType): item = tuple_fallback(upper_bound) elif isinstance(upper_bound, AnyType): - mx = mx.copy_modified(messages=ignore_messages) - return _analyze_member_access(name, fallback, mx, override_info) + with mx.msg.filter_errors(): + return _analyze_member_access(name, fallback, mx, override_info) elif isinstance(typ.item, TupleType): item = tuple_fallback(typ.item) elif isinstance(typ.item, FunctionLike) and typ.item.is_type_obj(): @@ -297,6 +295,7 @@ def analyze_type_type_member_access(name: str, # Access member on metaclass object via Type[Type[C]] if isinstance(typ.item.item, Instance): item = typ.item.item.type.metaclass_type + ignore_messages = False if item and not mx.is_operator: # See comment above for why operators are skipped result = analyze_class_attribute_access(item, name, mx, override_info) @@ -305,10 +304,12 @@ def analyze_type_type_member_access(name: str, return result else: # We don't want errors on metaclass lookup for classes with Any fallback - mx = mx.copy_modified(messages=ignore_messages) + ignore_messages = True if item is not None: fallback = item.type.metaclass_type or fallback - return _analyze_member_access(name, fallback, mx, override_info) + + with mx.msg.filter_errors(filter_errors=ignore_messages): + return _analyze_member_access(name, fallback, mx, override_info) def analyze_union_member_access(name: str, typ: UnionType, mx: MemberContext) -> Type: diff --git a/mypy/checkpattern.py b/mypy/checkpattern.py index e1d4f9fe285e7..84b9acae1aa20 100644 --- a/mypy/checkpattern.py +++ b/mypy/checkpattern.py @@ -416,29 +416,29 @@ def get_mapping_item_type(self, mapping_type: Type, key: Expression ) -> Optional[Type]: - local_errors = self.msg.clean_copy() - local_errors.disable_count = 0 mapping_type = get_proper_type(mapping_type) if isinstance(mapping_type, TypedDictType): - result: Optional[Type] = self.chk.expr_checker.visit_typeddict_index_expr( - mapping_type, key, local_errors=local_errors) + with self.msg.filter_errors() as local_errors: + result: Optional[Type] = self.chk.expr_checker.visit_typeddict_index_expr( + mapping_type, key) + has_local_errors = local_errors.has_new_errors() # If we can't determine the type statically fall back to treating it as a normal # mapping - if local_errors.is_errors(): - local_errors = self.msg.clean_copy() - local_errors.disable_count = 0 + if has_local_errors: + with self.msg.filter_errors() as local_errors: + result = self.get_simple_mapping_item_type(pattern, + mapping_type, + key, + self.msg) + + if local_errors.has_new_errors(): + result = None + else: + with self.msg.filter_errors(): result = self.get_simple_mapping_item_type(pattern, mapping_type, key, - local_errors) - - if local_errors.is_errors(): - result = None - else: - result = self.get_simple_mapping_item_type(pattern, - mapping_type, - key, - local_errors) + self.msg) return result def get_simple_mapping_item_type(self, @@ -507,14 +507,14 @@ def visit_class_pattern(self, o: ClassPattern) -> PatternType: pattern_type.captures) captures = pattern_type.captures else: - local_errors = self.msg.clean_copy() - match_args_type = analyze_member_access("__match_args__", typ, o, - False, False, False, - local_errors, - original_type=typ, - chk=self.chk) - - if local_errors.is_errors(): + with self.msg.filter_errors() as local_errors: + match_args_type = analyze_member_access("__match_args__", typ, o, + False, False, False, + self.msg, + original_type=typ, + chk=self.chk) + has_local_errors = local_errors.has_new_errors() + if has_local_errors: self.msg.fail(message_registry.MISSING_MATCH_ARGS.format(typ), o) return self.early_non_match() @@ -561,20 +561,21 @@ def visit_class_pattern(self, o: ClassPattern) -> PatternType: can_match = True for keyword, pattern in keyword_pairs: key_type: Optional[Type] = None - local_errors = self.msg.clean_copy() - if keyword is not None: - key_type = analyze_member_access(keyword, - narrowed_type, - pattern, - False, - False, - False, - local_errors, - original_type=new_type, - chk=self.chk) - else: - key_type = AnyType(TypeOfAny.from_error) - if local_errors.is_errors() or key_type is None: + with self.msg.filter_errors() as local_errors: + if keyword is not None: + key_type = analyze_member_access(keyword, + narrowed_type, + pattern, + False, + False, + False, + self.msg, + original_type=new_type, + chk=self.chk) + else: + key_type = AnyType(TypeOfAny.from_error) + has_local_errors = local_errors.has_new_errors() + if has_local_errors or key_type is None: key_type = AnyType(TypeOfAny.from_error) self.msg.fail(message_registry.CLASS_PATTERN_UNKNOWN_KEYWORD.format(typ, keyword), pattern) diff --git a/mypy/checkstrformat.py b/mypy/checkstrformat.py index dcb711150870b..995f3073ba798 100644 --- a/mypy/checkstrformat.py +++ b/mypy/checkstrformat.py @@ -17,6 +17,7 @@ ) from typing_extensions import Final, TYPE_CHECKING, TypeAlias as _TypeAlias +from mypy.errors import Errors from mypy.types import ( Type, AnyType, TupleType, Instance, UnionType, TypeOfAny, get_proper_type, TypeVarType, LiteralType, get_proper_types @@ -512,8 +513,7 @@ def apply_field_accessors(self, spec: ConversionSpecifier, repl: Expression, return repl assert spec.field - # This is a bit of a dirty trick, but it looks like this is the simplest way. - temp_errors = self.msg.clean_copy().errors + temp_errors = Errors() dummy = DUMMY_FIELD_NAME + spec.field[len(spec.key):] temp_ast: Node = parse( dummy, fnam="", module=None, options=self.chk.options, errors=temp_errors diff --git a/mypy/errors.py b/mypy/errors.py index 20e43fa810f90..6dc0a21e79041 100644 --- a/mypy/errors.py +++ b/mypy/errors.py @@ -4,8 +4,8 @@ from mypy.backports import OrderedDict from collections import defaultdict -from typing import Tuple, List, TypeVar, Set, Dict, Optional, TextIO, Callable -from typing_extensions import Final +from typing import Tuple, List, TypeVar, Set, Dict, Optional, TextIO, Callable, Union +from typing_extensions import Final, Literal from mypy.scope import Scope from mypy.options import Options @@ -122,6 +122,58 @@ def __init__(self, Optional[ErrorCode]] +class ErrorWatcher: + """Context manager that can be used to keep track of new errors recorded + around a given operation. + + Errors maintain a stack of such watchers. The handler is called starting + at the top of the stack, and is propagated down the stack unless filtered + out by one of the ErrorWatcher instances. + """ + def __init__(self, errors: 'Errors', *, + filter_errors: Union[bool, Callable[[str, ErrorInfo], bool]] = False, + save_filtered_errors: bool = False): + self.errors = errors + self._has_new_errors = False + self._filter = filter_errors + self._filtered: Optional[List[ErrorInfo]] = [] if save_filtered_errors else None + + def __enter__(self) -> 'ErrorWatcher': + self.errors._watchers.append(self) + return self + + def __exit__(self, exc_type: object, exc_val: object, exc_tb: object) -> Literal[False]: + assert self == self.errors._watchers.pop() + return False + + def on_error(self, file: str, info: ErrorInfo) -> bool: + """Handler called when a new error is recorded. + + The default implementation just sets the has_new_errors flag + + Return True to filter out the error, preventing it from being seen by other + ErrorWatcher further down the stack and from being recorded by Errors + """ + self._has_new_errors = True + if isinstance(self._filter, bool): + should_filter = self._filter + elif callable(self._filter): + should_filter = self._filter(file, info) + else: + raise AssertionError("invalid error filter: {}".format(type(self._filter))) + if should_filter and self._filtered is not None: + self._filtered.append(info) + + return should_filter + + def has_new_errors(self) -> bool: + return self._has_new_errors + + def filtered_errors(self) -> List[ErrorInfo]: + assert self._filtered is not None + return self._filtered + + class Errors: """Container for compile errors. @@ -134,6 +186,9 @@ class Errors: # files were processed. error_info_map: Dict[str, List[ErrorInfo]] + # optimization for legacy codebases with many files with errors + has_blockers: Set[str] + # Files that we have reported the errors for flushed_files: Set[str] @@ -178,6 +233,8 @@ class Errors: # in some cases to avoid reporting huge numbers of errors. seen_import_error = False + _watchers: List[ErrorWatcher] = [] + def __init__(self, show_error_context: bool = False, show_column_numbers: bool = False, @@ -209,6 +266,7 @@ def initialize(self) -> None: self.used_ignored_lines = defaultdict(lambda: defaultdict(list)) self.ignored_files = set() self.only_once_messages = set() + self.has_blockers = set() self.scope = None self.target_module = None self.seen_import_error = False @@ -234,9 +292,6 @@ def copy(self) -> 'Errors': new.seen_import_error = self.seen_import_error return new - def total_errors(self) -> int: - return sum(len(errs) for errs in self.error_info_map.values()) - def set_ignore_prefix(self, prefix: str) -> None: """Set path prefix that will be removed from all paths.""" prefix = os.path.normpath(prefix) @@ -354,14 +409,39 @@ def report(self, def _add_error_info(self, file: str, info: ErrorInfo) -> None: assert file not in self.flushed_files + # process the stack of ErrorWatchers before modifying any internal state + # in case we need to filter out the error entirely + if self._filter_error(file, info): + return if file not in self.error_info_map: self.error_info_map[file] = [] self.error_info_map[file].append(info) + if info.blocker: + self.has_blockers.add(file) if info.code is IMPORT: self.seen_import_error = True + def _filter_error(self, file: str, info: ErrorInfo) -> bool: + """ + process ErrorWatcher stack from top to bottom, + stopping early if error needs to be filtered out + """ + i = len(self._watchers) + while i > 0: + i -= 1 + w = self._watchers[i] + if w.on_error(file, info): + return True + return False + def add_error_info(self, info: ErrorInfo) -> None: file, line, end_line = info.origin + # process the stack of ErrorWatchers before modifying any internal state + # in case we need to filter out the error entirely + # NB: we need to do this both here and in _add_error_info, otherwise we + # might incorrectly update the sets of ignored or only_once messages + if self._filter_error(file, info): + return if not info.blocker: # Blockers cannot be ignored if file in self.ignored_lines: # It's okay if end_line is *before* line. @@ -476,12 +556,16 @@ def clear_errors_in_targets(self, path: str, targets: Set[str]) -> None: """Remove errors in specific fine-grained targets within a file.""" if path in self.error_info_map: new_errors = [] + has_blocker = False for info in self.error_info_map[path]: if info.target not in targets: new_errors.append(info) + has_blocker |= info.blocker elif info.only_once: self.only_once_messages.remove(info.message) self.error_info_map[path] = new_errors + if not has_blocker and path in self.has_blockers: + self.has_blockers.remove(path) def generate_unused_ignore_errors(self, file: str) -> None: ignored_lines = self.ignored_lines[file] @@ -551,19 +635,14 @@ def is_errors(self) -> bool: """Are there any generated messages?""" return bool(self.error_info_map) - def is_real_errors(self) -> bool: - """Are there any generated errors (not just notes, for example)?""" - return any(info.severity == 'error' - for infos in self.error_info_map.values() for info in infos) - def is_blockers(self) -> bool: """Are the any errors that are blockers?""" - return any(err for errs in self.error_info_map.values() for err in errs if err.blocker) + return bool(self.has_blockers) def blocker_module(self) -> Optional[str]: """Return the module with a blocking error, or None if not possible.""" - for errs in self.error_info_map.values(): - for err in errs: + for path in self.has_blockers: + for err in self.error_info_map[path]: if err.blocker: return err.module return None diff --git a/mypy/messages.py b/mypy/messages.py index 23ab172f54995..d499a574d5279 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -21,7 +21,7 @@ from typing_extensions import Final from mypy.erasetype import erase_type -from mypy.errors import Errors +from mypy.errors import Errors, ErrorWatcher, ErrorInfo from mypy.types import ( Type, CallableType, Instance, TypeVarType, TupleType, TypedDictType, LiteralType, UnionType, NoneType, AnyType, Overloaded, FunctionLike, DeletedType, TypeType, @@ -33,7 +33,7 @@ TypeInfo, Context, MypyFile, FuncDef, reverse_builtin_aliases, ArgKind, ARG_POS, ARG_OPT, ARG_NAMED, ARG_NAMED_OPT, ARG_STAR, ARG_STAR2, ReturnStmt, NameExpr, Var, CONTRAVARIANT, COVARIANT, SymbolNode, - CallExpr, IndexExpr, StrExpr, SymbolTable, TempNode, SYMBOL_FUNCBASE_TYPES + CallExpr, IndexExpr, StrExpr, SymbolTable, SYMBOL_FUNCBASE_TYPES ) from mypy.operators import op_methods, op_methods_to_symbols from mypy.subtypes import ( @@ -106,66 +106,38 @@ class MessageBuilder: modules: Dict[str, MypyFile] - # Number of times errors have been disabled. - disable_count = 0 - # Hack to deduplicate error messages from union types - disable_type_names_count = 0 + _disable_type_names: List[bool] def __init__(self, errors: Errors, modules: Dict[str, MypyFile]) -> None: self.errors = errors self.modules = modules - self.disable_count = 0 - self.disable_type_names_count = 0 + self._disable_type_names = [] # # Helpers # - def copy(self) -> 'MessageBuilder': - new = MessageBuilder(self.errors.copy(), self.modules) - new.disable_count = self.disable_count - new.disable_type_names_count = self.disable_type_names_count - return new - - def clean_copy(self) -> 'MessageBuilder': - errors = self.errors.copy() - errors.error_info_map = OrderedDict() - return MessageBuilder(errors, self.modules) + def filter_errors(self, *, filter_errors: bool = True, + save_filtered_errors: bool = False) -> ErrorWatcher: + return ErrorWatcher(self.errors, filter_errors=filter_errors, + save_filtered_errors=save_filtered_errors) - def add_errors(self, messages: 'MessageBuilder') -> None: + def add_errors(self, errors: List[ErrorInfo]) -> None: """Add errors in messages to this builder.""" - if self.disable_count <= 0: - for errs in messages.errors.error_info_map.values(): - for info in errs: - self.errors.add_error_info(info) - - @contextmanager - def disable_errors(self) -> Iterator[None]: - self.disable_count += 1 - try: - yield - finally: - self.disable_count -= 1 + for info in errors: + self.errors.add_error_info(info) @contextmanager def disable_type_names(self) -> Iterator[None]: - self.disable_type_names_count += 1 + self._disable_type_names.append(True) try: yield finally: - self.disable_type_names_count -= 1 - - def is_errors(self) -> bool: - return self.errors.is_errors() + self._disable_type_names.pop() - def most_recent_context(self) -> Context: - """Return a dummy context matching the most recent generated error in current file.""" - line, column = self.errors.most_recent_error_location() - node = TempNode(NoneType()) - node.line = line - node.column = column - return node + def are_type_names_disabled(self) -> bool: + return len(self._disable_type_names) > 0 and self._disable_type_names[-1] def report(self, msg: str, @@ -184,12 +156,11 @@ def report(self, end_line = context.end_line else: end_line = None - if self.disable_count <= 0: - self.errors.report(context.get_line() if context else -1, - context.get_column() if context else -1, - msg, severity=severity, file=file, offset=offset, - origin_line=origin.get_line() if origin else None, - end_line=end_line, code=code, allow_dups=allow_dups) + self.errors.report(context.get_line() if context else -1, + context.get_column() if context else -1, + msg, severity=severity, file=file, offset=offset, + origin_line=origin.get_line() if origin else None, + end_line=end_line, code=code, allow_dups=allow_dups) def fail(self, msg: str, @@ -309,7 +280,7 @@ def has_no_attr(self, extra = ' (not iterable)' elif member == '__aiter__': extra = ' (not async iterable)' - if not self.disable_type_names_count: + if not self.are_type_names_disabled(): failed = False if isinstance(original_type, Instance) and original_type.type.names: alternatives = set(original_type.type.names.keys()) @@ -391,7 +362,7 @@ def unsupported_operand_types(self, else: right_str = format_type(right_type) - if self.disable_type_names_count: + if self.are_type_names_disabled(): msg = 'Unsupported operand types for {} (likely involving Union)'.format(op) else: msg = 'Unsupported operand types for {} ({} and {})'.format( @@ -400,7 +371,7 @@ def unsupported_operand_types(self, def unsupported_left_operand(self, op: str, typ: Type, context: Context) -> None: - if self.disable_type_names_count: + if self.are_type_names_disabled(): msg = 'Unsupported left operand type for {} (some union)'.format(op) else: msg = 'Unsupported left operand type for {} ({})'.format( From d64efcd555fc7782592c213472cfa77bfcc2f11c Mon Sep 17 00:00:00 2001 From: jhance Date: Fri, 29 Apr 2022 08:24:55 -0700 Subject: [PATCH 260/377] Implement basic typevartuple constraints/inference (#12688) Implements basic inference for TypeVarTuple along with various check tests verifying uses of TypeVarTuple with functions works reasonably. --- mypy/applytype.py | 5 ++- mypy/constraints.py | 21 +++++++++ mypy/expandtype.py | 57 +++++++++++++++++++++++-- mypy/subtypes.py | 8 +++- mypy/test/testcheck.py | 2 + mypy/typeanal.py | 2 - mypy/types.py | 6 +++ test-data/unit/check-typevar-tuple.test | 29 +++++++++++++ 8 files changed, 122 insertions(+), 8 deletions(-) create mode 100644 test-data/unit/check-typevar-tuple.test diff --git a/mypy/applytype.py b/mypy/applytype.py index a967d834f1a2e..51a10c7084cfe 100644 --- a/mypy/applytype.py +++ b/mypy/applytype.py @@ -5,7 +5,8 @@ from mypy.expandtype import expand_type from mypy.types import ( Type, TypeVarId, TypeVarType, CallableType, AnyType, PartialType, get_proper_types, - TypeVarLikeType, ProperType, ParamSpecType, Parameters, get_proper_type + TypeVarLikeType, ProperType, ParamSpecType, Parameters, get_proper_type, + TypeVarTupleType, ) from mypy.nodes import Context @@ -20,6 +21,8 @@ def get_target_type( ) -> Optional[Type]: if isinstance(tvar, ParamSpecType): return type + if isinstance(tvar, TypeVarTupleType): + return type assert isinstance(tvar, TypeVarType) values = get_proper_types(tvar.values) if values: diff --git a/mypy/constraints.py b/mypy/constraints.py index 06feddc0d3cea..1d9ca8b138ed7 100644 --- a/mypy/constraints.py +++ b/mypy/constraints.py @@ -694,6 +694,27 @@ def infer_against_overloaded(self, overloaded: Overloaded, def visit_tuple_type(self, template: TupleType) -> List[Constraint]: actual = self.actual + # TODO: Support other items in the tuple besides Unpack + # TODO: Support subclasses of Tuple + is_varlength_tuple = ( + isinstance(actual, Instance) + and actual.type.fullname == "builtins.tuple" + ) + if len(template.items) == 1: + item = get_proper_type(template.items[0]) + if isinstance(item, UnpackType): + unpacked_type = get_proper_type(item.type) + if isinstance(unpacked_type, TypeVarTupleType): + if ( + isinstance(actual, (TupleType, AnyType)) + or is_varlength_tuple + ): + return [Constraint( + type_var=unpacked_type.id, + op=self.direction, + target=actual, + )] + if isinstance(actual, TupleType) and len(actual.items) == len(template.items): res: List[Constraint] = [] for i in range(len(template.items)): diff --git a/mypy/expandtype.py b/mypy/expandtype.py index eef841c9387ec..78b36f2887576 100644 --- a/mypy/expandtype.py +++ b/mypy/expandtype.py @@ -1,4 +1,4 @@ -from typing import Dict, Iterable, List, TypeVar, Mapping, cast +from typing import Dict, Iterable, List, TypeVar, Mapping, cast, Union, Optional from mypy.types import ( Type, Instance, CallableType, TypeVisitor, UnboundType, AnyType, @@ -45,6 +45,8 @@ def freshen_function_type_vars(callee: F) -> F: # TODO(PEP612): fix for ParamSpecType if isinstance(v, TypeVarType): tv: TypeVarLikeType = TypeVarType.new_unification_variable(v) + elif isinstance(v, TypeVarTupleType): + tv = TypeVarTupleType.new_unification_variable(v) else: assert isinstance(v, ParamSpecType) tv = ParamSpecType.new_unification_variable(v) @@ -135,7 +137,36 @@ def visit_type_var_tuple(self, t: TypeVarTupleType) -> Type: raise NotImplementedError def visit_unpack_type(self, t: UnpackType) -> Type: - raise NotImplementedError + # It is impossible to reasonally implement visit_unpack_type, because + # unpacking inherently expands to something more like a list of types. + # + # Relevant sections that can call unpack should call expand_unpack() + # instead. + assert False, "Mypy bug: unpacking must happen at a higher level" + + def expand_unpack(self, t: UnpackType) -> Optional[Union[List[Type], Instance, AnyType]]: + """May return either a list of types to unpack to, any, or a single + variable length tuple. The latter may not be valid in all contexts. + """ + proper_typ = get_proper_type(t.type) + if isinstance(proper_typ, TypeVarTupleType): + repl = get_proper_type(self.variables.get(proper_typ.id, t)) + if isinstance(repl, TupleType): + return repl.items + elif isinstance(repl, Instance) and repl.type.fullname == "builtins.tuple": + return repl + elif isinstance(repl, AnyType): + # tuple[Any, ...] would be better, but we don't have + # the type info to construct that type here. + return repl + elif isinstance(repl, TypeVarTupleType): + return [UnpackType(typ=repl)] + elif isinstance(repl, UninhabitedType): + return None + else: + raise NotImplementedError("Invalid type to expand: {}".format(repl)) + else: + raise NotImplementedError def visit_parameters(self, t: Parameters) -> Type: return t.copy_modified(arg_types=self.expand_types(t.arg_types)) @@ -179,7 +210,27 @@ def visit_overloaded(self, t: Overloaded) -> Type: return Overloaded(items) def visit_tuple_type(self, t: TupleType) -> Type: - return t.copy_modified(items=self.expand_types(t.items)) + items = [] + for item in t.items: + proper_item = get_proper_type(item) + if isinstance(proper_item, UnpackType): + unpacked_items = self.expand_unpack(proper_item) + if unpacked_items is None: + # TODO: better error, something like tuple of unknown? + return UninhabitedType() + elif isinstance(unpacked_items, Instance): + if len(t.items) == 1: + return unpacked_items + else: + assert False, "Invalid unpack of variable length tuple" + elif isinstance(unpacked_items, AnyType): + return unpacked_items + else: + items.extend(unpacked_items) + else: + items.append(proper_item.accept(self)) + + return t.copy_modified(items=items) def visit_typeddict_type(self, t: TypedDictType) -> Type: return t.copy_modified(item_types=self.expand_types(t.items.values())) diff --git a/mypy/subtypes.py b/mypy/subtypes.py index 809f457ab2a2f..8bb5927021579 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -350,7 +350,9 @@ def visit_type_var_tuple(self, left: TypeVarTupleType) -> bool: return self._is_subtype(left.upper_bound, self.right) def visit_unpack_type(self, left: UnpackType) -> bool: - raise NotImplementedError + if isinstance(self.right, UnpackType): + return self._is_subtype(left.type, self.right.type) + return False def visit_parameters(self, left: Parameters) -> bool: right = self.right @@ -1482,7 +1484,9 @@ def visit_type_var_tuple(self, left: TypeVarTupleType) -> bool: return self._is_proper_subtype(left.upper_bound, self.right) def visit_unpack_type(self, left: UnpackType) -> bool: - raise NotImplementedError + if isinstance(self.right, UnpackType): + return self._is_proper_subtype(left.type, self.right.type) + return False def visit_parameters(self, left: Parameters) -> bool: right = self.right diff --git a/mypy/test/testcheck.py b/mypy/test/testcheck.py index 355a400168f6c..4f6c82877775f 100644 --- a/mypy/test/testcheck.py +++ b/mypy/test/testcheck.py @@ -91,6 +91,7 @@ 'check-errorcodes.test', 'check-annotated.test', 'check-parameter-specification.test', + 'check-typevar-tuple.test', 'check-generic-alias.test', 'check-typeguard.test', 'check-functools.test', @@ -164,6 +165,7 @@ def run_case_once(self, testcase: DataDrivenTestCase, # Parse options after moving files (in case mypy.ini is being moved). options = parse_options(original_program_text, testcase, incremental_step) options.use_builtins_fixtures = True + options.enable_incomplete_features = True options.show_traceback = True # Enable some options automatically based on test file name. diff --git a/mypy/typeanal.py b/mypy/typeanal.py index eee8a43c25f35..119fbd3fbf794 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -1202,8 +1202,6 @@ def anal_var_def(self, var_def: TypeVarLikeType) -> TypeVarLikeType: var_def.variance, var_def.line ) - elif isinstance(var_def, TypeVarTupleType): - raise NotImplementedError else: return var_def diff --git a/mypy/types.py b/mypy/types.py index e43b73f093b89..69776e4188ad2 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -696,6 +696,12 @@ def __eq__(self, other: object) -> bool: return NotImplemented return self.id == other.id + @staticmethod + def new_unification_variable(old: 'TypeVarTupleType') -> 'TypeVarTupleType': + new_id = TypeVarId.new(meta_level=1) + return TypeVarTupleType(old.name, old.fullname, new_id, old.upper_bound, + line=old.line, column=old.column) + class UnboundType(ProperType): """Instance type that has not been bound during semantic analysis.""" diff --git a/test-data/unit/check-typevar-tuple.test b/test-data/unit/check-typevar-tuple.test new file mode 100644 index 0000000000000..ed11e5b53263c --- /dev/null +++ b/test-data/unit/check-typevar-tuple.test @@ -0,0 +1,29 @@ +[case testTypeVarTupleBasic] +from typing import Any, Tuple +from typing_extensions import Unpack, TypeVarTuple + +Ts = TypeVarTuple("Ts") + +def f(a: Tuple[Unpack[Ts]]) -> Tuple[Unpack[Ts]]: + return a + +any: Any +args: Tuple[int, str] = (1, 'x') +args2: Tuple[bool, str] = (False, 'y') +args3: Tuple[int, str, bool] = (2, 'z', True) +varargs: Tuple[int, ...] = (1, 2, 3) + +reveal_type(f(args)) # N: Revealed type is "Tuple[builtins.int, builtins.str]" + +reveal_type(f(varargs)) # N: Revealed type is "builtins.tuple[builtins.int, ...]" + +f(0) # E: Argument 1 to "f" has incompatible type "int"; expected + +def g(a: Tuple[Unpack[Ts]], b: Tuple[Unpack[Ts]]) -> Tuple[Unpack[Ts]]: + return a + +reveal_type(g(args, args)) # N: Revealed type is "Tuple[builtins.int, builtins.str]" +reveal_type(g(args, args2)) # N: Revealed type is "Tuple[builtins.int, builtins.str]" +reveal_type(g(args, args3)) # N: Revealed type is "builtins.tuple[builtins.object, ...]" +reveal_type(g(any, any)) # N: Revealed type is "Any" +[builtins fixtures/tuple.pyi] From d48d548ca5945897c4cbfa9929c0e22e6a4ec9c8 Mon Sep 17 00:00:00 2001 From: Hugues Date: Fri, 29 Apr 2022 08:27:11 -0700 Subject: [PATCH 261/377] introduce per-file timing-stats (#12639) When profiling mypy over a large codebase, it can be useful to know which files are slowest to typecheck. Gather per-file timing stats and expose them through a new (hidden) command line switch --- mypy/build.py | 32 +++++++++++++++++++++++++++++++- mypy/main.py | 3 +++ mypy/options.py | 1 + mypy/test/data.py | 10 ++++++---- mypy/test/helpers.py | 15 ++++++++++++--- mypy/util.py | 10 ++++++++++ test-data/unit/cmdline.test | 12 ++++++++++++ 7 files changed, 75 insertions(+), 8 deletions(-) diff --git a/mypy/build.py b/mypy/build.py index f7a9e9e05e1d3..f084e632417ad 100644 --- a/mypy/build.py +++ b/mypy/build.py @@ -36,7 +36,8 @@ from mypy.errors import Errors, CompileError, ErrorInfo, report_internal_error from mypy.util import ( DecodeError, decode_python_encoding, is_sub_path, get_mypy_comments, module_prefix, - read_py_file, hash_digest, is_typeshed_file, is_stub_package_file, get_top_two_prefixes + read_py_file, hash_digest, is_typeshed_file, is_stub_package_file, get_top_two_prefixes, + time_ref, time_spent_us ) if TYPE_CHECKING: from mypy.report import Reports # Avoid unconditional slow import @@ -256,6 +257,8 @@ def _build(sources: List[BuildSource], graph = dispatch(sources, manager, stdout) if not options.fine_grained_incremental: TypeState.reset_all_subtype_caches() + if options.timing_stats is not None: + dump_timing_stats(options.timing_stats, graph) return BuildResult(manager, graph) finally: t0 = time.time() @@ -1808,6 +1811,9 @@ class State: fine_grained_deps_loaded = False + # Cumulative time spent on this file, in microseconds (for profiling stats) + time_spent_us: int = 0 + def __init__(self, id: Optional[str], path: Optional[str], @@ -2034,6 +2040,8 @@ def parse_file(self) -> None: else: manager.log("Using cached AST for %s (%s)" % (self.xpath, self.id)) + t0 = time_ref() + with self.wrap_context(): source = self.source self.source = None # We won't need it again. @@ -2079,6 +2087,8 @@ def parse_file(self) -> None: self.tree.ignored_lines, self.ignore_all or self.options.ignore_errors) + self.time_spent_us += time_spent_us(t0) + if not cached: # Make a copy of any errors produced during parse time so that # fine-grained mode can repeat them when the module is @@ -2113,6 +2123,9 @@ def semantic_analysis_pass1(self) -> None: """ options = self.options assert self.tree is not None + + t0 = time_ref() + # Do the first pass of semantic analysis: analyze the reachability # of blocks and import statements. We must do this before # processing imports, since this may mark some import statements as @@ -2131,6 +2144,7 @@ def semantic_analysis_pass1(self) -> None: if options.allow_redefinition: # Perform more renaming across the AST to allow variable redefinitions self.tree.accept(VariableRenameVisitor()) + self.time_spent_us += time_spent_us(t0) def add_dependency(self, dep: str) -> None: if dep not in self.dependencies_set: @@ -2188,8 +2202,10 @@ def compute_dependencies(self) -> None: def type_check_first_pass(self) -> None: if self.options.semantic_analysis_only: return + t0 = time_ref() with self.wrap_context(): self.type_checker().check_first_pass() + self.time_spent_us += time_spent_us(t0) def type_checker(self) -> TypeChecker: if not self._type_checker: @@ -2207,14 +2223,17 @@ def type_map(self) -> Dict[Expression, Type]: def type_check_second_pass(self) -> bool: if self.options.semantic_analysis_only: return False + t0 = time_ref() with self.wrap_context(): return self.type_checker().check_second_pass() + self.time_spent_us += time_spent_us(t0) def finish_passes(self) -> None: assert self.tree is not None, "Internal error: method must be called on parsed file only" manager = self.manager if self.options.semantic_analysis_only: return + t0 = time_ref() with self.wrap_context(): # Some tests (and tools) want to look at the set of all types. options = manager.options @@ -2237,6 +2256,7 @@ def finish_passes(self) -> None: self.free_state() if not manager.options.fine_grained_incremental and not manager.options.preserve_asts: free_tree(self.tree) + self.time_spent_us += time_spent_us(t0) def free_state(self) -> None: if self._type_checker: @@ -2771,6 +2791,16 @@ def dumps(self) -> str: json.dumps(self.deps)) +def dump_timing_stats(path: str, graph: Graph) -> None: + """ + Dump timing stats for each file in the given graph + """ + with open(path, 'w') as f: + for k in sorted(graph.keys()): + v = graph[k] + f.write('{} {}\n'.format(v.id, v.time_spent_us)) + + def dump_graph(graph: Graph, stdout: Optional[TextIO] = None) -> None: """Dump the graph as a JSON string to stdout. diff --git a/mypy/main.py b/mypy/main.py index c4548ea9b6250..7c7a5993d5c5a 100644 --- a/mypy/main.py +++ b/mypy/main.py @@ -835,6 +835,9 @@ def add_invertible_flag(flag: str, parser.add_argument( '--dump-build-stats', action='store_true', help=argparse.SUPPRESS) + # dump timing stats for each processed file into the given output file + parser.add_argument( + '--timing-stats', dest='timing_stats', help=argparse.SUPPRESS) # --debug-cache will disable any cache-related compressions/optimizations, # which will make the cache writing process output pretty-printed JSON (which # is easier to debug). diff --git a/mypy/options.py b/mypy/options.py index 8e56d67bbeb8b..4cb2434958f42 100644 --- a/mypy/options.py +++ b/mypy/options.py @@ -263,6 +263,7 @@ def __init__(self) -> None: self.dump_inference_stats = False self.dump_build_stats = False self.enable_incomplete_features = False + self.timing_stats: Optional[str] = None # -- test options -- # Stop after the semantic analysis phase diff --git a/mypy/test/data.py b/mypy/test/data.py index e886b11ffa8e6..e18ac142d15e6 100644 --- a/mypy/test/data.py +++ b/mypy/test/data.py @@ -10,7 +10,7 @@ import sys import pytest -from typing import List, Tuple, Set, Optional, Iterator, Any, Dict, NamedTuple, Union +from typing import List, Tuple, Set, Optional, Iterator, Any, Dict, NamedTuple, Union, Pattern from mypy.test.config import test_data_prefix, test_temp_dir, PREFIX @@ -44,7 +44,7 @@ def parse_test_case(case: 'DataDrivenTestCase') -> None: normalize_output = True files: List[Tuple[str, str]] = [] # path and contents - output_files: List[Tuple[str, str]] = [] # path and contents for output files + output_files: List[Tuple[str, Union[str, Pattern[str]]]] = [] # output path and contents output: List[str] = [] # Regular output errors output2: Dict[int, List[str]] = {} # Output errors for incremental, runs 2+ deleted_paths: Dict[int, Set[str]] = {} # from run number of paths @@ -57,13 +57,15 @@ def parse_test_case(case: 'DataDrivenTestCase') -> None: # optionally followed by lines of text. item = first_item = test_items[0] for item in test_items[1:]: - if item.id == 'file' or item.id == 'outfile': + if item.id in {'file', 'outfile', 'outfile-re'}: # Record an extra file needed for the test case. assert item.arg is not None contents = expand_variables('\n'.join(item.data)) file_entry = (join(base_path, item.arg), contents) if item.id == 'file': files.append(file_entry) + elif item.id == 'outfile-re': + output_files.append((file_entry[0], re.compile(file_entry[1].rstrip(), re.S))) else: output_files.append(file_entry) elif item.id in ('builtins', 'builtins_py2'): @@ -220,7 +222,7 @@ class DataDrivenTestCase(pytest.Item): # Extra attributes used by some tests. last_line: int - output_files: List[Tuple[str, str]] # Path and contents for output files + output_files: List[Tuple[str, Union[str, Pattern[str]]]] # Path and contents for output files deleted_paths: Dict[int, Set[str]] # Mapping run number -> paths triggered: List[str] # Active triggers (one line per incremental step) diff --git a/mypy/test/helpers.py b/mypy/test/helpers.py index f9f117634c21b..5046c46eaa434 100644 --- a/mypy/test/helpers.py +++ b/mypy/test/helpers.py @@ -5,7 +5,7 @@ import shutil import contextlib -from typing import List, Iterable, Dict, Tuple, Callable, Any, Iterator, Union +from typing import List, Iterable, Dict, Tuple, Callable, Any, Iterator, Union, Pattern from mypy import defaults import mypy.api as api @@ -458,8 +458,17 @@ def check_test_output_files(testcase: DataDrivenTestCase, 'Expected file {} was not produced by test case{}'.format( path, ' on step %d' % step if testcase.output2 else '')) with open(path, 'r', encoding='utf8') as output_file: - actual_output_content = output_file.read().splitlines() - normalized_output = normalize_file_output(actual_output_content, + actual_output_content = output_file.read() + + if isinstance(expected_content, Pattern): + if expected_content.fullmatch(actual_output_content) is not None: + continue + raise AssertionError( + 'Output file {} did not match its expected output pattern\n---\n{}\n---'.format( + path, actual_output_content) + ) + + normalized_output = normalize_file_output(actual_output_content.splitlines(), os.path.abspath(test_temp_dir)) # We always normalize things like timestamp, but only handle operating-system # specific things if requested. diff --git a/mypy/util.py b/mypy/util.py index c02e5dcfc9b4a..1a3628458c483 100644 --- a/mypy/util.py +++ b/mypy/util.py @@ -8,6 +8,7 @@ import hashlib import io import shutil +import time from typing import ( TypeVar, List, Tuple, Optional, Dict, Sequence, Iterable, Container, IO, Callable @@ -763,3 +764,12 @@ def is_stub_package_file(file: str) -> bool: def unnamed_function(name: Optional[str]) -> bool: return name is not None and name == "_" + + +# TODO: replace with uses of perf_counter_ns when support for py3.6 is dropped +# (or when mypy properly handles alternate definitions based on python version check +time_ref = time.perf_counter + + +def time_spent_us(t0: float) -> int: + return int((time.perf_counter() - t0) * 1e6) diff --git a/test-data/unit/cmdline.test b/test-data/unit/cmdline.test index 1a038b9fac092..7fc5176433424 100644 --- a/test-data/unit/cmdline.test +++ b/test-data/unit/cmdline.test @@ -1373,3 +1373,15 @@ exclude = (?x)( 1() [out] c/cpkg.py:1: error: "int" not callable + + +[case testCmdlineTimingStats] +# cmd: mypy --timing-stats timing.txt . +[file b/__init__.py] +[file b/c.py] +class C: pass +[outfile-re timing.txt] +.* +b \d+ +b\.c \d+ +.* From c6cf7cd3dac90dce0be5bf888f530f2eee1534e7 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Fri, 29 Apr 2022 09:41:29 -0600 Subject: [PATCH 262/377] Use tuple[object, ...] and dict[str, object] as upper bounds for ParamSpec.args and ParamSpec.kwargs (#12668) Mypy thought that a variable annotated with P.args is not iterable, and that a variable annotated with P.kwargs does not have a .pop() method. Fixes #12386. --- mypy/checkmember.py | 2 +- mypy/semanal_shared.py | 50 +++++++++++- mypy/typeanal.py | 30 ++++---- .../unit/check-parameter-specification.test | 75 +++++++++++------- test-data/unit/fixtures/paramspec.pyi | 76 +++++++++++++++++++ 5 files changed, 186 insertions(+), 47 deletions(-) create mode 100644 test-data/unit/fixtures/paramspec.pyi diff --git a/mypy/checkmember.py b/mypy/checkmember.py index 2659ad18ed6e4..04b64e9ba7fe4 100644 --- a/mypy/checkmember.py +++ b/mypy/checkmember.py @@ -164,7 +164,7 @@ def _analyze_member_access(name: str, return analyze_typeddict_access(name, typ, mx, override_info) elif isinstance(typ, NoneType): return analyze_none_member_access(name, typ, mx) - elif isinstance(typ, TypeVarType): + elif isinstance(typ, TypeVarLikeType): return _analyze_member_access(name, typ.upper_bound, mx, override_info) elif isinstance(typ, DeletedType): mx.msg.deleted_as_rvalue(typ, mx.context) diff --git a/mypy/semanal_shared.py b/mypy/semanal_shared.py index 85a6779ac9f3b..72a89150bb64d 100644 --- a/mypy/semanal_shared.py +++ b/mypy/semanal_shared.py @@ -2,8 +2,8 @@ from abc import abstractmethod -from typing import Optional, List, Callable -from typing_extensions import Final +from typing import Optional, List, Callable, Union +from typing_extensions import Final, Protocol from mypy_extensions import trait from mypy.nodes import ( @@ -11,7 +11,8 @@ SymbolNode, SymbolTable ) from mypy.types import ( - Type, FunctionLike, Instance, TupleType, TPDICT_FB_NAMES, ProperType, get_proper_type + Type, FunctionLike, Instance, TupleType, TPDICT_FB_NAMES, ProperType, get_proper_type, + ParamSpecType, ParamSpecFlavor, Parameters, TypeVarId ) from mypy.tvar_scope import TypeVarLikeScope from mypy.errorcodes import ErrorCode @@ -212,3 +213,46 @@ def calculate_tuple_fallback(typ: TupleType) -> None: fallback = typ.partial_fallback assert fallback.type.fullname == 'builtins.tuple' fallback.args = (join.join_type_list(list(typ.items)),) + fallback.args[1:] + + +class _NamedTypeCallback(Protocol): + def __call__( + self, fully_qualified_name: str, args: Optional[List[Type]] = None + ) -> Instance: ... + + +def paramspec_args( + name: str, fullname: str, id: Union[TypeVarId, int], *, + named_type_func: _NamedTypeCallback, line: int = -1, column: int = -1, + prefix: Optional[Parameters] = None +) -> ParamSpecType: + return ParamSpecType( + name, + fullname, + id, + flavor=ParamSpecFlavor.ARGS, + upper_bound=named_type_func('builtins.tuple', [named_type_func('builtins.object')]), + line=line, + column=column, + prefix=prefix + ) + + +def paramspec_kwargs( + name: str, fullname: str, id: Union[TypeVarId, int], *, + named_type_func: _NamedTypeCallback, line: int = -1, column: int = -1, + prefix: Optional[Parameters] = None +) -> ParamSpecType: + return ParamSpecType( + name, + fullname, + id, + flavor=ParamSpecFlavor.KWARGS, + upper_bound=named_type_func( + 'builtins.dict', + [named_type_func('builtins.str'), named_type_func('builtins.object')] + ), + line=line, + column=column, + prefix=prefix + ) diff --git a/mypy/typeanal.py b/mypy/typeanal.py index 119fbd3fbf794..84d9758b9a573 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -33,7 +33,7 @@ from mypy.tvar_scope import TypeVarLikeScope from mypy.exprtotype import expr_to_unanalyzed_type, TypeTranslationError from mypy.plugin import Plugin, TypeAnalyzerPluginInterface, AnalyzeTypeContext -from mypy.semanal_shared import SemanticAnalyzerCoreInterface +from mypy.semanal_shared import SemanticAnalyzerCoreInterface, paramspec_args, paramspec_kwargs from mypy.errorcodes import ErrorCode from mypy import nodes, message_registry, errorcodes as codes @@ -711,13 +711,13 @@ def anal_star_arg_type(self, t: Type, kind: ArgKind, nested: bool) -> Type: tvar_def = self.tvar_scope.get_binding(sym) if isinstance(tvar_def, ParamSpecType): if kind == ARG_STAR: - flavor = ParamSpecFlavor.ARGS + make_paramspec = paramspec_args elif kind == ARG_STAR2: - flavor = ParamSpecFlavor.KWARGS + make_paramspec = paramspec_kwargs else: assert False, kind - return ParamSpecType(tvar_def.name, tvar_def.fullname, tvar_def.id, flavor, - upper_bound=self.named_type('builtins.object'), + return make_paramspec(tvar_def.name, tvar_def.fullname, tvar_def.id, + named_type_func=self.named_type, line=t.line, column=t.column) return self.anal_type(t, nested=nested) @@ -855,13 +855,11 @@ def analyze_callable_args_for_paramspec( if not isinstance(tvar_def, ParamSpecType): return None - # TODO: Use tuple[...] or Mapping[..] instead? - obj = self.named_type('builtins.object') return CallableType( - [ParamSpecType(tvar_def.name, tvar_def.fullname, tvar_def.id, ParamSpecFlavor.ARGS, - upper_bound=obj), - ParamSpecType(tvar_def.name, tvar_def.fullname, tvar_def.id, ParamSpecFlavor.KWARGS, - upper_bound=obj)], + [paramspec_args(tvar_def.name, tvar_def.fullname, tvar_def.id, + named_type_func=self.named_type), + paramspec_kwargs(tvar_def.name, tvar_def.fullname, tvar_def.id, + named_type_func=self.named_type)], [nodes.ARG_STAR, nodes.ARG_STAR2], [None, None], ret_type=ret_type, @@ -891,18 +889,16 @@ def analyze_callable_args_for_concatenate( if not isinstance(tvar_def, ParamSpecType): return None - # TODO: Use tuple[...] or Mapping[..] instead? - obj = self.named_type('builtins.object') # ick, CallableType should take ParamSpecType prefix = tvar_def.prefix # we don't set the prefix here as generic arguments will get updated at some point # in the future. CallableType.param_spec() accounts for this. return CallableType( [*prefix.arg_types, - ParamSpecType(tvar_def.name, tvar_def.fullname, tvar_def.id, ParamSpecFlavor.ARGS, - upper_bound=obj), - ParamSpecType(tvar_def.name, tvar_def.fullname, tvar_def.id, ParamSpecFlavor.KWARGS, - upper_bound=obj)], + paramspec_args(tvar_def.name, tvar_def.fullname, tvar_def.id, + named_type_func=self.named_type), + paramspec_kwargs(tvar_def.name, tvar_def.fullname, tvar_def.id, + named_type_func=self.named_type)], [*prefix.arg_kinds, nodes.ARG_STAR, nodes.ARG_STAR2], [*prefix.arg_names, None, None], ret_type=ret_type, diff --git a/test-data/unit/check-parameter-specification.test b/test-data/unit/check-parameter-specification.test index 2242b79d4b643..28b08aa7122f5 100644 --- a/test-data/unit/check-parameter-specification.test +++ b/test-data/unit/check-parameter-specification.test @@ -11,7 +11,7 @@ P2 = ParamSpec("P2", contravariant=True) # E: Only the first argument to ParamS P3 = ParamSpec("P3", bound=int) # E: Only the first argument to ParamSpec has defined semantics P4 = ParamSpec("P4", int, str) # E: Only the first argument to ParamSpec has defined semantics P5 = ParamSpec("P5", covariant=True, bound=int) # E: Only the first argument to ParamSpec has defined semantics -[builtins fixtures/tuple.pyi] +[builtins fixtures/paramspec.pyi] [case testParamSpecLocations] from typing import Callable, List @@ -35,7 +35,7 @@ def foo5(x: Callable[[int, str], P]) -> None: ... # E: Invalid location for Par def foo6(x: Callable[[P], int]) -> None: ... # E: Invalid location for ParamSpec "P" \ # N: You can use ParamSpec as the first argument to Callable, e.g., 'Callable[P, int]' -[builtins fixtures/tuple.pyi] +[builtins fixtures/paramspec.pyi] [case testParamSpecContextManagerLike] from typing import Callable, List, Iterator, TypeVar @@ -51,7 +51,7 @@ def whatever(x: int) -> Iterator[int]: reveal_type(whatever) # N: Revealed type is "def (x: builtins.int) -> builtins.list[builtins.int]" reveal_type(whatever(217)) # N: Revealed type is "builtins.list[builtins.int]" -[builtins fixtures/tuple.pyi] +[builtins fixtures/paramspec.pyi] [case testInvalidParamSpecType] # flags: --python-version 3.10 @@ -70,7 +70,7 @@ P = ParamSpec('P') def f(x: Callable[P, int]) -> None: ... reveal_type(f) # N: Revealed type is "def [P] (x: def (*P.args, **P.kwargs) -> builtins.int)" -[builtins fixtures/tuple.pyi] +[builtins fixtures/paramspec.pyi] [case testParamSpecSimpleFunction] from typing import Callable, TypeVar @@ -83,7 +83,7 @@ def changes_return_type_to_str(x: Callable[P, int]) -> Callable[P, str]: ... def returns_int(a: str, b: bool) -> int: ... reveal_type(changes_return_type_to_str(returns_int)) # N: Revealed type is "def (a: builtins.str, b: builtins.bool) -> builtins.str" -[builtins fixtures/tuple.pyi] +[builtins fixtures/paramspec.pyi] [case testParamSpecSimpleClass] from typing import Callable, TypeVar, Generic @@ -199,7 +199,7 @@ g: Any reveal_type(f(g)) # N: Revealed type is "def (*Any, **Any) -> builtins.str" f(g)(1, 3, x=1, y=2) -[builtins fixtures/tuple.pyi] +[builtins fixtures/paramspec.pyi] [case testParamSpecDecoratorImplementation] from typing import Callable, Any, TypeVar, List @@ -556,7 +556,7 @@ a: Callable[[int, bytes], str] b: Callable[[str, bytes], str] reveal_type(f(a, b)) # N: Revealed type is "def (builtins.bytes) -> builtins.str" -[builtins fixtures/tuple.pyi] +[builtins fixtures/paramspec.pyi] [case testParamSpecConcatenateInReturn] from typing_extensions import ParamSpec, Concatenate @@ -569,7 +569,7 @@ def f(i: Callable[Concatenate[int, P], str]) -> Callable[Concatenate[int, P], st n: Callable[[int, bytes], str] reveal_type(f(n)) # N: Revealed type is "def (builtins.int, builtins.bytes) -> builtins.str" -[builtins fixtures/tuple.pyi] +[builtins fixtures/paramspec.pyi] [case testParamSpecConcatenateNamedArgs] # flags: --strict-concatenate @@ -592,7 +592,7 @@ def f2(c: Callable[P, R]) -> Callable[Concatenate[int, P], R]: # reason for rejection: f2(lambda x: 42)(42, x=42) -[builtins fixtures/tuple.pyi] +[builtins fixtures/paramspec.pyi] [out] main:10: error: invalid syntax [out version>=3.8] @@ -619,7 +619,7 @@ def f2(c: Callable[P, R]) -> Callable[Concatenate[int, P], R]: # reason for rejection: f2(lambda x: 42)(42, x=42) -[builtins fixtures/tuple.pyi] +[builtins fixtures/paramspec.pyi] [out] main:9: error: invalid syntax [out version>=3.8] @@ -640,7 +640,7 @@ n = f(a) reveal_type(n) # N: Revealed type is "def (builtins.int)" reveal_type(n(42)) # N: Revealed type is "None" -[builtins fixtures/tuple.pyi] +[builtins fixtures/paramspec.pyi] [case testCallablesAsParameters] # credits to https://github.com/microsoft/pyright/issues/2705 @@ -658,7 +658,7 @@ def test(a: int, /, b: str) -> str: ... abc = Foo(test) reveal_type(abc) bar(abc) -[builtins fixtures/tuple.pyi] +[builtins fixtures/paramspec.pyi] [out] main:11: error: invalid syntax [out version>=3.8] @@ -677,7 +677,7 @@ n: Foo[[int]] def f(x: int) -> None: ... n.foo(f) -[builtins fixtures/tuple.pyi] +[builtins fixtures/paramspec.pyi] [case testParamSpecLiteralsTypeApplication] from typing_extensions import ParamSpec @@ -709,7 +709,7 @@ Z[bytes, str](lambda one: None) # E: Cannot infer type of lambda \ # E: Argument 1 to "Z" has incompatible type "Callable[[Any], None]"; expected "Callable[[bytes, str], None]" Z[bytes, str](f2) # E: Argument 1 to "Z" has incompatible type "Callable[[bytes, int], None]"; expected "Callable[[bytes, str], None]" -[builtins fixtures/tuple.pyi] +[builtins fixtures/paramspec.pyi] [case testParamSpecLiteralEllipsis] from typing_extensions import ParamSpec @@ -740,7 +740,7 @@ n = Z(f1) n = Z(f2) n = Z(f3) -[builtins fixtures/tuple.pyi] +[builtins fixtures/paramspec.pyi] [case testParamSpecApplyConcatenateTwice] from typing_extensions import ParamSpec, Concatenate @@ -770,7 +770,7 @@ def f(c: C[P]) -> None: reveal_type(p1) # N: Revealed type is "__main__.C[[builtins.str, **P`-1]]" p2 = p1.add_str() reveal_type(p2) # N: Revealed type is "__main__.C[[builtins.int, builtins.str, **P`-1]]" -[builtins fixtures/tuple.pyi] +[builtins fixtures/paramspec.pyi] [case testParamSpecLiteralJoin] from typing import Generic, Callable, Union @@ -788,7 +788,7 @@ def func( ) -> None: job = action if isinstance(action, Job) else Job(action) reveal_type(job) # N: Revealed type is "__main__.Job[[builtins.int]]" -[builtins fixtures/tuple.pyi] +[builtins fixtures/paramspec.pyi] [case testApplyParamSpecToParamSpecLiterals] from typing import TypeVar, Generic, Callable @@ -818,7 +818,7 @@ def func2(job: Job[..., None]) -> None: run_job(job, "Hello", 42) run_job(job, 42, msg="Hello") run_job(job, x=42, msg="Hello") -[builtins fixtures/tuple.pyi] +[builtins fixtures/paramspec.pyi] [case testExpandNonBareParamSpecAgainstCallable] from typing import Callable, TypeVar, Any @@ -850,7 +850,7 @@ reveal_type(A().func(f, 42)) # N: Revealed type is "builtins.int" # TODO: this should reveal `int` reveal_type(A().func(lambda x: x + x, 42)) # N: Revealed type is "Any" -[builtins fixtures/tuple.pyi] +[builtins fixtures/paramspec.pyi] [case testParamSpecConstraintOnOtherParamSpec] from typing import Callable, TypeVar, Any, Generic @@ -880,7 +880,7 @@ reveal_type(A().func(Job(lambda x: x))) # N: Revealed type is "__main__.Job[[x: def f(x: int, y: int) -> None: ... reveal_type(A().func(Job(f))) # N: Revealed type is "__main__.Job[[x: builtins.int, y: builtins.int], None]" -[builtins fixtures/tuple.pyi] +[builtins fixtures/paramspec.pyi] [case testConstraintBetweenParamSpecFunctions1] from typing import Callable, TypeVar, Any, Generic @@ -898,7 +898,7 @@ def func(__action: Job[_P]) -> Callable[_P, None]: ... reveal_type(func) # N: Revealed type is "def [_P] (__main__.Job[_P`-1]) -> def (*_P.args, **_P.kwargs)" -[builtins fixtures/tuple.pyi] +[builtins fixtures/paramspec.pyi] [case testConstraintBetweenParamSpecFunctions2] from typing import Callable, TypeVar, Any, Generic @@ -916,7 +916,7 @@ def func(__action: Job[_P]) -> Callable[_P, None]: ... reveal_type(func) # N: Revealed type is "def [_P] (__main__.Job[_P`-1]) -> def (*_P.args, **_P.kwargs)" -[builtins fixtures/tuple.pyi] +[builtins fixtures/paramspec.pyi] [case testConstraintsBetweenConcatenatePrefixes] from typing import Any, Callable, Generic, TypeVar @@ -937,7 +937,7 @@ def adds_await() -> Callable[ ... return decorator # we want `_T` and `_P` to refer to the same things. -[builtins fixtures/tuple.pyi] +[builtins fixtures/paramspec.pyi] [case testParamSpecVariance] from typing import Callable, Generic @@ -995,7 +995,7 @@ a3: Callable[[int], None] a3 = f3 # E: Incompatible types in assignment (expression has type "Callable[[bool], None]", variable has type "Callable[[int], None]") a3 = f2 a3 = f1 -[builtins fixtures/tuple.pyi] +[builtins fixtures/paramspec.pyi] [case testDecoratingClassesThatUseParamSpec] from typing import Generic, TypeVar, Callable, Any @@ -1039,7 +1039,7 @@ reveal_type(j) # N: Revealed type is "__main__.Job[[x: _T`-1]]" jf = j.into_callable() reveal_type(jf) # N: Revealed type is "def [_T] (x: _T`-1)" reveal_type(jf(1)) # N: Revealed type is "None" -[builtins fixtures/tuple.pyi] +[builtins fixtures/paramspec.pyi] [case testStackedConcatenateIsIllegal] from typing_extensions import Concatenate, ParamSpec @@ -1048,7 +1048,7 @@ from typing import Callable P = ParamSpec("P") def x(f: Callable[Concatenate[int, Concatenate[int, P]], None]) -> None: ... # E: Nested Concatenates are invalid -[builtins fixtures/tuple.pyi] +[builtins fixtures/paramspec.pyi] [case testPropagatedAnyConstraintsAreOK] from typing import Any, Callable, Generic, TypeVar @@ -1063,3 +1063,26 @@ class Job(Generic[P]): ... @callback def run_job(job: Job[...]) -> T: ... [builtins fixtures/tuple.pyi] + +[case testTupleAndDictOperationsOnParamSpecArgsAndKwargs] +from typing import Callable +from typing_extensions import ParamSpec + +P = ParamSpec('P') + +def func(callback: Callable[P, str]) -> Callable[P, str]: + def inner(*args: P.args, **kwargs: P.kwargs) -> str: + reveal_type(args[5]) # N: Revealed type is "builtins.object" + for a in args: + reveal_type(a) # N: Revealed type is "builtins.object" + b = 'foo' in args + reveal_type(b) # N: Revealed type is "builtins.bool" + reveal_type(args.count(42)) # N: Revealed type is "builtins.int" + reveal_type(len(args)) # N: Revealed type is "builtins.int" + for c, d in kwargs.items(): + reveal_type(c) # N: Revealed type is "builtins.str" + reveal_type(d) # N: Revealed type is "builtins.object" + kwargs.pop('bar') + return 'baz' + return inner +[builtins fixtures/paramspec.pyi] diff --git a/test-data/unit/fixtures/paramspec.pyi b/test-data/unit/fixtures/paramspec.pyi new file mode 100644 index 0000000000000..0686924aad6f4 --- /dev/null +++ b/test-data/unit/fixtures/paramspec.pyi @@ -0,0 +1,76 @@ +# builtins stub for paramspec-related test cases + +from typing import ( + Sequence, Generic, TypeVar, Iterable, Iterator, Tuple, Mapping, Optional, Union, Type, overload, + Protocol +) + +T = TypeVar("T") +T_co = TypeVar('T_co', covariant=True) +KT = TypeVar("KT") +VT = TypeVar("VT") + +class object: + def __init__(self) -> None: ... + +class function: ... +class ellipsis: ... + +class type: + def __init__(self, *a: object) -> None: ... + def __call__(self, *a: object) -> object: ... + +class list(Sequence[T], Generic[T]): + @overload + def __getitem__(self, i: int) -> T: ... + @overload + def __getitem__(self, s: slice) -> list[T]: ... + def __contains__(self, item: object) -> bool: ... + def __iter__(self) -> Iterator[T]: ... + +class int: + def __neg__(self) -> 'int': ... + +class bool(int): ... +class float: ... +class slice: ... +class str: ... +class bytes: ... + +class tuple(Sequence[T_co], Generic[T_co]): + def __new__(cls: Type[T], iterable: Iterable[T_co] = ...) -> T: ... + def __iter__(self) -> Iterator[T_co]: ... + def __contains__(self, item: object) -> bool: ... + def __getitem__(self, x: int) -> T_co: ... + def __mul__(self, n: int) -> Tuple[T_co, ...]: ... + def __rmul__(self, n: int) -> Tuple[T_co, ...]: ... + def __add__(self, x: Tuple[T_co, ...]) -> Tuple[T_co, ...]: ... + def __len__(self) -> int: ... + def count(self, obj: object) -> int: ... + +class _ItemsView(Iterable[Tuple[KT, VT]]): ... + +class dict(Mapping[KT, VT]): + @overload + def __init__(self, **kwargs: VT) -> None: ... + @overload + def __init__(self, arg: Iterable[Tuple[KT, VT]], **kwargs: VT) -> None: ... + def __getitem__(self, key: KT) -> VT: ... + def __setitem__(self, k: KT, v: VT) -> None: ... + def __iter__(self) -> Iterator[KT]: ... + def __contains__(self, item: object) -> int: ... + def update(self, a: Mapping[KT, VT]) -> None: ... + @overload + def get(self, k: KT) -> Optional[VT]: ... + @overload + def get(self, k: KT, default: Union[KT, T]) -> Union[VT, T]: ... + def __len__(self) -> int: ... + def pop(self, k: KT) -> VT: ... + def items(self) -> _ItemsView[KT, VT]: ... + +def isinstance(x: object, t: type) -> bool: ... + +class _Sized(Protocol): + def __len__(self) -> int: ... + +def len(x: _Sized) -> int: ... From ce6d2433fdb9254dac5523825ab8fb310eace371 Mon Sep 17 00:00:00 2001 From: Hugues Date: Sat, 30 Apr 2022 05:50:44 -0700 Subject: [PATCH 263/377] cleanups after recent refactor of error filtering (#12699) --- mypy/checkexpr.py | 197 +++++++++++++++++-------------------------- mypy/checkpattern.py | 12 +-- mypy/errors.py | 22 ----- 3 files changed, 82 insertions(+), 149 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index f6aef2e361cce..89f2cd19a2a78 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -87,7 +87,6 @@ Optional[Type], Context, Context, - MessageBuilder, ], None, ] @@ -908,7 +907,6 @@ def check_call(self, context: Context, arg_names: Optional[Sequence[Optional[str]]] = None, callable_node: Optional[Expression] = None, - arg_messages: Optional[MessageBuilder] = None, callable_name: Optional[str] = None, object_type: Optional[Type] = None) -> Tuple[Type, Type]: """Type check a call. @@ -926,27 +924,23 @@ def check_call(self, arg_names: names of arguments (optional) callable_node: associate the inferred callable type to this node, if specified - arg_messages: utility for generating messages, can be swapped to suppress errors, - by default uses 'self.msg' to show errors callable_name: Fully-qualified name of the function/method to call, or None if unavailable (examples: 'builtins.open', 'typing.Mapping.get') object_type: If callable_name refers to a method, the type of the object on which the method is being called """ - arg_messages = arg_messages or self.msg callee = get_proper_type(callee) if isinstance(callee, CallableType): return self.check_callable_call(callee, args, arg_kinds, context, arg_names, - callable_node, arg_messages, callable_name, - object_type) + callable_node, callable_name, object_type) elif isinstance(callee, Overloaded): return self.check_overload_call(callee, args, arg_kinds, arg_names, callable_name, - object_type, context, arg_messages) + object_type, context) elif isinstance(callee, AnyType) or not self.chk.in_checked_function(): return self.check_any_type_call(args, callee) elif isinstance(callee, UnionType): - return self.check_union_call(callee, args, arg_kinds, arg_names, context, arg_messages) + return self.check_union_call(callee, args, arg_kinds, arg_names, context) elif isinstance(callee, Instance): call_function = analyze_member_access('__call__', callee, context, is_lvalue=False, is_super=False, is_operator=True, msg=self.msg, @@ -957,7 +951,7 @@ def check_call(self, call_function = self.transform_callee_type( callable_name, call_function, args, arg_kinds, context, arg_names, callee) result = self.check_call(call_function, args, arg_kinds, context, arg_names, - callable_node, arg_messages, callable_name, callee) + callable_node, callable_name, callee) if callable_node: # check_call() stored "call_function" as the type, which is incorrect. # Override the type. @@ -965,14 +959,14 @@ def check_call(self, return result elif isinstance(callee, TypeVarType): return self.check_call(callee.upper_bound, args, arg_kinds, context, arg_names, - callable_node, arg_messages) + callable_node) elif isinstance(callee, TypeType): item = self.analyze_type_type_callee(callee.item, context) return self.check_call(item, args, arg_kinds, context, arg_names, - callable_node, arg_messages) + callable_node) elif isinstance(callee, TupleType): return self.check_call(tuple_fallback(callee), args, arg_kinds, context, - arg_names, callable_node, arg_messages, callable_name, + arg_names, callable_node, callable_name, object_type) else: return self.msg.not_callable(callee, context), AnyType(TypeOfAny.from_error) @@ -984,7 +978,6 @@ def check_callable_call(self, context: Context, arg_names: Optional[Sequence[Optional[str]]], callable_node: Optional[Expression], - arg_messages: MessageBuilder, callable_name: Optional[str], object_type: Optional[Type]) -> Tuple[Type, Type]: """Type check a call that targets a callable value. @@ -1050,10 +1043,10 @@ def check_callable_call(self, callee, args, arg_kinds, formal_to_actual) self.check_argument_count(callee, arg_types, arg_kinds, - arg_names, formal_to_actual, context, self.msg) + arg_names, formal_to_actual, context) self.check_argument_types(arg_types, arg_kinds, args, callee, formal_to_actual, context, - messages=arg_messages, object_type=object_type) + object_type=object_type) if (callee.is_type_obj() and (len(arg_types) == 1) and is_equivalent(callee.ret_type, self.named_type('builtins.type'))): @@ -1379,8 +1372,7 @@ def check_argument_count(self, actual_kinds: List[ArgKind], actual_names: Optional[Sequence[Optional[str]]], formal_to_actual: List[List[int]], - context: Optional[Context], - messages: Optional[MessageBuilder]) -> bool: + context: Optional[Context]) -> bool: """Check that there is a value for all required arguments to a function. Also check that there are no duplicate values for arguments. Report found errors @@ -1388,9 +1380,7 @@ def check_argument_count(self, Return False if there were any errors. Otherwise return True """ - if messages: - assert context, "Internal error: messages given without context" - elif context is None: + if context is None: # Avoid "is None" checks context = TempNode(AnyType(TypeOfAny.special_form)) @@ -1402,32 +1392,29 @@ def check_argument_count(self, all_actuals.extend(actuals) ok, is_unexpected_arg_error = self.check_for_extra_actual_arguments( - callee, actual_types, actual_kinds, actual_names, all_actuals, context, messages) + callee, actual_types, actual_kinds, actual_names, all_actuals, context) # Check for too many or few values for formals. for i, kind in enumerate(callee.arg_kinds): if kind.is_required() and not formal_to_actual[i] and not is_unexpected_arg_error: # No actual for a mandatory formal - if messages: - if kind.is_positional(): - messages.too_few_arguments(callee, context, actual_names) - else: - argname = callee.arg_names[i] or "?" - messages.missing_named_argument(callee, context, argname) + if kind.is_positional(): + self.msg.too_few_arguments(callee, context, actual_names) + else: + argname = callee.arg_names[i] or "?" + self.msg.missing_named_argument(callee, context, argname) ok = False elif not kind.is_star() and is_duplicate_mapping( formal_to_actual[i], actual_types, actual_kinds): if (self.chk.in_checked_function() or isinstance(get_proper_type(actual_types[formal_to_actual[i][0]]), TupleType)): - if messages: - messages.duplicate_argument_value(callee, i, context) + self.msg.duplicate_argument_value(callee, i, context) ok = False elif (kind.is_named() and formal_to_actual[i] and actual_kinds[formal_to_actual[i][0]] not in [nodes.ARG_NAMED, nodes.ARG_STAR2]): # Positional argument when expecting a keyword argument. - if messages: - messages.too_many_positional_arguments(callee, context) + self.msg.too_many_positional_arguments(callee, context) ok = False return ok @@ -1437,8 +1424,7 @@ def check_for_extra_actual_arguments(self, actual_kinds: List[ArgKind], actual_names: Optional[Sequence[Optional[str]]], all_actuals: List[int], - context: Context, - messages: Optional[MessageBuilder]) -> Tuple[bool, bool]: + context: Context) -> Tuple[bool, bool]: """Check for extra actual arguments. Return tuple (was everything ok, @@ -1459,15 +1445,13 @@ def check_for_extra_actual_arguments(self, # Extra actual: not matched by a formal argument. ok = False if kind != nodes.ARG_NAMED: - if messages: - messages.too_many_arguments(callee, context) + self.msg.too_many_arguments(callee, context) else: - if messages: - assert actual_names, "Internal error: named kinds without names given" - act_name = actual_names[i] - assert act_name is not None - act_type = actual_types[i] - messages.unexpected_keyword_argument(callee, act_name, act_type, context) + assert actual_names, "Internal error: named kinds without names given" + act_name = actual_names[i] + assert act_name is not None + act_type = actual_types[i] + self.msg.unexpected_keyword_argument(callee, act_name, act_type, context) is_unexpected_arg_error = True elif ((kind == nodes.ARG_STAR and nodes.ARG_STAR not in callee.arg_kinds) or kind == nodes.ARG_STAR2): @@ -1475,14 +1459,13 @@ def check_for_extra_actual_arguments(self, if isinstance(actual_type, (TupleType, TypedDictType)): if all_actuals.count(i) < len(actual_type.items): # Too many tuple/dict items as some did not match. - if messages: - if (kind != nodes.ARG_STAR2 - or not isinstance(actual_type, TypedDictType)): - messages.too_many_arguments(callee, context) - else: - messages.too_many_arguments_from_typed_dict(callee, actual_type, - context) - is_unexpected_arg_error = True + if (kind != nodes.ARG_STAR2 + or not isinstance(actual_type, TypedDictType)): + self.msg.too_many_arguments(callee, context) + else: + self.msg.too_many_arguments_from_typed_dict(callee, actual_type, + context) + is_unexpected_arg_error = True ok = False # *args/**kwargs can be applied even if the function takes a fixed # number of positional arguments. This may succeed at runtime. @@ -1496,7 +1479,6 @@ def check_argument_types(self, callee: CallableType, formal_to_actual: List[List[int]], context: Context, - messages: Optional[MessageBuilder] = None, check_arg: Optional[ArgChecker] = None, object_type: Optional[Type] = None) -> None: """Check argument types against a callable type. @@ -1505,7 +1487,6 @@ def check_argument_types(self, The check_call docstring describes some of the arguments. """ - messages = messages or self.msg check_arg = check_arg or self.check_arg # Keep track of consumed tuple *arg items. mapper = ArgTypeExpander(self.argument_infer_context()) @@ -1518,17 +1499,17 @@ def check_argument_types(self, # Check that a *arg is valid as varargs. if (actual_kind == nodes.ARG_STAR and not self.is_valid_var_arg(actual_type)): - messages.invalid_var_arg(actual_type, context) + self.msg.invalid_var_arg(actual_type, context) if (actual_kind == nodes.ARG_STAR2 and not self.is_valid_keyword_var_arg(actual_type)): is_mapping = is_subtype(actual_type, self.chk.named_type('typing.Mapping')) - messages.invalid_keyword_var_arg(actual_type, is_mapping, context) + self.msg.invalid_keyword_var_arg(actual_type, is_mapping, context) expanded_actual = mapper.expand_actual_type( actual_type, actual_kind, callee.arg_names[i], callee.arg_kinds[i]) check_arg(expanded_actual, actual_type, arg_kinds[actual], callee.arg_types[i], - actual + 1, i + 1, callee, object_type, args[actual], context, messages) + actual + 1, i + 1, callee, object_type, args[actual], context) def check_arg(self, caller_type: Type, @@ -1540,15 +1521,14 @@ def check_arg(self, callee: CallableType, object_type: Optional[Type], context: Context, - outer_context: Context, - messages: MessageBuilder) -> None: + outer_context: Context) -> None: """Check the type of a single argument in a call.""" caller_type = get_proper_type(caller_type) original_caller_type = get_proper_type(original_caller_type) callee_type = get_proper_type(callee_type) if isinstance(caller_type, DeletedType): - messages.deleted_as_rvalue(caller_type, context) + self.msg.deleted_as_rvalue(caller_type, context) # Only non-abstract non-protocol class can be given where Type[...] is expected... elif (isinstance(caller_type, CallableType) and isinstance(callee_type, TypeType) and caller_type.is_type_obj() and @@ -1559,7 +1539,7 @@ def check_arg(self, elif not is_subtype(caller_type, callee_type, options=self.chk.options): if self.chk.should_suppress_optional_error([caller_type, callee_type]): return - code = messages.incompatible_argument(n, + code = self.msg.incompatible_argument(n, m, callee, original_caller_type, @@ -1567,7 +1547,7 @@ def check_arg(self, object_type=object_type, context=context, outer_context=outer_context) - messages.incompatible_argument_note(original_caller_type, callee_type, context, + self.msg.incompatible_argument_note(original_caller_type, callee_type, context, code=code) def check_overload_call(self, @@ -1577,8 +1557,7 @@ def check_overload_call(self, arg_names: Optional[Sequence[Optional[str]]], callable_name: Optional[str], object_type: Optional[Type], - context: Context, - arg_messages: MessageBuilder) -> Tuple[Type, Type]: + context: Context) -> Tuple[Type, Type]: """Checks a call to an overloaded function.""" arg_types = self.infer_arg_types_in_empty_context(args) # Step 1: Filter call targets to remove ones where the argument counts don't match @@ -1595,12 +1574,11 @@ def check_overload_call(self, union_interrupted = False # did we try all union combinations? if any(self.real_union(arg) for arg in arg_types): try: - with arg_messages.filter_errors(): + with self.msg.filter_errors(): unioned_return = self.union_overload_result(plausible_targets, args, arg_types, arg_kinds, arg_names, callable_name, object_type, - context, - arg_messages=arg_messages) + context) except TooManyUnions: union_interrupted = True else: @@ -1620,7 +1598,7 @@ def check_overload_call(self, # Step 3: We try checking each branch one-by-one. inferred_result = self.infer_overload_return_type(plausible_targets, args, arg_types, arg_kinds, arg_names, callable_name, - object_type, context, arg_messages) + object_type, context) # If any of checks succeed, stop early. if inferred_result is not None and unioned_result is not None: # Both unioned and direct checks succeeded, choose the more precise type. @@ -1664,11 +1642,10 @@ def check_overload_call(self, code = None else: code = codes.OPERATOR - arg_messages.no_variant_matches_arguments( + self.msg.no_variant_matches_arguments( callee, arg_types, context, code=code) result = self.check_call(target, args, arg_kinds, context, arg_names, - arg_messages=arg_messages, callable_name=callable_name, object_type=object_type) if union_interrupted: @@ -1712,14 +1689,15 @@ def has_shape(typ: Type) -> bool: typ.arg_kinds, typ.arg_names, lambda i: arg_types[i]) - if self.check_argument_count(typ, arg_types, arg_kinds, arg_names, - formal_to_actual, None, None): - if args_have_var_arg and typ.is_var_arg: - star_matches.append(typ) - elif args_have_kw_arg and typ.is_kw_arg: - star_matches.append(typ) - else: - matches.append(typ) + with self.msg.filter_errors(): + if self.check_argument_count(typ, arg_types, arg_kinds, arg_names, + formal_to_actual, None): + if args_have_var_arg and typ.is_var_arg: + star_matches.append(typ) + elif args_have_kw_arg and typ.is_kw_arg: + star_matches.append(typ) + else: + matches.append(typ) return star_matches + matches @@ -1732,7 +1710,6 @@ def infer_overload_return_type(self, callable_name: Optional[str], object_type: Optional[Type], context: Context, - arg_messages: Optional[MessageBuilder] = None, ) -> Optional[Tuple[Type, Type]]: """Attempts to find the first matching callable from the given list. @@ -1744,7 +1721,6 @@ def infer_overload_return_type(self, Assumes all of the given targets have argument counts compatible with the caller. """ - arg_messages = self.msg if arg_messages is None else arg_messages matches: List[CallableType] = [] return_types: List[Type] = [] inferred_types: List[Type] = [] @@ -1759,7 +1735,6 @@ def infer_overload_return_type(self, arg_kinds=arg_kinds, arg_names=arg_names, context=context, - arg_messages=self.msg, callable_name=callable_name, object_type=object_type) is_match = not w.has_new_errors() @@ -1788,7 +1763,6 @@ def infer_overload_return_type(self, arg_kinds=arg_kinds, arg_names=arg_names, context=context, - arg_messages=arg_messages, callable_name=callable_name, object_type=object_type) else: @@ -1822,7 +1796,6 @@ def union_overload_result(self, callable_name: Optional[str], object_type: Optional[Type], context: Context, - arg_messages: Optional[MessageBuilder] = None, level: int = 0 ) -> Optional[List[Tuple[Type, Type]]]: """Accepts a list of overload signatures and attempts to match calls by destructuring @@ -1847,7 +1820,7 @@ def union_overload_result(self, with self.type_overrides_set(args, arg_types): res = self.infer_overload_return_type(plausible_targets, args, arg_types, arg_kinds, arg_names, callable_name, - object_type, context, arg_messages) + object_type, context) if res is not None: return [res] return None @@ -1857,7 +1830,7 @@ def union_overload_result(self, with self.type_overrides_set(args, arg_types): direct = self.infer_overload_return_type(plausible_targets, args, arg_types, arg_kinds, arg_names, callable_name, - object_type, context, arg_messages) + object_type, context) if direct is not None and not isinstance(get_proper_type(direct[0]), (UnionType, AnyType)): # We only return non-unions soon, to avoid greedy match. @@ -1873,7 +1846,7 @@ def union_overload_result(self, new_arg_types[idx] = item sub_result = self.union_overload_result(plausible_targets, args, new_arg_types, arg_kinds, arg_names, callable_name, - object_type, context, arg_messages, + object_type, context, level + 1) if sub_result is not None: res_items.extend(sub_result) @@ -2003,10 +1976,11 @@ def erased_signature_similarity(self, callee.arg_names, lambda i: arg_types[i]) - if not self.check_argument_count(callee, arg_types, arg_kinds, arg_names, - formal_to_actual, None, None): - # Too few or many arguments -> no match. - return False + with self.msg.filter_errors(): + if not self.check_argument_count(callee, arg_types, arg_kinds, arg_names, + formal_to_actual, None): + # Too few or many arguments -> no match. + return False def check_arg(caller_type: Type, original_ccaller_type: Type, @@ -2017,8 +1991,7 @@ def check_arg(caller_type: Type, callee: CallableType, object_type: Optional[Type], context: Context, - outer_context: Context, - messages: MessageBuilder) -> None: + outer_context: Context) -> None: if not arg_approximate_similarity(caller_type, callee_type): # No match -- exit early since none of the remaining work can change # the result. @@ -2052,8 +2025,7 @@ def check_union_call(self, args: List[Expression], arg_kinds: List[ArgKind], arg_names: Optional[Sequence[Optional[str]]], - context: Context, - arg_messages: MessageBuilder) -> Tuple[Type, Type]: + context: Context) -> Tuple[Type, Type]: with self.msg.disable_type_names(): results = [ self.check_call( @@ -2062,7 +2034,6 @@ def check_union_call(self, arg_kinds, context, arg_names, - arg_messages=arg_messages, ) for subtype in callee.relevant_items() ] @@ -2421,7 +2392,6 @@ def check_method_call_by_name(self, args: List[Expression], arg_kinds: List[ArgKind], context: Context, - local_errors: Optional[MessageBuilder] = None, original_type: Optional[Type] = None ) -> Tuple[Type, Type]: """Type check a call to a named method on an object. @@ -2429,21 +2399,20 @@ def check_method_call_by_name(self, Return tuple (result type, inferred method type). The 'original_type' is used for error messages. """ - local_errors = local_errors or self.msg original_type = original_type or base_type # Unions are special-cased to allow plugins to act on each element of the union. base_type = get_proper_type(base_type) if isinstance(base_type, UnionType): return self.check_union_method_call_by_name(method, base_type, args, arg_kinds, - context, local_errors, original_type) + context, original_type) method_type = analyze_member_access(method, base_type, context, False, False, True, - local_errors, original_type=original_type, + self.msg, original_type=original_type, chk=self.chk, in_literal_context=self.is_literal_context()) return self.check_method_call( - method, base_type, method_type, args, arg_kinds, context, local_errors) + method, base_type, method_type, args, arg_kinds, context) def check_union_method_call_by_name(self, method: str, @@ -2451,7 +2420,6 @@ def check_union_method_call_by_name(self, args: List[Expression], arg_kinds: List[ArgKind], context: Context, - local_errors: MessageBuilder, original_type: Optional[Type] = None ) -> Tuple[Type, Type]: """Type check a call to a named method on an object with union type. @@ -2465,10 +2433,10 @@ def check_union_method_call_by_name(self, for typ in base_type.relevant_items(): # Format error messages consistently with # mypy.checkmember.analyze_union_member_access(). - with local_errors.disable_type_names(): + with self.msg.disable_type_names(): item, meth_item = self.check_method_call_by_name( method, typ, args, arg_kinds, - context, local_errors, original_type, + context, original_type, ) res.append(item) meth_res.append(meth_item) @@ -2480,8 +2448,7 @@ def check_method_call(self, method_type: Type, args: List[Expression], arg_kinds: List[ArgKind], - context: Context, - local_errors: Optional[MessageBuilder] = None) -> Tuple[Type, Type]: + context: Context) -> Tuple[Type, Type]: """Type check a call to a method with the given name and type on an object. Return tuple (result type, inferred method type). @@ -2494,8 +2461,7 @@ def check_method_call(self, callable_name, method_type, args, arg_kinds, context, object_type=object_type) return self.check_call(method_type, args, arg_kinds, - context, arg_messages=local_errors, - callable_name=callable_name, object_type=base_type) + context, callable_name=callable_name, object_type=base_type) def check_op_reversible(self, op_name: str, @@ -2503,8 +2469,7 @@ def check_op_reversible(self, left_expr: Expression, right_type: Type, right_expr: Expression, - context: Context, - msg: MessageBuilder) -> Tuple[Type, Type]: + context: Context) -> Tuple[Type, Type]: def lookup_operator(op_name: str, base_type: Type) -> Optional[Type]: """Looks up the given operator and returns the corresponding type, if it exists.""" @@ -2683,7 +2648,7 @@ def lookup_definer(typ: Instance, attr_name: str) -> Optional[str]: # TODO: Remove this extra case return result - msg.add_errors(errors[0]) + self.msg.add_errors(errors[0]) if len(results) == 1: return results[0] else: @@ -2722,8 +2687,7 @@ def check_op(self, method: str, base_type: Type, left_expr=TempNode(left_possible_type, context=context), right_type=right_type, right_expr=arg, - context=context, - msg=self.msg) + context=context) all_results.append(result) all_inferred.append(inferred) @@ -2764,8 +2728,7 @@ def check_op(self, method: str, base_type: Type, left_expr=TempNode(left_possible_type, context=context), right_type=right_possible_type, right_expr=right_expr, - context=context, - msg=self.msg) + context=context) all_results.append(result) all_inferred.append(inferred) @@ -2798,7 +2761,6 @@ def check_op(self, method: str, base_type: Type, args=[arg], arg_kinds=[ARG_POS], context=context, - local_errors=self.msg, ) def get_reverse_op_method(self, method: str) -> str: @@ -3073,9 +3035,7 @@ def nonliteral_tuple_index_helper(self, left_type: TupleType, index: Expression) def visit_typeddict_index_expr(self, td_type: TypedDictType, index: Expression, - local_errors: Optional[MessageBuilder] = None ) -> Type: - local_errors = local_errors or self.msg if isinstance(index, (StrExpr, UnicodeExpr)): key_names = [index.value] else: @@ -3095,14 +3055,14 @@ def visit_typeddict_index_expr(self, td_type: TypedDictType, and key_type.fallback.type.fullname != 'builtins.bytes'): key_names.append(key_type.value) else: - local_errors.typeddict_key_must_be_string_literal(td_type, index) + self.msg.typeddict_key_must_be_string_literal(td_type, index) return AnyType(TypeOfAny.from_error) value_types = [] for key_name in key_names: value_type = td_type.items.get(key_name) if value_type is None: - local_errors.typeddict_key_not_found(td_type, key_name, index) + self.msg.typeddict_key_not_found(td_type, key_name, index) return AnyType(TypeOfAny.from_error) else: value_types.append(value_type) @@ -3827,8 +3787,7 @@ def check_generator_or_comprehension(self, gen: GeneratorExpr, self.chk.named_type('builtins.function'), name=id_for_messages, variables=[tv]) - return self.check_call(constructor, - [gen.left_expr], [nodes.ARG_POS], gen)[0] + return self.check_call(constructor, [gen.left_expr], [nodes.ARG_POS], gen)[0] def visit_dictionary_comprehension(self, e: DictionaryComprehension) -> Type: """Type check a dictionary comprehension.""" diff --git a/mypy/checkpattern.py b/mypy/checkpattern.py index 84b9acae1aa20..7836da0192571 100644 --- a/mypy/checkpattern.py +++ b/mypy/checkpattern.py @@ -428,8 +428,7 @@ def get_mapping_item_type(self, with self.msg.filter_errors() as local_errors: result = self.get_simple_mapping_item_type(pattern, mapping_type, - key, - self.msg) + key) if local_errors.has_new_errors(): result = None @@ -437,22 +436,19 @@ def get_mapping_item_type(self, with self.msg.filter_errors(): result = self.get_simple_mapping_item_type(pattern, mapping_type, - key, - self.msg) + key) return result def get_simple_mapping_item_type(self, pattern: MappingPattern, mapping_type: Type, - key: Expression, - local_errors: MessageBuilder + key: Expression ) -> Type: result, _ = self.chk.expr_checker.check_method_call_by_name('__getitem__', mapping_type, [key], [ARG_POS], - pattern, - local_errors=local_errors) + pattern) return result def visit_class_pattern(self, o: ClassPattern) -> PatternType: diff --git a/mypy/errors.py b/mypy/errors.py index 6dc0a21e79041..87a59e3ca9ed1 100644 --- a/mypy/errors.py +++ b/mypy/errors.py @@ -274,24 +274,6 @@ def initialize(self) -> None: def reset(self) -> None: self.initialize() - def copy(self) -> 'Errors': - new = Errors(self.show_error_context, - self.show_column_numbers, - self.show_error_codes, - self.pretty, - self.read_source, - self.show_absolute_path, - self.enabled_error_codes, - self.disabled_error_codes, - self.many_errors_threshold) - new.file = self.file - new.import_ctx = self.import_ctx[:] - new.function_or_member = self.function_or_member[:] - new.target_module = self.target_module - new.scope = self.scope - new.seen_import_error = self.seen_import_error - return new - def set_ignore_prefix(self, prefix: str) -> None: """Set path prefix that will be removed from all paths.""" prefix = os.path.normpath(prefix) @@ -651,10 +633,6 @@ def is_errors_for_file(self, file: str) -> bool: """Are there any errors for the given file?""" return file in self.error_info_map - def most_recent_error_location(self) -> Tuple[int, int]: - info = self.error_info_map[self.file][-1] - return info.line, info.column - def raise_error(self, use_stdout: bool = True) -> None: """Raise a CompileError with the generated messages. From 33dbbd2cde45fe688a716f5d10e51d1bd6a0b096 Mon Sep 17 00:00:00 2001 From: eggplants Date: Sun, 1 May 2022 13:32:35 +0900 Subject: [PATCH 264/377] fix: dead link in readme (#12702) `introduction.rst` has moved into `index.rst` in #12348. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c8f4df995f3ab..1be59f0b00275 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ number = input("What is your favourite number?") print("It is", number + 1) # error: Unsupported operand types for + ("str" and "int") ``` -See [the documentation](https://mypy.readthedocs.io/en/stable/introduction.html) for more examples. +See [the documentation](https://mypy.readthedocs.io/en/stable/index.html) for more examples. In particular, see: - [type hints cheat sheet](https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html) From dd6d78615455fdd9895cff1691f2de6bb2893a48 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sat, 30 Apr 2022 23:08:25 -0600 Subject: [PATCH 265/377] Use callback protocol instead of mypy_extensions (#12701) --- mypy/typeanal.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/mypy/typeanal.py b/mypy/typeanal.py index 84d9758b9a573..41225a6061f35 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -6,8 +6,7 @@ from mypy.backports import OrderedDict from typing import Callable, List, Optional, Set, Tuple, Iterator, TypeVar, Iterable, Sequence -from typing_extensions import Final -from mypy_extensions import DefaultNamedArg +from typing_extensions import Final, Protocol from mypy.messages import MessageBuilder, quote_type_string, format_type_bare from mypy.options import Options @@ -1241,8 +1240,15 @@ def set_allow_param_spec_literals(self, to: bool) -> Iterator[None]: TypeVarLikeList = List[Tuple[str, TypeVarLikeExpr]] -# Mypyc doesn't support callback protocols yet. -MsgCallback = Callable[[str, Context, DefaultNamedArg(Optional[ErrorCode], 'code')], None] + +class MsgCallback(Protocol): + def __call__( + self, + __msg: str, + __ctx: Context, + *, + code: Optional[ErrorCode] = None + ) -> None: ... def get_omitted_any(disallow_any: bool, fail: MsgCallback, note: MsgCallback, From a56ebec8bdc1f22c7bf801653f61c9963dd3fc90 Mon Sep 17 00:00:00 2001 From: Hugues Date: Sat, 30 Apr 2022 22:55:17 -0700 Subject: [PATCH 266/377] checkexpr: speedup argument count check (#12703) Replace List with Dict to avoid O(n**2) behavior in `check_for_extra_actual_arguments` This manifests for instance when initializing a set with `set([...])` instead of a set literal `{...}`. For large sets of literals (~80k entries) this change bring the typechecking of a single set initializer from over 1 min down to under 1s. --- mypy/checkexpr.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 89f2cd19a2a78..bd69c1427dce1 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -1386,10 +1386,11 @@ def check_argument_count(self, # TODO(jukka): We could return as soon as we find an error if messages is None. - # Collect list of all actual arguments matched to formal arguments. - all_actuals: List[int] = [] + # Collect dict of all actual arguments matched to formal arguments, with occurrence count + all_actuals: Dict[int, int] = {} for actuals in formal_to_actual: - all_actuals.extend(actuals) + for a in actuals: + all_actuals[a] = all_actuals.get(a, 0) + 1 ok, is_unexpected_arg_error = self.check_for_extra_actual_arguments( callee, actual_types, actual_kinds, actual_names, all_actuals, context) @@ -1423,7 +1424,7 @@ def check_for_extra_actual_arguments(self, actual_types: List[Type], actual_kinds: List[ArgKind], actual_names: Optional[Sequence[Optional[str]]], - all_actuals: List[int], + all_actuals: Dict[int, int], context: Context) -> Tuple[bool, bool]: """Check for extra actual arguments. @@ -1457,7 +1458,7 @@ def check_for_extra_actual_arguments(self, or kind == nodes.ARG_STAR2): actual_type = get_proper_type(actual_types[i]) if isinstance(actual_type, (TupleType, TypedDictType)): - if all_actuals.count(i) < len(actual_type.items): + if all_actuals.get(i, 0) < len(actual_type.items): # Too many tuple/dict items as some did not match. if (kind != nodes.ARG_STAR2 or not isinstance(actual_type, TypedDictType)): From 1662fe8142b6b115bb8da255b1a02bff9e8b7868 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sun, 1 May 2022 13:58:19 -0600 Subject: [PATCH 267/377] mypy/test: run pyupgrade (#12710) Re-attempt of #10741 Ran: `pyupgrade --py36-plus $(fd -e py) --keep-runtime-typing` I mostly only needed to change things where NamedTuple comments got dropped. Co-authored-by: hauntsaninja <> --- mypy/test/data.py | 27 +++++++++++++++----------- mypy/test/helpers.py | 12 ++++++------ mypy/test/test_find_sources.py | 12 ++++++------ mypy/test/testargs.py | 10 +++++----- mypy/test/testcheck.py | 2 +- mypy/test/testcmdline.py | 4 ++-- mypy/test/testdeps.py | 2 +- mypy/test/testfinegrained.py | 4 ++-- mypy/test/testgraph.py | 2 +- mypy/test/testmerge.py | 10 +++++----- mypy/test/testpep561.py | 12 ++++++------ mypy/test/testpythoneval.py | 4 ++-- mypy/test/testsemanal.py | 8 ++++---- mypy/test/teststubgen.py | 2 +- mypy/test/teststubtest.py | 35 +++++++++++++++++----------------- mypy/test/testsubtypes.py | 4 ++-- mypy/test/testtypegen.py | 2 +- mypy/test/testtypes.py | 18 ++++++++--------- 18 files changed, 87 insertions(+), 83 deletions(-) diff --git a/mypy/test/data.py b/mypy/test/data.py index e18ac142d15e6..9f1c6a1aa24c0 100644 --- a/mypy/test/data.py +++ b/mypy/test/data.py @@ -16,14 +16,19 @@ root_dir = os.path.normpath(PREFIX) + # File modify/create operation: copy module contents from source_path. -UpdateFile = NamedTuple('UpdateFile', [('module', str), - ('content', str), - ('target_path', str)]) +class UpdateFile(NamedTuple): + module: str + content: str + target_path: str + # File delete operation: delete module file. -DeleteFile = NamedTuple('DeleteFile', [('module', str), - ('path', str)]) +class DeleteFile(NamedTuple): + module: str + path: str + FileOperation = Union[UpdateFile, DeleteFile] @@ -100,9 +105,9 @@ def parse_test_case(case: 'DataDrivenTestCase') -> None: # File/directory to delete during a multi-step test case assert item.arg is not None m = re.match(r'(.*)\.([0-9]+)$', item.arg) - assert m, 'Invalid delete section: {}'.format(item.arg) + assert m, f'Invalid delete section: {item.arg}' num = int(m.group(2)) - assert num >= 2, "Can't delete during step {}".format(num) + assert num >= 2, f"Can't delete during step {num}" full = join(base_path, m.group(1)) deleted_paths.setdefault(num, set()).add(full) elif re.match(r'out[0-9]*$', item.id): @@ -271,7 +276,7 @@ def runtest(self) -> None: if save_dir: assert self.tmpdir is not None target_dir = os.path.join(save_dir, os.path.basename(self.tmpdir.name)) - print("Copying data from test {} to {}".format(self.name, target_dir)) + print(f"Copying data from test {self.name} to {target_dir}") if not os.path.isabs(target_dir): assert self.old_cwd target_dir = os.path.join(self.old_cwd, target_dir) @@ -339,7 +344,7 @@ def repr_failure(self, excinfo: Any, style: Optional[Any] = None) -> str: self.parent._prunetraceback(excinfo) excrepr = excinfo.getrepr(style='short') - return "data: {}:{}:\n{}".format(self.file, self.line, excrepr) + return f"data: {self.file}:{self.line}:\n{excrepr}" def find_steps(self) -> List[List[FileOperation]]: """Return a list of descriptions of file operations for each incremental step. @@ -493,7 +498,7 @@ def expand_errors(input: List[str], output: List[str], fnam: str) -> None: message = message.replace('\\#', '#') # adds back escaped # character if col is None: output.append( - '{}:{}: {}: {}'.format(fnam, i + 1, severity, message)) + f'{fnam}:{i + 1}: {severity}: {message}') else: output.append('{}:{}:{}: {}: {}'.format( fnam, i + 1, col, severity, message)) @@ -625,7 +630,7 @@ def collect(self) -> Iterator['DataFileCollector']: suite: DataSuite = self.obj assert os.path.isdir(suite.data_prefix), \ - 'Test data prefix ({}) not set correctly'.format(suite.data_prefix) + f'Test data prefix ({suite.data_prefix}) not set correctly' for data_file in suite.files: yield DataFileCollector.from_parent(parent=self, name=data_file) diff --git a/mypy/test/helpers.py b/mypy/test/helpers.py index 5046c46eaa434..af1fefe67ffd6 100644 --- a/mypy/test/helpers.py +++ b/mypy/test/helpers.py @@ -79,7 +79,7 @@ def assert_string_arrays_equal(expected: List[str], actual: List[str], if i >= len(actual) or expected[i] != actual[i]: if first_diff < 0: first_diff = i - sys.stderr.write(' {:<45} (diff)'.format(expected[i])) + sys.stderr.write(f' {expected[i]:<45} (diff)') else: e = expected[i] sys.stderr.write(' ' + e[:width]) @@ -96,7 +96,7 @@ def assert_string_arrays_equal(expected: List[str], actual: List[str], for j in range(num_skip_start, len(actual) - num_skip_end): if j >= len(expected) or expected[j] != actual[j]: - sys.stderr.write(' {:<45} (diff)'.format(actual[j])) + sys.stderr.write(f' {actual[j]:<45} (diff)') else: a = actual[j] sys.stderr.write(' ' + a[:width]) @@ -217,8 +217,8 @@ def show_align_message(s1: str, s2: str) -> None: extra = '...' # Write a chunk of both lines, aligned. - sys.stderr.write(' E: {}{}\n'.format(s1[:maxw], extra)) - sys.stderr.write(' A: {}{}\n'.format(s2[:maxw], extra)) + sys.stderr.write(f' E: {s1[:maxw]}{extra}\n') + sys.stderr.write(f' A: {s2[:maxw]}{extra}\n') # Write an indicator character under the different columns. sys.stderr.write(' ') for j in range(min(maxw, max(len(s1), len(s2)))): @@ -370,7 +370,7 @@ def parse_options(program_text: str, testcase: DataDrivenTestCase, options = Options() flags = re.search('# flags: (.*)$', program_text, flags=re.MULTILINE) if incremental_step > 1: - flags2 = re.search('# flags{}: (.*)$'.format(incremental_step), program_text, + flags2 = re.search(f'# flags{incremental_step}: (.*)$', program_text, flags=re.MULTILINE) if flags2: flags = flags2 @@ -457,7 +457,7 @@ def check_test_output_files(testcase: DataDrivenTestCase, raise AssertionError( 'Expected file {} was not produced by test case{}'.format( path, ' on step %d' % step if testcase.output2 else '')) - with open(path, 'r', encoding='utf8') as output_file: + with open(path, encoding='utf8') as output_file: actual_output_content = output_file.read() if isinstance(expected_content, Pattern): diff --git a/mypy/test/test_find_sources.py b/mypy/test/test_find_sources.py index 53da9c384bd21..e9e7432327e7f 100644 --- a/mypy/test/test_find_sources.py +++ b/mypy/test/test_find_sources.py @@ -26,7 +26,7 @@ def isdir(self, dir: str) -> bool: def listdir(self, dir: str) -> List[str]: if not dir.endswith(os.sep): dir += os.sep - return list(set(f[len(dir):].split(os.sep)[0] for f in self.files if f.startswith(dir))) + return list({f[len(dir):].split(os.sep)[0] for f in self.files if f.startswith(dir)}) def init_under_package_root(self, file: str) -> bool: return False @@ -278,15 +278,15 @@ def test_find_sources_exclude(self) -> None: # default for excluded_dir in ["site-packages", ".whatever", "node_modules", ".x/.z"]: - fscache = FakeFSCache({"/dir/a.py", "/dir/venv/{}/b.py".format(excluded_dir)}) + fscache = FakeFSCache({"/dir/a.py", f"/dir/venv/{excluded_dir}/b.py"}) assert find_sources(["/"], options, fscache) == [("a", "/dir")] with pytest.raises(InvalidSourceList): find_sources(["/dir/venv/"], options, fscache) - assert find_sources(["/dir/venv/{}".format(excluded_dir)], options, fscache) == [ - ("b", "/dir/venv/{}".format(excluded_dir)) + assert find_sources([f"/dir/venv/{excluded_dir}"], options, fscache) == [ + ("b", f"/dir/venv/{excluded_dir}") ] - assert find_sources(["/dir/venv/{}/b.py".format(excluded_dir)], options, fscache) == [ - ("b", "/dir/venv/{}".format(excluded_dir)) + assert find_sources([f"/dir/venv/{excluded_dir}/b.py"], options, fscache) == [ + ("b", f"/dir/venv/{excluded_dir}") ] files = { diff --git a/mypy/test/testargs.py b/mypy/test/testargs.py index f26e897fbb10f..8d74207f353fd 100644 --- a/mypy/test/testargs.py +++ b/mypy/test/testargs.py @@ -27,25 +27,25 @@ def test_executable_inference(self) -> None: base = ['file.py'] # dummy file # test inference given one (infer the other) - matching_version = base + ['--python-version={}'.format(sys_ver_str)] + matching_version = base + [f'--python-version={sys_ver_str}'] _, options = process_options(matching_version) assert options.python_version == sys.version_info[:2] assert options.python_executable == sys.executable - matching_version = base + ['--python-executable={}'.format(sys.executable)] + matching_version = base + [f'--python-executable={sys.executable}'] _, options = process_options(matching_version) assert options.python_version == sys.version_info[:2] assert options.python_executable == sys.executable # test inference given both - matching_version = base + ['--python-version={}'.format(sys_ver_str), - '--python-executable={}'.format(sys.executable)] + matching_version = base + [f'--python-version={sys_ver_str}', + f'--python-executable={sys.executable}'] _, options = process_options(matching_version) assert options.python_version == sys.version_info[:2] assert options.python_executable == sys.executable # test that --no-site-packages will disable executable inference - matching_version = base + ['--python-version={}'.format(sys_ver_str), + matching_version = base + [f'--python-version={sys_ver_str}', '--no-site-packages'] _, options = process_options(matching_version) assert options.python_version == sys.version_info[:2] diff --git a/mypy/test/testcheck.py b/mypy/test/testcheck.py index 4f6c82877775f..2f74e543d4690 100644 --- a/mypy/test/testcheck.py +++ b/mypy/test/testcheck.py @@ -328,7 +328,7 @@ def parse_module(self, """ m = re.search('# cmd: mypy -m ([a-zA-Z0-9_. ]+)$', program_text, flags=re.MULTILINE) if incremental_step > 1: - alt_regex = '# cmd{}: mypy -m ([a-zA-Z0-9_. ]+)$'.format(incremental_step) + alt_regex = f'# cmd{incremental_step}: mypy -m ([a-zA-Z0-9_. ]+)$' alt_m = re.search(alt_regex, program_text, flags=re.MULTILINE) if alt_m is not None: # Optionally return a different command if in a later step diff --git a/mypy/test/testcmdline.py b/mypy/test/testcmdline.py index 9fafb1f36cae6..d58d10087c808 100644 --- a/mypy/test/testcmdline.py +++ b/mypy/test/testcmdline.py @@ -46,7 +46,7 @@ def test_python_cmdline(testcase: DataDrivenTestCase, step: int) -> None: program_path = os.path.join(test_temp_dir, program) with open(program_path, 'w', encoding='utf8') as file: for s in testcase.input: - file.write('{}\n'.format(s)) + file.write(f'{s}\n') args = parse_args(testcase.input[0]) custom_cwd = parse_cwd(testcase.input[1]) if len(testcase.input) > 1 else None args.append('--show-traceback') @@ -94,7 +94,7 @@ def test_python_cmdline(testcase: DataDrivenTestCase, step: int) -> None: out = normalize_error_messages(err + out) obvious_result = 1 if out else 0 if obvious_result != result: - out.append('== Return code: {}'.format(result)) + out.append(f'== Return code: {result}') expected_out = testcase.output if step == 1 else testcase.output2[step] # Strip "tmp/" out of the test so that # E: works... expected_out = [s.replace("tmp" + os.sep, "") for s in expected_out] diff --git a/mypy/test/testdeps.py b/mypy/test/testdeps.py index 0b6f4958db752..d3d184be7f017 100644 --- a/mypy/test/testdeps.py +++ b/mypy/test/testdeps.py @@ -67,7 +67,7 @@ def run_case(self, testcase: DataDrivenTestCase) -> None: if source.startswith((' Li def get_suggest(self, program_text: str, incremental_step: int) -> List[Tuple[str, str]]: step_bit = '1?' if incremental_step == 1 else str(incremental_step) - regex = '# suggest{}: (--[a-zA-Z0-9_\\-./=?^ ]+ )*([a-zA-Z0-9_.:/?^ ]+)$'.format(step_bit) + regex = f'# suggest{step_bit}: (--[a-zA-Z0-9_\\-./=?^ ]+ )*([a-zA-Z0-9_.:/?^ ]+)$' m = re.findall(regex, program_text, flags=re.MULTILINE) return m diff --git a/mypy/test/testgraph.py b/mypy/test/testgraph.py index d713828ca44c1..7d32db2b1c1c4 100644 --- a/mypy/test/testgraph.py +++ b/mypy/test/testgraph.py @@ -29,7 +29,7 @@ def test_topsort(self) -> None: def test_scc(self) -> None: vertices = {"A", "B", "C", "D"} edges: Dict[str, List[str]] = {"A": ["B", "C"], "B": ["C"], "C": ["B", "D"], "D": []} - sccs = set(frozenset(x) for x in strongly_connected_components(vertices, edges)) + sccs = {frozenset(x) for x in strongly_connected_components(vertices, edges)} assert_equal(sccs, {frozenset({'A'}), frozenset({'B', 'C'}), diff --git a/mypy/test/testmerge.py b/mypy/test/testmerge.py index 92562d10134d3..2e2f6b67d34a7 100644 --- a/mypy/test/testmerge.py +++ b/mypy/test/testmerge.py @@ -164,11 +164,11 @@ def dump_symbol_tables(self, modules: Dict[str, MypyFile]) -> List[str]: return a def dump_symbol_table(self, module_id: str, symtable: SymbolTable) -> List[str]: - a = ['{}:'.format(module_id)] + a = [f'{module_id}:'] for name in sorted(symtable): if name.startswith('__'): continue - a.append(' {}: {}'.format(name, self.format_symbol_table_node(symtable[name]))) + a.append(f' {name}: {self.format_symbol_table_node(symtable[name])}') return a def format_symbol_table_node(self, node: SymbolTableNode) -> str: @@ -180,11 +180,11 @@ def format_symbol_table_node(self, node: SymbolTableNode) -> str: s = '{}<{}>'.format(str(type(node.node).__name__), self.id_mapper.id(node.node)) else: - s = '? ({})'.format(type(node.node)) + s = f'? ({type(node.node)})' if (isinstance(node.node, Var) and node.node.type and not node.node.fullname.startswith('typing.')): typestr = self.format_type(node.node.type) - s += '({})'.format(typestr) + s += f'({typestr})' return s def dump_typeinfos(self, modules: Dict[str, MypyFile]) -> List[str]: @@ -226,7 +226,7 @@ def dump_types(self, manager: FineGrainedBuildManager) -> List[str]: for node in get_subexpressions(tree) if node in all_types} if type_map: - a.append('## {}'.format(module_id)) + a.append(f'## {module_id}') for expr in sorted(type_map, key=lambda n: (n.line, short_type(n), str(n) + str(type_map[n]))): typ = type_map[expr] diff --git a/mypy/test/testpep561.py b/mypy/test/testpep561.py index d30d94c49beec..a49c7e8e58746 100644 --- a/mypy/test/testpep561.py +++ b/mypy/test/testpep561.py @@ -43,7 +43,7 @@ def virtualenv( proc = subprocess.run([sys.executable, '-m', 'virtualenv', - '-p{}'.format(python_executable), + f'-p{python_executable}', venv_dir], cwd=os.getcwd(), stdout=PIPE, stderr=PIPE) if proc.returncode != 0: err = proc.stdout.decode('utf-8') + proc.stderr.decode('utf-8') @@ -118,12 +118,12 @@ def test_pep561(testcase: DataDrivenTestCase) -> None: program = testcase.name + '.py' with open(program, 'w', encoding='utf-8') as f: for s in testcase.input: - f.write('{}\n'.format(s)) + f.write(f'{s}\n') cmd_line.append(program) cmd_line.extend(['--no-error-summary']) if python_executable != sys.executable: - cmd_line.append('--python-executable={}'.format(python_executable)) + cmd_line.append(f'--python-executable={python_executable}') steps = testcase.find_steps() if steps != [[]]: @@ -144,7 +144,7 @@ def test_pep561(testcase: DataDrivenTestCase) -> None: # Normalize paths so that the output is the same on Windows and Linux/macOS. line = line.replace(test_temp_dir + os.sep, test_temp_dir + '/') output.append(line.rstrip("\r\n")) - iter_count = '' if i == 0 else ' on iteration {}'.format(i + 1) + iter_count = '' if i == 0 else f' on iteration {i + 1}' expected = testcase.output if i == 0 else testcase.output2.get(i + 1, []) assert_string_arrays_equal(expected, output, @@ -189,14 +189,14 @@ def test_mypy_path_is_respected() -> None: mypy_config_path = os.path.join(temp_dir, 'mypy.ini') with open(mypy_config_path, 'w') as mypy_file: mypy_file.write('[mypy]\n') - mypy_file.write('mypy_path = ./{}\n'.format(packages)) + mypy_file.write(f'mypy_path = ./{packages}\n') with virtualenv() as venv: venv_dir, python_executable = venv cmd_line_args = [] if python_executable != sys.executable: - cmd_line_args.append('--python-executable={}'.format(python_executable)) + cmd_line_args.append(f'--python-executable={python_executable}') cmd_line_args.extend(['--config-file', mypy_config_path, '--package', pkg_name]) diff --git a/mypy/test/testpythoneval.py b/mypy/test/testpythoneval.py index 61e6d7fb839f0..8002b7410ee8d 100644 --- a/mypy/test/testpythoneval.py +++ b/mypy/test/testpythoneval.py @@ -82,8 +82,8 @@ def test_python_evaluation(testcase: DataDrivenTestCase, cache_dir: str) -> None mypy_cmdline.append(program_path) with open(program_path, 'w', encoding='utf8') as file: for s in testcase.input: - file.write('{}\n'.format(s)) - mypy_cmdline.append('--cache-dir={}'.format(cache_dir)) + file.write(f'{s}\n') + mypy_cmdline.append(f'--cache-dir={cache_dir}') output = [] # Type check the program. out, err, returncode = api.run(mypy_cmdline) diff --git a/mypy/test/testsemanal.py b/mypy/test/testsemanal.py index cbe0fb230d7a0..a58dc4a3960a0 100644 --- a/mypy/test/testsemanal.py +++ b/mypy/test/testsemanal.py @@ -126,7 +126,7 @@ def test_semanal_error(testcase: DataDrivenTestCase) -> None: options=get_semanal_options(src, testcase), alt_lib_path=test_temp_dir) a = res.errors - assert a, 'No errors reported in {}, line {}'.format(testcase.file, testcase.line) + assert a, f'No errors reported in {testcase.file}, line {testcase.line}' except CompileError as e: # Verify that there was a compile error and that the error messages # are equivalent. @@ -135,7 +135,7 @@ def test_semanal_error(testcase: DataDrivenTestCase) -> None: a = normalize_error_messages(a) assert_string_arrays_equal( testcase.output, a, - 'Invalid compiler output ({}, line {})'.format(testcase.file, testcase.line)) + f'Invalid compiler output ({testcase.file}, line {testcase.line})') # SymbolNode table export test cases @@ -158,7 +158,7 @@ def run_case(self, testcase: DataDrivenTestCase) -> None: raise CompileError(a) for f in sorted(result.files.keys()): if f not in ('builtins', 'typing', 'abc'): - a.append('{}:'.format(f)) + a.append(f'{f}:') for s in str(result.files[f].names).split('\n'): a.append(' ' + s) except CompileError as e: @@ -212,6 +212,6 @@ def __str__(self) -> str: not x.startswith('typing.') and not x.startswith('abc.')): ti = ('\n' + ' ').join(str(y).split('\n')) - a.append(' {} : {}'.format(x, ti)) + a.append(f' {x} : {ti}') a[-1] += ')' return '\n'.join(a) diff --git a/mypy/test/teststubgen.py b/mypy/test/teststubgen.py index 625ec3f30685f..97e3d98597cb4 100644 --- a/mypy/test/teststubgen.py +++ b/mypy/test/teststubgen.py @@ -627,7 +627,7 @@ def add_file(self, path: str, result: List[str], header: bool) -> None: result.append('<%s was not generated>' % path.replace('\\', '/')) return if header: - result.append('# {}'.format(path[4:])) + result.append(f'# {path[4:]}') with open(path, encoding='utf8') as file: result.extend(file.read().splitlines()) diff --git a/mypy/test/teststubtest.py b/mypy/test/teststubtest.py index 2983c23d51500..a17edbea24aab 100644 --- a/mypy/test/teststubtest.py +++ b/mypy/test/teststubtest.py @@ -103,14 +103,14 @@ def run_stubtest( f.write(stubtest_builtins_stub) with open("typing.pyi", "w") as f: f.write(stubtest_typing_stub) - with open("{}.pyi".format(TEST_MODULE_NAME), "w") as f: + with open(f"{TEST_MODULE_NAME}.pyi", "w") as f: f.write(stub) - with open("{}.py".format(TEST_MODULE_NAME), "w") as f: + with open(f"{TEST_MODULE_NAME}.py", "w") as f: f.write(runtime) if config_file: - with open("{}_config.ini".format(TEST_MODULE_NAME), "w") as f: + with open(f"{TEST_MODULE_NAME}_config.ini", "w") as f: f.write(config_file) - options = options + ["--mypy-config-file", "{}_config.ini".format(TEST_MODULE_NAME)] + options = options + ["--mypy-config-file", f"{TEST_MODULE_NAME}_config.ini"] output = io.StringIO() with contextlib.redirect_stdout(output): test_stubs( @@ -829,17 +829,16 @@ def test_dunders(self) -> Iterator[Case]: runtime="class B:\n def __call__(self, c, dx): pass", error="B.__call__", ) - if sys.version_info >= (3, 6): - yield Case( - stub=( - "class C:\n" - " def __init_subclass__(\n" - " cls, e: int = ..., **kwargs: int\n" - " ) -> None: ...\n" - ), - runtime="class C:\n def __init_subclass__(cls, e=1, **kwargs): pass", - error=None, - ) + yield Case( + stub=( + "class C:\n" + " def __init_subclass__(\n" + " cls, e: int = ..., **kwargs: int\n" + " ) -> None: ...\n" + ), + runtime="class C:\n def __init_subclass__(cls, e=1, **kwargs): pass", + error=None, + ) if sys.version_info >= (3, 9): yield Case( stub="class D:\n def __class_getitem__(cls, type: type) -> type: ...", @@ -1072,7 +1071,7 @@ def test_allowlist(self) -> None: allowlist = tempfile.NamedTemporaryFile(mode="w+", delete=False) try: with allowlist: - allowlist.write("{}.bad # comment\n# comment".format(TEST_MODULE_NAME)) + allowlist.write(f"{TEST_MODULE_NAME}.bad # comment\n# comment") output = run_stubtest( stub="def bad(number: int, text: str) -> None: ...", @@ -1083,7 +1082,7 @@ def test_allowlist(self) -> None: # test unused entry detection output = run_stubtest(stub="", runtime="", options=["--allowlist", allowlist.name]) - assert output == "note: unused allowlist entry {}.bad\n".format(TEST_MODULE_NAME) + assert output == f"note: unused allowlist entry {TEST_MODULE_NAME}.bad\n" output = run_stubtest( stub="", @@ -1094,7 +1093,7 @@ def test_allowlist(self) -> None: # test regex matching with open(allowlist.name, mode="w+") as f: - f.write("{}.b.*\n".format(TEST_MODULE_NAME)) + f.write(f"{TEST_MODULE_NAME}.b.*\n") f.write("(unused_missing)?\n") f.write("unused.*\n") diff --git a/mypy/test/testsubtypes.py b/mypy/test/testsubtypes.py index 5776d67a51846..3bfa3e174cfd0 100644 --- a/mypy/test/testsubtypes.py +++ b/mypy/test/testsubtypes.py @@ -188,10 +188,10 @@ def test_type_callable_subtyping(self) -> None: # * generic function types def assert_subtype(self, s: Type, t: Type) -> None: - assert is_subtype(s, t), '{} not subtype of {}'.format(s, t) + assert is_subtype(s, t), f'{s} not subtype of {t}' def assert_not_subtype(self, s: Type, t: Type) -> None: - assert not is_subtype(s, t), '{} subtype of {}'.format(s, t) + assert not is_subtype(s, t), f'{s} subtype of {t}' def assert_strict_subtype(self, s: Type, t: Type) -> None: self.assert_subtype(s, t) diff --git a/mypy/test/testtypegen.py b/mypy/test/testtypegen.py index a10035a8eab58..c652b38ba6fef 100644 --- a/mypy/test/testtypegen.py +++ b/mypy/test/testtypegen.py @@ -63,7 +63,7 @@ def run_case(self, testcase: DataDrivenTestCase) -> None: str(n) + str(map[n]))): ts = str(map[key]).replace('*', '') # Remove erased tags ts = ts.replace('__main__.', '') - a.append('{}({}) : {}'.format(short_type(key), key.line, ts)) + a.append(f'{short_type(key)}({key.line}) : {ts}') except CompileError as e: a = e.messages assert_string_arrays_equal( diff --git a/mypy/test/testtypes.py b/mypy/test/testtypes.py index 7458dfa9c6bf3..08469a60aba7e 100644 --- a/mypy/test/testtypes.py +++ b/mypy/test/testtypes.py @@ -866,9 +866,9 @@ def assert_simple_join(self, s: Type, t: Type, join: Type) -> None: actual = str(result) expected = str(join) assert_equal(actual, expected, - 'join({}, {}) == {{}} ({{}} expected)'.format(s, t)) - assert is_subtype(s, result), '{} not subtype of {}'.format(s, result) - assert is_subtype(t, result), '{} not subtype of {}'.format(t, result) + f'join({s}, {t}) == {{}} ({{}} expected)') + assert is_subtype(s, result), f'{s} not subtype of {result}' + assert is_subtype(t, result), f'{t} not subtype of {result}' def tuple(self, *a: Type) -> TupleType: return TupleType(list(a), self.fx.std_tuple) @@ -1081,9 +1081,9 @@ def assert_simple_meet(self, s: Type, t: Type, meet: Type) -> None: actual = str(result) expected = str(meet) assert_equal(actual, expected, - 'meet({}, {}) == {{}} ({{}} expected)'.format(s, t)) - assert is_subtype(result, s), '{} not subtype of {}'.format(result, s) - assert is_subtype(result, t), '{} not subtype of {}'.format(result, t) + f'meet({s}, {t}) == {{}} ({{}} expected)') + assert is_subtype(result, s), f'{result} not subtype of {s}' + assert is_subtype(result, t), f'{result} not subtype of {t}' def tuple(self, *a: Type) -> TupleType: return TupleType(list(a), self.fx.std_tuple) @@ -1132,14 +1132,14 @@ def assert_not_same(self, s: Type, t: Type, strict: bool = True) -> None: def assert_simple_is_same(self, s: Type, t: Type, expected: bool, strict: bool) -> None: actual = is_same_type(s, t) assert_equal(actual, expected, - 'is_same_type({}, {}) is {{}} ({{}} expected)'.format(s, t)) + f'is_same_type({s}, {t}) is {{}} ({{}} expected)') if strict: actual2 = (s == t) assert_equal(actual2, expected, - '({} == {}) is {{}} ({{}} expected)'.format(s, t)) + f'({s} == {t}) is {{}} ({{}} expected)') assert_equal(hash(s) == hash(t), expected, - '(hash({}) == hash({}) is {{}} ({{}} expected)'.format(s, t)) + f'(hash({s}) == hash({t}) is {{}} ({{}} expected)') class RemoveLastKnownValueSuite(Suite): From 57e57fa3e8281b0906daf0e0b2e5ee23e19d32bf Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sun, 1 May 2022 14:31:43 -0600 Subject: [PATCH 268/377] misc: run pyupgrade (#12709) Re-attempt of #10741 Ran: `pyupgrade --py36-plus $(fd -e py) --keep-runtime-typing` I mostly only needed to change things where NamedTuple comments got dropped. Co-authored-by: hauntsaninja <> --- misc/actions_stubs.py | 12 +++++----- misc/analyze_cache.py | 14 ++++++------ misc/apply-cache-diff.py | 2 +- misc/fix_annotate.py | 3 +-- misc/incremental_checker.py | 44 ++++++++++++++++++------------------- misc/perf_checker.py | 8 +++---- misc/sync-typeshed.py | 2 +- misc/test_case_to_actual.py | 2 +- misc/touch_checker.py | 32 +++++++++++++-------------- misc/variadics.py | 10 ++++----- runtests.py | 4 ++-- scripts/find_type.py | 2 +- setup.py | 2 +- 13 files changed, 68 insertions(+), 69 deletions(-) diff --git a/misc/actions_stubs.py b/misc/actions_stubs.py index 978af7187ffe3..0d52a882463d8 100644 --- a/misc/actions_stubs.py +++ b/misc/actions_stubs.py @@ -15,15 +15,15 @@ def apply_all(func: Any, directory: str, extension: str, to_extension: str='', exclude: Tuple[str]=('',), recursive: bool=True, debug: bool=False) -> None: excluded = [x+extension for x in exclude] if exclude else [] - for p, d, files in os.walk(os.path.join(base_path,directory)): + for p, d, files in os.walk(os.path.join(base_path, directory)): for f in files: - if "{}".format(f) in excluded: + if f in excluded: continue - inner_path = os.path.join(p,f) + inner_path = os.path.join(p, f) if not inner_path.endswith(extension): continue if to_extension: - new_path = "{}{}".format(inner_path[:-len(extension)],to_extension) + new_path = f"{inner_path[:-len(extension)]}{to_extension}" func(inner_path,new_path) else: func(inner_path) @@ -91,9 +91,9 @@ def main(action: str, directory: str, extension: str, to_extension: str, rec = "[Recursively] " if not_recursive else '' if not extension.startswith('.'): - extension = ".{}".format(extension) + extension = f".{extension}" if not to_extension.startswith('.'): - to_extension = ".{}".format(to_extension) + to_extension = f".{to_extension}" if directory.endswith('/'): directory = directory[:-1] if action == 'cp': diff --git a/misc/analyze_cache.py b/misc/analyze_cache.py index 334526a93742b..5f2048b5c11cb 100644 --- a/misc/analyze_cache.py +++ b/misc/analyze_cache.py @@ -37,10 +37,10 @@ def extract(chunks: Iterable[JsonDict]) -> Iterable[JsonDict]: def load_json(data_path: str, meta_path: str) -> CacheData: - with open(data_path, 'r') as ds: + with open(data_path) as ds: data_json = json.load(ds) - with open(meta_path, 'r') as ms: + with open(meta_path) as ms: meta_json = json.load(ms) data_size = os.path.getsize(data_path) @@ -66,7 +66,7 @@ def pluck(name: str, chunks: Iterable[JsonDict]) -> Iterable[JsonDict]: def report_counter(counter: Counter, amount: Optional[int] = None) -> None: for name, count in counter.most_common(amount): - print(' {: <8} {}'.format(count, name)) + print(f' {count: <8} {name}') print() @@ -138,7 +138,7 @@ def main() -> None: class_chunks = list(extract_classes(json_chunks)) total_size = sum(chunk.total_size for chunk in json_chunks) - print("Total cache size: {:.3f} megabytes".format(total_size / (1024 * 1024))) + print(f"Total cache size: {total_size / (1024 * 1024):.3f} megabytes") print() class_name_counter = Counter(chunk[".class"] for chunk in class_chunks) @@ -154,15 +154,15 @@ def main() -> None: build = chunk break original = json.dumps(build.data, sort_keys=True) - print("Size of build.data.json, in kilobytes: {:.3f}".format(len(original) / 1024)) + print(f"Size of build.data.json, in kilobytes: {len(original) / 1024:.3f}") build.data = compress(build.data) compressed = json.dumps(build.data, sort_keys=True) - print("Size of compressed build.data.json, in kilobytes: {:.3f}".format(len(compressed) / 1024)) + print(f"Size of compressed build.data.json, in kilobytes: {len(compressed) / 1024:.3f}") build.data = decompress(build.data) decompressed = json.dumps(build.data, sort_keys=True) - print("Size of decompressed build.data.json, in kilobytes: {:.3f}".format(len(decompressed) / 1024)) + print(f"Size of decompressed build.data.json, in kilobytes: {len(decompressed) / 1024:.3f}") print("Lossless conversion back", original == decompressed) diff --git a/misc/apply-cache-diff.py b/misc/apply-cache-diff.py index 543ece9981ab0..a9e13a1af9a51 100644 --- a/misc/apply-cache-diff.py +++ b/misc/apply-cache-diff.py @@ -24,7 +24,7 @@ def make_cache(input_dir: str, sqlite: bool) -> MetadataStore: def apply_diff(cache_dir: str, diff_file: str, sqlite: bool = False) -> None: cache = make_cache(cache_dir, sqlite) - with open(diff_file, "r") as f: + with open(diff_file) as f: diff = json.load(f) old_deps = json.loads(cache.read("@deps.meta.json")) diff --git a/misc/fix_annotate.py b/misc/fix_annotate.py index 0b552bf51d7a1..4c34e03817036 100644 --- a/misc/fix_annotate.py +++ b/misc/fix_annotate.py @@ -27,7 +27,6 @@ def foo(self, bar, baz=12): Finally, it knows that __init__() is supposed to return None. """ -from __future__ import print_function import os import re @@ -90,7 +89,7 @@ def transform(self, node, results): # Insert '# type: {annot}' comment. # For reference, see lib2to3/fixes/fix_tuple_params.py in stdlib. if len(children) >= 2 and children[1].type == token.INDENT: - children[1].prefix = '%s# type: %s\n%s' % (children[1].value, annot, children[1].prefix) + children[1].prefix = '{}# type: {}\n{}'.format(children[1].value, annot, children[1].prefix) children[1].changed() if FixAnnotate.counter is not None: FixAnnotate.counter -= 1 diff --git a/misc/incremental_checker.py b/misc/incremental_checker.py index 0c659bee7023b..8eea983ff5994 100755 --- a/misc/incremental_checker.py +++ b/misc/incremental_checker.py @@ -92,10 +92,10 @@ def ensure_environment_is_ready(mypy_path: str, temp_repo_path: str, mypy_cache_ def initialize_repo(repo_url: str, temp_repo_path: str, branch: str) -> None: - print("Cloning repo {0} to {1}".format(repo_url, temp_repo_path)) + print(f"Cloning repo {repo_url} to {temp_repo_path}") execute(["git", "clone", repo_url, temp_repo_path]) if branch is not None: - print("Checking out branch {}".format(branch)) + print(f"Checking out branch {branch}") execute(["git", "-C", temp_repo_path, "checkout", branch]) @@ -110,13 +110,13 @@ def get_commits(repo_folder_path: str, commit_range: str) -> List[Tuple[str, str def get_commits_starting_at(repo_folder_path: str, start_commit: str) -> List[Tuple[str, str]]: - print("Fetching commits starting at {0}".format(start_commit)) - return get_commits(repo_folder_path, '{0}^..HEAD'.format(start_commit)) + print(f"Fetching commits starting at {start_commit}") + return get_commits(repo_folder_path, f'{start_commit}^..HEAD') def get_nth_commit(repo_folder_path: str, n: int) -> Tuple[str, str]: - print("Fetching last {} commits (or all, if there are fewer commits than n)".format(n)) - return get_commits(repo_folder_path, '-{}'.format(n))[0] + print(f"Fetching last {n} commits (or all, if there are fewer commits than n)") + return get_commits(repo_folder_path, f'-{n}')[0] def run_mypy(target_file_path: Optional[str], @@ -187,7 +187,7 @@ def stop_daemon() -> None: def load_cache(incremental_cache_path: str = CACHE_PATH) -> JsonDict: if os.path.exists(incremental_cache_path): - with open(incremental_cache_path, 'r') as stream: + with open(incremental_cache_path) as stream: return json.load(stream) else: return {} @@ -213,17 +213,17 @@ def set_expected(commits: List[Tuple[str, str]], skip evaluating that commit and move on to the next.""" for commit_id, message in commits: if commit_id in cache: - print('Skipping commit (already cached): {0}: "{1}"'.format(commit_id, message)) + print(f'Skipping commit (already cached): {commit_id}: "{message}"') else: - print('Caching expected output for commit {0}: "{1}"'.format(commit_id, message)) + print(f'Caching expected output for commit {commit_id}: "{message}"') execute(["git", "-C", temp_repo_path, "checkout", commit_id]) runtime, output, stats = run_mypy(target_file_path, mypy_cache_path, mypy_script, incremental=False) cache[commit_id] = {'runtime': runtime, 'output': output} if output == "": - print(" Clean output ({:.3f} sec)".format(runtime)) + print(f" Clean output ({runtime:.3f} sec)") else: - print(" Output ({:.3f} sec)".format(runtime)) + print(f" Output ({runtime:.3f} sec)") print_offset(output, 8) print() @@ -246,7 +246,7 @@ def test_incremental(commits: List[Tuple[str, str]], commits = [commits[0]] + commits overall_stats = {} # type: Dict[str, float] for commit_id, message in commits: - print('Now testing commit {0}: "{1}"'.format(commit_id, message)) + print(f'Now testing commit {commit_id}: "{message}"') execute(["git", "-C", temp_repo_path, "checkout", commit_id]) runtime, output, stats = run_mypy(target_file_path, mypy_cache_path, mypy_script, incremental=True, daemon=daemon) @@ -255,18 +255,18 @@ def test_incremental(commits: List[Tuple[str, str]], expected_output = cache[commit_id]['output'] # type: str if output != expected_output: print(" Output does not match expected result!") - print(" Expected output ({:.3f} sec):".format(expected_runtime)) + print(f" Expected output ({expected_runtime:.3f} sec):") print_offset(expected_output, 8) - print(" Actual output: ({:.3f} sec):".format(runtime)) + print(f" Actual output: ({runtime:.3f} sec):") print_offset(output, 8) if exit_on_error: break else: print(" Output matches expected result!") - print(" Incremental: {:.3f} sec".format(runtime)) - print(" Original: {:.3f} sec".format(expected_runtime)) + print(f" Incremental: {runtime:.3f} sec") + print(f" Original: {expected_runtime:.3f} sec") if relevant_stats: - print(" Stats: {}".format(relevant_stats)) + print(f" Stats: {relevant_stats}") if overall_stats: print("Overall stats:", overall_stats) @@ -324,7 +324,7 @@ def test_repo(target_repo_url: str, temp_repo_path: str, elif range_type == "commit": start_commit = range_start else: - raise RuntimeError("Invalid option: {}".format(range_type)) + raise RuntimeError(f"Invalid option: {range_type}") commits = get_commits_starting_at(temp_repo_path, start_commit) if params.limit: commits = commits[:params.limit] @@ -419,10 +419,10 @@ def main() -> None: # The path to store the mypy incremental mode cache data mypy_cache_path = os.path.abspath(os.path.join(mypy_path, "misc", ".mypy_cache")) - print("Assuming mypy is located at {0}".format(mypy_path)) - print("Temp repo will be cloned at {0}".format(temp_repo_path)) - print("Testing file/dir located at {0}".format(target_file_path)) - print("Using cache data located at {0}".format(incremental_cache_path)) + print(f"Assuming mypy is located at {mypy_path}") + print(f"Temp repo will be cloned at {temp_repo_path}") + print(f"Testing file/dir located at {target_file_path}") + print(f"Using cache data located at {incremental_cache_path}") print() test_repo(params.repo_url, temp_repo_path, target_file_path, diff --git a/misc/perf_checker.py b/misc/perf_checker.py index e55f8ccd38fee..38a80c1481879 100644 --- a/misc/perf_checker.py +++ b/misc/perf_checker.py @@ -58,10 +58,10 @@ def trial(num_trials: int, command: Command) -> List[float]: def report(name: str, times: List[float]) -> None: - print("{}:".format(name)) - print(" Times: {}".format(times)) - print(" Mean: {}".format(statistics.mean(times))) - print(" Stdev: {}".format(statistics.stdev(times))) + print(f"{name}:") + print(f" Times: {times}") + print(f" Mean: {statistics.mean(times)}") + print(f" Stdev: {statistics.stdev(times)}") print() diff --git a/misc/sync-typeshed.py b/misc/sync-typeshed.py index 93cbd951e0f69..8f4bba8487b32 100644 --- a/misc/sync-typeshed.py +++ b/misc/sync-typeshed.py @@ -77,7 +77,7 @@ def main() -> None: if not args.typeshed_dir: # Clone typeshed repo if no directory given. with tempfile.TemporaryDirectory() as tempdir: - print('Cloning typeshed in {}...'.format(tempdir)) + print(f'Cloning typeshed in {tempdir}...') subprocess.run(['git', 'clone', 'https://github.com/python/typeshed.git'], check=True, cwd=tempdir) repo = os.path.join(tempdir, 'typeshed') diff --git a/misc/test_case_to_actual.py b/misc/test_case_to_actual.py index 9a91bb1fa07d3..ccf631286802a 100644 --- a/misc/test_case_to_actual.py +++ b/misc/test_case_to_actual.py @@ -62,7 +62,7 @@ def main() -> None: return test_file_path, root_path = sys.argv[1], sys.argv[2] - with open(test_file_path, 'r') as stream: + with open(test_file_path) as stream: chunks = produce_chunks(iter(stream)) write_tree(root_path, chunks) diff --git a/misc/touch_checker.py b/misc/touch_checker.py index c44afe492255b..d12c2e8166145 100644 --- a/misc/touch_checker.py +++ b/misc/touch_checker.py @@ -67,7 +67,7 @@ def make_change_wrappers(filename: str) -> Tuple[Command, Command]: def setup() -> None: nonlocal copy - with open(filename, 'r') as stream: + with open(filename) as stream: copy = stream.read() with open(filename, 'a') as stream: stream.write('\n\nfoo = 3') @@ -102,48 +102,48 @@ def main() -> None: lambda: None, lambda: execute(["python3", "-m", "mypy", "mypy"]), lambda: None) - print("Baseline: {}".format(baseline)) + print(f"Baseline: {baseline}") cold = test( lambda: delete_folder(".mypy_cache"), lambda: execute(["python3", "-m", "mypy", "-i", "mypy"]), lambda: None) - print("Cold cache: {}".format(cold)) + print(f"Cold cache: {cold}") warm = test( lambda: None, lambda: execute(["python3", "-m", "mypy", "-i", "mypy"]), lambda: None) - print("Warm cache: {}".format(warm)) + print(f"Warm cache: {warm}") print() deltas = [] for filename in glob.iglob("mypy/**/*.py", recursive=True): - print("{} {}".format(verb, filename)) + print(f"{verb} {filename}") setup, teardown = make_wrappers(filename) delta = test( setup, lambda: execute(["python3", "-m", "mypy", "-i", "mypy"]), teardown) - print(" Time: {}".format(delta)) + print(f" Time: {delta}") deltas.append(delta) print() print("Initial:") - print(" Baseline: {}".format(baseline)) - print(" Cold cache: {}".format(cold)) - print(" Warm cache: {}".format(warm)) + print(f" Baseline: {baseline}") + print(f" Cold cache: {cold}") + print(f" Warm cache: {warm}") print() print("Aggregate:") - print(" Times: {}".format(deltas)) - print(" Mean: {}".format(statistics.mean(deltas))) - print(" Median: {}".format(statistics.median(deltas))) - print(" Stdev: {}".format(statistics.stdev(deltas))) - print(" Min: {}".format(min(deltas))) - print(" Max: {}".format(max(deltas))) - print(" Total: {}".format(sum(deltas))) + print(f" Times: {deltas}") + print(f" Mean: {statistics.mean(deltas)}") + print(f" Median: {statistics.median(deltas)}") + print(f" Stdev: {statistics.stdev(deltas)}") + print(f" Min: {min(deltas)}") + print(f" Max: {max(deltas)}") + print(f" Total: {sum(deltas)}") print() if __name__ == '__main__': diff --git a/misc/variadics.py b/misc/variadics.py index 920028853a4f4..3ffc2a9678292 100644 --- a/misc/variadics.py +++ b/misc/variadics.py @@ -8,8 +8,8 @@ def prelude(limit: int, bound: str) -> None: print('from typing import Callable, Iterable, Iterator, Tuple, TypeVar, overload') - print('Ts = TypeVar(\'Ts\', bound={bound})'.format(bound=bound)) - print('R = TypeVar(\'R\')') + print(f"Ts = TypeVar('Ts', bound={bound})") + print("R = TypeVar('R')") for i in range(LIMIT): print('T{i} = TypeVar(\'T{i}\', bound={bound})'.format(i=i+1, bound=bound)) @@ -19,8 +19,8 @@ def expand_template(template: str, limit: int = LIMIT) -> None: print() for i in range(lower, limit): - tvs = ', '.join('T{i}'.format(i=j+1) for j in range(i)) - args = ', '.join(arg_template.format(i=j+1, Ts='T{}'.format(j+1)) + tvs = ', '.join(f'T{j+1}' for j in range(i)) + args = ', '.join(arg_template.format(i=j+1, Ts=f'T{j+1}') for j in range(i)) print('@overload') s = template.format(Ts=tvs, argsTs=args) @@ -49,6 +49,6 @@ def main(): expand_template('def make_check({argsTs}) -> Callable[[{Ts}], bool]: ...') expand_template('def my_map(f: Callable[[{Ts}], R], {argsTs}) -> Iterator[R]: ...', 'arg{i}: Iterable[{Ts}]') - + main() diff --git a/runtests.py b/runtests.py index 62437e1ab0118..871a214ef0c1e 100755 --- a/runtests.py +++ b/runtests.py @@ -84,7 +84,7 @@ def run_cmd(name: str) -> int: status = 0 cmd = cmds[name] - print('run %s: %s' % (name, cmd)) + print(f'run {name}: {cmd}') proc = subprocess.run(cmd, stderr=subprocess.STDOUT) if proc.returncode: print('\nFAILED: %s' % name) @@ -105,7 +105,7 @@ def start_background_cmd(name: str) -> Popen: def wait_background_cmd(name: str, proc: Popen) -> int: output = proc.communicate()[0] status = proc.returncode - print('run %s: %s' % (name, cmds[name])) + print(f'run {name}: {cmds[name]}') if status: print(output.decode().rstrip()) print('\nFAILED: %s' % name) diff --git a/scripts/find_type.py b/scripts/find_type.py index f488fca9f0eef..757c2a40fd15c 100755 --- a/scripts/find_type.py +++ b/scripts/find_type.py @@ -66,7 +66,7 @@ def main(): start_col = int(start_col_str) end_line = int(end_line_str) end_col = int(end_col_str) - with open(filename, 'r') as f: + with open(filename) as f: lines = f.readlines() lines[end_line - 1] = update_line(lines[end_line - 1], REVEAL_TYPE_END, end_col) # insert after end_col lines[start_line - 1] = update_line(lines[start_line - 1], REVEAL_TYPE_START, start_col) diff --git a/setup.py b/setup.py index c2e46675a26b0..bba99fec8259a 100644 --- a/setup.py +++ b/setup.py @@ -58,7 +58,7 @@ def pin_version(self): path = os.path.join(self.build_lib, 'mypy') self.mkpath(path) with open(os.path.join(path, 'version.py'), 'w') as stream: - stream.write('__version__ = "{}"\n'.format(version)) + stream.write(f'__version__ = "{version}"\n') def run(self): self.execute(self.pin_version, ()) From 7a2ad43431c182cf01a4b9bf73a3bea8e3fac9aa Mon Sep 17 00:00:00 2001 From: Hugues Date: Sun, 1 May 2022 13:59:22 -0700 Subject: [PATCH 269/377] checkexpr: speedup typechecking of container literals with tuple entries (#12706) `fast_dict_type` and `fast_container_type` only allowed Instance but not Tuple of Instances which was mostly an oversight, as opposed to an intentional omission. For #9427 --- mypy/checkexpr.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index bd69c1427dce1..cea44c6c17db5 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -118,6 +118,16 @@ class TooManyUnions(Exception): """ +def allow_fast_container_literal(t: ProperType) -> bool: + return ( + isinstance(t, Instance) + or ( + isinstance(t, TupleType) + and all(allow_fast_container_literal(get_proper_type(it)) for it in t.items) + ) + ) + + def extract_refexpr_names(expr: RefExpr) -> Set[str]: """Recursively extracts all module references from a reference expression. @@ -3265,7 +3275,7 @@ def fast_container_type( Limitations: - no active type context - no star expressions - - the joined type of all entries must be an Instance type + - the joined type of all entries must be an Instance or Tuple type """ ctx = self.type_context[-1] if ctx: @@ -3277,7 +3287,7 @@ def fast_container_type( return None values.append(self.accept(item)) vt = join.join_type_list(values) - if not isinstance(vt, Instance): + if not allow_fast_container_literal(vt): return None return self.chk.named_generic_type(container_fullname, [vt]) @@ -3377,7 +3387,7 @@ def fast_dict_type(self, e: DictExpr) -> Optional[Type]: Limitations: - no active type context - only supported star expressions are other dict instances - - the joined types of all keys and values must be Instance types + - the joined types of all keys and values must be Instance or Tuple types """ ctx = self.type_context[-1] if ctx: @@ -3401,7 +3411,7 @@ def fast_dict_type(self, e: DictExpr) -> Optional[Type]: values.append(self.accept(value)) kt = join.join_type_list(keys) vt = join.join_type_list(values) - if not (isinstance(kt, Instance) and isinstance(vt, Instance)): + if not (allow_fast_container_literal(kt) and allow_fast_container_literal(vt)): return None if stargs and (stargs[0] != kt or stargs[1] != vt): return None From 9a2f729856de6d16c9b59432e6ef4d2790033d4d Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Sun, 1 May 2022 15:01:02 -0600 Subject: [PATCH 270/377] Fix missing NoReturn annotations and incorrect try placements (#12705) --- mypy/build.py | 4 ++-- mypy/dmypy/client.py | 3 ++- mypy/dmypy_server.py | 6 +++--- mypy/errors.py | 7 ++++--- mypy/main.py | 2 +- mypy/semanal.py | 2 ++ 6 files changed, 14 insertions(+), 10 deletions(-) diff --git a/mypy/build.py b/mypy/build.py index f084e632417ad..2eaabbe75411c 100644 --- a/mypy/build.py +++ b/mypy/build.py @@ -24,7 +24,7 @@ from typing import (AbstractSet, Any, Dict, Iterable, Iterator, List, Sequence, Mapping, NamedTuple, Optional, Set, Tuple, TypeVar, Union, Callable, TextIO) -from typing_extensions import ClassVar, Final, TYPE_CHECKING, TypeAlias as _TypeAlias +from typing_extensions import ClassVar, NoReturn, Final, TYPE_CHECKING, TypeAlias as _TypeAlias from mypy_extensions import TypedDict from mypy.nodes import MypyFile, ImportBase, Import, ImportFrom, ImportAll, SymbolTable @@ -398,7 +398,7 @@ def load_plugins_from_config( if line == -1: line = 1 # We need to pick some line number that doesn't look too confusing - def plugin_error(message: str) -> None: + def plugin_error(message: str) -> NoReturn: errors.report(line, 0, message) errors.raise_error(use_stdout=False) diff --git a/mypy/dmypy/client.py b/mypy/dmypy/client.py index 3629372d1a852..56ec804ad7a79 100644 --- a/mypy/dmypy/client.py +++ b/mypy/dmypy/client.py @@ -14,6 +14,7 @@ import traceback from typing import Any, Callable, Dict, Mapping, Optional, Tuple, List +from typing_extensions import NoReturn from mypy.dmypy_util import DEFAULT_STATUS_FILE, receive from mypy.ipc import IPCClient, IPCException @@ -161,7 +162,7 @@ def main(argv: List[str]) -> None: sys.exit(2) -def fail(msg: str) -> None: +def fail(msg: str) -> NoReturn: print(msg, file=sys.stderr) sys.exit(2) diff --git a/mypy/dmypy_server.py b/mypy/dmypy_server.py index a8a7dd82f665f..04e25091484e0 100644 --- a/mypy/dmypy_server.py +++ b/mypy/dmypy_server.py @@ -209,8 +209,8 @@ def _response_metadata(self) -> Dict[str, str]: def serve(self) -> None: """Serve requests, synchronously (no thread or fork).""" command = None + server = IPCServer(CONNECTION_NAME, self.timeout) try: - server = IPCServer(CONNECTION_NAME, self.timeout) with open(self.status_file, 'w') as f: json.dump({'pid': os.getpid(), 'connection_name': server.connection_name}, f) f.write('\n') # I like my JSON with a trailing newline @@ -298,11 +298,11 @@ def cmd_stop(self) -> Dict[str, object]: def cmd_run(self, version: str, args: Sequence[str], is_tty: bool, terminal_width: int) -> Dict[str, object]: """Check a list of files, triggering a restart if needed.""" + stderr = io.StringIO() + stdout = io.StringIO() try: # Process options can exit on improper arguments, so we need to catch that and # capture stderr so the client can report it - stderr = io.StringIO() - stdout = io.StringIO() with redirect_stderr(stderr): with redirect_stdout(stdout): sources, options = mypy.main.process_options( diff --git a/mypy/errors.py b/mypy/errors.py index 87a59e3ca9ed1..590b02865fb50 100644 --- a/mypy/errors.py +++ b/mypy/errors.py @@ -1,11 +1,12 @@ import os.path import sys import traceback + from mypy.backports import OrderedDict from collections import defaultdict from typing import Tuple, List, TypeVar, Set, Dict, Optional, TextIO, Callable, Union -from typing_extensions import Final, Literal +from typing_extensions import Final, Literal, NoReturn from mypy.scope import Scope from mypy.options import Options @@ -633,7 +634,7 @@ def is_errors_for_file(self, file: str) -> bool: """Are there any errors for the given file?""" return file in self.error_info_map - def raise_error(self, use_stdout: bool = True) -> None: + def raise_error(self, use_stdout: bool = True) -> NoReturn: """Raise a CompileError with the generated messages. Render the messages suitable for displaying. @@ -908,7 +909,7 @@ def report_internal_error(err: Exception, options: Options, stdout: Optional[TextIO] = None, stderr: Optional[TextIO] = None, - ) -> None: + ) -> NoReturn: """Report internal error and exit. This optionally starts pdb or shows a traceback. diff --git a/mypy/main.py b/mypy/main.py index 7c7a5993d5c5a..a126122c18ed6 100644 --- a/mypy/main.py +++ b/mypy/main.py @@ -1138,7 +1138,7 @@ def maybe_write_junit_xml(td: float, serious: bool, messages: List[str], options td, serious, messages, options.junit_xml, py_version, options.platform) -def fail(msg: str, stderr: TextIO, options: Options) -> None: +def fail(msg: str, stderr: TextIO, options: Options) -> NoReturn: """Fail with a serious error.""" stderr.write('%s\n' % msg) maybe_write_junit_xml(0.0, serious=True, messages=[msg], options=options) diff --git a/mypy/semanal.py b/mypy/semanal.py index 985d5217cc08a..8b01489589849 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4573,6 +4573,8 @@ def lookup_qualified(self, name: str, ctx: Context, assert isinstance(node.target, ProperType) if isinstance(node.target, Instance): nextsym = node.target.type.get(part) + else: + nextsym = None else: if isinstance(node, Var): typ = get_proper_type(node.type) From 3c46b818237aa8e0e06f33a74a752921346f5c5a Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sun, 1 May 2022 15:47:29 -0600 Subject: [PATCH 271/377] Mention no_type_check in docs (#12713) Co-authored by: @chrisbeardy --- docs/source/type_inference_and_annotations.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/source/type_inference_and_annotations.rst b/docs/source/type_inference_and_annotations.rst index 040961d40a401..47a29a6abf95c 100644 --- a/docs/source/type_inference_and_annotations.rst +++ b/docs/source/type_inference_and_annotations.rst @@ -251,3 +251,12 @@ Similarly, you can also ignore all mypy checks in a file, by adding a # This is a test file, skipping type checking in it. import unittest ... + +Finally, adding a ``@typing.no_type_check`` decorator to a class, method or +function has the effect of ignoring that class, method or function. + +.. code-block:: python + + @typing.no_type_check + def foo() -> str: + return 12345 # No error! From fc335cb16315964b923eb1927e3aad1516891c28 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sun, 1 May 2022 15:52:34 -0600 Subject: [PATCH 272/377] mypy: run pyupgrade (#12711) Re-attempt of #10741 Ran: `pyupgrade --py36-plus $(fd -e py) --keep-runtime-typing` I mostly only needed to change things where NamedTuple comments got dropped. Notably, I omitted changes to pyinfo.py --- mypy/binder.py | 2 +- mypy/build.py | 152 +++++++++++++-------------- mypy/checker.py | 69 ++++++------- mypy/checkexpr.py | 10 +- mypy/checkmember.py | 6 +- mypy/checkpattern.py | 13 +-- mypy/checkstrformat.py | 2 +- mypy/config_parser.py | 30 +++--- mypy/constraints.py | 6 +- mypy/dmypy_os.py | 2 +- mypy/dmypy_server.py | 16 +-- mypy/errorcodes.py | 2 +- mypy/errors.py | 34 +++--- mypy/expandtype.py | 2 +- mypy/fastparse.py | 12 +-- mypy/fastparse2.py | 8 +- mypy/find_sources.py | 4 +- mypy/fixup.py | 4 +- mypy/gclogger.py | 2 +- mypy/ipc.py | 22 ++-- mypy/join.py | 2 +- mypy/lookup.py | 8 +- mypy/main.py | 20 ++-- mypy/meet.py | 6 +- mypy/memprofile.py | 2 +- mypy/messages.py | 182 ++++++++++++++++----------------- mypy/metastore.py | 4 +- mypy/modulefinder.py | 28 ++--- mypy/mro.py | 4 +- mypy/nodes.py | 26 ++--- mypy/operators.py | 4 +- mypy/options.py | 2 +- mypy/plugin.py | 139 ++++++++++++------------- mypy/plugins/attrs.py | 4 +- mypy/plugins/common.py | 2 +- mypy/plugins/default.py | 12 +-- mypy/plugins/enums.py | 12 +-- mypy/plugins/functools.py | 4 +- mypy/plugins/singledispatch.py | 23 +++-- mypy/report.py | 13 ++- mypy/semanal.py | 54 +++++----- mypy/semanal_classprop.py | 8 +- mypy/semanal_enum.py | 4 +- mypy/semanal_namedtuple.py | 14 +-- mypy/semanal_shared.py | 2 +- mypy/semanal_typeargs.py | 4 +- mypy/semanal_typeddict.py | 6 +- mypy/server/astdiff.py | 8 +- mypy/server/deps.py | 12 +-- mypy/server/mergecheck.py | 7 +- mypy/server/objgraph.py | 3 +- mypy/server/trigger.py | 2 +- mypy/server/update.py | 24 +++-- mypy/strconv.py | 46 ++++----- mypy/stubdoc.py | 11 +- mypy/stubgen.py | 64 ++++++------ mypy/stubgenc.py | 20 ++-- mypy/stubtest.py | 54 +++++----- mypy/stubutil.py | 14 ++- mypy/subtypes.py | 4 +- mypy/suggestions.py | 40 ++++---- mypy/tvar_scope.py | 4 +- mypy/typeanal.py | 32 +++--- mypy/typeops.py | 2 +- mypy/types.py | 86 ++++++++-------- mypy/typestate.py | 2 +- 66 files changed, 709 insertions(+), 713 deletions(-) diff --git a/mypy/binder.py b/mypy/binder.py index 2f83ffb095fc2..1dffb55a54acf 100644 --- a/mypy/binder.py +++ b/mypy/binder.py @@ -189,7 +189,7 @@ def update_from_options(self, frames: List[Frame]) -> bool: frames = [f for f in frames if not f.unreachable] changed = False - keys = set(key for f in frames for key in f.types) + keys = {key for f in frames for key in f.types} for key in keys: current_value = self._get(key) diff --git a/mypy/build.py b/mypy/build.py index 2eaabbe75411c..107a291ad582c 100644 --- a/mypy/build.py +++ b/mypy/build.py @@ -299,30 +299,30 @@ def normpath(path: str, options: Options) -> str: return os.path.abspath(path) -CacheMeta = NamedTuple('CacheMeta', - [('id', str), - ('path', str), - ('mtime', int), - ('size', int), - ('hash', str), - ('dependencies', List[str]), # names of imported modules - ('data_mtime', int), # mtime of data_json - ('data_json', str), # path of .data.json - ('suppressed', List[str]), # dependencies that weren't imported - ('options', Optional[Dict[str, object]]), # build options - # dep_prios and dep_lines are in parallel with - # dependencies + suppressed. - ('dep_prios', List[int]), - ('dep_lines', List[int]), - ('interface_hash', str), # hash representing the public interface - ('version_id', str), # mypy version for cache invalidation - ('ignore_all', bool), # if errors were ignored - ('plugin_data', Any), # config data from plugins - ]) +class CacheMeta(NamedTuple): + id: str + path: str + mtime: int + size: int + hash: str + dependencies: List[str] # names of imported modules + data_mtime: int # mtime of data_json + data_json: str # path of .data.json + suppressed: List[str] # dependencies that weren't imported + options: Optional[Dict[str, object]] # build options + # dep_prios and dep_lines are in parallel with dependencies + suppressed + dep_prios: List[int] + dep_lines: List[int] + interface_hash: str # hash representing the public interface + version_id: str # mypy version for cache invalidation + ignore_all: bool # if errors were ignored + plugin_data: Any # config data from plugins + # NOTE: dependencies + suppressed == all reachable imports; # suppressed contains those reachable imports that were prevented by # silent mode or simply not found. + # Metadata for the fine-grained dependencies file associated with a module. FgDepMeta = TypedDict('FgDepMeta', {'path': str, 'mtime': int}) @@ -413,7 +413,7 @@ def plugin_error(message: str) -> NoReturn: # Plugin paths can be relative to the config file location. plugin_path = os.path.join(os.path.dirname(options.config_file), plugin_path) if not os.path.isfile(plugin_path): - plugin_error('Can\'t find plugin "{}"'.format(plugin_path)) + plugin_error(f'Can\'t find plugin "{plugin_path}"') # Use an absolute path to avoid populating the cache entry # for 'tmp' during tests, since it will be different in # different tests. @@ -423,14 +423,14 @@ def plugin_error(message: str) -> NoReturn: sys.path.insert(0, plugin_dir) elif re.search(r'[\\/]', plugin_path): fnam = os.path.basename(plugin_path) - plugin_error('Plugin "{}" does not have a .py extension'.format(fnam)) + plugin_error(f'Plugin "{fnam}" does not have a .py extension') else: module_name = plugin_path try: module = importlib.import_module(module_name) except Exception as exc: - plugin_error('Error importing plugin "{}": {}'.format(plugin_path, exc)) + plugin_error(f'Error importing plugin "{plugin_path}": {exc}') finally: if plugin_dir is not None: assert sys.path[0] == plugin_dir @@ -443,7 +443,7 @@ def plugin_error(message: str) -> NoReturn: try: plugin_type = getattr(module, func_name)(__version__) except Exception: - print('Error calling the plugin(version) entry point of {}\n'.format(plugin_path), + print(f'Error calling the plugin(version) entry point of {plugin_path}\n', file=stdout) raise # Propagate to display traceback @@ -459,7 +459,7 @@ def plugin_error(message: str) -> NoReturn: custom_plugins.append(plugin_type(options)) snapshot[module_name] = take_module_snapshot(module) except Exception: - print('Error constructing plugin instance of {}\n'.format(plugin_type.__name__), + print(f'Error constructing plugin instance of {plugin_type.__name__}\n', file=stdout) raise # Propagate to display traceback @@ -503,7 +503,7 @@ def take_module_snapshot(module: types.ModuleType) -> str: else: digest = 'unknown' ver = getattr(module, '__version__', 'none') - return '{}:{}'.format(ver, digest) + return f'{ver}:{digest}' def find_config_file_line_number(path: str, section: str, setting_name: str) -> int: @@ -520,7 +520,7 @@ def find_config_file_line_number(path: str, section: str, setting_name: str) -> if line.startswith('[') and line.endswith(']'): current_section = line[1:-1].strip() in_desired_section = (current_section == section) - elif in_desired_section and re.match(r'{}\s*='.format(setting_name), line): + elif in_desired_section and re.match(fr'{setting_name}\s*=', line): results.append(i + 1) if len(results) == 1: return results[0] @@ -918,7 +918,7 @@ def write_deps_cache(rdeps: Dict[str, Dict[str, Set[str]]], assert deps_json manager.log("Writing deps cache", deps_json) if not manager.metastore.write(deps_json, deps_to_json(rdeps[id])): - manager.log("Error writing fine-grained deps JSON file {}".format(deps_json)) + manager.log(f"Error writing fine-grained deps JSON file {deps_json}") error = True else: fg_deps_meta[id] = {'path': deps_json, 'mtime': manager.getmtime(deps_json)} @@ -938,7 +938,7 @@ def write_deps_cache(rdeps: Dict[str, Dict[str, Set[str]]], meta = {'snapshot': meta_snapshot, 'deps_meta': fg_deps_meta} if not metastore.write(DEPS_META_FILE, json.dumps(meta)): - manager.log("Error writing fine-grained deps meta JSON file {}".format(DEPS_META_FILE)) + manager.log(f"Error writing fine-grained deps meta JSON file {DEPS_META_FILE}") error = True if error: @@ -1037,14 +1037,14 @@ def read_quickstart_file(options: Options, # just ignore it. raw_quickstart: Dict[str, Any] = {} try: - with open(options.quickstart_file, "r") as f: + with open(options.quickstart_file) as f: raw_quickstart = json.load(f) quickstart = {} for file, (x, y, z) in raw_quickstart.items(): quickstart[file] = (x, y, z) except Exception as e: - print("Warning: Failed to load quickstart file: {}\n".format(str(e)), file=stdout) + print(f"Warning: Failed to load quickstart file: {str(e)}\n", file=stdout) return quickstart @@ -1095,7 +1095,7 @@ def _load_json_file(file: str, manager: BuildManager, t0 = time.time() try: data = manager.metastore.read(file) - except IOError: + except OSError: manager.log(log_error + file) return None manager.add_stats(metastore_read_time=time.time() - t0) @@ -1221,11 +1221,11 @@ def find_cache_meta(id: str, path: str, manager: BuildManager) -> Optional[Cache """ # TODO: May need to take more build options into account meta_json, data_json, _ = get_cache_names(id, path, manager.options) - manager.trace('Looking for {} at {}'.format(id, meta_json)) + manager.trace(f'Looking for {id} at {meta_json}') t0 = time.time() meta = _load_json_file(meta_json, manager, - log_success='Meta {} '.format(id), - log_error='Could not load cache for {}: '.format(id)) + log_success=f'Meta {id} ', + log_error=f'Could not load cache for {id}: ') t1 = time.time() if meta is None: return None @@ -1243,7 +1243,7 @@ def find_cache_meta(id: str, path: str, manager: BuildManager) -> Optional[Cache if (m.id != id or m.mtime is None or m.size is None or m.dependencies is None or m.data_mtime is None): - manager.log('Metadata abandoned for {}: attributes are missing'.format(id)) + manager.log(f'Metadata abandoned for {id}: attributes are missing') return None # Ignore cache if generated by an older mypy version. @@ -1251,7 +1251,7 @@ def find_cache_meta(id: str, path: str, manager: BuildManager) -> Optional[Cache or m.options is None or len(m.dependencies) + len(m.suppressed) != len(m.dep_prios) or len(m.dependencies) + len(m.suppressed) != len(m.dep_lines)): - manager.log('Metadata abandoned for {}: new attributes are missing'.format(id)) + manager.log(f'Metadata abandoned for {id}: new attributes are missing') return None # Ignore cache if (relevant) options aren't the same. @@ -1265,7 +1265,7 @@ def find_cache_meta(id: str, path: str, manager: BuildManager) -> Optional[Cache # Older versions included debug_cache, but it's silly to compare it. del cached_options['debug_cache'] if cached_options != current_options: - manager.log('Metadata abandoned for {}: options differ'.format(id)) + manager.log(f'Metadata abandoned for {id}: options differ') if manager.options.verbosity >= 2: for key in sorted(set(cached_options) | set(current_options)): if cached_options.get(key) != current_options.get(key): @@ -1275,7 +1275,7 @@ def find_cache_meta(id: str, path: str, manager: BuildManager) -> Optional[Cache if manager.old_plugins_snapshot and manager.plugins_snapshot: # Check if plugins are still the same. if manager.plugins_snapshot != manager.old_plugins_snapshot: - manager.log('Metadata abandoned for {}: plugins differ'.format(id)) + manager.log(f'Metadata abandoned for {id}: plugins differ') return None # So that plugins can return data with tuples in it without # things silently always invalidating modules, we round-trip @@ -1284,7 +1284,7 @@ def find_cache_meta(id: str, path: str, manager: BuildManager) -> Optional[Cache manager.plugin.report_config_data(ReportConfigContext(id, path, is_check=True)) )) if m.plugin_data != plugin_data: - manager.log('Metadata abandoned for {}: plugin configuration differs'.format(id)) + manager.log(f'Metadata abandoned for {id}: plugin configuration differs') return None manager.add_stats(fresh_metas=1) @@ -1306,11 +1306,11 @@ def validate_meta(meta: Optional[CacheMeta], id: str, path: Optional[str], # we use cache data file mtime to propagate information about changes in the dependencies. if meta is None: - manager.log('Metadata not found for {}'.format(id)) + manager.log(f'Metadata not found for {id}') return None if meta.ignore_all and not ignore_all: - manager.log('Metadata abandoned for {}: errors were previously ignored'.format(id)) + manager.log(f'Metadata abandoned for {id}: errors were previously ignored') return None t0 = time.time() @@ -1321,10 +1321,10 @@ def validate_meta(meta: Optional[CacheMeta], id: str, path: Optional[str], try: data_mtime = manager.getmtime(meta.data_json) except OSError: - manager.log('Metadata abandoned for {}: failed to stat data_json'.format(id)) + manager.log(f'Metadata abandoned for {id}: failed to stat data_json') return None if data_mtime != meta.data_mtime: - manager.log('Metadata abandoned for {}: data cache is modified'.format(id)) + manager.log(f'Metadata abandoned for {id}: data cache is modified') return None if bazel: @@ -1335,7 +1335,7 @@ def validate_meta(meta: Optional[CacheMeta], id: str, path: Optional[str], except OSError: return None if not (stat.S_ISREG(st.st_mode) or stat.S_ISDIR(st.st_mode)): - manager.log('Metadata abandoned for {}: file {} does not exist'.format(id, path)) + manager.log(f'Metadata abandoned for {id}: file {path} does not exist') return None manager.add_stats(validate_stat_time=time.time() - t0) @@ -1358,7 +1358,7 @@ def validate_meta(meta: Optional[CacheMeta], id: str, path: Optional[str], size = st.st_size # Bazel ensures the cache is valid. if size != meta.size and not bazel and not fine_grained_cache: - manager.log('Metadata abandoned for {}: file {} has different size'.format(id, path)) + manager.log(f'Metadata abandoned for {id}: file {path} has different size') return None # Bazel ensures the cache is valid. @@ -1371,7 +1371,7 @@ def validate_meta(meta: Optional[CacheMeta], id: str, path: Optional[str], # the file is up to date even though the mtime is wrong, without needing to hash it. qmtime, qsize, qhash = manager.quickstart_state[path] if int(qmtime) == mtime and qsize == size and qhash == meta.hash: - manager.log('Metadata fresh (by quickstart) for {}: file {}'.format(id, path)) + manager.log(f'Metadata fresh (by quickstart) for {id}: file {path}') meta = meta._replace(mtime=mtime, path=path) return meta @@ -1387,7 +1387,7 @@ def validate_meta(meta: Optional[CacheMeta], id: str, path: Optional[str], manager.add_stats(validate_hash_time=time.time() - t0) if source_hash != meta.hash: if fine_grained_cache: - manager.log('Using stale metadata for {}: file {}'.format(id, path)) + manager.log(f'Using stale metadata for {id}: file {path}') return meta else: manager.log('Metadata abandoned for {}: file {} has different hash'.format( @@ -1430,7 +1430,7 @@ def validate_meta(meta: Optional[CacheMeta], id: str, path: Optional[str], return meta # It's a match on (id, path, size, hash, mtime). - manager.log('Metadata fresh for {}: file {}'.format(id, path)) + manager.log(f'Metadata fresh for {id}: file {path}') return meta @@ -1504,7 +1504,7 @@ def write_cache(id: str, path: str, tree: MypyFile, try: st = manager.get_stat(path) except OSError as err: - manager.log("Cannot get stat for {}: {}".format(path, err)) + manager.log(f"Cannot get stat for {path}: {err}") # Remove apparently-invalid cache files. # (This is purely an optimization.) for filename in [data_json, meta_json]: @@ -1518,13 +1518,13 @@ def write_cache(id: str, path: str, tree: MypyFile, # Write data cache file, if applicable # Note that for Bazel we don't record the data file's mtime. if old_interface_hash == interface_hash: - manager.trace("Interface for {} is unchanged".format(id)) + manager.trace(f"Interface for {id} is unchanged") else: - manager.trace("Interface for {} has changed".format(id)) + manager.trace(f"Interface for {id} has changed") if not metastore.write(data_json, data_str): # Most likely the error is the replace() call # (see https://github.com/python/mypy/issues/3215). - manager.log("Error writing data JSON file {}".format(data_json)) + manager.log(f"Error writing data JSON file {data_json}") # Let's continue without writing the meta file. Analysis: # If the replace failed, we've changed nothing except left # behind an extraneous temporary file; if the replace @@ -1538,7 +1538,7 @@ def write_cache(id: str, path: str, tree: MypyFile, try: data_mtime = manager.getmtime(data_json) except OSError: - manager.log("Error in os.stat({!r}), skipping cache write".format(data_json)) + manager.log(f"Error in os.stat({data_json!r}), skipping cache write") return interface_hash, None mtime = 0 if bazel else int(st.st_mtime) @@ -1573,7 +1573,7 @@ def write_cache(id: str, path: str, tree: MypyFile, # Most likely the error is the replace() call # (see https://github.com/python/mypy/issues/3215). # The next run will simply find the cache entry out of date. - manager.log("Error writing meta JSON file {}".format(meta_json)) + manager.log(f"Error writing meta JSON file {meta_json}") return interface_hash, cache_meta_from_dict(meta, data_json) @@ -1597,7 +1597,7 @@ def delete_cache(id: str, path: str, manager: BuildManager) -> None: manager.metastore.remove(filename) except OSError as e: if e.errno != errno.ENOENT: - manager.log("Error deleting cache file {}: {}".format(filename, e.strerror)) + manager.log(f"Error deleting cache file {filename}: {e.strerror}") """Dependency manager. @@ -1908,7 +1908,7 @@ def __init__(self, # know about modules that have cache information and defer # handling new modules until the fine-grained update. if manager.use_fine_grained_cache(): - manager.log("Deferring module to fine-grained update %s (%s)" % (path, id)) + manager.log(f"Deferring module to fine-grained update {path} ({id})") raise ModuleNotFound # Parse the file (and then some) to get the dependencies. @@ -2036,9 +2036,9 @@ def parse_file(self) -> None: cached = self.id in manager.ast_cache modules = manager.modules if not cached: - manager.log("Parsing %s (%s)" % (self.xpath, self.id)) + manager.log(f"Parsing {self.xpath} ({self.id})") else: - manager.log("Using cached AST for %s (%s)" % (self.xpath, self.id)) + manager.log(f"Using cached AST for {self.xpath} ({self.id})") t0 = time_ref() @@ -2051,7 +2051,7 @@ def parse_file(self) -> None: source = decode_python_encoding(manager.fscache.read(path), manager.options.python_version) self.source_hash = manager.fscache.hash_digest(path) - except IOError as ioerr: + except OSError as ioerr: # ioerr.strerror differs for os.stat failures between Windows and # other systems, but os.strerror(ioerr.errno) does not, so we use that. # (We want the error messages to be platform-independent so that the @@ -2062,9 +2062,9 @@ def parse_file(self) -> None: module_with_blocker=self.id) from ioerr except (UnicodeDecodeError, DecodeError) as decodeerr: if self.path.endswith('.pyd'): - err = "mypy: stubgen does not support .pyd files: '{}'".format(self.path) + err = f"mypy: stubgen does not support .pyd files: '{self.path}'" else: - err = "mypy: can't decode file '{}': {}".format(self.path, str(decodeerr)) + err = f"mypy: can't decode file '{self.path}': {str(decodeerr)}" raise CompileError([err], module_with_blocker=self.id) from decodeerr elif self.path and self.manager.fscache.isdir(self.path): source = '' @@ -2333,16 +2333,16 @@ def write_cache(self) -> None: dep_lines = self.dependency_lines() assert self.source_hash is not None assert len(set(self.dependencies)) == len(self.dependencies), ( - "Duplicates in dependencies list for {} ({})".format(self.id, self.dependencies)) + f"Duplicates in dependencies list for {self.id} ({self.dependencies})") new_interface_hash, self.meta = write_cache( self.id, self.path, self.tree, list(self.dependencies), list(self.suppressed), dep_prios, dep_lines, self.interface_hash, self.source_hash, self.ignore_all, self.manager) if new_interface_hash == self.interface_hash: - self.manager.log("Cached module {} has same interface".format(self.id)) + self.manager.log(f"Cached module {self.id} has same interface") else: - self.manager.log("Cached module {} has changed interface".format(self.id)) + self.manager.log(f"Cached module {self.id} has changed interface") self.mark_interface_stale() self.interface_hash = new_interface_hash @@ -2466,11 +2466,11 @@ def find_module_and_diagnose(manager: BuildManager, pass elif follow_imports == 'silent': # Still import it, but silence non-blocker errors. - manager.log("Silencing %s (%s)" % (result, id)) + manager.log(f"Silencing {result} ({id})") elif follow_imports == 'skip' or follow_imports == 'error': # In 'error' mode, produce special error messages. if id not in manager.missing_modules: - manager.log("Skipping %s (%s)" % (result, id)) + manager.log(f"Skipping {result} ({id})") if follow_imports == 'error': if ancestor_for: skipping_ancestor(manager, id, result, ancestor_for) @@ -2489,7 +2489,7 @@ def find_module_and_diagnose(manager: BuildManager, and not options.use_builtins_fixtures and not options.custom_typeshed_dir): raise CompileError([ - 'mypy: "%s" shadows library module "%s"' % (os.path.relpath(result), id), + f'mypy: "{os.path.relpath(result)}" shadows library module "{id}"', 'note: A user-defined top-level module with name "%s" is not supported' % id ]) return (result, follow_imports) @@ -2632,7 +2632,7 @@ def skipping_module(manager: BuildManager, line: int, caller_state: Optional[Sta manager.errors.set_import_context(caller_state.import_context) manager.errors.set_file(caller_state.xpath, caller_state.id) manager.errors.report(line, 0, - 'Import of "%s" ignored' % (id,), + f'Import of "{id}" ignored', severity='error') manager.errors.report(line, 0, "(Using --follow-imports=error, module not passed on command line)", @@ -2648,7 +2648,7 @@ def skipping_ancestor(manager: BuildManager, id: str, path: str, ancestor_for: ' # so we'd need to cache the decision. manager.errors.set_import_context([]) manager.errors.set_file(ancestor_for.xpath, ancestor_for.id) - manager.errors.report(-1, -1, 'Ancestor package "%s" ignored' % (id,), + manager.errors.report(-1, -1, f'Ancestor package "{id}" ignored', severity='error', only_once=True) manager.errors.report(-1, -1, "(Using --follow-imports=error, submodule passed on command line)", @@ -2784,7 +2784,7 @@ def __init__(self, index: int, scc: List[str]) -> None: def dumps(self) -> str: """Convert to JSON string.""" total_size = sum(self.sizes.values()) - return "[%s, %s, %s,\n %s,\n %s]" % (json.dumps(self.node_id), + return "[{}, {}, {},\n {},\n {}]".format(json.dumps(self.node_id), json.dumps(total_size), json.dumps(self.scc), json.dumps(self.sizes), @@ -2798,7 +2798,7 @@ def dump_timing_stats(path: str, graph: Graph) -> None: with open(path, 'w') as f: for k in sorted(graph.keys()): v = graph[k] - f.write('{} {}\n'.format(v.id, v.time_spent_us)) + f.write(f'{v.id} {v.time_spent_us}\n') def dump_graph(graph: Graph, stdout: Optional[TextIO] = None) -> None: @@ -2873,7 +2873,7 @@ def load_graph(sources: List[BuildSource], manager: BuildManager, manager.errors.set_file(st.xpath, st.id) manager.errors.report( -1, -1, - 'Duplicate module named "%s" (also at "%s")' % (st.id, graph[st.id].xpath), + f'Duplicate module named "{st.id}" (also at "{graph[st.id].xpath}")', blocker=True, ) manager.errors.report( @@ -3081,11 +3081,11 @@ def process_graph(graph: Graph, manager: BuildManager) -> None: scc_str = " ".join(scc) if fresh: - manager.trace("Queuing %s SCC (%s)" % (fresh_msg, scc_str)) + manager.trace(f"Queuing {fresh_msg} SCC ({scc_str})") fresh_scc_queue.append(scc) else: if len(fresh_scc_queue) > 0: - manager.log("Processing {} queued fresh SCCs".format(len(fresh_scc_queue))) + manager.log(f"Processing {len(fresh_scc_queue)} queued fresh SCCs") # Defer processing fresh SCCs until we actually run into a stale SCC # and need the earlier modules to be loaded. # @@ -3105,7 +3105,7 @@ def process_graph(graph: Graph, manager: BuildManager) -> None: fresh_scc_queue = [] size = len(scc) if size == 1: - manager.log("Processing SCC singleton (%s) as %s" % (scc_str, fresh_msg)) + manager.log(f"Processing SCC singleton ({scc_str}) as {fresh_msg}") else: manager.log("Processing SCC of size %d (%s) as %s" % (size, scc_str, fresh_msg)) process_stale_scc(graph, scc, manager) diff --git a/mypy/checker.py b/mypy/checker.py index 002f28d4db6cb..d0820e483d650 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -97,26 +97,23 @@ DeferredNodeType: _TypeAlias = Union[FuncDef, LambdaExpr, OverloadedFuncDef, Decorator] FineGrainedDeferredNodeType: _TypeAlias = Union[FuncDef, MypyFile, OverloadedFuncDef] + # A node which is postponed to be processed during the next pass. # In normal mode one can defer functions and methods (also decorated and/or overloaded) # and lambda expressions. Nested functions can't be deferred -- only top-level functions # and methods of classes not defined within a function can be deferred. -DeferredNode = NamedTuple( - 'DeferredNode', - [ - ('node', DeferredNodeType), - ('active_typeinfo', Optional[TypeInfo]), # And its TypeInfo (for semantic analysis - # self type handling) - ]) +class DeferredNode(NamedTuple): + node: DeferredNodeType + # And its TypeInfo (for semantic analysis self type handling + active_typeinfo: Optional[TypeInfo] + # Same as above, but for fine-grained mode targets. Only top-level functions/methods # and module top levels are allowed as such. -FineGrainedDeferredNode = NamedTuple( - 'FineGrainedDeferredNode', - [ - ('node', FineGrainedDeferredNodeType), - ('active_typeinfo', Optional[TypeInfo]), - ]) +class FineGrainedDeferredNode(NamedTuple): + node: FineGrainedDeferredNodeType + active_typeinfo: Optional[TypeInfo] + # Data structure returned by find_isinstance_check representing # information learned from the truth or falsehood of a condition. The @@ -131,25 +128,23 @@ # (such as two references to the same variable). TODO: it would # probably be better to have the dict keyed by the nodes' literal_hash # field instead. - TypeMap: _TypeAlias = Optional[Dict[Expression, Type]] + # An object that represents either a precise type or a type with an upper bound; # it is important for correct type inference with isinstance. -TypeRange = NamedTuple( - 'TypeRange', - [ - ('item', Type), - ('is_upper_bound', bool), # False => precise type - ]) +class TypeRange(NamedTuple): + item: Type + is_upper_bound: bool # False => precise type + # Keeps track of partial types in a single scope. In fine-grained incremental # mode partial types initially defined at the top level cannot be completed in # a function, and we use the 'is_function' attribute to enforce this. -PartialTypeScope = NamedTuple('PartialTypeScope', [('map', Dict[Var, Context]), - ('is_function', bool), - ('is_local', bool), - ]) +class PartialTypeScope(NamedTuple): + map: Dict[Var, Context] + is_function: bool + is_local: bool class TypeChecker(NodeVisitor[None], CheckerPluginInterface): @@ -891,7 +886,7 @@ def check_func_def(self, defn: FuncItem, typ: CallableType, name: Optional[str]) self.msg.unimported_type_becomes_any("Return type", ret_type, fdef) for idx, arg_type in enumerate(fdef.type.arg_types): if has_any_from_unimported_type(arg_type): - prefix = "Argument {} to \"{}\"".format(idx + 1, fdef.name) + prefix = f"Argument {idx + 1} to \"{fdef.name}\"" self.msg.unimported_type_becomes_any(prefix, arg_type, fdef) check_for_explicit_any(fdef.type, self.options, self.is_typeshed_stub, self.msg, context=fdef) @@ -1062,9 +1057,9 @@ def check_default_args(self, item: FuncItem, body_is_trivial: bool) -> None: name = arg.variable.name msg = 'Incompatible default for ' if name.startswith('__tuple_arg_'): - msg += "tuple argument {}".format(name[12:]) + msg += f"tuple argument {name[12:]}" else: - msg += 'argument "{}"'.format(name) + msg += f'argument "{name}"' self.check_simple_assignment( arg.variable.type, arg.initializer, @@ -1964,7 +1959,7 @@ def check_enum_bases(self, defn: ClassDef) -> None: continue elif enum_base is not None: self.fail( - 'No base classes are allowed after "{}"'.format(enum_base), + f'No base classes are allowed after "{enum_base}"', defn, ) break @@ -3308,8 +3303,8 @@ def check_simple_assignment(self, lvalue_type: Optional[Type], rvalue: Expressio self.msg.deleted_as_lvalue(lvalue_type, context) elif lvalue_type: self.check_subtype(rvalue_type, lvalue_type, context, msg, - '{} has type'.format(rvalue_name), - '{} has type'.format(lvalue_name), code=code) + f'{rvalue_name} has type', + f'{lvalue_name} has type', code=code) return rvalue_type def check_member_assignment(self, instance_type: Type, attribute_type: Type, @@ -3717,7 +3712,7 @@ def _type_check_raise_python2(self, e: Expression, s: RaiseStmt, typ: ProperType expected_type = TypeType(exc_type) self.check_subtype( typ.items[0], expected_type, s, - 'Argument 1 must be "{}" subtype'.format(expected_type), + f'Argument 1 must be "{expected_type}" subtype', ) # Typecheck `traceback` part: @@ -3732,7 +3727,7 @@ def _type_check_raise_python2(self, e: Expression, s: RaiseStmt, typ: ProperType ]) self.check_subtype( typ.items[2], traceback_type, s, - 'Argument 3 must be "{}" subtype'.format(traceback_type), + f'Argument 3 must be "{traceback_type}" subtype', ) else: expected_type_items = [ @@ -4302,7 +4297,7 @@ def _make_fake_typeinfo_and_full_name( curr_module_: MypyFile, ) -> Tuple[TypeInfo, str]: names_list = pretty_seq([x.type.name for x in base_classes_], "and") - short_name = ''.format(names_list) + short_name = f'' full_name_ = gen_unique_name(short_name, curr_module_.names) cdef, info_ = self.make_fake_typeinfo( curr_module_.fullname, @@ -4354,7 +4349,7 @@ def intersect_instance_callable(self, typ: Instance, callable_type: CallableType # have a valid fullname and a corresponding entry in a symbol table. We generate # a unique name inside the symbol table of the current module. cur_module = cast(MypyFile, self.scope.stack[0]) - gen_name = gen_unique_name("".format(typ.type.name), + gen_name = gen_unique_name(f"", cur_module.names) # Synthesize a fake TypeInfo @@ -5367,7 +5362,7 @@ def lookup(self, name: str) -> SymbolTableNode: table = cast(MypyFile, b.node).names if name in table: return table[name] - raise KeyError('Failed lookup: {}'.format(name)) + raise KeyError(f'Failed lookup: {name}') def lookup_qualified(self, name: str) -> SymbolTableNode: if '.' not in name: @@ -5891,7 +5886,7 @@ def and_conditional_maps(m1: TypeMap, m2: TypeMap) -> TypeMap: # arbitrarily give precedence to m2. (In the future, we could use # an intersection type.) result = m2.copy() - m2_keys = set(literal_hash(n2) for n2 in m2) + m2_keys = {literal_hash(n2) for n2 in m2} for n1 in m1: if literal_hash(n1) not in m2_keys: result[n1] = m1[n1] @@ -6561,7 +6556,7 @@ def is_static(func: Union[FuncBase, Decorator]) -> bool: return is_static(func.func) elif isinstance(func, FuncBase): return func.is_static - assert False, "Unexpected func type: {}".format(type(func)) + assert False, f"Unexpected func type: {type(func)}" def is_subtype_no_promote(left: Type, right: Type) -> bool: diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index cea44c6c17db5..ed6fd73acfa54 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -156,7 +156,7 @@ def extract_refexpr_names(expr: RefExpr) -> Set[str]: else: break else: - raise AssertionError("Unknown RefExpr subclass: {}".format(type(expr))) + raise AssertionError(f"Unknown RefExpr subclass: {type(expr)}") return output @@ -437,7 +437,7 @@ def method_fullname(self, object_type: Type, method_name: str) -> Optional[str]: type_name = tuple_fallback(object_type).type.fullname if type_name is not None: - return '{}.{}'.format(type_name, method_name) + return f'{type_name}.{method_name}' else: return None @@ -592,7 +592,7 @@ def check_typeddict_call_with_kwargs(self, callee: TypedDictType, self.chk.check_simple_assignment( lvalue_type=item_expected_type, rvalue=item_value, context=item_value, msg=message_registry.INCOMPATIBLE_TYPES, - lvalue_name='TypedDict item "{}"'.format(item_name), + lvalue_name=f'TypedDict item "{item_name}"', rvalue_name='expression', code=codes.TYPEDDICT_ITEM) @@ -2199,7 +2199,7 @@ def visit_op_expr(self, e: OpExpr) -> Type: e.method_type = method_type return result else: - raise RuntimeError('Unknown operator {}'.format(e.op)) + raise RuntimeError(f'Unknown operator {e.op}') def visit_comparison_expr(self, e: ComparisonExpr) -> Type: """Type check a comparison expression. @@ -2296,7 +2296,7 @@ def visit_comparison_expr(self, e: ComparisonExpr) -> Type: self.msg.dangerous_comparison(left_type, right_type, 'identity', e) method_type = None else: - raise RuntimeError('Unknown comparison operator {}'.format(operator)) + raise RuntimeError(f'Unknown comparison operator {operator}') e.method_types.append(method_type) diff --git a/mypy/checkmember.py b/mypy/checkmember.py index 04b64e9ba7fe4..29d2728c2174f 100644 --- a/mypy/checkmember.py +++ b/mypy/checkmember.py @@ -263,7 +263,7 @@ def analyze_type_callable_member_access(name: str, # Look up from the 'type' type. return _analyze_member_access(name, typ.fallback, mx) else: - assert False, 'Unexpected type {}'.format(repr(ret_type)) + assert False, f'Unexpected type {ret_type!r}' def analyze_type_type_member_access(name: str, @@ -410,7 +410,7 @@ def analyze_member_var_access(name: str, result = getattr_type # Call the attribute hook before returning. - fullname = '{}.{}'.format(method.info.fullname, name) + fullname = f'{method.info.fullname}.{name}' hook = mx.chk.plugin.get_attribute_hook(fullname) if hook: result = hook(AttributeContext(get_proper_type(mx.original_type), @@ -607,7 +607,7 @@ def analyze_var(name: str, mx.not_ready_callback(var.name, mx.context) # Implicit 'Any' type. result = AnyType(TypeOfAny.special_form) - fullname = '{}.{}'.format(var.info.fullname, name) + fullname = f'{var.info.fullname}.{name}' hook = mx.chk.plugin.get_attribute_hook(fullname) if result and not mx.is_lvalue and not implicit: result = analyze_descriptor_access(result, mx) diff --git a/mypy/checkpattern.py b/mypy/checkpattern.py index 7836da0192571..6a8a0196306c0 100644 --- a/mypy/checkpattern.py +++ b/mypy/checkpattern.py @@ -53,13 +53,10 @@ # For every Pattern a PatternType can be calculated. This requires recursively calculating # the PatternTypes of the sub-patterns first. # Using the data in the PatternType the match subject and captured names can be narrowed/inferred. -PatternType = NamedTuple( - 'PatternType', - [ - ('type', Type), # The type the match subject can be narrowed to - ('rest_type', Type), # The remaining type if the pattern didn't match - ('captures', Dict[Expression, Type]), # The variables captured by the pattern - ]) +class PatternType(NamedTuple): + type: Type # The type the match subject can be narrowed to + rest_type: Type # The remaining type if the pattern didn't match + captures: Dict[Expression, Type] # The variables captured by the pattern class PatternChecker(PatternVisitor[PatternType]): @@ -628,7 +625,7 @@ def update_type_map(self, ) -> None: # Calculating this would not be needed if TypeMap directly used literal hashes instead of # expressions, as suggested in the TODO above it's definition - already_captured = set(literal_hash(expr) for expr in original_type_map) + already_captured = {literal_hash(expr) for expr in original_type_map} for expr, typ in extra_type_map.items(): if literal_hash(expr) in already_captured: node = get_var(expr) diff --git a/mypy/checkstrformat.py b/mypy/checkstrformat.py index 995f3073ba798..589a1fd6ac408 100644 --- a/mypy/checkstrformat.py +++ b/mypy/checkstrformat.py @@ -519,7 +519,7 @@ def apply_field_accessors(self, spec: ConversionSpecifier, repl: Expression, dummy, fnam="", module=None, options=self.chk.options, errors=temp_errors ) if temp_errors.is_errors(): - self.msg.fail('Syntax error in format specifier "{}"'.format(spec.field), + self.msg.fail(f'Syntax error in format specifier "{spec.field}"', ctx, code=codes.STRING_FORMATTING) return TempNode(AnyType(TypeOfAny.from_error)) diff --git a/mypy/config_parser.py b/mypy/config_parser.py index 36358f9df79a1..a9ba8535a5d60 100644 --- a/mypy/config_parser.py +++ b/mypy/config_parser.py @@ -28,20 +28,20 @@ def parse_version(v: str) -> Tuple[int, int]: m = re.match(r'\A(\d)\.(\d+)\Z', v) if not m: raise argparse.ArgumentTypeError( - "Invalid python version '{}' (expected format: 'x.y')".format(v)) + f"Invalid python version '{v}' (expected format: 'x.y')") major, minor = int(m.group(1)), int(m.group(2)) if major == 2: if minor != 7: raise argparse.ArgumentTypeError( - "Python 2.{} is not supported (must be 2.7)".format(minor)) + f"Python 2.{minor} is not supported (must be 2.7)") elif major == 3: if minor < defaults.PYTHON3_VERSION_MIN[1]: raise argparse.ArgumentTypeError( - "Python 3.{0} is not supported (must be {1}.{2} or higher)".format(minor, + "Python 3.{} is not supported (must be {}.{} or higher)".format(minor, *defaults.PYTHON3_VERSION_MIN)) else: raise argparse.ArgumentTypeError( - "Python major version '{}' out of range (must be 2 or 3)".format(major)) + f"Python major version '{major}' out of range (must be 2 or 3)") return major, minor @@ -105,7 +105,7 @@ def check_follow_imports(choice: str) -> str: raise argparse.ArgumentTypeError( "invalid choice '{}' (choose from {})".format( choice, - ', '.join("'{}'".format(x) for x in choices))) + ', '.join(f"'{x}'" for x in choices))) return choice @@ -196,7 +196,7 @@ def parse_config_file(options: Options, set_strict_flags: Callable[[], None], parser = config_parser config_types = ini_config_types except (tomllib.TOMLDecodeError, configparser.Error, ConfigTOMLValueError) as err: - print("%s: %s" % (config_file, err), file=stderr) + print(f"{config_file}: {err}", file=stderr) else: if config_file in defaults.SHARED_CONFIG_FILES and 'mypy' not in parser: continue @@ -214,7 +214,7 @@ def parse_config_file(options: Options, set_strict_flags: Callable[[], None], print("%s: No [mypy] section in config file" % file_read, file=stderr) else: section = parser['mypy'] - prefix = '%s: [%s]: ' % (file_read, 'mypy') + prefix = '{}: [{}]: '.format(file_read, 'mypy') updates, report_dirs = parse_section( prefix, options, set_strict_flags, section, config_types, stderr) for k, v in updates.items(): @@ -258,7 +258,7 @@ def get_prefix(file_read: str, name: str) -> str: else: module_name_str = name - return '%s: [%s]: ' % (file_read, module_name_str) + return f'{file_read}: [{module_name_str}]: ' def is_toml(filename: str) -> bool: @@ -369,7 +369,7 @@ def parse_section(prefix: str, template: Options, if report_type in defaults.REPORTER_NAMES: report_dirs[report_type] = str(section[key]) else: - print("%sUnrecognized report type: %s" % (prefix, key), + print(f"{prefix}Unrecognized report type: {key}", file=stderr) continue if key.startswith('x_'): @@ -386,7 +386,7 @@ def parse_section(prefix: str, template: Options, elif key == 'strict': pass # Special handling below else: - print("%sUnrecognized option: %s = %s" % (prefix, key, section[key]), + print(f"{prefix}Unrecognized option: {key} = {section[key]}", file=stderr) if invert: dv = getattr(template, options_key, None) @@ -404,19 +404,19 @@ def parse_section(prefix: str, template: Options, v = not v elif callable(ct): if invert: - print("%sCan not invert non-boolean key %s" % (prefix, options_key), + print(f"{prefix}Can not invert non-boolean key {options_key}", file=stderr) continue try: v = ct(section.get(key)) except argparse.ArgumentTypeError as err: - print("%s%s: %s" % (prefix, key, err), file=stderr) + print(f"{prefix}{key}: {err}", file=stderr) continue else: - print("%sDon't know what type %s should have" % (prefix, key), file=stderr) + print(f"{prefix}Don't know what type {key} should have", file=stderr) continue except ValueError as err: - print("%s%s: %s" % (prefix, key, err), file=stderr) + print(f"{prefix}{key}: {err}", file=stderr) continue if key == 'strict': if v: @@ -493,7 +493,7 @@ def mypy_comments_to_config_map(line: str, name = entry value = None else: - name, value = [x.strip() for x in entry.split('=', 1)] + name, value = (x.strip() for x in entry.split('=', 1)) name = name.replace('-', '_') if value is None: diff --git a/mypy/constraints.py b/mypy/constraints.py index 1d9ca8b138ed7..9a6d87575bdc8 100644 --- a/mypy/constraints.py +++ b/mypy/constraints.py @@ -45,7 +45,7 @@ def __repr__(self) -> str: op_str = '<:' if self.op == SUPERTYPE_OF: op_str = ':>' - return '{} {} {}'.format(self.type_var, op_str, self.target) + return f'{self.type_var} {op_str} {self.target}' def infer_constraints_for_callable( @@ -748,7 +748,7 @@ def visit_union_type(self, template: UnionType) -> List[Constraint]: " (should have been handled in infer_constraints)") def visit_type_alias_type(self, template: TypeAliasType) -> List[Constraint]: - assert False, "This should be never called, got {}".format(template) + assert False, f"This should be never called, got {template}" def infer_against_any(self, types: Iterable[Type], any_type: AnyType) -> List[Constraint]: res: List[Constraint] = [] @@ -791,7 +791,7 @@ def neg_op(op: int) -> int: elif op == SUPERTYPE_OF: return SUBTYPE_OF else: - raise ValueError('Invalid operator {}'.format(op)) + raise ValueError(f'Invalid operator {op}') def find_matching_overload_item(overloaded: Overloaded, template: CallableType) -> CallableType: diff --git a/mypy/dmypy_os.py b/mypy/dmypy_os.py index 3168f7566a270..1405e0a309e9c 100644 --- a/mypy/dmypy_os.py +++ b/mypy/dmypy_os.py @@ -38,6 +38,6 @@ def alive(pid: int) -> bool: def kill(pid: int) -> None: """Kill the process.""" if sys.platform == 'win32': - subprocess.check_output("taskkill /pid {pid} /f /t".format(pid=pid)) + subprocess.check_output(f"taskkill /pid {pid} /f /t") else: os.kill(pid, signal.SIGKILL) diff --git a/mypy/dmypy_server.py b/mypy/dmypy_server.py index 04e25091484e0..de03d64005256 100644 --- a/mypy/dmypy_server.py +++ b/mypy/dmypy_server.py @@ -56,7 +56,7 @@ def daemonize(options: Options, """ command = [sys.executable, '-m', 'mypy.dmypy', '--status-file', status_file, 'daemon'] pickled_options = pickle.dumps((options.snapshot(), timeout, log_file)) - command.append('--options-data="{}"'.format(base64.b64encode(pickled_options).decode())) + command.append(f'--options-data="{base64.b64encode(pickled_options).decode()}"') info = STARTUPINFO() info.dwFlags = 0x1 # STARTF_USESHOWWINDOW aka use wShowWindow's value info.wShowWindow = 0 # SW_HIDE aka make the window invisible @@ -200,7 +200,7 @@ def __init__(self, options: Options, self.formatter = FancyFormatter(sys.stdout, sys.stderr, options.show_error_codes) def _response_metadata(self) -> Dict[str, str]: - py_version = '{}_{}'.format(self.options.python_version[0], self.options.python_version[1]) + py_version = f'{self.options.python_version[0]}_{self.options.python_version[1]}' return { 'platform': self.options.platform, 'python_version': py_version, @@ -367,7 +367,7 @@ def cmd_recheck(self, sources = sources + added_sources # Make a copy! t1 = time.time() manager = self.fine_grained_manager.manager - manager.log("fine-grained increment: cmd_recheck: {:.3f}s".format(t1 - t0)) + manager.log(f"fine-grained increment: cmd_recheck: {t1 - t0:.3f}s") if not self.following_imports(): messages = self.fine_grained_increment(sources, remove, update) else: @@ -525,10 +525,10 @@ def fine_grained_increment(self, manager.search_paths) manager.search_paths = compute_search_paths(sources, manager.options, manager.data_dir) t1 = time.time() - manager.log("fine-grained increment: find_changed: {:.3f}s".format(t1 - t0)) + manager.log(f"fine-grained increment: find_changed: {t1 - t0:.3f}s") messages = self.fine_grained_manager.update(changed, removed) t2 = time.time() - manager.log("fine-grained increment: update: {:.3f}s".format(t2 - t1)) + manager.log(f"fine-grained increment: update: {t2 - t1:.3f}s") manager.add_stats( find_changes_time=t1 - t0, fg_update_time=t2 - t1, @@ -555,7 +555,7 @@ def fine_grained_increment_follow_imports(self, sources: List[BuildSource]) -> L manager.search_paths = compute_search_paths(sources, manager.options, manager.data_dir) t1 = time.time() - manager.log("fine-grained increment: find_changed: {:.3f}s".format(t1 - t0)) + manager.log(f"fine-grained increment: find_changed: {t1 - t0:.3f}s") seen = {source.module for source in sources} @@ -646,7 +646,7 @@ def refresh_file(module: str, path: str) -> List[str]: t5 = time.time() - manager.log("fine-grained increment: update: {:.3f}s".format(t5 - t1)) + manager.log(f"fine-grained increment: update: {t5 - t1:.3f}s") manager.add_stats( find_changes_time=t1 - t0, fg_update_time=t2 - t1, @@ -902,7 +902,7 @@ def get_meminfo() -> Dict[str, Any]: def find_all_sources_in_build(graph: mypy.build.Graph, extra: Sequence[BuildSource] = ()) -> List[BuildSource]: result = list(extra) - seen = set(source.module for source in result) + seen = {source.module for source in result} for module, state in graph.items(): if module not in seen: result.append(BuildSource(state.path, module)) diff --git a/mypy/errorcodes.py b/mypy/errorcodes.py index 85d6d9dd41594..e237e818edaea 100644 --- a/mypy/errorcodes.py +++ b/mypy/errorcodes.py @@ -25,7 +25,7 @@ def __init__(self, code: str, error_codes[code] = self def __str__(self) -> str: - return ''.format(self.code) + return f'' ATTR_DEFINED: Final = ErrorCode("attr-defined", "Check that attribute exists", "General") diff --git a/mypy/errors.py b/mypy/errors.py index 590b02865fb50..0ad56b079eccd 100644 --- a/mypy/errors.py +++ b/mypy/errors.py @@ -161,7 +161,7 @@ def on_error(self, file: str, info: ErrorInfo) -> bool: elif callable(self._filter): should_filter = self._filter(file, info) else: - raise AssertionError("invalid error filter: {}".format(type(self._filter))) + raise AssertionError(f"invalid error filter: {type(self._filter)}") if should_filter and self._filtered is not None: self._filtered.append(info) @@ -661,18 +661,18 @@ def format_messages(self, error_info: List[ErrorInfo], s = '' if file is not None: if self.show_column_numbers and line >= 0 and column >= 0: - srcloc = '{}:{}:{}'.format(file, line, 1 + column) + srcloc = f'{file}:{line}:{1 + column}' elif line >= 0: - srcloc = '{}:{}'.format(file, line) + srcloc = f'{file}:{line}' else: srcloc = file - s = '{}: {}: {}'.format(srcloc, severity, message) + s = f'{srcloc}: {severity}: {message}' else: s = message if self.show_error_codes and code and severity != 'note': # If note has an error code, it is related to a previous error. Avoid # displaying duplicate error codes. - s = '{} [{}]'.format(s, code.code) + s = f'{s} [{code.code}]' a.append(s) if self.pretty: # Add source code fragment and a location marker. @@ -723,10 +723,12 @@ def targets(self) -> Set[str]: """Return a set of all targets that contain errors.""" # TODO: Make sure that either target is always defined or that not being defined # is okay for fine-grained incremental checking. - return set(info.target - for errs in self.error_info_map.values() - for info in errs - if info.target) + return { + info.target + for errs in self.error_info_map.values() + for info in errs + if info.target + } def render_messages(self, errors: List[ErrorInfo]) -> List[ErrorTuple]: @@ -792,7 +794,7 @@ def render_messages(self, result.append((file, -1, -1, 'note', 'At top level:', e.allow_dups, None)) else: result.append((file, -1, -1, 'note', - 'In class "{}":'.format(e.type), e.allow_dups, None)) + f'In class "{e.type}":', e.allow_dups, None)) if isinstance(e.message, ErrorMessage): result.append( @@ -927,14 +929,14 @@ def report_internal_error(err: Exception, # Compute file:line prefix for official-looking error messages. if file: if line: - prefix = '{}:{}: '.format(file, line) + prefix = f'{file}:{line}: ' else: - prefix = '{}: '.format(file) + prefix = f'{file}: ' else: prefix = '' # Print "INTERNAL ERROR" message. - print('{}error: INTERNAL ERROR --'.format(prefix), + print(f'{prefix}error: INTERNAL ERROR --', 'Please try using mypy master on GitHub:\n' 'https://mypy.readthedocs.io/en/stable/common_issues.html' '#using-a-development-mypy-build', @@ -946,7 +948,7 @@ def report_internal_error(err: Exception, print('If this issue continues with mypy master, ' 'please report a bug at https://github.com/python/mypy/issues', file=stderr) - print('version: {}'.format(mypy_version), + print(f'version: {mypy_version}', file=stderr) # If requested, drop into pdb. This overrides show_tb. @@ -969,8 +971,8 @@ def report_internal_error(err: Exception, print('Traceback (most recent call last):') for s in traceback.format_list(tb + tb2): print(s.rstrip('\n')) - print('{}: {}'.format(type(err).__name__, err), file=stdout) - print('{}: note: use --pdb to drop into pdb'.format(prefix), file=stderr) + print(f'{type(err).__name__}: {err}', file=stdout) + print(f'{prefix}: note: use --pdb to drop into pdb', file=stderr) # Exit. The caller has nothing more to say. # We use exit code 2 to signal that this is no ordinary error. diff --git a/mypy/expandtype.py b/mypy/expandtype.py index 78b36f2887576..985114a53051f 100644 --- a/mypy/expandtype.py +++ b/mypy/expandtype.py @@ -164,7 +164,7 @@ def expand_unpack(self, t: UnpackType) -> Optional[Union[List[Type], Instance, A elif isinstance(repl, UninhabitedType): return None else: - raise NotImplementedError("Invalid type to expand: {}".format(repl)) + raise NotImplementedError(f"Invalid type to expand: {repl}") else: raise NotImplementedError diff --git a/mypy/fastparse.py b/mypy/fastparse.py index 0b3322db2af3d..e4e8f4a7888d2 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -250,7 +250,7 @@ def parse_type_comment(type_comment: str, except SyntaxError: if errors is not None: stripped_type = type_comment.split("#", 2)[0].strip() - err_msg = '{} "{}"'.format(TYPE_COMMENT_SYNTAX_ERROR, stripped_type) + err_msg = f'{TYPE_COMMENT_SYNTAX_ERROR} "{stripped_type}"' errors.report(line, column, err_msg, blocker=True, code=codes.SYNTAX) return None, None else: @@ -833,7 +833,7 @@ def do_func_def(self, n: Union[ast3.FunctionDef, ast3.AsyncFunctionDef], arg_types.insert(0, AnyType(TypeOfAny.special_form)) except SyntaxError: stripped_type = n.type_comment.split("#", 2)[0].strip() - err_msg = '{} "{}"'.format(TYPE_COMMENT_SYNTAX_ERROR, stripped_type) + err_msg = f'{TYPE_COMMENT_SYNTAX_ERROR} "{stripped_type}"' self.fail(err_msg, lineno, n.col_offset) if n.type_comment and n.type_comment[0] not in ["(", "#"]: self.note('Suggestion: wrap argument types in parentheses', @@ -1751,7 +1751,7 @@ def visit_Call(self, e: Call) -> Type: typ = converted else: self.fail( - 'Unexpected argument "{}" for argument constructor'.format(k.arg), + f'Unexpected argument "{k.arg}" for argument constructor', value.lineno, value.col_offset) return CallableArgument(typ, name, constructor, e.lineno, e.col_offset) @@ -1840,7 +1840,7 @@ def numeric_type(self, value: object, n: AST) -> Type: # RawExpressionType so we just pass in 'None' for now. We'll report the # appropriate error at a later stage. numeric_value = None - type_name = 'builtins.{}'.format(type(value).__name__) + type_name = f'builtins.{type(value).__name__}' return RawExpressionType( numeric_value, type_name, @@ -1939,7 +1939,7 @@ def visit_Attribute(self, n: Attribute) -> Type: before_dot = self.visit(n.value) if isinstance(before_dot, UnboundType) and not before_dot.args: - return UnboundType("{}.{}".format(before_dot.name, n.attr), line=self.line) + return UnboundType(f"{before_dot.name}.{n.attr}", line=self.line) else: return self.invalid_type(n) @@ -1959,5 +1959,5 @@ def stringify_name(n: AST) -> Optional[str]: elif isinstance(n, Attribute): sv = stringify_name(n.value) if sv is not None: - return "{}.{}".format(sv, n.attr) + return f"{sv}.{n.attr}" return None # Can't do it. diff --git a/mypy/fastparse2.py b/mypy/fastparse2.py index 0e8faa957d67c..e42a1e3c52c58 100644 --- a/mypy/fastparse2.py +++ b/mypy/fastparse2.py @@ -408,7 +408,7 @@ def visit_FunctionDef(self, n: ast27.FunctionDef) -> Statement: arg_types.insert(0, AnyType(TypeOfAny.special_form)) except SyntaxError: stripped_type = type_comment.split("#", 2)[0].strip() - err_msg = '{} "{}"'.format(TYPE_COMMENT_SYNTAX_ERROR, stripped_type) + err_msg = f'{TYPE_COMMENT_SYNTAX_ERROR} "{stripped_type}"' self.fail(err_msg, lineno, n.col_offset) arg_types = [AnyType(TypeOfAny.from_error)] * len(args) return_type = AnyType(TypeOfAny.from_error) @@ -545,14 +545,14 @@ def convert_arg(self, index: int, arg: ast27.expr, line: int, if isinstance(arg, Name): v = arg.id elif isinstance(arg, ast27_Tuple): - v = '__tuple_arg_{}'.format(index + 1) + v = f'__tuple_arg_{index + 1}' rvalue = NameExpr(v) rvalue.set_line(line) assignment = AssignmentStmt([self.visit(arg)], rvalue) assignment.set_line(line) decompose_stmts.append(assignment) else: - raise RuntimeError("'{}' is not a valid argument.".format(ast27.dump(arg))) + raise RuntimeError(f"'{ast27.dump(arg)}' is not a valid argument.") return Var(v) def get_type(self, @@ -578,7 +578,7 @@ def stringify_name(self, n: AST) -> str: if isinstance(n, Name): return n.id elif isinstance(n, Attribute): - return "{}.{}".format(self.stringify_name(n.value), n.attr) + return f"{self.stringify_name(n.value)}.{n.attr}" else: assert False, "can't stringify " + str(type(n)) diff --git a/mypy/find_sources.py b/mypy/find_sources.py index 25da5b4aa842f..64e975f868337 100644 --- a/mypy/find_sources.py +++ b/mypy/find_sources.py @@ -38,7 +38,7 @@ def create_source_list(paths: Sequence[str], options: Options, sub_sources = finder.find_sources_in_dir(path) if not sub_sources and not allow_empty_dir: raise InvalidSourceList( - "There are no .py[i] files in directory '{}'".format(path) + f"There are no .py[i] files in directory '{path}'" ) sources.extend(sub_sources) else: @@ -185,7 +185,7 @@ def _crawl_up_helper(self, dir: str) -> Optional[Tuple[str, str]]: if not name.isidentifier(): # in most cases the directory name is invalid, we'll just stop crawling upwards # but if there's an __init__.py in the directory, something is messed up - raise InvalidSourceList("{} is not a valid Python package name".format(name)) + raise InvalidSourceList(f"{name} is not a valid Python package name") # we're definitely a package, so we always return a non-None value mod_prefix, base_dir = self.crawl_up_dir(parent) return module_join(mod_prefix, name), base_dir diff --git a/mypy/fixup.py b/mypy/fixup.py index ec979e4e1927c..1f04c2b181fa9 100644 --- a/mypy/fixup.py +++ b/mypy/fixup.py @@ -81,7 +81,7 @@ def visit_symbol_table(self, symtab: SymbolTable, table_fullname: str) -> None: assert stnode.node is not None, (table_fullname + "." + key, cross_ref) value.node = stnode.node elif not self.allow_missing: - assert False, "Could not find cross-ref %s" % (cross_ref,) + assert False, f"Could not find cross-ref {cross_ref}" else: # We have a missing crossref in allow missing mode, need to put something value.node = missing_info(self.modules) @@ -92,7 +92,7 @@ def visit_symbol_table(self, symtab: SymbolTable, table_fullname: str) -> None: elif value.node is not None: value.node.accept(self) else: - assert False, 'Unexpected empty node %r: %s' % (key, value) + assert False, f'Unexpected empty node {key!r}: {value}' def visit_func_def(self, func: FuncDef) -> None: if self.current_info is not None: diff --git a/mypy/gclogger.py b/mypy/gclogger.py index 1f36225461de7..b8d7980f5f435 100644 --- a/mypy/gclogger.py +++ b/mypy/gclogger.py @@ -29,7 +29,7 @@ def gc_callback(self, phase: str, info: Mapping[str, int]) -> None: self.gc_collected += info['collected'] self.gc_uncollectable += info['uncollectable'] else: - assert False, "Unrecognized gc phase (%r)" % (phase,) + assert False, f"Unrecognized gc phase ({phase!r})" def __exit__(self, *args: object) -> None: while self.gc_callback in gc.callbacks: diff --git a/mypy/ipc.py b/mypy/ipc.py index f48ac18075d80..bf8bfa43b62af 100644 --- a/mypy/ipc.py +++ b/mypy/ipc.py @@ -59,7 +59,7 @@ def read(self, size: int = 100000) -> bytes: timeout = int(self.timeout * 1000) if self.timeout else _winapi.INFINITE res = _winapi.WaitForSingleObject(ov.event, timeout) if res != _winapi.WAIT_OBJECT_0: - raise IPCException("Bad result from I/O wait: {}".format(res)) + raise IPCException(f"Bad result from I/O wait: {res}") except BaseException: ov.cancel() raise @@ -96,17 +96,17 @@ def write(self, data: bytes) -> None: timeout = int(self.timeout * 1000) if self.timeout else _winapi.INFINITE res = _winapi.WaitForSingleObject(ov.event, timeout) if res != _winapi.WAIT_OBJECT_0: - raise IPCException("Bad result from I/O wait: {}".format(res)) + raise IPCException(f"Bad result from I/O wait: {res}") elif err != 0: - raise IPCException("Failed writing to pipe with error: {}".format(err)) + raise IPCException(f"Failed writing to pipe with error: {err}") except BaseException: ov.cancel() raise bytes_written, err = ov.GetOverlappedResult(True) assert err == 0, err assert bytes_written == len(data) - except WindowsError as e: - raise IPCException("Failed to write with error: {}".format(e.winerror)) from e + except OSError as e: + raise IPCException(f"Failed to write with error: {e.winerror}") from e else: self.connection.sendall(data) self.connection.shutdown(socket.SHUT_WR) @@ -129,8 +129,8 @@ def __init__(self, name: str, timeout: Optional[float]) -> None: try: _winapi.WaitNamedPipe(self.name, timeout) except FileNotFoundError as e: - raise IPCException("The NamedPipe at {} was not found.".format(self.name)) from e - except WindowsError as e: + raise IPCException(f"The NamedPipe at {self.name} was not found.") from e + except OSError as e: if e.winerror == _winapi.ERROR_SEM_TIMEOUT: raise IPCException("Timed out waiting for connection.") from e else: @@ -145,7 +145,7 @@ def __init__(self, name: str, timeout: Optional[float]) -> None: _winapi.FILE_FLAG_OVERLAPPED, _winapi.NULL, ) - except WindowsError as e: + except OSError as e: if e.winerror == _winapi.ERROR_PIPE_BUSY: raise IPCException("The connection is busy.") from e else: @@ -179,7 +179,7 @@ def __init__(self, name: str, timeout: Optional[float] = None) -> None: name = r'\\.\pipe\{}-{}.pipe'.format( name, base64.urlsafe_b64encode(os.urandom(6)).decode()) else: - name = '{}.sock'.format(name) + name = f'{name}.sock' super().__init__(name, timeout) if sys.platform == 'win32': self.connection = _winapi.CreateNamedPipe(self.name, @@ -198,7 +198,7 @@ def __init__(self, name: str, timeout: Optional[float] = None) -> None: ) if self.connection == -1: # INVALID_HANDLE_VALUE err = _winapi.GetLastError() - raise IPCException('Invalid handle to pipe: {}'.format(err)) + raise IPCException(f'Invalid handle to pipe: {err}') else: self.sock_directory = tempfile.mkdtemp() sockfile = os.path.join(self.sock_directory, self.name) @@ -216,7 +216,7 @@ def __enter__(self) -> 'IPCServer': ov = _winapi.ConnectNamedPipe(self.connection, overlapped=True) # TODO: remove once typeshed supports Literal types assert isinstance(ov, _winapi.Overlapped) - except WindowsError as e: + except OSError as e: # Don't raise if the client already exists, or the client already connected if e.winerror not in (_winapi.ERROR_PIPE_CONNECTED, _winapi.ERROR_NO_DATA): raise diff --git a/mypy/join.py b/mypy/join.py index 78f280411622d..94d0afc434f9e 100644 --- a/mypy/join.py +++ b/mypy/join.py @@ -451,7 +451,7 @@ def visit_type_type(self, t: TypeType) -> ProperType: return self.default(self.s) def visit_type_alias_type(self, t: TypeAliasType) -> ProperType: - assert False, "This should be never called, got {}".format(t) + assert False, f"This should be never called, got {t}" def join(self, s: Type, t: Type) -> ProperType: return join_types(s, t) diff --git a/mypy/lookup.py b/mypy/lookup.py index fcb2f16073935..8a8350080bc26 100644 --- a/mypy/lookup.py +++ b/mypy/lookup.py @@ -26,7 +26,7 @@ def lookup_fully_qualified(name: str, modules: Dict[str, MypyFile], *, while True: if '.' not in head: if raise_on_missing: - assert '.' in head, "Cannot find module for %s" % (name,) + assert '.' in head, f"Cannot find module for {name}" return None head, tail = head.rsplit('.', maxsplit=1) rest.append(tail) @@ -38,13 +38,13 @@ def lookup_fully_qualified(name: str, modules: Dict[str, MypyFile], *, if not rest: # Looks like a module, don't use this to avoid confusions. if raise_on_missing: - assert rest, "Cannot find %s, got a module symbol" % (name,) + assert rest, f"Cannot find {name}, got a module symbol" return None while True: key = rest.pop() if key not in names: if raise_on_missing: - assert key in names, "Cannot find component %r for %r" % (key, name) + assert key in names, f"Cannot find component {key!r} for {name!r}" return None stnode = names[key] if not rest: @@ -54,6 +54,6 @@ def lookup_fully_qualified(name: str, modules: Dict[str, MypyFile], *, # or a Var made up for a missing module. if not isinstance(node, TypeInfo): if raise_on_missing: - assert node, "Cannot find %s" % (name,) + assert node, f"Cannot find {name}" return None names = node.names diff --git a/mypy/main.py b/mypy/main.py index a126122c18ed6..6b02382953142 100644 --- a/mypy/main.py +++ b/mypy/main.py @@ -36,7 +36,7 @@ def stat_proxy(path: str) -> os.stat_result: try: st = orig_stat(path) except os.error as err: - print("stat(%r) -> %s" % (path, err)) + print(f"stat({path!r}) -> {err}") raise else: print("stat(%r) -> (st_mode=%o, st_mtime=%d, st_size=%d)" % @@ -231,11 +231,11 @@ def invert_flag_name(flag: str) -> str: if len(split) == 2: prefix, rest = split if prefix in flag_prefix_map: - return '--{}-{}'.format(flag_prefix_map[prefix], rest) + return f'--{flag_prefix_map[prefix]}-{rest}' elif prefix == 'no': - return '--{}'.format(rest) + return f'--{rest}' - return '--no-{}'.format(flag[2:]) + return f'--no-{flag[2:]}' class PythonExecutableInferenceError(Exception): @@ -248,9 +248,9 @@ def python_executable_prefix(v: str) -> List[str]: # is the `py` launcher, which can be passed a version e.g. `py -3.8`, and it will # execute an installed Python 3.8 interpreter. See also: # https://docs.python.org/3/using/windows.html#python-launcher-for-windows - return ['py', '-{}'.format(v)] + return ['py', f'-{v}'] else: - return ['python{}'.format(v)] + return [f'python{v}'] def _python_executable_from_version(python_version: Tuple[int, int]) -> str: @@ -460,7 +460,7 @@ def add_invertible_flag(flag: str, group = parser if help is not argparse.SUPPRESS: - help += " (inverse: {})".format(inverse) + help += f" (inverse: {inverse})" arg = group.add_argument(flag, action='store_false' if default else 'store_true', @@ -1050,11 +1050,11 @@ def set_strict_flags() -> None: cache = FindModuleCache(search_paths, fscache, options) for p in special_opts.packages: if os.sep in p or os.altsep and os.altsep in p: - fail("Package name '{}' cannot have a slash in it.".format(p), + fail(f"Package name '{p}' cannot have a slash in it.", stderr, options) p_targets = cache.find_modules_recursive(p) if not p_targets: - fail("Can't find package '{}'".format(p), stderr, options) + fail(f"Can't find package '{p}'", stderr, options) targets.extend(p_targets) for m in special_opts.modules: targets.append(BuildSource(None, m, None)) @@ -1133,7 +1133,7 @@ def process_cache_map(parser: argparse.ArgumentParser, def maybe_write_junit_xml(td: float, serious: bool, messages: List[str], options: Options) -> None: if options.junit_xml: - py_version = '{}_{}'.format(options.python_version[0], options.python_version[1]) + py_version = f'{options.python_version[0]}_{options.python_version[1]}' util.write_junit_xml( td, serious, messages, options.junit_xml, py_version, options.platform) diff --git a/mypy/meet.py b/mypy/meet.py index ad77251828386..2602f0c1abd89 100644 --- a/mypy/meet.py +++ b/mypy/meet.py @@ -444,8 +444,8 @@ def are_tuples_overlapping(left: Type, right: Type, *, left, right = get_proper_types((left, right)) left = adjust_tuple(left, right) or left right = adjust_tuple(right, left) or right - assert isinstance(left, TupleType), 'Type {} is not a tuple'.format(left) - assert isinstance(right, TupleType), 'Type {} is not a tuple'.format(right) + assert isinstance(left, TupleType), f'Type {left} is not a tuple' + assert isinstance(right, TupleType), f'Type {right} is not a tuple' if len(left.items) != len(right.items): return False return all(is_overlapping_types(l, r, @@ -712,7 +712,7 @@ def visit_type_type(self, t: TypeType) -> ProperType: return self.default(self.s) def visit_type_alias_type(self, t: TypeAliasType) -> ProperType: - assert False, "This should be never called, got {}".format(t) + assert False, f"This should be never called, got {t}" def meet(self, s: Type, t: Type) -> ProperType: return meet_types(s, t) diff --git a/mypy/memprofile.py b/mypy/memprofile.py index 5052d04189945..7494fed757501 100644 --- a/mypy/memprofile.py +++ b/mypy/memprofile.py @@ -94,7 +94,7 @@ def find_recursive_objects(objs: List[object]) -> None: We use this since gc.get_objects() does not return objects without pointers in them such as strings. """ - seen = set(id(o) for o in objs) + seen = {id(o) for o in objs} def visit(o: object) -> None: if id(o) not in seen: diff --git a/mypy/messages.py b/mypy/messages.py index d499a574d5279..801f84c2580bb 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -231,7 +231,7 @@ def has_no_attr(self, if (isinstance(original_type, Instance) and original_type.type.has_readable_member(member)): - self.fail('Member "{}" is not assignable'.format(member), context) + self.fail(f'Member "{member}" is not assignable', context) elif member == '__contains__': self.fail('Unsupported right operand type for in ({})'.format( format_type(original_type)), context, code=codes.OPERATOR) @@ -363,7 +363,7 @@ def unsupported_operand_types(self, right_str = format_type(right_type) if self.are_type_names_disabled(): - msg = 'Unsupported operand types for {} (likely involving Union)'.format(op) + msg = f'Unsupported operand types for {op} (likely involving Union)' else: msg = 'Unsupported operand types for {} ({} and {})'.format( op, left_str, right_str) @@ -372,7 +372,7 @@ def unsupported_operand_types(self, def unsupported_left_operand(self, op: str, typ: Type, context: Context) -> None: if self.are_type_names_disabled(): - msg = 'Unsupported left operand type for {} (some union)'.format(op) + msg = f'Unsupported left operand type for {op} (some union)' else: msg = 'Unsupported left operand type for {} ({})'.format( op, format_type(typ)) @@ -384,7 +384,7 @@ def not_callable(self, typ: Type, context: Context) -> Type: def untyped_function_call(self, callee: CallableType, context: Context) -> Type: name = callable_name(callee) or '(unknown)' - self.fail('Call to untyped function {} in typed context'.format(name), context, + self.fail(f'Call to untyped function {name} in typed context', context, code=codes.NO_UNTYPED_CALL) return AnyType(TypeOfAny.from_error) @@ -421,7 +421,7 @@ def incompatible_argument(self, for method, op in op_methods_to_symbols.items(): for variant in method, '__r' + method[2:]: # FIX: do not rely on textual formatting - if name.startswith('"{}" of'.format(variant)): + if name.startswith(f'"{variant}" of'): if op == 'in' or variant != method: # Reversed order of base/argument. self.unsupported_operand_types(op, arg_type, base, @@ -455,7 +455,7 @@ def incompatible_argument(self, context, code=codes.ASSIGNMENT) return codes.ASSIGNMENT - target = 'to {} '.format(name) + target = f'to {name} ' msg = '' code = codes.MISC @@ -535,7 +535,7 @@ def incompatible_argument(self, if isinstance(outer_context, CallExpr) and len(outer_context.arg_names) >= n: arg_name = outer_context.arg_names[n - 1] if arg_name is not None: - arg_label = '"{}"'.format(arg_name) + arg_label = f'"{arg_name}"' if (arg_kind == ARG_STAR2 and isinstance(arg_type, TypedDictType) and m <= len(callee.arg_names) @@ -547,7 +547,7 @@ def incompatible_argument(self, arg_type.items[arg_name], expected_type, bare=True) - arg_label = '"{}"'.format(arg_name) + arg_label = f'"{arg_name}"' if isinstance(outer_context, IndexExpr) and isinstance(outer_context.index, StrExpr): msg = 'Value of "{}" has incompatible type {}; expected {}' .format( outer_context.index.value, quote_type_string(arg_type_str), @@ -642,7 +642,7 @@ def too_few_arguments(self, callee: CallableType, context: Context, callee_name = callable_name(callee) if callee_name is not None and diff and all(d is not None for d in diff): args = '", "'.join(cast(List[str], diff)) - msg += ' "{}" in call to {}'.format(args, callee_name) + msg += f' "{args}" in call to {callee_name}' else: msg = 'Too few arguments' + for_function(callee) @@ -651,7 +651,7 @@ def too_few_arguments(self, callee: CallableType, context: Context, self.fail(msg, context, code=codes.CALL_ARG) def missing_named_argument(self, callee: CallableType, context: Context, name: str) -> None: - msg = 'Missing named argument "{}"'.format(name) + for_function(callee) + msg = f'Missing named argument "{name}"' + for_function(callee) self.fail(msg, context, code=codes.CALL_ARG) def too_many_arguments(self, callee: CallableType, context: Context) -> None: @@ -666,7 +666,7 @@ def too_many_arguments_from_typed_dict(self, # Try to determine the name of the extra argument. for key in arg_type.items: if key not in callee.arg_names: - msg = 'Extra argument "{}" from **args'.format(key) + for_function(callee) + msg = f'Extra argument "{key}" from **args' + for_function(callee) break else: self.too_many_arguments(callee, context) @@ -692,7 +692,7 @@ def maybe_note_about_special_args(self, callee: CallableType, context: Context) def unexpected_keyword_argument(self, callee: CallableType, name: str, arg_type: Type, context: Context) -> None: - msg = 'Unexpected keyword argument "{}"'.format(name) + for_function(callee) + msg = f'Unexpected keyword argument "{name}"' + for_function(callee) # Suggest intended keyword, look for type match else fallback on any match. matching_type_args = [] not_matching_type_args = [] @@ -715,7 +715,7 @@ def unexpected_keyword_argument(self, callee: CallableType, name: str, arg_type: fname = callable_name(callee) if not fname: # an alias to function with a different name fname = 'Called function' - self.note('{} defined here'.format(fname), callee.definition, + self.note(f'{fname} defined here', callee.definition, file=module.path, origin=context, code=codes.CALL_ARG) def duplicate_argument_value(self, callee: CallableType, index: int, @@ -731,7 +731,7 @@ def does_not_return_value(self, callee_type: Optional[Type], context: Context) - if isinstance(callee_type, FunctionLike): name = callable_name(callee_type) if name is not None: - self.fail('{} does not return a value'.format(capitalize(name)), context, + self.fail(f'{capitalize(name)} does not return a value', context, code=codes.FUNC_RETURNS_VALUE) else: self.fail('Function does not return a value', context, code=codes.FUNC_RETURNS_VALUE) @@ -744,8 +744,8 @@ def deleted_as_rvalue(self, typ: DeletedType, context: Context) -> None: if typ.source is None: s = "" else: - s = ' "{}"'.format(typ.source) - self.fail('Trying to read deleted variable{}'.format(s), context) + s = f' "{typ.source}"' + self.fail(f'Trying to read deleted variable{s}', context) def deleted_as_lvalue(self, typ: DeletedType, context: Context) -> None: """Report an error about using an deleted type as an lvalue. @@ -756,8 +756,8 @@ def deleted_as_lvalue(self, typ: DeletedType, context: Context) -> None: if typ.source is None: s = "" else: - s = ' "{}"'.format(typ.source) - self.fail('Assignment to variable{} outside except: block'.format(s), context) + s = f' "{typ.source}"' + self.fail(f'Assignment to variable{s} outside except: block', context) def no_variant_matches_arguments(self, overload: Overloaded, @@ -768,13 +768,13 @@ def no_variant_matches_arguments(self, code = code or codes.CALL_OVERLOAD name = callable_name(overload) if name: - name_str = ' of {}'.format(name) + name_str = f' of {name}' else: name_str = '' arg_types_str = ', '.join(format_type(arg) for arg in arg_types) num_args = len(arg_types) if num_args == 0: - self.fail('All overload variants{} require at least one argument'.format(name_str), + self.fail(f'All overload variants{name_str} require at least one argument', context, code=code) elif num_args == 1: self.fail('No overload variant{} matches argument type {}' @@ -784,7 +784,7 @@ def no_variant_matches_arguments(self, .format(name_str, arg_types_str), context, code=code) self.note( - 'Possible overload variant{}:'.format(plural_s(len(overload.items))), + f'Possible overload variant{plural_s(len(overload.items))}:', context, code=code) for item in overload.items: self.note(pretty_callable(item), context, offset=4, code=code) @@ -793,7 +793,7 @@ def wrong_number_values_to_unpack(self, provided: int, expected: int, context: Context) -> None: if provided < expected: if provided == 1: - self.fail('Need more than 1 value to unpack ({} expected)'.format(expected), + self.fail(f'Need more than 1 value to unpack ({expected} expected)', context) else: self.fail('Need more than {} values to unpack ({} expected)'.format( @@ -806,11 +806,11 @@ def unpacking_strings_disallowed(self, context: Context) -> None: self.fail("Unpacking a string is disallowed", context) def type_not_iterable(self, type: Type, context: Context) -> None: - self.fail('{} object is not iterable'.format(format_type(type)), context) + self.fail(f'{format_type(type)} object is not iterable', context) def incompatible_operator_assignment(self, op: str, context: Context) -> None: - self.fail('Result type of {} incompatible in assignment'.format(op), + self.fail(f'Result type of {op} incompatible in assignment', context) def overload_signature_incompatible_with_supertype( @@ -919,9 +919,9 @@ def return_type_incompatible_with_supertype( def override_target(self, name: str, name_in_super: str, supertype: str) -> str: - target = 'supertype "{}"'.format(supertype) + target = f'supertype "{supertype}"' if name_in_super != name: - target = '"{}" of {}'.format(name_in_super, target) + target = f'"{name_in_super}" of {target}' return target def incompatible_type_application(self, expected_arg_count: int, @@ -941,7 +941,7 @@ def could_not_infer_type_arguments(self, callee_type: CallableType, n: int, context: Context) -> None: callee_name = callable_name(callee_type) if callee_name is not None and n > 0: - self.fail('Cannot infer type argument {} of {}'.format(n, callee_name), context) + self.fail(f'Cannot infer type argument {n} of {callee_name}', context) else: self.fail('Cannot infer function type argument', context) @@ -954,11 +954,11 @@ def invalid_keyword_var_arg(self, typ: Type, is_mapping: bool, context: Context) self.fail('Keywords must be strings', context) else: self.fail( - 'Argument after ** must be a mapping, not {}'.format(format_type(typ)), + f'Argument after ** must be a mapping, not {format_type(typ)}', context, code=codes.ARG_TYPE) def undefined_in_superclass(self, member: str, context: Context) -> None: - self.fail('"{}" undefined in superclass'.format(member), context) + self.fail(f'"{member}" undefined in superclass', context) def first_argument_for_super_must_be_type(self, actual: Type, context: Context) -> None: actual = get_proper_type(actual) @@ -968,7 +968,7 @@ def first_argument_for_super_must_be_type(self, actual: Type, context: Context) type_str = 'a non-type instance' else: type_str = format_type(actual) - self.fail('Argument 1 for "super" must be a type object; got {}'.format(type_str), context, + self.fail(f'Argument 1 for "super" must be a type object; got {type_str}', context, code=codes.ARG_TYPE) def too_few_string_formatting_arguments(self, context: Context) -> None: @@ -1010,7 +1010,7 @@ def cannot_determine_type(self, name: str, context: Context) -> None: self.fail('Cannot determine type of "%s"' % name, context, code=codes.HAS_TYPE) def cannot_determine_type_in_base(self, name: str, base: str, context: Context) -> None: - self.fail('Cannot determine type of "%s" in base class "%s"' % (name, base), 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: self.fail('Attribute function "%s" with type %s does not accept self argument' @@ -1050,7 +1050,7 @@ def cant_assign_to_classvar(self, name: str, context: Context) -> None: self.fail('Cannot assign to class variable "%s" via instance' % name, context) def final_cant_override_writable(self, name: str, ctx: Context) -> None: - self.fail('Cannot override writable attribute "{}" with a final one'.format(name), ctx) + self.fail(f'Cannot override writable attribute "{name}" with a final one', ctx) def cant_override_final(self, name: str, base_name: str, ctx: Context) -> None: self.fail('Cannot override final attribute "{}"' @@ -1062,7 +1062,7 @@ def cant_assign_to_final(self, name: str, attr_assign: bool, ctx: Context) -> No Pass `attr_assign=True` if the assignment assigns to an attribute. """ kind = "attribute" if attr_assign else "name" - self.fail('Cannot assign to final {} "{}"'.format(kind, unmangle(name)), ctx) + self.fail(f'Cannot assign to final {kind} "{unmangle(name)}"', ctx) def protocol_members_cant_be_final(self, ctx: Context) -> None: self.fail("Protocol member cannot be final", ctx) @@ -1095,7 +1095,7 @@ def dangerous_comparison(self, left: Type, right: Type, kind: str, ctx: Context) def overload_inconsistently_applies_decorator(self, decorator: str, context: Context) -> None: self.fail( - 'Overload does not consistently use the "@{}" '.format(decorator) + f'Overload does not consistently use the "@{decorator}" ' + 'decorator on all function signatures.', context) @@ -1113,7 +1113,7 @@ def overloaded_signature_will_never_match(self, index1: int, index2: int, context) def overloaded_signatures_typevar_specific(self, index: int, context: Context) -> None: - self.fail('Overloaded function implementation cannot satisfy signature {} '.format(index) + + self.fail(f'Overloaded function implementation cannot satisfy signature {index} ' + 'due to inconsistencies in how they use type variables', context) def overloaded_signatures_arg_specific(self, index: int, context: Context) -> None: @@ -1128,7 +1128,7 @@ def warn_both_operands_are_from_unions(self, context: Context) -> None: self.note('Both left and right operands are unions', context, code=codes.OPERATOR) def warn_operand_was_from_union(self, side: str, original: Type, context: Context) -> None: - self.note('{} operand is of type {}'.format(side, format_type(original)), context, + self.note(f'{side} operand is of type {format_type(original)}', context, code=codes.OPERATOR) def operator_method_signatures_overlap( @@ -1152,19 +1152,19 @@ def signatures_incompatible(self, method: str, other_method: str, def yield_from_invalid_operand_type(self, expr: Type, context: Context) -> Type: text = format_type(expr) if format_type(expr) != 'object' else expr - self.fail('"yield from" can\'t be applied to {}'.format(text), context) + self.fail(f'"yield from" can\'t be applied to {text}', context) return AnyType(TypeOfAny.from_error) def invalid_signature(self, func_type: Type, context: Context) -> None: - self.fail('Invalid signature {}'.format(format_type(func_type)), context) + self.fail(f'Invalid signature {format_type(func_type)}', context) def invalid_signature_for_special_method( self, func_type: Type, context: Context, method_name: str) -> None: - self.fail('Invalid signature {} for "{}"'.format(format_type(func_type), method_name), + self.fail(f'Invalid signature {format_type(func_type)} for "{method_name}"', context) def reveal_type(self, typ: Type, context: Context) -> None: - self.note('Revealed type is "{}"'.format(typ), context) + self.note(f'Revealed type is "{typ}"', context) def reveal_locals(self, type_map: Dict[str, Optional[Type]], context: Context) -> None: # To ensure that the output is predictable on Python < 3.6, @@ -1173,15 +1173,15 @@ def reveal_locals(self, type_map: Dict[str, Optional[Type]], context: Context) - if sorted_locals: self.note("Revealed local types are:", context) for k, v in sorted_locals.items(): - self.note(' {}: {}'.format(k, v), context) + self.note(f' {k}: {v}', context) else: self.note("There are no locals to reveal", context) def unsupported_type_type(self, item: Type, context: Context) -> None: - self.fail('Cannot instantiate type "Type[{}]"'.format(format_type_bare(item)), context) + self.fail(f'Cannot instantiate type "Type[{format_type_bare(item)}]"', context) def redundant_cast(self, typ: Type, context: Context) -> None: - self.fail('Redundant cast to {}'.format(format_type(typ)), context, + self.fail(f'Redundant cast to {format_type(typ)}', context, code=codes.REDUNDANT_CAST) def assert_type_fail(self, source_type: Type, target_type: Type, context: Context) -> None: @@ -1190,7 +1190,7 @@ def assert_type_fail(self, source_type: Type, target_type: Type, context: Contex code=codes.ASSERT_TYPE) def unimported_type_becomes_any(self, prefix: str, typ: Type, ctx: Context) -> None: - self.fail("{} becomes {} due to an unfollowed import".format(prefix, format_type(typ)), + self.fail(f"{prefix} becomes {format_type(typ)} due to an unfollowed import", ctx, code=codes.NO_ANY_UNIMPORTED) def need_annotation_for_var(self, node: SymbolNode, context: Context, @@ -1204,18 +1204,18 @@ def need_annotation_for_var(self, node: SymbolNode, context: Context, alias = alias.split('.')[-1] type_dec = '' if alias == 'Dict': - type_dec = '{}, {}'.format(type_dec, type_dec) + type_dec = f'{type_dec}, {type_dec}' if has_variable_annotations: - hint = ' (hint: "{}: {}[{}] = ...")'.format(node.name, alias, type_dec) + hint = f' (hint: "{node.name}: {alias}[{type_dec}] = ...")' else: - hint = ' (hint: "{} = ... # type: {}[{}]")'.format(node.name, alias, type_dec) + hint = f' (hint: "{node.name} = ... # type: {alias}[{type_dec}]")' if has_variable_annotations: needed = 'annotation' else: needed = 'comment' - self.fail('Need type {} for "{}"{}'.format(needed, unmangle(node.name), hint), context, + self.fail(f'Need type {needed} for "{unmangle(node.name)}"{hint}', context, code=codes.VAR_ANNOTATED) def explicit_any(self, ctx: Context) -> None: @@ -1249,12 +1249,12 @@ def unexpected_typeddict_keys( return found = format_key_list(actual_keys, short=True) if not expected_keys: - self.fail('Unexpected TypedDict {}'.format(found), context) + self.fail(f'Unexpected TypedDict {found}', context) return expected = format_key_list(expected_keys) if actual_keys and actual_set < expected_set: - found = 'only {}'.format(found) - self.fail('Expected {} but found {}'.format(expected, found), context, + found = f'only {found}' + self.fail(f'Expected {expected} but found {found}', context, code=codes.TYPEDDICT_ITEM) def typeddict_key_must_be_string_literal( @@ -1295,7 +1295,7 @@ def typeddict_key_cannot_be_deleted( item_name: str, context: Context) -> None: if typ.is_anonymous(): - self.fail('TypedDict key "{}" cannot be deleted'.format(item_name), + self.fail(f'TypedDict key "{item_name}" cannot be deleted', context) else: self.fail('Key "{}" of TypedDict {} cannot be deleted'.format( @@ -1318,7 +1318,7 @@ def disallowed_any_type(self, typ: Type, context: Context) -> None: if isinstance(typ, AnyType): message = 'Expression has type "Any"' else: - message = 'Expression type contains "Any" (has type {})'.format(format_type(typ)) + message = f'Expression type contains "Any" (has type {format_type(typ)})' self.fail(message, context) def incorrectly_returning_any(self, typ: Type, context: Context) -> None: @@ -1347,7 +1347,7 @@ def untyped_decorated_function(self, typ: Type, context: Context) -> None: format_type(typ)), context) def typed_function_untyped_decorator(self, func_name: str, context: Context) -> None: - self.fail('Untyped decorator makes function "{}" untyped'.format(func_name), context) + self.fail(f'Untyped decorator makes function "{func_name}" untyped', context) def bad_proto_variance(self, actual: int, tvar_name: str, expected: int, context: Context) -> None: @@ -1367,7 +1367,7 @@ def concrete_only_call(self, typ: Type, context: Context) -> None: def cannot_use_function_with_type( self, method_name: str, type_name: str, context: Context) -> None: - self.fail("Cannot use {}() with {} type".format(method_name, type_name), context) + self.fail(f"Cannot use {method_name}() with {type_name} type", context) def report_non_method_protocol(self, tp: TypeInfo, members: List[str], context: Context) -> None: @@ -1396,14 +1396,14 @@ def redundant_left_operand(self, op_name: str, context: Context) -> None: it does not change the truth value of the entire condition as a whole. 'op_name' should either be the string "and" or the string "or". """ - self.redundant_expr('Left operand of "{}"'.format(op_name), op_name == 'and', context) + self.redundant_expr(f'Left operand of "{op_name}"', op_name == 'and', context) def unreachable_right_operand(self, op_name: str, context: Context) -> None: """Indicates that the right operand of a boolean expression is redundant: it does not change the truth value of the entire condition as a whole. 'op_name' should either be the string "and" or the string "or". """ - self.fail('Right operand of "{}" is never evaluated'.format(op_name), + self.fail(f'Right operand of "{op_name}" is never evaluated', context, code=codes.UNREACHABLE) def redundant_condition_in_comprehension(self, truthiness: bool, context: Context) -> None: @@ -1413,7 +1413,7 @@ def redundant_condition_in_if(self, truthiness: bool, context: Context) -> None: self.redundant_expr("If condition", truthiness, context) def redundant_expr(self, description: str, truthiness: bool, context: Context) -> None: - self.fail("{} is always {}".format(description, str(truthiness).lower()), + self.fail(f"{description} is always {str(truthiness).lower()}", context, code=codes.REDUNDANT_EXPR) def impossible_intersection(self, @@ -1628,9 +1628,9 @@ def generate_incompatible_tuple_error(self, .format(str(i), format_type(rhs_t), format_type(lhs_t))) error_cnt += 1 - error_msg = msg + ' ({} tuple items are incompatible'.format(str(error_cnt)) + error_msg = msg + f' ({str(error_cnt)} tuple items are incompatible' if error_cnt - 3 > 0: - error_msg += '; {} items are omitted)'.format(str(error_cnt - 3)) + error_msg += f'; {str(error_cnt - 3)} items are omitted)' else: error_msg += ')' self.fail(error_msg, context, code=code) @@ -1638,7 +1638,7 @@ def generate_incompatible_tuple_error(self, self.note(note, context, code=code) def add_fixture_note(self, fullname: str, ctx: Context) -> None: - self.note('Maybe your test fixture does not define "{}"?'.format(fullname), ctx) + self.note(f'Maybe your test fixture does not define "{fullname}"?', ctx) if fullname in SUGGESTED_TEST_FIXTURES: self.note( 'Consider adding [builtins fixtures/{}] to your test description'.format( @@ -1653,7 +1653,7 @@ def quote_type_string(type_string: str) -> str: # Messages are easier to read if these aren't quoted. We use a # regex to match strings with variable contents. return type_string - return '"{}"'.format(type_string) + return f'"{type_string}"' def format_callable_args(arg_types: List[Type], arg_kinds: List[ArgKind], @@ -1701,7 +1701,7 @@ def format_list(types: Sequence[Type]) -> str: def format_literal_value(typ: LiteralType) -> str: if typ.is_enum_literal(): underlying_type = format(typ.fallback) - return '{}.{}'.format(underlying_type, typ.value) + return f'{underlying_type}.{typ.value}' else: return typ.value_repr() @@ -1723,14 +1723,14 @@ def format_literal_value(typ: LiteralType) -> str: return base_str elif itype.type.fullname == 'builtins.tuple': item_type_str = format(itype.args[0]) - return 'Tuple[{}, ...]'.format(item_type_str) + return f'Tuple[{item_type_str}, ...]' elif itype.type.fullname in reverse_builtin_aliases: alias = reverse_builtin_aliases[itype.type.fullname] alias = alias.split('.')[-1] - return '{}[{}]'.format(alias, format_list(itype.args)) + return f'{alias}[{format_list(itype.args)}]' else: # There are type arguments. Convert the arguments to strings. - return '{}[{}]'.format(base_str, format_list(itype.args)) + return f'{base_str}[{format_list(itype.args)}]' elif isinstance(typ, TypeVarType): # This is similar to non-generic instance types. return typ.name @@ -1751,7 +1751,7 @@ def format_literal_value(typ: LiteralType) -> str: # Prefer the name of the fallback class (if not tuple), as it's more informative. if typ.partial_fallback.type.fullname != 'builtins.tuple': return format(typ.partial_fallback) - s = 'Tuple[{}]'.format(format_list(typ.items)) + s = f'Tuple[{format_list(typ.items)}]' return s elif isinstance(typ, TypedDictType): # If the TypedDictType is named, return the name @@ -1766,7 +1766,7 @@ def format_literal_value(typ: LiteralType) -> str: s = 'TypedDict({{{}}})'.format(', '.join(items)) return s elif isinstance(typ, LiteralType): - return 'Literal[{}]'.format(format_literal_value(typ)) + return f'Literal[{format_literal_value(typ)}]' elif isinstance(typ, UnionType): literal_items, union_items = separate_union_literals(typ) @@ -1778,9 +1778,9 @@ def format_literal_value(typ: LiteralType) -> str: ) if len(union_items) == 1 and isinstance(get_proper_type(union_items[0]), NoneType): - return 'Optional[{}]'.format(literal_str) + return f'Optional[{literal_str}]' elif union_items: - return 'Union[{}, {}]'.format(format_list(union_items), literal_str) + return f'Union[{format_list(union_items)}, {literal_str}]' else: return literal_str else: @@ -1790,9 +1790,9 @@ def format_literal_value(typ: LiteralType) -> str: for t in typ.items) == 1) if print_as_optional: rest = [t for t in typ.items if not isinstance(get_proper_type(t), NoneType)] - return 'Optional[{}]'.format(format(rest[0])) + return f'Optional[{format(rest[0])}]' else: - s = 'Union[{}]'.format(format_list(typ.items)) + s = f'Union[{format_list(typ.items)}]' return s elif isinstance(typ, NoneType): @@ -1807,7 +1807,7 @@ def format_literal_value(typ: LiteralType) -> str: else: return '' elif isinstance(typ, TypeType): - return 'Type[{}]'.format(format(typ.item)) + return f'Type[{format(typ.item)}]' elif isinstance(typ, FunctionLike): func = typ if func.is_type_obj(): @@ -1820,7 +1820,7 @@ def format_literal_value(typ: LiteralType) -> str: else: return_type = format(func.ret_type) if func.is_ellipsis_args: - return 'Callable[..., {}]'.format(return_type) + return f'Callable[..., {return_type}]' param_spec = func.param_spec() if param_spec is not None: return f'Callable[{format(param_spec)}, {return_type}]' @@ -1830,7 +1830,7 @@ def format_literal_value(typ: LiteralType) -> str: func.arg_names, format, verbosity) - return 'Callable[[{}], {}]'.format(args, return_type) + return f'Callable[[{args}], {return_type}]' else: # Use a simple representation for function types; proper # function types may result in long and difficult-to-read @@ -1884,8 +1884,8 @@ def find_type_overlaps(*types: Type) -> Set[str]: for inst in collect_all_instances(type): d.setdefault(inst.type.name, set()).add(inst.type.fullname) for shortname in d.keys(): - if 'typing.{}'.format(shortname) in TYPES_FOR_UNIMPORTED_HINTS: - d[shortname].add('typing.{}'.format(shortname)) + if f'typing.{shortname}' in TYPES_FOR_UNIMPORTED_HINTS: + d[shortname].add(f'typing.{shortname}') overlaps: Set[str] = set() for fullnames in d.values(): @@ -1993,20 +1993,20 @@ def [T <: int] f(self, x: int, y: T) -> None if s: s = ', ' + s s = definition_args[0] + s - s = '{}({})'.format(tp.definition.name, s) + s = f'{tp.definition.name}({s})' elif tp.name: first_arg = tp.def_extras.get('first_arg') if first_arg: if s: s = ', ' + s s = first_arg + s - s = '{}({})'.format(tp.name.split()[0], s) # skip "of Class" part + s = f'{tp.name.split()[0]}({s})' # skip "of Class" part else: - s = '({})'.format(s) + s = f'({s})' s += ' -> ' if tp.type_guard is not None: - s += 'TypeGuard[{}]'.format(format_type_bare(tp.type_guard)) + s += f'TypeGuard[{format_type_bare(tp.type_guard)}]' else: s += format_type_bare(tp.ret_type) @@ -2017,7 +2017,7 @@ def [T <: int] f(self, x: int, y: T) -> None upper_bound = get_proper_type(tvar.upper_bound) if (isinstance(upper_bound, Instance) and upper_bound.type.fullname != 'builtins.object'): - tvars.append('{} <: {}'.format(tvar.name, format_type_bare(upper_bound))) + tvars.append(f'{tvar.name} <: {format_type_bare(upper_bound)}') elif tvar.values: tvars.append('{} in ({})' .format(tvar.name, ', '.join([format_type_bare(tp) @@ -2028,7 +2028,7 @@ def [T <: int] f(self, x: int, y: T) -> None # For other TypeVarLikeTypes, just use the repr tvars.append(repr(tvar)) s = '[{}] {}'.format(', '.join(tvars), s) - return 'def {}'.format(s) + return f'def {s}' def variance_string(variance: int) -> str: @@ -2134,7 +2134,7 @@ def format_string_list(lst: List[str]) -> str: if len(lst) == 1: return lst[0] elif len(lst) <= 5: - return '%s and %s' % (', '.join(lst[:-1]), lst[-1]) + return '{} and {}'.format(', '.join(lst[:-1]), lst[-1]) else: return '%s, ... and %s (%i methods suppressed)' % ( ', '.join(lst[:2]), lst[-1], len(lst) - 3) @@ -2151,14 +2151,14 @@ def format_item_name_list(s: Iterable[str]) -> str: def callable_name(type: FunctionLike) -> Optional[str]: name = type.get_name() if name is not None and name[0] != '<': - return '"{}"'.format(name).replace(' of ', '" of "') + return f'"{name}"'.replace(' of ', '" of "') return name def for_function(callee: CallableType) -> str: name = callable_name(callee) if name is not None: - return ' for {}'.format(name) + return f' for {name}' return '' @@ -2194,7 +2194,7 @@ def pretty_seq(args: Sequence[str], conjunction: str) -> str: if len(quoted) == 1: return quoted[0] if len(quoted) == 2: - return "{} {} {}".format(quoted[0], conjunction, quoted[1]) + return f"{quoted[0]} {conjunction} {quoted[1]}" last_sep = ", " + conjunction + " " return ", ".join(quoted[:-1]) + last_sep + quoted[-1] @@ -2218,7 +2218,7 @@ def append_invariance_notes(notes: List[str], arg_type: Instance, 'which is covariant in the value type') if invariant_type and covariant_suggestion: notes.append( - '"{}" is invariant -- see '.format(invariant_type) + + f'"{invariant_type}" is invariant -- see ' + "https://mypy.readthedocs.io/en/stable/common_issues.html#variance") notes.append(covariant_suggestion) return notes @@ -2256,11 +2256,11 @@ def make_inferred_type_note(context: Context, def format_key_list(keys: List[str], *, short: bool = False) -> str: - formatted_keys = ['"{}"'.format(key) for key in keys] + formatted_keys = [f'"{key}"' for key in keys] td = '' if short else 'TypedDict ' if len(keys) == 0: - return 'no {}keys'.format(td) + return f'no {td}keys' elif len(keys) == 1: - return '{}key {}'.format(td, formatted_keys[0]) + return f'{td}key {formatted_keys[0]}' else: return '{}keys ({})'.format(td, ', '.join(formatted_keys)) diff --git a/mypy/metastore.py b/mypy/metastore.py index 3d4cdeff34006..29f1bbba2feb1 100644 --- a/mypy/metastore.py +++ b/mypy/metastore.py @@ -95,7 +95,7 @@ def read(self, name: str) -> str: if not self.cache_dir_prefix: raise FileNotFoundError() - with open(os.path.join(self.cache_dir_prefix, name), 'r') as f: + with open(os.path.join(self.cache_dir_prefix, name)) as f: return f.read() def write(self, name: str, data: str, mtime: Optional[float] = None) -> bool: @@ -179,7 +179,7 @@ def _query(self, name: str, field: str) -> Any: if not self.db: raise FileNotFoundError() - cur = self.db.execute('SELECT {} FROM files WHERE path = ?'.format(field), (name,)) + cur = self.db.execute(f'SELECT {field} FROM files WHERE path = ?', (name,)) results = cur.fetchall() if not results: raise FileNotFoundError() diff --git a/mypy/modulefinder.py b/mypy/modulefinder.py index 94d2dd34c16e7..bee99156a5701 100644 --- a/mypy/modulefinder.py +++ b/mypy/modulefinder.py @@ -25,14 +25,18 @@ from mypy.stubinfo import is_legacy_bundled_package from mypy import pyinfo + # Paths to be searched in find_module(). SearchPaths = NamedTuple( 'SearchPaths', - [('python_path', Tuple[str, ...]), # where user code is found - ('mypy_path', Tuple[str, ...]), # from $MYPYPATH or config variable - ('package_path', Tuple[str, ...]), # from get_site_packages_dirs() - ('typeshed_path', Tuple[str, ...]), # paths in typeshed - ]) + [ + ('python_path', Tuple[str, ...]), # where user code is found + ('mypy_path', Tuple[str, ...]), # from $MYPYPATH or config variable + ('package_path', Tuple[str, ...]), # from get_site_packages_dirs() + ('typeshed_path', Tuple[str, ...]), # paths in typeshed + ] +) + # Package dirs are a two-tuple of path to search and whether to verify the module OnePackageDir = Tuple[str, bool] @@ -113,7 +117,7 @@ def __init__(self, path: Optional[str], module: Optional[str], self.base_dir = base_dir # Directory where the package is rooted (e.g. 'xxx/yyy') def __repr__(self) -> str: - return 'BuildSource(path=%r, module=%r, has_text=%s, base_dir=%r)' % ( + return 'BuildSource(path={!r}, module={!r}, has_text={}, base_dir={!r})'.format( self.path, self.module, self.text is not None, @@ -526,7 +530,7 @@ def matches_exclude(subpath: str, for exclude in excludes: if re.search(exclude, subpath_str): if verbose: - print("TRACE: Excluding {} (matches pattern {})".format(subpath_str, exclude), + print(f"TRACE: Excluding {subpath_str} (matches pattern {exclude})", file=sys.stderr) return True return False @@ -538,7 +542,7 @@ def verify_module(fscache: FileSystemCache, id: str, path: str, prefix: str) -> path = os.path.dirname(path) for i in range(id.count('.')): path = os.path.dirname(path) - if not any(fscache.isfile_case(os.path.join(path, '__init__{}'.format(extension)), + if not any(fscache.isfile_case(os.path.join(path, f'__init__{extension}'), prefix) for extension in PYTHON_EXTENSIONS): return False @@ -552,7 +556,7 @@ def highest_init_level(fscache: FileSystemCache, id: str, path: str, prefix: str level = 0 for i in range(id.count('.')): path = os.path.dirname(path) - if any(fscache.isfile_case(os.path.join(path, '__init__{}'.format(extension)), + if any(fscache.isfile_case(os.path.join(path, f'__init__{extension}'), prefix) for extension in PYTHON_EXTENSIONS): level = i + 1 @@ -601,7 +605,7 @@ def default_lib_path(data_dir: str, path.append('/usr/local/lib/mypy') if not path: print("Could not resolve typeshed subdirectories. Your mypy install is broken.\n" - "Python executable is located at {0}.\nMypy located at {1}".format( + "Python executable is located at {}.\nMypy located at {}".format( sys.executable, data_dir), file=sys.stderr) sys.exit(1) return path @@ -672,7 +676,7 @@ def _parse_pth_file(dir: str, pth_filename: str) -> Iterator[str]: pth_file = os.path.join(dir, pth_filename) try: - f = open(pth_file, "r") + f = open(pth_file) except OSError: return with f: @@ -789,7 +793,7 @@ def compute_search_paths(sources: List[BuildSource], if (site_dir in mypypath or any(p.startswith(site_dir + os.path.sep) for p in mypypath) or os.path.altsep and any(p.startswith(site_dir + os.path.altsep) for p in mypypath)): - print("{} is in the MYPYPATH. Please remove it.".format(site_dir), file=sys.stderr) + print(f"{site_dir} is in the MYPYPATH. Please remove it.", file=sys.stderr) print("See https://mypy.readthedocs.io/en/stable/running_mypy.html" "#how-mypy-handles-imports for more info", file=sys.stderr) sys.exit(1) diff --git a/mypy/mro.py b/mypy/mro.py index 2aeb96e4e7563..1bea83c6d97d5 100644 --- a/mypy/mro.py +++ b/mypy/mro.py @@ -11,7 +11,7 @@ def calculate_mro(info: TypeInfo, obj_type: Optional[Callable[[], Instance]] = N Raise MroError if cannot determine mro. """ mro = linearize_hierarchy(info, obj_type) - assert mro, "Could not produce a MRO at all for %s" % (info,) + assert mro, f"Could not produce a MRO at all for {info}" info.mro = mro # The property of falling back to Any is inherited. info.fallback_to_any = any(baseinfo.fallback_to_any for baseinfo in info.mro) @@ -36,7 +36,7 @@ def linearize_hierarchy(info: TypeInfo, bases = [obj_type().type] lin_bases = [] for base in bases: - assert base is not None, "Cannot linearize bases for %s %s" % (info.fullname, bases) + assert base is not None, f"Cannot linearize bases for {info.fullname} {bases}" lin_bases.append(linearize_hierarchy(base, obj_type)) lin_bases.append(bases) return [info] + merge(lin_bases) diff --git a/mypy/nodes.py b/mypy/nodes.py index 5a27783e97e1e..c0e53ea9367c9 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -254,7 +254,7 @@ def deserialize(cls, data: JsonDict) -> 'SymbolNode': method = deserialize_map.get(classname) if method is not None: return method(data) - raise NotImplementedError('unexpected .class {}'.format(classname)) + raise NotImplementedError(f'unexpected .class {classname}') # Items: fullname, related symbol table node, surrounding type (if any) @@ -1660,7 +1660,7 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: return visitor.visit_name_expr(self) def serialize(self) -> JsonDict: - assert False, "Serializing NameExpr: %s" % (self,) + assert False, f"Serializing NameExpr: {self}" class MemberExpr(RefExpr): @@ -2868,18 +2868,18 @@ def type_str(typ: 'mypy.types.Type') -> str: description = name + str_conv.format_id(self.names[name].node) node = self.names[name].node if isinstance(node, Var) and node.type: - description += ' ({})'.format(type_str(node.type)) + description += f' ({type_str(node.type)})' names.append(description) items = [ - 'Name({})'.format(self.fullname), + f'Name({self.fullname})', base, mro, ('Names', names), ] if self.declared_metaclass: - items.append('DeclaredMetaclass({})'.format(type_str(self.declared_metaclass))) + items.append(f'DeclaredMetaclass({type_str(self.declared_metaclass)})') if self.metaclass_type: - items.append('MetaclassType({})'.format(type_str(self.metaclass_type))) + items.append(f'MetaclassType({type_str(self.metaclass_type)})') return mypy.strconv.dump_tagged( items, head, @@ -3328,12 +3328,12 @@ def copy(self) -> 'SymbolTableNode': return new def __str__(self) -> str: - s = '{}/{}'.format(node_kinds[self.kind], short_type(self.node)) + s = f'{node_kinds[self.kind]}/{short_type(self.node)}' if isinstance(self.node, SymbolNode): - s += ' ({})'.format(self.node.fullname) + s += f' ({self.node.fullname})' # Include declared type of variables and functions. if self.type is not None: - s += ' : {}'.format(self.type) + s += f' : {self.type}' return s def serialize(self, prefix: str, name: str) -> JsonDict: @@ -3358,7 +3358,7 @@ def serialize(self, prefix: str, name: str) -> JsonDict: if isinstance(self.node, MypyFile): data['cross_ref'] = self.node.fullname else: - assert self.node is not None, '%s:%s' % (prefix, name) + assert self.node is not None, f'{prefix}:{name}' if prefix is not None: fullname = self.node.fullname if (fullname is not None and '.' in fullname @@ -3366,7 +3366,7 @@ def serialize(self, prefix: str, name: str) -> JsonDict: and not (isinstance(self.node, Var) and self.node.from_module_getattr)): assert not isinstance(self.node, PlaceholderNode), ( - 'Definition of {} is unexpectedly incomplete'.format(fullname) + f'Definition of {fullname} is unexpectedly incomplete' ) data['cross_ref'] = fullname return data @@ -3468,7 +3468,7 @@ def get_member_expr_fullname(expr: MemberExpr) -> Optional[str]: initial = get_member_expr_fullname(expr.expr) else: return None - return '{}.{}'.format(initial, expr.name) + return f'{initial}.{expr.name}' deserialize_map: Final = { @@ -3519,7 +3519,7 @@ def check_arg_names(names: Sequence[Optional[str]], nodes: List[T], fail: Callab seen_names: Set[Optional[str]] = set() for name, node in zip(names, nodes): if name is not None and name in seen_names: - fail('Duplicate argument "{}" in {}'.format(name, description), node) + fail(f'Duplicate argument "{name}" in {description}', node) break seen_names.add(name) diff --git a/mypy/operators.py b/mypy/operators.py index aa26cb2ec6e94..85cbfcb99528c 100644 --- a/mypy/operators.py +++ b/mypy/operators.py @@ -51,7 +51,7 @@ ">>", } -inplace_operator_methods: Final = set("__i" + op_methods[op][2:] for op in ops_with_inplace_method) +inplace_operator_methods: Final = {"__i" + op_methods[op][2:] for op in ops_with_inplace_method} reverse_op_methods: Final = { '__add__': '__radd__', @@ -99,7 +99,7 @@ '__rshift__', } -normal_from_reverse_op: Final = dict((m, n) for n, m in reverse_op_methods.items()) +normal_from_reverse_op: Final = {m: n for n, m in reverse_op_methods.items()} reverse_op_method_set: Final = set(reverse_op_methods.values()) unary_op_methods: Final = { diff --git a/mypy/options.py b/mypy/options.py index 4cb2434958f42..b8bc53feb89cb 100644 --- a/mypy/options.py +++ b/mypy/options.py @@ -325,7 +325,7 @@ def snapshot(self) -> object: return d def __repr__(self) -> str: - return 'Options({})'.format(pprint.pformat(self.snapshot())) + return f'Options({pprint.pformat(self.snapshot())})' def apply_changes(self, changes: Dict[str, object]) -> 'Options': new_options = Options() diff --git a/mypy/plugin.py b/mypy/plugin.py index dfa446521548b..74a62d6510d29 100644 --- a/mypy/plugin.py +++ b/mypy/plugin.py @@ -175,11 +175,10 @@ def analyze_callable_args(self, arglist: TypeList) -> Optional[Tuple[List[Type], # A context for a hook that semantically analyzes an unbound type. -AnalyzeTypeContext = NamedTuple( - 'AnalyzeTypeContext', [ - ('type', UnboundType), # Type to analyze - ('context', Context), # Relevant location context (e.g. for error messages) - ('api', TypeAnalyzerPluginInterface)]) +class AnalyzeTypeContext(NamedTuple): + type: UnboundType # Type to analyze + context: Context # Relevant location context (e.g. for error messages) + api: TypeAnalyzerPluginInterface @mypyc_attr(allow_interpreted_subclasses=True) @@ -384,100 +383,96 @@ def is_stub_file(self) -> bool: # A context for querying for configuration data about a module for # cache invalidation purposes. -ReportConfigContext = NamedTuple( - 'ReportConfigContext', [ - ('id', str), # Module name - ('path', str), # Module file path - ('is_check', bool) # Is this invocation for checking whether the config matches - ]) +class ReportConfigContext(NamedTuple): + id: str # Module name + path: str # Module file path + is_check: bool # Is this invocation for checking whether the config matches + # A context for a function signature hook that infers a better signature for a # function. Note that argument types aren't available yet. If you need them, # you have to use a method hook instead. -FunctionSigContext = NamedTuple( - 'FunctionSigContext', [ - ('args', List[List[Expression]]), # Actual expressions for each formal argument - ('default_signature', CallableType), # Original signature of the method - ('context', Context), # Relevant location context (e.g. for error messages) - ('api', CheckerPluginInterface)]) +class FunctionSigContext(NamedTuple): + args: List[List[Expression]] # Actual expressions for each formal argument + default_signature: CallableType # Original signature of the method + context: Context # Relevant location context (e.g. for error messages) + api: CheckerPluginInterface + # A context for a function hook that infers the return type of a function with # a special signature. # # A no-op callback would just return the inferred return type, but a useful # callback at least sometimes can infer a more precise type. -FunctionContext = NamedTuple( - 'FunctionContext', [ - ('arg_types', List[List[Type]]), # List of actual caller types for each formal argument - ('arg_kinds', List[List[ArgKind]]), # Ditto for argument kinds, see nodes.ARG_* constants - # Names of formal parameters from the callee definition, - # these will be sufficient in most cases. - ('callee_arg_names', List[Optional[str]]), - # Names of actual arguments in the call expression. For example, - # in a situation like this: - # def func(**kwargs) -> None: - # pass - # func(kw1=1, kw2=2) - # callee_arg_names will be ['kwargs'] and arg_names will be [['kw1', 'kw2']]. - ('arg_names', List[List[Optional[str]]]), - ('default_return_type', Type), # Return type inferred from signature - ('args', List[List[Expression]]), # Actual expressions for each formal argument - ('context', Context), # Relevant location context (e.g. for error messages) - ('api', CheckerPluginInterface)]) +class FunctionContext(NamedTuple): + arg_types: List[List[Type]] # List of actual caller types for each formal argument + arg_kinds: List[List[ArgKind]] # Ditto for argument kinds, see nodes.ARG_* constants + # Names of formal parameters from the callee definition, + # these will be sufficient in most cases. + callee_arg_names: List[Optional[str]] + # Names of actual arguments in the call expression. For example, + # in a situation like this: + # def func(**kwargs) -> None: + # pass + # func(kw1=1, kw2=2) + # callee_arg_names will be ['kwargs'] and arg_names will be [['kw1', 'kw2']]. + arg_names: List[List[Optional[str]]] + default_return_type: Type # Return type inferred from signature + args: List[List[Expression]] # Actual expressions for each formal argument + context: Context # Relevant location context (e.g. for error messages) + api: CheckerPluginInterface + # A context for a method signature hook that infers a better signature for a # method. Note that argument types aren't available yet. If you need them, # you have to use a method hook instead. # TODO: document ProperType in the plugin changelog/update issue. -MethodSigContext = NamedTuple( - 'MethodSigContext', [ - ('type', ProperType), # Base object type for method call - ('args', List[List[Expression]]), # Actual expressions for each formal argument - ('default_signature', CallableType), # Original signature of the method - ('context', Context), # Relevant location context (e.g. for error messages) - ('api', CheckerPluginInterface)]) +class MethodSigContext(NamedTuple): + type: ProperType # Base object type for method call + args: List[List[Expression]] # Actual expressions for each formal argument + default_signature: CallableType # Original signature of the method + context: Context # Relevant location context (e.g. for error messages) + api: CheckerPluginInterface + # A context for a method hook that infers the return type of a method with a # special signature. # # This is very similar to FunctionContext (only differences are documented). -MethodContext = NamedTuple( - 'MethodContext', [ - ('type', ProperType), # Base object type for method call - ('arg_types', List[List[Type]]), # List of actual caller types for each formal argument - # see FunctionContext for details about names and kinds - ('arg_kinds', List[List[ArgKind]]), - ('callee_arg_names', List[Optional[str]]), - ('arg_names', List[List[Optional[str]]]), - ('default_return_type', Type), # Return type inferred by mypy - ('args', List[List[Expression]]), # Lists of actual expressions for every formal argument - ('context', Context), - ('api', CheckerPluginInterface)]) +class MethodContext(NamedTuple): + type: ProperType # Base object type for method call + arg_types: List[List[Type]] # List of actual caller types for each formal argument + # see FunctionContext for details about names and kinds + arg_kinds: List[List[ArgKind]] + callee_arg_names: List[Optional[str]] + arg_names: List[List[Optional[str]]] + default_return_type: Type # Return type inferred by mypy + args: List[List[Expression]] # Lists of actual expressions for every formal argument + context: Context + api: CheckerPluginInterface + # A context for an attribute type hook that infers the type of an attribute. -AttributeContext = NamedTuple( - 'AttributeContext', [ - ('type', ProperType), # Type of object with attribute - ('default_attr_type', Type), # Original attribute type - ('context', Context), # Relevant location context (e.g. for error messages) - ('api', CheckerPluginInterface)]) +class AttributeContext(NamedTuple): + type: ProperType # Type of object with attribute + default_attr_type: Type # Original attribute type + context: Context # Relevant location context (e.g. for error messages) + api: CheckerPluginInterface + # A context for a class hook that modifies the class definition. -ClassDefContext = NamedTuple( - 'ClassDefContext', [ - ('cls', ClassDef), # The class definition - ('reason', Expression), # The expression being applied (decorator, metaclass, base class) - ('api', SemanticAnalyzerPluginInterface) - ]) +class ClassDefContext(NamedTuple): + cls: ClassDef # The class definition + reason: Expression # The expression being applied (decorator, metaclass, base class) + api: SemanticAnalyzerPluginInterface + # A context for dynamic class definitions like # Base = declarative_base() -DynamicClassDefContext = NamedTuple( - 'DynamicClassDefContext', [ - ('call', CallExpr), # The r.h.s. of dynamic class definition - ('name', str), # The name this class is being assigned to - ('api', SemanticAnalyzerPluginInterface) - ]) +class DynamicClassDefContext(NamedTuple): + call: CallExpr # The r.h.s. of dynamic class definition + name: str # The name this class is being assigned to + api: SemanticAnalyzerPluginInterface @mypyc_attr(allow_interpreted_subclasses=True) diff --git a/mypy/plugins/attrs.py b/mypy/plugins/attrs.py index 0f6431d4700a2..38fd2f040be50 100644 --- a/mypy/plugins/attrs.py +++ b/mypy/plugins/attrs.py @@ -251,7 +251,7 @@ def _get_decorator_optional_bool_argument( return False if attr_value.fullname == 'builtins.None': return None - ctx.api.fail('"{}" argument must be True or False.'.format(name), ctx.reason) + ctx.api.fail(f'"{name}" argument must be True or False.', ctx.reason) return default return default else: @@ -683,7 +683,7 @@ def _make_frozen(ctx: 'mypy.plugin.ClassDefContext', attributes: List[Attribute] # can modify it. var = Var(attribute.name, ctx.cls.info[attribute.name].type) var.info = ctx.cls.info - var._fullname = '%s.%s' % (ctx.cls.info.fullname, var.name) + var._fullname = f'{ctx.cls.info.fullname}.{var.name}' ctx.cls.info.names[var.name] = SymbolTableNode(MDEF, var) var.is_property = True diff --git a/mypy/plugins/common.py b/mypy/plugins/common.py index 90db614404bd2..985a3f0fa6c7b 100644 --- a/mypy/plugins/common.py +++ b/mypy/plugins/common.py @@ -39,7 +39,7 @@ def _get_bool_argument(ctx: ClassDefContext, expr: CallExpr, if attr_value: ret = ctx.api.parse_bool(attr_value) if ret is None: - ctx.api.fail('"{}" argument must be True or False.'.format(name), expr) + ctx.api.fail(f'"{name}" argument must be True or False.', expr) return default return ret return default diff --git a/mypy/plugins/default.py b/mypy/plugins/default.py index acbb0460ae07a..a7fa2cfaa868f 100644 --- a/mypy/plugins/default.py +++ b/mypy/plugins/default.py @@ -37,11 +37,11 @@ def get_method_signature_hook(self, fullname: str if fullname == 'typing.Mapping.get': return typed_dict_get_signature_callback - elif fullname in set(n + '.setdefault' for n in TPDICT_FB_NAMES): + elif fullname in {n + '.setdefault' for n in TPDICT_FB_NAMES}: return typed_dict_setdefault_signature_callback - elif fullname in set(n + '.pop' for n in TPDICT_FB_NAMES): + elif fullname in {n + '.pop' for n in TPDICT_FB_NAMES}: return typed_dict_pop_signature_callback - elif fullname in set(n + '.update' for n in TPDICT_FB_NAMES): + elif fullname in {n + '.update' for n in TPDICT_FB_NAMES}: return typed_dict_update_signature_callback elif fullname == 'ctypes.Array.__setitem__': return ctypes.array_setitem_callback @@ -61,11 +61,11 @@ def get_method_hook(self, fullname: str return int_neg_callback elif fullname in ('builtins.tuple.__mul__', 'builtins.tuple.__rmul__'): return tuple_mul_callback - elif fullname in set(n + '.setdefault' for n in TPDICT_FB_NAMES): + elif fullname in {n + '.setdefault' for n in TPDICT_FB_NAMES}: return typed_dict_setdefault_callback - elif fullname in set(n + '.pop' for n in TPDICT_FB_NAMES): + elif fullname in {n + '.pop' for n in TPDICT_FB_NAMES}: return typed_dict_pop_callback - elif fullname in set(n + '.__delitem__' for n in TPDICT_FB_NAMES): + elif fullname in {n + '.__delitem__' for n in TPDICT_FB_NAMES}: return typed_dict_delitem_callback elif fullname == 'ctypes.Array.__getitem__': return ctypes.array_getitem_callback diff --git a/mypy/plugins/enums.py b/mypy/plugins/enums.py index ea9a02f5b41e4..afd59bf0374d0 100644 --- a/mypy/plugins/enums.py +++ b/mypy/plugins/enums.py @@ -20,11 +20,11 @@ from mypy.subtypes import is_equivalent from mypy.semanal_enum import ENUM_BASES -ENUM_NAME_ACCESS: Final = {"{}.name".format(prefix) for prefix in ENUM_BASES} | { - "{}._name_".format(prefix) for prefix in ENUM_BASES +ENUM_NAME_ACCESS: Final = {f"{prefix}.name" for prefix in ENUM_BASES} | { + f"{prefix}._name_" for prefix in ENUM_BASES } -ENUM_VALUE_ACCESS: Final = {"{}.value".format(prefix) for prefix in ENUM_BASES} | { - "{}._value_".format(prefix) for prefix in ENUM_BASES +ENUM_VALUE_ACCESS: Final = {f"{prefix}.value" for prefix in ENUM_BASES} | { + f"{prefix}._value_" for prefix in ENUM_BASES } @@ -75,8 +75,8 @@ def _infer_value_type_with_auto_fallback( """ if proper_type is None: return None - if not ((isinstance(proper_type, Instance) and - proper_type.type.fullname == 'enum.auto')): + if not (isinstance(proper_type, Instance) and + proper_type.type.fullname == 'enum.auto'): return proper_type assert isinstance(ctx.type, Instance), 'An incorrect ctx.type was passed.' info = ctx.type.type diff --git a/mypy/plugins/functools.py b/mypy/plugins/functools.py index e52d478927e8c..9e4d24283049c 100644 --- a/mypy/plugins/functools.py +++ b/mypy/plugins/functools.py @@ -20,7 +20,9 @@ } -_MethodInfo = NamedTuple('_MethodInfo', [('is_static', bool), ('type', CallableType)]) +class _MethodInfo(NamedTuple): + is_static: bool + type: CallableType def functools_total_ordering_maker_callback(ctx: mypy.plugin.ClassDefContext, diff --git a/mypy/plugins/singledispatch.py b/mypy/plugins/singledispatch.py index f4b3d7c19425c..0eb855d3a3150 100644 --- a/mypy/plugins/singledispatch.py +++ b/mypy/plugins/singledispatch.py @@ -12,21 +12,22 @@ from typing import List, NamedTuple, Optional, Sequence, TypeVar, Union from typing_extensions import Final -SingledispatchTypeVars = NamedTuple('SingledispatchTypeVars', [ - ('return_type', Type), - ('fallback', CallableType), -]) -RegisterCallableInfo = NamedTuple('RegisterCallableInfo', [ - ('register_type', Type), - ('singledispatch_obj', Instance), -]) +class SingledispatchTypeVars(NamedTuple): + return_type: Type + fallback: CallableType + + +class RegisterCallableInfo(NamedTuple): + register_type: Type + singledispatch_obj: Instance + SINGLEDISPATCH_TYPE: Final = 'functools._SingleDispatchCallable' -SINGLEDISPATCH_REGISTER_METHOD: Final = '{}.register'.format(SINGLEDISPATCH_TYPE) +SINGLEDISPATCH_REGISTER_METHOD: Final = f'{SINGLEDISPATCH_TYPE}.register' -SINGLEDISPATCH_CALLABLE_CALL_METHOD: Final = '{}.__call__'.format(SINGLEDISPATCH_TYPE) +SINGLEDISPATCH_CALLABLE_CALL_METHOD: Final = f'{SINGLEDISPATCH_TYPE}.__call__' def get_singledispatch_info(typ: Instance) -> Optional[SingledispatchTypeVars]: @@ -55,7 +56,7 @@ def get_first_arg(args: List[List[T]]) -> Optional[T]: def make_fake_register_class_instance(api: CheckerPluginInterface, type_args: Sequence[Type] ) -> Instance: defn = ClassDef(REGISTER_RETURN_CLASS, Block([])) - defn.fullname = 'functools.{}'.format(REGISTER_RETURN_CLASS) + defn.fullname = f'functools.{REGISTER_RETURN_CLASS}' info = TypeInfo(SymbolTable(), defn, "functools") obj_type = api.named_generic_type('builtins.object', []).type info.bases = [Instance(obj_type, [])] diff --git a/mypy/report.py b/mypy/report.py index 23b5c78ef9298..8d3465f3c1f0b 100644 --- a/mypy/report.py +++ b/mypy/report.py @@ -131,8 +131,7 @@ def should_skip_path(path: str) -> bool: def iterate_python_lines(path: str) -> Iterator[Tuple[int, str]]: """Return an iterator over (line number, line text) from a Python file.""" with tokenize.open(path) as input_file: - for line_info in enumerate(input_file, 1): - yield line_info + yield from enumerate(input_file, 1) class FuncCounterVisitor(TraverserVisitor): @@ -262,10 +261,10 @@ def _report_any_exprs(self) -> None: for filename in sorted(self.counts): (num_any, num_total) = self.counts[filename] coverage = (float(num_total - num_any) / float(num_total)) * 100 - coverage_str = '{:.2f}%'.format(coverage) + coverage_str = f'{coverage:.2f}%' rows.append([filename, str(num_any), str(num_total), coverage_str]) rows.sort(key=lambda x: x[0]) - total_row = ["Total", str(total_any), str(total_expr), '{:.2f}%'.format(total_coverage)] + total_row = ["Total", str(total_any), str(total_expr), f'{total_coverage:.2f}%'] self._write_out_report('any-exprs.txt', column_names, rows, total_row) def _report_types_of_anys(self) -> None: @@ -506,7 +505,7 @@ def _get_any_info_for_line(visitor: stats.StatisticsVisitor, lineno: int) -> str for typ in visitor.any_line_map[lineno]: counter[typ.type_of_any] += 1 for any_type, occurrences in counter.items(): - result += "\n{} (x{})".format(type_of_any_name_map[any_type], occurrences) + result += f"\n{type_of_any_name_map[any_type]} (x{occurrences})" return result else: return "No Anys on this line!" @@ -541,10 +540,10 @@ def get_line_rate(covered_lines: int, total_lines: int) -> str: if total_lines == 0: return str(1.0) else: - return '{:.4f}'.format(covered_lines / total_lines) + return f'{covered_lines / total_lines:.4f}' -class CoberturaPackage(object): +class CoberturaPackage: """Container for XML and statistics mapping python modules to Cobertura package.""" def __init__(self, name: str) -> None: diff --git a/mypy/semanal.py b/mypy/semanal.py index 8b01489589849..eb0411f0afc88 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -460,7 +460,7 @@ def add_implicit_module_attrs(self, file_node: MypyFile) -> None: assert isinstance(node, TypeInfo) typ = Instance(node, [self.str_type(), AnyType(TypeOfAny.special_form)]) else: - assert t is not None, 'type should be specified for {}'.format(name) + assert t is not None, f'type should be specified for {name}' typ = UnboundType(t) existing = file_node.names.get(name) @@ -924,7 +924,7 @@ def process_static_or_class_method_in_overload(self, defn: OverloadedFuncDef) -> elif isinstance(item, FuncDef): inner = item else: - assert False, "The 'item' variable is an unexpected type: {}".format(type(item)) + assert False, f"The 'item' variable is an unexpected type: {type(item)}" class_status.append(inner.is_class) static_status.append(inner.is_static) @@ -934,7 +934,7 @@ def process_static_or_class_method_in_overload(self, defn: OverloadedFuncDef) -> elif isinstance(defn.impl, FuncDef): inner = defn.impl else: - assert False, "Unexpected impl type: {}".format(type(defn.impl)) + assert False, f"Unexpected impl type: {type(defn.impl)}" class_status.append(inner.is_class) static_status.append(inner.is_static) @@ -969,7 +969,7 @@ def analyze_property_with_multi_part_definition(self, defn: OverloadedFuncDef) - self.fail("Decorated property not supported", item) item.func.accept(self) else: - self.fail('Unexpected definition for property "{}"'.format(first_item.func.name), + self.fail(f'Unexpected definition for property "{first_item.func.name}"', item) deleted_items.append(i + 1) for i in reversed(deleted_items): @@ -1536,7 +1536,7 @@ def analyze_base_classes( else: msg = 'Invalid base class' if name: - msg += ' "{}"'.format(name) + msg += f' "{name}"' self.fail(msg, base_expr) is_error = True continue @@ -1570,7 +1570,7 @@ def configure_base_classes(self, elif isinstance(base, AnyType): if self.options.disallow_subclassing_any: if isinstance(base_expr, (NameExpr, MemberExpr)): - msg = 'Class cannot subclass "{}" (has type "Any")'.format(base_expr.name) + msg = f'Class cannot subclass "{base_expr.name}" (has type "Any")' else: msg = 'Class cannot subclass value of type "Any"' self.fail(msg, base_expr) @@ -1579,12 +1579,12 @@ def configure_base_classes(self, msg = 'Invalid base class' name = self.get_name_repr_of_expr(base_expr) if name: - msg += ' "{}"'.format(name) + msg += f' "{name}"' self.fail(msg, base_expr) info.fallback_to_any = True if self.options.disallow_any_unimported and has_any_from_unimported_type(base): if isinstance(base_expr, (NameExpr, MemberExpr)): - prefix = "Base type {}".format(base_expr.name) + prefix = f"Base type {base_expr.name}" else: prefix = "Base type" self.msg.unimported_type_becomes_any(prefix, base, base_expr) @@ -1942,7 +1942,7 @@ def report_missing_module_attribute( imported_id, context, module_public=module_public, module_hidden=module_hidden ) return - message = 'Module "{}" has no attribute "{}"'.format(import_id, source_id) + message = f'Module "{import_id}" has no attribute "{source_id}"' # Suggest alternatives, if any match is found. module = self.modules.get(import_id) if module: @@ -1954,7 +1954,7 @@ def report_missing_module_attribute( matches = best_matches(source_id, alternatives)[:3] if matches: suggestion = "; maybe {}?".format(pretty_seq(matches, "or")) - message += "{}".format(suggestion) + message += f"{suggestion}" self.fail(message, context, code=codes.ATTR_DEFINED) self.add_unknown_imported_symbol( imported_id, context, target_name=None, module_public=module_public, @@ -1963,7 +1963,7 @@ def report_missing_module_attribute( if import_id == 'typing': # The user probably has a missing definition in a test fixture. Let's verify. - fullname = 'builtins.{}'.format(source_id.lower()) + fullname = f'builtins.{source_id.lower()}' if (self.lookup_fully_qualified_or_none(fullname) is None and fullname in SUGGESTED_TEST_FIXTURES): # Yes. Generate a helpful note. @@ -3126,7 +3126,7 @@ def process_typevar_declaration(self, s: AssignmentStmt) -> bool: if self.options.disallow_any_unimported: for idx, constraint in enumerate(values, start=1): if has_any_from_unimported_type(constraint): - prefix = "Constraint {}".format(idx) + prefix = f"Constraint {idx}" self.msg.unimported_type_becomes_any(prefix, constraint, s) if has_any_from_unimported_type(upper_bound): @@ -3167,11 +3167,11 @@ def check_typevarlike_name(self, call: CallExpr, name: str, context: Context) -> call.callee.name if isinstance(call.callee, NameExpr) else call.callee.fullname ) if len(call.args) < 1: - self.fail("Too few arguments for {}()".format(typevarlike_type), context) + self.fail(f"Too few arguments for {typevarlike_type}()", context) return False if (not isinstance(call.args[0], (StrExpr, BytesExpr, UnicodeExpr)) or not call.arg_kinds[0] == ARG_POS): - self.fail("{}() expects a string literal as first argument".format(typevarlike_type), + self.fail(f"{typevarlike_type}() expects a string literal as first argument", context) return False elif call.args[0].value != name: @@ -3792,7 +3792,7 @@ def visit_global_decl(self, g: GlobalDecl) -> None: self.statement = g for name in g.names: if name in self.nonlocal_decls[-1]: - self.fail('Name "{}" is nonlocal and global'.format(name), g) + self.fail(f'Name "{name}" is nonlocal and global', g) self.global_decls[-1].add(name) def visit_nonlocal_decl(self, d: NonlocalDecl) -> None: @@ -3805,14 +3805,14 @@ def visit_nonlocal_decl(self, d: NonlocalDecl) -> None: if table is not None and name in table: break else: - self.fail('No binding for nonlocal "{}" found'.format(name), d) + self.fail(f'No binding for nonlocal "{name}" found', d) if self.locals[-1] is not None and name in self.locals[-1]: self.fail('Name "{}" is already defined in local ' 'scope before nonlocal declaration'.format(name), d) if name in self.global_decls[-1]: - self.fail('Name "{}" is nonlocal and global'.format(name), d) + self.fail(f'Name "{name}" is nonlocal and global', d) self.nonlocal_decls[-1].add(name) def visit_print_stmt(self, s: PrintStmt) -> None: @@ -4880,9 +4880,9 @@ def add_redefinition(self, symbol.no_serialize = True while True: if i == 1: - new_name = '{}-redefinition'.format(name) + new_name = f'{name}-redefinition' else: - new_name = '{}-redefinition{}'.format(name, i) + new_name = f'{name}-redefinition{i}' existing = names.get(new_name) if existing is None: names[new_name] = symbol @@ -5109,7 +5109,7 @@ def process_placeholder(self, name: str, kind: str, ctx: Context) -> None: self.defer(ctx) def cannot_resolve_name(self, name: str, kind: str, ctx: Context) -> None: - self.fail('Cannot resolve {} "{}" (possible cyclic definition)'.format(kind, name), ctx) + self.fail(f'Cannot resolve {kind} "{name}" (possible cyclic definition)', ctx) def qualified_name(self, name: str) -> str: if self.type is not None: @@ -5217,12 +5217,12 @@ def name_not_defined(self, name: str, ctx: Context, namespace: Optional[str] = N # later on. Defer current target. self.record_incomplete_ref() return - message = 'Name "{}" is not defined'.format(name) + message = f'Name "{name}" is not defined' self.fail(message, ctx, code=codes.NAME_DEFINED) - if 'builtins.{}'.format(name) in SUGGESTED_TEST_FIXTURES: + if f'builtins.{name}' in SUGGESTED_TEST_FIXTURES: # The user probably has a missing definition in a test fixture. Let's verify. - fullname = 'builtins.{}'.format(name) + fullname = f'builtins.{name}' if self.lookup_fully_qualified_or_none(fullname) is None: # Yes. Generate a helpful note. self.msg.add_fixture_note(fullname, ctx) @@ -5236,7 +5236,7 @@ def name_not_defined(self, name: str, ctx: Context, namespace: Optional[str] = N for name in TYPES_FOR_UNIMPORTED_HINTS } for module in modules_with_unimported_hints: - fullname = '{}.{}'.format(module, name).lower() + fullname = f'{module}.{name}'.lower() if fullname not in lowercased: continue # User probably forgot to import these types. @@ -5266,10 +5266,10 @@ def already_defined(self, elif node and node.line != -1 and self.is_local_name(node.fullname): # TODO: Using previous symbol node may give wrong line. We should use # the line number where the binding was established instead. - extra_msg = ' on line {}'.format(node.line) + extra_msg = f' on line {node.line}' else: extra_msg = ' (possibly by an import)' - self.fail('{} "{}" already defined{}'.format(noun, unmangle(name), extra_msg), ctx, + self.fail(f'{noun} "{unmangle(name)}" already defined{extra_msg}', ctx, code=codes.NO_REDEF) def name_already_defined(self, @@ -5457,7 +5457,7 @@ def schedule_patch(self, priority: int, patch: Callable[[], None]) -> None: def report_hang(self) -> None: print('Deferral trace:') for mod, line in self.deferral_debug_context: - print(' {}:{}'.format(mod, line)) + print(f' {mod}:{line}') self.errors.report(-1, -1, 'INTERNAL ERROR: maximum semantic analysis iteration count reached', blocker=True) diff --git a/mypy/semanal_classprop.py b/mypy/semanal_classprop.py index 4be57b64342e1..e985b55a20d1b 100644 --- a/mypy/semanal_classprop.py +++ b/mypy/semanal_classprop.py @@ -105,14 +105,14 @@ def calculate_class_abstract_status(typ: TypeInfo, is_stub_file: bool, errors: E def report(message: str, severity: str) -> None: errors.report(typ.line, typ.column, message, severity=severity) - attrs = ", ".join('"{}"'.format(attr) for attr in sorted(abstract)) - report("Class {} has abstract attributes {}".format(typ.fullname, attrs), 'error') + attrs = ", ".join(f'"{attr}"' for attr in sorted(abstract)) + report(f"Class {typ.fullname} has abstract attributes {attrs}", 'error') report("If it is meant to be abstract, add 'abc.ABCMeta' as an explicit metaclass", 'note') if typ.is_final and abstract: - attrs = ", ".join('"{}"'.format(attr) for attr in sorted(abstract)) + attrs = ", ".join(f'"{attr}"' for attr in sorted(abstract)) errors.report(typ.line, typ.column, - "Final class {} has abstract attributes {}".format(typ.fullname, attrs)) + f"Final class {typ.fullname} has abstract attributes {attrs}") def check_protocol_status(info: TypeInfo, errors: Errors) -> None: diff --git a/mypy/semanal_enum.py b/mypy/semanal_enum.py index 8b5ecf1b1df41..251767bef3e0d 100644 --- a/mypy/semanal_enum.py +++ b/mypy/semanal_enum.py @@ -106,7 +106,7 @@ def build_enum_call_typeinfo(self, name: str, items: List[str], fullname: str, var = Var(item) var.info = info var.is_property = True - var._fullname = '{}.{}'.format(info.fullname, item) + var._fullname = f'{info.fullname}.{item}' info.names[item] = SymbolTableNode(MDEF, var) return info @@ -127,7 +127,7 @@ def parse_enum_call_args(self, call: CallExpr, valid_name = [None, 'value', 'names', 'module', 'qualname', 'type', 'start'] for arg_name in call.arg_names: if arg_name not in valid_name: - self.fail_enum_call_arg('Unexpected keyword argument "{}"'.format(arg_name), call) + self.fail_enum_call_arg(f'Unexpected keyword argument "{arg_name}"', call) value, names = None, None for arg_name, arg in zip(call.arg_names, args): if arg_name == 'value': diff --git a/mypy/semanal_namedtuple.py b/mypy/semanal_namedtuple.py index 2357225caebbe..4e05dfb996053 100644 --- a/mypy/semanal_namedtuple.py +++ b/mypy/semanal_namedtuple.py @@ -266,7 +266,7 @@ def parse_namedtuple_args(self, call: CallExpr, fullname: str # TODO: Share code with check_argument_count in checkexpr.py? args = call.args if len(args) < 2: - self.fail('Too few arguments for "{}()"'.format(type_name), call) + self.fail(f'Too few arguments for "{type_name}()"', call) return None defaults: List[Expression] = [] if len(args) > 2: @@ -289,11 +289,11 @@ def parse_namedtuple_args(self, call: CallExpr, fullname: str ) break if call.arg_kinds[:2] != [ARG_POS, ARG_POS]: - self.fail('Unexpected arguments to "{}()"'.format(type_name), call) + self.fail(f'Unexpected arguments to "{type_name}()"', call) return None if not isinstance(args[0], (StrExpr, BytesExpr, UnicodeExpr)): self.fail( - '"{}()" expects a string literal as the first argument'.format(type_name), call) + f'"{type_name}()" expects a string literal as the first argument', call) return None typename = cast(Union[StrExpr, BytesExpr, UnicodeExpr], call.args[0]).value types: List[Type] = [] @@ -333,10 +333,10 @@ def parse_namedtuple_args(self, call: CallExpr, fullname: str types = [AnyType(TypeOfAny.unannotated) for _ in items] underscore = [item for item in items if item.startswith('_')] if underscore: - self.fail('"{}()" field names cannot start with an underscore: '.format(type_name) + self.fail(f'"{type_name}()" field names cannot start with an underscore: ' + ', '.join(underscore), call) if len(defaults) > len(items): - self.fail('Too many defaults given in call to "{}()"'.format(type_name), call) + self.fail(f'Too many defaults given in call to "{type_name}()"', call) defaults = defaults[:len(items)] return items, types, defaults, typename, True @@ -420,7 +420,7 @@ def add_field(var: Var, is_initialized_in_class: bool = False, var.info = info var.is_initialized_in_class = is_initialized_in_class var.is_property = is_property - var._fullname = '%s.%s' % (info.fullname, var.name) + var._fullname = f'{info.fullname}.{var.name}' info.names[var.name] = SymbolTableNode(MDEF, var) fields = [Var(item, typ) for item, typ in zip(items, types)] @@ -528,7 +528,7 @@ def save_namedtuple_body(self, named_tuple_info: TypeInfo) -> Iterator[None]: continue ctx = named_tuple_info.names[prohibited].node assert ctx is not None - self.fail('Cannot overwrite NamedTuple attribute "{}"'.format(prohibited), + self.fail(f'Cannot overwrite NamedTuple attribute "{prohibited}"', ctx) # Restore the names in the original symbol table. This ensures that the symbol diff --git a/mypy/semanal_shared.py b/mypy/semanal_shared.py index 72a89150bb64d..6d6c4ac9f0d4c 100644 --- a/mypy/semanal_shared.py +++ b/mypy/semanal_shared.py @@ -189,7 +189,7 @@ def set_callable_name(sig: Type, fdef: FuncDef) -> ProperType: else: class_name = fdef.info.name return sig.with_name( - '{} of {}'.format(fdef.name, class_name)) + f'{fdef.name} of {class_name}') else: return sig.with_name(fdef.name) else: diff --git a/mypy/semanal_typeargs.py b/mypy/semanal_typeargs.py index f8e14d28661ac..483154000d1bd 100644 --- a/mypy/semanal_typeargs.py +++ b/mypy/semanal_typeargs.py @@ -121,8 +121,8 @@ def check_type_var_values(self, type: TypeInfo, actuals: List[Type], arg_name: s message_registry.INVALID_TYPEVAR_ARG_VALUE.format(type.name), context, code=codes.TYPE_VAR) else: - class_name = '"{}"'.format(type.name) - actual_type_name = '"{}"'.format(actual.type.name) + class_name = f'"{type.name}"' + actual_type_name = f'"{actual.type.name}"' self.fail( message_registry.INCOMPATIBLE_TYPEVAR_VALUE.format( arg_name, class_name, actual_type_name), diff --git a/mypy/semanal_typeddict.py b/mypy/semanal_typeddict.py index ffc6a7df3931e..3b384bdec1a32 100644 --- a/mypy/semanal_typeddict.py +++ b/mypy/semanal_typeddict.py @@ -156,7 +156,7 @@ def analyze_typeddict_classdef_fields( self.fail('Overwriting TypedDict field "{}" while extending' .format(name), stmt) if name in fields: - self.fail('Duplicate TypedDict key "{}"'.format(name), stmt) + self.fail(f'Duplicate TypedDict key "{name}"', stmt) continue # Append name and type in this case... fields.append(name) @@ -282,7 +282,7 @@ def parse_typeddict_args( return self.fail_typeddict_arg("Unexpected arguments to TypedDict()", call) if len(args) == 3 and call.arg_names[2] != 'total': return self.fail_typeddict_arg( - 'Unexpected keyword argument "{}" for "TypedDict"'.format(call.arg_names[2]), call) + f'Unexpected keyword argument "{call.arg_names[2]}" for "TypedDict"', call) if not isinstance(args[0], (StrExpr, BytesExpr, UnicodeExpr)): return self.fail_typeddict_arg( "TypedDict() expects a string literal as the first argument", call) @@ -328,7 +328,7 @@ def parse_typeddict_fields_with_types( key = field_name_expr.value items.append(key) if key in seen_keys: - self.fail('Duplicate TypedDict key "{}"'.format(key), field_name_expr) + self.fail(f'Duplicate TypedDict key "{key}"', field_name_expr) seen_keys.add(key) else: name_context = field_name_expr or field_type_expr diff --git a/mypy/server/astdiff.py b/mypy/server/astdiff.py index f41a54752fee2..1f3b68fbde1b4 100644 --- a/mypy/server/astdiff.py +++ b/mypy/server/astdiff.py @@ -89,8 +89,8 @@ def compare_symbol_table_snapshots( Return a set of fully-qualified names (e.g., 'mod.func' or 'mod.Class.method'). """ # Find names only defined only in one version. - names1 = {'%s.%s' % (name_prefix, name) for name in snapshot1} - names2 = {'%s.%s' % (name_prefix, name) for name in snapshot2} + names1 = {f'{name_prefix}.{name}' for name in snapshot1} + names2 = {f'{name_prefix}.{name}' for name in snapshot2} triggers = names1 ^ names2 # Look for names defined in both versions that are different. @@ -99,7 +99,7 @@ def compare_symbol_table_snapshots( item2 = snapshot2[name] kind1 = item1[0] kind2 = item2[0] - item_name = '%s.%s' % (name_prefix, name) + item_name = f'{name_prefix}.{name}' if kind1 != kind2: # Different kind of node in two snapshots -> trivially different. triggers.add(item_name) @@ -338,7 +338,7 @@ def visit_callable_type(self, typ: CallableType) -> SnapshotItem: return ('CallableType', snapshot_types(typ.arg_types), snapshot_type(typ.ret_type), - tuple([encode_optional_str(name) for name in typ.arg_names]), + tuple(encode_optional_str(name) for name in typ.arg_names), tuple(typ.arg_kinds), typ.is_type_obj(), typ.is_ellipsis_args) diff --git a/mypy/server/deps.py b/mypy/server/deps.py index c7623ff26c7f8..b70a43db25401 100644 --- a/mypy/server/deps.py +++ b/mypy/server/deps.py @@ -361,20 +361,20 @@ def visit_assignment_stmt(self, o: AssignmentStmt) -> None: elif isinstance(rvalue, CallExpr) and isinstance(rvalue.analyzed, NamedTupleExpr): # Depend on types of named tuple items. info = rvalue.analyzed.info - prefix = '%s.%s' % (self.scope.current_full_target(), info.name) + prefix = f'{self.scope.current_full_target()}.{info.name}' for name, symnode in info.names.items(): if not name.startswith('_') and isinstance(symnode.node, Var): typ = symnode.node.type if typ: self.add_type_dependencies(typ) self.add_type_dependencies(typ, target=make_trigger(prefix)) - attr_target = make_trigger('%s.%s' % (prefix, name)) + attr_target = make_trigger(f'{prefix}.{name}') self.add_type_dependencies(typ, target=attr_target) elif isinstance(rvalue, CallExpr) and isinstance(rvalue.analyzed, TypedDictExpr): # Depend on the underlying typeddict type info = rvalue.analyzed.info assert info.typeddict_type is not None - prefix = '%s.%s' % (self.scope.current_full_target(), info.name) + prefix = f'{self.scope.current_full_target()}.{info.name}' self.add_type_dependencies(info.typeddict_type, target=make_trigger(prefix)) elif isinstance(rvalue, CallExpr) and isinstance(rvalue.analyzed, EnumCallExpr): # Enum values are currently not checked, but for future we add the deps on them @@ -440,7 +440,7 @@ def process_lvalue(self, lvalue: Expression) -> None: # global variable. lvalue_type = self.get_non_partial_lvalue_type(lvalue) type_triggers = self.get_type_triggers(lvalue_type) - attr_trigger = make_trigger('%s.%s' % (self.scope.current_full_target(), + attr_trigger = make_trigger('{}.{}'.format(self.scope.current_full_target(), lvalue.name)) for type_trigger in type_triggers: self.add_dependency(type_trigger, attr_trigger) @@ -827,10 +827,10 @@ def attribute_triggers(self, typ: Type, name: str) -> List[str]: if isinstance(typ, TupleType): typ = typ.partial_fallback if isinstance(typ, Instance): - member = '%s.%s' % (typ.type.fullname, name) + member = f'{typ.type.fullname}.{name}' return [make_trigger(member)] elif isinstance(typ, FunctionLike) and typ.is_type_obj(): - member = '%s.%s' % (typ.type_object().fullname, name) + member = f'{typ.type_object().fullname}.{name}' triggers = [make_trigger(member)] triggers.extend(self.attribute_triggers(typ.fallback, name)) return triggers diff --git a/mypy/server/mergecheck.py b/mypy/server/mergecheck.py index 476d1cc809f7e..2c28242251e90 100644 --- a/mypy/server/mergecheck.py +++ b/mypy/server/mergecheck.py @@ -50,7 +50,8 @@ def check_consistency(o: object) -> None: path2 = get_path(sym2, seen, parents) if fn in m: - print('\nDuplicate %r nodes with fullname %r found:' % (type(sym).__name__, fn)) + print('\nDuplicate {!r} nodes with fullname {!r} found:'.format( + type(sym).__name__, fn)) print('[1] %d: %s' % (id(sym1), path_to_str(path1))) print('[2] %d: %s' % (id(sym2), path_to_str(path2))) @@ -72,11 +73,11 @@ def path_to_str(path: List[Tuple[object, object]]) -> str: result += '[%s]' % repr(attr) else: if isinstance(obj, Var): - result += '.%s(%s:%s)' % (attr, t, obj.name) + result += f'.{attr}({t}:{obj.name})' elif t in ('BuildManager', 'FineGrainedBuildManager'): # Omit class name for some classes that aren't part of a class # hierarchy since there isn't much ambiguity. result += '.%s' % attr else: - result += '.%s(%s)' % (attr, t) + result += f'.{attr}({t})' return result diff --git a/mypy/server/objgraph.py b/mypy/server/objgraph.py index 89f0ba79388bb..236f70d04e38a 100644 --- a/mypy/server/objgraph.py +++ b/mypy/server/objgraph.py @@ -69,8 +69,7 @@ def get_edge_candidates(o: object) -> Iterator[Tuple[object, object]]: except AssertionError: pass if isinstance(o, Mapping): - for k, v in o.items(): - yield k, v + yield from o.items() elif isinstance(o, Iterable) and not isinstance(o, str): for i, e in enumerate(o): yield i, e diff --git a/mypy/server/trigger.py b/mypy/server/trigger.py index c10264766ae65..3b9b02d20c81f 100644 --- a/mypy/server/trigger.py +++ b/mypy/server/trigger.py @@ -21,4 +21,4 @@ def make_wildcard_trigger(module: str) -> str: This is used for "from m import *" dependencies. """ - return '<%s%s>' % (module, WILDCARD_TAG) + return f'<{module}{WILDCARD_TAG}>' diff --git a/mypy/server/update.py b/mypy/server/update.py index 2f57001766d57..233e989a0e367 100644 --- a/mypy/server/update.py +++ b/mypy/server/update.py @@ -493,17 +493,21 @@ def ensure_trees_loaded(manager: BuildManager, graph: Dict[str, State], # - Remaining changed modules that are not processed yet as (module id, path) # tuples (non-empty if the original changed module imported other new # modules) -NormalUpdate = NamedTuple('NormalUpdate', [('module', str), - ('path', str), - ('remaining', List[Tuple[str, str]]), - ('tree', Optional[MypyFile])]) +class NormalUpdate(NamedTuple): + module: str + path: str + remaining: List[Tuple[str, str]] + tree: Optional[MypyFile] + # The result of update_module_isolated when there is a blocking error. Items # are similar to NormalUpdate (but there are fewer). -BlockedUpdate = NamedTuple('BlockedUpdate', [('module', str), - ('path', str), - ('remaining', List[Tuple[str, str]]), - ('messages', List[str])]) +class BlockedUpdate(NamedTuple): + module: str + path: str + remaining: List[Tuple[str, str]] + messages: List[str] + UpdateResult = Union[NormalUpdate, BlockedUpdate] @@ -1128,9 +1132,9 @@ def target_from_node(module: str, return module else: # OverloadedFuncDef or FuncDef if node.info: - return '%s.%s' % (node.info.fullname, node.name) + return f'{node.info.fullname}.{node.name}' else: - return '%s.%s' % (module, node.name) + return f'{module}.{node.name}' if sys.platform != "win32": diff --git a/mypy/strconv.py b/mypy/strconv.py index 1a08423b41648..13f3e04ef712a 100644 --- a/mypy/strconv.py +++ b/mypy/strconv.py @@ -39,7 +39,7 @@ def get_id(self, o: object) -> Optional[int]: def format_id(self, o: object) -> str: if self.id_mapper: - return '<{}>'.format(self.get_id(o)) + return f'<{self.get_id(o)}>' else: return '' @@ -53,7 +53,7 @@ def dump(self, nodes: Sequence[object], obj: 'mypy.nodes.Context') -> str: tag = short_type(obj) + ':' + str(obj.get_line()) if self.show_ids: assert self.id_mapper is not None - tag += '<{}>'.format(self.get_id(obj)) + tag += f'<{self.get_id(obj)}>' return dump_tagged(nodes, tag, self) def func_helper(self, o: 'mypy.nodes.FuncItem') -> List[object]: @@ -109,7 +109,7 @@ def visit_import(self, o: 'mypy.nodes.Import') -> str: a = [] for id, as_id in o.ids: if as_id is not None: - a.append('{} : {}'.format(id, as_id)) + a.append(f'{id} : {as_id}') else: a.append(id) return 'Import:{}({})'.format(o.line, ', '.join(a)) @@ -118,7 +118,7 @@ def visit_import_from(self, o: 'mypy.nodes.ImportFrom') -> str: a = [] for name, as_name in o.names: if as_name is not None: - a.append('{} : {}'.format(name, as_name)) + a.append(f'{name} : {as_name}') else: a.append(name) return 'ImportFrom:{}({}, [{}])'.format(o.line, "." * o.relative + o.id, ', '.join(a)) @@ -133,7 +133,7 @@ def visit_func_def(self, o: 'mypy.nodes.FuncDef') -> str: a.insert(0, o.name) arg_kinds = {arg.kind for arg in o.arguments} if len(arg_kinds & {mypy.nodes.ARG_NAMED, mypy.nodes.ARG_NAMED_OPT}) > 0: - a.insert(1, 'MaxPos({})'.format(o.max_pos)) + a.insert(1, f'MaxPos({o.max_pos})') if o.is_abstract: a.insert(-1, 'Abstract') if o.is_static: @@ -170,11 +170,11 @@ def visit_class_def(self, o: 'mypy.nodes.ClassDef') -> str: if o.type_vars: a.insert(1, ('TypeVars', o.type_vars)) if o.metaclass: - a.insert(1, 'Metaclass({})'.format(o.metaclass)) + a.insert(1, f'Metaclass({o.metaclass})') if o.decorators: a.insert(1, ('Decorators', o.decorators)) if o.info and o.info._promote: - a.insert(1, 'Promote({})'.format(o.info._promote)) + a.insert(1, f'Promote({o.info._promote})') if o.info and o.info.tuple_type: a.insert(1, ('TupleType', [o.info.tuple_type])) if o.info and o.info.fallback_to_any: @@ -329,16 +329,16 @@ def visit_match_stmt(self, o: 'mypy.nodes.MatchStmt') -> str: # Simple expressions def visit_int_expr(self, o: 'mypy.nodes.IntExpr') -> str: - return 'IntExpr({})'.format(o.value) + return f'IntExpr({o.value})' def visit_str_expr(self, o: 'mypy.nodes.StrExpr') -> str: - return 'StrExpr({})'.format(self.str_repr(o.value)) + return f'StrExpr({self.str_repr(o.value)})' def visit_bytes_expr(self, o: 'mypy.nodes.BytesExpr') -> str: - return 'BytesExpr({})'.format(self.str_repr(o.value)) + return f'BytesExpr({self.str_repr(o.value)})' def visit_unicode_expr(self, o: 'mypy.nodes.UnicodeExpr') -> str: - return 'UnicodeExpr({})'.format(self.str_repr(o.value)) + return f'UnicodeExpr({self.str_repr(o.value)})' def str_repr(self, s: str) -> str: s = re.sub(r'\\u[0-9a-fA-F]{4}', lambda m: '\\' + m.group(0), s) @@ -346,10 +346,10 @@ def str_repr(self, s: str) -> str: lambda m: r'\u%.4x' % ord(m.group(0)), s) def visit_float_expr(self, o: 'mypy.nodes.FloatExpr') -> str: - return 'FloatExpr({})'.format(o.value) + return f'FloatExpr({o.value})' def visit_complex_expr(self, o: 'mypy.nodes.ComplexExpr') -> str: - return 'ComplexExpr({})'.format(o.value) + return f'ComplexExpr({o.value})' def visit_ellipsis(self, o: 'mypy.nodes.EllipsisExpr') -> str: return 'Ellipsis' @@ -362,7 +362,7 @@ def visit_name_expr(self, o: 'mypy.nodes.NameExpr') -> str: o.is_inferred_def or o.is_special_form, o.node) if isinstance(o.node, mypy.nodes.Var) and o.node.is_final: - pretty += ' = {}'.format(o.node.final_value) + pretty += f' = {o.node.final_value}' return short_type(o) + '(' + pretty + ')' def pretty_name(self, name: str, kind: Optional[int], fullname: Optional[str], @@ -379,13 +379,13 @@ def pretty_name(self, name: str, kind: Optional[int], fullname: Optional[str], elif kind == mypy.nodes.GDEF or (fullname != name and fullname is not None): # Append fully qualified name for global references. - n += ' [{}{}]'.format(fullname, id) + n += f' [{fullname}{id}]' elif kind == mypy.nodes.LDEF: # Add tag to signify a local reference. - n += ' [l{}]'.format(id) + n += f' [l{id}]' elif kind == mypy.nodes.MDEF: # Add tag to signify a member reference. - n += ' [m{}]'.format(id) + n += f' [m{id}]' else: n += id return n @@ -481,7 +481,7 @@ def visit_type_var_expr(self, o: 'mypy.nodes.TypeVarExpr') -> str: if o.values: a += [('Values', o.values)] if not mypy.types.is_named_instance(o.upper_bound, 'builtins.object'): - a += ['UpperBound({})'.format(o.upper_bound)] + a += [f'UpperBound({o.upper_bound})'] return self.dump(a, o) def visit_paramspec_expr(self, o: 'mypy.nodes.ParamSpecExpr') -> str: @@ -493,7 +493,7 @@ def visit_paramspec_expr(self, o: 'mypy.nodes.ParamSpecExpr') -> str: if o.variance == mypy.nodes.CONTRAVARIANT: a += ['Variance(CONTRAVARIANT)'] if not mypy.types.is_named_instance(o.upper_bound, 'builtins.object'): - a += ['UpperBound({})'.format(o.upper_bound)] + a += [f'UpperBound({o.upper_bound})'] return self.dump(a, o) def visit_type_var_tuple_expr(self, o: 'mypy.nodes.TypeVarTupleExpr') -> str: @@ -505,11 +505,11 @@ def visit_type_var_tuple_expr(self, o: 'mypy.nodes.TypeVarTupleExpr') -> str: if o.variance == mypy.nodes.CONTRAVARIANT: a += ['Variance(CONTRAVARIANT)'] if not mypy.types.is_named_instance(o.upper_bound, 'builtins.object'): - a += ['UpperBound({})'.format(o.upper_bound)] + a += [f'UpperBound({o.upper_bound})'] return self.dump(a, o) def visit_type_alias_expr(self, o: 'mypy.nodes.TypeAliasExpr') -> str: - return 'TypeAliasExpr({})'.format(o.type) + return f'TypeAliasExpr({o.type})' def visit_namedtuple_expr(self, o: 'mypy.nodes.NamedTupleExpr') -> str: return 'NamedTupleExpr:{}({}, {})'.format(o.line, @@ -517,14 +517,14 @@ def visit_namedtuple_expr(self, o: 'mypy.nodes.NamedTupleExpr') -> str: o.info.tuple_type) def visit_enum_call_expr(self, o: 'mypy.nodes.EnumCallExpr') -> str: - return 'EnumCallExpr:{}({}, {})'.format(o.line, o.info.name, o.items) + return f'EnumCallExpr:{o.line}({o.info.name}, {o.items})' def visit_typeddict_expr(self, o: 'mypy.nodes.TypedDictExpr') -> str: return 'TypedDictExpr:{}({})'.format(o.line, o.info.name) def visit__promote_expr(self, o: 'mypy.nodes.PromoteExpr') -> str: - return 'PromoteExpr:{}({})'.format(o.line, o.type) + return f'PromoteExpr:{o.line}({o.type})' def visit_newtype_expr(self, o: 'mypy.nodes.NewTypeExpr') -> str: return 'NewTypeExpr:{}({}, {})'.format(o.line, o.name, diff --git a/mypy/stubdoc.py b/mypy/stubdoc.py index 1c31223d26a10..a596ddb4f78dc 100644 --- a/mypy/stubdoc.py +++ b/mypy/stubdoc.py @@ -52,11 +52,10 @@ def __eq__(self, other: Any) -> bool: return False -FunctionSig = NamedTuple('FunctionSig', [ - ('name', str), - ('args', List[ArgSig]), - ('ret_type', str) -]) +class FunctionSig(NamedTuple): + name: str + args: List[ArgSig] + ret_type: str # States of the docstring parser. @@ -237,7 +236,7 @@ def infer_sig_from_docstring(docstr: Optional[str], name: str) -> Optional[List[ def is_unique_args(sig: FunctionSig) -> bool: """return true if function argument names are unique""" - return len(sig.args) == len(set((arg.name for arg in sig.args))) + return len(sig.args) == len({arg.name for arg in sig.args}) # Return only signatures that have unique argument names. Mypy fails on non-unique arg names. return [sig for sig in sigs if is_unique_args(sig)] diff --git a/mypy/stubgen.py b/mypy/stubgen.py index eade0bbdc363a..41fc58a2b0fce 100755 --- a/mypy/stubgen.py +++ b/mypy/stubgen.py @@ -259,14 +259,14 @@ def visit_unbound_type(self, t: UnboundType) -> str: s = t.name self.stubgen.import_tracker.require_name(s) if t.args: - s += '[{}]'.format(self.args_str(t.args)) + s += f'[{self.args_str(t.args)}]' return s def visit_none_type(self, t: NoneType) -> str: return "None" def visit_type_list(self, t: TypeList) -> str: - return '[{}]'.format(self.list_str(t.items)) + return f'[{self.list_str(t.items)}]' def args_str(self, args: Iterable[Type]) -> str: """Convert an array of arguments to strings and join the results with commas. @@ -279,7 +279,7 @@ def args_str(self, args: Iterable[Type]) -> str: for arg in args: arg_str = arg.accept(self) if isinstance(arg, UnboundType) and arg.original_str_fallback in types: - res.append("'{}'".format(arg_str)) + res.append(f"'{arg_str}'") else: res.append(arg_str) return ', '.join(res) @@ -307,7 +307,7 @@ def visit_call_expr(self, node: CallExpr) -> str: elif kind == ARG_STAR2: args.append('**' + arg.accept(self)) elif kind == ARG_NAMED: - args.append('{}={}'.format(name, arg.accept(self))) + args.append(f'{name}={arg.accept(self)}') else: raise ValueError("Unknown argument kind %s in call" % kind) return "{}({})".format(callee, ", ".join(args)) @@ -333,7 +333,7 @@ def visit_str_expr(self, node: StrExpr) -> str: def visit_index_expr(self, node: IndexExpr) -> str: base = node.base.accept(self) index = node.index.accept(self) - return "{}[{}]".format(base, index) + return f"{base}[{index}]" def visit_tuple_expr(self, node: TupleExpr) -> str: return ", ".join(n.accept(self) for n in node.items) @@ -436,21 +436,21 @@ def import_lines(self) -> List[str]: # This name was found in a from ... import ... # Collect the name in the module_map if name in self.reverse_alias: - name = '{} as {}'.format(self.reverse_alias[name], name) + name = f'{self.reverse_alias[name]} as {name}' elif name in self.reexports: - name = '{} as {}'.format(name, name) + name = f'{name} as {name}' module_map[m].append(name) else: # This name was found in an import ... # We can already generate the import line if name in self.reverse_alias: source = self.reverse_alias[name] - result.append("import {} as {}\n".format(source, name)) + result.append(f"import {source} as {name}\n") elif name in self.reexports: assert '.' not in name # Because reexports only has nonqualified names - result.append("import {} as {}\n".format(name, name)) + result.append(f"import {name} as {name}\n") else: - result.append("import {}\n".format(self.direct_imports[name])) + result.append(f"import {self.direct_imports[name]}\n") # Now generate all the from ... import ... lines collected in module_map for module, names in sorted(module_map.items()): @@ -635,7 +635,7 @@ def visit_func_def(self, o: FuncDef, is_abstract: bool = False, for s in self._decorators: self.add(s) self.clear_decorators() - self.add("%s%sdef %s(" % (self._indent, 'async ' if o.is_coroutine else '', o.name)) + self.add("{}{}def {}(".format(self._indent, 'async ' if o.is_coroutine else '', o.name)) self.record_name(o.name) args: List[str] = [] for i, arg_ in enumerate(o.arguments): @@ -653,7 +653,7 @@ def visit_func_def(self, o: FuncDef, is_abstract: bool = False, # Luckily, an argument explicitly annotated with "Any" has # type "UnboundType" and will not match. if not isinstance(get_proper_type(annotated_type), AnyType): - annotation = ": {}".format(self.print_annotation(annotated_type)) + annotation = f": {self.print_annotation(annotated_type)}" if kind.is_named() and not any(arg.startswith('*') for arg in args): args.append('*') @@ -664,14 +664,14 @@ def visit_func_def(self, o: FuncDef, is_abstract: bool = False, if typename == '': annotation = '=...' else: - annotation = ': {} = ...'.format(typename) + annotation = f': {typename} = ...' else: annotation += ' = ...' arg = name + annotation elif kind == ARG_STAR: - arg = '*%s%s' % (name, annotation) + arg = f'*{name}{annotation}' elif kind == ARG_STAR2: - arg = '**%s%s' % (name, annotation) + arg = f'**{name}{annotation}' else: arg = name + annotation args.append(arg) @@ -711,7 +711,7 @@ def visit_func_def(self, o: FuncDef, is_abstract: bool = False, retfield = ' -> ' + retname self.add(', '.join(args)) - self.add("){}: ...\n".format(retfield)) + self.add(f"){retfield}: ...\n") self._state = FUNC def is_none_expr(self, expr: Expression) -> bool: @@ -807,10 +807,10 @@ def process_member_expr_decorator(self, expr: MemberExpr, context: Decorator) -> if expr.name == 'abstractproperty': self.import_tracker.require_name(expr.expr.name) self.add_decorator('%s' % ('property')) - self.add_decorator('%s.%s' % (expr.expr.name, 'abstractmethod')) + self.add_decorator('{}.{}'.format(expr.expr.name, 'abstractmethod')) else: self.import_tracker.require_name(expr.expr.name) - self.add_decorator('%s.%s' % (expr.expr.name, expr.name)) + self.add_decorator(f'{expr.expr.name}.{expr.name}') is_abstract = True elif expr.name == 'coroutine': if (isinstance(expr.expr, MemberExpr) and @@ -835,7 +835,7 @@ def process_member_expr_decorator(self, expr: MemberExpr, context: Decorator) -> self.import_tracker.reverse_alias.get(expr.expr.name) in TYPING_MODULE_NAMES) and expr.name == 'overload'): self.import_tracker.require_name(expr.expr.name) - self.add_decorator('%s.%s' % (expr.expr.name, 'overload')) + self.add_decorator('{}.{}'.format(expr.expr.name, 'overload')) is_overload = True return is_abstract, is_overload @@ -845,7 +845,7 @@ def visit_class_def(self, o: ClassDef) -> None: if not self._indent and self._state != EMPTY: sep = len(self._output) self.add('\n') - self.add('%sclass %s' % (self._indent, o.name)) + self.add(f'{self._indent}class {o.name}') self.record_name(o.name) base_types = self.get_base_types(o) if base_types: @@ -892,7 +892,7 @@ def get_base_types(self, cdef: ClassDef) -> List[str]: base_types.append(base.name) elif isinstance(base, MemberExpr): modname = get_qualified_name(base.expr) - base_types.append('%s.%s' % (modname, base.name)) + base_types.append(f'{modname}.{base.name}') elif isinstance(base, IndexExpr): p = AliasPrinter(self) base_types.append(base.accept(p)) @@ -961,18 +961,18 @@ def process_namedtuple(self, lvalue: NameExpr, rvalue: CallExpr) -> None: list_items = cast(List[StrExpr], rvalue.args[1].items) items = [item.value for item in list_items] else: - self.add('%s%s: Incomplete' % (self._indent, lvalue.name)) + self.add(f'{self._indent}{lvalue.name}: Incomplete') self.import_tracker.require_name('Incomplete') return self.import_tracker.require_name('NamedTuple') - self.add('{}class {}(NamedTuple):'.format(self._indent, lvalue.name)) + self.add(f'{self._indent}class {lvalue.name}(NamedTuple):') if len(items) == 0: self.add(' ...\n') else: self.import_tracker.require_name('Incomplete') self.add('\n') for item in items: - self.add('{} {}: Incomplete\n'.format(self._indent, item)) + self.add(f'{self._indent} {item}: Incomplete\n') self._state = CLASS def is_alias_expression(self, expr: Expression, top_level: bool = True) -> bool: @@ -1020,7 +1020,7 @@ def is_alias_expression(self, expr: Expression, top_level: bool = True) -> bool: def process_typealias(self, lvalue: NameExpr, rvalue: Expression) -> None: p = AliasPrinter(self) - self.add("{} = {}\n".format(lvalue.name, rvalue.accept(p))) + self.add(f"{lvalue.name} = {rvalue.accept(p)}\n") self.record_name(lvalue.name) self._vars[-1].append(lvalue.name) @@ -1036,7 +1036,7 @@ def visit_if_stmt(self, o: IfStmt) -> None: super().visit_if_stmt(o) def visit_import_all(self, o: ImportAll) -> None: - self.add_import_line('from %s%s import *\n' % ('.' * o.relative, o.id)) + self.add_import_line('from {}{} import *\n'.format('.' * o.relative, o.id)) def visit_import_from(self, o: ImportFrom) -> None: exported_names: Set[str] = set() @@ -1127,10 +1127,10 @@ def get_init(self, lvalue: str, rvalue: Expression, self.import_tracker.module_for.get('Final') in TYPING_MODULE_NAMES): # Final without type argument is invalid in stubs. final_arg = self.get_str_type_of_node(rvalue) - typename += '[{}]'.format(final_arg) + typename += f'[{final_arg}]' else: typename = self.get_str_type_of_node(rvalue) - return '%s%s: %s\n' % (self._indent, lvalue, typename) + return f'{self._indent}{lvalue}: {typename}\n' def add(self, string: str) -> None: """Add text to generated stub.""" @@ -1139,7 +1139,7 @@ def add(self, string: str) -> None: def add_decorator(self, name: str) -> None: if not self._indent and self._state not in (EMPTY, FUNC): self._decorators.append('\n') - self._decorators.append('%s@%s\n' % (self._indent, name)) + self._decorators.append(f'{self._indent}@{name}\n') def clear_decorators(self) -> None: self._decorators.clear() @@ -1295,7 +1295,7 @@ def get_qualified_name(o: Expression) -> str: if isinstance(o, NameExpr): return o.name elif isinstance(o, MemberExpr): - return '%s.%s' % (get_qualified_name(o.expr), o.name) + return f'{get_qualified_name(o.expr)}.{o.name}' else: return ERROR_MARKER @@ -1420,7 +1420,7 @@ def is_non_library_module(module: str) -> bool: def translate_module_name(module: str, relative: int) -> Tuple[str, int]: for pkg in VENDOR_PACKAGES: for alt in 'six.moves', 'six': - substr = '{}.{}'.format(pkg, alt) + substr = f'{pkg}.{alt}' if (module.endswith('.' + substr) or (module == substr and relative)): return alt, 0 @@ -1513,7 +1513,7 @@ def generate_asts_for_modules(py_modules: List[StubSource], try: res = build([module.source for module in py_modules], mypy_options) except CompileError as e: - raise SystemExit("Critical error during semantic analysis: {}".format(e)) from e + raise SystemExit(f"Critical error during semantic analysis: {e}") from e for mod in py_modules: mod.ast = res.graph[mod.module].tree diff --git a/mypy/stubgenc.py b/mypy/stubgenc.py index 4b0bd4a62552a..e9fa0ef62bb2d 100755 --- a/mypy/stubgenc.py +++ b/mypy/stubgenc.py @@ -73,7 +73,7 @@ def generate_stub_for_c_module(module_name: str, continue if name not in done and not inspect.ismodule(obj): type_str = strip_or_import(get_type_fullname(type(obj)), module, imports) - variables.append('%s: %s' % (name, type_str)) + variables.append(f'{name}: {type_str}') output = [] for line in sorted(set(imports)): output.append(line) @@ -133,7 +133,7 @@ def is_c_type(obj: object) -> bool: def is_pybind11_overloaded_function_docstring(docstr: str, name: str) -> bool: - return docstr.startswith("{}(*args, **kwargs)\n".format(name) + + return docstr.startswith(f"{name}(*args, **kwargs)\n" + "Overloaded function.\n\n") @@ -254,7 +254,7 @@ def strip_or_import(typ: str, module: ModuleType, imports: List[str]) -> str: if arg_module == 'builtins': stripped_type = typ[len('builtins') + 1:] else: - imports.append('import %s' % (arg_module,)) + imports.append(f'import {arg_module}') if stripped_type == 'NoneType': stripped_type = 'None' return stripped_type @@ -304,14 +304,14 @@ def infer_prop_type(docstr: Optional[str]) -> Optional[str]: if is_static_property(obj): trailing_comment = " # read-only" if readonly else "" static_properties.append( - '{}: ClassVar[{}] = ...{}'.format(name, inferred, trailing_comment) + f'{name}: ClassVar[{inferred}] = ...{trailing_comment}' ) else: # regular property if readonly: ro_properties.append('@property') - ro_properties.append('def {}(self) -> {}: ...'.format(name, inferred)) + ro_properties.append(f'def {name}(self) -> {inferred}: ...') else: - rw_properties.append('{}: {}'.format(name, inferred)) + rw_properties.append(f'{name}: {inferred}') def generate_c_type_stub(module: ModuleType, @@ -370,7 +370,7 @@ def generate_c_type_stub(module: ModuleType, if is_skipped_attribute(attr): continue if attr not in done: - static_properties.append('%s: ClassVar[%s] = ...' % ( + static_properties.append('{}: ClassVar[{}] = ...'.format( attr, strip_or_import(get_type_fullname(type(value)), module, imports))) all_bases = type.mro(obj) if all_bases[-1] is object: @@ -398,7 +398,7 @@ def generate_c_type_stub(module: ModuleType, else: bases_str = '' if types or static_properties or rw_properties or methods or ro_properties: - output.append('class %s%s:' % (class_name, bases_str)) + output.append(f'class {class_name}{bases_str}:') for line in types: if output and output[-1] and \ not output[-1].startswith('class') and line.startswith('class'): @@ -413,11 +413,11 @@ def generate_c_type_stub(module: ModuleType, for line in ro_properties: output.append(' %s' % line) else: - output.append('class %s%s: ...' % (class_name, bases_str)) + output.append(f'class {class_name}{bases_str}: ...') def get_type_fullname(typ: type) -> str: - return '%s.%s' % (typ.__module__, getattr(typ, '__qualname__', typ.__name__)) + return '{}.{}'.format(typ.__module__, getattr(typ, '__qualname__', typ.__name__)) def method_name_sort_key(name: str) -> Tuple[int, str]: diff --git a/mypy/stubtest.py b/mypy/stubtest.py index d3bc40bc27e8a..ea0deb35092f9 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -105,9 +105,9 @@ def get_description(self, concise: bool = False) -> str: stub_loc_str = "" if stub_line: - stub_loc_str += " at line {}".format(stub_line) + stub_loc_str += f" at line {stub_line}" if stub_file: - stub_loc_str += " in file {}".format(Path(stub_file)) + stub_loc_str += f" in file {Path(stub_file)}" runtime_line = None runtime_file = None @@ -123,9 +123,9 @@ def get_description(self, concise: bool = False) -> str: runtime_loc_str = "" if runtime_line: - runtime_loc_str += " at line {}".format(runtime_line) + runtime_loc_str += f" at line {runtime_line}" if runtime_file: - runtime_loc_str += " in file {}".format(Path(runtime_file)) + runtime_loc_str += f" in file {Path(runtime_file)}" output = [ _style("error: ", color="red", bold=True), @@ -172,7 +172,7 @@ def test_module(module_name: str) -> Iterator[Error]: # mentioned in __all__ __import__(module_name, fromlist=["*"]) except Exception as e: - yield Error([module_name], "failed to import: {}".format(e), stub, MISSING) + yield Error([module_name], f"failed to import: {e}", stub, MISSING) return with warnings.catch_warnings(): @@ -207,11 +207,11 @@ def verify_mypyfile( return # Check things in the stub - to_check = set( + to_check = { m for m, o in stub.names.items() if not o.module_hidden and (not is_probably_private(m) or hasattr(runtime, m)) - ) + } def _belongs_to_runtime(r: types.ModuleType, attr: str) -> bool: obj = getattr(r, attr) @@ -302,7 +302,7 @@ class SubClass(runtime): # type: ignore for entry in sorted(to_check): mangled_entry = entry if entry.startswith("__") and not entry.endswith("__"): - mangled_entry = "_{}{}".format(stub.name, entry) + mangled_entry = f"_{stub.name}{entry}" stub_to_verify = next((t.names[entry].node for t in stub.mro if entry in t.names), MISSING) assert stub_to_verify is not None try: @@ -478,7 +478,7 @@ def get_desc(arg: Any) -> str: arg_type = get_type(arg) return ( get_name(arg) - + (": {}".format(arg_type) if arg_type else "") + + (f": {arg_type}" if arg_type else "") + (" = ..." if has_default(arg) else "") ) @@ -550,7 +550,7 @@ def from_overloadedfuncdef(stub: nodes.OverloadedFuncDef) -> "Signature[nodes.Ar # For positional-only args, we allow overloads to have different names for the same # argument. To accomplish this, we just make up a fake index-based name. name = ( - "__{}".format(index) + f"__{index}" if arg.variable.name.startswith("__") or assume_positional_only else arg.variable.name ) @@ -649,24 +649,24 @@ def _verify_signature( # If the variable is in runtime.kwonly, it's just mislabelled as not a # keyword-only argument if stub_arg.variable.name not in runtime.kwonly: - yield 'runtime does not have argument "{}"'.format(stub_arg.variable.name) + yield f'runtime does not have argument "{stub_arg.variable.name}"' else: - yield 'stub argument "{}" is not keyword-only'.format(stub_arg.variable.name) + yield f'stub argument "{stub_arg.variable.name}" is not keyword-only' if stub.varpos is not None: - yield 'runtime does not have *args argument "{}"'.format(stub.varpos.variable.name) + yield f'runtime does not have *args argument "{stub.varpos.variable.name}"' elif len(stub.pos) < len(runtime.pos): for runtime_arg in runtime.pos[len(stub.pos):]: if runtime_arg.name not in stub.kwonly: - yield 'stub does not have argument "{}"'.format(runtime_arg.name) + yield f'stub does not have argument "{runtime_arg.name}"' else: - yield 'runtime argument "{}" is not keyword-only'.format(runtime_arg.name) + yield f'runtime argument "{runtime_arg.name}" is not keyword-only' # Checks involving *args if len(stub.pos) <= len(runtime.pos) or runtime.varpos is None: if stub.varpos is None and runtime.varpos is not None: - yield 'stub does not have *args argument "{}"'.format(runtime.varpos.name) + yield f'stub does not have *args argument "{runtime.varpos.name}"' if stub.varpos is not None and runtime.varpos is None: - yield 'runtime does not have *args argument "{}"'.format(stub.varpos.variable.name) + yield f'runtime does not have *args argument "{stub.varpos.variable.name}"' # Check keyword-only args for arg in sorted(set(stub.kwonly) & set(runtime.kwonly)): @@ -682,26 +682,26 @@ def _verify_signature( # takes *kwargs, since runtime logic may prevent additional arguments from actually being # accepted. for arg in sorted(set(stub.kwonly) - set(runtime.kwonly)): - yield 'runtime does not have argument "{}"'.format(arg) + yield f'runtime does not have argument "{arg}"' for arg in sorted(set(runtime.kwonly) - set(stub.kwonly)): - if arg in set(stub_arg.variable.name for stub_arg in stub.pos): + if arg in {stub_arg.variable.name for stub_arg in stub.pos}: # Don't report this if we've reported it before if len(stub.pos) > len(runtime.pos) and runtime.varpos is not None: - yield 'stub argument "{}" is not keyword-only'.format(arg) + yield f'stub argument "{arg}" is not keyword-only' else: - yield 'stub does not have argument "{}"'.format(arg) + yield f'stub does not have argument "{arg}"' # Checks involving **kwargs if stub.varkw is None and runtime.varkw is not None: # As mentioned above, don't enforce that the stub takes **kwargs. # Also check against positional parameters, to avoid a nitpicky message when an argument # isn't marked as keyword-only - stub_pos_names = set(stub_arg.variable.name for stub_arg in stub.pos) + stub_pos_names = {stub_arg.variable.name for stub_arg in stub.pos} # Ideally we'd do a strict subset check, but in practice the errors from that aren't useful if not set(runtime.kwonly).issubset(set(stub.kwonly) | stub_pos_names): - yield 'stub does not have **kwargs argument "{}"'.format(runtime.varkw.name) + yield f'stub does not have **kwargs argument "{runtime.varkw.name}"' if stub.varkw is not None and runtime.varkw is None: - yield 'runtime does not have **kwargs argument "{}"'.format(stub.varkw.variable.name) + yield f'runtime does not have **kwargs argument "{stub.varkw.variable.name}"' @verify.register(nodes.FuncItem) @@ -803,7 +803,7 @@ def verify_var( if should_error: yield Error( object_path, - "variable differs from runtime type {}".format(runtime_type), + f"variable differs from runtime type {runtime_type}", stub, runtime, ) @@ -855,7 +855,7 @@ def verify_overloadedfuncdef( "is inconsistent, " + message, stub, runtime, - stub_desc=str(stub.type) + "\nInferred signature: {}".format(stub_sig), + stub_desc=str(stub.type) + f"\nInferred signature: {stub_sig}", runtime_desc="def " + str(signature), ) @@ -1400,7 +1400,7 @@ def set_strict_flags() -> None: # not needed yet # This lets us allowlist errors that don't manifest at all on some systems if not allowlist[w] and not allowlist_regexes[w].fullmatch(""): exit_code = 1 - print("note: unused allowlist entry {}".format(w)) + print(f"note: unused allowlist entry {w}") # Print the generated allowlist if args.generate_allowlist: diff --git a/mypy/stubutil.py b/mypy/stubutil.py index 5772d3fc99818..8ed73cab203b6 100644 --- a/mypy/stubutil.py +++ b/mypy/stubutil.py @@ -66,11 +66,9 @@ def walk_packages(inspect: ModuleInspect, yield prop.name if prop.is_c_module: # Recursively iterate through the subpackages - for submodule in walk_packages(inspect, prop.subpackages, verbose): - yield submodule + yield from walk_packages(inspect, prop.subpackages, verbose) else: - for submodule in prop.subpackages: - yield submodule + yield from prop.subpackages def find_module_path_and_all_py2(module: str, @@ -83,7 +81,7 @@ def find_module_path_and_all_py2(module: str, Raise CantImport if the module can't be imported, or exit if it's a C extension module. """ - cmd_template = '{interpreter} -c "%s"'.format(interpreter=interpreter) + cmd_template = f'{interpreter} -c "%s"' code = ("import importlib, json; mod = importlib.import_module('%s'); " "print(mod.__file__); print(json.dumps(getattr(mod, '__all__', None)))") % module try: @@ -188,7 +186,7 @@ def generate_guarded(mod: str, target: str, def report_missing(mod: str, message: Optional[str] = '', traceback: str = '') -> None: if message: message = ' with error: ' + message - print('{}: Failed to import, skipping{}'.format(mod, message)) + print(f'{mod}: Failed to import, skipping{message}') m = re.search(r"ModuleNotFoundError: No module named '([^']*)'", traceback) if m: missing_module = m.group(1) @@ -202,8 +200,8 @@ def fail_missing(mod: str, reason: ModuleNotFoundReason) -> None: elif reason is ModuleNotFoundReason.FOUND_WITHOUT_TYPE_HINTS: clarification = "(module likely exists, but is not PEP 561 compatible)" else: - clarification = "(unknown reason '{}')".format(reason) - raise SystemExit("Can't find module '{}' {}".format(mod, clarification)) + clarification = f"(unknown reason '{reason}')" + raise SystemExit(f"Can't find module '{mod}' {clarification}") @overload diff --git a/mypy/subtypes.py b/mypy/subtypes.py index 8bb5927021579..bbde38c5f92fc 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -591,7 +591,7 @@ def visit_type_type(self, left: TypeType) -> bool: return False def visit_type_alias_type(self, left: TypeAliasType) -> bool: - assert False, "This should be never called, got {}".format(left) + assert False, f"This should be never called, got {left}" T = TypeVar('T', Instance, TypeAliasType) @@ -1588,7 +1588,7 @@ def visit_type_type(self, left: TypeType) -> bool: return False def visit_type_alias_type(self, left: TypeAliasType) -> bool: - assert False, "This should be never called, got {}".format(left) + assert False, f"This should be never called, got {left}" def is_more_precise(left: Type, right: Type, *, ignore_promotions: bool = False) -> bool: diff --git a/mypy/suggestions.py b/mypy/suggestions.py index 46f8ff28dc761..fbbf00118e82c 100644 --- a/mypy/suggestions.py +++ b/mypy/suggestions.py @@ -62,18 +62,18 @@ import os -PyAnnotateSignature = TypedDict('PyAnnotateSignature', - {'return_type': str, 'arg_types': List[str]}) +class PyAnnotateSignature(TypedDict): + return_type: str + arg_types: List[str] -Callsite = NamedTuple( - 'Callsite', - [('path', str), - ('line', int), - ('arg_kinds', List[List[ArgKind]]), - ('callee_arg_names', List[Optional[str]]), - ('arg_names', List[List[Optional[str]]]), - ('arg_types', List[List[Type]])]) +class Callsite(NamedTuple): + path: str + line: int + arg_kinds: List[List[ArgKind]] + callee_arg_names: List[Optional[str]] + arg_names: List[List[Optional[str]]] + arg_types: List[List[Type]] class SuggestionPlugin(Plugin): @@ -250,7 +250,7 @@ def suggest_callsites(self, function: str) -> str: callsites, _ = self.get_callsites(node) return '\n'.join(dedup( - ["%s:%s: %s" % (path, line, self.format_args(arg_kinds, arg_names, arg_types)) + [f"{path}:{line}: {self.format_args(arg_kinds, arg_names, arg_types)}" for path, line, arg_kinds, _, arg_names, arg_types in callsites] )) @@ -483,7 +483,7 @@ def format_args(self, arg = '**' + arg elif kind.is_named(): if name: - arg = "%s=%s" % (name, arg) + arg = f"{name}={arg}" args.append(arg) return "(%s)" % (", ".join(args)) @@ -504,14 +504,14 @@ def find_node(self, key: str) -> Tuple[str, str, FuncDef]: ' package.module.Class.method or path/to/file.py:line'.format(key)) file, line = key.split(':') if not line.isdigit(): - raise SuggestionFailure('Line number must be a number. Got {}'.format(line)) + raise SuggestionFailure(f'Line number must be a number. Got {line}') line_number = int(line) modname, node = self.find_node_by_file_and_line(file, line_number) tail = node.fullname[len(modname) + 1:] # add one to account for '.' else: target = split_target(self.fgmanager.graph, key) if not target: - raise SuggestionFailure("Cannot find module for %s" % (key,)) + raise SuggestionFailure(f"Cannot find module for {key}") modname, tail = target node = self.find_node_by_module_and_name(modname, tail) @@ -589,7 +589,7 @@ def find_node_by_file_and_line(self, file: str, line: int) -> Tuple[str, SymbolN closest_line = sym_line node = sym.node if not node: - raise SuggestionFailure('Cannot find a function at line {}'.format(line)) + raise SuggestionFailure(f'Cannot find a function at line {line}') return modname, node def extract_from_decorator(self, node: Decorator) -> Optional[FuncDef]: @@ -720,7 +720,7 @@ def score_type(self, t: Type, arg_pos: bool) -> int: return 0 def score_callable(self, t: CallableType) -> int: - return (sum([self.score_type(x, arg_pos=True) for x in t.arg_types]) + + return (sum(self.score_type(x, arg_pos=True) for x in t.arg_types) + self.score_type(t.ret_type, arg_pos=False)) @@ -803,7 +803,7 @@ def visit_instance(self, t: Instance) -> str: if (mod, obj) == ('builtins', 'tuple'): mod, obj = 'typing', 'Tuple[' + t.args[0].accept(self) + ', ...]' elif t.args: - obj += '[{}]'.format(self.list_str(t.args)) + obj += f'[{self.list_str(t.args)}]' if mod_obj == ('builtins', 'unicode'): return 'Text' @@ -819,7 +819,7 @@ def visit_tuple_type(self, t: TupleType) -> str: if fallback_name != 'builtins.tuple': return t.partial_fallback.accept(self) s = self.list_str(t.items) - return 'Tuple[{}]'.format(s) + return f'Tuple[{s}]' def visit_uninhabited_type(self, t: UninhabitedType) -> str: return "Any" @@ -829,7 +829,7 @@ def visit_typeddict_type(self, t: TypedDictType) -> str: def visit_union_type(self, t: UnionType) -> str: if len(t.items) == 2 and is_optional(t): - return "Optional[{}]".format(remove_optional(t).accept(self)) + return f"Optional[{remove_optional(t).accept(self)}]" else: return super().visit_union_type(t) @@ -845,7 +845,7 @@ def visit_callable_type(self, t: CallableType) -> str: args = [typ.accept(self) for typ in t.arg_types] arg_str = "[{}]".format(", ".join(args)) - return "Callable[{}, {}]".format(arg_str, t.ret_type.accept(self)) + return f"Callable[{arg_str}, {t.ret_type.accept(self)}]" class StrToText(TypeTranslator): diff --git a/mypy/tvar_scope.py b/mypy/tvar_scope.py index c1fe1cd6be356..ecb00938fec92 100644 --- a/mypy/tvar_scope.py +++ b/mypy/tvar_scope.py @@ -120,7 +120,7 @@ def get_binding(self, item: Union[str, SymbolTableNode]) -> Optional[TypeVarLike return None def __str__(self) -> str: - me = ", ".join('{}: {}`{}'.format(k, v.name, v.id) for k, v in self.scope.items()) + me = ", ".join(f'{k}: {v.name}`{v.id}' for k, v in self.scope.items()) if self.parent is None: return me - return "{} <- {}".format(str(self.parent), me) + return f"{self.parent} <- {me}" diff --git a/mypy/typeanal.py b/mypy/typeanal.py index 41225a6061f35..536e170a9644d 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -99,7 +99,7 @@ def no_subscript_builtin_alias(name: str, propose_alt: bool = True) -> str: nongen_builtins = get_nongen_builtins((3, 8)) replacement = nongen_builtins[name] if replacement and propose_alt: - msg += ', use "{}" instead'.format(replacement) + msg += f', use "{replacement}" instead' return msg @@ -199,7 +199,7 @@ def visit_unbound_type_nonoptional(self, t: UnboundType, defining_literal: bool) self.api.record_incomplete_ref() return AnyType(TypeOfAny.special_form) if node is None: - self.fail('Internal error (node is None, kind={})'.format(sym.kind), t) + self.fail(f'Internal error (node is None, kind={sym.kind})', t) return AnyType(TypeOfAny.special_form) fullname = node.fullname hook = self.plugin.get_type_analyze_hook(fullname) @@ -213,11 +213,11 @@ def visit_unbound_type_nonoptional(self, t: UnboundType, defining_literal: bool) tvar_def = self.tvar_scope.get_binding(sym) if isinstance(sym.node, ParamSpecExpr): if tvar_def is None: - self.fail('ParamSpec "{}" is unbound'.format(t.name), t) + self.fail(f'ParamSpec "{t.name}" is unbound', t) return AnyType(TypeOfAny.from_error) assert isinstance(tvar_def, ParamSpecType) if len(t.args) > 0: - self.fail('ParamSpec "{}" used with arguments'.format(t.name), t) + self.fail(f'ParamSpec "{t.name}" used with arguments', t) # Change the line number return ParamSpecType( tvar_def.name, tvar_def.fullname, tvar_def.id, tvar_def.flavor, @@ -230,7 +230,7 @@ def visit_unbound_type_nonoptional(self, t: UnboundType, defining_literal: bool) if isinstance(sym.node, TypeVarExpr) and tvar_def is not None: assert isinstance(tvar_def, TypeVarType) if len(t.args) > 0: - self.fail('Type variable "{}" used with arguments'.format(t.name), t) + self.fail(f'Type variable "{t.name}" used with arguments', t) # Change the line number return TypeVarType( tvar_def.name, tvar_def.fullname, tvar_def.id, tvar_def.values, @@ -244,11 +244,11 @@ def visit_unbound_type_nonoptional(self, t: UnboundType, defining_literal: bool) return AnyType(TypeOfAny.from_error) if isinstance(sym.node, TypeVarTupleExpr): if tvar_def is None: - self.fail('TypeVarTuple "{}" is unbound'.format(t.name), t) + self.fail(f'TypeVarTuple "{t.name}" is unbound', t) return AnyType(TypeOfAny.from_error) assert isinstance(tvar_def, TypeVarTupleType) if len(t.args) > 0: - self.fail('Type variable "{}" used with arguments'.format(t.name), t) + self.fail(f'Type variable "{t.name}" used with arguments', t) # Change the line number return TypeVarTupleType( tvar_def.name, tvar_def.fullname, tvar_def.id, @@ -299,7 +299,7 @@ def cannot_resolve_type(self, t: UnboundType) -> None: # need access to MessageBuilder here. Also move the similar # message generation logic in semanal.py. self.api.fail( - 'Cannot resolve name "{}" (possible cyclic definition)'.format(t.name), + f'Cannot resolve name "{t.name}" (possible cyclic definition)', t) def apply_concatenate_operator(self, t: UnboundType) -> Type: @@ -779,10 +779,10 @@ def visit_raw_expression_type(self, t: RawExpressionType) -> Type: if t.base_type_name in ('builtins.int', 'builtins.bool'): # The only time it makes sense to use an int or bool is inside of # a literal type. - msg = "Invalid type: try using Literal[{}] instead?".format(repr(t.literal_value)) + msg = f"Invalid type: try using Literal[{repr(t.literal_value)}] instead?" elif t.base_type_name in ('builtins.float', 'builtins.complex'): # We special-case warnings for floats and complex numbers. - msg = "Invalid type: {} literals cannot be used as a type".format(t.simple_name()) + msg = f"Invalid type: {t.simple_name()} literals cannot be used as a type" else: # And in all other cases, we default to a generic error message. # Note: the reason why we use a generic error message for strings @@ -1042,14 +1042,14 @@ def analyze_literal_param(self, idx: int, arg: Type, ctx: Context) -> Optional[L # TODO: Once we start adding support for enums, make sure we report a custom # error for case 2 as well. if arg.type_of_any not in (TypeOfAny.from_error, TypeOfAny.special_form): - self.fail('Parameter {} of Literal[...] cannot be of type "Any"'.format(idx), ctx) + self.fail(f'Parameter {idx} of Literal[...] cannot be of type "Any"', ctx) return None elif isinstance(arg, RawExpressionType): # A raw literal. Convert it directly into a literal if we can. if arg.literal_value is None: name = arg.simple_name() if name in ('float', 'complex'): - msg = 'Parameter {} of Literal[...] cannot be of type "{}"'.format(idx, name) + msg = f'Parameter {idx} of Literal[...] cannot be of type "{name}"' else: msg = 'Invalid type: Literal[...] cannot contain arbitrary expressions' self.fail(msg, ctx) @@ -1076,7 +1076,7 @@ def analyze_literal_param(self, idx: int, arg: Type, ctx: Context) -> Optional[L out.extend(union_result) return out else: - self.fail('Parameter {} of Literal[...] is invalid'.format(idx), ctx) + self.fail(f'Parameter {idx} of Literal[...] is invalid', ctx) return None def analyze_type(self, t: Type) -> Type: @@ -1138,7 +1138,7 @@ def bind_function_type_variables( defs: List[TypeVarLikeType] = [] for name, tvar in typevars: if not self.tvar_scope.allow_binding(tvar.fullname): - self.fail('Type variable "{}" is bound by an outer class'.format(name), defn) + self.fail(f'Type variable "{name}" is bound by an outer class', defn) self.tvar_scope.bind_new(name, tvar) binding = self.tvar_scope.get_binding(tvar.fullname) assert binding is not None @@ -1178,7 +1178,7 @@ def anal_type(self, t: Type, nested: bool = True, *, allow_param_spec: bool = Fa if analyzed.prefix.arg_types: self.fail('Invalid location for Concatenate', t) else: - self.fail('Invalid location for ParamSpec "{}"'.format(analyzed.name), t) + self.fail(f'Invalid location for ParamSpec "{analyzed.name}"', t) self.note( 'You can use ParamSpec as the first argument to Callable, e.g., ' "'Callable[{}, int]'".format(analyzed.name), @@ -1314,7 +1314,7 @@ def fix_instance(t: Instance, fail: MsgCallback, note: MsgCallback, return # Invalid number of type parameters. n = len(t.type.type_vars) - s = '{} type arguments'.format(n) + s = f'{n} type arguments' if n == 0: s = 'no type arguments' elif n == 1: diff --git a/mypy/typeops.py b/mypy/typeops.py index dbfeebe42f14d..e2e44b915c0cf 100644 --- a/mypy/typeops.py +++ b/mypy/typeops.py @@ -811,7 +811,7 @@ def try_contracting_literals_in_union(types: Sequence[Type]) -> List[ProperType] if fullname not in sum_types: sum_types[fullname] = (set(get_enum_values(typ.fallback)) if typ.fallback.type.is_enum - else set((True, False)), + else {True, False}, []) literals, indexes = sum_types[fullname] literals.discard(typ.value) diff --git a/mypy/types.py b/mypy/types.py index 69776e4188ad2..a958e6c67dcce 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -200,7 +200,7 @@ def deserialize_type(data: Union[JsonDict, str]) -> 'Type': method = deserialize_map.get(classname) if method is not None: return method(data) - raise NotImplementedError('unexpected .class {}'.format(classname)) + raise NotImplementedError(f'unexpected .class {classname}') class Type(mypy.nodes.Context): @@ -235,11 +235,11 @@ def __repr__(self) -> str: return self.accept(TypeStrVisitor()) def serialize(self) -> Union[JsonDict, str]: - raise NotImplementedError('Cannot serialize {} instance'.format(self.__class__.__name__)) + raise NotImplementedError(f'Cannot serialize {self.__class__.__name__} instance') @classmethod def deserialize(cls, data: JsonDict) -> 'Type': - raise NotImplementedError('Cannot deserialize {} instance'.format(cls.__name__)) + raise NotImplementedError(f'Cannot deserialize {cls.__name__} instance') class TypeAliasType(Type): @@ -375,7 +375,7 @@ def __init__(self, type_guard: Type): self.type_guard = type_guard def __repr__(self) -> str: - return "TypeGuard({})".format(self.type_guard) + return f"TypeGuard({self.type_guard})" class RequiredType(Type): @@ -388,9 +388,9 @@ def __init__(self, item: Type, *, required: bool) -> None: def __repr__(self) -> str: if self.required: - return "Required[{}]".format(self.item) + return f"Required[{self.item}]" else: - return "NotRequired[{}]".format(self.item) + return f"NotRequired[{self.item}]" def accept(self, visitor: 'TypeVisitor[T]') -> T: return self.item.accept(visitor) @@ -1261,11 +1261,11 @@ def with_name(self, name: str) -> 'FunctionLike': pass def get_name(self) -> Optional[str]: pass -FormalArgument = NamedTuple('FormalArgument', [ - ('name', Optional[str]), - ('pos', Optional[int]), - ('typ', Type), - ('required', bool)]) +class FormalArgument(NamedTuple): + name: Optional[str] + pos: Optional[int] + typ: Type + required: bool # TODO: should this take bound typevars too? what would this take? @@ -1635,7 +1635,7 @@ def max_possible_positional_args(self) -> int: This takes into account *arg and **kwargs but excludes keyword-only args.""" if self.is_var_arg or self.is_kw_arg: return sys.maxsize - return sum([kind.is_positional() for kind in self.arg_kinds]) + return sum(kind.is_positional() for kind in self.arg_kinds) def formal_arguments(self, include_star_args: bool = False) -> List[FormalArgument]: """Return a list of the formal arguments of this callable, ignoring *arg and **kwargs. @@ -2234,7 +2234,7 @@ def value_repr(self) -> str: # If this is backed by an enum, if self.is_enum_literal(): - return '{}.{}'.format(fallback_name, self.value) + return f'{fallback_name}.{self.value}' if fallback_name == 'builtins.bytes': # Note: 'builtins.bytes' only appears in Python 3, so we want to @@ -2522,7 +2522,7 @@ def accept(self, visitor: 'TypeVisitor[T]') -> T: def serialize(self) -> str: # We should never get here since all placeholders should be replaced # during semantic analysis. - assert False, "Internal error: unresolved placeholder type {}".format(self.fullname) + assert False, f"Internal error: unresolved placeholder type {self.fullname}" @overload @@ -2593,18 +2593,18 @@ def __init__(self, id_mapper: Optional[IdMapper] = None) -> None: def visit_unbound_type(self, t: UnboundType) -> str: s = t.name + '?' if t.args: - s += '[{}]'.format(self.list_str(t.args)) + s += f'[{self.list_str(t.args)}]' return s def visit_type_list(self, t: TypeList) -> str: - return ''.format(self.list_str(t.items)) + return f'' def visit_callable_argument(self, t: CallableArgument) -> str: typ = t.typ.accept(self) if t.name is None: - return "{}({})".format(t.constructor, typ) + return f"{t.constructor}({typ})" else: - return "{}({}, {})".format(t.constructor, typ, t.name) + return f"{t.constructor}({typ}, {t.name})" def visit_any(self, t: AnyType) -> str: if self.any_as_dots and t.type_of_any == TypeOfAny.special_form: @@ -2624,35 +2624,35 @@ def visit_deleted_type(self, t: DeletedType) -> str: if t.source is None: return "" else: - return "".format(t.source) + return f"" def visit_instance(self, t: Instance) -> str: if t.last_known_value and not t.args: # Instances with a literal fallback should never be generic. If they are, # something went wrong so we fall back to showing the full Instance repr. - s = '{}?'.format(t.last_known_value) + s = f'{t.last_known_value}?' else: s = t.type.fullname or t.type.name or '' if t.args: if t.type.fullname == 'builtins.tuple': assert len(t.args) == 1 - s += '[{}, ...]'.format(self.list_str(t.args)) + s += f'[{self.list_str(t.args)}, ...]' else: - s += '[{}]'.format(self.list_str(t.args)) + s += f'[{self.list_str(t.args)}]' if self.id_mapper: - s += '<{}>'.format(self.id_mapper.id(t.type)) + s += f'<{self.id_mapper.id(t.type)}>' return s def visit_type_var(self, t: TypeVarType) -> str: if t.name is None: # Anonymous type variable type (only numeric id). - s = '`{}'.format(t.id) + s = f'`{t.id}' else: # Named type variable type. - s = '{}`{}'.format(t.name, t.id) + s = f'{t.name}`{t.id}' if self.id_mapper and t.upper_bound: - s += '(upper_bound={})'.format(t.upper_bound.accept(self)) + s += f'(upper_bound={t.upper_bound.accept(self)})' return s def visit_param_spec(self, t: ParamSpecType) -> str: @@ -2740,13 +2740,13 @@ def visit_callable_type(self, t: CallableType) -> str: s += ', ' s += f'*{n}.args, **{n}.kwargs' - s = '({})'.format(s) + s = f'({s})' if not isinstance(get_proper_type(t.ret_type), NoneType): if t.type_guard is not None: - s += ' -> TypeGuard[{}]'.format(t.type_guard.accept(self)) + s += f' -> TypeGuard[{t.type_guard.accept(self)}]' else: - s += ' -> {}'.format(t.ret_type.accept(self)) + s += f' -> {t.ret_type.accept(self)}' if t.variables: vs = [] @@ -2755,9 +2755,9 @@ def visit_callable_type(self, t: CallableType) -> str: # We reimplement TypeVarType.__repr__ here in order to support id_mapper. if var.values: vals = '({})'.format(', '.join(val.accept(self) for val in var.values)) - vs.append('{} in {}'.format(var.name, vals)) + vs.append(f'{var.name} in {vals}') elif not is_named_instance(var.upper_bound, 'builtins.object'): - vs.append('{} <: {}'.format(var.name, var.upper_bound.accept(self))) + vs.append(f'{var.name} <: {var.upper_bound.accept(self)}') else: vs.append(var.name) else: @@ -2765,7 +2765,7 @@ def visit_callable_type(self, t: CallableType) -> str: vs.append(var.name) s = '{} {}'.format('[{}]'.format(', '.join(vs)), s) - return 'def {}'.format(s) + return f'def {s}' def visit_overloaded(self, t: Overloaded) -> str: a = [] @@ -2778,15 +2778,15 @@ def visit_tuple_type(self, t: TupleType) -> str: if t.partial_fallback and t.partial_fallback.type: fallback_name = t.partial_fallback.type.fullname if fallback_name != 'builtins.tuple': - return 'Tuple[{}, fallback={}]'.format(s, t.partial_fallback.accept(self)) - return 'Tuple[{}]'.format(s) + return f'Tuple[{s}, fallback={t.partial_fallback.accept(self)}]' + return f'Tuple[{s}]' def visit_typeddict_type(self, t: TypedDictType) -> str: def item_str(name: str, typ: str) -> str: if name in t.required_keys: - return '{!r}: {}'.format(name, typ) + return f'{name!r}: {typ}' else: - return '{!r}?: {}'.format(name, typ) + return f'{name!r}?: {typ}' s = '{' + ', '.join(item_str(name, typ.accept(self)) for name, typ in t.items.items()) + '}' @@ -2794,21 +2794,21 @@ def item_str(name: str, typ: str) -> str: if t.fallback and t.fallback.type: if t.fallback.type.fullname not in TPDICT_FB_NAMES: prefix = repr(t.fallback.type.fullname) + ', ' - return 'TypedDict({}{})'.format(prefix, s) + return f'TypedDict({prefix}{s})' def visit_raw_expression_type(self, t: RawExpressionType) -> str: return repr(t.literal_value) def visit_literal_type(self, t: LiteralType) -> str: - return 'Literal[{}]'.format(t.value_repr()) + return f'Literal[{t.value_repr()}]' def visit_star_type(self, t: StarType) -> str: s = t.type.accept(self) - return '*{}'.format(s) + return f'*{s}' def visit_union_type(self, t: UnionType) -> str: s = self.list_str(t.items) - return 'Union[{}]'.format(s) + return f'Union[{s}]' def visit_partial_type(self, t: PartialType) -> str: if t.type is None: @@ -2821,10 +2821,10 @@ def visit_ellipsis_type(self, t: EllipsisType) -> str: return '...' def visit_type_type(self, t: TypeType) -> str: - return 'Type[{}]'.format(t.item.accept(self)) + return f'Type[{t.item.accept(self)}]' def visit_placeholder_type(self, t: PlaceholderType) -> str: - return ''.format(t.fullname) + return f'' def visit_type_alias_type(self, t: TypeAliasType) -> str: if t.alias is not None: @@ -2836,7 +2836,7 @@ def visit_type_alias_type(self, t: TypeAliasType) -> str: return '' def visit_unpack_type(self, t: UnpackType) -> str: - return 'Unpack[{}]'.format(t.type.accept(self)) + return f'Unpack[{t.type.accept(self)}]' def list_str(self, a: Iterable[Type]) -> str: """Convert items of an array to strings (pretty-print types) diff --git a/mypy/typestate.py b/mypy/typestate.py index 9e3d724bb185b..bbb593ce0daf8 100644 --- a/mypy/typestate.py +++ b/mypy/typestate.py @@ -202,7 +202,7 @@ def __iter__(self) -> Iterator[int]: # a concrete class may not be reprocessed, so not all -> deps # are added. for base_info in info.mro[:-1]: - trigger = make_trigger('%s.%s' % (base_info.fullname, attr)) + trigger = make_trigger(f'{base_info.fullname}.{attr}') if 'typing' in trigger or 'builtins' in trigger: # TODO: avoid everything from typeshed continue From 3c1a762965dff65fd96817e9fef671be7377b287 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sun, 1 May 2022 17:12:56 -0600 Subject: [PATCH 273/377] mypy: use more f-strings (#12714) Done largely using https://github.com/ikamensh/flynt I went over this pretty closely since I wasn't familiar with the tool I made a couple changes and left out a couple instances which were harder to parse --- mypy/build.py | 41 +++++++++++++------------- mypy/checker.py | 8 ++--- mypy/checkexpr.py | 2 +- mypy/checkstrformat.py | 2 +- mypy/config_parser.py | 10 +++---- mypy/dmypy/client.py | 8 ++--- mypy/dmypy_server.py | 2 +- mypy/dmypy_util.py | 2 +- mypy/fastparse.py | 2 +- mypy/main.py | 21 +++++++------- mypy/memprofile.py | 10 +++---- mypy/messages.py | 53 ++++++++++++++-------------------- mypy/moduleinspect.py | 2 +- mypy/nodes.py | 7 ++--- mypy/plugins/dataclasses.py | 2 +- mypy/plugins/singledispatch.py | 4 +-- mypy/report.py | 7 ++--- mypy/semanal.py | 18 ++++++------ mypy/semanal_enum.py | 12 ++++---- mypy/semanal_newtype.py | 2 +- mypy/semanal_typeddict.py | 2 +- mypy/server/deps.py | 2 +- mypy/server/mergecheck.py | 4 +-- mypy/server/trigger.py | 2 +- mypy/server/update.py | 25 ++++++++-------- mypy/strconv.py | 18 +++++------- mypy/stubdoc.py | 4 +-- mypy/stubgen.py | 32 ++++++++++---------- mypy/stubgenc.py | 16 +++++----- mypy/stubutil.py | 10 +++---- mypy/suggestions.py | 13 ++++----- mypy/test/data.py | 9 ++---- mypy/test/testcheck.py | 2 +- mypy/test/testdeps.py | 5 ++-- mypy/test/testdiff.py | 3 +- mypy/test/testfinegrained.py | 6 ++-- mypy/test/testmerge.py | 12 +++----- mypy/test/testparse.py | 3 +- mypy/test/testpythoneval.py | 2 +- mypy/test/testsemanal.py | 9 ++---- mypy/test/teststubgen.py | 6 ++-- mypy/test/teststubtest.py | 3 +- mypy/test/testtransform.py | 3 +- mypy/test/testtypegen.py | 3 +- mypy/typeanal.py | 9 +++--- mypy/types.py | 6 ++-- mypy/util.py | 2 +- 47 files changed, 190 insertions(+), 236 deletions(-) diff --git a/mypy/build.py b/mypy/build.py index 107a291ad582c..ba2d1b1b3d354 100644 --- a/mypy/build.py +++ b/mypy/build.py @@ -665,7 +665,7 @@ def dump_stats(self) -> None: if self.options.dump_build_stats: print("Stats:") for key, value in sorted(self.stats_summary().items()): - print("{:24}{}".format(key + ":", value)) + print(f"{key + ':':24}{value}") def use_fine_grained_cache(self) -> bool: return self.cache_enabled and self.options.use_fine_grained_cache @@ -1083,7 +1083,7 @@ def read_deps_cache(manager: BuildManager, except FileNotFoundError: matched = False if not matched: - manager.log('Invalid or missing fine-grained deps cache: {}'.format(meta['path'])) + manager.log(f"Invalid or missing fine-grained deps cache: {meta['path']}") return None return module_deps_metas @@ -1485,8 +1485,7 @@ def write_cache(id: str, path: str, tree: MypyFile, # Obtain file paths. meta_json, data_json, _ = get_cache_names(id, path, manager.options) - manager.log('Writing {} {} {} {}'.format( - id, path, meta_json, data_json)) + manager.log(f'Writing {id} {path} {meta_json} {data_json}') # Update tree.path so that in bazel mode it's made relative (since # sometimes paths leak out). @@ -1590,7 +1589,7 @@ def delete_cache(id: str, path: str, manager: BuildManager) -> None: # tracked separately. meta_path, data_path, _ = get_cache_names(id, path, manager.options) cache_paths = [meta_path, data_path] - manager.log('Deleting {} {} {}'.format(id, path, " ".join(x for x in cache_paths if x))) + manager.log(f"Deleting {id} {path} {' '.join(x for x in cache_paths if x)}") for filename in cache_paths: try: @@ -2490,7 +2489,7 @@ def find_module_and_diagnose(manager: BuildManager, and not options.custom_typeshed_dir): raise CompileError([ f'mypy: "{os.path.relpath(result)}" shadows library module "{id}"', - 'note: A user-defined top-level module with name "%s" is not supported' % id + f'note: A user-defined top-level module with name "{id}" is not supported' ]) return (result, follow_imports) else: @@ -2523,7 +2522,7 @@ def find_module_and_diagnose(manager: BuildManager, # If we can't find a root source it's always fatal. # TODO: This might hide non-fatal errors from # root sources processed earlier. - raise CompileError(["mypy: can't find module '%s'" % id]) + raise CompileError([f"mypy: can't find module '{id}'"]) else: raise ModuleNotFound @@ -2670,21 +2669,21 @@ def log_configuration(manager: BuildManager, sources: List[BuildSource]) -> None ] for conf_name, conf_value in configuration_vars: - manager.log("{:24}{}".format(conf_name + ":", conf_value)) + manager.log(f"{conf_name + ':':24}{conf_value}") for source in sources: - manager.log("{:24}{}".format("Found source:", source)) + manager.log(f"{'Found source:':24}{source}") # Complete list of searched paths can get very long, put them under TRACE for path_type, paths in manager.search_paths._asdict().items(): if not paths: - manager.trace("No %s" % path_type) + manager.trace(f"No {path_type}") continue - manager.trace("%s:" % path_type) + manager.trace(f"{path_type}:") for pth in paths: - manager.trace(" %s" % pth) + manager.trace(f" {pth}") # The driver @@ -2720,7 +2719,7 @@ def dispatch(sources: List[BuildSource], if not graph: print("Nothing to do?!", file=stdout) return graph - manager.log("Loaded graph with %d nodes (%.3f sec)" % (len(graph), t1 - t0)) + manager.log(f"Loaded graph with {len(graph)} nodes ({t1 - t0:.3f} sec)") if manager.options.dump_graph: dump_graph(graph, stdout) return graph @@ -3009,7 +3008,7 @@ def process_graph(graph: Graph, manager: BuildManager) -> None: scc.append('builtins') if manager.options.verbosity >= 2: for id in scc: - manager.trace("Priorities for %s:" % id, + manager.trace(f"Priorities for {id}:", " ".join("%s:%d" % (x, graph[id].priorities[x]) for x in graph[id].dependencies if x in ascc and x in graph[id].priorities)) @@ -3059,19 +3058,19 @@ def process_graph(graph: Graph, manager: BuildManager) -> None: # (on some platforms). if oldest_in_scc < newest_in_deps: fresh = False - fresh_msg = "out of date by %.0f seconds" % (newest_in_deps - oldest_in_scc) + fresh_msg = f"out of date by {newest_in_deps - oldest_in_scc:.0f} seconds" else: fresh_msg = "fresh" elif undeps: - fresh_msg = "stale due to changed suppression (%s)" % " ".join(sorted(undeps)) + fresh_msg = f"stale due to changed suppression ({' '.join(sorted(undeps))})" elif stale_scc: fresh_msg = "inherently stale" if stale_scc != ascc: - fresh_msg += " (%s)" % " ".join(sorted(stale_scc)) + fresh_msg += f" ({' '.join(sorted(stale_scc))})" if stale_deps: - fresh_msg += " with stale deps (%s)" % " ".join(sorted(stale_deps)) + fresh_msg += f" with stale deps ({' '.join(sorted(stale_deps))})" else: - fresh_msg = "stale due to deps (%s)" % " ".join(sorted(stale_deps)) + fresh_msg = f"stale due to deps ({' '.join(sorted(stale_deps))})" # Initialize transitive_error for all SCC members from union # of transitive_error of dependencies. @@ -3371,7 +3370,7 @@ def topsort(data: Dict[T, Set[T]]) -> Iterable[Set[T]]: data = {item: (dep - ready) for item, dep in data.items() if item not in ready} - assert not data, "A cyclic dependency exists amongst %r" % data + assert not data, f"A cyclic dependency exists amongst {data!r}" def missing_stubs_file(cache_dir: str) -> str: @@ -3388,7 +3387,7 @@ def record_missing_stub_packages(cache_dir: str, missing_stub_packages: Set[str] if missing_stub_packages: with open(fnam, 'w') as f: for pkg in sorted(missing_stub_packages): - f.write('%s\n' % pkg) + f.write(f'{pkg}\n') else: if os.path.isfile(fnam): os.remove(fnam) diff --git a/mypy/checker.py b/mypy/checker.py index d0820e483d650..cff637dbb57af 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -886,7 +886,7 @@ def check_func_def(self, defn: FuncItem, typ: CallableType, name: Optional[str]) self.msg.unimported_type_becomes_any("Return type", ret_type, fdef) for idx, arg_type in enumerate(fdef.type.arg_types): if has_any_from_unimported_type(arg_type): - prefix = f"Argument {idx + 1} to \"{fdef.name}\"" + prefix = f'Argument {idx + 1} to "{fdef.name}"' self.msg.unimported_type_becomes_any(prefix, arg_type, fdef) check_for_explicit_any(fdef.type, self.options, self.is_typeshed_stub, self.msg, context=fdef) @@ -1918,9 +1918,7 @@ def check_final_enum(self, defn: ClassDef, base: TypeInfo) -> None: for sym in base.names.values(): if self.is_final_enum_value(sym): self.fail( - 'Cannot extend enum with existing members: "{}"'.format( - base.name, - ), + f'Cannot extend enum with existing members: "{base.name}"', defn, ) break @@ -2571,7 +2569,7 @@ def check_compatibility_super(self, lvalue: RefExpr, lvalue_type: Optional[Type] return self.check_subtype(compare_type, base_type, rvalue, message_registry.INCOMPATIBLE_TYPES_IN_ASSIGNMENT, 'expression has type', - 'base class "%s" defined the type as' % base.name, + f'base class "{base.name}" defined the type as', code=codes.ASSIGNMENT) return True diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index ed6fd73acfa54..9dfc0e2a64587 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -263,7 +263,7 @@ def analyze_ref_expr(self, e: RefExpr, lvalue: bool = False) -> Type: result = self.object_type() else: if isinstance(node, PlaceholderNode): - assert False, 'PlaceholderNode %r leaked to checker' % node.fullname + assert False, f'PlaceholderNode {node.fullname!r} leaked to checker' # Unknown reference; use any type implicitly to avoid # generating extra type errors. result = AnyType(TypeOfAny.from_error) diff --git a/mypy/checkstrformat.py b/mypy/checkstrformat.py index 589a1fd6ac408..20b3716ea5135 100644 --- a/mypy/checkstrformat.py +++ b/mypy/checkstrformat.py @@ -718,7 +718,7 @@ def check_mapping_str_interpolation(self, specifiers: List[ConversionSpecifier], self.chk.check_subtype(rep_type, expected_type, replacements, message_registry.INCOMPATIBLE_TYPES_IN_STR_INTERPOLATION, 'expression has type', - 'placeholder with key \'%s\' has type' % specifier.key, + f'placeholder with key \'{specifier.key}\' has type', code=codes.STRING_FORMATTING) if specifier.conv_type == 's': self.check_s_special_cases(expr, rep_type, expr) diff --git a/mypy/config_parser.py b/mypy/config_parser.py index a9ba8535a5d60..952c3f96f29ab 100644 --- a/mypy/config_parser.py +++ b/mypy/config_parser.py @@ -211,10 +211,10 @@ def parse_config_file(options: Options, set_strict_flags: Callable[[], None], if 'mypy' not in parser: if filename or file_read not in defaults.SHARED_CONFIG_FILES: - print("%s: No [mypy] section in config file" % file_read, file=stderr) + print(f"{file_read}: No [mypy] section in config file", file=stderr) else: section = parser['mypy'] - prefix = '{}: [{}]: '.format(file_read, 'mypy') + prefix = f"{file_read}: [mypy]: " updates, report_dirs = parse_section( prefix, options, set_strict_flags, section, config_types, stderr) for k, v in updates.items(): @@ -322,7 +322,7 @@ def destructure_overrides(toml_data: Dict[str, Any]) -> Dict[str, Any]: for module in modules: module_overrides = override.copy() del module_overrides['module'] - old_config_name = 'mypy-%s' % module + old_config_name = f'mypy-{module}' if old_config_name not in result: result[old_config_name] = module_overrides else: @@ -447,7 +447,7 @@ def convert_to_boolean(value: Optional[Any]) -> bool: if not isinstance(value, str): value = str(value) if value.lower() not in configparser.RawConfigParser.BOOLEAN_STATES: - raise ValueError('Not a boolean: %s' % value) + raise ValueError(f'Not a boolean: {value}') return configparser.RawConfigParser.BOOLEAN_STATES[value.lower()] @@ -552,7 +552,7 @@ def get_config_module_names(filename: Optional[str], modules: List[str]) -> str: return '' if not is_toml(filename): - return ", ".join("[mypy-%s]" % module for module in modules) + return ", ".join(f"[mypy-{module}]" for module in modules) return "module = ['%s']" % ("', '".join(sorted(modules))) diff --git a/mypy/dmypy/client.py b/mypy/dmypy/client.py index 56ec804ad7a79..3ed85dca9750b 100644 --- a/mypy/dmypy/client.py +++ b/mypy/dmypy/client.py @@ -273,7 +273,7 @@ def do_run(args: argparse.Namespace) -> None: response = request(args.status_file, 'run', version=__version__, args=args.flags) # If the daemon signals that a restart is necessary, do it if 'restart' in response: - print('Restarting: {}'.format(response['restart'])) + print(f"Restarting: {response['restart']}") restart_server(args, allow_sources=True) response = request(args.status_file, 'run', version=__version__, args=args.flags) @@ -300,7 +300,7 @@ def do_status(args: argparse.Namespace) -> None: if args.verbose or 'error' in response: show_stats(response) if 'error' in response: - fail("Daemon is stuck; consider %s kill" % sys.argv[0]) + fail(f"Daemon is stuck; consider {sys.argv[0]} kill") print("Daemon is up and running") @@ -311,7 +311,7 @@ def do_stop(args: argparse.Namespace) -> None: response = request(args.status_file, 'stop', timeout=5) if 'error' in response: show_stats(response) - fail("Daemon is stuck; consider %s kill" % sys.argv[0]) + fail(f"Daemon is stuck; consider {sys.argv[0]} kill") else: print("Daemon stopped") @@ -389,7 +389,7 @@ def check_output(response: Dict[str, Any], verbose: bool, try: out, err, status_code = response['out'], response['err'], response['status'] except KeyError: - fail("Response: %s" % str(response)) + fail(f"Response: {str(response)}") sys.stdout.write(out) sys.stdout.flush() sys.stderr.write(err) diff --git a/mypy/dmypy_server.py b/mypy/dmypy_server.py index de03d64005256..3fbda6b1a7d8f 100644 --- a/mypy/dmypy_server.py +++ b/mypy/dmypy_server.py @@ -264,7 +264,7 @@ def run_command(self, command: str, data: Dict[str, object]) -> Dict[str, object key = 'cmd_' + command method = getattr(self.__class__, key, None) if method is None: - return {'error': "Unrecognized command '%s'" % command} + return {'error': f"Unrecognized command '{command}'"} else: if command not in {'check', 'recheck', 'run'}: # Only the above commands use some error formatting. diff --git a/mypy/dmypy_util.py b/mypy/dmypy_util.py index 8a527afe57629..2b458c51e5a4d 100644 --- a/mypy/dmypy_util.py +++ b/mypy/dmypy_util.py @@ -27,5 +27,5 @@ def receive(connection: IPCBase) -> Any: except Exception as e: raise OSError("Data received is not valid JSON") from e if not isinstance(data, dict): - raise OSError("Data received is not a dict (%s)" % str(type(data))) + raise OSError(f"Data received is not a dict ({type(data)})") return data diff --git a/mypy/fastparse.py b/mypy/fastparse.py index e4e8f4a7888d2..242b6d260c1ef 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -56,7 +56,7 @@ if sys.version_info >= (3, 8): import ast as ast3 assert 'kind' in ast3.Constant._fields, \ - "This 3.8.0 alpha (%s) is too old; 3.8.0a3 required" % sys.version.split()[0] + f"This 3.8.0 alpha ({sys.version.split()[0]}) is too old; 3.8.0a3 required" # TODO: Num, Str, Bytes, NameConstant, Ellipsis are deprecated in 3.8. # TODO: Index, ExtSlice are deprecated in 3.9. from ast import ( diff --git a/mypy/main.py b/mypy/main.py index 6b02382953142..f598194455c17 100644 --- a/mypy/main.py +++ b/mypy/main.py @@ -791,9 +791,9 @@ def add_invertible_flag(flag: str, description='Generate a report in the specified format.') for report_type in sorted(defaults.REPORTER_NAMES): if report_type not in {'memory-xml'}: - report_group.add_argument('--%s-report' % report_type.replace('_', '-'), + report_group.add_argument(f"--{report_type.replace('_', '-')}-report", metavar='DIR', - dest='special-opts:%s_report' % report_type) + dest=f'special-opts:{report_type}_report') other_group = parser.add_argument_group( title='Miscellaneous') @@ -918,7 +918,7 @@ def add_invertible_flag(flag: str, # Don't explicitly test if "config_file is not None" for this check. # This lets `--config-file=` (an empty string) be used to disable all config files. if config_file and not os.path.exists(config_file): - parser.error("Cannot find config file '%s'" % config_file) + parser.error(f"Cannot find config file '{config_file}'") options = Options() @@ -989,8 +989,7 @@ def set_strict_flags() -> None: invalid_codes = (enabled_codes | disabled_codes) - valid_error_codes if invalid_codes: - parser.error("Invalid error code(s): %s" % - ', '.join(sorted(invalid_codes))) + parser.error(f"Invalid error code(s): {', '.join(sorted(invalid_codes))}") options.disabled_error_codes |= {error_codes[code] for code in disabled_codes} options.enabled_error_codes |= {error_codes[code] for code in enabled_codes} @@ -1090,17 +1089,17 @@ def process_package_roots(fscache: Optional[FileSystemCache], package_root = [] for root in options.package_root: if os.path.isabs(root): - parser.error("Package root cannot be absolute: %r" % root) + parser.error(f"Package root cannot be absolute: {root!r}") drive, root = os.path.splitdrive(root) if drive and drive != current_drive: - parser.error("Package root must be on current drive: %r" % (drive + root)) + parser.error(f"Package root must be on current drive: {drive + root!r}") # Empty package root is always okay. if root: root = os.path.relpath(root) # Normalize the heck out of it. if not root.endswith(os.sep): root = root + os.sep if root.startswith(dotdotslash): - parser.error("Package root cannot be above current directory: %r" % root) + parser.error(f"Package root cannot be above current directory: {root!r}") if root in trivial_paths: root = '' package_root.append(root) @@ -1119,9 +1118,9 @@ def process_cache_map(parser: argparse.ArgumentParser, for i in range(0, n, 3): source, meta_file, data_file = special_opts.cache_map[i:i + 3] if source in options.cache_map: - parser.error("Duplicate --cache-map source %s)" % source) + parser.error(f"Duplicate --cache-map source {source})") if not source.endswith('.py') and not source.endswith('.pyi'): - parser.error("Invalid --cache-map source %s (triple[0] must be *.py[i])" % source) + parser.error(f"Invalid --cache-map source {source} (triple[0] must be *.py[i])") if not meta_file.endswith('.meta.json'): parser.error("Invalid --cache-map meta_file %s (triple[1] must be *.meta.json)" % meta_file) @@ -1140,7 +1139,7 @@ def maybe_write_junit_xml(td: float, serious: bool, messages: List[str], options def fail(msg: str, stderr: TextIO, options: Options) -> NoReturn: """Fail with a serious error.""" - stderr.write('%s\n' % msg) + stderr.write(f'{msg}\n') maybe_write_junit_xml(0.0, serious=True, messages=[msg], options=options) sys.exit(2) diff --git a/mypy/memprofile.py b/mypy/memprofile.py index 7494fed757501..ac49fd346abc4 100644 --- a/mypy/memprofile.py +++ b/mypy/memprofile.py @@ -33,23 +33,23 @@ def collect_memory_stats() -> Tuple[Dict[str, int], n = type(obj).__name__ if hasattr(obj, '__dict__'): # Keep track of which class a particular __dict__ is associated with. - inferred[id(obj.__dict__)] = '%s (__dict__)' % n + inferred[id(obj.__dict__)] = f'{n} (__dict__)' if isinstance(obj, (Node, Type)): # type: ignore if hasattr(obj, '__dict__'): for x in obj.__dict__.values(): if isinstance(x, list): # Keep track of which node a list is associated with. - inferred[id(x)] = '%s (list)' % n + inferred[id(x)] = f'{n} (list)' if isinstance(x, tuple): # Keep track of which node a list is associated with. - inferred[id(x)] = '%s (tuple)' % n + inferred[id(x)] = f'{n} (tuple)' for k in get_class_descriptors(type(obj)): x = getattr(obj, k, None) if isinstance(x, list): - inferred[id(x)] = '%s (list)' % n + inferred[id(x)] = f'{n} (list)' if isinstance(x, tuple): - inferred[id(x)] = '%s (tuple)' % n + inferred[id(x)] = f'{n} (tuple)' freqs: Dict[str, int] = {} memuse: Dict[str, int] = {} diff --git a/mypy/messages.py b/mypy/messages.py index 801f84c2580bb..70d79384c1a9d 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -365,8 +365,7 @@ def unsupported_operand_types(self, if self.are_type_names_disabled(): msg = f'Unsupported operand types for {op} (likely involving Union)' else: - msg = 'Unsupported operand types for {} ({} and {})'.format( - op, left_str, right_str) + msg = f'Unsupported operand types for {op} ({left_str} and {right_str})' self.fail(msg, context, code=code) def unsupported_left_operand(self, op: str, typ: Type, @@ -374,8 +373,7 @@ def unsupported_left_operand(self, op: str, typ: Type, if self.are_type_names_disabled(): msg = f'Unsupported left operand type for {op} (some union)' else: - msg = 'Unsupported left operand type for {} ({})'.format( - op, format_type(typ)) + msg = f'Unsupported left operand type for {op} ({format_type(typ)})' self.fail(msg, context, code=codes.OPERATOR) def not_callable(self, typ: Type, context: Context) -> Type: @@ -707,7 +705,7 @@ def unexpected_keyword_argument(self, callee: CallableType, name: str, arg_type: if not matches: matches = best_matches(name, not_matching_type_args) if matches: - msg += "; did you mean {}?".format(pretty_seq(matches[:3], "or")) + msg += f"; did you mean {pretty_seq(matches[:3], 'or')}?" self.fail(msg, context, code=codes.CALL_ARG) module = find_defining_module(self.modules, callee) if module: @@ -980,7 +978,7 @@ def too_many_string_formatting_arguments(self, context: Context) -> None: code=codes.STRING_FORMATTING) def unsupported_placeholder(self, placeholder: str, context: Context) -> None: - self.fail('Unsupported format character "%s"' % placeholder, context, + self.fail(f'Unsupported format character "{placeholder}"', context, code=codes.STRING_FORMATTING) def string_interpolation_with_star_and_key(self, context: Context) -> None: @@ -999,7 +997,7 @@ def requires_int_or_char(self, context: Context, context, code=codes.STRING_FORMATTING) def key_not_in_mapping(self, key: str, context: Context) -> None: - self.fail('Key "%s" not found in mapping' % key, context, + self.fail(f'Key "{key}" not found in mapping', context, code=codes.STRING_FORMATTING) def string_interpolation_mixing_key_and_non_keys(self, context: Context) -> None: @@ -1007,7 +1005,7 @@ def string_interpolation_mixing_key_and_non_keys(self, context: Context) -> None code=codes.STRING_FORMATTING) def cannot_determine_type(self, name: str, context: Context) -> None: - self.fail('Cannot determine type of "%s"' % name, context, code=codes.HAS_TYPE) + self.fail(f'Cannot determine type of "{name}"', context, code=codes.HAS_TYPE) def cannot_determine_type_in_base(self, name: str, base: str, context: Context) -> None: self.fail(f'Cannot determine type of "{name}" in base class "{base}"', context) @@ -1029,7 +1027,7 @@ def incompatible_conditional_function_def(self, defn: FuncDef) -> None: def cannot_instantiate_abstract_class(self, class_name: str, abstract_attributes: List[str], context: Context) -> None: - attrs = format_string_list(['"%s"' % a for a in abstract_attributes]) + 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), @@ -1047,7 +1045,7 @@ def cant_assign_to_method(self, context: Context) -> None: code=codes.ASSIGNMENT) def cant_assign_to_classvar(self, name: str, context: Context) -> None: - self.fail('Cannot assign to class variable "%s" via instance' % name, context) + self.fail(f'Cannot assign to class variable "{name}" via instance', context) def final_cant_override_writable(self, name: str, ctx: Context) -> None: self.fail(f'Cannot override writable attribute "{name}" with a final one', ctx) @@ -1072,8 +1070,7 @@ def final_without_value(self, ctx: Context) -> None: def read_only_property(self, name: str, type: TypeInfo, context: Context) -> None: - self.fail('Property "{}" defined in "{}" is read-only'.format( - name, type.name), context) + self.fail(f'Property "{name}" defined in "{type.name}" is read-only', context) def incompatible_typevar_value(self, callee: CallableType, @@ -1142,8 +1139,7 @@ def operator_method_signatures_overlap( def forward_operator_not_callable( self, forward_method: str, context: Context) -> None: - self.fail('Forward operator "{}" is not callable'.format( - forward_method), context) + self.fail(f'Forward operator "{forward_method}" is not callable', context) def signatures_incompatible(self, method: str, other_method: str, context: Context) -> None: @@ -1322,8 +1318,7 @@ def disallowed_any_type(self, typ: Type, context: Context) -> None: self.fail(message, context) def incorrectly_returning_any(self, typ: Type, context: Context) -> None: - message = 'Returning Any from function declared to return {}'.format( - format_type(typ)) + message = f'Returning Any from function declared to return {format_type(typ)}' self.fail(message, context, code=codes.NO_ANY_RETURN) def incorrect__exit__return(self, context: Context) -> None: @@ -1481,8 +1476,7 @@ def report_protocol_problems(self, if conflict_types and (not is_subtype(subtype, erase_type(supertype)) or not subtype.type.defn.type_vars or not supertype.type.defn.type_vars): - self.note('Following member(s) of {} have ' - 'conflicts:'.format(format_type(subtype)), + self.note(f'Following member(s) of {format_type(subtype)} have conflicts:', context, code=code) for name, got, exp in conflict_types[:MAX_ITEMS]: @@ -1562,8 +1556,7 @@ def print_more(self, *, code: Optional[ErrorCode] = None) -> None: if len(conflicts) > max_items: - self.note('<{} more conflict(s) not shown>' - .format(len(conflicts) - max_items), + self.note(f'<{len(conflicts) - max_items} more conflict(s) not shown>', context, offset=offset, code=code) def try_report_long_tuple_assignment_error(self, @@ -1670,9 +1663,7 @@ def format_callable_args(arg_types: List[Type], arg_kinds: List[ArgKind], else: constructor = ARG_CONSTRUCTOR_NAMES[arg_kind] if arg_kind.is_star() or arg_name is None: - arg_strings.append("{}({})".format( - constructor, - format(arg_type))) + arg_strings.append(f"{constructor}({format(arg_type)})") else: arg_strings.append("{}({}, {})".format( constructor, @@ -1760,10 +1751,8 @@ def format_literal_value(typ: LiteralType) -> str: items = [] for (item_name, item_type) in typ.items.items(): modifier = '' if item_name in typ.required_keys else '?' - items.append('{!r}{}: {}'.format(item_name, - modifier, - format(item_type))) - s = 'TypedDict({{{}}})'.format(', '.join(items)) + items.append(f'{item_name!r}{modifier}: {format(item_type)}') + s = f"TypedDict({{{', '.join(items)}}})" return s elif isinstance(typ, LiteralType): return f'Literal[{format_literal_value(typ)}]' @@ -2027,7 +2016,7 @@ def [T <: int] f(self, x: int, y: T) -> None else: # For other TypeVarLikeTypes, just use the repr tvars.append(repr(tvar)) - s = '[{}] {}'.format(', '.join(tvars), s) + s = f"[{', '.join(tvars)}] {s}" return f'def {s}' @@ -2134,7 +2123,7 @@ def format_string_list(lst: List[str]) -> str: if len(lst) == 1: return lst[0] elif len(lst) <= 5: - return '{} and {}'.format(', '.join(lst[:-1]), lst[-1]) + return f"{', '.join(lst[:-1])} and {lst[-1]}" else: return '%s, ... and %s (%i methods suppressed)' % ( ', '.join(lst[:2]), lst[-1], len(lst) - 3) @@ -2143,9 +2132,9 @@ def format_string_list(lst: List[str]) -> str: def format_item_name_list(s: Iterable[str]) -> str: lst = list(s) if len(lst) <= 5: - return '(' + ', '.join(['"%s"' % name for name in lst]) + ')' + return '(' + ', '.join([f'"{name}"' for name in lst]) + ')' else: - return '(' + ', '.join(['"%s"' % name for name in lst[:5]]) + ', ...)' + return '(' + ', '.join([f'"{name}"' for name in lst[:5]]) + ', ...)' def callable_name(type: FunctionLike) -> Optional[str]: @@ -2263,4 +2252,4 @@ def format_key_list(keys: List[str], *, short: bool = False) -> str: elif len(keys) == 1: return f'{td}key {formatted_keys[0]}' else: - return '{}keys ({})'.format(td, ', '.join(formatted_keys)) + return f"{td}keys ({', '.join(formatted_keys)})" diff --git a/mypy/moduleinspect.py b/mypy/moduleinspect.py index ebcbb25ea5e50..2b2068e0b7c5f 100644 --- a/mypy/moduleinspect.py +++ b/mypy/moduleinspect.py @@ -138,7 +138,7 @@ def get_package_properties(self, package_id: str) -> ModuleProperties: if res is None: # The process died; recover and report error. self._start() - raise InspectError('Process died when importing %r' % package_id) + raise InspectError(f'Process died when importing {package_id!r}') if isinstance(res, str): # Error importing module if self.counter > 0: diff --git a/mypy/nodes.py b/mypy/nodes.py index c0e53ea9367c9..4ffa3116a1189 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -483,7 +483,7 @@ def deserialize(cls, data: JsonDict) -> 'ImportedName': assert False, "ImportedName should never be serialized" def __str__(self) -> str: - return 'ImportedName(%s)' % self.target_fullname + return f'ImportedName({self.target_fullname})' FUNCBASE_FLAGS: Final = ["is_property", "is_class", "is_static", "is_final"] @@ -2778,7 +2778,7 @@ def __getitem__(self, name: str) -> 'SymbolTableNode': raise KeyError(name) def __repr__(self) -> str: - return '' % self.fullname + return f'' def __bool__(self) -> bool: # We defined this here instead of just overriding it in @@ -2859,8 +2859,7 @@ def type_str(typ: 'mypy.types.Type') -> str: head = 'TypeInfo' + str_conv.format_id(self) if self.bases: - base = 'Bases({})'.format(', '.join(type_str(base) - for base in self.bases)) + base = f"Bases({', '.join(type_str(base) for base in self.bases)})" mro = 'Mro({})'.format(', '.join(item.fullname + str_conv.format_id(item) for item in self.mro)) names = [] diff --git a/mypy/plugins/dataclasses.py b/mypy/plugins/dataclasses.py index 5827a21e8ccf8..62b4c89bd674b 100644 --- a/mypy/plugins/dataclasses.py +++ b/mypy/plugins/dataclasses.py @@ -195,7 +195,7 @@ def transform(self) -> None: if existing_method is not None and not existing_method.plugin_generated: assert existing_method.node ctx.api.fail( - 'You may not have a custom %s method when order=True' % method_name, + f'You may not have a custom {method_name} method when order=True', existing_method.node, ) diff --git a/mypy/plugins/singledispatch.py b/mypy/plugins/singledispatch.py index 0eb855d3a3150..d6150836c562d 100644 --- a/mypy/plugins/singledispatch.py +++ b/mypy/plugins/singledispatch.py @@ -48,9 +48,7 @@ def get_first_arg(args: List[List[T]]) -> Optional[T]: REGISTER_RETURN_CLASS: Final = '_SingleDispatchRegisterCallable' -REGISTER_CALLABLE_CALL_METHOD: Final = 'functools.{}.__call__'.format( - REGISTER_RETURN_CLASS -) +REGISTER_CALLABLE_CALL_METHOD: Final = f'functools.{REGISTER_RETURN_CLASS}.__call__' def make_fake_register_class_instance(api: CheckerPluginInterface, type_args: Sequence[Type] diff --git a/mypy/report.py b/mypy/report.py index 8d3465f3c1f0b..28fa5c274b74c 100644 --- a/mypy/report.py +++ b/mypy/report.py @@ -181,8 +181,7 @@ def on_finish(self) -> None: with open(os.path.join(self.output_dir, "linecount.txt"), "w") as f: f.write("{:7} {:7} {:6} {:6} total\n".format(*total_counts)) for c, p in counts: - f.write('{:7} {:7} {:6} {:6} {}\n'.format( - c[0], c[1], c[2], c[3], p)) + f.write(f'{c[0]:7} {c[1]:7} {c[2]:6} {c[3]:6} {p}\n') register_reporter('linecount', LineCountReporter) @@ -490,7 +489,7 @@ def on_file(self, # Assumes a layout similar to what XmlReporter uses. xslt_path = os.path.relpath('mypy-html.xslt', path) transform_pi = etree.ProcessingInstruction('xml-stylesheet', - 'type="text/xsl" href="%s"' % pathname2url(xslt_path)) + f'type="text/xsl" href="{pathname2url(xslt_path)}"') root.addprevious(transform_pi) self.schema.assertValid(doc) @@ -526,7 +525,7 @@ def on_finish(self) -> None: total=str(file_info.total())) xslt_path = os.path.relpath('mypy-html.xslt', '.') transform_pi = etree.ProcessingInstruction('xml-stylesheet', - 'type="text/xsl" href="%s"' % pathname2url(xslt_path)) + f'type="text/xsl" href="{pathname2url(xslt_path)}"') root.addprevious(transform_pi) self.schema.assertValid(doc) diff --git a/mypy/semanal.py b/mypy/semanal.py index eb0411f0afc88..a9445a9c87489 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -366,7 +366,7 @@ def prepare_builtins_namespace(self, file_node: MypyFile) -> None: for name in CORE_BUILTIN_CLASSES: cdef = ClassDef(name, Block([])) # Dummy ClassDef, will be replaced later info = TypeInfo(SymbolTable(), cdef, 'builtins') - info._fullname = 'builtins.%s' % name + info._fullname = f'builtins.{name}' names[name] = SymbolTableNode(GDEF, info) bool_info = names['bool'].node @@ -388,7 +388,7 @@ def prepare_builtins_namespace(self, file_node: MypyFile) -> None: for name, typ in special_var_types: v = Var(name, typ) - v._fullname = 'builtins.%s' % name + v._fullname = f'builtins.{name}' file_node.names[name] = SymbolTableNode(GDEF, v) # @@ -1107,7 +1107,7 @@ def visit_decorator(self, dec: Decorator) -> None: def check_decorated_function_is_method(self, decorator: str, context: Context) -> None: if not self.type or self.is_func_scope(): - self.fail('"%s" used with a non-method' % decorator, context) + self.fail(f'"{decorator}" used with a non-method', context) # # Classes @@ -1722,7 +1722,7 @@ def verify_base_classes(self, defn: ClassDef) -> bool: return False dup = find_duplicate(info.direct_base_classes()) if dup: - self.fail('Duplicate base class "%s"' % dup.name, defn, blocker=True) + self.fail(f'Duplicate base class "{dup.name}"', defn, blocker=True) return False return not cycle @@ -1749,7 +1749,7 @@ def analyze_metaclass(self, defn: ClassDef) -> None: elif isinstance(defn.metaclass, MemberExpr): metaclass_name = get_member_expr_fullname(defn.metaclass) if metaclass_name is None: - self.fail('Dynamic metaclass not supported for "%s"' % defn.name, defn.metaclass) + self.fail(f'Dynamic metaclass not supported for "{defn.name}"', defn.metaclass) return sym = self.lookup_qualified(metaclass_name, defn.metaclass) if sym is None: @@ -1766,7 +1766,7 @@ def analyze_metaclass(self, defn: ClassDef) -> None: self.defer(defn) return if not isinstance(sym.node, TypeInfo) or sym.node.tuple_type is not None: - self.fail('Invalid metaclass "%s"' % metaclass_name, defn.metaclass) + self.fail(f'Invalid metaclass "{metaclass_name}"', defn.metaclass) return if not sym.node.is_metaclass(): self.fail('Metaclasses not inheriting from "type" are not supported', @@ -1788,7 +1788,7 @@ def analyze_metaclass(self, defn: ClassDef) -> None: # Inconsistency may happen due to multiple baseclasses even in classes that # do not declare explicit metaclass, but it's harder to catch at this stage if defn.metaclass is not None: - self.fail('Inconsistent metaclass structure for "%s"' % defn.name, defn) + self.fail(f'Inconsistent metaclass structure for "{defn.name}"', defn) else: if defn.info.metaclass_type.type.has_base('enum.EnumMeta'): defn.info.is_enum = True @@ -1953,7 +1953,7 @@ def report_missing_module_attribute( alternatives = set(module.names.keys()).difference({source_id}) matches = best_matches(source_id, alternatives)[:3] if matches: - suggestion = "; maybe {}?".format(pretty_seq(matches, "or")) + suggestion = f"; maybe {pretty_seq(matches, 'or')}?" message += f"{suggestion}" self.fail(message, context, code=codes.ATTR_DEFINED) self.add_unknown_imported_symbol( @@ -3120,7 +3120,7 @@ def process_typevar_declaration(self, s: AssignmentStmt) -> bool: # Also give error for another type variable with the same name. (isinstance(existing.node, TypeVarExpr) and existing.node is call.analyzed)): - self.fail('Cannot redefine "%s" as a type variable' % name, s) + self.fail(f'Cannot redefine "{name}" as a type variable', s) return False if self.options.disallow_any_unimported: diff --git a/mypy/semanal_enum.py b/mypy/semanal_enum.py index 251767bef3e0d..0f09a4bf94579 100644 --- a/mypy/semanal_enum.py +++ b/mypy/semanal_enum.py @@ -119,11 +119,11 @@ def parse_enum_call_args(self, call: CallExpr, """ args = call.args if not all([arg_kind in [ARG_POS, ARG_NAMED] for arg_kind in call.arg_kinds]): - return self.fail_enum_call_arg("Unexpected arguments to %s()" % class_name, call) + return self.fail_enum_call_arg(f"Unexpected arguments to {class_name}()", call) if len(args) < 2: - return self.fail_enum_call_arg("Too few arguments for %s()" % class_name, call) + return self.fail_enum_call_arg(f"Too few arguments for {class_name}()", call) if len(args) > 6: - return self.fail_enum_call_arg("Too many arguments for %s()" % class_name, call) + return self.fail_enum_call_arg(f"Too many arguments for {class_name}()", call) valid_name = [None, 'value', 'names', 'module', 'qualname', 'type', 'start'] for arg_name in call.arg_names: if arg_name not in valid_name: @@ -140,7 +140,7 @@ def parse_enum_call_args(self, call: CallExpr, names = args[1] if not isinstance(value, (StrExpr, UnicodeExpr)): return self.fail_enum_call_arg( - "%s() expects a string literal as the first argument" % class_name, call) + f"{class_name}() expects a string literal as the first argument", call) items = [] values: List[Optional[Expression]] = [] if isinstance(names, (StrExpr, UnicodeExpr)): @@ -171,7 +171,7 @@ def parse_enum_call_args(self, call: CallExpr, for key, value in names.items: if not isinstance(key, (StrExpr, UnicodeExpr)): return self.fail_enum_call_arg( - "%s() with dict literal requires string literals" % class_name, call) + f"{class_name}() with dict literal requires string literals", call) items.append(key.value) values.append(value) elif isinstance(args[1], RefExpr) and isinstance(args[1].node, Var): @@ -198,7 +198,7 @@ def parse_enum_call_args(self, call: CallExpr, class_name, call) if len(items) == 0: - return self.fail_enum_call_arg("%s() needs at least one item" % class_name, call) + return self.fail_enum_call_arg(f"{class_name}() needs at least one item", call) if not values: values = [None] * len(items) assert len(items) == len(values) diff --git a/mypy/semanal_newtype.py b/mypy/semanal_newtype.py index 047df3d85b83d..948c5b36052f1 100644 --- a/mypy/semanal_newtype.py +++ b/mypy/semanal_newtype.py @@ -127,7 +127,7 @@ def analyze_newtype_declaration(self, # Give a better error message than generic "Name already defined". if (existing and not isinstance(existing.node, PlaceholderNode) and not s.rvalue.analyzed): - self.fail('Cannot redefine "%s" as a NewType' % name, s) + self.fail(f'Cannot redefine "{name}" as a NewType', s) # This dummy NewTypeExpr marks the call as sufficiently analyzed; it will be # overwritten later with a fully complete NewTypeExpr if there are no other diff --git a/mypy/semanal_typeddict.py b/mypy/semanal_typeddict.py index 3b384bdec1a32..4087f477c597e 100644 --- a/mypy/semanal_typeddict.py +++ b/mypy/semanal_typeddict.py @@ -86,7 +86,7 @@ def analyze_typeddict_classdef(self, defn: ClassDef) -> Tuple[bool, Optional[Typ typeddict_bases.append(expr) else: assert isinstance(expr.node, TypeInfo) - self.fail('Duplicate base class "%s"' % expr.node.name, defn) + self.fail(f'Duplicate base class "{expr.node.name}"', defn) else: self.fail("All bases of a new TypedDict must be TypedDict types", defn) diff --git a/mypy/server/deps.py b/mypy/server/deps.py index b70a43db25401..f339344e79b58 100644 --- a/mypy/server/deps.py +++ b/mypy/server/deps.py @@ -1040,4 +1040,4 @@ def dump_all_dependencies(modules: Dict[str, MypyFile], for trigger, targets in sorted(all_deps.items(), key=lambda x: x[0]): print(trigger) for target in sorted(targets): - print(' %s' % target) + print(f' {target}') diff --git a/mypy/server/mergecheck.py b/mypy/server/mergecheck.py index 2c28242251e90..41d19f60f436f 100644 --- a/mypy/server/mergecheck.py +++ b/mypy/server/mergecheck.py @@ -70,14 +70,14 @@ def path_to_str(path: List[Tuple[object, object]]) -> str: for attr, obj in path: t = type(obj).__name__ if t in ('dict', 'tuple', 'SymbolTable', 'list'): - result += '[%s]' % repr(attr) + result += f'[{repr(attr)}]' else: if isinstance(obj, Var): result += f'.{attr}({t}:{obj.name})' elif t in ('BuildManager', 'FineGrainedBuildManager'): # Omit class name for some classes that aren't part of a class # hierarchy since there isn't much ambiguity. - result += '.%s' % attr + result += f'.{attr}' else: result += f'.{attr}({t})' return result diff --git a/mypy/server/trigger.py b/mypy/server/trigger.py index 3b9b02d20c81f..bfd542a405373 100644 --- a/mypy/server/trigger.py +++ b/mypy/server/trigger.py @@ -9,7 +9,7 @@ def make_trigger(name: str) -> str: - return '<%s>' % name + return f'<{name}>' def make_wildcard_trigger(module: str) -> str: diff --git a/mypy/server/update.py b/mypy/server/update.py index 233e989a0e367..e50bb1d158a28 100644 --- a/mypy/server/update.py +++ b/mypy/server/update.py @@ -236,7 +236,7 @@ def update(self, if self.blocking_error: # Handle blocking errors first. We'll exit as soon as we find a # module that still has blocking errors. - self.manager.log_fine_grained('existing blocker: %s' % self.blocking_error[0]) + self.manager.log_fine_grained(f'existing blocker: {self.blocking_error[0]}') changed_modules = dedupe_modules([self.blocking_error] + changed_modules) blocking_error = self.blocking_error[0] self.blocking_error = None @@ -322,7 +322,7 @@ def update_one(self, and next_id not in self.previous_modules and next_id not in initial_set): self.manager.log_fine_grained( - 'skip %r (module with blocking error not in import graph)' % next_id) + f'skip {next_id!r} (module with blocking error not in import graph)') return changed_modules, (next_id, next_path), None result = self.update_module(next_id, next_path, next_id in removed_set) @@ -333,8 +333,7 @@ def update_one(self, t1 = time.time() self.manager.log_fine_grained( - "update once: {} in {:.3f}s - {} left".format( - next_id, t1 - t0, len(changed_modules))) + f"update once: {next_id} in {t1 - t0:.3f}s - {len(changed_modules)} left") return changed_modules, (next_id, next_path), blocker_messages @@ -362,7 +361,7 @@ def update_module(self, - Module which was actually processed as (id, path) tuple - If there was a blocking error, the error messages from it """ - self.manager.log_fine_grained('--- update single %r ---' % module) + self.manager.log_fine_grained(f'--- update single {module!r} ---') self.updated_modules.append(module) # builtins and friends could potentially get triggered because @@ -406,7 +405,7 @@ def update_module(self, if is_verbose(self.manager): filtered = [trigger for trigger in triggered if not trigger.endswith('__>')] - self.manager.log_fine_grained('triggered: %r' % sorted(filtered)) + self.manager.log_fine_grained(f'triggered: {sorted(filtered)!r}') self.triggered.extend(triggered | self.previous_targets_with_errors) if module in graph: graph[module].update_fine_grained_deps(self.deps) @@ -534,7 +533,7 @@ def update_module_isolated(module: str, Returns a named tuple describing the result (see above for details). """ if module not in graph: - manager.log_fine_grained('new module %r' % module) + manager.log_fine_grained(f'new module {module!r}') if not manager.fscache.isfile(path) or force_removed: delete_module(module, path, graph, manager) @@ -592,7 +591,7 @@ def restore(ids: List[str]) -> None: remaining_modules = changed_modules # The remaining modules haven't been processed yet so drop them. restore([id for id, _ in remaining_modules]) - manager.log_fine_grained('--> %r (newly imported)' % module) + manager.log_fine_grained(f'--> {module!r} (newly imported)') else: remaining_modules = [] @@ -662,7 +661,7 @@ def delete_module(module_id: str, path: str, graph: Graph, manager: BuildManager) -> None: - manager.log_fine_grained('delete module %r' % module_id) + manager.log_fine_grained(f'delete module {module_id!r}') # TODO: Remove deps for the module (this only affects memory use, not correctness) if module_id in graph: del graph[module_id] @@ -815,7 +814,7 @@ def propagate_changes_using_dependencies( if id is not None and id not in up_to_date_modules: if id not in todo: todo[id] = set() - manager.log_fine_grained('process target with error: %s' % target) + manager.log_fine_grained(f'process target with error: {target}') more_nodes, _ = lookup_target(manager, target) todo[id].update(more_nodes) triggered = set() @@ -835,7 +834,7 @@ def propagate_changes_using_dependencies( up_to_date_modules = set() targets_with_errors = set() if is_verbose(manager): - manager.log_fine_grained('triggered: %r' % list(triggered)) + manager.log_fine_grained(f'triggered: {list(triggered)!r}') return remaining_modules @@ -891,7 +890,7 @@ def find_targets_recursive( if module_id not in result: result[module_id] = set() - manager.log_fine_grained('process: %s' % target) + manager.log_fine_grained(f'process: {target}') deferred, stale_proto = lookup_target(manager, target) if stale_proto: stale_protos.add(stale_proto) @@ -1040,7 +1039,7 @@ def lookup_target(manager: BuildManager, """ def not_found() -> None: manager.log_fine_grained( - "Can't find matching target for %s (stale dependency?)" % target) + f"Can't find matching target for {target} (stale dependency?)") modules = manager.modules items = split_target(modules, target) diff --git a/mypy/strconv.py b/mypy/strconv.py index 13f3e04ef712a..8d6cf92d8f2a0 100644 --- a/mypy/strconv.py +++ b/mypy/strconv.py @@ -112,7 +112,7 @@ def visit_import(self, o: 'mypy.nodes.Import') -> str: a.append(f'{id} : {as_id}') else: a.append(id) - return 'Import:{}({})'.format(o.line, ', '.join(a)) + return f"Import:{o.line}({', '.join(a)})" def visit_import_from(self, o: 'mypy.nodes.ImportFrom') -> str: a = [] @@ -121,10 +121,10 @@ def visit_import_from(self, o: 'mypy.nodes.ImportFrom') -> str: a.append(f'{name} : {as_name}') else: a.append(name) - return 'ImportFrom:{}({}, [{}])'.format(o.line, "." * o.relative + o.id, ', '.join(a)) + return f"ImportFrom:{o.line}({'.' * o.relative + o.id}, [{', '.join(a)}])" def visit_import_all(self, o: 'mypy.nodes.ImportAll') -> str: - return 'ImportAll:{}({})'.format(o.line, "." * o.relative + o.id) + return f"ImportAll:{o.line}({'.' * o.relative + o.id})" # Definitions @@ -418,7 +418,7 @@ def visit_call_expr(self, o: 'mypy.nodes.CallExpr') -> str: elif kind == mypy.nodes.ARG_STAR2: extra.append(('DictVarArg', [o.args[i]])) else: - raise RuntimeError("unknown kind %s" % kind) + raise RuntimeError(f"unknown kind {kind}") a: List[Any] = [o.callee, ("Args", args)] return self.dump(a + extra, o) @@ -512,23 +512,19 @@ def visit_type_alias_expr(self, o: 'mypy.nodes.TypeAliasExpr') -> str: return f'TypeAliasExpr({o.type})' def visit_namedtuple_expr(self, o: 'mypy.nodes.NamedTupleExpr') -> str: - return 'NamedTupleExpr:{}({}, {})'.format(o.line, - o.info.name, - o.info.tuple_type) + return f'NamedTupleExpr:{o.line}({o.info.name}, {o.info.tuple_type})' def visit_enum_call_expr(self, o: 'mypy.nodes.EnumCallExpr') -> str: return f'EnumCallExpr:{o.line}({o.info.name}, {o.items})' def visit_typeddict_expr(self, o: 'mypy.nodes.TypedDictExpr') -> str: - return 'TypedDictExpr:{}({})'.format(o.line, - o.info.name) + return f'TypedDictExpr:{o.line}({o.info.name})' def visit__promote_expr(self, o: 'mypy.nodes.PromoteExpr') -> str: return f'PromoteExpr:{o.line}({o.type})' def visit_newtype_expr(self, o: 'mypy.nodes.NewTypeExpr') -> str: - return 'NewTypeExpr:{}({}, {})'.format(o.line, o.name, - self.dump([o.old_type], o)) + return f'NewTypeExpr:{o.line}({o.name}, {self.dump([o.old_type], o)})' def visit_lambda_expr(self, o: 'mypy.nodes.LambdaExpr') -> str: a = self.func_helper(o) diff --git a/mypy/stubdoc.py b/mypy/stubdoc.py index a596ddb4f78dc..175b6f9f432cc 100644 --- a/mypy/stubdoc.py +++ b/mypy/stubdoc.py @@ -311,8 +311,8 @@ def build_signature(positional: Sequence[str], if arg.startswith('*'): args.append(arg) else: - args.append('%s=...' % arg) - sig = '(%s)' % ', '.join(args) + args.append(f'{arg}=...') + sig = f"({', '.join(args)})" # Ad-hoc fixes. sig = sig.replace('(self)', '') return sig diff --git a/mypy/stubgen.py b/mypy/stubgen.py index 41fc58a2b0fce..2d3e8e8f48ef4 100755 --- a/mypy/stubgen.py +++ b/mypy/stubgen.py @@ -309,8 +309,8 @@ def visit_call_expr(self, node: CallExpr) -> str: elif kind == ARG_NAMED: args.append(f'{name}={arg.accept(self)}') else: - raise ValueError("Unknown argument kind %s in call" % kind) - return "{}({})".format(callee, ", ".join(args)) + raise ValueError(f"Unknown argument kind {kind} in call") + return f"{callee}({', '.join(args)})" def visit_name_expr(self, node: NameExpr) -> str: self.stubgen.import_tracker.require_name(node.name) @@ -339,7 +339,7 @@ def visit_tuple_expr(self, node: TupleExpr) -> str: return ", ".join(n.accept(self) for n in node.items) def visit_list_expr(self, node: ListExpr) -> str: - return "[{}]".format(", ".join(n.accept(self) for n in node.items)) + return f"[{', '.join(n.accept(self) for n in node.items)}]" def visit_ellipsis(self, node: EllipsisExpr) -> str: return "..." @@ -454,7 +454,7 @@ def import_lines(self) -> List[str]: # Now generate all the from ... import ... lines collected in module_map for module, names in sorted(module_map.items()): - result.append("from {} import {}\n".format(module, ', '.join(sorted(names)))) + result.append(f"from {module} import {', '.join(sorted(names))}\n") return result @@ -589,7 +589,7 @@ def visit_mypy_file(self, o: MypyFile) -> None: self.add('\n') self.add('# Names in __all__ with no definition:\n') for name in sorted(undefined_names): - self.add('# %s\n' % name) + self.add(f'# {name}\n') def visit_overloaded_func_def(self, o: OverloadedFuncDef) -> None: """@property with setters and getters, or @overload chain""" @@ -635,7 +635,7 @@ def visit_func_def(self, o: FuncDef, is_abstract: bool = False, for s in self._decorators: self.add(s) self.clear_decorators() - self.add("{}{}def {}(".format(self._indent, 'async ' if o.is_coroutine else '', o.name)) + self.add(f"{self._indent}{'async ' if o.is_coroutine else ''}def {o.name}(") self.record_name(o.name) args: List[str] = [] for i, arg_ in enumerate(o.arguments): @@ -799,7 +799,7 @@ def process_member_expr_decorator(self, expr: MemberExpr, context: Decorator) -> is_abstract = False is_overload = False if expr.name == 'setter' and isinstance(expr.expr, NameExpr): - self.add_decorator('%s.setter' % expr.expr.name) + self.add_decorator(f'{expr.expr.name}.setter') elif (isinstance(expr.expr, NameExpr) and (expr.expr.name == 'abc' or self.import_tracker.reverse_alias.get(expr.expr.name) == 'abc') and @@ -835,7 +835,7 @@ def process_member_expr_decorator(self, expr: MemberExpr, context: Decorator) -> self.import_tracker.reverse_alias.get(expr.expr.name) in TYPING_MODULE_NAMES) and expr.name == 'overload'): self.import_tracker.require_name(expr.expr.name) - self.add_decorator('{}.{}'.format(expr.expr.name, 'overload')) + self.add_decorator(f"{expr.expr.name}.overload") is_overload = True return is_abstract, is_overload @@ -865,7 +865,7 @@ def visit_class_def(self, o: ClassDef) -> None: base_types.append(type_str) self.add_typing_import('Protocol') if base_types: - self.add('(%s)' % ', '.join(base_types)) + self.add(f"({', '.join(base_types)})") self.add(':\n') n = len(self._output) self._indent += ' ' @@ -1036,7 +1036,7 @@ def visit_if_stmt(self, o: IfStmt) -> None: super().visit_if_stmt(o) def visit_import_all(self, o: ImportAll) -> None: - self.add_import_line('from {}{} import *\n'.format('.' * o.relative, o.id)) + self.add_import_line(f"from {'.' * o.relative}{o.id} import *\n") def visit_import_from(self, o: ImportFrom) -> None: exported_names: Set[str] = set() @@ -1227,7 +1227,7 @@ def get_str_type_of_node(self, rvalue: Expression, if can_infer_optional and \ isinstance(rvalue, NameExpr) and rvalue.name == 'None': self.add_typing_import('Incomplete') - return '{} | None'.format(self.typing_name('Incomplete')) + return f"{self.typing_name('Incomplete')} | None" if can_be_any: self.add_typing_import('Incomplete') return self.typing_name('Incomplete') @@ -1492,7 +1492,7 @@ def parse_source_file(mod: StubSource, mypy_options: MypyOptions) -> None: if errors.is_blockers(): # Syntax error! for m in errors.new_messages(): - sys.stderr.write('%s\n' % m) + sys.stderr.write(f'{m}\n') sys.exit(1) @@ -1504,7 +1504,7 @@ def generate_asts_for_modules(py_modules: List[StubSource], if not py_modules: return # Nothing to do here, but there may be C modules if verbose: - print('Processing %d files...' % len(py_modules)) + print(f'Processing {len(py_modules)} files...') if parse_only: for mod in py_modules: parse_source_file(mod, mypy_options) @@ -1557,7 +1557,7 @@ def collect_docs_signatures(doc_dir: str) -> Tuple[Dict[str, str], Dict[str, str """ all_sigs: List[Sig] = [] all_class_sigs: List[Sig] = [] - for path in glob.glob('%s/*.rst' % doc_dir): + for path in glob.glob(f'{doc_dir}/*.rst'): with open(path) as f: loc_sigs, loc_class_sigs = parse_all_signatures(f.readlines()) all_sigs += loc_sigs @@ -1610,9 +1610,9 @@ def generate_stubs(options: Options) -> None: if not options.quiet and num_modules > 0: print('Processed %d modules' % num_modules) if len(files) == 1: - print('Generated %s' % files[0]) + print(f'Generated {files[0]}') else: - print('Generated files under %s' % common_dir_prefix(files) + os.sep) + print(f'Generated files under {common_dir_prefix(files)}' + os.sep) HEADER = """%(prog)s [-h] [--py2] [more options, see -h] diff --git a/mypy/stubgenc.py b/mypy/stubgenc.py index e9fa0ef62bb2d..682ed418ffc77 100755 --- a/mypy/stubgenc.py +++ b/mypy/stubgenc.py @@ -47,7 +47,7 @@ def generate_stub_for_c_module(module_name: str, will be overwritten. """ module = importlib.import_module(module_name) - assert is_c_module(module), '%s is not a C module' % module_name + assert is_c_module(module), f'{module_name} is not a C module' subdir = os.path.dirname(target) if subdir and not os.path.isdir(subdir): os.makedirs(subdir) @@ -90,7 +90,7 @@ def generate_stub_for_c_module(module_name: str, output = add_typing_import(output) with open(target, 'w') as file: for line in output: - file.write('%s\n' % line) + file.write(f'{line}\n') def add_typing_import(output: List[str]) -> List[str]: @@ -100,7 +100,7 @@ def add_typing_import(output: List[str]) -> List[str]: if any(re.search(r'\b%s\b' % name, line) for line in output): names.append(name) if names: - return ['from typing import %s' % ', '.join(names), ''] + output + return [f"from typing import {', '.join(names)}", ''] + output else: return output[:] @@ -405,19 +405,19 @@ def generate_c_type_stub(module: ModuleType, output.append('') output.append(' ' + line) for line in static_properties: - output.append(' %s' % line) + output.append(f' {line}') for line in rw_properties: - output.append(' %s' % line) + output.append(f' {line}') for line in methods: - output.append(' %s' % line) + output.append(f' {line}') for line in ro_properties: - output.append(' %s' % line) + output.append(f' {line}') else: output.append(f'class {class_name}{bases_str}: ...') def get_type_fullname(typ: type) -> str: - return '{}.{}'.format(typ.__module__, getattr(typ, '__qualname__', typ.__name__)) + return f"{typ.__module__}.{getattr(typ, '__qualname__', typ.__name__)}" def method_name_sort_key(name: str) -> Tuple[int, str]: diff --git a/mypy/stubutil.py b/mypy/stubutil.py index 8ed73cab203b6..55f8c0b29345f 100644 --- a/mypy/stubutil.py +++ b/mypy/stubutil.py @@ -54,10 +54,10 @@ def walk_packages(inspect: ModuleInspect, """ for package_name in packages: if package_name in NOT_IMPORTABLE_MODULES: - print('%s: Skipped (blacklisted)' % package_name) + print(f'{package_name}: Skipped (blacklisted)') continue if verbose: - print('Trying to import %r for runtime introspection' % package_name) + print(f'Trying to import {package_name!r} for runtime introspection') try: prop = inspect.get_package_properties(package_name) except InspectError: @@ -144,7 +144,7 @@ def find_module_path_and_all_py3(inspect: ModuleInspect, # TODO: Support custom interpreters. if verbose: - print('Trying to import %r for runtime introspection' % module) + print(f'Trying to import {module!r} for runtime introspection') try: mod = inspect.get_package_properties(module) except InspectError as e: @@ -166,7 +166,7 @@ def generate_guarded(mod: str, target: str, Optionally report success. """ if verbose: - print('Processing %s' % mod) + print(f'Processing {mod}') try: yield except Exception as e: @@ -177,7 +177,7 @@ def generate_guarded(mod: str, target: str, print("Stub generation failed for", mod, file=sys.stderr) else: if verbose: - print('Created %s' % target) + print(f'Created {target}') PY2_MODULES = {'cStringIO', 'urlparse', 'collections.UserDict'} diff --git a/mypy/suggestions.py b/mypy/suggestions.py index fbbf00118e82c..d311d0edde638 100644 --- a/mypy/suggestions.py +++ b/mypy/suggestions.py @@ -485,7 +485,7 @@ def format_args(self, if name: arg = f"{name}={arg}" args.append(arg) - return "(%s)" % (", ".join(args)) + return f"({', '.join(args)})" def find_node(self, key: str) -> Tuple[str, str, FuncDef]: """From a target name, return module/target names and the func def. @@ -518,10 +518,10 @@ def find_node(self, key: str) -> Tuple[str, str, FuncDef]: if isinstance(node, Decorator): node = self.extract_from_decorator(node) if not node: - raise SuggestionFailure("Object %s is a decorator we can't handle" % key) + raise SuggestionFailure(f"Object {key} is a decorator we can't handle") if not isinstance(node, FuncDef): - raise SuggestionFailure("Object %s is not a function" % key) + raise SuggestionFailure(f"Object {key} is not a function") return modname, tail, node @@ -686,10 +686,7 @@ def pyannotate_signature( def format_signature(self, sig: PyAnnotateSignature) -> str: """Format a callable type in a way suitable as an annotation... kind of""" - return "({}) -> {}".format( - ", ".join(sig['arg_types']), - sig['return_type'] - ) + return f"({', '.join(sig['arg_types'])}) -> {sig['return_type']}" def format_type(self, cur_module: Optional[str], typ: Type) -> str: if self.use_fixme and isinstance(get_proper_type(typ), AnyType): @@ -843,7 +840,7 @@ def visit_callable_type(self, t: CallableType) -> str: # other thing, and I suspect this will produce more better # results than falling back to `...` args = [typ.accept(self) for typ in t.arg_types] - arg_str = "[{}]".format(", ".join(args)) + arg_str = f"[{', '.join(args)}]" return f"Callable[{arg_str}, {t.ret_type.accept(self)}]" diff --git a/mypy/test/data.py b/mypy/test/data.py index 9f1c6a1aa24c0..de7e38693f237 100644 --- a/mypy/test/data.py +++ b/mypy/test/data.py @@ -162,13 +162,11 @@ def parse_test_case(case: 'DataDrivenTestCase') -> None: triggered = item.data else: raise ValueError( - 'Invalid section header {} in {} at line {}'.format( - item.id, case.file, item.line)) + f'Invalid section header {item.id} in {case.file} at line {item.line}') if out_section_missing: raise ValueError( - '{}, line {}: Required output section not found'.format( - case.file, first_item.line)) + f'{case.file}, line {first_item.line}: Required output section not found') for passnum in stale_modules.keys(): if passnum not in rechecked_modules: @@ -500,8 +498,7 @@ def expand_errors(input: List[str], output: List[str], fnam: str) -> None: output.append( f'{fnam}:{i + 1}: {severity}: {message}') else: - output.append('{}:{}:{}: {}: {}'.format( - fnam, i + 1, col, severity, message)) + output.append(f'{fnam}:{i + 1}:{col}: {severity}: {message}') def fix_win_path(line: str) -> str: diff --git a/mypy/test/testcheck.py b/mypy/test/testcheck.py index 2f74e543d4690..f0dc4bc6a6715 100644 --- a/mypy/test/testcheck.py +++ b/mypy/test/testcheck.py @@ -346,7 +346,7 @@ def parse_module(self, cache = FindModuleCache(search_paths, fscache=None, options=None) for module_name in module_names.split(' '): path = cache.find_module(module_name) - assert isinstance(path, str), "Can't find ad hoc case file: %s" % module_name + assert isinstance(path, str), f"Can't find ad hoc case file: {module_name}" with open(path, encoding='utf8') as f: program_text = f.read() out.append((module_name, path, program_text)) diff --git a/mypy/test/testdeps.py b/mypy/test/testdeps.py index d3d184be7f017..7446d44339a0b 100644 --- a/mypy/test/testdeps.py +++ b/mypy/test/testdeps.py @@ -67,15 +67,14 @@ def run_case(self, testcase: DataDrivenTestCase) -> None: if source.startswith((' {', '.join(sorted(targets))}" # Clean up output a bit line = line.replace('__main__', 'm') a.append(line) assert_string_arrays_equal( testcase.output, a, - 'Invalid output ({}, line {})'.format(testcase.file, - testcase.line)) + f'Invalid output ({testcase.file}, line {testcase.line})') def build(self, source: str, diff --git a/mypy/test/testdiff.py b/mypy/test/testdiff.py index 9e1e9097152b6..56f4564e91d3a 100644 --- a/mypy/test/testdiff.py +++ b/mypy/test/testdiff.py @@ -47,8 +47,7 @@ def run_case(self, testcase: DataDrivenTestCase) -> None: assert_string_arrays_equal( testcase.output, a, - 'Invalid output ({}, line {})'.format(testcase.file, - testcase.line)) + f'Invalid output ({testcase.file}, line {testcase.line})') def build(self, source: str, options: Options) -> Tuple[List[str], Optional[Dict[str, MypyFile]]]: diff --git a/mypy/test/testfinegrained.py b/mypy/test/testfinegrained.py index 9fbfdc4395fe7..783e21e2869e3 100644 --- a/mypy/test/testfinegrained.py +++ b/mypy/test/testfinegrained.py @@ -130,15 +130,13 @@ def run_case(self, testcase: DataDrivenTestCase) -> None: assert_string_arrays_equal( testcase.output, a, - 'Invalid output ({}, line {})'.format( - testcase.file, testcase.line)) + f'Invalid output ({testcase.file}, line {testcase.line})') if testcase.triggered: assert_string_arrays_equal( testcase.triggered, self.format_triggered(all_triggered), - 'Invalid active triggers ({}, line {})'.format(testcase.file, - testcase.line)) + f'Invalid active triggers ({testcase.file}, line {testcase.line})') def get_options(self, source: str, diff --git a/mypy/test/testmerge.py b/mypy/test/testmerge.py index 2e2f6b67d34a7..fe0de2a7fe2d4 100644 --- a/mypy/test/testmerge.py +++ b/mypy/test/testmerge.py @@ -98,8 +98,7 @@ def run_case(self, testcase: DataDrivenTestCase) -> None: assert_string_arrays_equal( testcase.output, a, - 'Invalid output ({}, line {})'.format(testcase.file, - testcase.line)) + f'Invalid output ({testcase.file}, line {testcase.line})') def build(self, source: str, testcase: DataDrivenTestCase) -> Optional[BuildResult]: options = parse_options(source, testcase, incremental_step=1) @@ -142,7 +141,7 @@ def dump(self, return self.dump_symbol_tables(modules) elif kind == TYPES: return self.dump_types(manager) - assert False, 'Invalid kind %s' % kind + assert False, f'Invalid kind {kind}' def dump_asts(self, modules: Dict[str, MypyFile]) -> List[str]: a = [] @@ -177,8 +176,7 @@ def format_symbol_table_node(self, node: SymbolTableNode) -> str: return 'UNBOUND_IMPORTED' return 'None' if isinstance(node.node, Node): - s = '{}<{}>'.format(str(type(node.node).__name__), - self.id_mapper.id(node.node)) + s = f'{str(type(node.node).__name__)}<{self.id_mapper.id(node.node)}>' else: s = f'? ({type(node.node)})' if (isinstance(node.node, Var) and node.node.type and @@ -230,9 +228,7 @@ def dump_types(self, manager: FineGrainedBuildManager) -> List[str]: for expr in sorted(type_map, key=lambda n: (n.line, short_type(n), str(n) + str(type_map[n]))): typ = type_map[expr] - a.append('{}:{}: {}'.format(short_type(expr), - expr.line, - self.format_type(typ))) + a.append(f'{short_type(expr)}:{expr.line}: {self.format_type(typ)}') return a def format_type(self, typ: Type) -> str: diff --git a/mypy/test/testparse.py b/mypy/test/testparse.py index 1587147c0777d..340d6b9044765 100644 --- a/mypy/test/testparse.py +++ b/mypy/test/testparse.py @@ -83,5 +83,4 @@ def test_parse_error(testcase: DataDrivenTestCase) -> None: # are equivalent. assert_string_arrays_equal( testcase.output, e.messages, - 'Invalid compiler output ({}, line {})'.format(testcase.file, - testcase.line)) + f'Invalid compiler output ({testcase.file}, line {testcase.line})') diff --git a/mypy/test/testpythoneval.py b/mypy/test/testpythoneval.py index 8002b7410ee8d..7707382947556 100644 --- a/mypy/test/testpythoneval.py +++ b/mypy/test/testpythoneval.py @@ -70,7 +70,7 @@ def test_python_evaluation(testcase: DataDrivenTestCase, cache_dir: str) -> None return else: interpreter = python3_path - mypy_cmdline.append('--python-version={}'.format('.'.join(map(str, PYTHON3_VERSION)))) + mypy_cmdline.append(f"--python-version={'.'.join(map(str, PYTHON3_VERSION))}") m = re.search('# flags: (.*)$', '\n'.join(testcase.input), re.MULTILINE) if m: diff --git a/mypy/test/testsemanal.py b/mypy/test/testsemanal.py index a58dc4a3960a0..c7a623507ac15 100644 --- a/mypy/test/testsemanal.py +++ b/mypy/test/testsemanal.py @@ -102,8 +102,7 @@ def test_semanal(testcase: DataDrivenTestCase) -> None: a = normalize_error_messages(a) assert_string_arrays_equal( testcase.output, a, - 'Invalid semantic analyzer output ({}, line {})'.format(testcase.file, - testcase.line)) + f'Invalid semantic analyzer output ({testcase.file}, line {testcase.line})') # Semantic analyzer error test cases @@ -165,8 +164,7 @@ def run_case(self, testcase: DataDrivenTestCase) -> None: a = e.messages assert_string_arrays_equal( testcase.output, a, - 'Invalid semantic analyzer output ({}, line {})'.format( - testcase.file, testcase.line)) + f'Invalid semantic analyzer output ({testcase.file}, line {testcase.line})') # Type info export test cases @@ -200,8 +198,7 @@ def run_case(self, testcase: DataDrivenTestCase) -> None: a = e.messages assert_string_arrays_equal( testcase.output, a, - 'Invalid semantic analyzer output ({}, line {})'.format( - testcase.file, testcase.line)) + f'Invalid semantic analyzer output ({testcase.file}, line {testcase.line})') class TypeInfoMap(Dict[str, TypeInfo]): diff --git a/mypy/test/teststubgen.py b/mypy/test/teststubgen.py index 97e3d98597cb4..3c2b2967fb3cb 100644 --- a/mypy/test/teststubgen.py +++ b/mypy/test/teststubgen.py @@ -662,11 +662,11 @@ def test_infer_setitem_sig(self) -> None: def test_infer_binary_op_sig(self) -> None: for op in ('eq', 'ne', 'lt', 'le', 'gt', 'ge', 'add', 'radd', 'sub', 'rsub', 'mul', 'rmul'): - assert_equal(infer_method_sig('__%s__' % op), [self_arg, ArgSig(name='other')]) + assert_equal(infer_method_sig(f'__{op}__'), [self_arg, ArgSig(name='other')]) def test_infer_unary_op_sig(self) -> None: for op in ('neg', 'pos'): - assert_equal(infer_method_sig('__%s__' % op), [self_arg]) + assert_equal(infer_method_sig(f'__{op}__'), [self_arg]) def test_generate_c_type_stub_no_crash_for_object(self) -> None: output: List[str] = [] @@ -1074,7 +1074,7 @@ def test_non_existent(self) -> None: def module_to_path(out_dir: str, module: str) -> str: - fnam = os.path.join(out_dir, '{}.pyi'.format(module.replace('.', '/'))) + fnam = os.path.join(out_dir, f"{module.replace('.', '/')}.pyi") if not os.path.exists(fnam): alt_fnam = fnam.replace('.pyi', '/__init__.pyi') if os.path.exists(alt_fnam): diff --git a/mypy/test/teststubtest.py b/mypy/test/teststubtest.py index a17edbea24aab..de48c9ce2723d 100644 --- a/mypy/test/teststubtest.py +++ b/mypy/test/teststubtest.py @@ -1167,8 +1167,7 @@ def test_config_file(self) -> None: runtime = "temp = 5\n" stub = "from decimal import Decimal\ntemp: Decimal\n" config_file = ( - "[mypy]\n" - "plugins={}/test-data/unit/plugins/decimal_to_int.py\n".format(root_dir) + f"[mypy]\nplugins={root_dir}/test-data/unit/plugins/decimal_to_int.py\n" ) output = run_stubtest(stub=stub, runtime=runtime, options=[]) assert remove_color_code(output) == ( diff --git a/mypy/test/testtransform.py b/mypy/test/testtransform.py index e1e3b6ab63ed5..bd400b254ff42 100644 --- a/mypy/test/testtransform.py +++ b/mypy/test/testtransform.py @@ -72,5 +72,4 @@ def test_transform(testcase: DataDrivenTestCase) -> None: a = normalize_error_messages(a) assert_string_arrays_equal( testcase.output, a, - 'Invalid semantic analyzer output ({}, line {})'.format(testcase.file, - testcase.line)) + f'Invalid semantic analyzer output ({testcase.file}, line {testcase.line})') diff --git a/mypy/test/testtypegen.py b/mypy/test/testtypegen.py index c652b38ba6fef..a91cd0a2972d3 100644 --- a/mypy/test/testtypegen.py +++ b/mypy/test/testtypegen.py @@ -68,5 +68,4 @@ def run_case(self, testcase: DataDrivenTestCase) -> None: a = e.messages assert_string_arrays_equal( testcase.output, a, - 'Invalid type checker output ({}, line {})'.format(testcase.file, - testcase.line)) + f'Invalid type checker output ({testcase.file}, line {testcase.line})') diff --git a/mypy/typeanal.py b/mypy/typeanal.py index 536e170a9644d..d734a1cc330f4 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -94,7 +94,8 @@ def analyze_type_alias(node: Expression, def no_subscript_builtin_alias(name: str, propose_alt: bool = True) -> str: - msg = '"{}" is not subscriptable'.format(name.split('.')[-1]) + class_name = name.split('.')[-1] + msg = f'"{class_name}" is not subscriptable' # This should never be called if the python_version is 3.9 or newer nongen_builtins = get_nongen_builtins((3, 8)) replacement = nongen_builtins[name] @@ -971,8 +972,7 @@ def analyze_callable_args(self, arglist: TypeList) -> Optional[Tuple[List[Type], # Looking it up already put an error message in return None elif found.fullname not in ARG_KINDS_BY_CONSTRUCTOR: - self.fail('Invalid argument constructor "{}"'.format( - found.fullname), arg) + self.fail(f'Invalid argument constructor "{found.fullname}"', arg) return None else: assert found.fullname is not None @@ -1322,8 +1322,7 @@ def fix_instance(t: Instance, fail: MsgCallback, note: MsgCallback, act = str(len(t.args)) if act == '0': act = 'none' - fail('"{}" expects {}, but {} given'.format( - t.type.name, s, act), t, code=codes.TYPE_ARG) + fail(f'"{t.type.name}" expects {s}, but {act} given', t, code=codes.TYPE_ARG) # Construct the correct number of type arguments, as # otherwise the type checker may crash as it expects # things to be right. diff --git a/mypy/types.py b/mypy/types.py index a958e6c67dcce..8f45e87b8fb9e 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -2754,7 +2754,7 @@ def visit_callable_type(self, t: CallableType) -> str: if isinstance(var, TypeVarType): # We reimplement TypeVarType.__repr__ here in order to support id_mapper. if var.values: - vals = '({})'.format(', '.join(val.accept(self) for val in var.values)) + vals = f"({', '.join(val.accept(self) for val in var.values)})" vs.append(f'{var.name} in {vals}') elif not is_named_instance(var.upper_bound, 'builtins.object'): vs.append(f'{var.name} <: {var.upper_bound.accept(self)}') @@ -2763,7 +2763,7 @@ def visit_callable_type(self, t: CallableType) -> str: else: # For other TypeVarLikeTypes, just use the name vs.append(var.name) - s = '{} {}'.format('[{}]'.format(', '.join(vs)), s) + s = f"[{', '.join(vs)}] {s}" return f'def {s}' @@ -2771,7 +2771,7 @@ def visit_overloaded(self, t: Overloaded) -> str: a = [] for i in t.items: a.append(i.accept(self)) - return 'Overload({})'.format(', '.join(a)) + return f"Overload({', '.join(a)})" def visit_tuple_type(self, t: TupleType) -> str: s = self.list_str(t.items) diff --git a/mypy/util.py b/mypy/util.py index 1a3628458c483..c207fb7e18cd0 100644 --- a/mypy/util.py +++ b/mypy/util.py @@ -743,7 +743,7 @@ def format_error( if blockers: msg += ' (errors prevented further checking)' else: - msg += ' (checked {} source file{})'.format(n_sources, 's' if n_sources != 1 else '') + msg += f" (checked {n_sources} source file{'s' if n_sources != 1 else ''})" if not use_color: return msg return self.style(msg, 'red', bold=True) From ad177f99fd3322072e389a1a7432ee7b15c84472 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sun, 1 May 2022 17:16:16 -0600 Subject: [PATCH 274/377] mypyc: run pyupgrade (#12708) Re-attempt of #10741 Ran: `pyupgrade --py36-plus $(fd -e py) --keep-runtime-typing` I mostly only needed to change things where NamedTuple comments got dropped. --- mypyc/analysis/dataflow.py | 2 +- mypyc/analysis/ircheck.py | 8 +- mypyc/build.py | 12 +- mypyc/codegen/cstring.py | 4 +- mypyc/codegen/emit.py | 186 +++++++++++++-------------- mypyc/codegen/emitclass.py | 152 +++++++++++----------- mypyc/codegen/emitfunc.py | 82 ++++++------ mypyc/codegen/emitmodule.py | 112 ++++++++-------- mypyc/codegen/emitwrapper.py | 90 ++++++------- mypyc/common.py | 6 +- mypyc/crash.py | 2 +- mypyc/ir/class_ir.py | 11 +- mypyc/ir/func_ir.py | 8 +- mypyc/ir/ops.py | 6 +- mypyc/ir/pprint.py | 24 ++-- mypyc/ir/rtypes.py | 24 ++-- mypyc/irbuild/builder.py | 8 +- mypyc/irbuild/callable_class.py | 2 +- mypyc/irbuild/classdef.py | 4 +- mypyc/irbuild/env_class.py | 4 +- mypyc/irbuild/function.py | 4 +- mypyc/irbuild/generator.py | 2 +- mypyc/irbuild/ll_builder.py | 6 +- mypyc/irbuild/statement.py | 2 +- mypyc/namegen.py | 2 +- mypyc/primitives/int_ops.py | 2 + mypyc/primitives/registry.py | 1 + mypyc/test-data/fixtures/testutil.py | 6 +- mypyc/test/test_cheader.py | 6 +- mypyc/test/test_commandline.py | 2 +- mypyc/test/test_run.py | 4 +- mypyc/test/test_serialization.py | 14 +- mypyc/test/testutil.py | 8 +- mypyc/transform/uninit.py | 2 +- 34 files changed, 406 insertions(+), 402 deletions(-) diff --git a/mypyc/analysis/dataflow.py b/mypyc/analysis/dataflow.py index 9b459f77edbe7..3b79f101a670a 100644 --- a/mypyc/analysis/dataflow.py +++ b/mypyc/analysis/dataflow.py @@ -125,7 +125,7 @@ def __init__(self, before: 'AnalysisDict[T]', after: 'AnalysisDict[T]') -> None: self.after = after def __str__(self) -> str: - return 'before: %s\nafter: %s\n' % (self.before, self.after) + return f'before: {self.before}\nafter: {self.after}\n' GenAndKill = Tuple[Set[Value], Set[Value]] diff --git a/mypyc/analysis/ircheck.py b/mypyc/analysis/ircheck.py index 6450766f404c3..6c8e8d7f18e5b 100644 --- a/mypyc/analysis/ircheck.py +++ b/mypyc/analysis/ircheck.py @@ -17,7 +17,7 @@ from mypyc.ir.func_ir import FuncIR, FUNC_STATICMETHOD -class FnError(object): +class FnError: def __init__(self, source: Union[Op, BasicBlock], desc: str) -> None: self.source = source self.desc = desc @@ -129,8 +129,7 @@ def check_op_sources_valid(fn: FuncIR) -> List[FnError]: return errors -disjoint_types = set( - [ +disjoint_types = { int_rprimitive.name, bytes_rprimitive.name, str_rprimitive.name, @@ -139,8 +138,7 @@ def check_op_sources_valid(fn: FuncIR) -> List[FnError]: set_rprimitive.name, tuple_rprimitive.name, range_rprimitive.name, - ] -) +} def can_coerce_to(src: RType, dest: RType) -> bool: diff --git a/mypyc/build.py b/mypyc/build.py index 2c04eed9e64c0..f5ff0201ffaf9 100644 --- a/mypyc/build.py +++ b/mypyc/build.py @@ -200,7 +200,7 @@ def generate_c(sources: List[BuildSource], t1 = time.time() if compiler_options.verbose: - print("Parsed and typechecked in {:.3f}s".format(t1 - t0)) + print(f"Parsed and typechecked in {t1 - t0:.3f}s") if not messages and result: errors = Errors() @@ -212,7 +212,7 @@ def generate_c(sources: List[BuildSource], t2 = time.time() if compiler_options.verbose: - print("Compiled to C in {:.3f}s".format(t2 - t1)) + print(f"Compiled to C in {t2 - t1:.3f}s") # ... you know, just in case. if options.junit_xml: @@ -304,7 +304,7 @@ def write_file(path: str, contents: str) -> None: try: with open(path, 'rb') as f: old_contents: Optional[bytes] = f.read() - except IOError: + except OSError: old_contents = None if old_contents != encoded_contents: os.makedirs(os.path.dirname(path), exist_ok=True) @@ -513,8 +513,8 @@ def mypycify( cflags: List[str] = [] if compiler.compiler_type == 'unix': cflags += [ - '-O{}'.format(opt_level), - '-g{}'.format(debug_level), + f'-O{opt_level}', + f'-g{debug_level}', '-Werror', '-Wno-unused-function', '-Wno-unused-label', '-Wno-unreachable-code', '-Wno-unused-variable', '-Wno-unused-command-line-argument', '-Wno-unknown-warning-option', @@ -535,7 +535,7 @@ def mypycify( elif debug_level in ('2', '3'): debug_level = "FULL" cflags += [ - '/O{}'.format(opt_level), + f'/O{opt_level}', f'/DEBUG:{debug_level}', '/wd4102', # unreferenced label '/wd4101', # unreferenced local variable diff --git a/mypyc/codegen/cstring.py b/mypyc/codegen/cstring.py index 3626d2625e84b..dba2bf8142462 100644 --- a/mypyc/codegen/cstring.py +++ b/mypyc/codegen/cstring.py @@ -23,7 +23,7 @@ from typing_extensions import Final -CHAR_MAP: Final = ["\\{:03o}".format(i) for i in range(256)] +CHAR_MAP: Final = [f"\\{i:03o}" for i in range(256)] # It is safe to use string.printable as it always uses the C locale. for c in string.printable: @@ -32,7 +32,7 @@ # These assignments must come last because we prioritize simple escape # sequences over any other representation. for c in ('\'', '"', '\\', 'a', 'b', 'f', 'n', 'r', 't', 'v'): - escaped = '\\{}'.format(c) + escaped = f'\\{c}' decoded = escaped.encode('ascii').decode('unicode_escape') CHAR_MAP[ord(decoded)] = escaped diff --git a/mypyc/codegen/emit.py b/mypyc/codegen/emit.py index 531121134b037..94ea940ca3e6e 100644 --- a/mypyc/codegen/emit.py +++ b/mypyc/codegen/emit.py @@ -161,7 +161,7 @@ def emit_label(self, label: Union[BasicBlock, str]) -> None: else: text = self.label(label) # Extra semicolon prevents an error when the next line declares a tempvar - self.fragments.append('{}: ;\n'.format(text)) + self.fragments.append(f'{text}: ;\n') def emit_from_emitter(self, emitter: 'Emitter') -> None: self.fragments.extend(emitter.fragments) @@ -201,7 +201,7 @@ def get_module_group_prefix(self, module_name: str) -> str: target_group_name = groups.get(module_name) if target_group_name and target_group_name != self.context.group_name: self.context.group_deps.add(target_group_name) - return 'exports_{}.'.format(exported_name(target_group_name)) + return f'exports_{exported_name(target_group_name)}.' else: return '' @@ -225,7 +225,7 @@ def static_name(self, id: str, module: Optional[str], prefix: str = STATIC_PREFI # the pointer also. star_maybe = '*' if lib_prefix else '' suffix = self.names.private_name(module or '', id) - return '{}{}{}{}'.format(star_maybe, lib_prefix, prefix, suffix) + return f'{star_maybe}{lib_prefix}{prefix}{suffix}' def type_struct_name(self, cl: ClassIR) -> str: return self.static_name(cl.name, cl.module_name, prefix=TYPE_PREFIX) @@ -254,13 +254,13 @@ def c_error_value(self, rtype: RType) -> str: return self.c_undefined_value(rtype) def native_function_name(self, fn: FuncDecl) -> str: - return '{}{}'.format(NATIVE_PREFIX, fn.cname(self.names)) + return f'{NATIVE_PREFIX}{fn.cname(self.names)}' def tuple_c_declaration(self, rtuple: RTuple) -> List[str]: result = [ - '#ifndef MYPYC_DECLARED_{}'.format(rtuple.struct_name), - '#define MYPYC_DECLARED_{}'.format(rtuple.struct_name), - 'typedef struct {} {{'.format(rtuple.struct_name), + f'#ifndef MYPYC_DECLARED_{rtuple.struct_name}', + f'#define MYPYC_DECLARED_{rtuple.struct_name}', + f'typedef struct {rtuple.struct_name} {{', ] if len(rtuple.types) == 0: # empty tuple # Empty tuples contain a flag so that they can still indicate @@ -269,9 +269,9 @@ def tuple_c_declaration(self, rtuple: RTuple) -> List[str]: else: i = 0 for typ in rtuple.types: - result.append('{}f{};'.format(self.ctype_spaced(typ), i)) + result.append(f'{self.ctype_spaced(typ)}f{i};') i += 1 - result.append('}} {};'.format(rtuple.struct_name)) + result.append(f'}} {rtuple.struct_name};') values = self.tuple_undefined_value_helper(rtuple) result.append('static {} {} = {{ {} }};'.format( self.ctype(rtuple), self.tuple_undefined_value(rtuple), ''.join(values))) @@ -295,8 +295,8 @@ def emit_undefined_attr_check(self, rtype: RType, attr_expr: str, attr_expr, compare, self.c_undefined_value(rtype) ) if unlikely: - check = '(unlikely{})'.format(check) - self.emit_line('if {} {{'.format(check)) + check = f'(unlikely{check})' + self.emit_line(f'if {check} {{') def tuple_undefined_check_cond( self, rtuple: RTuple, tuple_expr_in_c: str, @@ -363,7 +363,7 @@ def emit_inc_ref(self, dest: str, rtype: RType, *, rare: bool = False) -> None: self.emit_line('CPyTagged_INCREF(%s);' % dest) elif isinstance(rtype, RTuple): for i, item_type in enumerate(rtype.types): - self.emit_inc_ref('{}.f{}'.format(dest, i), item_type) + self.emit_inc_ref(f'{dest}.f{i}', item_type) elif not rtype.is_unboxed: # Always inline, since this is a simple op self.emit_line('CPy_INCREF(%s);' % dest) @@ -385,19 +385,19 @@ def emit_dec_ref(self, x = 'X' if is_xdec else '' if is_int_rprimitive(rtype): if rare: - self.emit_line('CPyTagged_%sDecRef(%s);' % (x, dest)) + self.emit_line(f'CPyTagged_{x}DecRef({dest});') else: # Inlined - self.emit_line('CPyTagged_%sDECREF(%s);' % (x, dest)) + self.emit_line(f'CPyTagged_{x}DECREF({dest});') elif isinstance(rtype, RTuple): for i, item_type in enumerate(rtype.types): - self.emit_dec_ref('{}.f{}'.format(dest, i), item_type, is_xdec=is_xdec, rare=rare) + self.emit_dec_ref(f'{dest}.f{i}', item_type, is_xdec=is_xdec, rare=rare) elif not rtype.is_unboxed: if rare: - self.emit_line('CPy_%sDecRef(%s);' % (x, dest)) + self.emit_line(f'CPy_{x}DecRef({dest});') else: # Inlined - self.emit_line('CPy_%sDECREF(%s);' % (x, dest)) + self.emit_line(f'CPy_{x}DECREF({dest});') # Otherwise assume it's an unboxed, pointerless value and do nothing. def pretty_name(self, typ: RType) -> str: @@ -447,7 +447,7 @@ def emit_cast(self, assert isinstance(error, ReturnHandler) handle_error = 'return %s;' % error.value if raise_exception: - raise_exc = 'CPy_TypeError("{}", {}); '.format(self.pretty_name(typ), src) + raise_exc = f'CPy_TypeError("{self.pretty_name(typ)}", {src}); ' err = raise_exc + handle_error else: err = handle_error @@ -458,13 +458,13 @@ def emit_cast(self, assert value_type is not None if is_same_type(value_type, typ): if declare_dest: - self.emit_line('PyObject *{};'.format(dest)) + self.emit_line(f'PyObject *{dest};') check = '({} != Py_None)' if likely: - check = '(likely{})'.format(check) + check = f'(likely{check})' self.emit_arg_check(src, dest, typ, check.format(src), optional) self.emit_lines( - ' {} = {};'.format(dest, src), + f' {dest} = {src};', 'else {', err, '}') @@ -475,7 +475,7 @@ def emit_cast(self, or is_str_rprimitive(typ) or is_range_rprimitive(typ) or is_float_rprimitive(typ) or is_int_rprimitive(typ) or is_bool_rprimitive(typ) or is_bit_rprimitive(typ)): if declare_dest: - self.emit_line('PyObject *{};'.format(dest)) + self.emit_line(f'PyObject *{dest};') if is_list_rprimitive(typ): prefix = 'PyList' elif is_dict_rprimitive(typ): @@ -496,41 +496,41 @@ def emit_cast(self, assert False, 'unexpected primitive type' check = '({}_Check({}))' if likely: - check = '(likely{})'.format(check) + check = f'(likely{check})' self.emit_arg_check(src, dest, typ, check.format(prefix, src), optional) self.emit_lines( - ' {} = {};'.format(dest, src), + f' {dest} = {src};', 'else {', err, '}') elif is_bytes_rprimitive(typ): if declare_dest: - self.emit_line('PyObject *{};'.format(dest)) + self.emit_line(f'PyObject *{dest};') check = '(PyBytes_Check({}) || PyByteArray_Check({}))' if likely: - check = '(likely{})'.format(check) + check = f'(likely{check})' self.emit_arg_check(src, dest, typ, check.format(src, src), optional) self.emit_lines( - ' {} = {};'.format(dest, src), + f' {dest} = {src};', 'else {', err, '}') elif is_tuple_rprimitive(typ): if declare_dest: - self.emit_line('{} {};'.format(self.ctype(typ), dest)) + self.emit_line(f'{self.ctype(typ)} {dest};') check = '(PyTuple_Check({}))' if likely: - check = '(likely{})'.format(check) + check = f'(likely{check})' self.emit_arg_check(src, dest, typ, check.format(src), optional) self.emit_lines( - ' {} = {};'.format(dest, src), + f' {dest} = {src};', 'else {', err, '}') elif isinstance(typ, RInstance): if declare_dest: - self.emit_line('PyObject *{};'.format(dest)) + self.emit_line(f'PyObject *{dest};') concrete = all_concrete_classes(typ.class_ir) # If there are too many concrete subclasses or we can't find any # (meaning the code ought to be dead or we aren't doing global opts), @@ -548,31 +548,31 @@ def emit_cast(self, check = full_str.format( src=src, targets=[self.type_struct_name(ir) for ir in concrete]) if likely: - check = '(likely{})'.format(check) + check = f'(likely{check})' self.emit_arg_check(src, dest, typ, check, optional) self.emit_lines( - ' {} = {};'.format(dest, src), + f' {dest} = {src};', 'else {', err, '}') elif is_none_rprimitive(typ): if declare_dest: - self.emit_line('PyObject *{};'.format(dest)) + self.emit_line(f'PyObject *{dest};') check = '({} == Py_None)' if likely: - check = '(likely{})'.format(check) + check = f'(likely{check})' self.emit_arg_check(src, dest, typ, check.format(src), optional) self.emit_lines( - ' {} = {};'.format(dest, src), + f' {dest} = {src};', 'else {', err, '}') elif is_object_rprimitive(typ): if declare_dest: - self.emit_line('PyObject *{};'.format(dest)) + self.emit_line(f'PyObject *{dest};') self.emit_arg_check(src, dest, typ, '', optional) - self.emit_line('{} = {};'.format(dest, src)) + self.emit_line(f'{dest} = {src};') if optional: self.emit_line('}') elif isinstance(typ, RUnion): @@ -596,12 +596,12 @@ def emit_union_cast(self, The arguments are similar to emit_cast. """ if declare_dest: - self.emit_line('PyObject *{};'.format(dest)) + self.emit_line(f'PyObject *{dest};') good_label = self.new_label() if optional: - self.emit_line('if ({} == NULL) {{'.format(src)) - self.emit_line('{} = {};'.format(dest, self.c_error_value(typ))) - self.emit_line('goto {};'.format(good_label)) + self.emit_line(f'if ({src} == NULL) {{') + self.emit_line(f'{dest} = {self.c_error_value(typ)};') + self.emit_line(f'goto {good_label};') self.emit_line('}') for item in typ.items: self.emit_cast(src, @@ -611,7 +611,7 @@ def emit_union_cast(self, raise_exception=False, optional=False, likely=False) - self.emit_line('if ({} != NULL) goto {};'.format(dest, good_label)) + self.emit_line(f'if ({dest} != NULL) goto {good_label};') # Handle cast failure. self.emit_line(err) self.emit_label(good_label) @@ -623,7 +623,7 @@ def emit_tuple_cast(self, src: str, dest: str, typ: RTuple, declare_dest: bool, The arguments are similar to emit_cast. """ if declare_dest: - self.emit_line('PyObject *{};'.format(dest)) + self.emit_line(f'PyObject *{dest};') # This reuse of the variable is super dodgy. We don't even # care about the values except to check whether they are # invalid. @@ -631,26 +631,26 @@ def emit_tuple_cast(self, src: str, dest: str, typ: RTuple, declare_dest: bool, self.emit_lines( 'if (unlikely(!(PyTuple_Check({r}) && PyTuple_GET_SIZE({r}) == {size}))) {{'.format( r=src, size=len(typ.types)), - '{} = NULL;'.format(dest), - 'goto {};'.format(out_label), + f'{dest} = NULL;', + f'goto {out_label};', '}') for i, item in enumerate(typ.types): # Since we did the checks above this should never fail - self.emit_cast('PyTuple_GET_ITEM({}, {})'.format(src, i), + self.emit_cast(f'PyTuple_GET_ITEM({src}, {i})', dest, item, declare_dest=False, raise_exception=False, optional=False) - self.emit_line('if ({} == NULL) goto {};'.format(dest, out_label)) + self.emit_line(f'if ({dest} == NULL) goto {out_label};') - self.emit_line('{} = {};'.format(dest, src)) + self.emit_line(f'{dest} = {src};') self.emit_label(out_label) def emit_arg_check(self, src: str, dest: str, typ: RType, check: str, optional: bool) -> None: if optional: - self.emit_line('if ({} == NULL) {{'.format(src)) - self.emit_line('{} = {};'.format(dest, self.c_error_value(typ))) + self.emit_line(f'if ({src} == NULL) {{') + self.emit_line(f'{dest} = {self.c_error_value(typ)};') if check != '': self.emit_line('{}if {}'.format('} else ' if optional else '', check)) elif optional: @@ -687,61 +687,61 @@ def emit_unbox(self, error = error or AssignHandler() # TODO: Verify refcount handling. if isinstance(error, AssignHandler): - failure = '%s = %s;' % (dest, self.c_error_value(typ)) + failure = f'{dest} = {self.c_error_value(typ)};' elif isinstance(error, GotoHandler): failure = 'goto %s;' % error.label else: assert isinstance(error, ReturnHandler) failure = 'return %s;' % error.value if raise_exception: - raise_exc = 'CPy_TypeError("{}", {}); '.format(self.pretty_name(typ), src) + raise_exc = f'CPy_TypeError("{self.pretty_name(typ)}", {src}); ' failure = raise_exc + failure if is_int_rprimitive(typ) or is_short_int_rprimitive(typ): if declare_dest: - self.emit_line('CPyTagged {};'.format(dest)) - self.emit_arg_check(src, dest, typ, '(likely(PyLong_Check({})))'.format(src), + self.emit_line(f'CPyTagged {dest};') + self.emit_arg_check(src, dest, typ, f'(likely(PyLong_Check({src})))', optional) if borrow: - self.emit_line(' {} = CPyTagged_BorrowFromObject({});'.format(dest, src)) + self.emit_line(f' {dest} = CPyTagged_BorrowFromObject({src});') else: - self.emit_line(' {} = CPyTagged_FromObject({});'.format(dest, src)) + self.emit_line(f' {dest} = CPyTagged_FromObject({src});') self.emit_line('else {') self.emit_line(failure) self.emit_line('}') elif is_bool_rprimitive(typ) or is_bit_rprimitive(typ): # Whether we are borrowing or not makes no difference. if declare_dest: - self.emit_line('char {};'.format(dest)) - self.emit_arg_check(src, dest, typ, '(unlikely(!PyBool_Check({}))) {{'.format(src), + self.emit_line(f'char {dest};') + self.emit_arg_check(src, dest, typ, f'(unlikely(!PyBool_Check({src}))) {{', optional) self.emit_line(failure) self.emit_line('} else') - conversion = '{} == Py_True'.format(src) - self.emit_line(' {} = {};'.format(dest, conversion)) + conversion = f'{src} == Py_True' + self.emit_line(f' {dest} = {conversion};') elif is_none_rprimitive(typ): # Whether we are borrowing or not makes no difference. if declare_dest: - self.emit_line('char {};'.format(dest)) - self.emit_arg_check(src, dest, typ, '(unlikely({} != Py_None)) {{'.format(src), + self.emit_line(f'char {dest};') + self.emit_arg_check(src, dest, typ, f'(unlikely({src} != Py_None)) {{', optional) self.emit_line(failure) self.emit_line('} else') - self.emit_line(' {} = 1;'.format(dest)) + self.emit_line(f' {dest} = 1;') elif isinstance(typ, RTuple): self.declare_tuple_struct(typ) if declare_dest: - self.emit_line('{} {};'.format(self.ctype(typ), dest)) + self.emit_line(f'{self.ctype(typ)} {dest};') # HACK: The error handling for unboxing tuples is busted # and instead of fixing it I am just wrapping it in the # cast code which I think is right. This is not good. if optional: - self.emit_line('if ({} == NULL) {{'.format(src)) - self.emit_line('{} = {};'.format(dest, self.c_error_value(typ))) + self.emit_line(f'if ({src} == NULL) {{') + self.emit_line(f'{dest} = {self.c_error_value(typ)};') self.emit_line('} else {') cast_temp = self.temp_name() self.emit_tuple_cast(src, cast_temp, typ, declare_dest=True, err='', src_type=None) - self.emit_line('if (unlikely({} == NULL)) {{'.format(cast_temp)) + self.emit_line(f'if (unlikely({cast_temp} == NULL)) {{') # self.emit_arg_check(src, dest, typ, # '(!PyTuple_Check({}) || PyTuple_Size({}) != {}) {{'.format( @@ -749,11 +749,11 @@ def emit_unbox(self, self.emit_line(failure) # TODO: Decrease refcount? self.emit_line('} else {') if not typ.types: - self.emit_line('{}.empty_struct_error_flag = 0;'.format(dest)) + self.emit_line(f'{dest}.empty_struct_error_flag = 0;') for i, item_type in enumerate(typ.types): temp = self.temp_name() # emit_tuple_cast above checks the size, so this should not fail - self.emit_line('PyObject *{} = PyTuple_GET_ITEM({}, {});'.format(temp, src, i)) + self.emit_line(f'PyObject *{temp} = PyTuple_GET_ITEM({src}, {i});') temp2 = self.temp_name() # Unbox or check the item. if item_type.is_unboxed: @@ -768,7 +768,7 @@ def emit_unbox(self, if not borrow: self.emit_inc_ref(temp, object_rprimitive) self.emit_cast(temp, temp2, item_type, declare_dest=True) - self.emit_line('{}.f{} = {};'.format(dest, i, temp2)) + self.emit_line(f'{dest}.f{i} = {temp2};') self.emit_line('}') if optional: self.emit_line('}') @@ -791,54 +791,54 @@ def emit_box(self, src: str, dest: str, typ: RType, declare_dest: bool = False, declaration = '' if is_int_rprimitive(typ) or is_short_int_rprimitive(typ): # Steal the existing reference if it exists. - self.emit_line('{}{} = CPyTagged_StealAsObject({});'.format(declaration, dest, src)) + self.emit_line(f'{declaration}{dest} = CPyTagged_StealAsObject({src});') elif is_bool_rprimitive(typ) or is_bit_rprimitive(typ): # N.B: bool is special cased to produce a borrowed value # after boxing, so we don't need to increment the refcount # when this comes directly from a Box op. - self.emit_lines('{}{} = {} ? Py_True : Py_False;'.format(declaration, dest, src)) + self.emit_lines(f'{declaration}{dest} = {src} ? Py_True : Py_False;') if not can_borrow: self.emit_inc_ref(dest, object_rprimitive) elif is_none_rprimitive(typ): # N.B: None is special cased to produce a borrowed value # after boxing, so we don't need to increment the refcount # when this comes directly from a Box op. - self.emit_lines('{}{} = Py_None;'.format(declaration, dest)) + self.emit_lines(f'{declaration}{dest} = Py_None;') if not can_borrow: self.emit_inc_ref(dest, object_rprimitive) elif is_int32_rprimitive(typ): - self.emit_line('{}{} = PyLong_FromLong({});'.format(declaration, dest, src)) + self.emit_line(f'{declaration}{dest} = PyLong_FromLong({src});') elif is_int64_rprimitive(typ): - self.emit_line('{}{} = PyLong_FromLongLong({});'.format(declaration, dest, src)) + self.emit_line(f'{declaration}{dest} = PyLong_FromLongLong({src});') elif isinstance(typ, RTuple): self.declare_tuple_struct(typ) - self.emit_line('{}{} = PyTuple_New({});'.format(declaration, dest, len(typ.types))) - self.emit_line('if (unlikely({} == NULL))'.format(dest)) + self.emit_line(f'{declaration}{dest} = PyTuple_New({len(typ.types)});') + self.emit_line(f'if (unlikely({dest} == NULL))') self.emit_line(' CPyError_OutOfMemory();') # TODO: Fail if dest is None for i in range(0, len(typ.types)): if not typ.is_unboxed: - self.emit_line('PyTuple_SET_ITEM({}, {}, {}.f{}'.format(dest, i, src, i)) + self.emit_line(f'PyTuple_SET_ITEM({dest}, {i}, {src}.f{i}') else: inner_name = self.temp_name() - self.emit_box('{}.f{}'.format(src, i), inner_name, typ.types[i], + self.emit_box(f'{src}.f{i}', inner_name, typ.types[i], declare_dest=True) - self.emit_line('PyTuple_SET_ITEM({}, {}, {});'.format(dest, i, inner_name)) + self.emit_line(f'PyTuple_SET_ITEM({dest}, {i}, {inner_name});') else: assert not typ.is_unboxed # Type is boxed -- trivially just assign. - self.emit_line('{}{} = {};'.format(declaration, dest, src)) + self.emit_line(f'{declaration}{dest} = {src};') def emit_error_check(self, value: str, rtype: RType, failure: str) -> None: """Emit code for checking a native function return value for uncaught exception.""" if not isinstance(rtype, RTuple): - self.emit_line('if ({} == {}) {{'.format(value, self.c_error_value(rtype))) + self.emit_line(f'if ({value} == {self.c_error_value(rtype)}) {{') else: if len(rtype.types) == 0: return # empty tuples can't fail. else: cond = self.tuple_undefined_check_cond(rtype, value, self.c_error_value, '==') - self.emit_line('if ({}) {{'.format(cond)) + self.emit_line(f'if ({cond}) {{') self.emit_lines(failure, '}') def emit_gc_visit(self, target: str, rtype: RType) -> None: @@ -851,15 +851,15 @@ def emit_gc_visit(self, target: str, rtype: RType) -> None: # Not refcounted -> no pointers -> no GC interaction. return elif isinstance(rtype, RPrimitive) and rtype.name == 'builtins.int': - self.emit_line('if (CPyTagged_CheckLong({})) {{'.format(target)) - self.emit_line('Py_VISIT(CPyTagged_LongAsObject({}));'.format(target)) + self.emit_line(f'if (CPyTagged_CheckLong({target})) {{') + self.emit_line(f'Py_VISIT(CPyTagged_LongAsObject({target}));') self.emit_line('}') elif isinstance(rtype, RTuple): for i, item_type in enumerate(rtype.types): - self.emit_gc_visit('{}.f{}'.format(target, i), item_type) + self.emit_gc_visit(f'{target}.f{i}', item_type) elif self.ctype(rtype) == 'PyObject *': # The simplest case. - self.emit_line('Py_VISIT({});'.format(target)) + self.emit_line(f'Py_VISIT({target});') else: assert False, 'emit_gc_visit() not implemented for %s' % repr(rtype) @@ -873,16 +873,16 @@ def emit_gc_clear(self, target: str, rtype: RType) -> None: # Not refcounted -> no pointers -> no GC interaction. return elif isinstance(rtype, RPrimitive) and rtype.name == 'builtins.int': - self.emit_line('if (CPyTagged_CheckLong({})) {{'.format(target)) - self.emit_line('CPyTagged __tmp = {};'.format(target)) - self.emit_line('{} = {};'.format(target, self.c_undefined_value(rtype))) + self.emit_line(f'if (CPyTagged_CheckLong({target})) {{') + self.emit_line(f'CPyTagged __tmp = {target};') + self.emit_line(f'{target} = {self.c_undefined_value(rtype)};') self.emit_line('Py_XDECREF(CPyTagged_LongAsObject(__tmp));') self.emit_line('}') elif isinstance(rtype, RTuple): for i, item_type in enumerate(rtype.types): - self.emit_gc_clear('{}.f{}'.format(target, i), item_type) + self.emit_gc_clear(f'{target}.f{i}', item_type) elif self.ctype(rtype) == 'PyObject *' and self.c_undefined_value(rtype) == 'NULL': # The simplest case. - self.emit_line('Py_CLEAR({});'.format(target)) + self.emit_line(f'Py_CLEAR({target});') else: assert False, 'emit_gc_clear() not implemented for %s' % repr(rtype) diff --git a/mypyc/codegen/emitclass.py b/mypyc/codegen/emitclass.py index 9c960cf80bdde..437b50444d633 100644 --- a/mypyc/codegen/emitclass.py +++ b/mypyc/codegen/emitclass.py @@ -20,11 +20,11 @@ def native_slot(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> str: - return '{}{}'.format(NATIVE_PREFIX, fn.cname(emitter.names)) + return f'{NATIVE_PREFIX}{fn.cname(emitter.names)}' def wrapper_slot(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> str: - return '{}{}'.format(PREFIX, fn.cname(emitter.names)) + return f'{PREFIX}{fn.cname(emitter.names)}' # We maintain a table from dunder function names to struct slots they @@ -164,7 +164,7 @@ def generate_class_type_decl(cl: ClassIR, c_emitter: Emitter, context = c_emitter.context name = emitter.type_struct_name(cl) context.declarations[name] = HeaderDeclaration( - 'PyTypeObject *{};'.format(emitter.type_struct_name(cl)), + f'PyTypeObject *{emitter.type_struct_name(cl)};', needs_export=True) # If this is a non-extension class, all we want is the type object decl. @@ -175,7 +175,7 @@ def generate_class_type_decl(cl: ClassIR, c_emitter: Emitter, generate_full = not cl.is_trait and not cl.builtin_base if generate_full: context.declarations[emitter.native_function_name(cl.ctor)] = HeaderDeclaration( - '{};'.format(native_function_header(cl.ctor, emitter)), + f'{native_function_header(cl.ctor, emitter)};', needs_export=True, ) @@ -188,19 +188,19 @@ def generate_class(cl: ClassIR, module: str, emitter: Emitter) -> None: name = cl.name name_prefix = cl.name_prefix(emitter.names) - setup_name = '{}_setup'.format(name_prefix) - new_name = '{}_new'.format(name_prefix) - members_name = '{}_members'.format(name_prefix) - getseters_name = '{}_getseters'.format(name_prefix) - vtable_name = '{}_vtable'.format(name_prefix) - traverse_name = '{}_traverse'.format(name_prefix) - clear_name = '{}_clear'.format(name_prefix) - dealloc_name = '{}_dealloc'.format(name_prefix) - methods_name = '{}_methods'.format(name_prefix) - vtable_setup_name = '{}_trait_vtable_setup'.format(name_prefix) + setup_name = f'{name_prefix}_setup' + new_name = f'{name_prefix}_new' + members_name = f'{name_prefix}_members' + getseters_name = f'{name_prefix}_getseters' + vtable_name = f'{name_prefix}_vtable' + traverse_name = f'{name_prefix}_traverse' + clear_name = f'{name_prefix}_clear' + dealloc_name = f'{name_prefix}_dealloc' + methods_name = f'{name_prefix}_methods' + vtable_setup_name = f'{name_prefix}_trait_vtable_setup' fields: Dict[str, str] = OrderedDict() - fields['tp_name'] = '"{}"'.format(name) + fields['tp_name'] = f'"{name}"' generate_full = not cl.is_trait and not cl.builtin_base needs_getseters = cl.needs_getseters or not cl.is_generated @@ -209,9 +209,9 @@ def generate_class(cl: ClassIR, module: str, emitter: Emitter) -> None: fields['tp_new'] = new_name if generate_full: - fields['tp_dealloc'] = '(destructor){}_dealloc'.format(name_prefix) - fields['tp_traverse'] = '(traverseproc){}_traverse'.format(name_prefix) - fields['tp_clear'] = '(inquiry){}_clear'.format(name_prefix) + fields['tp_dealloc'] = f'(destructor){name_prefix}_dealloc' + fields['tp_traverse'] = f'(traverseproc){name_prefix}_traverse' + fields['tp_clear'] = f'(inquiry){name_prefix}_clear' if needs_getseters: fields['tp_getset'] = getseters_name fields['tp_methods'] = methods_name @@ -236,7 +236,7 @@ def emit_line() -> None: slots = generate_slots(cl, slot_defs, emitter) if slots: table_struct_name = generate_side_table_for_class(cl, table_name, type, slots, emitter) - fields['tp_{}'.format(table_name)] = '&{}'.format(table_struct_name) + fields[f'tp_{table_name}'] = f'&{table_struct_name}' richcompare_name = generate_richcompare_wrapper(cl, emitter) if richcompare_name: @@ -245,11 +245,11 @@ def emit_line() -> None: # If the class inherits from python, make space for a __dict__ struct_name = cl.struct_name(emitter.names) if cl.builtin_base: - base_size = 'sizeof({})'.format(cl.builtin_base) + base_size = f'sizeof({cl.builtin_base})' elif cl.is_trait: base_size = 'sizeof(PyObject)' else: - base_size = 'sizeof({})'.format(struct_name) + base_size = f'sizeof({struct_name})' # Since our types aren't allocated using type() we need to # populate these fields ourselves if we want them to have correct # values. PyType_Ready will inherit the offsets from tp_base but @@ -259,17 +259,17 @@ def emit_line() -> None: if cl.has_dict: # __dict__ lives right after the struct and __weakref__ lives right after that # TODO: They should get members in the struct instead of doing this nonsense. - weak_offset = '{} + sizeof(PyObject *)'.format(base_size) + weak_offset = f'{base_size} + sizeof(PyObject *)' emitter.emit_lines( - 'PyMemberDef {}[] = {{'.format(members_name), - '{{"__dict__", T_OBJECT_EX, {}, 0, NULL}},'.format(base_size), - '{{"__weakref__", T_OBJECT_EX, {}, 0, NULL}},'.format(weak_offset), + f'PyMemberDef {members_name}[] = {{', + f'{{"__dict__", T_OBJECT_EX, {base_size}, 0, NULL}},', + f'{{"__weakref__", T_OBJECT_EX, {weak_offset}, 0, NULL}},', '{0}', '};', ) fields['tp_members'] = members_name - fields['tp_basicsize'] = '{} + 2*sizeof(PyObject *)'.format(base_size) + fields['tp_basicsize'] = f'{base_size} + 2*sizeof(PyObject *)' fields['tp_dictoffset'] = base_size fields['tp_weaklistoffset'] = weak_offset else: @@ -279,7 +279,7 @@ def emit_line() -> None: # Declare setup method that allocates and initializes an object. type is the # type of the class being initialized, which could be another class if there # is an interpreted subclass. - emitter.emit_line('static PyObject *{}(PyTypeObject *type);'.format(setup_name)) + emitter.emit_line(f'static PyObject *{setup_name}(PyTypeObject *type);') assert cl.ctor is not None emitter.emit_line(native_function_header(cl.ctor, emitter) + ';') @@ -323,10 +323,10 @@ def emit_line() -> None: flags.append('_Py_TPFLAGS_HAVE_VECTORCALL') fields['tp_flags'] = ' | '.join(flags) - emitter.emit_line("static PyTypeObject {}_template_ = {{".format(emitter.type_struct_name(cl))) + emitter.emit_line(f"static PyTypeObject {emitter.type_struct_name(cl)}_template_ = {{") emitter.emit_line("PyVarObject_HEAD_INIT(NULL, 0)") for field, value in fields.items(): - emitter.emit_line(".{} = {},".format(field, value)) + emitter.emit_line(f".{field} = {value},") emitter.emit_line("};") emitter.emit_line("static PyTypeObject *{t}_template = &{t}_template_;".format( t=emitter.type_struct_name(cl))) @@ -344,11 +344,11 @@ def emit_line() -> None: def getter_name(cl: ClassIR, attribute: str, names: NameGenerator) -> str: - return names.private_name(cl.module_name, '{}_get{}'.format(cl.name, attribute)) + return names.private_name(cl.module_name, f'{cl.name}_get{attribute}') def setter_name(cl: ClassIR, attribute: str, names: NameGenerator) -> str: - return names.private_name(cl.module_name, '{}_set{}'.format(cl.name, attribute)) + return names.private_name(cl.module_name, f'{cl.name}_set{attribute}') def generate_object_struct(cl: ClassIR, emitter: Emitter) -> None: @@ -370,7 +370,7 @@ def generate_object_struct(cl: ClassIR, emitter: Emitter) -> None: if isinstance(rtype, RTuple): emitter.declare_tuple_struct(rtype) - lines.append('}} {};'.format(cl.struct_name(emitter.names))) + lines.append(f'}} {cl.struct_name(emitter.names)};') lines.append('') emitter.context.declarations[cl.struct_name(emitter.names)] = HeaderDeclaration( lines, @@ -439,11 +439,11 @@ def trait_offset_table_name(trait: ClassIR) -> str: # Emit vtable setup function emitter.emit_line('static bool') - emitter.emit_line('{}{}(void)'.format(NATIVE_PREFIX, vtable_setup_name)) + emitter.emit_line(f'{NATIVE_PREFIX}{vtable_setup_name}(void)') emitter.emit_line('{') if base.allow_interpreted_subclasses and not shadow: - emitter.emit_line('{}{}_shadow();'.format(NATIVE_PREFIX, vtable_setup_name)) + emitter.emit_line(f'{NATIVE_PREFIX}{vtable_setup_name}_shadow();') subtables = [] for trait, vtable in base.trait_vtables.items(): @@ -458,7 +458,7 @@ def trait_offset_table_name(trait: ClassIR) -> str: emitter.emit_line('return 1;') emitter.emit_line('}') - return vtable_name if not subtables else "{} + {}".format(vtable_name, len(subtables) * 3) + return vtable_name if not subtables else f"{vtable_name} + {len(subtables) * 3}" def generate_offset_table(trait_offset_table_name: str, @@ -466,7 +466,7 @@ def generate_offset_table(trait_offset_table_name: str, trait: ClassIR, cl: ClassIR) -> None: """Generate attribute offset row of a trait vtable.""" - emitter.emit_line('size_t {}_scratch[] = {{'.format(trait_offset_table_name)) + emitter.emit_line(f'size_t {trait_offset_table_name}_scratch[] = {{') for attr in trait.attributes: emitter.emit_line('offsetof({}, {}),'.format( cl.struct_name(emitter.names), emitter.attr(attr) @@ -485,7 +485,7 @@ def generate_vtable(entries: VTableEntries, emitter: Emitter, subtables: List[Tuple[ClassIR, str, str]], shadow: bool) -> None: - emitter.emit_line('CPyVTableItem {}_scratch[] = {{'.format(vtable_name)) + emitter.emit_line(f'CPyVTableItem {vtable_name}_scratch[] = {{') if subtables: emitter.emit_line('/* Array of trait vtables */') for trait, table, offset_table in subtables: @@ -516,26 +516,26 @@ def generate_setup_for_class(cl: ClassIR, emitter: Emitter) -> None: """Generate a native function that allocates an instance of a class.""" emitter.emit_line('static PyObject *') - emitter.emit_line('{}(PyTypeObject *type)'.format(func_name)) + emitter.emit_line(f'{func_name}(PyTypeObject *type)') emitter.emit_line('{') - emitter.emit_line('{} *self;'.format(cl.struct_name(emitter.names))) + emitter.emit_line(f'{cl.struct_name(emitter.names)} *self;') emitter.emit_line('self = ({struct} *)type->tp_alloc(type, 0);'.format( struct=cl.struct_name(emitter.names))) emitter.emit_line('if (self == NULL)') emitter.emit_line(' return NULL;') if shadow_vtable_name: - emitter.emit_line('if (type != {}) {{'.format(emitter.type_struct_name(cl))) - emitter.emit_line('self->vtable = {};'.format(shadow_vtable_name)) + emitter.emit_line(f'if (type != {emitter.type_struct_name(cl)}) {{') + emitter.emit_line(f'self->vtable = {shadow_vtable_name};') emitter.emit_line('} else {') - emitter.emit_line('self->vtable = {};'.format(vtable_name)) + emitter.emit_line(f'self->vtable = {vtable_name};') emitter.emit_line('}') else: - emitter.emit_line('self->vtable = {};'.format(vtable_name)) + emitter.emit_line(f'self->vtable = {vtable_name};') if cl.has_method('__call__') and emitter.use_vectorcall(): name = cl.method_decl('__call__').cname(emitter.names) - emitter.emit_line('self->vectorcall = {}{};'.format(PREFIX, name)) + emitter.emit_line(f'self->vectorcall = {PREFIX}{name};') for base in reversed(cl.base_mro): for attr, rtype in base.attributes.items(): @@ -562,9 +562,9 @@ def generate_constructor_for_class(cl: ClassIR, vtable_name: str, emitter: Emitter) -> None: """Generate a native function that allocates and initializes an instance of a class.""" - emitter.emit_line('{}'.format(native_function_header(fn, emitter))) + emitter.emit_line(f'{native_function_header(fn, emitter)}') emitter.emit_line('{') - emitter.emit_line('PyObject *self = {}({});'.format(setup_name, emitter.type_struct_name(cl))) + emitter.emit_line(f'PyObject *self = {setup_name}({emitter.type_struct_name(cl)});') emitter.emit_line('if (self == NULL)') emitter.emit_line(' return NULL;') args = ', '.join(['self'] + [REG_PREFIX + arg.name for arg in fn.sig.args]) @@ -602,11 +602,11 @@ def generate_init_for_class(cl: ClassIR, __init__ methods return a PyObject. Translate NULL to -1, everything else to 0. """ - func_name = '{}_init'.format(cl.name_prefix(emitter.names)) + func_name = f'{cl.name_prefix(emitter.names)}_init' emitter.emit_line('static int') emitter.emit_line( - '{}(PyObject *self, PyObject *args, PyObject *kwds)'.format(func_name)) + f'{func_name}(PyObject *self, PyObject *args, PyObject *kwds)') emitter.emit_line('{') emitter.emit_line('return {}{}(self, args, kwds) != NULL ? 0 : -1;'.format( PREFIX, init_fn.cname(emitter.names))) @@ -622,18 +622,18 @@ def generate_new_for_class(cl: ClassIR, emitter: Emitter) -> None: emitter.emit_line('static PyObject *') emitter.emit_line( - '{}(PyTypeObject *type, PyObject *args, PyObject *kwds)'.format(func_name)) + f'{func_name}(PyTypeObject *type, PyObject *args, PyObject *kwds)') emitter.emit_line('{') # TODO: Check and unbox arguments if not cl.allow_interpreted_subclasses: - emitter.emit_line('if (type != {}) {{'.format(emitter.type_struct_name(cl))) + emitter.emit_line(f'if (type != {emitter.type_struct_name(cl)}) {{') emitter.emit_line( 'PyErr_SetString(PyExc_TypeError, "interpreted classes cannot inherit from compiled");' ) emitter.emit_line('return NULL;') emitter.emit_line('}') - emitter.emit_line('return {}(type);'.format(setup_name)) + emitter.emit_line(f'return {setup_name}(type);') emitter.emit_line('}') @@ -642,9 +642,9 @@ def generate_new_for_trait(cl: ClassIR, emitter: Emitter) -> None: emitter.emit_line('static PyObject *') emitter.emit_line( - '{}(PyTypeObject *type, PyObject *args, PyObject *kwds)'.format(func_name)) + f'{func_name}(PyTypeObject *type, PyObject *args, PyObject *kwds)') emitter.emit_line('{') - emitter.emit_line('if (type != {}) {{'.format(emitter.type_struct_name(cl))) + emitter.emit_line(f'if (type != {emitter.type_struct_name(cl)}) {{') emitter.emit_line( 'PyErr_SetString(PyExc_TypeError, ' '"interpreted classes cannot inherit from compiled traits");' @@ -669,7 +669,7 @@ def generate_traverse_for_class(cl: ClassIR, emitter.emit_line('{') for base in reversed(cl.base_mro): for attr, rtype in base.attributes.items(): - emitter.emit_gc_visit('self->{}'.format(emitter.attr(attr)), rtype) + emitter.emit_gc_visit(f'self->{emitter.attr(attr)}', rtype) if cl.has_dict: struct_name = cl.struct_name(emitter.names) # __dict__ lives right after the struct and __weakref__ lives right after that @@ -687,11 +687,11 @@ def generate_clear_for_class(cl: ClassIR, func_name: str, emitter: Emitter) -> None: emitter.emit_line('static int') - emitter.emit_line('{}({} *self)'.format(func_name, cl.struct_name(emitter.names))) + emitter.emit_line(f'{func_name}({cl.struct_name(emitter.names)} *self)') emitter.emit_line('{') for base in reversed(cl.base_mro): for attr, rtype in base.attributes.items(): - emitter.emit_gc_clear('self->{}'.format(emitter.attr(attr)), rtype) + emitter.emit_gc_clear(f'self->{emitter.attr(attr)}', rtype) if cl.has_dict: struct_name = cl.struct_name(emitter.names) # __dict__ lives right after the struct and __weakref__ lives right after that @@ -710,12 +710,12 @@ def generate_dealloc_for_class(cl: ClassIR, clear_func_name: str, emitter: Emitter) -> None: emitter.emit_line('static void') - emitter.emit_line('{}({} *self)'.format(dealloc_func_name, cl.struct_name(emitter.names))) + emitter.emit_line(f'{dealloc_func_name}({cl.struct_name(emitter.names)} *self)') emitter.emit_line('{') emitter.emit_line('PyObject_GC_UnTrack(self);') # The trashcan is needed to handle deep recursive deallocations - emitter.emit_line('CPy_TRASHCAN_BEGIN(self, {})'.format(dealloc_func_name)) - emitter.emit_line('{}(self);'.format(clear_func_name)) + emitter.emit_line(f'CPy_TRASHCAN_BEGIN(self, {dealloc_func_name})') + emitter.emit_line(f'{clear_func_name}(self);') emitter.emit_line('Py_TYPE(self)->tp_free((PyObject *)self);') emitter.emit_line('CPy_TRASHCAN_END(self)') emitter.emit_line('}') @@ -724,12 +724,12 @@ def generate_dealloc_for_class(cl: ClassIR, def generate_methods_table(cl: ClassIR, name: str, emitter: Emitter) -> None: - emitter.emit_line('static PyMethodDef {}[] = {{'.format(name)) + emitter.emit_line(f'static PyMethodDef {name}[] = {{') for fn in cl.methods.values(): if fn.decl.is_prop_setter or fn.decl.is_prop_getter: continue - emitter.emit_line('{{"{}",'.format(fn.name)) - emitter.emit_line(' (PyCFunction){}{},'.format(PREFIX, fn.cname(emitter.names))) + emitter.emit_line(f'{{"{fn.name}",') + emitter.emit_line(f' (PyCFunction){PREFIX}{fn.cname(emitter.names)},') if use_fastcall(emitter.capi_version): flags = ['METH_FASTCALL'] else: @@ -758,10 +758,10 @@ def generate_side_table_for_class(cl: ClassIR, type: str, slots: Dict[str, str], emitter: Emitter) -> Optional[str]: - name = '{}_{}'.format(cl.name_prefix(emitter.names), name) - emitter.emit_line('static {} {} = {{'.format(type, name)) + name = f'{cl.name_prefix(emitter.names)}_{name}' + emitter.emit_line(f'static {type} {name} = {{') for field, value in slots.items(): - emitter.emit_line(".{} = {},".format(field, value)) + emitter.emit_line(f".{field} = {value},") emitter.emit_line("};") return name @@ -796,20 +796,20 @@ def generate_getseter_declarations(cl: ClassIR, emitter: Emitter) -> None: def generate_getseters_table(cl: ClassIR, name: str, emitter: Emitter) -> None: - emitter.emit_line('static PyGetSetDef {}[] = {{'.format(name)) + emitter.emit_line(f'static PyGetSetDef {name}[] = {{') if not cl.is_trait: for attr in cl.attributes: - emitter.emit_line('{{"{}",'.format(attr)) + emitter.emit_line(f'{{"{attr}",') emitter.emit_line(' (getter){}, (setter){},'.format( getter_name(cl, attr, emitter.names), setter_name(cl, attr, emitter.names))) emitter.emit_line(' NULL, NULL},') for prop in cl.properties: - emitter.emit_line('{{"{}",'.format(prop)) - emitter.emit_line(' (getter){},'.format(getter_name(cl, prop, emitter.names))) + emitter.emit_line(f'{{"{prop}",') + emitter.emit_line(f' (getter){getter_name(cl, prop, emitter.names)},') setter = cl.properties[prop][1] if setter: - emitter.emit_line(' (setter){},'.format(setter_name(cl, prop, emitter.names))) + emitter.emit_line(f' (setter){setter_name(cl, prop, emitter.names)},') emitter.emit_line('NULL, NULL},') else: emitter.emit_line('NULL, NULL, NULL},') @@ -845,15 +845,15 @@ def generate_getter(cl: ClassIR, emitter.emit_line('{}({} *self, void *closure)'.format(getter_name(cl, attr, emitter.names), cl.struct_name(emitter.names))) emitter.emit_line('{') - attr_expr = 'self->{}'.format(attr_field) + attr_expr = f'self->{attr_field}' emitter.emit_undefined_attr_check(rtype, attr_expr, '==', unlikely=True) emitter.emit_line('PyErr_SetString(PyExc_AttributeError,') emitter.emit_line(' "attribute {} of {} undefined");'.format(repr(attr), repr(cl.name))) emitter.emit_line('return NULL;') emitter.emit_line('}') - emitter.emit_inc_ref('self->{}'.format(attr_field), rtype) - emitter.emit_box('self->{}'.format(attr_field), 'retval', rtype, declare_dest=True) + emitter.emit_inc_ref(f'self->{attr_field}', rtype) + emitter.emit_box(f'self->{attr_field}', 'retval', rtype, declare_dest=True) emitter.emit_line('return retval;') emitter.emit_line('}') @@ -879,9 +879,9 @@ def generate_setter(cl: ClassIR, emitter.emit_line('}') if rtype.is_refcounted: - attr_expr = 'self->{}'.format(attr_field) + attr_expr = f'self->{attr_field}' emitter.emit_undefined_attr_check(rtype, attr_expr, '!=') - emitter.emit_dec_ref('self->{}'.format(attr_field), rtype) + emitter.emit_dec_ref(f'self->{attr_field}', rtype) emitter.emit_line('}') if deletable: @@ -895,7 +895,7 @@ def generate_setter(cl: ClassIR, emitter.emit_lines('if (!tmp)', ' return -1;') emitter.emit_inc_ref('tmp', rtype) - emitter.emit_line('self->{} = tmp;'.format(attr_field)) + emitter.emit_line(f'self->{attr_field} = tmp;') if deletable: emitter.emit_line('} else') emitter.emit_line(' self->{} = {};'.format(attr_field, diff --git a/mypyc/codegen/emitfunc.py b/mypyc/codegen/emitfunc.py index 294f416520f24..91b3a539adf57 100644 --- a/mypyc/codegen/emitfunc.py +++ b/mypyc/codegen/emitfunc.py @@ -31,13 +31,13 @@ def native_function_type(fn: FuncIR, emitter: Emitter) -> str: args = ', '.join(emitter.ctype(arg.type) for arg in fn.args) or 'void' ret = emitter.ctype(fn.ret_type) - return '{} (*)({})'.format(ret, args) + return f'{ret} (*)({args})' def native_function_header(fn: FuncDecl, emitter: Emitter) -> str: args = [] for arg in fn.sig.args: - args.append('{}{}{}'.format(emitter.ctype_spaced(arg.type), REG_PREFIX, arg.name)) + args.append(f'{emitter.ctype_spaced(arg.type)}{REG_PREFIX}{arg.name}') return '{ret_type}{name}({args})'.format( ret_type=emitter.ctype_spaced(fn.sig.ret_type), @@ -54,7 +54,7 @@ def generate_native_function(fn: FuncIR, body = Emitter(emitter.context, names) visitor = FunctionEmitterVisitor(body, declarations, source_path, module_name) - declarations.emit_line('{} {{'.format(native_function_header(fn.decl, emitter))) + declarations.emit_line(f'{native_function_header(fn.decl, emitter)} {{') body.indent() for r in all_values(fn.arg_regs, fn.blocks): @@ -143,7 +143,7 @@ def visit_branch(self, op: Branch) -> None: cond = '' if op.op == Branch.BOOL: expr_result = self.reg(op.value) - cond = '{}{}'.format(neg, expr_result) + cond = f'{neg}{expr_result}' elif op.op == Branch.IS_ERROR: typ = op.value.type compare = '!=' if negated else '==' @@ -163,22 +163,22 @@ def visit_branch(self, op: Branch) -> None: # For error checks, tell the compiler the branch is unlikely if op.traceback_entry is not None or op.rare: if not negated_rare: - cond = 'unlikely({})'.format(cond) + cond = f'unlikely({cond})' else: - cond = 'likely({})'.format(cond) + cond = f'likely({cond})' if false is self.next_block: if op.traceback_entry is None: - self.emit_line('if ({}) goto {};'.format(cond, self.label(true))) + self.emit_line(f'if ({cond}) goto {self.label(true)};') else: - self.emit_line('if ({}) {{'.format(cond)) + self.emit_line(f'if ({cond}) {{') self.emit_traceback(op) self.emit_lines( 'goto %s;' % self.label(true), '}' ) else: - self.emit_line('if ({}) {{'.format(cond)) + self.emit_line(f'if ({cond}) {{') self.emit_traceback(op) self.emit_lines( 'goto %s;' % self.label(true), @@ -195,10 +195,10 @@ def visit_tuple_set(self, op: TupleSet) -> None: tuple_type = op.tuple_type self.emitter.declare_tuple_struct(tuple_type) if len(op.items) == 0: # empty tuple - self.emit_line('{}.empty_struct_error_flag = 0;'.format(dest)) + self.emit_line(f'{dest}.empty_struct_error_flag = 0;') else: for i, item in enumerate(op.items): - self.emit_line('{}.f{} = {};'.format(dest, i, self.reg(item))) + self.emit_line(f'{dest}.f{i} = {self.reg(item)};') self.emit_inc_ref(dest, tuple_type) def visit_assign(self, op: Assign) -> None: @@ -207,7 +207,7 @@ def visit_assign(self, op: Assign) -> None: # clang whines about self assignment (which we might generate # for some casts), so don't emit it. if dest != src: - self.emit_line('%s = %s;' % (dest, src)) + self.emit_line(f'{dest} = {src};') def visit_assign_multi(self, op: AssignMulti) -> None: typ = op.dest.type @@ -225,10 +225,10 @@ def visit_load_error_value(self, op: LoadErrorValue) -> None: if isinstance(op.type, RTuple): values = [self.c_undefined_value(item) for item in op.type.types] tmp = self.temp_name() - self.emit_line('%s %s = { %s };' % (self.ctype(op.type), tmp, ', '.join(values))) - self.emit_line('%s = %s;' % (self.reg(op), tmp)) + self.emit_line('{} {} = {{ {} }};'.format(self.ctype(op.type), tmp, ', '.join(values))) + self.emit_line(f'{self.reg(op)} = {tmp};') else: - self.emit_line('%s = %s;' % (self.reg(op), + self.emit_line('{} = {};'.format(self.reg(op), self.c_error_value(op.type))) def visit_load_literal(self, op: LoadLiteral) -> None: @@ -251,7 +251,7 @@ def get_attr_expr(self, obj: str, op: Union[GetAttr, SetAttr], decl_cl: ClassIR) classes, and *(obj + attr_offset) for attributes defined by traits. We also insert all necessary C casts here. """ - cast = '({} *)'.format(op.class_type.struct_name(self.emitter.names)) + cast = f'({op.class_type.struct_name(self.emitter.names)} *)' if decl_cl.is_trait and op.class_type.class_ir.is_trait: # For pure trait access find the offset first, offsets # are ordered by attribute position in the cl.attributes dict. @@ -259,23 +259,23 @@ def get_attr_expr(self, obj: str, op: Union[GetAttr, SetAttr], decl_cl: ClassIR) trait_attr_index = list(decl_cl.attributes).index(op.attr) # TODO: reuse these names somehow? offset = self.emitter.temp_name() - self.declarations.emit_line('size_t {};'.format(offset)) + self.declarations.emit_line(f'size_t {offset};') self.emitter.emit_line('{} = {};'.format( offset, 'CPy_FindAttrOffset({}, {}, {})'.format( self.emitter.type_struct_name(decl_cl), - '({}{})->vtable'.format(cast, obj), + f'({cast}{obj})->vtable', trait_attr_index, ) )) - attr_cast = '({} *)'.format(self.ctype(op.class_type.attr_type(op.attr))) - return '*{}((char *){} + {})'.format(attr_cast, obj, offset) + attr_cast = f'({self.ctype(op.class_type.attr_type(op.attr))} *)' + return f'*{attr_cast}((char *){obj} + {offset})' else: # Cast to something non-trait. Note: for this to work, all struct # members for non-trait classes must obey monotonic linear growth. if op.class_type.class_ir.is_trait: assert not decl_cl.is_trait - cast = '({} *)'.format(decl_cl.struct_name(self.emitter.names)) + cast = f'({decl_cl.struct_name(self.emitter.names)} *)' return '({}{})->{}'.format( cast, obj, self.emitter.attr(op.attr) ) @@ -301,7 +301,7 @@ def visit_get_attr(self, op: GetAttr) -> None: else: # Otherwise, use direct or offset struct access. attr_expr = self.get_attr_expr(obj, op, decl_cl) - self.emitter.emit_line('{} = {};'.format(dest, attr_expr)) + self.emitter.emit_line(f'{dest} = {attr_expr};') self.emitter.emit_undefined_attr_check( attr_rtype, dest, '==', unlikely=True ) @@ -371,8 +371,8 @@ def visit_set_attr(self, op: SetAttr) -> None: self.emitter.emit_line('}') # This steal the reference to src, so we don't need to increment the arg self.emitter.emit_lines( - '{} = {};'.format(attr_expr, src), - '{} = 1;'.format(dest), + f'{attr_expr} = {src};', + f'{dest} = 1;', ) PREFIX_MAP: Final = { @@ -392,7 +392,7 @@ def visit_load_static(self, op: LoadStatic) -> None: s = repr(op.ann) if not any(x in s for x in ('/*', '*/', '\0')): ann = ' /* %s */' % s - self.emit_line('%s = %s;%s' % (dest, name, ann)) + self.emit_line(f'{dest} = {name};{ann}') def visit_init_static(self, op: InitStatic) -> None: value = self.reg(op.value) @@ -400,13 +400,13 @@ def visit_init_static(self, op: InitStatic) -> None: name = self.emitter.static_name(op.identifier, op.module_name, prefix) if op.namespace == NAMESPACE_TYPE: value = '(PyTypeObject *)%s' % value - self.emit_line('%s = %s;' % (name, value)) + self.emit_line(f'{name} = {value};') self.emit_inc_ref(name, op.value.type) def visit_tuple_get(self, op: TupleGet) -> None: dest = self.reg(op) src = self.reg(op.src) - self.emit_line('{} = {}.f{};'.format(dest, src, op.index)) + self.emit_line(f'{dest} = {src}.f{op.index};') self.emit_inc_ref(dest, op.type) def get_dest_assign(self, dest: Value) -> str: @@ -421,7 +421,7 @@ def visit_call(self, op: Call) -> None: args = ', '.join(self.reg(arg) for arg in op.args) lib = self.emitter.get_group_prefix(op.fn) cname = op.fn.cname(self.names) - self.emit_line('%s%s%s%s(%s);' % (dest, lib, NATIVE_PREFIX, cname, args)) + self.emit_line(f'{dest}{lib}{NATIVE_PREFIX}{cname}({args});') def visit_method_call(self, op: MethodCall) -> None: """Call native method.""" @@ -441,7 +441,7 @@ def visit_method_call(self, op: MethodCall) -> None: # turned into the class for class methods obj_args = ( [] if method.decl.kind == FUNC_STATICMETHOD else - ['(PyObject *)Py_TYPE({})'.format(obj)] if method.decl.kind == FUNC_CLASSMETHOD else + [f'(PyObject *)Py_TYPE({obj})'] if method.decl.kind == FUNC_CLASSMETHOD else [obj]) args = ', '.join(obj_args + [self.reg(arg) for arg in op.args]) mtype = native_function_type(method, self.emitter) @@ -485,7 +485,7 @@ def visit_raise_standard_error(self, op: RaiseStandardError) -> None: if isinstance(op.value, str): message = op.value.replace('"', '\\"') self.emitter.emit_line( - 'PyErr_SetString(PyExc_{}, "{}");'.format(op.class_name, message)) + f'PyErr_SetString(PyExc_{op.class_name}, "{message}");') elif isinstance(op.value, Value): self.emitter.emit_line( 'PyErr_SetObject(PyExc_{}, {});'.format(op.class_name, @@ -493,8 +493,8 @@ def visit_raise_standard_error(self, op: RaiseStandardError) -> None: else: assert False, 'op value type must be either str or Value' else: - self.emitter.emit_line('PyErr_SetNone(PyExc_{});'.format(op.class_name)) - self.emitter.emit_line('{} = 0;'.format(self.reg(op))) + self.emitter.emit_line(f'PyErr_SetNone(PyExc_{op.class_name});') + self.emitter.emit_line(f'{self.reg(op)} = 0;') def visit_call_c(self, op: CallC) -> None: if op.is_void: @@ -502,13 +502,13 @@ def visit_call_c(self, op: CallC) -> None: else: dest = self.get_dest_assign(op) args = ', '.join(self.reg(arg) for arg in op.args) - self.emitter.emit_line("{}{}({});".format(dest, op.function_name, args)) + self.emitter.emit_line(f"{dest}{op.function_name}({args});") def visit_truncate(self, op: Truncate) -> None: dest = self.reg(op) value = self.reg(op.src) # for C backend the generated code are straight assignments - self.emit_line("{} = {};".format(dest, value)) + self.emit_line(f"{dest} = {value};") def visit_load_global(self, op: LoadGlobal) -> None: dest = self.reg(op) @@ -517,13 +517,13 @@ def visit_load_global(self, op: LoadGlobal) -> None: s = repr(op.ann) if not any(x in s for x in ('/*', '*/', '\0')): ann = ' /* %s */' % s - self.emit_line('%s = %s;%s' % (dest, op.identifier, ann)) + self.emit_line(f'{dest} = {op.identifier};{ann}') def visit_int_op(self, op: IntOp) -> None: dest = self.reg(op) lhs = self.reg(op.lhs) rhs = self.reg(op.rhs) - self.emit_line('%s = %s %s %s;' % (dest, lhs, op.op_str[op.op], rhs)) + self.emit_line(f'{dest} = {lhs} {op.op_str[op.op]} {rhs};') def visit_comparison_op(self, op: ComparisonOp) -> None: dest = self.reg(op) @@ -545,7 +545,7 @@ def visit_comparison_op(self, op: ComparisonOp) -> None: elif isinstance(op.rhs, Integer) and op.rhs.value < 0: # Force signed ==/!= with negative operand lhs_cast = self.emit_signed_int_cast(op.lhs.type) - self.emit_line('%s = %s%s %s %s%s;' % (dest, lhs_cast, lhs, + self.emit_line('{} = {}{} {} {}{};'.format(dest, lhs_cast, lhs, op.op_str[op.op], rhs_cast, rhs)) def visit_load_mem(self, op: LoadMem) -> None: @@ -553,7 +553,7 @@ def visit_load_mem(self, op: LoadMem) -> None: src = self.reg(op.src) # TODO: we shouldn't dereference to type that are pointer type so far type = self.ctype(op.type) - self.emit_line('%s = *(%s *)%s;' % (dest, type, src)) + self.emit_line(f'{dest} = *({type} *){src};') def visit_set_mem(self, op: SetMem) -> None: dest = self.reg(op.dest) @@ -562,7 +562,7 @@ def visit_set_mem(self, op: SetMem) -> None: # clang whines about self assignment (which we might generate # for some casts), so don't emit it. if dest != src: - self.emit_line('*(%s *)%s = %s;' % (dest_type, dest, src)) + self.emit_line(f'*({dest_type} *){dest} = {src};') def visit_get_element_ptr(self, op: GetElementPtr) -> None: dest = self.reg(op) @@ -570,14 +570,14 @@ def visit_get_element_ptr(self, op: GetElementPtr) -> None: # TODO: support tuple type assert isinstance(op.src_type, RStruct) assert op.field in op.src_type.names, "Invalid field name." - self.emit_line('%s = (%s)&((%s *)%s)->%s;' % (dest, op.type._ctype, op.src_type.name, + self.emit_line('{} = ({})&(({} *){})->{};'.format(dest, op.type._ctype, op.src_type.name, src, op.field)) def visit_load_address(self, op: LoadAddress) -> None: typ = op.type dest = self.reg(op) src = self.reg(op.src) if isinstance(op.src, Register) else op.src - self.emit_line('%s = (%s)&%s;' % (dest, typ._ctype, src)) + self.emit_line(f'{dest} = ({typ._ctype})&{src};') def visit_keep_alive(self, op: KeepAlive) -> None: # This is a no-op. diff --git a/mypyc/codegen/emitmodule.py b/mypyc/codegen/emitmodule.py index 35aa0046dcf91..6eea3f1ea8810 100644 --- a/mypyc/codegen/emitmodule.py +++ b/mypyc/codegen/emitmodule.py @@ -344,7 +344,7 @@ def write_cache( # If the metadata isn't there, skip writing the cache. try: meta_data = result.manager.metastore.read(meta_path) - except IOError: + except OSError: continue newpath = get_state_ir_cache_name(st) @@ -422,15 +422,15 @@ def compile_modules_to_c( def generate_function_declaration(fn: FuncIR, emitter: Emitter) -> None: emitter.context.declarations[emitter.native_function_name(fn.decl)] = HeaderDeclaration( - '{};'.format(native_function_header(fn.decl, emitter)), + f'{native_function_header(fn.decl, emitter)};', needs_export=True) if fn.name != TOP_LEVEL_NAME: if is_fastcall_supported(fn, emitter.capi_version): emitter.context.declarations[PREFIX + fn.cname(emitter.names)] = HeaderDeclaration( - '{};'.format(wrapper_function_header(fn, emitter.names))) + f'{wrapper_function_header(fn, emitter.names)};') else: emitter.context.declarations[PREFIX + fn.cname(emitter.names)] = HeaderDeclaration( - '{};'.format(legacy_wrapper_function_header(fn, emitter.names))) + f'{legacy_wrapper_function_header(fn, emitter.names)};') def pointerize(decl: str, name: str) -> str: @@ -438,10 +438,10 @@ def pointerize(decl: str, name: str) -> str: # This doesn't work in general but does work for all our types... if '(' in decl: # Function pointer. Stick an * in front of the name and wrap it in parens. - return decl.replace(name, '(*{})'.format(name)) + return decl.replace(name, f'(*{name})') else: # Non-function pointer. Just stick an * in front of the name. - return decl.replace(name, '*{}'.format(name)) + return decl.replace(name, f'*{name}') def group_dir(group_name: str) -> str: @@ -506,9 +506,9 @@ def generate_c_for_modules(self) -> List[Tuple[str, str]]: # reduce the number of compiler invocations needed if self.compiler_options.include_runtime_files: for name in RUNTIME_C_FILES: - base_emitter.emit_line('#include "{}"'.format(name)) - base_emitter.emit_line('#include "__native{}.h"'.format(self.short_group_suffix)) - base_emitter.emit_line('#include "__native_internal{}.h"'.format(self.short_group_suffix)) + base_emitter.emit_line(f'#include "{name}"') + base_emitter.emit_line(f'#include "__native{self.short_group_suffix}.h"') + base_emitter.emit_line(f'#include "__native_internal{self.short_group_suffix}.h"') emitter = base_emitter self.generate_literal_tables() @@ -516,9 +516,9 @@ def generate_c_for_modules(self) -> List[Tuple[str, str]]: for module_name, module in self.modules: if multi_file: emitter = Emitter(self.context) - emitter.emit_line('#include "__native{}.h"'.format(self.short_group_suffix)) + emitter.emit_line(f'#include "__native{self.short_group_suffix}.h"') emitter.emit_line( - '#include "__native_internal{}.h"'.format(self.short_group_suffix)) + f'#include "__native_internal{self.short_group_suffix}.h"') self.declare_module(module_name, emitter) self.declare_internal_globals(module_name, emitter) @@ -543,7 +543,7 @@ def generate_c_for_modules(self) -> List[Tuple[str, str]]: generate_legacy_wrapper_function( fn, emitter, self.source_paths[module_name], module_name) if multi_file: - name = ('__native_{}.c'.format(emitter.names.private_name(module_name))) + name = (f'__native_{emitter.names.private_name(module_name)}.c') file_contents.append((name, ''.join(emitter.fragments))) # The external header file contains type declarations while @@ -551,17 +551,17 @@ def generate_c_for_modules(self) -> List[Tuple[str, str]]: # (which are shared between shared libraries via dynamic # exports tables and not accessed directly.) ext_declarations = Emitter(self.context) - ext_declarations.emit_line('#ifndef MYPYC_NATIVE{}_H'.format(self.group_suffix)) - ext_declarations.emit_line('#define MYPYC_NATIVE{}_H'.format(self.group_suffix)) + ext_declarations.emit_line(f'#ifndef MYPYC_NATIVE{self.group_suffix}_H') + ext_declarations.emit_line(f'#define MYPYC_NATIVE{self.group_suffix}_H') ext_declarations.emit_line('#include ') ext_declarations.emit_line('#include ') declarations = Emitter(self.context) - declarations.emit_line('#ifndef MYPYC_NATIVE_INTERNAL{}_H'.format(self.group_suffix)) - declarations.emit_line('#define MYPYC_NATIVE_INTERNAL{}_H'.format(self.group_suffix)) + declarations.emit_line(f'#ifndef MYPYC_NATIVE_INTERNAL{self.group_suffix}_H') + declarations.emit_line(f'#define MYPYC_NATIVE_INTERNAL{self.group_suffix}_H') declarations.emit_line('#include ') declarations.emit_line('#include ') - declarations.emit_line('#include "__native{}.h"'.format(self.short_group_suffix)) + declarations.emit_line(f'#include "__native{self.short_group_suffix}.h"') declarations.emit_line() declarations.emit_line('int CPyGlobalsInit(void);') declarations.emit_line() @@ -578,9 +578,9 @@ def generate_c_for_modules(self) -> List[Tuple[str, str]]: short_lib = exported_name(lib.split('.')[-1]) declarations.emit_lines( '#include <{}>'.format( - os.path.join(group_dir(lib), "__native_{}.h".format(short_lib)) + os.path.join(group_dir(lib), f"__native_{short_lib}.h") ), - 'struct export_table_{} exports_{};'.format(elib, elib) + f'struct export_table_{elib} exports_{elib};' ) sorted_decls = self.toposort_declarations() @@ -594,7 +594,7 @@ def generate_c_for_modules(self) -> List[Tuple[str, str]]: decls = ext_declarations if declaration.is_type else declarations if not declaration.is_type: decls.emit_lines( - 'extern {}'.format(declaration.decl[0]), *declaration.decl[1:]) + f'extern {declaration.decl[0]}', *declaration.decl[1:]) # If there is a definition, emit it. Otherwise repeat the declaration # (without an extern). if declaration.defn: @@ -614,11 +614,11 @@ def generate_c_for_modules(self) -> List[Tuple[str, str]]: output_dir = group_dir(self.group_name) if self.group_name else '' return file_contents + [ - (os.path.join(output_dir, '__native{}.c'.format(self.short_group_suffix)), + (os.path.join(output_dir, f'__native{self.short_group_suffix}.c'), ''.join(emitter.fragments)), - (os.path.join(output_dir, '__native_internal{}.h'.format(self.short_group_suffix)), + (os.path.join(output_dir, f'__native_internal{self.short_group_suffix}.h'), ''.join(declarations.fragments)), - (os.path.join(output_dir, '__native{}.h'.format(self.short_group_suffix)), + (os.path.join(output_dir, f'__native{self.short_group_suffix}.h'), ''.join(ext_declarations.fragments)), ] @@ -699,7 +699,7 @@ def generate_export_table(self, decl_emitter: Emitter, code_emitter: Emitter) -> decl_emitter.emit_lines( '', - 'struct export_table{} {{'.format(self.group_suffix), + f'struct export_table{self.group_suffix} {{', ) for name, decl in decls.items(): if decl.needs_export: @@ -709,11 +709,11 @@ def generate_export_table(self, decl_emitter: Emitter, code_emitter: Emitter) -> code_emitter.emit_lines( '', - 'static struct export_table{} exports = {{'.format(self.group_suffix), + f'static struct export_table{self.group_suffix} exports = {{', ) for name, decl in decls.items(): if decl.needs_export: - code_emitter.emit_line('&{},'.format(name)) + code_emitter.emit_line(f'&{name},') code_emitter.emit_line('};') @@ -772,13 +772,13 @@ def generate_shared_lib_init(self, emitter: Emitter) -> None: for mod, _ in self.modules: name = exported_name(mod) emitter.emit_lines( - 'extern PyObject *CPyInit_{}(void);'.format(name), + f'extern PyObject *CPyInit_{name}(void);', 'capsule = PyCapsule_New((void *)CPyInit_{}, "{}.init_{}", NULL);'.format( name, shared_lib_name(self.group_name), name), 'if (!capsule) {', 'goto fail;', '}', - 'res = PyObject_SetAttrString(module, "init_{}", capsule);'.format(name), + f'res = PyObject_SetAttrString(module, "init_{name}", capsule);', 'Py_DECREF(capsule);', 'if (res < 0) {', 'goto fail;', @@ -793,7 +793,7 @@ def generate_shared_lib_init(self, emitter: Emitter) -> None: shared_lib_name(group)), 'struct export_table_{} *pexports_{} = PyCapsule_Import("{}.exports", 0);'.format( egroup, egroup, shared_lib_name(group)), - 'if (!pexports_{}) {{'.format(egroup), + f'if (!pexports_{egroup}) {{', 'goto fail;', '}', 'memcpy(&exports_{group}, pexports_{group}, sizeof(exports_{group}));'.format( @@ -821,10 +821,10 @@ def generate_globals_init(self, emitter: Emitter) -> None: emitter.emit_line('CPy_Init();') for symbol, fixup in self.simple_inits: - emitter.emit_line('{} = {};'.format(symbol, fixup)) + emitter.emit_line(f'{symbol} = {fixup};') values = 'CPyLit_Str, CPyLit_Bytes, CPyLit_Int, CPyLit_Float, CPyLit_Complex, CPyLit_Tuple' - emitter.emit_lines('if (CPyStatics_Initialize(CPyStatics, {}) < 0) {{'.format(values), + emitter.emit_lines(f'if (CPyStatics_Initialize(CPyStatics, {values}) < 0) {{', 'return -1;', '}') @@ -838,7 +838,7 @@ def generate_module_def(self, emitter: Emitter, module_name: str, module: Module """Emit the PyModuleDef struct for a module and the module init function.""" # Emit module methods module_prefix = emitter.names.private_name(module_name) - emitter.emit_line('static PyMethodDef {}module_methods[] = {{'.format(module_prefix)) + emitter.emit_line(f'static PyMethodDef {module_prefix}module_methods[] = {{') for fn in module.functions: if fn.class_name is not None or fn.name == TOP_LEVEL_NAME: continue @@ -859,13 +859,13 @@ def generate_module_def(self, emitter: Emitter, module_name: str, module: Module emitter.emit_line() # Emit module definition struct - emitter.emit_lines('static struct PyModuleDef {}module = {{'.format(module_prefix), + emitter.emit_lines(f'static struct PyModuleDef {module_prefix}module = {{', 'PyModuleDef_HEAD_INIT,', - '"{}",'.format(module_name), + f'"{module_name}",', 'NULL, /* docstring */', '-1, /* size of per-interpreter state of the module,', ' or -1 if the module keeps state in global variables. */', - '{}module_methods'.format(module_prefix), + f'{module_prefix}module_methods', '};') emitter.emit_line() # Emit module init function. If we are compiling just one module, this @@ -874,9 +874,9 @@ def generate_module_def(self, emitter: Emitter, module_name: str, module: Module # the shared library, and in this case we use an internal module # initialized function that will be called by the shim. if not self.use_shared_lib: - declaration = 'PyMODINIT_FUNC PyInit_{}(void)'.format(module_name) + declaration = f'PyMODINIT_FUNC PyInit_{module_name}(void)' else: - declaration = 'PyObject *CPyInit_{}(void)'.format(exported_name(module_name)) + declaration = f'PyObject *CPyInit_{exported_name(module_name)}(void)' emitter.emit_lines(declaration, '{') emitter.emit_line('PyObject* modname = NULL;') @@ -887,21 +887,21 @@ def generate_module_def(self, emitter: Emitter, module_name: str, module: Module # imported, whereas this we want to have to stop a circular import. module_static = self.module_internal_static_name(module_name, emitter) - emitter.emit_lines('if ({}) {{'.format(module_static), - 'Py_INCREF({});'.format(module_static), - 'return {};'.format(module_static), + emitter.emit_lines(f'if ({module_static}) {{', + f'Py_INCREF({module_static});', + f'return {module_static};', '}') - emitter.emit_lines('{} = PyModule_Create(&{}module);'.format(module_static, module_prefix), - 'if (unlikely({} == NULL))'.format(module_static), + emitter.emit_lines(f'{module_static} = PyModule_Create(&{module_prefix}module);', + f'if (unlikely({module_static} == NULL))', ' goto fail;') emitter.emit_line( 'modname = PyObject_GetAttrString((PyObject *){}, "__name__");'.format( module_static)) module_globals = emitter.static_name('globals', module_name) - emitter.emit_lines('{} = PyModule_GetDict({});'.format(module_globals, module_static), - 'if (unlikely({} == NULL))'.format(module_globals), + emitter.emit_lines(f'{module_globals} = PyModule_GetDict({module_static});', + f'if (unlikely({module_globals} == NULL))', ' goto fail;') # HACK: Manually instantiate generated classes here @@ -914,7 +914,7 @@ def generate_module_def(self, emitter: Emitter, module_name: str, module: Module '{t} = (PyTypeObject *)CPyType_FromTemplate(' '(PyObject *){t}_template, NULL, modname);' .format(t=type_struct)) - emitter.emit_lines('if (unlikely(!{}))'.format(type_struct), + emitter.emit_lines(f'if (unlikely(!{type_struct}))', ' goto fail;') emitter.emit_lines('if (CPyGlobalsInit() < 0)', @@ -924,19 +924,19 @@ def generate_module_def(self, emitter: Emitter, module_name: str, module: Module emitter.emit_lines('Py_DECREF(modname);') - emitter.emit_line('return {};'.format(module_static)) + emitter.emit_line(f'return {module_static};') emitter.emit_lines('fail:', - 'Py_CLEAR({});'.format(module_static), + f'Py_CLEAR({module_static});', 'Py_CLEAR(modname);') for name, typ in module.final_names: static_name = emitter.static_name(name, module_name) emitter.emit_dec_ref(static_name, typ, is_xdec=True) undef = emitter.c_undefined_value(typ) - emitter.emit_line('{} = {};'.format(static_name, undef)) + emitter.emit_line(f'{static_name} = {undef};') # the type objects returned from CPyType_FromTemplate are all new references # so we have to decref them for t in type_structs: - emitter.emit_line('Py_CLEAR({});'.format(t)) + emitter.emit_line(f'Py_CLEAR({t});') emitter.emit_line('return NULL;') emitter.emit_line('}') @@ -946,7 +946,7 @@ def generate_top_level_call(self, module: ModuleIR, emitter: Emitter) -> None: for fn in reversed(module.functions): if fn.name == TOP_LEVEL_NAME: emitter.emit_lines( - 'char result = {}();'.format(emitter.native_function_name(fn.decl)), + f'char result = {emitter.native_function_name(fn.decl)}();', 'if (result == 2)', ' goto fail;', ) @@ -986,18 +986,18 @@ def declare_global(self, type_spaced: str, name: str, *, initializer: Optional[str] = None) -> None: if '[' not in type_spaced: - base = '{}{}'.format(type_spaced, name) + base = f'{type_spaced}{name}' else: a, b = type_spaced.split('[', 1) - base = '{}{}[{}'.format(a, name, b) + base = f'{a}{name}[{b}' if not initializer: defn = None else: - defn = ['{} = {};'.format(base, initializer)] + defn = [f'{base} = {initializer};'] if name not in self.context.declarations: self.context.declarations[name] = HeaderDeclaration( - '{};'.format(base), + f'{base};', defn=defn, ) @@ -1028,7 +1028,7 @@ def declare_finals( for name, typ in final_names: static_name = emitter.static_name(name, module) emitter.context.declarations[static_name] = HeaderDeclaration( - '{}{};'.format(emitter.ctype_spaced(typ), static_name), + f'{emitter.ctype_spaced(typ)}{static_name};', [self.final_definition(module, name, typ, emitter)], needs_export=True) @@ -1041,7 +1041,7 @@ def final_definition( undefined = '{{ {} }}'.format(''.join(emitter.tuple_undefined_value_helper(typ))) else: undefined = emitter.c_undefined_value(typ) - return '{}{} = {};'.format(emitter.ctype_spaced(typ), static_name, undefined) + return f'{emitter.ctype_spaced(typ)}{static_name} = {undefined};' def declare_static_pyobject(self, identifier: str, emitter: Emitter) -> None: symbol = emitter.static_name(identifier, None) diff --git a/mypyc/codegen/emitwrapper.py b/mypyc/codegen/emitwrapper.py index dd08bdb40bf3c..a68438c5f0dbd 100644 --- a/mypyc/codegen/emitwrapper.py +++ b/mypyc/codegen/emitwrapper.py @@ -86,8 +86,8 @@ def reorder_arg_groups(groups: Dict[ArgKind, List[RuntimeArg]]) -> List[RuntimeA def make_static_kwlist(args: List[RuntimeArg]) -> str: - arg_names = ''.join('"{}", '.format(arg.name) for arg in args) - return 'static const char * const kwlist[] = {{{}0}};'.format(arg_names) + arg_names = ''.join(f'"{arg.name}", ' for arg in args) + return f'static const char * const kwlist[] = {{{arg_names}0}};' def make_format_string(func_name: Optional[str], groups: Dict[ArgKind, List[RuntimeArg]]) -> str: @@ -116,7 +116,7 @@ def make_format_string(func_name: Optional[str], groups: Dict[ArgKind, List[Runt if groups[ARG_NAMED]: format += '@' + 'O' * len(groups[ARG_NAMED]) if func_name is not None: - format += ':{}'.format(func_name) + format += f':{func_name}' return format @@ -129,13 +129,13 @@ def generate_wrapper_function(fn: FuncIR, In particular, this handles unboxing the arguments, calling the native function, and then boxing the return value. """ - emitter.emit_line('{} {{'.format(wrapper_function_header(fn, emitter.names))) + emitter.emit_line(f'{wrapper_function_header(fn, emitter.names)} {{') # If fn is a method, then the first argument is a self param real_args = list(fn.args) if fn.class_name and not fn.decl.kind == FUNC_STATICMETHOD: arg = real_args.pop(0) - emitter.emit_line('PyObject *obj_{} = self;'.format(arg.name)) + emitter.emit_line(f'PyObject *obj_{arg.name} = self;') # Need to order args as: required, optional, kwonly optional, kwonly required # This is because CPyArg_ParseStackAndKeywords format string requires @@ -146,20 +146,20 @@ def generate_wrapper_function(fn: FuncIR, emitter.emit_line(make_static_kwlist(reordered_args)) fmt = make_format_string(fn.name, groups) # Define the arguments the function accepts (but no types yet) - emitter.emit_line('static CPyArg_Parser parser = {{"{}", kwlist, 0}};'.format(fmt)) + emitter.emit_line(f'static CPyArg_Parser parser = {{"{fmt}", kwlist, 0}};') for arg in real_args: emitter.emit_line('PyObject *obj_{}{};'.format( arg.name, ' = NULL' if arg.optional else '')) - cleanups = ['CPy_DECREF(obj_{});'.format(arg.name) + cleanups = [f'CPy_DECREF(obj_{arg.name});' for arg in groups[ARG_STAR] + groups[ARG_STAR2]] arg_ptrs: List[str] = [] if groups[ARG_STAR] or groups[ARG_STAR2]: - arg_ptrs += ['&obj_{}'.format(groups[ARG_STAR][0].name) if groups[ARG_STAR] else 'NULL'] - arg_ptrs += ['&obj_{}'.format(groups[ARG_STAR2][0].name) if groups[ARG_STAR2] else 'NULL'] - arg_ptrs += ['&obj_{}'.format(arg.name) for arg in reordered_args] + arg_ptrs += [f'&obj_{groups[ARG_STAR][0].name}' if groups[ARG_STAR] else 'NULL'] + arg_ptrs += [f'&obj_{groups[ARG_STAR2][0].name}' if groups[ARG_STAR2] else 'NULL'] + arg_ptrs += [f'&obj_{arg.name}' for arg in reordered_args] if fn.name == '__call__' and use_vectorcall(emitter.capi_version): nargs = 'PyVectorcall_NARGS(nargs)' @@ -212,13 +212,13 @@ def generate_legacy_wrapper_function(fn: FuncIR, In particular, this handles unboxing the arguments, calling the native function, and then boxing the return value. """ - emitter.emit_line('{} {{'.format(legacy_wrapper_function_header(fn, emitter.names))) + emitter.emit_line(f'{legacy_wrapper_function_header(fn, emitter.names)} {{') # If fn is a method, then the first argument is a self param real_args = list(fn.args) if fn.class_name and not fn.decl.kind == FUNC_STATICMETHOD: arg = real_args.pop(0) - emitter.emit_line('PyObject *obj_{} = self;'.format(arg.name)) + emitter.emit_line(f'PyObject *obj_{arg.name} = self;') # Need to order args as: required, optional, kwonly optional, kwonly required # This is because CPyArg_ParseTupleAndKeywords format string requires @@ -231,14 +231,14 @@ def generate_legacy_wrapper_function(fn: FuncIR, emitter.emit_line('PyObject *obj_{}{};'.format( arg.name, ' = NULL' if arg.optional else '')) - cleanups = ['CPy_DECREF(obj_{});'.format(arg.name) + cleanups = [f'CPy_DECREF(obj_{arg.name});' for arg in groups[ARG_STAR] + groups[ARG_STAR2]] arg_ptrs: List[str] = [] if groups[ARG_STAR] or groups[ARG_STAR2]: - arg_ptrs += ['&obj_{}'.format(groups[ARG_STAR][0].name) if groups[ARG_STAR] else 'NULL'] - arg_ptrs += ['&obj_{}'.format(groups[ARG_STAR2][0].name) if groups[ARG_STAR2] else 'NULL'] - arg_ptrs += ['&obj_{}'.format(arg.name) for arg in reordered_args] + arg_ptrs += [f'&obj_{groups[ARG_STAR][0].name}' if groups[ARG_STAR] else 'NULL'] + arg_ptrs += [f'&obj_{groups[ARG_STAR2][0].name}' if groups[ARG_STAR2] else 'NULL'] + arg_ptrs += [f'&obj_{arg.name}' for arg in reordered_args] emitter.emit_lines( 'if (!CPyArg_ParseTupleAndKeywords(args, kw, "{}", "{}", kwlist{})) {{'.format( @@ -322,7 +322,7 @@ def generate_bin_op_forward_only_wrapper(fn: FuncIR, # return NotImplemented # ... rmethod = reverse_op_methods[fn.name] - emitter.emit_line('_Py_IDENTIFIER({});'.format(rmethod)) + emitter.emit_line(f'_Py_IDENTIFIER({rmethod});') emitter.emit_line( 'return CPy_CallReverseOpMethod(obj_left, obj_right, "{}", &PyId_{});'.format( op_methods_to_symbols[fn.name], @@ -370,7 +370,7 @@ def generate_bin_op_both_wrappers(cl: ClassIR, gen.emit_call() gen.emit_error_handling() emitter.emit_line('} else {') - emitter.emit_line('_Py_IDENTIFIER({});'.format(fn_rev.name)) + emitter.emit_line(f'_Py_IDENTIFIER({fn_rev.name});') emitter.emit_line( 'return CPy_CallReverseOpMethod(obj_left, obj_right, "{}", &PyId_{});'.format( op_methods_to_symbols[fn.name], @@ -395,18 +395,18 @@ def generate_bin_op_both_wrappers(cl: ClassIR, def generate_richcompare_wrapper(cl: ClassIR, emitter: Emitter) -> Optional[str]: """Generates a wrapper for richcompare dunder methods.""" # Sort for determinism on Python 3.5 - matches = sorted([name for name in RICHCOMPARE_OPS if cl.has_method(name)]) + matches = sorted(name for name in RICHCOMPARE_OPS if cl.has_method(name)) if not matches: return None - name = '{}_RichCompare_{}'.format(DUNDER_PREFIX, cl.name_prefix(emitter.names)) + name = f'{DUNDER_PREFIX}_RichCompare_{cl.name_prefix(emitter.names)}' emitter.emit_line( 'static PyObject *{name}(PyObject *obj_lhs, PyObject *obj_rhs, int op) {{'.format( name=name) ) emitter.emit_line('switch (op) {') for func in matches: - emitter.emit_line('case {}: {{'.format(RICHCOMPARE_OPS[func])) + emitter.emit_line(f'case {RICHCOMPARE_OPS[func]}: {{') method = cl.get_method(func) assert method is not None generate_wrapper_core(method, emitter, arg_names=['lhs', 'rhs']) @@ -423,7 +423,7 @@ def generate_richcompare_wrapper(cl: ClassIR, emitter: Emitter) -> Optional[str] def generate_get_wrapper(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> str: """Generates a wrapper for native __get__ methods.""" - name = '{}{}{}'.format(DUNDER_PREFIX, fn.name, cl.name_prefix(emitter.names)) + name = f'{DUNDER_PREFIX}{fn.name}{cl.name_prefix(emitter.names)}' emitter.emit_line( 'static PyObject *{name}(PyObject *self, PyObject *instance, PyObject *owner) {{'. format(name=name)) @@ -438,7 +438,7 @@ def generate_get_wrapper(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> str: def generate_hash_wrapper(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> str: """Generates a wrapper for native __hash__ methods.""" - name = '{}{}{}'.format(DUNDER_PREFIX, fn.name, cl.name_prefix(emitter.names)) + name = f'{DUNDER_PREFIX}{fn.name}{cl.name_prefix(emitter.names)}' emitter.emit_line('static Py_ssize_t {name}(PyObject *self) {{'.format( name=name )) @@ -463,7 +463,7 @@ def generate_hash_wrapper(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> str: def generate_len_wrapper(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> str: """Generates a wrapper for native __len__ methods.""" - name = '{}{}{}'.format(DUNDER_PREFIX, fn.name, cl.name_prefix(emitter.names)) + name = f'{DUNDER_PREFIX}{fn.name}{cl.name_prefix(emitter.names)}' emitter.emit_line('static Py_ssize_t {name}(PyObject *self) {{'.format( name=name )) @@ -486,7 +486,7 @@ def generate_len_wrapper(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> str: def generate_bool_wrapper(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> str: """Generates a wrapper for native __bool__ methods.""" - name = '{}{}{}'.format(DUNDER_PREFIX, fn.name, cl.name_prefix(emitter.names)) + name = f'{DUNDER_PREFIX}{fn.name}{cl.name_prefix(emitter.names)}' emitter.emit_line('static int {name}(PyObject *self) {{'.format( name=name )) @@ -510,7 +510,7 @@ def generate_del_item_wrapper(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> str: This is only called from a combined __delitem__/__setitem__ wrapper. """ name = '{}{}{}'.format(DUNDER_PREFIX, '__delitem__', cl.name_prefix(emitter.names)) - input_args = ', '.join('PyObject *obj_{}'.format(arg.name) for arg in fn.args) + input_args = ', '.join(f'PyObject *obj_{arg.name}' for arg in fn.args) emitter.emit_line('static int {name}({input_args}) {{'.format( name=name, input_args=input_args, @@ -541,14 +541,14 @@ def generate_set_del_item_wrapper(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> args = list(args) + [RuntimeArg('___value', object_rprimitive, ARG_POS)] name = '{}{}{}'.format(DUNDER_PREFIX, '__setitem__', cl.name_prefix(emitter.names)) - input_args = ', '.join('PyObject *obj_{}'.format(arg.name) for arg in args) + input_args = ', '.join(f'PyObject *obj_{arg.name}' for arg in args) emitter.emit_line('static int {name}({input_args}) {{'.format( name=name, input_args=input_args, )) # First check if this is __delitem__ - emitter.emit_line('if (obj_{} == NULL) {{'.format(args[2].name)) + emitter.emit_line(f'if (obj_{args[2].name} == NULL) {{') if del_name is not None: # We have a native implementation, so call it emitter.emit_line('return {}(obj_{}, obj_{});'.format(del_name, @@ -557,7 +557,7 @@ def generate_set_del_item_wrapper(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> else: # Try to call superclass method instead emitter.emit_line( - 'PyObject *super = CPy_Super(CPyModule_builtins, obj_{});'.format(args[0].name)) + f'PyObject *super = CPy_Super(CPyModule_builtins, obj_{args[0].name});') emitter.emit_line('if (super == NULL) return -1;') emitter.emit_line( 'PyObject *result = PyObject_CallMethod(super, "__delitem__", "O", obj_{});'.format( @@ -572,14 +572,14 @@ def generate_set_del_item_wrapper(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> generate_set_del_item_wrapper_inner(fn, emitter, args) else: emitter.emit_line( - 'PyObject *super = CPy_Super(CPyModule_builtins, obj_{});'.format(args[0].name)) + f'PyObject *super = CPy_Super(CPyModule_builtins, obj_{args[0].name});') emitter.emit_line('if (super == NULL) return -1;') emitter.emit_line('PyObject *result;') if method_cls is None and cl.builtin_base is None: - msg = "'{}' object does not support item assignment".format(cl.name) + msg = f"'{cl.name}' object does not support item assignment" emitter.emit_line( - 'PyErr_SetString(PyExc_TypeError, "{}");'.format(msg)) + f'PyErr_SetString(PyExc_TypeError, "{msg}");') emitter.emit_line('result = NULL;') else: # A base class may have __setitem__ @@ -597,7 +597,7 @@ def generate_set_del_item_wrapper_inner(fn: FuncIR, emitter: Emitter, args: Sequence[RuntimeArg]) -> None: for arg in args: generate_arg_check(arg.name, arg.type, emitter, GotoHandler('fail')) - native_args = ', '.join('arg_{}'.format(arg.name) for arg in args) + native_args = ', '.join(f'arg_{arg.name}' for arg in args) emitter.emit_line('{}val = {}{}({});'.format(emitter.ctype_spaced(fn.ret_type), NATIVE_PREFIX, fn.cname(emitter.names), @@ -612,7 +612,7 @@ def generate_set_del_item_wrapper_inner(fn: FuncIR, emitter: Emitter, def generate_contains_wrapper(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> str: """Generates a wrapper for a native __contains__ method.""" - name = '{}{}{}'.format(DUNDER_PREFIX, fn.name, cl.name_prefix(emitter.names)) + name = f'{DUNDER_PREFIX}{fn.name}{cl.name_prefix(emitter.names)}' emitter.emit_line( 'static int {name}(PyObject *self, PyObject *obj_item) {{'. format(name=name)) @@ -676,8 +676,8 @@ def generate_arg_check(name: str, error = error or AssignHandler() if typ.is_unboxed: # Borrow when unboxing to avoid reference count manipulation. - emitter.emit_unbox('obj_{}'.format(name), - 'arg_{}'.format(name), + emitter.emit_unbox(f'obj_{name}', + f'arg_{name}', typ, declare_dest=True, raise_exception=raise_exception, @@ -687,15 +687,15 @@ def generate_arg_check(name: str, elif is_object_rprimitive(typ): # Object is trivial since any object is valid if optional: - emitter.emit_line('PyObject *arg_{};'.format(name)) - emitter.emit_line('if (obj_{} == NULL) {{'.format(name)) - emitter.emit_line('arg_{} = {};'.format(name, emitter.c_error_value(typ))) - emitter.emit_lines('} else {', 'arg_{} = obj_{}; '.format(name, name), '}') + emitter.emit_line(f'PyObject *arg_{name};') + emitter.emit_line(f'if (obj_{name} == NULL) {{') + emitter.emit_line(f'arg_{name} = {emitter.c_error_value(typ)};') + emitter.emit_lines('} else {', f'arg_{name} = obj_{name}; ', '}') else: - emitter.emit_line('PyObject *arg_{} = obj_{};'.format(name, name)) + emitter.emit_line(f'PyObject *arg_{name} = obj_{name};') else: - emitter.emit_cast('obj_{}'.format(name), - 'arg_{}'.format(name), + emitter.emit_cast(f'obj_{name}', + f'arg_{name}', typ, declare_dest=True, raise_exception=raise_exception, @@ -739,7 +739,7 @@ def use_goto(self) -> bool: def emit_header(self) -> None: """Emit the function header of the wrapper implementation.""" - input_args = ', '.join('PyObject *obj_{}'.format(arg) for arg in self.arg_names) + input_args = ', '.join(f'PyObject *obj_{arg}' for arg in self.arg_names) self.emitter.emit_line('static PyObject *{name}({input_args}) {{'.format( name=self.wrapper_name(), input_args=input_args, @@ -766,7 +766,7 @@ def emit_call(self, not_implemented_handler: str = '') -> None: If not_implemented_handler is non-empty, use this C code to handle a NotImplemented return value (if it's possible based on the return type). """ - native_args = ', '.join('arg_{}'.format(arg) for arg in self.arg_names) + native_args = ', '.join(f'arg_{arg}' for arg in self.arg_names) ret_type = self.ret_type emitter = self.emitter if ret_type.is_unboxed or self.use_goto(): diff --git a/mypyc/common.py b/mypyc/common.py index 6080649f7eb6a..e07bbe2511cb2 100644 --- a/mypyc/common.py +++ b/mypyc/common.py @@ -75,7 +75,7 @@ def shared_lib_name(group_name: str) -> str: (This just adds a suffix to the final component.) """ - return '{}__mypyc'.format(group_name) + return f'{group_name}__mypyc' def short_name(name: str) -> str: @@ -107,7 +107,7 @@ def get_id_from_name(name: str, fullname: str, line: int) -> str: it handles the case where the function is named '_', in which case multiple different functions could have the same name.""" if unnamed_function(name): - return "{}.{}".format(fullname, line) + return f"{fullname}.{line}" else: return fullname @@ -115,7 +115,7 @@ def get_id_from_name(name: str, fullname: str, line: int) -> str: def short_id_from_name(func_name: str, shortname: str, line: Optional[int]) -> str: if unnamed_function(func_name): assert line is not None - partial_name = "{}.{}".format(shortname, line) + partial_name = f"{shortname}.{line}" else: partial_name = shortname return partial_name diff --git a/mypyc/crash.py b/mypyc/crash.py index 04948dd08decf..b248e27bbdb87 100644 --- a/mypyc/crash.py +++ b/mypyc/crash.py @@ -27,5 +27,5 @@ def crash_report(module_path: str, line: int) -> 'NoReturn': print('Traceback (most recent call last):') for s in traceback.format_list(tb + tb2): print(s.rstrip('\n')) - print('{}:{}: {}: {}'.format(module_path, line, type(err).__name__, err)) + print(f'{module_path}:{line}: {type(err).__name__}: {err}') raise SystemExit(2) diff --git a/mypyc/ir/class_ir.py b/mypyc/ir/class_ir.py index d6407610e2bcf..2e3e2b15c9301 100644 --- a/mypyc/ir/class_ir.py +++ b/mypyc/ir/class_ir.py @@ -75,6 +75,7 @@ ('method', FuncIR), ('shadow_method', Optional[FuncIR])]) + VTableEntries = List[VTableMethod] @@ -162,7 +163,7 @@ def __repr__(self) -> str: @property def fullname(self) -> str: - return "{}.{}".format(self.module_name, self.name) + return f"{self.module_name}.{self.name}" def real_base(self) -> Optional['ClassIR']: """Return the actual concrete base class, if there is one.""" @@ -172,7 +173,7 @@ def real_base(self) -> Optional['ClassIR']: def vtable_entry(self, name: str) -> int: assert self.vtable is not None, "vtable not computed yet" - assert name in self.vtable, '%r has no attribute %r' % (self.name, name) + assert name in self.vtable, f'{self.name!r} has no attribute {name!r}' return self.vtable[name] def attr_details(self, name: str) -> Tuple[RType, 'ClassIR']: @@ -181,7 +182,7 @@ def attr_details(self, name: str) -> Tuple[RType, 'ClassIR']: return ir.attributes[name], ir if name in ir.property_types: return ir.property_types[name], ir - raise KeyError('%r has no attribute %r' % (self.name, name)) + raise KeyError(f'{self.name!r} has no attribute {name!r}') def attr_type(self, name: str) -> RType: return self.attr_details(name)[0] @@ -190,7 +191,7 @@ def method_decl(self, name: str) -> FuncDecl: for ir in self.mro: if name in ir.method_decls: return ir.method_decls[name] - raise KeyError('%r has no attribute %r' % (self.name, name)) + raise KeyError(f'{self.name!r} has no attribute {name!r}') def method_sig(self, name: str) -> FuncSignature: return self.method_decl(name).sig @@ -234,7 +235,7 @@ def name_prefix(self, names: NameGenerator) -> str: return names.private_name(self.module_name, self.name) def struct_name(self, names: NameGenerator) -> str: - return '{}Object'.format(exported_name(self.fullname)) + return f'{exported_name(self.fullname)}Object' def get_method_and_class(self, name: str) -> Optional[Tuple[FuncIR, 'ClassIR']]: for ir in self.mro: diff --git a/mypyc/ir/func_ir.py b/mypyc/ir/func_ir.py index 1426b0ecdf0f6..6a5a720e309bc 100644 --- a/mypyc/ir/func_ir.py +++ b/mypyc/ir/func_ir.py @@ -31,7 +31,7 @@ def optional(self) -> bool: return self.kind.is_optional() def __repr__(self) -> str: - return 'RuntimeArg(name=%s, type=%s, optional=%r, pos_only=%r)' % ( + return 'RuntimeArg(name={}, type={}, optional={!r}, pos_only={!r})'.format( self.name, self.type, self.optional, self.pos_only) def serialize(self) -> JsonDict: @@ -58,7 +58,7 @@ def __init__(self, args: Sequence[RuntimeArg], ret_type: RType) -> None: self.ret_type = ret_type def __repr__(self) -> str: - return 'FuncSignature(args=%r, ret=%r)' % (self.args, self.ret_type) + return f'FuncSignature(args={self.args!r}, ret={self.ret_type!r})' def serialize(self) -> JsonDict: return {'args': [t.serialize() for t in self.args], 'ret_type': self.ret_type.serialize()} @@ -234,9 +234,9 @@ def cname(self, names: NameGenerator) -> str: def __repr__(self) -> str: if self.class_name: - return ''.format(self.class_name, self.name) + return f'' else: - return ''.format(self.name) + return f'' def serialize(self) -> JsonDict: # We don't include blocks in the serialized version diff --git a/mypyc/ir/ops.py b/mypyc/ir/ops.py index 65480ebcc7c38..ecd2293c657f7 100644 --- a/mypyc/ir/ops.py +++ b/mypyc/ir/ops.py @@ -145,7 +145,7 @@ def is_void(self) -> bool: return False def __repr__(self) -> str: - return '' % (self.name, hex(id(self))) + return f'' class Integer(Value): @@ -279,7 +279,7 @@ def targets(self) -> Sequence[BasicBlock]: def set_target(self, i: int, new: BasicBlock) -> None: """Update a basic block target.""" - raise AssertionError("Invalid set_target({}, {})".format(self, i)) + raise AssertionError(f"Invalid set_target({self}, {i})") class Goto(ControlOp): @@ -474,7 +474,7 @@ def __init__(self, src: Value, is_xdec: bool = False, line: int = -1) -> None: self.is_xdec = is_xdec def __repr__(self) -> str: - return '<%sDecRef %r>' % ('X' if self.is_xdec else '', self.src) + return '<{}DecRef {!r}>'.format('X' if self.is_xdec else '', self.src) def sources(self) -> List[Value]: return [self.src] diff --git a/mypyc/ir/pprint.py b/mypyc/ir/pprint.py index daa0fd0f86df4..aab8dc86664ff 100644 --- a/mypyc/ir/pprint.py +++ b/mypyc/ir/pprint.py @@ -40,15 +40,15 @@ def visit_goto(self, op: Goto) -> str: def visit_branch(self, op: Branch) -> str: fmt, typ = self.branch_op_names[op.op] if op.negated: - fmt = 'not {}'.format(fmt) + fmt = f'not {fmt}' cond = self.format(fmt, op.value) tb = '' if op.traceback_entry: tb = ' (error at %s:%d)' % op.traceback_entry - fmt = 'if {} goto %l{} else goto %l'.format(cond, tb) + fmt = f'if {cond} goto %l{tb} else goto %l' if typ: - fmt += ' :: {}'.format(typ) + fmt += f' :: {typ}' return self.format(fmt, op.true, op.false) def visit_return(self, op: Return) -> str: @@ -83,16 +83,16 @@ def visit_set_attr(self, op: SetAttr) -> str: return self.format('%r.%s = %r; %r = is_error', op.obj, op.attr, op.src, op) def visit_load_static(self, op: LoadStatic) -> str: - ann = ' ({})'.format(repr(op.ann)) if op.ann else '' + ann = f' ({repr(op.ann)})' if op.ann else '' name = op.identifier if op.module_name is not None: - name = '{}.{}'.format(op.module_name, name) + name = f'{op.module_name}.{name}' return self.format('%r = %s :: %s%s', op, name, op.namespace, ann) def visit_init_static(self, op: InitStatic) -> str: name = op.identifier if op.module_name is not None: - name = '{}.{}'.format(op.module_name, name) + name = f'{op.module_name}.{name}' return self.format('%s = %r :: %s', name, op.value, op.namespace) def visit_tuple_get(self, op: TupleGet) -> str: @@ -106,21 +106,21 @@ def visit_inc_ref(self, op: IncRef) -> str: s = self.format('inc_ref %r', op.src) # TODO: Remove bool check (it's unboxed) if is_bool_rprimitive(op.src.type) or is_int_rprimitive(op.src.type): - s += ' :: {}'.format(short_name(op.src.type.name)) + s += f' :: {short_name(op.src.type.name)}' return s def visit_dec_ref(self, op: DecRef) -> str: s = self.format('%sdec_ref %r', 'x' if op.is_xdec else '', op.src) # TODO: Remove bool check (it's unboxed) if is_bool_rprimitive(op.src.type) or is_int_rprimitive(op.src.type): - s += ' :: {}'.format(short_name(op.src.type.name)) + s += f' :: {short_name(op.src.type.name)}' return s def visit_call(self, op: Call) -> str: args = ', '.join(self.format('%r', arg) for arg in op.args) # TODO: Display long name? short_name = op.fn.shortname - s = '%s(%s)' % (short_name, args) + s = f'{short_name}({args})' if not op.is_void: s = self.format('%r = ', op) + s return s @@ -163,7 +163,7 @@ def visit_truncate(self, op: Truncate) -> str: return self.format("%r = truncate %r: %t to %t", op, op.src, op.src_type, op.type) def visit_load_global(self, op: LoadGlobal) -> str: - ann = ' ({})'.format(repr(op.ann)) if op.ann else '' + ann = f' ({repr(op.ann)})' if op.ann else '' return self.format('%r = load_global %s :: static%s', op, op.identifier, ann) def visit_int_op(self, op: IntOp) -> str: @@ -248,7 +248,7 @@ def format(self, fmt: str, *args: Any) -> str: # String result.append(str(arg)) else: - raise ValueError('Invalid format sequence %{}'.format(typespec)) + raise ValueError(f'Invalid format sequence %{typespec}') i = n + 2 else: i = n @@ -267,7 +267,7 @@ def format_registers(func_ir: FuncIR, i += 1 group.append(names[regs[i]]) i += 1 - result.append('%s :: %s' % (', '.join(group), regs[i0].type)) + result.append('{} :: {}'.format(', '.join(group), regs[i0].type)) return result diff --git a/mypyc/ir/rtypes.py b/mypyc/ir/rtypes.py index 4bf71883b15df..2c875d7c8f01d 100644 --- a/mypyc/ir/rtypes.py +++ b/mypyc/ir/rtypes.py @@ -65,7 +65,7 @@ def __repr__(self) -> str: return '<%s>' % self.__class__.__name__ def serialize(self) -> Union[JsonDict, str]: - raise NotImplementedError('Cannot serialize {} instance'.format(self.__class__.__name__)) + raise NotImplementedError(f'Cannot serialize {self.__class__.__name__} instance') def deserialize_type(data: Union[JsonDict, str], ctx: 'DeserMaps') -> 'RType': @@ -86,7 +86,7 @@ def deserialize_type(data: Union[JsonDict, str], ctx: 'DeserMaps') -> 'RType': elif data == "void": return RVoid() else: - assert False, "Can't find class {}".format(data) + assert False, f"Can't find class {data}" elif data['.class'] == 'RTuple': return RTuple.deserialize(data, ctx) elif data['.class'] == 'RUnion': @@ -445,7 +445,7 @@ def visit_rprimitive(self, t: 'RPrimitive') -> str: return 'I' elif t._ctype == 'char': return 'C' - assert not t.is_unboxed, "{} unexpected unboxed type".format(t) + assert not t.is_unboxed, f"{t} unexpected unboxed type" return 'O' def visit_rtuple(self, t: 'RTuple') -> str: @@ -488,8 +488,8 @@ def __init__(self, types: List[RType]) -> None: # in the same way python can just assign a Tuple[int, bool] to a Tuple[int, bool]. self.unique_id = self.accept(TupleNameVisitor()) # Nominally the max c length is 31 chars, but I'm not honestly worried about this. - self.struct_name = 'tuple_{}'.format(self.unique_id) - self._ctype = '{}'.format(self.struct_name) + self.struct_name = f'tuple_{self.unique_id}' + self._ctype = f'{self.struct_name}' def accept(self, visitor: 'RTypeVisitor[T]') -> T: return visitor.visit_rtuple(self) @@ -548,7 +548,7 @@ def compute_rtype_alignment(typ: RType) -> int: items = typ.types else: assert False, "invalid rtype for computing alignment" - max_alignment = max([compute_rtype_alignment(item) for item in items]) + max_alignment = max(compute_rtype_alignment(item) for item in items) return max_alignment @@ -622,12 +622,14 @@ def accept(self, visitor: 'RTypeVisitor[T]') -> T: def __str__(self) -> str: # if not tuple(unnamed structs) - return '%s{%s}' % (self.name, ', '.join(name + ":" + str(typ) + return '{}{{{}}}'.format(self.name, ', '.join(name + ":" + str(typ) for name, typ in zip(self.names, self.types))) def __repr__(self) -> str: - return '' % (self.name, ', '.join(name + ":" + repr(typ) for name, typ - in zip(self.names, self.types))) + return ''.format( + self.name, ', '.join(name + ":" + repr(typ) + for name, typ in zip(self.names, self.types)) + ) def __eq__(self, other: object) -> bool: return (isinstance(other, RStruct) and self.name == other.name @@ -774,10 +776,10 @@ def accept(self, visitor: 'RTypeVisitor[T]') -> T: return visitor.visit_rarray(self) def __str__(self) -> str: - return '%s[%s]' % (self.item_type, self.length) + return f'{self.item_type}[{self.length}]' def __repr__(self) -> str: - return '' % (self.item_type, self.length) + return f'' def __eq__(self, other: object) -> bool: return (isinstance(other, RArray) and self.item_type == other.item_type diff --git a/mypyc/irbuild/builder.py b/mypyc/irbuild/builder.py index 57baa8dbf5748..72c03801e326e 100644 --- a/mypyc/irbuild/builder.py +++ b/mypyc/irbuild/builder.py @@ -419,7 +419,7 @@ def init_final_static(self, if class_name is None: name = lvalue.name else: - name = '{}.{}'.format(class_name, lvalue.name) + name = f'{class_name}.{lvalue.name}' assert name is not None, "Full name not set for variable" coerced = self.coerce(rvalue_reg, type_override or self.node_type(lvalue), lvalue.line) self.final_names.append((name, coerced.type)) @@ -432,7 +432,7 @@ def load_final_static(self, fullname: str, typ: RType, line: int, module, name = split_name return self.builder.load_static_checked( typ, name, module, line=line, - error_msg='value for final name "{}" was not set'.format(error_name)) + error_msg=f'value for final name "{error_name}" was not set') def load_final_literal_value(self, val: Union[int, str, bytes, float, bool], line: int) -> Value: @@ -685,7 +685,7 @@ def pop_loop_stack(self) -> None: def spill(self, value: Value) -> AssignmentTarget: """Moves a given Value instance into the generator class' environment class.""" - name = '{}{}'.format(TEMP_ATTR_NAME, self.temp_counter) + name = f'{TEMP_ATTR_NAME}{self.temp_counter}' self.temp_counter += 1 target = self.add_var_to_env_class(Var(name), value.type, self.fn_info.generator_class) # Shouldn't be able to fail, so -1 for line @@ -817,7 +817,7 @@ def get_final_ref(self, expr: MemberExpr) -> Optional[Tuple[str, Var, bool]]: is_final = sym.node.is_final or expr_fullname == 'enum.Enum' if is_final: final_var = sym.node - fullname = '{}.{}'.format(sym.node.info.fullname, final_var.name) + fullname = f'{sym.node.info.fullname}.{final_var.name}' native = self.is_native_module(expr.expr.node.module_name) elif self.is_module_member_expr(expr): # a module attribute diff --git a/mypyc/irbuild/callable_class.py b/mypyc/irbuild/callable_class.py index 0261332800aed..fe561cfc531d5 100644 --- a/mypyc/irbuild/callable_class.py +++ b/mypyc/irbuild/callable_class.py @@ -45,7 +45,7 @@ class for the nested function. # else: # def foo(): ----> foo_obj_0() # return False - name = base_name = '{}_obj'.format(builder.fn_info.namespaced_name()) + name = base_name = f'{builder.fn_info.namespaced_name()}_obj' count = 0 while name in builder.callable_class_names: name = base_name + '_' + str(count) diff --git a/mypyc/irbuild/classdef.py b/mypyc/irbuild/classdef.py index 80ec331cd5502..9a458181dc6c3 100644 --- a/mypyc/irbuild/classdef.py +++ b/mypyc/irbuild/classdef.py @@ -588,11 +588,11 @@ def check_deletable_declaration(builder: IRBuilder, cl: ClassIR, line: int) -> N for attr in cl.deletable: if attr not in cl.attributes: if not cl.has_attr(attr): - builder.error('Attribute "{}" not defined'.format(attr), line) + builder.error(f'Attribute "{attr}" not defined', line) continue for base in cl.mro: if attr in base.property_types: - builder.error('Cannot make property "{}" deletable'.format(attr), line) + builder.error(f'Cannot make property "{attr}" deletable', line) break else: _, base = cl.attr_details(attr) diff --git a/mypyc/irbuild/env_class.py b/mypyc/irbuild/env_class.py index 44bcccb507d01..9ed764c8bcca4 100644 --- a/mypyc/irbuild/env_class.py +++ b/mypyc/irbuild/env_class.py @@ -43,7 +43,7 @@ class is generated, the function environment has not yet been Return a ClassIR representing an environment for a function containing a nested function. """ - env_class = ClassIR('{}_env'.format(builder.fn_info.namespaced_name()), + env_class = ClassIR(f'{builder.fn_info.namespaced_name()}_env', builder.module_name, is_generated=True) env_class.attributes[SELF_NAME] = RInstance(env_class) if builder.fn_info.is_nested: @@ -122,7 +122,7 @@ def load_outer_env(builder: IRBuilder, Returns the register where the environment class was loaded. """ env = builder.add(GetAttr(base, ENV_ATTR_NAME, builder.fn_info.fitem.line)) - assert isinstance(env.type, RInstance), '{} must be of type RInstance'.format(env) + assert isinstance(env.type, RInstance), f'{env} must be of type RInstance' for symbol, target in outer_env.items(): env.type.class_ir.attributes[symbol.name] = target.type diff --git a/mypyc/irbuild/function.py b/mypyc/irbuild/function.py index 5b567251111ab..275d3449f8128 100644 --- a/mypyc/irbuild/function.py +++ b/mypyc/irbuild/function.py @@ -130,7 +130,7 @@ def transform_lambda_expr(builder: IRBuilder, expr: LambdaExpr) -> Value: fsig = FuncSignature(runtime_args, ret_type) - fname = '{}{}'.format(LAMBDA_NAME, builder.lambda_counter) + fname = f'{LAMBDA_NAME}{builder.lambda_counter}' builder.lambda_counter += 1 func_ir, func_reg = gen_func_item(builder, expr, fname, fsig) assert func_reg is not None @@ -993,7 +993,7 @@ def load_singledispatch_registry(builder: IRBuilder, dispatch_func_obj: Value, l def singledispatch_main_func_name(orig_name: str) -> str: - return '__mypyc_singledispatch_main_function_{}__'.format(orig_name) + return f'__mypyc_singledispatch_main_function_{orig_name}__' def get_registry_identifier(fitem: FuncDef) -> str: diff --git a/mypyc/irbuild/generator.py b/mypyc/irbuild/generator.py index 7655939b44128..7a96d390e156d 100644 --- a/mypyc/irbuild/generator.py +++ b/mypyc/irbuild/generator.py @@ -64,7 +64,7 @@ def instantiate_generator_class(builder: IRBuilder) -> Value: def setup_generator_class(builder: IRBuilder) -> ClassIR: - name = '{}_gen'.format(builder.fn_info.namespaced_name()) + name = f'{builder.fn_info.namespaced_name()}_gen' generator_class_ir = ClassIR(name, builder.module_name, is_generated=True) generator_class_ir.attributes[ENV_ATTR_NAME] = RInstance(builder.fn_info.env_class) diff --git a/mypyc/irbuild/ll_builder.py b/mypyc/irbuild/ll_builder.py index 98a69d92406d8..1927773489b15 100644 --- a/mypyc/irbuild/ll_builder.py +++ b/mypyc/irbuild/ll_builder.py @@ -821,7 +821,7 @@ def load_static_checked(self, typ: RType, identifier: str, module_name: Optional line: int = -1, error_msg: Optional[str] = None) -> Value: if error_msg is None: - error_msg = 'name "{}" is not defined'.format(identifier) + error_msg = f'name "{identifier}" is not defined' ok_block, error_block = BasicBlock(), BasicBlock() value = self.add(LoadStatic(typ, identifier, module_name, namespace, line=line)) self.add(Branch(value, error_block, ok_block, Branch.IS_ERROR, rare=True)) @@ -838,7 +838,7 @@ def load_module(self, name: str) -> Value: def get_native_type(self, cls: ClassIR) -> Value: """Load native type object.""" - fullname = '%s.%s' % (cls.module_name, cls.name) + fullname = f'{cls.module_name}.{cls.name}' return self.load_native_type_object(fullname) def load_native_type_object(self, fullname: str) -> Value: @@ -1332,7 +1332,7 @@ def matching_call_c(self, if all(is_subtype(actual.type, formal) for actual, formal in zip(args, desc.arg_types)): if matching: - assert matching.priority != desc.priority, 'Ambiguous:\n1) %s\n2) %s' % ( + assert matching.priority != desc.priority, 'Ambiguous:\n1) {}\n2) {}'.format( matching, desc) if desc.priority > matching.priority: matching = desc diff --git a/mypyc/irbuild/statement.py b/mypyc/irbuild/statement.py index 6a744781ee50b..9c9273b0cd769 100644 --- a/mypyc/irbuild/statement.py +++ b/mypyc/irbuild/statement.py @@ -666,7 +666,7 @@ def transform_del_item(builder: IRBuilder, target: AssignmentTarget, line: int) if isinstance(target.obj_type, RInstance): cl = target.obj_type.class_ir if not cl.is_deletable(target.attr): - builder.error('"{}" cannot be deleted'.format(target.attr), line) + builder.error(f'"{target.attr}" cannot be deleted', line) builder.note( 'Using "__deletable__ = ' + '[\'\']" in the class body enables "del obj."', line) diff --git a/mypyc/namegen.py b/mypyc/namegen.py index acf901caf93cb..99abf8a759ff4 100644 --- a/mypyc/namegen.py +++ b/mypyc/namegen.py @@ -73,7 +73,7 @@ def private_name(self, module: str, partial_name: Optional[str] = None) -> str: module_prefix = module + '.' else: module_prefix = '' - actual = exported_name('{}{}'.format(module_prefix, partial_name)) + actual = exported_name(f'{module_prefix}{partial_name}') self.translations[module, partial_name] = actual return actual diff --git a/mypyc/primitives/int_ops.py b/mypyc/primitives/int_ops.py index f4a2ce8c66e35..44703528976c3 100644 --- a/mypyc/primitives/int_ops.py +++ b/mypyc/primitives/int_ops.py @@ -124,6 +124,7 @@ def int_unary_op(name: str, c_function_name: str) -> CFunctionDescription: int_neg_op = int_unary_op('-', 'CPyTagged_Negate') int_invert_op = int_unary_op('~', 'CPyTagged_Invert') + # Primitives related to integer comparison operations: # Description for building int comparison ops @@ -139,6 +140,7 @@ def int_unary_op(name: str, c_function_name: str) -> CFunctionDescription: ('c_func_negated', bool), ('c_func_swap_operands', bool)]) + # Equals operation on two boxed tagged integers int_equal_ = custom_op( arg_types=[int_rprimitive, int_rprimitive], diff --git a/mypyc/primitives/registry.py b/mypyc/primitives/registry.py index 5ed910549f5aa..0174051ec98d4 100644 --- a/mypyc/primitives/registry.py +++ b/mypyc/primitives/registry.py @@ -60,6 +60,7 @@ ('extra_int_constants', List[Tuple[int, RType]]), ('priority', int)]) + # A description for C load operations including LoadGlobal and LoadAddress LoadAddressDescription = NamedTuple( 'LoadAddressDescription', [('name', str), diff --git a/mypyc/test-data/fixtures/testutil.py b/mypyc/test-data/fixtures/testutil.py index 462b02c1946dd..f6c20835a2876 100644 --- a/mypyc/test-data/fixtures/testutil.py +++ b/mypyc/test-data/fixtures/testutil.py @@ -11,10 +11,10 @@ def assertRaises(typ: type, msg: str = '') -> Iterator[None]: try: yield except Exception as e: - assert isinstance(e, typ), "{} is not a {}".format(e, typ.__name__) - assert msg in str(e), 'Message "{}" does not match "{}"'.format(e, msg) + assert isinstance(e, typ), f"{e} is not a {typ.__name__}" + assert msg in str(e), f'Message "{e}" does not match "{msg}"' else: - assert False, "Expected {} but got no exception".format(typ.__name__) + assert False, f"Expected {typ.__name__} but got no exception" T = TypeVar('T') U = TypeVar('U') diff --git a/mypyc/test/test_cheader.py b/mypyc/test/test_cheader.py index 0301a66707201..0966059e24438 100644 --- a/mypyc/test/test_cheader.py +++ b/mypyc/test/test_cheader.py @@ -19,8 +19,8 @@ def test_primitives_included_in_header(self) -> None: def check_name(name: str) -> None: if name.startswith('CPy'): - assert re.search(r'\b{}\b'.format(name), header), ( - '"{}" is used in mypyc.primitives but not declared in CPy.h'.format(name)) + assert re.search(fr'\b{name}\b', header), ( + f'"{name}" is used in mypyc.primitives but not declared in CPy.h') for values in [registry.method_call_ops.values(), registry.function_ops.values(), @@ -33,7 +33,7 @@ def check_name(name: str) -> None: check_name(op.c_function_name) primitives_path = os.path.join(os.path.dirname(__file__), '..', 'primitives') - for fnam in glob.glob('{}/*.py'.format(primitives_path)): + for fnam in glob.glob(f'{primitives_path}/*.py'): with open(fnam) as f: content = f.read() for name in re.findall(r'c_function_name=["\'](CPy[A-Z_a-z0-9]+)', content): diff --git a/mypyc/test/test_commandline.py b/mypyc/test/test_commandline.py index 5c80d0fddb1d7..3ca380f8eebd5 100644 --- a/mypyc/test/test_commandline.py +++ b/mypyc/test/test_commandline.py @@ -59,7 +59,7 @@ def run_case(self, testcase: DataDrivenTestCase) -> None: cwd='tmp') finally: suffix = 'pyd' if sys.platform == 'win32' else 'so' - so_paths = glob.glob('tmp/**/*.{}'.format(suffix), recursive=True) + so_paths = glob.glob(f'tmp/**/*.{suffix}', recursive=True) for path in so_paths: os.remove(path) diff --git a/mypyc/test/test_run.py b/mypyc/test/test_run.py index 2a2aa8fae0e4b..466815534fdbd 100644 --- a/mypyc/test/test_run.py +++ b/mypyc/test/test_run.py @@ -263,7 +263,7 @@ def run_case_step(self, testcase: DataDrivenTestCase, incremental_step: int) -> # Assert that an output file got created suffix = 'pyd' if sys.platform == 'win32' else 'so' - assert glob.glob('native.*.{}'.format(suffix)) or glob.glob('native.{}'.format(suffix)) + assert glob.glob(f'native.*.{suffix}') or glob.glob(f'native.{suffix}') driver_path = 'driver.py' if not os.path.isfile(driver_path): @@ -309,7 +309,7 @@ def run_case_step(self, testcase: DataDrivenTestCase, incremental_step: int) -> msg = 'Invalid output' expected = testcase.output else: - msg = 'Invalid output (step {})'.format(incremental_step) + msg = f'Invalid output (step {incremental_step})' expected = testcase.output2.get(incremental_step, []) if not expected: diff --git a/mypyc/test/test_serialization.py b/mypyc/test/test_serialization.py index 5737ccc7b6238..683bb807620e7 100644 --- a/mypyc/test/test_serialization.py +++ b/mypyc/test/test_serialization.py @@ -46,27 +46,27 @@ def assert_blobs_same(x: Any, y: Any, trail: Tuple[Any, ...]) -> None: The `trail` argument is used in error messages. """ - assert type(x) is type(y), ("Type mismatch at {}".format(trail), type(x), type(y)) + 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, "Name mismatch at {}".format(trail) + assert x.fullname == y.fullname, f"Name mismatch at {trail}" elif isinstance(x, OrderedDict): - assert len(x.keys()) == len(y.keys()), "Keys mismatch at {}".format(trail) + 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",)) assert_blobs_same(xv, yv, trail + (xk,)) elif isinstance(x, dict): - assert x.keys() == y.keys(), "Keys mismatch at {}".format(trail) + assert x.keys() == y.keys(), f"Keys mismatch at {trail}" for k in x.keys(): assert_blobs_same(x[k], y[k], trail + (k,)) elif isinstance(x, Iterable) and not isinstance(x, str): for i, (xv, yv) in enumerate(zip(x, y)): assert_blobs_same(xv, yv, trail + (i,)) elif isinstance(x, RType): - assert is_same_type(x, y), "RType mismatch at {}".format(trail) + assert is_same_type(x, y), f"RType mismatch at {trail}" elif isinstance(x, FuncSignature): - assert is_same_signature(x, y), "Signature mismatch at {}".format(trail) + assert is_same_signature(x, y), f"Signature mismatch at {trail}" else: - assert x == y, "Value mismatch at {}".format(trail) + assert x == y, f"Value mismatch at {trail}" def assert_modules_same(ir1: ModuleIR, ir2: ModuleIR) -> None: diff --git a/mypyc/test/testutil.py b/mypyc/test/testutil.py index 985356bc469ba..c5dc2588a7e20 100644 --- a/mypyc/test/testutil.py +++ b/mypyc/test/testutil.py @@ -134,7 +134,7 @@ def update_testcase_output(testcase: DataDrivenTestCase, output: List[str]) -> N # We can't rely on the test line numbers to *find* the test, since # we might fix multiple tests in a run. So find it by the case # header. Give up if there are multiple tests with the same name. - test_slug = '[case {}]'.format(testcase.name) + test_slug = f'[case {testcase.name}]' if data_lines.count(test_slug) != 1: return start_idx = data_lines.index(test_slug) @@ -165,7 +165,7 @@ def assert_test_output(testcase: DataDrivenTestCase, assert_string_arrays_equal( expected_output, actual, - '{} ({}, line {})'.format(message, testcase.file, testcase.line)) + f'{message} ({testcase.file}, line {testcase.line})') def get_func_names(expected: List[str]) -> List[str]: @@ -205,7 +205,7 @@ def show_c(cfiles: List[List[Tuple[str, str]]]) -> None: heading('Generated C') for group in cfiles: for cfile, ctext in group: - print('== {} =='.format(cfile)) + print(f'== {cfile} ==') print_with_line_numbers(ctext) heading('End C') @@ -262,5 +262,5 @@ def infer_ir_build_options_from_test_name(name: str) -> Optional[CompilerOptions if m: options.capi_version = (int(m.group(1)), int(m.group(2))) elif '_py' in name or '_Python' in name: - assert False, 'Invalid _py* suffix (should be _pythonX_Y): {}'.format(name) + assert False, f'Invalid _py* suffix (should be _pythonX_Y): {name}' return options diff --git a/mypyc/transform/uninit.py b/mypyc/transform/uninit.py index 47544e511734d..ca21d2690636d 100644 --- a/mypyc/transform/uninit.py +++ b/mypyc/transform/uninit.py @@ -72,7 +72,7 @@ def split_blocks_at_uninits(blocks: List[BasicBlock], line=op.line)) raise_std = RaiseStandardError( RaiseStandardError.UNBOUND_LOCAL_ERROR, - 'local variable "{}" referenced before assignment'.format(src.name), + f'local variable "{src.name}" referenced before assignment', op.line) error_block.ops.append(raise_std) error_block.ops.append(Unreachable()) From 9f8b814fc5b3bb8daf0ef04aca3dfd1fb056bc8b Mon Sep 17 00:00:00 2001 From: Marcel Otoboni Date: Tue, 3 May 2022 09:05:15 -0300 Subject: [PATCH 275/377] Add check if python_version was parsed as float in pyproject.toml (#12558) Fixes #12108 Co-authored-by: Marcel-ICMC Co-authored-by: Shantanu <12621235+hauntsaninja@users.noreply.github.com> --- mypy/config_parser.py | 18 ++++++++++++------ test-data/unit/cmdline.test | 9 +++++++++ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/mypy/config_parser.py b/mypy/config_parser.py index 952c3f96f29ab..678e68cca886d 100644 --- a/mypy/config_parser.py +++ b/mypy/config_parser.py @@ -24,8 +24,8 @@ _INI_PARSER_CALLABLE: _TypeAlias = Callable[[Any], _CONFIG_VALUE_TYPES] -def parse_version(v: str) -> Tuple[int, int]: - m = re.match(r'\A(\d)\.(\d+)\Z', v) +def parse_version(v: Union[str, float]) -> Tuple[int, int]: + m = re.match(r'\A(\d)\.(\d+)\Z', str(v)) if not m: raise argparse.ArgumentTypeError( f"Invalid python version '{v}' (expected format: 'x.y')") @@ -36,9 +36,15 @@ def parse_version(v: str) -> Tuple[int, int]: f"Python 2.{minor} is not supported (must be 2.7)") elif major == 3: if minor < defaults.PYTHON3_VERSION_MIN[1]: - raise argparse.ArgumentTypeError( - "Python 3.{} is not supported (must be {}.{} or higher)".format(minor, - *defaults.PYTHON3_VERSION_MIN)) + msg = "Python 3.{0} is not supported (must be {1}.{2} or higher)".format( + minor, + *defaults.PYTHON3_VERSION_MIN + ) + + if isinstance(v, float): + msg += ". You may need to put quotes around your Python version" + + raise argparse.ArgumentTypeError(msg) else: raise argparse.ArgumentTypeError( f"Python major version '{major}' out of range (must be 2 or 3)") @@ -142,7 +148,7 @@ def check_follow_imports(choice: str) -> str: # Reuse the ini_config_types and overwrite the diff toml_config_types: Final[Dict[str, _INI_PARSER_CALLABLE]] = ini_config_types.copy() toml_config_types.update({ - 'python_version': lambda s: parse_version(str(s)), + 'python_version': parse_version, 'strict_optional_whitelist': try_split, 'mypy_path': lambda s: [expand_path(p) for p in try_split(s, '[,:]')], 'files': lambda s: split_and_match_files_list(try_split(s)), diff --git a/test-data/unit/cmdline.test b/test-data/unit/cmdline.test index 7fc5176433424..66dfd4edff2ec 100644 --- a/test-data/unit/cmdline.test +++ b/test-data/unit/cmdline.test @@ -561,6 +561,15 @@ main.py:1: error: Cannot find implementation or library stub for module named "a main.py:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports main.py:1: error: Cannot find implementation or library stub for module named "a" +[case testPythonVersionWrongFormatPyProjectTOML] +# cmd: mypy -c pass +[file pyproject.toml] +\[tool.mypy] +python_version = 3.10 +[out] +pyproject.toml: [mypy]: python_version: Python 3.1 is not supported (must be 3.4 or higher). You may need to put quotes around your Python version +== Return code: 0 + [case testPythonVersionTooOld10] # cmd: mypy -c pass [file mypy.ini] From 4746519effeafc64da7687af8fe1685d44545219 Mon Sep 17 00:00:00 2001 From: dzcode <9089037+dzcode@users.noreply.github.com> Date: Tue, 3 May 2022 15:12:00 -0600 Subject: [PATCH 276/377] Fix crash when using decorator in class scope (#12724) Fixes #12474 --- mypy/semanal.py | 6 +++--- test-data/unit/check-classes.test | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index a9445a9c87489..62ec1c823ec2b 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4927,7 +4927,7 @@ def _get_node_for_class_scoped_import( # when it can also be a FuncBase. Once fixed, `f` in the following can be removed. # See also https://github.com/mypyc/mypyc/issues/892 f = cast(Any, lambda x: x) - if isinstance(f(symbol_node), (FuncBase, Var)): + if isinstance(f(symbol_node), (Decorator, FuncBase, Var)): # For imports in class scope, we construct a new node to represent the symbol and # set its `info` attribute to `self.type`. existing = self.current_symbol_table().get(name) @@ -4935,7 +4935,7 @@ def _get_node_for_class_scoped_import( # The redefinition checks in `add_symbol_table_node` don't work for our # constructed Var / FuncBase, so check for possible redefinitions here. existing is not None - and isinstance(f(existing.node), (FuncBase, Var)) + and isinstance(f(existing.node), (Decorator, FuncBase, Var)) and ( isinstance(f(existing.type), f(AnyType)) or f(existing.type) == f(symbol_node).type @@ -4944,7 +4944,7 @@ def _get_node_for_class_scoped_import( return existing.node # Construct the new node - if isinstance(f(symbol_node), FuncBase): + if isinstance(f(symbol_node), (FuncBase, Decorator)): # In theory we could construct a new node here as well, but in practice # it doesn't work well, see #12197 typ: Optional[Type] = AnyType(TypeOfAny.from_error) diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index d74481a55cbbd..5c1e8dfa44f46 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -7284,3 +7284,19 @@ def meth1(self: Any, y: str) -> str: ... T = TypeVar("T") def meth2(self: Any, y: T) -> T: ... + +[case testClassScopeImportWithWrapperAndError] +class Foo: + from mod import foo # E: Unsupported class scoped import + +[file mod.py] +from typing import Any, Callable, TypeVar + +FuncT = TypeVar("FuncT", bound=Callable[..., Any]) +def identity_wrapper(func: FuncT) -> FuncT: + return func + +@identity_wrapper +def foo(self: Any) -> str: + return "" + From 4f07c79aea0fef61ab649d6acedf01186f1054eb Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Wed, 4 May 2022 18:23:25 +0200 Subject: [PATCH 277/377] Fix TypeError with enable-incomplete-features flag (#12726) --- mypy/main.py | 2 +- test-data/unit/cmdline.test | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/mypy/main.py b/mypy/main.py index f598194455c17..c735bb389a35a 100644 --- a/mypy/main.py +++ b/mypy/main.py @@ -869,7 +869,7 @@ def add_invertible_flag(flag: str, # Must be followed by another flag or by '--' (and then only file args may follow). parser.add_argument('--cache-map', nargs='+', dest='special-opts:cache_map', help=argparse.SUPPRESS) - parser.add_argument('--enable-incomplete-features', default=False, + parser.add_argument('--enable-incomplete-features', action='store_true', help=argparse.SUPPRESS) # options specifying code to check diff --git a/test-data/unit/cmdline.test b/test-data/unit/cmdline.test index 66dfd4edff2ec..a1b4d986b98af 100644 --- a/test-data/unit/cmdline.test +++ b/test-data/unit/cmdline.test @@ -1394,3 +1394,8 @@ class C: pass b \d+ b\.c \d+ .* + +[case testCmdlineEnableIncompleteFeatures] +# cmd: mypy --enable-incomplete-features a.py +[file a.py] +pass From 269adee09330f6f1836b0ae13e20450c9f708c2a Mon Sep 17 00:00:00 2001 From: frerikandriessen <85996204+frerikandriessen@users.noreply.github.com> Date: Sat, 7 May 2022 20:57:59 +0200 Subject: [PATCH 278/377] Add more precise error message for Callable annotation (#12518) Adds a more precise error message for a Callable annotation, if the option --disallow-any-generics (part of --strict mode) has been used. The suggestion in the old message was incorrect in this scenario. Fixes #11757 --- mypy/typeanal.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mypy/typeanal.py b/mypy/typeanal.py index d734a1cc330f4..98e37bd0aa400 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -950,7 +950,10 @@ def analyze_callable_type(self, t: UnboundType) -> Type: return AnyType(TypeOfAny.from_error) ret = maybe_ret else: - self.fail('Please use "Callable[[], ]" or "Callable"', t) + if self.options.disallow_any_generics: + self.fail('Please use "Callable[[], ]"', t) + else: + self.fail('Please use "Callable[[], ]" or "Callable"', t) return AnyType(TypeOfAny.from_error) assert isinstance(ret, CallableType) return ret.accept(self) From 91e890fe308e7b9c8ab969a4831a4ff13fbc0aa3 Mon Sep 17 00:00:00 2001 From: Michael Lee Date: Sat, 7 May 2022 15:32:10 -0700 Subject: [PATCH 279/377] Add info about classes and types to 'getting started' docs (#6557) Co-authored-by: 97littleleaf11 <97littleleaf11@users.noreply.github.com> Co-authored-by: Jingchen Ye <11172084+97littleleaf11@users.noreply.github.com> Co-authored-by: AlexWaygood --- docs/source/class_basics.rst | 2 + docs/source/getting_started.rst | 136 +++++++++++++++++++++++------ docs/source/installed_packages.rst | 9 ++ docs/source/running_mypy.rst | 2 +- 4 files changed, 121 insertions(+), 28 deletions(-) diff --git a/docs/source/class_basics.rst b/docs/source/class_basics.rst index a7f57afee4e73..48734a514adad 100644 --- a/docs/source/class_basics.rst +++ b/docs/source/class_basics.rst @@ -1,3 +1,5 @@ +.. _class-basics: + Class basics ============ diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst index ee102ad8b6398..6d92ce30d7237 100644 --- a/docs/source/getting_started.rst +++ b/docs/source/getting_started.rst @@ -4,7 +4,7 @@ Getting started =============== This chapter introduces some core concepts of mypy, including function -annotations, the :py:mod:`typing` module, library stubs, and more. +annotations, the :py:mod:`typing` module, stub files, and more. Be sure to read this chapter carefully, as the rest of the documentation may not make much sense otherwise. @@ -317,28 +317,119 @@ syntax like so: # If you're using Python 3.6+ my_global_dict: Dict[int, float] = {} -.. _stubs-intro: -Library stubs and typeshed -************************** +Types and classes +***************** + +So far, we've only seen examples of pre-existing types like the ``int`` +or ``float`` builtins, or generic types from ``collections.abc`` and +``typing``, such as ``Iterable``. However, these aren't the only types you can +use: in fact, you can use any Python class as a type! + +For example, suppose you've defined a custom class representing a bank account: + +.. code-block:: python + + class BankAccount: + # Note: It is ok to omit type hints for the "self" parameter. + # Mypy will infer the correct type. + + def __init__(self, account_name: str, initial_balance: int = 0) -> None: + # Note: Mypy will infer the correct types of your fields + # based on the types of the parameters. + self.account_name = account_name + self.balance = initial_balance + + def deposit(self, amount: int) -> None: + self.balance += amount + + def withdraw(self, amount: int) -> None: + self.balance -= amount + + def overdrawn(self) -> bool: + return self.balance < 0 + +You can declare that a function will accept any instance of your class +by simply annotating the parameters with ``BankAccount``: + +.. code-block:: python + + def transfer(src: BankAccount, dst: BankAccount, amount: int) -> None: + src.withdraw(amount) + dst.deposit(amount) + + account_1 = BankAccount('Alice', 400) + account_2 = BankAccount('Bob', 200) + transfer(account_1, account_2, 50) + +In fact, the ``transfer`` function we wrote above can accept more then just +instances of ``BankAccount``: it can also accept any instance of a *subclass* +of ``BankAccount``. For example, suppose you write a new class that looks like this: + +.. code-block:: python + + class AuditedBankAccount(BankAccount): + def __init__(self, account_name: str, initial_balance: int = 0) -> None: + super().__init__(account_name, initial_balance) + self.audit_log: list[str] = [] -Mypy uses library *stubs* to type check code interacting with library -modules, including the Python standard library. A library stub defines -a skeleton of the public interface of the library, including classes, -variables and functions, and their types. Mypy ships with stubs for -the standard library from the `typeshed -`_ project, which contains library -stubs for the Python builtins, the standard library, and selected -third-party packages. + def deposit(self, amount: int) -> None: + self.audit_log.append(f"Deposited {amount}") + self.balance += amount -For example, consider this code: + def withdraw(self, amount: int) -> None: + self.audit_log.append(f"Withdrew {amount}") + self.balance -= amount + +Since ``AuditedBankAccount`` is a subclass of ``BankAccount``, we can directly pass +in instances of it into our ``transfer`` function: .. code-block:: python - x = chr(4) + audited = AuditedBankAccount('Charlie', 300) + transfer(account_1, audited, 100) # Type checks! + +This behavior is actually a fundamental aspect of the PEP 484 type system: when +we annotate some variable with a type ``T``, we are actually telling mypy that +variable can be assigned an instance of ``T``, or an instance of a *subclass* of ``T``. +The same rule applies to type hints on parameters or fields. + +See :ref:`class-basics` to learn more about how to work with code involving classes. + + +.. _stubs-intro: + +Stubs files and typeshed +************************ -Without a library stub, mypy would have no way of inferring the type of ``x`` -and checking that the argument to :py:func:`chr` has a valid type. +Mypy also understands how to work with classes found in the standard library. +For example, here is a function which uses the ``Path`` object from the +`pathlib standard library module `_: + +.. code-block:: python + + from pathlib import Path + + def load_template(template_path: Path, name: str) -> str: + # Mypy understands that 'file_path.read_text()' returns a str... + template = template_path.read_text() + + # ...so understands this line type checks. + return template.replace('USERNAME', name) + +This behavior may surprise you if you're familiar with how +Python internally works. The standard library does not use type hints +anywhere, so how did mypy know that ``Path.read_text()`` returns a ``str``, +or that ``str.replace(...)`` accepts exactly two ``str`` arguments? + +The answer is that mypy comes bundled with *stub files* from the +the `typeshed `_ project, which +contains stub files for the Python builtins, the standard library, +and selected third-party packages. + +A *stub file* is a file containing a skeleton of the public interface +of that Python module, including classes, variables, functions -- and +most importantly, their types. Mypy complains if it can't find a stub (or a real module) for a library module that you import. Some modules ship with stubs or inline @@ -349,7 +440,7 @@ the stubs for the ``requests`` package like this: .. code-block:: shell - python3 -m pip install types-requests + $ python3 -m pip install types-requests The stubs are usually packaged in a distribution named ``types-``. Note that the distribution name may be @@ -363,17 +454,8 @@ often suggest the name of the stub distribution: prog.py:1: note: Hint: "python3 -m pip install types-PyYAML" ... -.. note:: - - Starting in mypy 0.900, most third-party package stubs must be - installed explicitly. This decouples mypy and stub versioning, - allowing stubs to updated without updating mypy. This also allows - stubs not originally included with mypy to be installed. Earlier - mypy versions included a fixed set of stubs for third-party - packages. - You can also :ref:`create -stubs ` easily. We discuss ways of silencing complaints +stubs ` easily. We discuss strategies for handling errors about missing stubs in :ref:`ignore-missing-imports`. Configuring mypy diff --git a/docs/source/installed_packages.rst b/docs/source/installed_packages.rst index 8e5bff04ea72c..73e808bb9be49 100644 --- a/docs/source/installed_packages.rst +++ b/docs/source/installed_packages.rst @@ -33,6 +33,15 @@ you can create such packages. example), it is recommended that you also pin the versions of all your stub package dependencies. +.. note:: + + Starting in mypy 0.900, most third-party package stubs must be + installed explicitly. This decouples mypy and stub versioning, + allowing stubs to updated without updating mypy. This also allows + stubs not originally included with mypy to be installed. Earlier + mypy versions included a fixed set of stubs for third-party + packages. + Using installed packages with mypy (PEP 561) ******************************************** diff --git a/docs/source/running_mypy.rst b/docs/source/running_mypy.rst index 070e4556c04e6..46ad2c65c386a 100644 --- a/docs/source/running_mypy.rst +++ b/docs/source/running_mypy.rst @@ -322,7 +322,7 @@ this error, try: In some rare cases, you may get the "Cannot find implementation or library stub for module" error even when the module is installed in your system. This can happen when the module is both missing type hints and is installed -on your system in a unconventional way. +on your system in an unconventional way. In this case, follow the steps above on how to handle :ref:`missing type hints in third party libraries `. From 23e2a51e05ce38aa765fe67ab1507836227b301b Mon Sep 17 00:00:00 2001 From: Danny Weinberg Date: Sat, 7 May 2022 16:10:26 -0700 Subject: [PATCH 280/377] Add a class attribute hook to the plugin system (#9881) This adds a get_class_attribute_hook to plugins to modify attributes on classes (as opposed to the existing get_attribute_hook, which is for attributes on instances). Fixes #9645 --- docs/source/extending_mypy.rst | 4 + mypy/checkmember.py | 28 +++++-- mypy/plugin.py | 29 +++++++- test-data/unit/check-custom-plugin.test | 89 +++++++++++++++++++++++ test-data/unit/plugins/class_attr_hook.py | 20 +++++ 5 files changed, 161 insertions(+), 9 deletions(-) create mode 100644 test-data/unit/plugins/class_attr_hook.py diff --git a/docs/source/extending_mypy.rst b/docs/source/extending_mypy.rst index 5c59bef506cc3..00c328be7728b 100644 --- a/docs/source/extending_mypy.rst +++ b/docs/source/extending_mypy.rst @@ -198,6 +198,10 @@ fields which already exist on the class. *Exception:* if :py:meth:`__getattr__ < :py:meth:`__getattribute__ ` is a method on the class, the hook is called for all fields which do not refer to methods. +**get_class_attribute_hook()** is similar to above, but for attributes on classes rather than instances. +Unlike above, this does not have special casing for :py:meth:`__getattr__ ` or +:py:meth:`__getattribute__ `. + **get_class_decorator_hook()** can be used to update class definition for given class decorators. For example, you can add some attributes to the class to match runtime behaviour: diff --git a/mypy/checkmember.py b/mypy/checkmember.py index 29d2728c2174f..964ab301d171d 100644 --- a/mypy/checkmember.py +++ b/mypy/checkmember.py @@ -704,10 +704,13 @@ def analyze_class_attribute_access(itype: Instance, if override_info: info = override_info + fullname = '{}.{}'.format(info.fullname, name) + hook = mx.chk.plugin.get_class_attribute_hook(fullname) + node = info.get(name) if not node: if info.fallback_to_any: - return AnyType(TypeOfAny.special_form) + return apply_class_attr_hook(mx, hook, AnyType(TypeOfAny.special_form)) return None is_decorated = isinstance(node.node, Decorator) @@ -732,14 +735,16 @@ def analyze_class_attribute_access(itype: Instance, if info.is_enum and not (mx.is_lvalue or is_decorated or is_method): enum_class_attribute_type = analyze_enum_class_attribute_access(itype, name, mx) if enum_class_attribute_type: - return enum_class_attribute_type + return apply_class_attr_hook(mx, hook, enum_class_attribute_type) t = node.type if t: if isinstance(t, PartialType): symnode = node.node assert isinstance(symnode, Var) - return mx.chk.handle_partial_var_type(t, mx.is_lvalue, symnode, mx.context) + return apply_class_attr_hook(mx, hook, + mx.chk.handle_partial_var_type(t, mx.is_lvalue, symnode, + mx.context)) # Find the class where method/variable was defined. if isinstance(node.node, Decorator): @@ -790,7 +795,8 @@ def analyze_class_attribute_access(itype: Instance, mx.self_type, original_vars=original_vars) if not mx.is_lvalue: result = analyze_descriptor_access(result, mx) - return result + + return apply_class_attr_hook(mx, hook, result) elif isinstance(node.node, Var): mx.not_ready_callback(name, mx.context) return AnyType(TypeOfAny.special_form) @@ -814,7 +820,7 @@ def analyze_class_attribute_access(itype: Instance, if is_decorated: assert isinstance(node.node, Decorator) if node.node.type: - return node.node.type + return apply_class_attr_hook(mx, hook, node.node.type) else: mx.not_ready_callback(name, mx.context) return AnyType(TypeOfAny.from_error) @@ -826,7 +832,17 @@ def analyze_class_attribute_access(itype: Instance, # unannotated implicit class methods we do this here. if node.node.is_class: typ = bind_self(typ, is_classmethod=True) - return typ + return apply_class_attr_hook(mx, hook, typ) + + +def apply_class_attr_hook(mx: MemberContext, + hook: Optional[Callable[[AttributeContext], Type]], + result: Type, + ) -> Optional[Type]: + if hook: + result = hook(AttributeContext(get_proper_type(mx.original_type), + result, mx.context, mx.chk)) + return result def analyze_enum_class_attribute_access(itype: Instance, diff --git a/mypy/plugin.py b/mypy/plugin.py index 74a62d6510d29..72d28c39436a6 100644 --- a/mypy/plugin.py +++ b/mypy/plugin.py @@ -637,10 +637,10 @@ def get_method_hook(self, fullname: str def get_attribute_hook(self, fullname: str ) -> Optional[Callable[[AttributeContext], Type]]: - """Adjust type of a class attribute. + """Adjust type of an instance attribute. - This method is called with attribute full name using the class where the attribute was - defined (or Var.info.fullname for generated attributes). + This method is called with attribute full name using the class of the instance where + the attribute was defined (or Var.info.fullname for generated attributes). For classes without __getattr__ or __getattribute__, this hook is only called for names of fields/properties (but not methods) that exist in the instance MRO. @@ -667,6 +667,25 @@ class Derived(Base): """ return None + def get_class_attribute_hook(self, fullname: str + ) -> Optional[Callable[[AttributeContext], Type]]: + """ + Adjust type of a class attribute. + + This method is called with attribute full name using the class where the attribute was + defined (or Var.info.fullname for generated attributes). + + For example: + + class Cls: + x: Any + + Cls.x + + get_class_attribute_hook is called with '__main__.Cls.x' as fullname. + """ + return None + def get_class_decorator_hook(self, fullname: str ) -> Optional[Callable[[ClassDefContext], None]]: """Update class definition for given class decorators. @@ -788,6 +807,10 @@ def get_attribute_hook(self, fullname: str ) -> Optional[Callable[[AttributeContext], Type]]: return self._find_hook(lambda plugin: plugin.get_attribute_hook(fullname)) + def get_class_attribute_hook(self, fullname: str + ) -> Optional[Callable[[AttributeContext], Type]]: + return self._find_hook(lambda plugin: plugin.get_class_attribute_hook(fullname)) + def get_class_decorator_hook(self, fullname: str ) -> Optional[Callable[[ClassDefContext], None]]: return self._find_hook(lambda plugin: plugin.get_class_decorator_hook(fullname)) diff --git a/test-data/unit/check-custom-plugin.test b/test-data/unit/check-custom-plugin.test index b5bf0a67eb915..ee19113f000f9 100644 --- a/test-data/unit/check-custom-plugin.test +++ b/test-data/unit/check-custom-plugin.test @@ -902,3 +902,92 @@ reveal_type(f()) # N: Revealed type is "builtins.str" [file mypy.ini] \[mypy] plugins=/test-data/unit/plugins/method_in_decorator.py + +[case testClassAttrPluginClassVar] +# flags: --config-file tmp/mypy.ini + +from typing import Type + +class Cls: + attr = 'test' + unchanged = 'test' + +reveal_type(Cls().attr) # N: Revealed type is "builtins.str" +reveal_type(Cls.attr) # N: Revealed type is "builtins.int" +reveal_type(Cls.unchanged) # N: Revealed type is "builtins.str" +x: Type[Cls] +reveal_type(x.attr) # N: Revealed type is "builtins.int" +[file mypy.ini] +\[mypy] +plugins=/test-data/unit/plugins/class_attr_hook.py + +[case testClassAttrPluginMethod] +# flags: --config-file tmp/mypy.ini + +class Cls: + def attr(self) -> None: + pass + +reveal_type(Cls.attr) # N: Revealed type is "builtins.int" +[file mypy.ini] +\[mypy] +plugins=/test-data/unit/plugins/class_attr_hook.py + +[case testClassAttrPluginEnum] +# flags: --config-file tmp/mypy.ini + +import enum + +class Cls(enum.Enum): + attr = 'test' + +reveal_type(Cls.attr) # N: Revealed type is "builtins.int" +[file mypy.ini] +\[mypy] +plugins=/test-data/unit/plugins/class_attr_hook.py + +[case testClassAttrPluginMetaclassAnyBase] +# flags: --config-file tmp/mypy.ini + +from typing import Any, Type +class M(type): + attr = 'test' + +B: Any +class Cls(B, metaclass=M): + pass + +reveal_type(Cls.attr) # N: Revealed type is "builtins.int" +[file mypy.ini] +\[mypy] +plugins=/test-data/unit/plugins/class_attr_hook.py + +[case testClassAttrPluginMetaclassRegularBase] +# flags: --config-file tmp/mypy.ini + +from typing import Any, Type +class M(type): + attr = 'test' + +class B: + attr = None + +class Cls(B, metaclass=M): + pass + +reveal_type(Cls.attr) # N: Revealed type is "builtins.int" +[file mypy.ini] +\[mypy] +plugins=/test-data/unit/plugins/class_attr_hook.py + +[case testClassAttrPluginPartialType] +# flags: --config-file tmp/mypy.ini + +class Cls: + attr = None + def f(self) -> int: + return Cls.attr + 1 + +[file mypy.ini] +\[mypy] +plugins=/test-data/unit/plugins/class_attr_hook.py diff --git a/test-data/unit/plugins/class_attr_hook.py b/test-data/unit/plugins/class_attr_hook.py new file mode 100644 index 0000000000000..348e5df0ee035 --- /dev/null +++ b/test-data/unit/plugins/class_attr_hook.py @@ -0,0 +1,20 @@ +from typing import Callable, Optional + +from mypy.plugin import AttributeContext, Plugin +from mypy.types import Type as MypyType + + +class ClassAttrPlugin(Plugin): + def get_class_attribute_hook(self, fullname: str + ) -> Optional[Callable[[AttributeContext], MypyType]]: + if fullname == '__main__.Cls.attr': + return my_hook + return None + + +def my_hook(ctx: AttributeContext) -> MypyType: + return ctx.api.named_generic_type('builtins.int', []) + + +def plugin(_version: str): + return ClassAttrPlugin From 49d5cc907c391b4bcf52f9966f008f80badf12ab Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Sun, 8 May 2022 02:01:14 +0100 Subject: [PATCH 281/377] Ensure instances of `CallableType` can always be hashed (#12741) --- mypy/types.py | 9 +++++++-- test-data/unit/check-typeddict.test | 11 +++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/mypy/types.py b/mypy/types.py index 8f45e87b8fb9e..afe1a88e06b17 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -14,7 +14,7 @@ import mypy.nodes from mypy.state import state from mypy.nodes import ( - INVARIANT, SymbolNode, FuncDef, + INVARIANT, SymbolNode, FuncDef, FakeInfo, ArgKind, ARG_POS, ARG_STAR, ARG_STAR2, ) from mypy.util import IdMapper @@ -1766,7 +1766,12 @@ def expand_param_spec(self, variables=[*variables, *self.variables]) def __hash__(self) -> int: - return hash((self.ret_type, self.is_type_obj(), + # self.is_type_obj() will fail if self.fallback.type is a FakeInfo + if isinstance(self.fallback.type, FakeInfo): + is_type_obj = 2 + else: + is_type_obj = self.is_type_obj() + return hash((self.ret_type, is_type_obj, self.is_ellipsis_args, self.name, tuple(self.arg_types), tuple(self.arg_names), tuple(self.arg_kinds))) diff --git a/test-data/unit/check-typeddict.test b/test-data/unit/check-typeddict.test index 297e2df78a9b4..1ca9ec593d11f 100644 --- a/test-data/unit/check-typeddict.test +++ b/test-data/unit/check-typeddict.test @@ -221,6 +221,17 @@ reveal_type(d) # N: Revealed type is "TypedDict('__main__.D', {'y': builtins.in [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] +[case testTypedDictWithClassmethodAlternativeConstructorDoesNotCrash] +# https://github.com/python/mypy/issues/5653 +from typing import TypedDict + +class Foo(TypedDict): + bar: str + @classmethod # E: Invalid statement in TypedDict definition; expected "field_name: field_type" + def baz(cls) -> "Foo": ... +[builtins fixtures/dict.pyi] +[typing fixtures/typing-typeddict.pyi] + [case testCanCreateTypedDictTypeWithUnderscoreItemName] from mypy_extensions import TypedDict Point = TypedDict('Point', {'x': int, 'y': int, '_fallback': object}) From fb11c98e3aa8931104ac9f4618c1342c045d999c Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Sun, 8 May 2022 05:55:39 +0300 Subject: [PATCH 282/377] Fixes generic inference in functions with `TypeGuard` (#11797) Fixes #11780, fixes #11428 --- mypy/applytype.py | 7 ++++ mypy/checkexpr.py | 22 +++++++------ test-data/unit/check-typeguard.test | 50 +++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 9 deletions(-) diff --git a/mypy/applytype.py b/mypy/applytype.py index 51a10c7084cfe..b32b88fa32763 100644 --- a/mypy/applytype.py +++ b/mypy/applytype.py @@ -103,6 +103,12 @@ def apply_generic_arguments( # Apply arguments to argument types. arg_types = [expand_type(at, id_to_type) for at in callable.arg_types] + # Apply arguments to TypeGuard if any. + if callable.type_guard is not None: + type_guard = expand_type(callable.type_guard, id_to_type) + else: + type_guard = None + # The callable may retain some type vars if only some were applied. remaining_tvars = [tv for tv in tvars if tv.id not in id_to_type] @@ -110,4 +116,5 @@ def apply_generic_arguments( arg_types=arg_types, ret_type=expand_type(callable.ret_type, id_to_type), variables=remaining_tvars, + type_guard=type_guard, ) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 9dfc0e2a64587..21fd7d81967f5 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -344,11 +344,6 @@ def visit_call_expr_inner(self, e: CallExpr, allow_none_return: bool = False) -> ret_type=self.object_type(), fallback=self.named_type('builtins.function')) callee_type = get_proper_type(self.accept(e.callee, type_context, always_allow_any=True)) - if (isinstance(e.callee, RefExpr) - and isinstance(callee_type, CallableType) - and callee_type.type_guard is not None): - # Cache it for find_isinstance_check() - e.callee.type_guard = callee_type.type_guard if (self.chk.options.disallow_untyped_calls and self.chk.in_checked_function() and isinstance(callee_type, CallableType) @@ -886,10 +881,19 @@ def check_call_expr_with_callee_type(self, # Unions are special-cased to allow plugins to act on each item in the union. elif member is not None and isinstance(object_type, UnionType): return self.check_union_call_expr(e, object_type, member) - return self.check_call(callee_type, e.args, e.arg_kinds, e, - e.arg_names, callable_node=e.callee, - callable_name=callable_name, - object_type=object_type)[0] + ret_type, callee_type = self.check_call( + callee_type, e.args, e.arg_kinds, e, + e.arg_names, callable_node=e.callee, + callable_name=callable_name, + object_type=object_type, + ) + proper_callee = get_proper_type(callee_type) + if (isinstance(e.callee, RefExpr) + and isinstance(proper_callee, CallableType) + and proper_callee.type_guard is not None): + # Cache it for find_isinstance_check() + e.callee.type_guard = proper_callee.type_guard + return ret_type def check_union_call_expr(self, e: CallExpr, object_type: UnionType, member: str) -> Type: """"Type check calling a member expression where the base type is a union.""" diff --git a/test-data/unit/check-typeguard.test b/test-data/unit/check-typeguard.test index ecefce0914055..64fc7ea695cb3 100644 --- a/test-data/unit/check-typeguard.test +++ b/test-data/unit/check-typeguard.test @@ -547,3 +547,53 @@ accepts_typeguard(with_typeguard_a) # E: Argument 1 to "accepts_typeguard" has accepts_typeguard(with_typeguard_b) accepts_typeguard(with_typeguard_c) [builtins fixtures/tuple.pyi] + +[case testTypeGuardWithIdentityGeneric] +from typing import TypeVar +from typing_extensions import TypeGuard + +_T = TypeVar("_T") + +def identity(val: _T) -> TypeGuard[_T]: + pass + +def func1(name: _T): + reveal_type(name) # N: Revealed type is "_T`-1" + if identity(name): + reveal_type(name) # N: Revealed type is "_T`-1" + +def func2(name: str): + reveal_type(name) # N: Revealed type is "builtins.str" + if identity(name): + reveal_type(name) # N: Revealed type is "builtins.str" +[builtins fixtures/tuple.pyi] + +[case testTypeGuardWithGenericInstance] +from typing import TypeVar, List +from typing_extensions import TypeGuard + +_T = TypeVar("_T") + +def is_list_of_str(val: _T) -> TypeGuard[List[_T]]: + pass + +def func(name: str): + reveal_type(name) # N: Revealed type is "builtins.str" + if is_list_of_str(name): + reveal_type(name) # N: Revealed type is "builtins.list[builtins.str]" +[builtins fixtures/tuple.pyi] + +[case testTypeGuardWithTupleGeneric] +from typing import TypeVar, Tuple +from typing_extensions import TypeGuard + +_T = TypeVar("_T") + +def is_two_element_tuple(val: Tuple[_T, ...]) -> TypeGuard[Tuple[_T, _T]]: + pass + +def func(names: Tuple[str, ...]): + reveal_type(names) # N: Revealed type is "builtins.tuple[builtins.str, ...]" + if is_two_element_tuple(names): + reveal_type(names) # N: Revealed type is "Tuple[builtins.str, builtins.str]" +[builtins fixtures/tuple.pyi] From f28bf11496b14e5b6a4610438b4a6582fbd0d3c1 Mon Sep 17 00:00:00 2001 From: Tomoki Nakagawa <33854773+nakatomotoi@users.noreply.github.com> Date: Mon, 9 May 2022 08:19:05 +0900 Subject: [PATCH 283/377] Add error when making abstractmethod final (#12743) Fixes #12164 --- mypy/semanal.py | 2 ++ test-data/unit/check-final.test | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/mypy/semanal.py b/mypy/semanal.py index 62ec1c823ec2b..555cb749074e9 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -1103,6 +1103,8 @@ def visit_decorator(self, dec: Decorator) -> None: dec.func.accept(self) if dec.decorators and dec.var.is_property: self.fail('Decorated property not supported', dec) + if dec.func.is_abstract and dec.func.is_final: + self.fail(f"Method {dec.func.name} is both abstract and final", dec) def check_decorated_function_is_method(self, decorator: str, context: Context) -> None: diff --git a/test-data/unit/check-final.test b/test-data/unit/check-final.test index a955d021647d7..2f298ad1be3bf 100644 --- a/test-data/unit/check-final.test +++ b/test-data/unit/check-final.test @@ -1091,3 +1091,21 @@ class A: b: ClassVar[Final[int]] # E: Final can be only used as an outermost qualifier in a variable annotation c: ClassVar[Final] = 1 # E: Final can be only used as an outermost qualifier in a variable annotation [out] + +[case testFinalClassWithAbstractMethod] +from typing import final +from abc import ABC, abstractmethod + +@final +class A(ABC): # E: Final class __main__.A has abstract attributes "B" + @abstractmethod + def B(self) -> None: ... + +[case testFinalDefiningFuncWithAbstractMethod] +from typing import final +from abc import ABC, abstractmethod + +class A(ABC): + @final # E: Method B is both abstract and final + @abstractmethod + def B(self) -> None: ... From 612074f05ba5d65e016c031dc94b13f962d9c6b4 Mon Sep 17 00:00:00 2001 From: 97littleleaf11 <11172084+97littleleaf11@users.noreply.github.com> Date: Mon, 9 May 2022 07:27:53 +0800 Subject: [PATCH 284/377] Add documentation for -xfail tests (#12750) --- test-data/unit/README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test-data/unit/README.md b/test-data/unit/README.md index 06a5b77ef7691..080e8770d9f74 100644 --- a/test-data/unit/README.md +++ b/test-data/unit/README.md @@ -34,16 +34,18 @@ with text "abc..." - use `\` to escape the `#` character and indicate that the rest of the line is part of the error message - repeating `# E: ` several times in one line indicates multiple expected errors in one line -- `W: ...` and `N: ...` works exactly like `E:`, but report a warning and a note respectively +- `W: ...` and `N: ...` works exactly like `E: ...`, but report a warning and a note respectively - lines that don't contain the above should cause no type check errors - optional `[builtins fixtures/...]` tells the type checker to use stubs from the indicated file (see Fixtures section below) -- optional `[out]` is an alternative to the "# E:" notation: it indicates that +- optional `[out]` is an alternative to the `# E: ` notation: it indicates that any text after it contains the expected type checking error messages. -Usually, "E: " is preferred because it makes it easier to associate the +Usually, `# E: ` is preferred because it makes it easier to associate the errors with the code generating them at a glance, and to change the code of the test without having to change line numbers in `[out]` - an empty `[out]` section has no effect +- to add tests for a feature that hasn't been implemented yet, append `-xfail` + to the end of the test name - to run just this test, use `pytest -n0 -k testNewSyntaxBasics` From e1c03ab0f37495ef4072892778ab126d04860814 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0t=C4=9Bp=C3=A1n=20Hor=C3=A1=C4=8Dek?= <4643182+shoracek@users.noreply.github.com> Date: Mon, 9 May 2022 16:58:57 +0200 Subject: [PATCH 285/377] Make ValuePattern non-exhaustive (#12751) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes behaviour of PatternChecker so that ValuePattern does not cover the entire (non-literal) type since it can catch only a single value. Fixes: #12545 Signed-off-by: Štěpán Horáček --- mypy/checkpattern.py | 4 +++- test-data/unit/check-python310.test | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/mypy/checkpattern.py b/mypy/checkpattern.py index 6a8a0196306c0..978b03b342f59 100644 --- a/mypy/checkpattern.py +++ b/mypy/checkpattern.py @@ -23,7 +23,7 @@ from mypy.typeops import try_getting_str_literals_from_type, make_simplified_union, \ coerce_to_literal from mypy.types import ( - ProperType, AnyType, TypeOfAny, Instance, Type, UninhabitedType, get_proper_type, + LiteralType, ProperType, AnyType, TypeOfAny, Instance, Type, UninhabitedType, get_proper_type, TypedDictType, TupleType, NoneType, UnionType ) from mypy.typevars import fill_typevars @@ -183,6 +183,8 @@ def visit_value_pattern(self, o: ValuePattern) -> PatternType: o, default=current_type ) + if not isinstance(get_proper_type(narrowed_type), (LiteralType, UninhabitedType)): + return PatternType(narrowed_type, UnionType.make_union([narrowed_type, rest_type]), {}) return PatternType(narrowed_type, rest_type, {}) def visit_singleton_pattern(self, o: SingletonPattern) -> PatternType: diff --git a/test-data/unit/check-python310.test b/test-data/unit/check-python310.test index cb39a519a1467..818981238b3bf 100644 --- a/test-data/unit/check-python310.test +++ b/test-data/unit/check-python310.test @@ -1576,3 +1576,18 @@ def f(x: AST) -> None: reveal_type(b) # N: Revealed type is "builtins.int" reveal_type(c) # N: Revealed type is "builtins.str" [builtins fixtures/tuple.pyi] + +[case testMatchReachableDottedNames] +# flags: --warn-unreachable +class Consts: + BLANK = "" + SPECIAL = "asdf" + +def test_func(test_str: str) -> str: + match test_str: + case Consts.BLANK: + return "blank" + case Consts.SPECIAL: + return "special" + case _: + return "other" From 03901ef657daf6f477e6fe933c42ac270cf5034b Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Wed, 11 May 2022 13:38:34 +0100 Subject: [PATCH 286/377] Running dataclass transform in a later pass to fix crashes (#12762) The dataclass plugin could crash if it encountered a placeholder. Fix the issue by running the plugin after the main semantic analysis pass, when all placeholders have been resolved. Also add a new hook called get_class_decorator_hook_2 that is used by the dataclass plugin. We may want to do a similar change to the attrs plugin, but let's change one thing at a time. Fix #12685. --- mypy/plugin.py | 32 ++++++++++++- mypy/plugins/dataclasses.py | 47 +++++++++++++----- mypy/plugins/default.py | 11 ++++- mypy/semanal.py | 37 ++++++++------- mypy/semanal_main.py | 59 +++++++++++++++++++++-- test-data/unit/check-dataclasses.test | 68 ++++++++++++++++++++++++++- 6 files changed, 217 insertions(+), 37 deletions(-) diff --git a/mypy/plugin.py b/mypy/plugin.py index 72d28c39436a6..2f571d7eecc6d 100644 --- a/mypy/plugin.py +++ b/mypy/plugin.py @@ -692,9 +692,33 @@ def get_class_decorator_hook(self, fullname: str The plugin can modify a TypeInfo _in place_ (for example add some generated methods to the symbol table). This hook is called after the class body was - semantically analyzed. + semantically analyzed, but *there may still be placeholders* (typically + caused by forward references). - The hook is called with full names of all class decorators, for example + NOTE: Usually get_class_decorator_hook_2 is the better option, since it + guarantees that there are no placeholders. + + The hook is called with full names of all class decorators. + + The hook can be called multiple times per class, so it must be + idempotent. + """ + return None + + def get_class_decorator_hook_2(self, fullname: str + ) -> Optional[Callable[[ClassDefContext], bool]]: + """Update class definition for given class decorators. + + Similar to get_class_decorator_hook, but this runs in a later pass when + placeholders have been resolved. + + The hook can return False if some base class hasn't been + processed yet using class hooks. It causes all class hooks + (that are run in this same pass) to be invoked another time for + the file(s) currently being processed. + + The hook can be called multiple times per class, so it must be + idempotent. """ return None @@ -815,6 +839,10 @@ def get_class_decorator_hook(self, fullname: str ) -> Optional[Callable[[ClassDefContext], None]]: return self._find_hook(lambda plugin: plugin.get_class_decorator_hook(fullname)) + def get_class_decorator_hook_2(self, fullname: str + ) -> Optional[Callable[[ClassDefContext], bool]]: + return self._find_hook(lambda plugin: plugin.get_class_decorator_hook_2(fullname)) + def get_metaclass_hook(self, fullname: str ) -> Optional[Callable[[ClassDefContext], None]]: return self._find_hook(lambda plugin: plugin.get_metaclass_hook(fullname)) diff --git a/mypy/plugins/dataclasses.py b/mypy/plugins/dataclasses.py index 62b4c89bd674b..24077bb4a5490 100644 --- a/mypy/plugins/dataclasses.py +++ b/mypy/plugins/dataclasses.py @@ -107,10 +107,19 @@ def expand_typevar_from_subtype(self, sub_type: TypeInfo) -> None: class DataclassTransformer: + """Implement the behavior of @dataclass. + + Note that this may be executed multiple times on the same class, so + everything here must be idempotent. + + This runs after the main semantic analysis pass, so you can assume that + there are no placeholders. + """ + def __init__(self, ctx: ClassDefContext) -> None: self._ctx = ctx - def transform(self) -> None: + def transform(self) -> bool: """Apply all the necessary transformations to the underlying dataclass so as to ensure it is fully type checked according to the rules in PEP 557. @@ -119,12 +128,11 @@ def transform(self) -> None: info = self._ctx.cls.info attributes = self.collect_attributes() if attributes is None: - # Some definitions are not ready, defer() should be already called. - return + # Some definitions are not ready. We need another pass. + return False for attr in attributes: if attr.type is None: - ctx.api.defer() - return + return False decorator_arguments = { 'init': _get_decorator_bool_argument(self._ctx, 'init', True), 'eq': _get_decorator_bool_argument(self._ctx, 'eq', True), @@ -236,6 +244,8 @@ def transform(self) -> None: 'frozen': decorator_arguments['frozen'], } + return True + def add_slots(self, info: TypeInfo, attributes: List[DataclassAttribute], @@ -294,6 +304,9 @@ def collect_attributes(self) -> Optional[List[DataclassAttribute]]: b: SomeOtherType = ... are collected. + + Return None if some dataclass base class hasn't been processed + yet and thus we'll need to ask for another pass. """ # First, collect attributes belonging to the current class. ctx = self._ctx @@ -315,14 +328,11 @@ def collect_attributes(self) -> Optional[List[DataclassAttribute]]: sym = cls.info.names.get(lhs.name) if sym is None: - # This name is likely blocked by a star import. We don't need to defer because - # defer() is already called by mark_incomplete(). + # There was probably a semantic analysis error. continue node = sym.node - if isinstance(node, PlaceholderNode): - # This node is not ready yet. - return None + assert not isinstance(node, PlaceholderNode) assert isinstance(node, Var) # x: ClassVar[int] is ignored by dataclasses. @@ -390,6 +400,9 @@ def collect_attributes(self) -> Optional[List[DataclassAttribute]]: # we'll have unmodified attrs laying around. all_attrs = attrs.copy() for info in cls.info.mro[1:-1]: + if 'dataclass_tag' in info.metadata and 'dataclass' not in info.metadata: + # We haven't processed the base class yet. Need another pass. + return None if 'dataclass' not in info.metadata: continue @@ -517,11 +530,21 @@ def _add_dataclass_fields_magic_attribute(self) -> None: ) -def dataclass_class_maker_callback(ctx: ClassDefContext) -> None: +def dataclass_tag_callback(ctx: ClassDefContext) -> None: + """Record that we have a dataclass in the main semantic analysis pass. + + The later pass implemented by DataclassTransformer will use this + to detect dataclasses in base classes. + """ + # The value is ignored, only the existence matters. + ctx.cls.info.metadata['dataclass_tag'] = {} + + +def dataclass_class_maker_callback(ctx: ClassDefContext) -> bool: """Hooks into the class typechecking process to add support for dataclasses. """ transformer = DataclassTransformer(ctx) - transformer.transform() + return transformer.transform() def _collect_field_args(expr: Expression, diff --git a/mypy/plugins/default.py b/mypy/plugins/default.py index a7fa2cfaa868f..50e0e8cb43151 100644 --- a/mypy/plugins/default.py +++ b/mypy/plugins/default.py @@ -117,12 +117,21 @@ def get_class_decorator_hook(self, fullname: str auto_attribs_default=None, ) elif fullname in dataclasses.dataclass_makers: - return dataclasses.dataclass_class_maker_callback + return dataclasses.dataclass_tag_callback elif fullname in functools.functools_total_ordering_makers: return functools.functools_total_ordering_maker_callback return None + def get_class_decorator_hook_2(self, fullname: str + ) -> Optional[Callable[[ClassDefContext], bool]]: + from mypy.plugins import dataclasses + + if fullname in dataclasses.dataclass_makers: + return dataclasses.dataclass_class_maker_callback + + return None + def contextmanager_callback(ctx: FunctionContext) -> Type: """Infer a better return type for 'contextlib.contextmanager'.""" diff --git a/mypy/semanal.py b/mypy/semanal.py index 555cb749074e9..d68928ef21ad4 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -1234,43 +1234,44 @@ def analyze_namedtuple_classdef(self, defn: ClassDef) -> bool: def apply_class_plugin_hooks(self, defn: ClassDef) -> None: """Apply a plugin hook that may infer a more precise definition for a class.""" - def get_fullname(expr: Expression) -> Optional[str]: - if isinstance(expr, CallExpr): - return get_fullname(expr.callee) - elif isinstance(expr, IndexExpr): - return get_fullname(expr.base) - elif isinstance(expr, RefExpr): - if expr.fullname: - return expr.fullname - # If we don't have a fullname look it up. This happens because base classes are - # analyzed in a different manner (see exprtotype.py) and therefore those AST - # nodes will not have full names. - sym = self.lookup_type_node(expr) - if sym: - return sym.fullname - return None for decorator in defn.decorators: - decorator_name = get_fullname(decorator) + decorator_name = self.get_fullname_for_hook(decorator) if decorator_name: hook = self.plugin.get_class_decorator_hook(decorator_name) if hook: hook(ClassDefContext(defn, decorator, self)) if defn.metaclass: - metaclass_name = get_fullname(defn.metaclass) + metaclass_name = self.get_fullname_for_hook(defn.metaclass) if metaclass_name: hook = self.plugin.get_metaclass_hook(metaclass_name) if hook: hook(ClassDefContext(defn, defn.metaclass, self)) for base_expr in defn.base_type_exprs: - base_name = get_fullname(base_expr) + base_name = self.get_fullname_for_hook(base_expr) if base_name: hook = self.plugin.get_base_class_hook(base_name) if hook: hook(ClassDefContext(defn, base_expr, self)) + def get_fullname_for_hook(self, expr: Expression) -> Optional[str]: + if isinstance(expr, CallExpr): + return self.get_fullname_for_hook(expr.callee) + elif isinstance(expr, IndexExpr): + return self.get_fullname_for_hook(expr.base) + elif isinstance(expr, RefExpr): + if expr.fullname: + return expr.fullname + # If we don't have a fullname look it up. This happens because base classes are + # analyzed in a different manner (see exprtotype.py) and therefore those AST + # nodes will not have full names. + sym = self.lookup_type_node(expr) + if sym: + return sym.fullname + return None + def analyze_class_keywords(self, defn: ClassDef) -> None: for value in defn.keywords.values(): value.accept(self) diff --git a/mypy/semanal_main.py b/mypy/semanal_main.py index 7a82032b46b7b..bb0af8edc46f6 100644 --- a/mypy/semanal_main.py +++ b/mypy/semanal_main.py @@ -45,6 +45,8 @@ from mypy.checker import FineGrainedDeferredNode from mypy.server.aststrip import SavedAttributes from mypy.util import is_typeshed_file +from mypy.options import Options +from mypy.plugin import ClassDefContext import mypy.build if TYPE_CHECKING: @@ -82,6 +84,8 @@ def semantic_analysis_for_scc(graph: 'Graph', scc: List[str], errors: Errors) -> apply_semantic_analyzer_patches(patches) # This pass might need fallbacks calculated above. check_type_arguments(graph, scc, errors) + # Run class decorator hooks (they requite complete MROs and no placeholders). + apply_class_plugin_hooks(graph, scc, errors) calculate_class_properties(graph, scc, errors) check_blockers(graph, scc) # Clean-up builtins, so that TypeVar etc. are not accessible without importing. @@ -132,6 +136,7 @@ def semantic_analysis_for_targets( check_type_arguments_in_targets(nodes, state, state.manager.errors) calculate_class_properties(graph, [state.id], state.manager.errors) + apply_class_plugin_hooks(graph, [state.id], state.manager.errors) def restore_saved_attrs(saved_attrs: SavedAttributes) -> None: @@ -382,14 +387,62 @@ def check_type_arguments_in_targets(targets: List[FineGrainedDeferredNode], stat target.node.accept(analyzer) +def apply_class_plugin_hooks(graph: 'Graph', scc: List[str], errors: Errors) -> None: + """Apply class plugin hooks within a SCC. + + We run these after to the main semantic analysis so that the hooks + don't need to deal with incomplete definitions such as placeholder + types. + + Note that some hooks incorrectly run during the main semantic + analysis pass, for historical reasons. + """ + num_passes = 0 + incomplete = True + # If we encounter a base class that has not been processed, we'll run another + # pass. This should eventually reach a fixed point. + while incomplete: + assert num_passes < 10, "Internal error: too many class plugin hook passes" + num_passes += 1 + incomplete = False + for module in scc: + state = graph[module] + tree = state.tree + assert tree + for _, node, _ in tree.local_definitions(): + if isinstance(node.node, TypeInfo): + if not apply_hooks_to_class(state.manager.semantic_analyzer, + module, node.node, state.options, tree, errors): + incomplete = True + + +def apply_hooks_to_class(self: SemanticAnalyzer, + module: str, + info: TypeInfo, + options: Options, + file_node: MypyFile, + errors: Errors) -> bool: + # TODO: Move more class-related hooks here? + defn = info.defn + ok = True + for decorator in defn.decorators: + with self.file_context(file_node, options, info): + decorator_name = self.get_fullname_for_hook(decorator) + if decorator_name: + hook = self.plugin.get_class_decorator_hook_2(decorator_name) + if hook: + ok = ok and hook(ClassDefContext(defn, decorator, self)) + return ok + + def calculate_class_properties(graph: 'Graph', scc: List[str], errors: Errors) -> None: for module in scc: - tree = graph[module].tree + state = graph[module] + tree = state.tree assert tree for _, node, _ in tree.local_definitions(): if isinstance(node.node, TypeInfo): - saved = (module, node.node, None) # module, class, function - with errors.scope.saved_scope(saved) if errors.scope else nullcontext(): + with state.manager.semantic_analyzer.file_context(tree, state.options, node.node): calculate_class_abstract_status(node.node, tree.is_stub, errors) check_protocol_status(node.node, errors) calculate_class_vars(node.node) diff --git a/test-data/unit/check-dataclasses.test b/test-data/unit/check-dataclasses.test index bce1ee24a31a4..4cddc59b01534 100644 --- a/test-data/unit/check-dataclasses.test +++ b/test-data/unit/check-dataclasses.test @@ -1207,7 +1207,7 @@ class A2: from dataclasses import dataclass @dataclass -class A: # E: Name "x" already defined (possibly by an import) +class A: x: int = 0 x: int = 0 # E: Name "x" already defined on line 7 @@ -1619,3 +1619,69 @@ Child(x='', y='') # E: Argument "y" to "Child" has incompatible type "str"; exp Child(x='', y=1) Child(x=None, y=None) [builtins fixtures/dataclasses.pyi] + +[case testDataclassGenericInheritanceSpecialCase1] +# flags: --python-version 3.7 +from dataclasses import dataclass +from typing import Generic, TypeVar, List + +T = TypeVar("T") + +@dataclass +class Parent(Generic[T]): + x: List[T] + +@dataclass +class Child1(Parent["Child2"]): ... + +@dataclass +class Child2(Parent["Child1"]): ... + +def f(c: Child2) -> None: + reveal_type(Child1([c]).x) # N: Revealed type is "builtins.list[__main__.Child2]" + +def g(c: Child1) -> None: + reveal_type(Child2([c]).x) # N: Revealed type is "builtins.list[__main__.Child1]" +[builtins fixtures/dataclasses.pyi] + +[case testDataclassGenericInheritanceSpecialCase2] +# flags: --python-version 3.7 +from dataclasses import dataclass +from typing import Generic, TypeVar + +T = TypeVar("T") + +# A subclass might be analyzed before base in import cycles. They are +# defined here in reversed order to simulate this. + +@dataclass +class Child1(Parent["Child2"]): + x: int + +@dataclass +class Child2(Parent["Child1"]): + y: int + +@dataclass +class Parent(Generic[T]): + key: str + +Child1(x=1, key='') +Child2(y=1, key='') +[builtins fixtures/dataclasses.pyi] + +[case testDataclassGenericWithBound] +# flags: --python-version 3.7 +from dataclasses import dataclass +from typing import Generic, TypeVar + +T = TypeVar("T", bound="C") + +@dataclass +class C(Generic[T]): + x: int + +c: C[C] +d: C[str] # E: Type argument "str" of "C" must be a subtype of "C[Any]" +C(x=2) +[builtins fixtures/dataclasses.pyi] From 8faf44ad44f19c2dcf3f31f12eed5e58494fc3a3 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Wed, 11 May 2022 15:16:19 +0100 Subject: [PATCH 287/377] Fix crash related to functools.total_ordering and forward reference (#12767) Run the plugin in a later pass to avoid placeholder nodes. Fixes #11728. --- mypy/plugins/default.py | 6 +++--- mypy/plugins/functools.py | 10 ++++++---- test-data/unit/check-functools.test | 21 +++++++++++++++++++++ 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/mypy/plugins/default.py b/mypy/plugins/default.py index 50e0e8cb43151..0ae95eb040dbc 100644 --- a/mypy/plugins/default.py +++ b/mypy/plugins/default.py @@ -96,7 +96,6 @@ def get_class_decorator_hook(self, fullname: str ) -> Optional[Callable[[ClassDefContext], None]]: from mypy.plugins import attrs from mypy.plugins import dataclasses - from mypy.plugins import functools if fullname in attrs.attr_class_makers: return attrs.attr_class_maker_callback @@ -118,17 +117,18 @@ def get_class_decorator_hook(self, fullname: str ) elif fullname in dataclasses.dataclass_makers: return dataclasses.dataclass_tag_callback - elif fullname in functools.functools_total_ordering_makers: - return functools.functools_total_ordering_maker_callback return None def get_class_decorator_hook_2(self, fullname: str ) -> Optional[Callable[[ClassDefContext], bool]]: from mypy.plugins import dataclasses + from mypy.plugins import functools if fullname in dataclasses.dataclass_makers: return dataclasses.dataclass_class_maker_callback + elif fullname in functools.functools_total_ordering_makers: + return functools.functools_total_ordering_maker_callback return None diff --git a/mypy/plugins/functools.py b/mypy/plugins/functools.py index 9e4d24283049c..db10b7f1a2623 100644 --- a/mypy/plugins/functools.py +++ b/mypy/plugins/functools.py @@ -26,25 +26,25 @@ class _MethodInfo(NamedTuple): def functools_total_ordering_maker_callback(ctx: mypy.plugin.ClassDefContext, - auto_attribs_default: bool = False) -> None: + auto_attribs_default: bool = False) -> bool: """Add dunder methods to classes decorated with functools.total_ordering.""" if ctx.api.options.python_version < (3,): # This plugin is not supported in Python 2 mode (it's a no-op). - return + return True comparison_methods = _analyze_class(ctx) if not comparison_methods: ctx.api.fail( 'No ordering operation defined when using "functools.total_ordering": < > <= >=', ctx.reason) - return + return True # prefer __lt__ to __le__ to __gt__ to __ge__ root = max(comparison_methods, key=lambda k: (comparison_methods[k] is None, k)) root_method = comparison_methods[root] if not root_method: # None of the defined comparison methods can be analysed - return + return True other_type = _find_other_type(root_method) bool_type = ctx.api.named_type('builtins.bool') @@ -61,6 +61,8 @@ def functools_total_ordering_maker_callback(ctx: mypy.plugin.ClassDefContext, args = [Argument(Var('other', other_type), other_type, None, ARG_POS)] add_method_to_class(ctx.api, ctx.cls, additional_op, args, ret_type) + return True + def _find_other_type(method: _MethodInfo) -> Type: """Find the type of the ``other`` argument in a comparison method.""" diff --git a/test-data/unit/check-functools.test b/test-data/unit/check-functools.test index 5f9159ab9c524..a2c6ba2eee05d 100644 --- a/test-data/unit/check-functools.test +++ b/test-data/unit/check-functools.test @@ -132,3 +132,24 @@ from typing import TypeVar, Generic _T = TypeVar('_T') class cached_property(Generic[_T]): ... [builtins fixtures/property.pyi] + +[case testTotalOrderingWithForwardReference] +from typing import Generic, Any, TypeVar +import functools + +T = TypeVar("T", bound="C") + +@functools.total_ordering +class D(Generic[T]): + def __lt__(self, other: Any) -> bool: + ... + +class C: + pass + +def f(d: D[C]) -> None: + reveal_type(d.__gt__) # N: Revealed type is "def (other: Any) -> builtins.bool" + +d: D[int] # E: Type argument "int" of "D" must be a subtype of "C" +[builtins fixtures/ops.pyi] +[builtins fixtures/dict.pyi] From 5ceaf3d7ec67a9bdee78d656e24dc9e25051759c Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 13 May 2022 13:38:20 +0100 Subject: [PATCH 288/377] [mypyc] Fix TypeError in lambda argument to overloaded function (#12780) Previously we could export an invalid type for a lambda passed to an overloaded function. We find the matching overload variant by type checking the arguments against all overload items. We exported types for lambdas always from the final potential overload item, even if that wasn't the matching one. This could result in mypyc adding invalid type coercions that could result in bogus TypeErrors. The fix is to store types inferred when looking for matching overload items into temporary type maps, and only the type map from the matching item gets merged into the exported types. This doesn't fully solve the problem -- if there are Any types in the arguments, we can still export invalid types. This should be enough to unblock syncing typeshed (#12766). Typeshed started triggering the issue in compiled mypy when re.sub was changed to an overloaded function. Work on #12773. --- mypy/build.py | 5 +- mypy/checker.py | 247 ++++++++++++++++------------ mypy/checkexpr.py | 40 +++-- mypy/checkstrformat.py | 8 +- mypyc/test-data/run-functions.test | 28 ++++ test-data/unit/typexport-basic.test | 38 ++++- 6 files changed, 238 insertions(+), 128 deletions(-) diff --git a/mypy/build.py b/mypy/build.py index ba2d1b1b3d354..c0b9aff5ab32e 100644 --- a/mypy/build.py +++ b/mypy/build.py @@ -2217,7 +2217,10 @@ def type_checker(self) -> TypeChecker: return self._type_checker def type_map(self) -> Dict[Expression, Type]: - return self.type_checker().type_map + # We can extract the master type map directly since at this + # point no temporary type maps can be active. + assert len(self.type_checker()._type_maps) == 1 + return self.type_checker()._type_maps[0] def type_check_second_pass(self) -> bool: if self.options.semantic_analysis_only: diff --git a/mypy/checker.py b/mypy/checker.py index cff637dbb57af..109a3b1f15d27 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -161,8 +161,15 @@ class TypeChecker(NodeVisitor[None], CheckerPluginInterface): errors: Errors # Utility for generating messages msg: MessageBuilder - # Types of type checked nodes - type_map: Dict[Expression, Type] + # Types of type checked nodes. The first item is the "master" type + # map that will store the final, exported types. Additional items + # are temporary type maps used during type inference, and these + # will be eventually popped and either discarded or merged into + # the master type map. + # + # Avoid accessing this directly, but prefer the lookup_type(), + # has_type() etc. helpers instead. + _type_maps: List[Dict[Expression, Type]] # Helper for managing conditional types binder: ConditionalTypeBinder @@ -246,7 +253,7 @@ def __init__(self, errors: Errors, modules: Dict[str, MypyFile], options: Option self.partial_reported = set() self.var_decl_frames = {} self.deferred_nodes = [] - self.type_map = {} + self._type_maps = [{}] self.module_refs = set() self.pass_num = 0 self.current_node_deferred = False @@ -283,7 +290,9 @@ def reset(self) -> None: self.partial_reported.clear() self.module_refs.clear() self.binder = ConditionalTypeBinder() - self.type_map.clear() + self._type_maps[1:] = [] + self._type_maps[0].clear() + self.temp_type_map = None assert self.inferred_attribute_types is None assert self.partial_types == [] @@ -2227,9 +2236,9 @@ def visit_assignment_stmt(self, s: AssignmentStmt) -> None: if len(s.lvalues) > 1: # Chained assignment (e.g. x = y = ...). # Make sure that rvalue type will not be reinferred. - if s.rvalue not in self.type_map: + if not self.has_type(s.rvalue): self.expr_checker.accept(s.rvalue) - rvalue = self.temp_node(self.type_map[s.rvalue], s) + rvalue = self.temp_node(self.lookup_type(s.rvalue), s) for lv in s.lvalues[:-1]: with self.enter_final_context(s.is_final_def): self.check_assignment(lv, rvalue, s.type is None) @@ -2935,7 +2944,9 @@ def check_multi_assignment_from_union(self, lvalues: List[Expression], rvalue: E infer_lvalue_type=infer_lvalue_type, rv_type=item, undefined_rvalue=True) for t, lv in zip(transposed, self.flatten_lvalues(lvalues)): - t.append(self.type_map.pop(lv, AnyType(TypeOfAny.special_form))) + # We can access _type_maps directly since temporary type maps are + # only created within expressions. + t.append(self._type_maps[0].pop(lv, AnyType(TypeOfAny.special_form))) union_types = tuple(make_simplified_union(col) for col in transposed) for expr, items in assignments.items(): # Bind a union of types collected in 'assignments' to every expression. @@ -3986,8 +3997,8 @@ def visit_decorator(self, e: Decorator) -> None: # if this is a expression like @b.a where b is an object, get the type of b # so we can pass it the method hook in the plugins object_type: Optional[Type] = None - if fullname is None and isinstance(d, MemberExpr) and d.expr in self.type_map: - object_type = self.type_map[d.expr] + if fullname is None and isinstance(d, MemberExpr) and self.has_type(d.expr): + object_type = self.lookup_type(d.expr) fullname = self.expr_checker.method_fullname(object_type, d.name) self.check_for_untyped_decorator(e.func, dec, d) sig, t2 = self.expr_checker.check_call(dec, [temp], @@ -4545,8 +4556,6 @@ def find_type_equals_check(self, node: ComparisonExpr, expr_indices: List[int] expr_indices: The list of indices of expressions in ``node`` that are being compared """ - type_map = self.type_map - def is_type_call(expr: CallExpr) -> bool: """Is expr a call to type with one argument?""" return (refers_to_fullname(expr.callee, 'builtins.type') @@ -4565,7 +4574,7 @@ def is_type_call(expr: CallExpr) -> bool: if isinstance(expr, CallExpr) and is_type_call(expr): exprs_in_type_calls.append(expr.args[0]) else: - current_type = get_isinstance_type(expr, type_map) + current_type = self.get_isinstance_type(expr) if current_type is None: continue if type_being_compared is not None: @@ -4588,7 +4597,7 @@ def is_type_call(expr: CallExpr) -> bool: else_maps: List[TypeMap] = [] for expr in exprs_in_type_calls: current_if_type, current_else_type = self.conditional_types_with_intersection( - type_map[expr], + self.lookup_type(expr), type_being_compared, expr ) @@ -4633,12 +4642,11 @@ def find_isinstance_check(self, node: Expression Can return None, None in situations involving NoReturn. """ if_map, else_map = self.find_isinstance_check_helper(node) - new_if_map = self.propagate_up_typemap_info(self.type_map, if_map) - new_else_map = self.propagate_up_typemap_info(self.type_map, else_map) + new_if_map = self.propagate_up_typemap_info(if_map) + new_else_map = self.propagate_up_typemap_info(else_map) return new_if_map, new_else_map def find_isinstance_check_helper(self, node: Expression) -> Tuple[TypeMap, TypeMap]: - type_map = self.type_map if is_true_literal(node): return {}, None if is_false_literal(node): @@ -4653,8 +4661,8 @@ def find_isinstance_check_helper(self, node: Expression) -> Tuple[TypeMap, TypeM return conditional_types_to_typemaps( expr, *self.conditional_types_with_intersection( - type_map[expr], - get_isinstance_type(node.args[1], type_map), + self.lookup_type(expr), + self.get_isinstance_type(node.args[1]), expr ) ) @@ -4662,12 +4670,12 @@ def find_isinstance_check_helper(self, node: Expression) -> Tuple[TypeMap, TypeM if len(node.args) != 2: # the error will be reported elsewhere return {}, {} if literal(expr) == LITERAL_TYPE: - return self.infer_issubclass_maps(node, expr, type_map) + return self.infer_issubclass_maps(node, expr) elif refers_to_fullname(node.callee, 'builtins.callable'): if len(node.args) != 1: # the error will be reported elsewhere return {}, {} if literal(expr) == LITERAL_TYPE: - vartype = type_map[expr] + vartype = self.lookup_type(expr) return self.conditional_callable_type_map(expr, vartype) elif isinstance(node.callee, RefExpr): if node.callee.type_guard is not None: @@ -4691,14 +4699,14 @@ def find_isinstance_check_helper(self, node: Expression) -> Tuple[TypeMap, TypeM operand_types = [] narrowable_operand_index_to_hash = {} for i, expr in enumerate(operands): - if expr not in type_map: + if not self.has_type(expr): return {}, {} - expr_type = type_map[expr] + expr_type = self.lookup_type(expr) operand_types.append(expr_type) if (literal(expr) == LITERAL_TYPE and not is_literal_none(expr) - and not is_literal_enum(type_map, expr)): + and not self.is_literal_enum(expr)): h = literal_hash(expr) if h is not None: narrowable_operand_index_to_hash[i] = h @@ -4871,7 +4879,7 @@ def has_no_custom_eq_checks(t: Type) -> bool: # Restrict the type of the variable to True-ish/False-ish in the if and else branches # respectively - original_vartype = type_map[node] + original_vartype = self.lookup_type(node) self._check_for_truthy_type(original_vartype, node) vartype = try_expanding_sum_type_to_union(original_vartype, "builtins.bool") @@ -4890,7 +4898,6 @@ def has_no_custom_eq_checks(t: Type) -> bool: return if_map, else_map def propagate_up_typemap_info(self, - existing_types: Mapping[Expression, Type], new_types: TypeMap) -> TypeMap: """Attempts refining parent expressions of any MemberExpr or IndexExprs in new_types. @@ -4924,7 +4931,7 @@ def propagate_up_typemap_info(self, output_map[expr] = expr_type # Next, try using this information to refine the parent types, if applicable. - new_mapping = self.refine_parent_types(existing_types, expr, expr_type) + new_mapping = self.refine_parent_types(expr, expr_type) for parent_expr, proposed_parent_type in new_mapping.items(): # We don't try inferring anything if we've already inferred something for # the parent expression. @@ -4935,7 +4942,6 @@ def propagate_up_typemap_info(self, return output_map def refine_parent_types(self, - existing_types: Mapping[Expression, Type], expr: Expression, expr_type: Type) -> Mapping[Expression, Type]: """Checks if the given expr is a 'lookup operation' into a union and iteratively refines @@ -4958,7 +4964,7 @@ def refine_parent_types(self, # operation against arbitrary types. if isinstance(expr, MemberExpr): parent_expr = expr.expr - parent_type = existing_types.get(parent_expr) + parent_type = self.lookup_type_or_none(parent_expr) member_name = expr.name def replay_lookup(new_parent_type: ProperType) -> Optional[Type]: @@ -4981,9 +4987,9 @@ def replay_lookup(new_parent_type: ProperType) -> Optional[Type]: return member_type elif isinstance(expr, IndexExpr): parent_expr = expr.base - parent_type = existing_types.get(parent_expr) + parent_type = self.lookup_type_or_none(parent_expr) - index_type = existing_types.get(expr.index) + index_type = self.lookup_type_or_none(expr.index) if index_type is None: return output @@ -5335,7 +5341,41 @@ def str_type(self) -> Instance: def store_type(self, node: Expression, typ: Type) -> None: """Store the type of a node in the type map.""" - self.type_map[node] = typ + self._type_maps[-1][node] = typ + + def has_type(self, node: Expression) -> bool: + for m in reversed(self._type_maps): + if node in m: + return True + return False + + def lookup_type_or_none(self, node: Expression) -> Optional[Type]: + for m in reversed(self._type_maps): + if node in m: + return m[node] + return None + + def lookup_type(self, node: Expression) -> Type: + for m in reversed(self._type_maps): + t = m.get(node) + if t is not None: + return t + raise KeyError(node) + + def store_types(self, d: Dict[Expression, Type]) -> None: + self._type_maps[-1].update(d) + + @contextmanager + def local_type_map(self) -> Iterator[Dict[Expression, Type]]: + """Store inferred types into a temporary type map (returned). + + This can be used to perform type checking "experiments" without + affecting exported types (which are used by mypyc). + """ + temp_type_map: Dict[Expression, Type] = {} + self._type_maps.append(temp_type_map) + yield temp_type_map + self._type_maps.pop() def in_checked_function(self) -> bool: """Should we type-check the current function? @@ -5579,11 +5619,10 @@ def push_type_map(self, type_map: 'TypeMap') -> None: def infer_issubclass_maps(self, node: CallExpr, expr: Expression, - type_map: Dict[Expression, Type] ) -> Tuple[TypeMap, TypeMap]: """Infer type restrictions for an expression in issubclass call.""" - vartype = type_map[expr] - type = get_isinstance_type(node.args[1], type_map) + vartype = self.lookup_type(expr) + type = self.get_isinstance_type(node.args[1]) if isinstance(vartype, TypeVarType): vartype = vartype.upper_bound vartype = get_proper_type(vartype) @@ -5683,6 +5722,75 @@ def is_writable_attribute(self, node: Node) -> bool: else: return False + def get_isinstance_type(self, expr: Expression) -> Optional[List[TypeRange]]: + if isinstance(expr, OpExpr) and expr.op == '|': + left = self.get_isinstance_type(expr.left) + right = self.get_isinstance_type(expr.right) + if left is None or right is None: + return None + return left + right + all_types = get_proper_types(flatten_types(self.lookup_type(expr))) + types: List[TypeRange] = [] + for typ in all_types: + if isinstance(typ, FunctionLike) and typ.is_type_obj(): + # Type variables may be present -- erase them, which is the best + # we can do (outside disallowing them here). + erased_type = erase_typevars(typ.items[0].ret_type) + types.append(TypeRange(erased_type, is_upper_bound=False)) + elif isinstance(typ, TypeType): + # Type[A] means "any type that is a subtype of A" rather than "precisely type A" + # we indicate this by setting is_upper_bound flag + types.append(TypeRange(typ.item, is_upper_bound=True)) + elif isinstance(typ, Instance) and typ.type.fullname == 'builtins.type': + object_type = Instance(typ.type.mro[-1], []) + types.append(TypeRange(object_type, is_upper_bound=True)) + elif isinstance(typ, AnyType): + types.append(TypeRange(typ, is_upper_bound=False)) + else: # we didn't see an actual type, but rather a variable with unknown value + return None + if not types: + # this can happen if someone has empty tuple as 2nd argument to isinstance + # strictly speaking, we should return UninhabitedType but for simplicity we will simply + # refuse to do any type inference for now + return None + return types + + def is_literal_enum(self, n: Expression) -> bool: + """Returns true if this expression (with the given type context) is an Enum literal. + + For example, if we had an enum: + + class Foo(Enum): + A = 1 + B = 2 + + ...and if the expression 'Foo' referred to that enum within the current type context, + then the expression 'Foo.A' would be a literal enum. However, if we did 'a = Foo.A', + then the variable 'a' would *not* be a literal enum. + + We occasionally special-case expressions like 'Foo.A' and treat them as a single primitive + unit for the same reasons we sometimes treat 'True', 'False', or 'None' as a single + primitive unit. + """ + if not isinstance(n, MemberExpr) or not isinstance(n.expr, NameExpr): + return False + + parent_type = self.lookup_type_or_none(n.expr) + member_type = self.lookup_type_or_none(n) + if member_type is None or parent_type is None: + return False + + parent_type = get_proper_type(parent_type) + member_type = get_proper_type(coerce_to_literal(member_type)) + if not isinstance(parent_type, FunctionLike) or not isinstance(member_type, LiteralType): + return False + + if not parent_type.is_type_obj(): + return False + + return (member_type.is_enum_literal() + and member_type.fallback.type == parent_type.type_object()) + @overload def conditional_types(current_type: Type, @@ -5785,42 +5893,6 @@ def is_false_literal(n: Expression) -> bool: or isinstance(n, IntExpr) and n.value == 0) -def is_literal_enum(type_map: Mapping[Expression, Type], n: Expression) -> bool: - """Returns true if this expression (with the given type context) is an Enum literal. - - For example, if we had an enum: - - class Foo(Enum): - A = 1 - B = 2 - - ...and if the expression 'Foo' referred to that enum within the current type context, - then the expression 'Foo.A' would be a literal enum. However, if we did 'a = Foo.A', - then the variable 'a' would *not* be a literal enum. - - We occasionally special-case expressions like 'Foo.A' and treat them as a single primitive - unit for the same reasons we sometimes treat 'True', 'False', or 'None' as a single - primitive unit. - """ - if not isinstance(n, MemberExpr) or not isinstance(n.expr, NameExpr): - return False - - parent_type = type_map.get(n.expr) - member_type = type_map.get(n) - if member_type is None or parent_type is None: - return False - - parent_type = get_proper_type(parent_type) - member_type = get_proper_type(coerce_to_literal(member_type)) - if not isinstance(parent_type, FunctionLike) or not isinstance(member_type, LiteralType): - return False - - if not parent_type.is_type_obj(): - return False - - return member_type.is_enum_literal() and member_type.fallback.type == parent_type.type_object() - - def is_literal_none(n: Expression) -> bool: """Returns true if this expression is the 'None' literal/keyword.""" return isinstance(n, NameExpr) and n.fullname == 'builtins.None' @@ -5986,41 +6058,6 @@ def flatten_types(t: Type) -> List[Type]: return [t] -def get_isinstance_type(expr: Expression, - type_map: Dict[Expression, Type]) -> Optional[List[TypeRange]]: - if isinstance(expr, OpExpr) and expr.op == '|': - left = get_isinstance_type(expr.left, type_map) - right = get_isinstance_type(expr.right, type_map) - if left is None or right is None: - return None - return left + right - all_types = get_proper_types(flatten_types(type_map[expr])) - types: List[TypeRange] = [] - for typ in all_types: - if isinstance(typ, FunctionLike) and typ.is_type_obj(): - # Type variables may be present -- erase them, which is the best - # we can do (outside disallowing them here). - erased_type = erase_typevars(typ.items[0].ret_type) - types.append(TypeRange(erased_type, is_upper_bound=False)) - elif isinstance(typ, TypeType): - # Type[A] means "any type that is a subtype of A" rather than "precisely type A" - # we indicate this by setting is_upper_bound flag - types.append(TypeRange(typ.item, is_upper_bound=True)) - elif isinstance(typ, Instance) and typ.type.fullname == 'builtins.type': - object_type = Instance(typ.type.mro[-1], []) - types.append(TypeRange(object_type, is_upper_bound=True)) - elif isinstance(typ, AnyType): - types.append(TypeRange(typ, is_upper_bound=False)) - else: # we didn't see an actual type, but rather a variable whose value is unknown to us - return None - if not types: - # this can happen if someone has empty tuple as 2nd argument to isinstance - # strictly speaking, we should return UninhabitedType but for simplicity we will simply - # refuse to do any type inference for now - return None - return types - - def expand_func(defn: FuncItem, map: Dict[TypeVarId, Type]) -> FuncItem: visitor = TypeTransformVisitor(map) ret = defn.accept(visitor) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 21fd7d81967f5..bfbe961adc7aa 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -369,9 +369,9 @@ def visit_call_expr_inner(self, e: CallExpr, allow_none_return: bool = False) -> # be invoked for these. if (fullname is None and isinstance(e.callee, MemberExpr) - and e.callee.expr in self.chk.type_map): + and self.chk.has_type(e.callee.expr)): member = e.callee.name - object_type = self.chk.type_map[e.callee.expr] + object_type = self.chk.lookup_type(e.callee.expr) ret_type = self.check_call_expr_with_callee_type(callee_type, e, fullname, object_type, member) if isinstance(e.callee, RefExpr) and len(e.args) == 2: @@ -401,8 +401,8 @@ def check_str_format_call(self, e: CallExpr) -> None: format_value = None if isinstance(e.callee.expr, (StrExpr, UnicodeExpr)): format_value = e.callee.expr.value - elif e.callee.expr in self.chk.type_map: - base_typ = try_getting_literal(self.chk.type_map[e.callee.expr]) + elif self.chk.has_type(e.callee.expr): + base_typ = try_getting_literal(self.chk.lookup_type(e.callee.expr)) if isinstance(base_typ, LiteralType) and isinstance(base_typ.value, str): format_value = base_typ.value if format_value is not None: @@ -442,7 +442,7 @@ def always_returns_none(self, node: Expression) -> bool: if self.defn_returns_none(node.node): return True if isinstance(node, MemberExpr) and node.node is None: # instance or class attribute - typ = get_proper_type(self.chk.type_map.get(node.expr)) + typ = get_proper_type(self.chk.lookup_type(node.expr)) if isinstance(typ, Instance): info = typ.type elif isinstance(typ, CallableType) and typ.is_type_obj(): @@ -478,7 +478,7 @@ def defn_returns_none(self, defn: Optional[SymbolNode]) -> bool: def check_runtime_protocol_test(self, e: CallExpr) -> None: for expr in mypy.checker.flatten(e.args[1]): - tp = get_proper_type(self.chk.type_map[expr]) + tp = get_proper_type(self.chk.lookup_type(expr)) if (isinstance(tp, CallableType) and tp.is_type_obj() and tp.type_object().is_protocol and not tp.type_object().runtime_protocol): @@ -486,7 +486,7 @@ def check_runtime_protocol_test(self, e: CallExpr) -> None: def check_protocol_issubclass(self, e: CallExpr) -> None: for expr in mypy.checker.flatten(e.args[1]): - tp = get_proper_type(self.chk.type_map[expr]) + tp = get_proper_type(self.chk.lookup_type(expr)) if (isinstance(tp, CallableType) and tp.is_type_obj() and tp.type_object().is_protocol): attr_members = non_method_protocol_members(tp.type_object()) @@ -1740,18 +1740,20 @@ def infer_overload_return_type(self, return_types: List[Type] = [] inferred_types: List[Type] = [] args_contain_any = any(map(has_any_type, arg_types)) + type_maps: List[Dict[Expression, Type]] = [] for typ in plausible_targets: assert self.msg is self.chk.msg with self.msg.filter_errors() as w: - ret_type, infer_type = self.check_call( - callee=typ, - args=args, - arg_kinds=arg_kinds, - arg_names=arg_names, - context=context, - callable_name=callable_name, - object_type=object_type) + with self.chk.local_type_map() as m: + ret_type, infer_type = self.check_call( + callee=typ, + args=args, + arg_kinds=arg_kinds, + arg_names=arg_names, + context=context, + callable_name=callable_name, + object_type=object_type) is_match = not w.has_new_errors() if is_match: # Return early if possible; otherwise record info so we can @@ -1761,6 +1763,7 @@ def infer_overload_return_type(self, matches.append(typ) return_types.append(ret_type) inferred_types.append(infer_type) + type_maps.append(m) if len(matches) == 0: # No match was found @@ -1769,8 +1772,10 @@ def infer_overload_return_type(self, # An argument of type or containing the type 'Any' caused ambiguity. # We try returning a precise type if we can. If not, we give up and just return 'Any'. if all_same_types(return_types): + self.chk.store_types(type_maps[0]) return return_types[0], inferred_types[0] elif all_same_types([erase_type(typ) for typ in return_types]): + self.chk.store_types(type_maps[0]) return erase_type(return_types[0]), erase_type(inferred_types[0]) else: return self.check_call(callee=AnyType(TypeOfAny.special_form), @@ -1782,6 +1787,7 @@ def infer_overload_return_type(self, object_type=object_type) else: # Success! No ambiguity; return the first match. + self.chk.store_types(type_maps[0]) return return_types[0], inferred_types[0] def overload_erased_call_targets(self, @@ -3546,10 +3552,10 @@ def visit_lambda_expr(self, e: LambdaExpr) -> Type: # Type context available. self.chk.return_types.append(inferred_type.ret_type) self.chk.check_func_item(e, type_override=type_override) - if e.expr() not in self.chk.type_map: + if not self.chk.has_type(e.expr()): # TODO: return expression must be accepted before exiting function scope. self.accept(e.expr(), allow_none_return=True) - ret_type = self.chk.type_map[e.expr()] + ret_type = self.chk.lookup_type(e.expr()) self.chk.return_types.pop() return replace_callable_return_type(inferred_type, ret_type) diff --git a/mypy/checkstrformat.py b/mypy/checkstrformat.py index 20b3716ea5135..60a0d35ede080 100644 --- a/mypy/checkstrformat.py +++ b/mypy/checkstrformat.py @@ -317,7 +317,7 @@ def check_specs_in_format_call(self, call: CallExpr, assert len(replacements) == len(specs) for spec, repl in zip(specs, replacements): repl = self.apply_field_accessors(spec, repl, ctx=call) - actual_type = repl.type if isinstance(repl, TempNode) else self.chk.type_map.get(repl) + actual_type = repl.type if isinstance(repl, TempNode) else self.chk.lookup_type(repl) assert actual_type is not None # Special case custom formatting. @@ -370,7 +370,7 @@ def perform_special_format_checks(self, spec: ConversionSpecifier, call: CallExp if spec.conv_type == 'c': if isinstance(repl, (StrExpr, BytesExpr)) and len(repl.value) != 1: self.msg.requires_int_or_char(call, format_call=True) - c_typ = get_proper_type(self.chk.type_map[repl]) + c_typ = get_proper_type(self.chk.lookup_type(repl)) if isinstance(c_typ, Instance) and c_typ.last_known_value: c_typ = c_typ.last_known_value if isinstance(c_typ, LiteralType) and isinstance(c_typ.value, str): @@ -442,7 +442,7 @@ def get_expr_by_position(self, pos: int, call: CallExpr) -> Optional[Expression] # Fall back to *args when present in call. star_arg = star_args[0] - varargs_type = get_proper_type(self.chk.type_map[star_arg]) + varargs_type = get_proper_type(self.chk.lookup_type(star_arg)) if (not isinstance(varargs_type, Instance) or not varargs_type.type.has_base('typing.Sequence')): # Error should be already reported. @@ -465,7 +465,7 @@ def get_expr_by_name(self, key: str, call: CallExpr) -> Optional[Expression]: if not star_args_2: return None star_arg_2 = star_args_2[0] - kwargs_type = get_proper_type(self.chk.type_map[star_arg_2]) + kwargs_type = get_proper_type(self.chk.lookup_type(star_arg_2)) if (not isinstance(kwargs_type, Instance) or not kwargs_type.type.has_base('typing.Mapping')): # Error should be already reported. diff --git a/mypyc/test-data/run-functions.test b/mypyc/test-data/run-functions.test index 66b56503f329e..77e9c9ed32f78 100644 --- a/mypyc/test-data/run-functions.test +++ b/mypyc/test-data/run-functions.test @@ -1192,3 +1192,31 @@ def foo(): pass def test_decorator_name(): assert foo.__name__ == "foo" + +[case testLambdaArgToOverloaded] +from lib import sub + +def test_str_overload() -> None: + assert sub('x', lambda m: m) == 'x' + +def test_bytes_overload() -> None: + assert sub(b'x', lambda m: m) == b'x' + +[file lib.py] +from typing import overload, Callable, TypeVar, Generic + +T = TypeVar("T") + +class Match(Generic[T]): + def __init__(self, x: T) -> None: + self.x = x + + def group(self, n: int) -> T: + return self.x + +@overload +def sub(s: str, f: Callable[[str], str]) -> str: ... +@overload +def sub(s: bytes, f: Callable[[bytes], bytes]) -> bytes: ... +def sub(s, f): + return f(s) diff --git a/test-data/unit/typexport-basic.test b/test-data/unit/typexport-basic.test index bdefb49e30382..5cbdf38d1b4f2 100644 --- a/test-data/unit/typexport-basic.test +++ b/test-data/unit/typexport-basic.test @@ -1182,6 +1182,43 @@ IntExpr(2) : Literal[1]? OpExpr(2) : builtins.str StrExpr(2) : Literal['%d']? +[case testExportOverloadArgType] +## LambdaExpr|NameExpr +from typing import List, overload, Callable +@overload +def f(x: int, f: Callable[[int], int]) -> None: ... +@overload +def f(x: str, f: Callable[[str], str]) -> None: ... +def f(x): ... +f( + 1, lambda x: x) +[builtins fixtures/list.pyi] +[out] +NameExpr(8) : Overload(def (x: builtins.int, f: def (builtins.int) -> builtins.int), def (x: builtins.str, f: def (builtins.str) -> builtins.str)) +LambdaExpr(9) : def (builtins.int) -> builtins.int +NameExpr(9) : builtins.int + +[case testExportOverloadArgTypeNested] +## LambdaExpr +from typing import overload, Callable +@overload +def f(x: int, f: Callable[[int], int]) -> int: ... +@overload +def f(x: str, f: Callable[[str], str]) -> str: ... +def f(x): ... +f( + f(1, lambda y: y), + lambda x: x) +f( + f('x', lambda y: y), + lambda x: x) +[builtins fixtures/list.pyi] +[out] +LambdaExpr(9) : def (builtins.int) -> builtins.int +LambdaExpr(10) : def (builtins.int) -> builtins.int +LambdaExpr(12) : def (builtins.str) -> builtins.str +LambdaExpr(13) : def (builtins.str) -> builtins.str + -- TODO -- -- test expressions @@ -1193,7 +1230,6 @@ StrExpr(2) : Literal['%d']? -- more complex lambda (multiple arguments etc.) -- list comprehension -- generator expression --- overloads -- other things -- type inference -- default argument value From 50a653e0714e303178c890854b9074fc030907f0 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 13 May 2022 14:49:53 +0100 Subject: [PATCH 289/377] Fix forward references and generic inheritance in attrs classes (#12772) Move the attrs plugin to a later pass, so that we won't have placeholders. Fix various issues related to forward references and generic inheritance, including some crashes. This is follow-up to #12762 and related to #12656 and #12633. --- mypy/plugins/attrs.py | 112 ++++++++++++++---------- mypy/plugins/default.py | 40 +++++---- test-data/unit/check-attr.test | 143 +++++++++++++++++++++++++++++++ test-data/unit/fixtures/dict.pyi | 2 +- 4 files changed, 235 insertions(+), 62 deletions(-) diff --git a/mypy/plugins/attrs.py b/mypy/plugins/attrs.py index 38fd2f040be50..dbce8a4021410 100644 --- a/mypy/plugins/attrs.py +++ b/mypy/plugins/attrs.py @@ -7,7 +7,6 @@ import mypy.plugin # To avoid circular imports. from mypy.exprtotype import expr_to_unanalyzed_type, TypeTranslationError -from mypy.lookup import lookup_fully_qualified from mypy.nodes import ( Context, Argument, Var, ARG_OPT, ARG_POS, TypeInfo, AssignmentStmt, TupleExpr, ListExpr, NameExpr, CallExpr, RefExpr, FuncDef, @@ -61,10 +60,12 @@ class Converter: """Holds information about a `converter=` argument""" def __init__(self, - name: Optional[str] = None, - is_attr_converters_optional: bool = False) -> None: - self.name = name + type: Optional[Type] = None, + is_attr_converters_optional: bool = False, + is_invalid_converter: bool = False) -> None: + self.type = type self.is_attr_converters_optional = is_attr_converters_optional + self.is_invalid_converter = is_invalid_converter class Attribute: @@ -89,29 +90,14 @@ def argument(self, ctx: 'mypy.plugin.ClassDefContext') -> Argument: init_type = self.init_type or self.info[self.name].type - if self.converter.name: + if self.converter.type and not self.converter.is_invalid_converter: # When a converter is set the init_type is overridden by the first argument # of the converter method. - converter = lookup_fully_qualified(self.converter.name, ctx.api.modules, - raise_on_missing=False) - if not converter: - # The converter may be a local variable. Check there too. - converter = ctx.api.lookup_qualified(self.converter.name, self.info, True) - - # Get the type of the converter. - converter_type: Optional[Type] = None - if converter and isinstance(converter.node, TypeInfo): - from mypy.checkmember import type_object_type # To avoid import cycle. - converter_type = type_object_type(converter.node, ctx.api.named_type) - elif converter and isinstance(converter.node, OverloadedFuncDef): - converter_type = converter.node.type - elif converter and converter.type: - converter_type = converter.type - + converter_type = self.converter.type init_type = None converter_type = get_proper_type(converter_type) if isinstance(converter_type, CallableType) and converter_type.arg_types: - init_type = ctx.api.anal_type(converter_type.arg_types[0]) + init_type = converter_type.arg_types[0] elif isinstance(converter_type, Overloaded): types: List[Type] = [] for item in converter_type.items: @@ -124,8 +110,7 @@ def argument(self, ctx: 'mypy.plugin.ClassDefContext') -> Argument: types.append(item.arg_types[0]) # Make a union of all the valid types. if types: - args = make_simplified_union(types) - init_type = ctx.api.anal_type(args) + init_type = make_simplified_union(types) if self.converter.is_attr_converters_optional and init_type: # If the converter was attr.converter.optional(type) then add None to @@ -135,9 +120,8 @@ def argument(self, ctx: 'mypy.plugin.ClassDefContext') -> Argument: if not init_type: ctx.api.fail("Cannot determine __init__ type from converter", self.context) init_type = AnyType(TypeOfAny.from_error) - elif self.converter.name == '': + elif self.converter.is_invalid_converter: # This means we had a converter but it's not of a type we can infer. - # Error was shown in _get_converter_name init_type = AnyType(TypeOfAny.from_error) if init_type is None: @@ -170,8 +154,9 @@ def serialize(self) -> JsonDict: 'has_default': self.has_default, 'init': self.init, 'kw_only': self.kw_only, - 'converter_name': self.converter.name, + 'converter_type': self.converter.type.serialize() if self.converter.type else None, 'converter_is_attr_converters_optional': self.converter.is_attr_converters_optional, + 'converter_is_invalid_converter': self.converter.is_invalid_converter, 'context_line': self.context.line, 'context_column': self.context.column, 'init_type': self.init_type.serialize() if self.init_type else None, @@ -185,22 +170,26 @@ def deserialize(cls, info: TypeInfo, raw_init_type = data['init_type'] init_type = deserialize_and_fixup_type(raw_init_type, api) if raw_init_type else None + converter_type = None + if data['converter_type']: + converter_type = deserialize_and_fixup_type(data['converter_type'], api) return Attribute(data['name'], info, data['has_default'], data['init'], data['kw_only'], - Converter(data['converter_name'], data['converter_is_attr_converters_optional']), + Converter(converter_type, data['converter_is_attr_converters_optional'], + data['converter_is_invalid_converter']), Context(line=data['context_line'], column=data['context_column']), init_type) def expand_typevar_from_subtype(self, sub_type: TypeInfo) -> None: """Expands type vars in the context of a subtype when an attribute is inherited from a generic super type.""" - if not isinstance(self.init_type, TypeVarType): - return - - self.init_type = map_type_from_supertype(self.init_type, sub_type, self.info) + if self.init_type: + self.init_type = map_type_from_supertype(self.init_type, sub_type, self.info) + else: + self.init_type = None def _determine_eq_order(ctx: 'mypy.plugin.ClassDefContext') -> bool: @@ -258,9 +247,19 @@ def _get_decorator_optional_bool_argument( return default +def attr_tag_callback(ctx: 'mypy.plugin.ClassDefContext') -> None: + """Record that we have an attrs class in the main semantic analysis pass. + + The later pass implemented by attr_class_maker_callback will use this + to detect attrs lasses in base classes. + """ + # The value is ignored, only the existence matters. + ctx.cls.info.metadata['attrs_tag'] = {} + + def attr_class_maker_callback(ctx: 'mypy.plugin.ClassDefContext', auto_attribs_default: Optional[bool] = False, - frozen_default: bool = False) -> None: + frozen_default: bool = False) -> bool: """Add necessary dunder methods to classes decorated with attr.s. attrs is a package that lets you define classes without writing dull boilerplate code. @@ -271,6 +270,9 @@ def attr_class_maker_callback(ctx: 'mypy.plugin.ClassDefContext', into properties. See http://www.attrs.org/en/stable/how-does-it-work.html for information on how attrs works. + + If this returns False, some required metadata was not ready yet and we need another + pass. """ info = ctx.cls.info @@ -283,17 +285,26 @@ def attr_class_maker_callback(ctx: 'mypy.plugin.ClassDefContext', kw_only = _get_decorator_bool_argument(ctx, 'kw_only', False) match_args = _get_decorator_bool_argument(ctx, 'match_args', True) + early_fail = False if ctx.api.options.python_version[0] < 3: if auto_attribs: ctx.api.fail("auto_attribs is not supported in Python 2", ctx.reason) - return + early_fail = True if not info.defn.base_type_exprs: # Note: This will not catch subclassing old-style classes. ctx.api.fail("attrs only works with new-style classes", info.defn) - return + early_fail = True if kw_only: ctx.api.fail(KW_ONLY_PYTHON_2_UNSUPPORTED, ctx.reason) - return + early_fail = True + if early_fail: + _add_empty_metadata(info) + return True + + for super_info in ctx.cls.info.mro[1:-1]: + if 'attrs_tag' in super_info.metadata and 'attrs' not in super_info.metadata: + # Super class is not ready yet. Request another pass. + return False attributes = _analyze_class(ctx, auto_attribs, kw_only) @@ -301,12 +312,10 @@ def attr_class_maker_callback(ctx: 'mypy.plugin.ClassDefContext', for attr in attributes: node = info.get(attr.name) if node is None: - # This name is likely blocked by a star import. We don't need to defer because - # defer() is already called by mark_incomplete(). - return - if node.type is None and not ctx.api.final_iteration: - ctx.api.defer() - return + # This name is likely blocked by some semantic analysis error that + # should have been reported already. + _add_empty_metadata(info) + return True _add_attrs_magic_attribute(ctx, [(attr.name, info[attr.name].type) for attr in attributes]) if slots: @@ -330,6 +339,8 @@ def attr_class_maker_callback(ctx: 'mypy.plugin.ClassDefContext', if frozen: _make_frozen(ctx, attributes) + return True + def _get_frozen(ctx: 'mypy.plugin.ClassDefContext', frozen_default: bool) -> bool: """Return whether this class is frozen.""" @@ -423,6 +434,14 @@ def _analyze_class(ctx: 'mypy.plugin.ClassDefContext', return attributes +def _add_empty_metadata(info: TypeInfo) -> None: + """Add empty metadata to mark that we've finished processing this class.""" + info.metadata['attrs'] = { + 'attributes': [], + 'frozen': False, + } + + def _detect_auto_attribs(ctx: 'mypy.plugin.ClassDefContext') -> bool: """Return whether auto_attribs should be enabled or disabled. @@ -602,12 +621,13 @@ def _parse_converter(ctx: 'mypy.plugin.ClassDefContext', if (isinstance(converter.node, FuncDef) and converter.node.type and isinstance(converter.node.type, FunctionLike)): - return Converter(converter.node.fullname) + return Converter(converter.node.type) elif (isinstance(converter.node, OverloadedFuncDef) and is_valid_overloaded_converter(converter.node)): - return Converter(converter.node.fullname) + return Converter(converter.node.type) elif isinstance(converter.node, TypeInfo): - return Converter(converter.node.fullname) + from mypy.checkmember import type_object_type # To avoid import cycle. + return Converter(type_object_type(converter.node, ctx.api.named_type)) if (isinstance(converter, CallExpr) and isinstance(converter.callee, RefExpr) @@ -625,7 +645,7 @@ def _parse_converter(ctx: 'mypy.plugin.ClassDefContext', "Unsupported converter, only named functions and types are currently supported", converter ) - return Converter('') + return Converter(None, is_invalid_converter=True) return Converter(None) diff --git a/mypy/plugins/default.py b/mypy/plugins/default.py index 0ae95eb040dbc..40997803aa7e3 100644 --- a/mypy/plugins/default.py +++ b/mypy/plugins/default.py @@ -94,10 +94,34 @@ def get_attribute_hook(self, fullname: str def get_class_decorator_hook(self, fullname: str ) -> Optional[Callable[[ClassDefContext], None]]: + from mypy.plugins import dataclasses from mypy.plugins import attrs + + # These dataclass and attrs hooks run in the main semantic analysis pass + # and only tag known dataclasses/attrs classes, so that the second + # hooks (in get_class_decorator_hook_2) can detect dataclasses/attrs classes + # in the MRO. + if fullname in dataclasses.dataclass_makers: + return dataclasses.dataclass_tag_callback + if (fullname in attrs.attr_class_makers + or fullname in attrs.attr_dataclass_makers + or fullname in attrs.attr_frozen_makers + or fullname in attrs.attr_define_makers): + return attrs.attr_tag_callback + + return None + + def get_class_decorator_hook_2(self, fullname: str + ) -> Optional[Callable[[ClassDefContext], bool]]: from mypy.plugins import dataclasses + from mypy.plugins import functools + from mypy.plugins import attrs - if fullname in attrs.attr_class_makers: + if fullname in dataclasses.dataclass_makers: + return dataclasses.dataclass_class_maker_callback + elif fullname in functools.functools_total_ordering_makers: + return functools.functools_total_ordering_maker_callback + elif fullname in attrs.attr_class_makers: return attrs.attr_class_maker_callback elif fullname in attrs.attr_dataclass_makers: return partial( @@ -115,20 +139,6 @@ def get_class_decorator_hook(self, fullname: str attrs.attr_class_maker_callback, auto_attribs_default=None, ) - elif fullname in dataclasses.dataclass_makers: - return dataclasses.dataclass_tag_callback - - return None - - def get_class_decorator_hook_2(self, fullname: str - ) -> Optional[Callable[[ClassDefContext], bool]]: - from mypy.plugins import dataclasses - from mypy.plugins import functools - - if fullname in dataclasses.dataclass_makers: - return dataclasses.dataclass_class_maker_callback - elif fullname in functools.functools_total_ordering_makers: - return functools.functools_total_ordering_maker_callback return None diff --git a/test-data/unit/check-attr.test b/test-data/unit/check-attr.test index a69bd473624d1..fdb0da7e0fce4 100644 --- a/test-data/unit/check-attr.test +++ b/test-data/unit/check-attr.test @@ -544,6 +544,37 @@ reveal_type(sub.three) # N: Revealed type is "builtins.float" [builtins fixtures/bool.pyi] +[case testAttrsGenericInheritance3] +import attr +from typing import Any, Callable, Generic, TypeVar, List + +T = TypeVar("T") +S = TypeVar("S") + +@attr.s(auto_attribs=True) +class Parent(Generic[T]): + f: Callable[[T], Any] + +@attr.s(auto_attribs=True) +class Child(Parent[T]): ... + +class A: ... +def func(obj: A) -> bool: ... + +reveal_type(Child[A](func).f) # N: Revealed type is "def (__main__.A) -> Any" + +@attr.s(auto_attribs=True) +class Parent2(Generic[T]): + a: List[T] + +@attr.s(auto_attribs=True) +class Child2(Generic[T, S], Parent2[S]): + b: List[T] + +reveal_type(Child2([A()], [1]).a) # N: Revealed type is "builtins.list[__main__.A]" +reveal_type(Child2[int, A]([A()], [1]).b) # N: Revealed type is "builtins.list[builtins.int]" +[builtins fixtures/list.pyi] + [case testAttrsMultiGenericInheritance] from typing import Generic, TypeVar import attr @@ -1010,6 +1041,9 @@ class Good(object): @attr.s class Bad: # E: attrs only works with new-style classes pass +@attr.s +class SubclassOfBad(Bad): + pass [builtins_py2 fixtures/bool.pyi] [case testAttrsAutoAttribsPy2] @@ -1591,3 +1625,112 @@ class B: class AB(A, B): pass [builtins fixtures/attr.pyi] + +[case testAttrsForwardReferenceInTypeVarBound] +from typing import TypeVar, Generic +import attr + +T = TypeVar("T", bound="C") + +@attr.define +class D(Generic[T]): + x: int + +class C: + pass +[builtins fixtures/attr.pyi] + +[case testComplexTypeInAttrIb] +import a + +[file a.py] +import attr +import b +from typing import Callable + +@attr.s +class C: + a = attr.ib(type=Lst[int]) + # Note that for this test, the 'Value of type "int" is not indexable' errors are silly, + # and a consequence of Callable etc. being set to an int in the test stub. + b = attr.ib(type=Callable[[], C]) +[builtins fixtures/bool.pyi] + +[file b.py] +import attr +import a +from typing import List as Lst, Optional + +@attr.s +class D: + a = attr.ib(type=Lst[int]) + b = attr.ib(type=Optional[int]) +[builtins fixtures/list.pyi] +[out] +tmp/b.py:8: error: Value of type "int" is not indexable +tmp/a.py:7: error: Name "Lst" is not defined +tmp/a.py:10: error: Value of type "int" is not indexable + +[case testAttrsGenericInheritanceSpecialCase1] +import attr +from typing import Generic, TypeVar, List + +T = TypeVar("T") + +@attr.define +class Parent(Generic[T]): + x: List[T] + +@attr.define +class Child1(Parent["Child2"]): ... + +@attr.define +class Child2(Parent["Child1"]): ... + +def f(c: Child2) -> None: + reveal_type(Child1([c]).x) # N: Revealed type is "builtins.list[__main__.Child2]" + +def g(c: Child1) -> None: + reveal_type(Child2([c]).x) # N: Revealed type is "builtins.list[__main__.Child1]" +[builtins fixtures/list.pyi] + +[case testAttrsGenericInheritanceSpecialCase2] +import attr +from typing import Generic, TypeVar + +T = TypeVar("T") + +# A subclass might be analyzed before base in import cycles. They are +# defined here in reversed order to simulate this. + +@attr.define +class Child1(Parent["Child2"]): + x: int + +@attr.define +class Child2(Parent["Child1"]): + y: int + +@attr.define +class Parent(Generic[T]): + key: str + +Child1(x=1, key='') +Child2(y=1, key='') +[builtins fixtures/list.pyi] + +[case testAttrsUnsupportedConverterWithDisallowUntypedDefs] +# flags: --disallow-untyped-defs +import attr +from typing import Mapping, Any, Union + +def default_if_none(factory: Any) -> Any: pass + +@attr.s(slots=True, frozen=True) +class C: + name: Union[str, None] = attr.ib(default=None) + options: Mapping[str, Mapping[str, Any]] = attr.ib( + default=None, converter=default_if_none(factory=dict) \ + # E: Unsupported converter, only named functions and types are currently supported + ) +[builtins fixtures/dict.pyi] diff --git a/test-data/unit/fixtures/dict.pyi b/test-data/unit/fixtures/dict.pyi index f8a5e3481d135..9e7cb6f8c70d9 100644 --- a/test-data/unit/fixtures/dict.pyi +++ b/test-data/unit/fixtures/dict.pyi @@ -34,7 +34,7 @@ class dict(Mapping[KT, VT]): class int: # for convenience def __add__(self, x: Union[int, complex]) -> int: pass def __sub__(self, x: Union[int, complex]) -> int: pass - def __neg__(self): pass + def __neg__(self) -> int: pass real: int imag: int From 7fbf4deb845d6041700d1addc6eaa2097560f0f3 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Fri, 13 May 2022 14:18:31 -0700 Subject: [PATCH 290/377] Sync typeshed (#12766) Source commit: https://github.com/python/typeshed/commit/a27f15ef0eb12b961d0fb58f8615a3df901a9176 Co-authored-by: hauntsaninja <> --- mypy/typeshed/stdlib/_ast.pyi | 2 +- mypy/typeshed/stdlib/_csv.pyi | 62 +- mypy/typeshed/stdlib/_decimal.pyi | 18 +- mypy/typeshed/stdlib/_socket.pyi | 4 + mypy/typeshed/stdlib/_typeshed/__init__.pyi | 25 +- mypy/typeshed/stdlib/asyncio/transports.pyi | 6 +- mypy/typeshed/stdlib/builtins.pyi | 76 ++- mypy/typeshed/stdlib/contextlib.pyi | 4 +- mypy/typeshed/stdlib/csv.pyi | 49 +- mypy/typeshed/stdlib/dataclasses.pyi | 22 +- mypy/typeshed/stdlib/datetime.pyi | 7 +- mypy/typeshed/stdlib/enum.pyi | 20 +- mypy/typeshed/stdlib/http/__init__.pyi | 22 +- mypy/typeshed/stdlib/inspect.pyi | 73 ++- mypy/typeshed/stdlib/logging/__init__.pyi | 2 +- .../stdlib/multiprocessing/managers.pyi | 18 +- mypy/typeshed/stdlib/os/__init__.pyi | 4 + mypy/typeshed/stdlib/posix.pyi | 3 + mypy/typeshed/stdlib/re.pyi | 70 ++- mypy/typeshed/stdlib/socket.pyi | 23 +- mypy/typeshed/stdlib/sqlite3/dbapi2.pyi | 2 + mypy/typeshed/stdlib/statistics.pyi | 8 +- mypy/typeshed/stdlib/subprocess.pyi | 559 +++++++++++++++++- mypy/typeshed/stdlib/sys.pyi | 8 +- mypy/typeshed/stdlib/tkinter/__init__.pyi | 178 +++++- mypy/typeshed/stdlib/types.pyi | 4 + mypy/typeshed/stdlib/typing.pyi | 65 +- mypy/typeshed/stdlib/typing_extensions.pyi | 20 +- mypy/typeshed/stdlib/urllib/error.pyi | 2 + mypy/typeshed/stdlib/warnings.pyi | 49 +- .../typeshed/stdlib/xml/etree/ElementTree.pyi | 2 +- mypy/typeshed/stdlib/zipfile.pyi | 2 + .../stubs/mypy-extensions/METADATA.toml | 1 - .../stubs/mypy-extensions/mypy_extensions.pyi | 17 +- test-data/unit/cmdline.test | 4 +- test-data/unit/pythoneval.test | 14 +- 36 files changed, 1263 insertions(+), 182 deletions(-) diff --git a/mypy/typeshed/stdlib/_ast.pyi b/mypy/typeshed/stdlib/_ast.pyi index cb13c74520813..1305b0c94d9bd 100644 --- a/mypy/typeshed/stdlib/_ast.pyi +++ b/mypy/typeshed/stdlib/_ast.pyi @@ -319,7 +319,7 @@ class FormattedValue(expr): if sys.version_info >= (3, 10): __match_args__ = ("value", "conversion", "format_spec") value: expr - conversion: int | None + conversion: int format_spec: expr | None class JoinedStr(expr): diff --git a/mypy/typeshed/stdlib/_csv.pyi b/mypy/typeshed/stdlib/_csv.pyi index ae9031df6e818..7d15365d3b026 100644 --- a/mypy/typeshed/stdlib/_csv.pyi +++ b/mypy/typeshed/stdlib/_csv.pyi @@ -1,5 +1,6 @@ +from _typeshed import SupportsWrite from collections.abc import Iterable, Iterator -from typing import Any, Protocol, Union +from typing import Any, Union from typing_extensions import Literal, TypeAlias __version__: str @@ -9,6 +10,10 @@ QUOTE_MINIMAL: Literal[0] QUOTE_NONE: Literal[3] QUOTE_NONNUMERIC: Literal[2] +# Ideally this would be `QUOTE_ALL | QUOTE_MINIMAL | QUOTE_NONE | QUOTE_NONNUMERIC` +# However, using literals in situations like these can cause false-positives (see #7258) +_QuotingType: TypeAlias = int + class Error(Exception): ... class Dialect: @@ -18,28 +23,63 @@ class Dialect: doublequote: bool skipinitialspace: bool lineterminator: str - quoting: int - strict: int + quoting: _QuotingType + strict: bool def __init__(self) -> None: ... _DialectLike: TypeAlias = Union[str, Dialect, type[Dialect]] class _reader(Iterator[list[str]]): - dialect: Dialect + @property + def dialect(self) -> Dialect: ... line_num: int def __next__(self) -> list[str]: ... class _writer: - dialect: Dialect + @property + def dialect(self) -> Dialect: ... def writerow(self, row: Iterable[Any]) -> Any: ... def writerows(self, rows: Iterable[Iterable[Any]]) -> None: ... -class _Writer(Protocol): - def write(self, __s: str) -> object: ... - -def writer(csvfile: _Writer, dialect: _DialectLike = ..., **fmtparams: Any) -> _writer: ... -def reader(csvfile: Iterable[str], dialect: _DialectLike = ..., **fmtparams: Any) -> _reader: ... -def register_dialect(name: str, dialect: Any = ..., **fmtparams: Any) -> None: ... +def writer( + csvfile: SupportsWrite[str], + dialect: _DialectLike = ..., + *, + delimiter: str = ..., + quotechar: str | None = ..., + escapechar: str | None = ..., + doublequote: bool = ..., + skipinitialspace: bool = ..., + lineterminator: str = ..., + quoting: _QuotingType = ..., + strict: bool = ..., +) -> _writer: ... +def reader( + csvfile: Iterable[str], + dialect: _DialectLike = ..., + *, + delimiter: str = ..., + quotechar: str | None = ..., + escapechar: str | None = ..., + doublequote: bool = ..., + skipinitialspace: bool = ..., + lineterminator: str = ..., + quoting: _QuotingType = ..., + strict: bool = ..., +) -> _reader: ... +def register_dialect( + name: str, + dialect: Any = ..., + *, + delimiter: str = ..., + quotechar: str | None = ..., + escapechar: str | None = ..., + doublequote: bool = ..., + skipinitialspace: bool = ..., + lineterminator: str = ..., + quoting: _QuotingType = ..., + strict: bool = ..., +) -> None: ... def unregister_dialect(name: str) -> None: ... def get_dialect(name: str) -> Dialect: ... def list_dialects() -> list[str]: ... diff --git a/mypy/typeshed/stdlib/_decimal.pyi b/mypy/typeshed/stdlib/_decimal.pyi index fdeca8f7c42fd..a259058ee163e 100644 --- a/mypy/typeshed/stdlib/_decimal.pyi +++ b/mypy/typeshed/stdlib/_decimal.pyi @@ -52,7 +52,23 @@ class FloatOperation(DecimalException, TypeError): ... def setcontext(__context: Context) -> None: ... def getcontext() -> Context: ... -def localcontext(ctx: Context | None = ...) -> _ContextManager: ... + +if sys.version_info >= (3, 11): + def localcontext( + ctx: Context | None = ..., + *, + prec: int | None = ..., + rounding: str | None = ..., + Emin: int | None = ..., + Emax: int | None = ..., + capitals: int | None = ..., + clamp: int | None = ..., + traps: dict[_TrapType, bool] | None = ..., + flags: dict[_TrapType, bool] | None = ..., + ) -> _ContextManager: ... + +else: + def localcontext(ctx: Context | None = ...) -> _ContextManager: ... class Decimal: def __new__(cls: type[Self], value: _DecimalNew = ..., context: Context | None = ...) -> Self: ... diff --git a/mypy/typeshed/stdlib/_socket.pyi b/mypy/typeshed/stdlib/_socket.pyi index 2366412050cdc..e49cdfbb983a2 100644 --- a/mypy/typeshed/stdlib/_socket.pyi +++ b/mypy/typeshed/stdlib/_socket.pyi @@ -256,6 +256,8 @@ SO_SNDLOWAT: int SO_SNDTIMEO: int SO_TYPE: int SO_USELOOPBACK: int +if sys.platform == "linux" and sys.version_info >= (3, 11): + SO_INCOMING_CPU: int TCP_CORK: int TCP_DEFER_ACCEPT: int TCP_FASTOPEN: int @@ -271,6 +273,8 @@ TCP_SYNCNT: int TCP_WINDOW_CLAMP: int if sys.version_info >= (3, 7): TCP_NOTSENT_LOWAT: int +if sys.version_info >= (3, 11) and sys.platform == "darwin": + TCP_CONNECTION_INFO: int # Specifically-documented constants diff --git a/mypy/typeshed/stdlib/_typeshed/__init__.pyi b/mypy/typeshed/stdlib/_typeshed/__init__.pyi index a80ea0702f772..d5e0c691e8c00 100644 --- a/mypy/typeshed/stdlib/_typeshed/__init__.pyi +++ b/mypy/typeshed/stdlib/_typeshed/__init__.pyi @@ -5,6 +5,7 @@ import array import ctypes import mmap +import pickle import sys from collections.abc import Awaitable, Container, Iterable, Set as AbstractSet from os import PathLike @@ -63,12 +64,27 @@ class SupportsAllComparisons(SupportsDunderLT, SupportsDunderGT, SupportsDunderL SupportsRichComparison: TypeAlias = SupportsDunderLT | SupportsDunderGT SupportsRichComparisonT = TypeVar("SupportsRichComparisonT", bound=SupportsRichComparison) # noqa: Y001 +# Dunder protocols + +class SupportsAdd(Protocol): + def __add__(self, __x: Any) -> Any: ... + class SupportsDivMod(Protocol[_T_contra, _T_co]): def __divmod__(self, __other: _T_contra) -> _T_co: ... class SupportsRDivMod(Protocol[_T_contra, _T_co]): def __rdivmod__(self, __other: _T_contra) -> _T_co: ... +# This protocol is generic over the iterator type, while Iterable is +# generic over the type that is iterated over. +class SupportsIter(Protocol[_T_co]): + def __iter__(self) -> _T_co: ... + +# This protocol is generic over the iterator type, while AsyncIterable is +# generic over the type that is iterated over. +class SupportsAiter(Protocol[_T_co]): + def __aiter__(self) -> _T_co: ... + class SupportsLenAndGetItem(Protocol[_T_co]): def __len__(self) -> int: ... def __getitem__(self, __k: int) -> _T_co: ... @@ -194,8 +210,13 @@ class SupportsWrite(Protocol[_T_contra]): ReadOnlyBuffer: TypeAlias = bytes # stable # Anything that implements the read-write buffer interface. # The buffer interface is defined purely on the C level, so we cannot define a normal Protocol -# for it. Instead we have to list the most common stdlib buffer classes in a Union. -WriteableBuffer: TypeAlias = bytearray | memoryview | array.array[Any] | mmap.mmap | ctypes._CData # stable +# for it (until PEP 688 is implemented). Instead we have to list the most common stdlib buffer classes in a Union. +if sys.version_info >= (3, 8): + WriteableBuffer: TypeAlias = ( + bytearray | memoryview | array.array[Any] | mmap.mmap | ctypes._CData | pickle.PickleBuffer + ) # stable +else: + WriteableBuffer: TypeAlias = bytearray | memoryview | array.array[Any] | mmap.mmap | ctypes._CData # stable # Same as _WriteableBuffer, but also includes read-only buffer types (like bytes). ReadableBuffer: TypeAlias = ReadOnlyBuffer | WriteableBuffer # stable diff --git a/mypy/typeshed/stdlib/asyncio/transports.pyi b/mypy/typeshed/stdlib/asyncio/transports.pyi index a8cd753c2af8f..7e17beb9f630a 100644 --- a/mypy/typeshed/stdlib/asyncio/transports.pyi +++ b/mypy/typeshed/stdlib/asyncio/transports.pyi @@ -28,9 +28,7 @@ class ReadTransport(BaseTransport): class WriteTransport(BaseTransport): def set_write_buffer_limits(self, high: int | None = ..., low: int | None = ...) -> None: ... def get_write_buffer_size(self) -> int: ... - if sys.version_info >= (3, 9): - def get_write_buffer_limits(self) -> tuple[int, int]: ... - + def get_write_buffer_limits(self) -> tuple[int, int]: ... def write(self, data: Any) -> None: ... def writelines(self, list_of_data: list[Any]) -> None: ... def write_eof(self) -> None: ... @@ -53,4 +51,6 @@ class SubprocessTransport(BaseTransport): class _FlowControlMixin(Transport): def __init__(self, extra: Mapping[Any, Any] | None = ..., loop: AbstractEventLoop | None = ...) -> None: ... + def set_write_buffer_limits(self, high: int | None = ..., low: int | None = ...) -> None: ... + def get_write_buffer_size(self) -> int: ... def get_write_buffer_limits(self) -> tuple[int, int]: ... diff --git a/mypy/typeshed/stdlib/builtins.pyi b/mypy/typeshed/stdlib/builtins.pyi index bf1e6cde2c089..d3d34c72fcfcc 100644 --- a/mypy/typeshed/stdlib/builtins.pyi +++ b/mypy/typeshed/stdlib/builtins.pyi @@ -11,8 +11,11 @@ from _typeshed import ( ReadableBuffer, Self, StrOrBytesPath, + SupportsAdd, + SupportsAiter, SupportsAnext, SupportsDivMod, + SupportsIter, SupportsKeysAndGetItem, SupportsLenAndGetItem, SupportsNext, @@ -71,12 +74,6 @@ _SupportsAnextT = TypeVar("_SupportsAnextT", bound=SupportsAnext[Any], covariant _AwaitableT = TypeVar("_AwaitableT", bound=Awaitable[Any]) _AwaitableT_co = TypeVar("_AwaitableT_co", bound=Awaitable[Any], covariant=True) -class _SupportsIter(Protocol[_T_co]): - def __iter__(self) -> _T_co: ... - -class _SupportsAiter(Protocol[_T_co]): - def __aiter__(self) -> _T_co: ... - class object: __doc__: str | None __dict__: dict[str, Any] @@ -122,7 +119,8 @@ class staticmethod(Generic[_R_co]): if sys.version_info >= (3, 10): __name__: str __qualname__: str - __wrapped__: Callable[..., _R_co] + @property + def __wrapped__(self) -> Callable[..., _R_co]: ... def __call__(self, *args: Any, **kwargs: Any) -> _R_co: ... class classmethod(Generic[_R_co]): @@ -135,7 +133,8 @@ class classmethod(Generic[_R_co]): if sys.version_info >= (3, 10): __name__: str __qualname__: str - __wrapped__: Callable[..., _R_co] + @property + def __wrapped__(self) -> Callable[..., _R_co]: ... class type: @property @@ -251,11 +250,9 @@ class int: def __rmod__(self, __x: int) -> int: ... def __rdivmod__(self, __x: int) -> tuple[int, int]: ... @overload - def __pow__(self, __x: int, __modulo: Literal[0]) -> NoReturn: ... - @overload - def __pow__(self, __x: int, __modulo: int) -> int: ... + def __pow__(self, __x: Literal[0]) -> Literal[1]: ... @overload - def __pow__(self, __x: Literal[0], __modulo: None = ...) -> Literal[1]: ... + def __pow__(self, __x: Literal[0], __modulo: None) -> Literal[1]: ... @overload def __pow__(self, __x: _PositiveInteger, __modulo: None = ...) -> int: ... @overload @@ -264,6 +261,10 @@ class int: # return type must be Any as `int | float` causes too many false-positive errors @overload def __pow__(self, __x: int, __modulo: None = ...) -> Any: ... + @overload + def __pow__(self, __x: int, __modulo: Literal[0]) -> NoReturn: ... + @overload + def __pow__(self, __x: int, __modulo: int) -> int: ... def __rpow__(self, __x: int, __mod: int | None = ...) -> Any: ... def __and__(self, __n: int) -> int: ... def __or__(self, __n: int) -> int: ... @@ -328,7 +329,12 @@ class float: def __rtruediv__(self, __x: float) -> float: ... def __rmod__(self, __x: float) -> float: ... def __rdivmod__(self, __x: float) -> tuple[float, float]: ... - # Returns complex if the argument is negative. + @overload + def __rpow__(self, __x: _PositiveInteger, __modulo: None = ...) -> float: ... + @overload + def __rpow__(self, __x: _NegativeInteger, __mod: None = ...) -> complex: ... + # Returning `complex` for the general case gives too many false-positive errors. + @overload def __rpow__(self, __x: float, __mod: None = ...) -> Any: ... def __getnewargs__(self) -> tuple[float]: ... def __trunc__(self) -> int: ... @@ -1092,7 +1098,7 @@ class _PathLike(Protocol[_AnyStr_co]): def __fspath__(self) -> _AnyStr_co: ... if sys.version_info >= (3, 10): - def aiter(__async_iterable: _SupportsAiter[_SupportsAnextT]) -> _SupportsAnextT: ... + def aiter(__async_iterable: SupportsAiter[_SupportsAnextT]) -> _SupportsAnextT: ... class _SupportsSynchronousAnext(Protocol[_AwaitableT_co]): def __anext__(self) -> _AwaitableT_co: ... @@ -1144,9 +1150,22 @@ def eval( ) -> Any: ... # Comment above regarding `eval` applies to `exec` as well -def exec( - __source: str | ReadableBuffer | CodeType, __globals: dict[str, Any] | None = ..., __locals: Mapping[str, object] | None = ... -) -> None: ... +if sys.version_info >= (3, 11): + def exec( + __source: str | ReadableBuffer | CodeType, + __globals: dict[str, Any] | None = ..., + __locals: Mapping[str, object] | None = ..., + *, + closure: tuple[_Cell, ...] | None = ..., + ) -> None: ... + +else: + def exec( + __source: str | ReadableBuffer | CodeType, + __globals: dict[str, Any] | None = ..., + __locals: Mapping[str, object] | None = ..., + ) -> None: ... + def exit(code: object = ...) -> NoReturn: ... class filter(Iterator[_T], Generic[_T]): @@ -1183,8 +1202,14 @@ def help(request: object = ...) -> None: ... def hex(__number: int | SupportsIndex) -> str: ... def id(__obj: object) -> int: ... def input(__prompt: object = ...) -> str: ... + +class _GetItemIterable(Protocol[_T_co]): + def __getitem__(self, __i: int) -> _T_co: ... + +@overload +def iter(__iterable: SupportsIter[_SupportsNextT]) -> _SupportsNextT: ... @overload -def iter(__iterable: _SupportsIter[_SupportsNextT]) -> _SupportsNextT: ... +def iter(__iterable: _GetItemIterable[_T]) -> Iterator[_T]: ... @overload def iter(__function: Callable[[], _T | None], __sentinel: None) -> Iterator[_T]: ... @overload @@ -1423,6 +1448,10 @@ if sys.version_info >= (3, 8): @overload def pow(base: int, exp: int, mod: None = ...) -> Any: ... @overload + def pow(base: _PositiveInteger, exp: float, mod: None = ...) -> float: ... + @overload + def pow(base: _NegativeInteger, exp: float, mod: None = ...) -> complex: ... + @overload def pow(base: float, exp: int, mod: None = ...) -> float: ... # float base & float exp could return float or complex # return type must be Any (same as complex base, complex exp), @@ -1456,6 +1485,10 @@ else: @overload def pow(__base: int, __exp: int, __mod: None = ...) -> Any: ... @overload + def pow(__base: _PositiveInteger, __exp: float, __mod: None = ...) -> float: ... + @overload + def pow(__base: _NegativeInteger, __exp: float, __mod: None = ...) -> complex: ... + @overload def pow(__base: float, __exp: int, __mod: None = ...) -> float: ... @overload def pow(__base: float, __exp: complex | _SupportsSomeKindOfPow, __mod: None = ...) -> Any: ... @@ -1501,11 +1534,8 @@ def sorted( @overload def sorted(__iterable: Iterable[_T], *, key: Callable[[_T], SupportsRichComparison], reverse: bool = ...) -> list[_T]: ... -class _SupportsSum(Protocol): - def __add__(self, __x: Any) -> Any: ... - -_SumT = TypeVar("_SumT", bound=_SupportsSum) -_SumS = TypeVar("_SumS", bound=_SupportsSum) +_SumT = TypeVar("_SumT", bound=SupportsAdd) +_SumS = TypeVar("_SumS", bound=SupportsAdd) @overload def sum(__iterable: Iterable[_SumT]) -> _SumT | Literal[0]: ... diff --git a/mypy/typeshed/stdlib/contextlib.pyi b/mypy/typeshed/stdlib/contextlib.pyi index c93eeac3b44f7..1b6ee4298174c 100644 --- a/mypy/typeshed/stdlib/contextlib.pyi +++ b/mypy/typeshed/stdlib/contextlib.pyi @@ -78,7 +78,7 @@ _F = TypeVar("_F", bound=Callable[..., Any]) _P = ParamSpec("_P") _ExitFunc: TypeAlias = Callable[[type[BaseException] | None, BaseException | None, TracebackType | None], bool | None] -_CM_EF = TypeVar("_CM_EF", AbstractContextManager[Any], _ExitFunc) +_CM_EF = TypeVar("_CM_EF", bound=AbstractContextManager[Any] | _ExitFunc) class ContextDecorator: def __call__(self, func: _F) -> _F: ... @@ -177,7 +177,7 @@ class ExitStack(AbstractContextManager[ExitStack]): if sys.version_info >= (3, 7): _ExitCoroFunc: TypeAlias = Callable[[type[BaseException] | None, BaseException | None, TracebackType | None], Awaitable[bool]] - _ACM_EF = TypeVar("_ACM_EF", AbstractAsyncContextManager[Any], _ExitCoroFunc) + _ACM_EF = TypeVar("_ACM_EF", bound=AbstractAsyncContextManager[Any] | _ExitCoroFunc) class AsyncExitStack(AbstractAsyncContextManager[AsyncExitStack]): def __init__(self) -> None: ... diff --git a/mypy/typeshed/stdlib/csv.pyi b/mypy/typeshed/stdlib/csv.pyi index dcb3f19bebe18..de69c71ad9412 100644 --- a/mypy/typeshed/stdlib/csv.pyi +++ b/mypy/typeshed/stdlib/csv.pyi @@ -1,4 +1,6 @@ import sys + +# actually csv.Dialect is a different class to _csv.Dialect at runtime, but for typing purposes, they're identical from _csv import ( QUOTE_ALL as QUOTE_ALL, QUOTE_MINIMAL as QUOTE_MINIMAL, @@ -8,6 +10,7 @@ from _csv import ( Error as Error, __version__ as __version__, _DialectLike, + _QuotingType, _reader, _writer, field_size_limit as field_size_limit, @@ -18,9 +21,10 @@ from _csv import ( unregister_dialect as unregister_dialect, writer as writer, ) -from _typeshed import Self +from _typeshed import Self, SupportsWrite from collections.abc import Collection, Iterable, Iterator, Mapping, Sequence from typing import Any, Generic, TypeVar, overload +from typing_extensions import Literal if sys.version_info >= (3, 8): from builtins import dict as _DictReadMapping @@ -59,7 +63,7 @@ class excel(Dialect): doublequote: bool skipinitialspace: bool lineterminator: str - quoting: int + quoting: _QuotingType class excel_tab(excel): delimiter: str @@ -70,7 +74,7 @@ class unix_dialect(Dialect): doublequote: bool skipinitialspace: bool lineterminator: str - quoting: int + quoting: _QuotingType class DictReader(Generic[_T], Iterator[_DictReadMapping[_T, str]]): fieldnames: Sequence[_T] | None @@ -87,8 +91,15 @@ class DictReader(Generic[_T], Iterator[_DictReadMapping[_T, str]]): restkey: str | None = ..., restval: str | None = ..., dialect: _DialectLike = ..., - *args: Any, - **kwds: Any, + *, + delimiter: str = ..., + quotechar: str | None = ..., + escapechar: str | None = ..., + doublequote: bool = ..., + skipinitialspace: bool = ..., + lineterminator: str = ..., + quoting: _QuotingType = ..., + strict: bool = ..., ) -> None: ... @overload def __init__( @@ -98,8 +109,15 @@ class DictReader(Generic[_T], Iterator[_DictReadMapping[_T, str]]): restkey: str | None = ..., restval: str | None = ..., dialect: _DialectLike = ..., - *args: Any, - **kwds: Any, + *, + delimiter: str = ..., + quotechar: str | None = ..., + escapechar: str | None = ..., + doublequote: bool = ..., + skipinitialspace: bool = ..., + lineterminator: str = ..., + quoting: _QuotingType = ..., + strict: bool = ..., ) -> None: ... def __iter__(self: Self) -> Self: ... def __next__(self) -> _DictReadMapping[_T, str]: ... @@ -107,17 +125,24 @@ class DictReader(Generic[_T], Iterator[_DictReadMapping[_T, str]]): class DictWriter(Generic[_T]): fieldnames: Collection[_T] restval: Any | None - extrasaction: str + extrasaction: Literal["raise", "ignore"] writer: _writer def __init__( self, - f: Any, + f: SupportsWrite[str], fieldnames: Collection[_T], restval: Any | None = ..., - extrasaction: str = ..., + extrasaction: Literal["raise", "ignore"] = ..., dialect: _DialectLike = ..., - *args: Any, - **kwds: Any, + *, + delimiter: str = ..., + quotechar: str | None = ..., + escapechar: str | None = ..., + doublequote: bool = ..., + skipinitialspace: bool = ..., + lineterminator: str = ..., + quoting: _QuotingType = ..., + strict: bool = ..., ) -> None: ... if sys.version_info >= (3, 8): def writeheader(self) -> Any: ... diff --git a/mypy/typeshed/stdlib/dataclasses.pyi b/mypy/typeshed/stdlib/dataclasses.pyi index f58c6f9f1460b..1cbf998dd3034 100644 --- a/mypy/typeshed/stdlib/dataclasses.pyi +++ b/mypy/typeshed/stdlib/dataclasses.pyi @@ -79,7 +79,23 @@ else: @overload def dataclass(_cls: None) -> Callable[[type[_T]], type[_T]]: ... -if sys.version_info >= (3, 10): +if sys.version_info >= (3, 11): + @overload + def dataclass( + *, + init: bool = ..., + repr: bool = ..., + eq: bool = ..., + order: bool = ..., + unsafe_hash: bool = ..., + frozen: bool = ..., + match_args: bool = ..., + kw_only: bool = ..., + slots: bool = ..., + weakref_slot: bool = ..., + ) -> Callable[[type[_T]], type[_T]]: ... + +elif sys.version_info >= (3, 10): @overload def dataclass( *, @@ -227,7 +243,7 @@ class InitVar(Generic[_T]): if sys.version_info >= (3, 10): def make_dataclass( cls_name: str, - fields: Iterable[str | tuple[str, type] | tuple[str, type, Field[Any]]], + fields: Iterable[str | tuple[str, type] | tuple[str, type, Any]], *, bases: tuple[type, ...] = ..., namespace: dict[str, Any] | None = ..., @@ -245,7 +261,7 @@ if sys.version_info >= (3, 10): else: def make_dataclass( cls_name: str, - fields: Iterable[str | tuple[str, type] | tuple[str, type, Field[Any]]], + fields: Iterable[str | tuple[str, type] | tuple[str, type, Any]], *, bases: tuple[type, ...] = ..., namespace: dict[str, Any] | None = ..., diff --git a/mypy/typeshed/stdlib/datetime.pyi b/mypy/typeshed/stdlib/datetime.pyi index 113c679743fd6..e2a359d0a536e 100644 --- a/mypy/typeshed/stdlib/datetime.pyi +++ b/mypy/typeshed/stdlib/datetime.pyi @@ -4,7 +4,9 @@ from time import struct_time from typing import ClassVar, NamedTuple, NoReturn, SupportsAbs, TypeVar, overload from typing_extensions import Literal, TypeAlias, final -if sys.version_info >= (3, 9): +if sys.version_info >= (3, 11): + __all__ = ("date", "datetime", "time", "timedelta", "timezone", "tzinfo", "MINYEAR", "MAXYEAR", "UTC") +elif sys.version_info >= (3, 9): __all__ = ("date", "datetime", "time", "timedelta", "timezone", "tzinfo", "MINYEAR", "MAXYEAR") _D = TypeVar("_D", bound=date) @@ -29,6 +31,9 @@ class timezone(tzinfo): def __init__(self, offset: timedelta, name: str = ...) -> None: ... def __hash__(self) -> int: ... +if sys.version_info >= (3, 11): + UTC: timezone + if sys.version_info >= (3, 9): class _IsoCalendarDate(NamedTuple): year: int diff --git a/mypy/typeshed/stdlib/enum.pyi b/mypy/typeshed/stdlib/enum.pyi index a7c84c5b1c0d4..9ebeba37ab711 100644 --- a/mypy/typeshed/stdlib/enum.pyi +++ b/mypy/typeshed/stdlib/enum.pyi @@ -4,7 +4,7 @@ from _typeshed import Self from abc import ABCMeta from builtins import property as _builtins_property from collections.abc import Iterable, Iterator, Mapping -from typing import Any, TypeVar, overload +from typing import Any, Generic, TypeVar, overload from typing_extensions import Literal, TypeAlias if sys.version_info >= (3, 11): @@ -21,6 +21,8 @@ if sys.version_info >= (3, 11): "unique", "property", "verify", + "member", + "nonmember", "FlagBoundary", "STRICT", "CONFORM", @@ -54,6 +56,15 @@ _EnumerationT = TypeVar("_EnumerationT", bound=type[Enum]) # _EnumNames: TypeAlias = str | Iterable[str] | Iterable[Iterable[str | Any]] | Mapping[str, Any] +if sys.version_info >= (3, 11): + class nonmember(Generic[_EnumMemberT]): + value: _EnumMemberT + def __init__(self, value: _EnumMemberT) -> None: ... + + class member(Generic[_EnumMemberT]): + value: _EnumMemberT + def __init__(self, value: _EnumMemberT) -> None: ... + class _EnumDict(dict[str, Any]): def __init__(self) -> None: ... def __setitem__(self, key: str, value: Any) -> None: ... @@ -155,7 +166,12 @@ class Enum(metaclass=EnumMeta): def _missing_(cls, value: object) -> Any: ... @staticmethod def _generate_next_value_(name: str, start: int, count: int, last_values: list[Any]) -> Any: ... - def __new__(cls: type[Self], value: Any) -> Self: ... + # It's not true that `__new__` will accept any argument type, + # so ideally we'd use `Any` to indicate that the argument type is inexpressible. + # However, using `Any` causes too many false-positives for those using mypy's `--disallow-any-expr` + # (see #7752, #2539, mypy/#5788), + # and in practice using `object` here has the same effect as using `Any`. + def __new__(cls: type[Self], value: object) -> Self: ... def __dir__(self) -> list[str]: ... def __format__(self, format_spec: str) -> str: ... def __hash__(self) -> Any: ... diff --git a/mypy/typeshed/stdlib/http/__init__.pyi b/mypy/typeshed/stdlib/http/__init__.pyi index 822cc0932939c..10c1d5926e845 100644 --- a/mypy/typeshed/stdlib/http/__init__.pyi +++ b/mypy/typeshed/stdlib/http/__init__.pyi @@ -2,7 +2,13 @@ import sys from enum import IntEnum from typing_extensions import Literal -__all__ = ["HTTPStatus"] +if sys.version_info >= (3, 11): + from enum import StrEnum + +if sys.version_info >= (3, 11): + __all__ = ["HTTPStatus", "HTTPMethod"] +else: + __all__ = ["HTTPStatus"] class HTTPStatus(IntEnum): @property @@ -74,3 +80,17 @@ class HTTPStatus(IntEnum): EARLY_HINTS: Literal[103] IM_A_TEAPOT: Literal[418] TOO_EARLY: Literal[425] + +if sys.version_info >= (3, 11): + class HTTPMethod(StrEnum): + @property + def description(self) -> str: ... + CONNECT: str + DELETE: str + GET: str + HEAD: str + OPTIONS: str + PATCH: str + POST: str + PUT: str + TRACE: str diff --git a/mypy/typeshed/stdlib/inspect.pyi b/mypy/typeshed/stdlib/inspect.pyi index 7ca9c9bb3fc48..38d928f43c9af 100644 --- a/mypy/typeshed/stdlib/inspect.pyi +++ b/mypy/typeshed/stdlib/inspect.pyi @@ -1,3 +1,4 @@ +import dis import enum import sys import types @@ -459,20 +460,64 @@ def unwrap(func: Callable[..., Any], *, stop: Callable[[Any], Any] | None = ...) # The interpreter stack # -class Traceback(NamedTuple): - filename: str - lineno: int - function: str - code_context: list[str] | None - index: int | None # type: ignore[assignment] - -class FrameInfo(NamedTuple): - frame: FrameType - filename: str - lineno: int - function: str - code_context: list[str] | None - index: int | None # type: ignore[assignment] +if sys.version_info >= (3, 11): + class _Traceback(NamedTuple): + filename: str + lineno: int + function: str + code_context: list[str] | None + index: int | None # type: ignore[assignment] + + class Traceback(_Traceback): + positions: dis.Positions | None + def __new__( + cls: type[Self], + filename: str, + lineno: int, + function: str, + code_context: list[str] | None, + index: int | None, + *, + positions: dis.Positions | None = ..., + ) -> Self: ... + + class _FrameInfo(NamedTuple): + frame: FrameType + filename: str + lineno: int + function: str + code_context: list[str] | None + index: int | None # type: ignore[assignment] + + class FrameInfo(_FrameInfo): + positions: dis.Positions | None + def __new__( + cls: type[Self], + frame: FrameType, + filename: str, + lineno: int, + function: str, + code_context: list[str] | None, + index: int | None, + *, + positions: dis.Positions | None = ..., + ) -> Self: ... + +else: + class Traceback(NamedTuple): + filename: str + lineno: int + function: str + code_context: list[str] | None + index: int | None # type: ignore[assignment] + + class FrameInfo(NamedTuple): + frame: FrameType + filename: str + lineno: int + function: str + code_context: list[str] | None + index: int | None # type: ignore[assignment] def getframeinfo(frame: FrameType | TracebackType, context: int = ...) -> Traceback: ... def getouterframes(frame: Any, context: int = ...) -> list[FrameInfo]: ... diff --git a/mypy/typeshed/stdlib/logging/__init__.pyi b/mypy/typeshed/stdlib/logging/__init__.pyi index edb15061a5886..6ad4cd4f94e76 100644 --- a/mypy/typeshed/stdlib/logging/__init__.pyi +++ b/mypy/typeshed/stdlib/logging/__init__.pyi @@ -408,7 +408,7 @@ class LogRecord: ) -> None: ... def getMessage(self) -> str: ... -_L = TypeVar("_L", Logger, LoggerAdapter[Logger], LoggerAdapter[Any]) +_L = TypeVar("_L", bound=Logger | LoggerAdapter[Any]) class LoggerAdapter(Generic[_L]): logger: _L diff --git a/mypy/typeshed/stdlib/multiprocessing/managers.pyi b/mypy/typeshed/stdlib/multiprocessing/managers.pyi index 234660cc4f806..b8d5ddda0f35e 100644 --- a/mypy/typeshed/stdlib/multiprocessing/managers.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/managers.pyi @@ -76,9 +76,21 @@ class Server: def accept_connection(self, c: Connection, name: str) -> None: ... class BaseManager: - def __init__( - self, address: Any | None = ..., authkey: bytes | None = ..., serializer: str = ..., ctx: BaseContext | None = ... - ) -> None: ... + if sys.version_info >= (3, 11): + def __init__( + self, + address: Any | None = ..., + authkey: bytes | None = ..., + serializer: str = ..., + ctx: BaseContext | None = ..., + *, + shutdown_timeout: float = ..., + ) -> None: ... + else: + def __init__( + self, address: Any | None = ..., authkey: bytes | None = ..., serializer: str = ..., ctx: BaseContext | None = ... + ) -> None: ... + def get_server(self) -> Server: ... def connect(self) -> None: ... def start(self, initializer: Callable[..., Any] | None = ..., initargs: Iterable[Any] = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/os/__init__.pyi b/mypy/typeshed/stdlib/os/__init__.pyi index 76c114591d323..2310de701d54b 100644 --- a/mypy/typeshed/stdlib/os/__init__.pyi +++ b/mypy/typeshed/stdlib/os/__init__.pyi @@ -605,6 +605,10 @@ def fstat(fd: int) -> stat_result: ... def ftruncate(__fd: int, __length: int) -> None: ... def fsync(fd: FileDescriptorLike) -> None: ... def isatty(__fd: int) -> bool: ... + +if sys.platform != "win32" and sys.version_info >= (3, 11): + def login_tty(__fd: int) -> None: ... + def lseek(__fd: int, __position: int, __how: int) -> int: ... def open(path: StrOrBytesPath, flags: int, mode: int = ..., *, dir_fd: int | None = ...) -> int: ... def pipe() -> tuple[int, int]: ... diff --git a/mypy/typeshed/stdlib/posix.pyi b/mypy/typeshed/stdlib/posix.pyi index 5dba5b36e3d2b..e248db397ab89 100644 --- a/mypy/typeshed/stdlib/posix.pyi +++ b/mypy/typeshed/stdlib/posix.pyi @@ -269,6 +269,9 @@ if sys.platform != "win32": if sys.version_info >= (3, 10): from os import RWF_APPEND as RWF_APPEND + if sys.version_info >= (3, 11): + from os import login_tty as login_tty + if sys.version_info >= (3, 9): from os import CLD_KILLED as CLD_KILLED, CLD_STOPPED as CLD_STOPPED, waitstatus_to_exitcode as waitstatus_to_exitcode diff --git a/mypy/typeshed/stdlib/re.pyi b/mypy/typeshed/stdlib/re.pyi index ff2a55fb4e616..2f4f3a3a0ed40 100644 --- a/mypy/typeshed/stdlib/re.pyi +++ b/mypy/typeshed/stdlib/re.pyi @@ -1,6 +1,7 @@ import enum import sre_compile import sys +from _typeshed import ReadableBuffer from collections.abc import Callable, Iterator from sre_constants import error as error from typing import Any, AnyStr, overload @@ -155,70 +156,67 @@ if sys.version_info < (3, 7): # undocumented _pattern_type: type -# Type-wise these overloads are unnecessary, they could also be modeled using +# Type-wise the compile() overloads are unnecessary, they could also be modeled using # unions in the parameter types. However mypy has a bug regarding TypeVar # constraints (https://github.com/python/mypy/issues/11880), # which limits us here because AnyStr is a constrained TypeVar. +# pattern arguments do *not* accept arbitrary buffers such as bytearray, +# because the pattern must be hashable. @overload def compile(pattern: AnyStr, flags: _FlagsType = ...) -> Pattern[AnyStr]: ... @overload def compile(pattern: Pattern[AnyStr], flags: _FlagsType = ...) -> Pattern[AnyStr]: ... @overload -def search(pattern: AnyStr, string: AnyStr, flags: _FlagsType = ...) -> Match[AnyStr] | None: ... +def search(pattern: str | Pattern[str], string: str, flags: _FlagsType = ...) -> Match[str] | None: ... @overload -def search(pattern: Pattern[AnyStr], string: AnyStr, flags: _FlagsType = ...) -> Match[AnyStr] | None: ... +def search(pattern: bytes | Pattern[bytes], string: ReadableBuffer, flags: _FlagsType = ...) -> Match[bytes] | None: ... @overload -def match(pattern: AnyStr, string: AnyStr, flags: _FlagsType = ...) -> Match[AnyStr] | None: ... +def match(pattern: str | Pattern[str], string: str, flags: _FlagsType = ...) -> Match[str] | None: ... @overload -def match(pattern: Pattern[AnyStr], string: AnyStr, flags: _FlagsType = ...) -> Match[AnyStr] | None: ... +def match(pattern: bytes | Pattern[bytes], string: ReadableBuffer, flags: _FlagsType = ...) -> Match[bytes] | None: ... @overload -def fullmatch(pattern: AnyStr, string: AnyStr, flags: _FlagsType = ...) -> Match[AnyStr] | None: ... +def fullmatch(pattern: str | Pattern[str], string: str, flags: _FlagsType = ...) -> Match[str] | None: ... @overload -def fullmatch(pattern: Pattern[AnyStr], string: AnyStr, flags: _FlagsType = ...) -> Match[AnyStr] | None: ... +def fullmatch(pattern: bytes | Pattern[bytes], string: ReadableBuffer, flags: _FlagsType = ...) -> Match[bytes] | None: ... @overload -def split(pattern: AnyStr, string: AnyStr, maxsplit: int = ..., flags: _FlagsType = ...) -> list[AnyStr | Any]: ... +def split(pattern: str | Pattern[str], string: str, maxsplit: int = ..., flags: _FlagsType = ...) -> list[str | Any]: ... @overload -def split(pattern: Pattern[AnyStr], string: AnyStr, maxsplit: int = ..., flags: _FlagsType = ...) -> list[AnyStr | Any]: ... +def split( + pattern: bytes | Pattern[bytes], string: ReadableBuffer, maxsplit: int = ..., flags: _FlagsType = ... +) -> list[bytes | Any]: ... @overload -def findall(pattern: AnyStr, string: AnyStr, flags: _FlagsType = ...) -> list[Any]: ... +def findall(pattern: str | Pattern[str], string: str, flags: _FlagsType = ...) -> list[Any]: ... @overload -def findall(pattern: Pattern[AnyStr], string: AnyStr, flags: _FlagsType = ...) -> list[Any]: ... - -# Return an iterator yielding match objects over all non-overlapping matches -# for the RE pattern in string. The string is scanned left-to-right, and -# matches are returned in the order found. Empty matches are included in the -# result unless they touch the beginning of another match. -@overload -def finditer(pattern: AnyStr, string: AnyStr, flags: _FlagsType = ...) -> Iterator[Match[AnyStr]]: ... +def findall(pattern: bytes | Pattern[bytes], string: ReadableBuffer, flags: _FlagsType = ...) -> list[Any]: ... @overload -def finditer(pattern: Pattern[AnyStr], string: AnyStr, flags: _FlagsType = ...) -> Iterator[Match[AnyStr]]: ... +def finditer(pattern: str | Pattern[str], string: str, flags: _FlagsType = ...) -> Iterator[Match[str]]: ... @overload -def sub(pattern: AnyStr, repl: AnyStr, string: AnyStr, count: int = ..., flags: _FlagsType = ...) -> AnyStr: ... +def finditer(pattern: bytes | Pattern[bytes], string: ReadableBuffer, flags: _FlagsType = ...) -> Iterator[Match[bytes]]: ... @overload def sub( - pattern: AnyStr, repl: Callable[[Match[AnyStr]], AnyStr], string: AnyStr, count: int = ..., flags: _FlagsType = ... -) -> AnyStr: ... -@overload -def sub(pattern: Pattern[AnyStr], repl: AnyStr, string: AnyStr, count: int = ..., flags: _FlagsType = ...) -> AnyStr: ... + pattern: str | Pattern[str], repl: str | Callable[[Match[str]], str], string: str, count: int = ..., flags: _FlagsType = ... +) -> str: ... @overload def sub( - pattern: Pattern[AnyStr], repl: Callable[[Match[AnyStr]], AnyStr], string: AnyStr, count: int = ..., flags: _FlagsType = ... -) -> AnyStr: ... -@overload -def subn(pattern: AnyStr, repl: AnyStr, string: AnyStr, count: int = ..., flags: _FlagsType = ...) -> tuple[AnyStr, int]: ... -@overload -def subn( - pattern: AnyStr, repl: Callable[[Match[AnyStr]], AnyStr], string: AnyStr, count: int = ..., flags: _FlagsType = ... -) -> tuple[AnyStr, int]: ... + pattern: bytes | Pattern[bytes], + repl: ReadableBuffer | Callable[[Match[bytes]], ReadableBuffer], + string: ReadableBuffer, + count: int = ..., + flags: _FlagsType = ..., +) -> bytes: ... @overload def subn( - pattern: Pattern[AnyStr], repl: AnyStr, string: AnyStr, count: int = ..., flags: _FlagsType = ... -) -> tuple[AnyStr, int]: ... + pattern: str | Pattern[str], repl: str | Callable[[Match[str]], str], string: str, count: int = ..., flags: _FlagsType = ... +) -> tuple[str, int]: ... @overload def subn( - pattern: Pattern[AnyStr], repl: Callable[[Match[AnyStr]], AnyStr], string: AnyStr, count: int = ..., flags: _FlagsType = ... -) -> tuple[AnyStr, int]: ... + pattern: bytes | Pattern[bytes], + repl: ReadableBuffer | Callable[[Match[bytes]], ReadableBuffer], + string: ReadableBuffer, + count: int = ..., + flags: _FlagsType = ..., +) -> tuple[bytes, int]: ... def escape(pattern: AnyStr) -> AnyStr: ... def purge() -> None: ... def template(pattern: AnyStr | Pattern[AnyStr], flags: _FlagsType = ...) -> Pattern[AnyStr]: ... diff --git a/mypy/typeshed/stdlib/socket.pyi b/mypy/typeshed/stdlib/socket.pyi index 7801940f8564b..4f8ec07ccc955 100644 --- a/mypy/typeshed/stdlib/socket.pyi +++ b/mypy/typeshed/stdlib/socket.pyi @@ -366,6 +366,8 @@ if sys.platform == "linux" and sys.version_info >= (3, 9): ) if sys.platform == "linux" and sys.version_info >= (3, 10): from _socket import IPPROTO_MPTCP as IPPROTO_MPTCP +if sys.platform == "linux" and sys.version_info >= (3, 11): + from _socket import SO_INCOMING_CPU as SO_INCOMING_CPU if sys.platform == "win32": from _socket import ( RCVALL_IPLEVEL as RCVALL_IPLEVEL, @@ -605,11 +607,22 @@ class SocketIO(RawIOBase): def mode(self) -> Literal["rb", "wb", "rwb"]: ... def getfqdn(name: str = ...) -> str: ... -def create_connection( - address: tuple[str | None, int], - timeout: float | None = ..., # noqa: F811 - source_address: tuple[bytearray | bytes | str, int] | None = ..., -) -> socket: ... + +if sys.version_info >= (3, 11): + def create_connection( + address: tuple[str | None, int], + timeout: float | None = ..., # noqa: F811 + source_address: tuple[bytearray | bytes | str, int] | None = ..., + *, + all_errors: bool = ..., + ) -> socket: ... + +else: + def create_connection( + address: tuple[str | None, int], + timeout: float | None = ..., # noqa: F811 + source_address: tuple[bytearray | bytes | str, int] | None = ..., + ) -> socket: ... if sys.version_info >= (3, 8): def has_dualstack_ipv6() -> bool: ... diff --git a/mypy/typeshed/stdlib/sqlite3/dbapi2.pyi b/mypy/typeshed/stdlib/sqlite3/dbapi2.pyi index 87e843c5fb266..a6ccc9977c1ce 100644 --- a/mypy/typeshed/stdlib/sqlite3/dbapi2.pyi +++ b/mypy/typeshed/stdlib/sqlite3/dbapi2.pyi @@ -460,3 +460,5 @@ if sys.version_info >= (3, 11): def __len__(self) -> int: ... def __enter__(self: Self) -> Self: ... def __exit__(self, __typ: object, __val: object, __tb: object) -> Literal[False]: ... + def __getitem__(self, __item: SupportsIndex | slice) -> int: ... + def __setitem__(self, __item: SupportsIndex | slice, __value: int) -> None: ... diff --git a/mypy/typeshed/stdlib/statistics.pyi b/mypy/typeshed/stdlib/statistics.pyi index 540ccfcaaa8cf..e6c3d8f35bc63 100644 --- a/mypy/typeshed/stdlib/statistics.pyi +++ b/mypy/typeshed/stdlib/statistics.pyi @@ -94,7 +94,13 @@ else: def median(data: Iterable[_NumberT]) -> _NumberT: ... def median_low(data: Iterable[SupportsRichComparisonT]) -> SupportsRichComparisonT: ... def median_high(data: Iterable[SupportsRichComparisonT]) -> SupportsRichComparisonT: ... -def median_grouped(data: Iterable[_NumberT], interval: _NumberT = ...) -> _NumberT: ... + +if sys.version_info >= (3, 11): + def median_grouped(data: Iterable[SupportsFloat], interval: SupportsFloat = ...) -> float: ... + +else: + def median_grouped(data: Iterable[_NumberT], interval: _NumberT = ...) -> _NumberT | float: ... + def mode(data: Iterable[_HashableT]) -> _HashableT: ... if sys.version_info >= (3, 8): diff --git a/mypy/typeshed/stdlib/subprocess.pyi b/mypy/typeshed/stdlib/subprocess.pyi index 98bbf7d33f904..83178e15d9e83 100644 --- a/mypy/typeshed/stdlib/subprocess.pyi +++ b/mypy/typeshed/stdlib/subprocess.pyi @@ -118,6 +118,12 @@ else: _T = TypeVar("_T") +# These two are private but documented +if sys.version_info >= (3, 11): + _USE_VFORK: bool +if sys.version_info >= (3, 8): + _USE_POSIX_SPAWN: bool + class CompletedProcess(Generic[_T]): # morally: _CMD args: Any @@ -792,13 +798,562 @@ class Popen(Generic[AnyStr]): stdout: IO[AnyStr] | None stderr: IO[AnyStr] | None pid: int - returncode: int + returncode: int | Any universal_newlines: bool # Technically it is wrong that Popen provides __new__ instead of __init__ # but this shouldn't come up hopefully? - if sys.version_info >= (3, 7): + if sys.version_info >= (3, 11): + # process_group is added in 3.11 + @overload + def __new__( + cls, + args: _CMD, + bufsize: int = ..., + executable: StrOrBytesPath | None = ..., + stdin: _FILE | None = ..., + stdout: _FILE | None = ..., + stderr: _FILE | None = ..., + preexec_fn: Callable[[], Any] | None = ..., + close_fds: bool = ..., + shell: bool = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., + universal_newlines: bool = ..., + startupinfo: Any | None = ..., + creationflags: int = ..., + restore_signals: bool = ..., + start_new_session: bool = ..., + pass_fds: Any = ..., + *, + text: bool | None = ..., + encoding: str, + errors: str | None = ..., + user: str | int | None = ..., + group: str | int | None = ..., + extra_groups: Iterable[str | int] | None = ..., + umask: int = ..., + pipesize: int = ..., + process_group: int | None = ..., + ) -> Popen[str]: ... + @overload + def __new__( + cls, + args: _CMD, + bufsize: int = ..., + executable: StrOrBytesPath | None = ..., + stdin: _FILE | None = ..., + stdout: _FILE | None = ..., + stderr: _FILE | None = ..., + preexec_fn: Callable[[], Any] | None = ..., + close_fds: bool = ..., + shell: bool = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., + universal_newlines: bool = ..., + startupinfo: Any | None = ..., + creationflags: int = ..., + restore_signals: bool = ..., + start_new_session: bool = ..., + pass_fds: Any = ..., + *, + text: bool | None = ..., + encoding: str | None = ..., + errors: str, + user: str | int | None = ..., + group: str | int | None = ..., + extra_groups: Iterable[str | int] | None = ..., + umask: int = ..., + pipesize: int = ..., + process_group: int | None = ..., + ) -> Popen[str]: ... + @overload + def __new__( + cls, + args: _CMD, + bufsize: int = ..., + executable: StrOrBytesPath | None = ..., + stdin: _FILE | None = ..., + stdout: _FILE | None = ..., + stderr: _FILE | None = ..., + preexec_fn: Callable[[], Any] | None = ..., + close_fds: bool = ..., + shell: bool = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., + *, + universal_newlines: Literal[True], + startupinfo: Any | None = ..., + creationflags: int = ..., + restore_signals: bool = ..., + start_new_session: bool = ..., + pass_fds: Any = ..., + # where the *real* keyword only args start + text: bool | None = ..., + encoding: str | None = ..., + errors: str | None = ..., + user: str | int | None = ..., + group: str | int | None = ..., + extra_groups: Iterable[str | int] | None = ..., + umask: int = ..., + pipesize: int = ..., + process_group: int | None = ..., + ) -> Popen[str]: ... + @overload + def __new__( + cls, + args: _CMD, + bufsize: int = ..., + executable: StrOrBytesPath | None = ..., + stdin: _FILE | None = ..., + stdout: _FILE | None = ..., + stderr: _FILE | None = ..., + preexec_fn: Callable[[], Any] | None = ..., + close_fds: bool = ..., + shell: bool = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., + universal_newlines: bool = ..., + startupinfo: Any | None = ..., + creationflags: int = ..., + restore_signals: bool = ..., + start_new_session: bool = ..., + pass_fds: Any = ..., + *, + text: Literal[True], + encoding: str | None = ..., + errors: str | None = ..., + user: str | int | None = ..., + group: str | int | None = ..., + extra_groups: Iterable[str | int] | None = ..., + umask: int = ..., + pipesize: int = ..., + process_group: int | None = ..., + ) -> Popen[str]: ... + @overload + def __new__( + cls, + args: _CMD, + bufsize: int = ..., + executable: StrOrBytesPath | None = ..., + stdin: _FILE | None = ..., + stdout: _FILE | None = ..., + stderr: _FILE | None = ..., + preexec_fn: Callable[[], Any] | None = ..., + close_fds: bool = ..., + shell: bool = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., + universal_newlines: Literal[False] = ..., + startupinfo: Any | None = ..., + creationflags: int = ..., + restore_signals: bool = ..., + start_new_session: bool = ..., + pass_fds: Any = ..., + *, + text: Literal[None, False] = ..., + encoding: None = ..., + errors: None = ..., + user: str | int | None = ..., + group: str | int | None = ..., + extra_groups: Iterable[str | int] | None = ..., + umask: int = ..., + pipesize: int = ..., + process_group: int | None = ..., + ) -> Popen[bytes]: ... + @overload + def __new__( + cls, + args: _CMD, + bufsize: int = ..., + executable: StrOrBytesPath | None = ..., + stdin: _FILE | None = ..., + stdout: _FILE | None = ..., + stderr: _FILE | None = ..., + preexec_fn: Callable[[], Any] | None = ..., + close_fds: bool = ..., + shell: bool = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., + universal_newlines: bool = ..., + startupinfo: Any | None = ..., + creationflags: int = ..., + restore_signals: bool = ..., + start_new_session: bool = ..., + pass_fds: Any = ..., + *, + text: bool | None = ..., + encoding: str | None = ..., + errors: str | None = ..., + user: str | int | None = ..., + group: str | int | None = ..., + extra_groups: Iterable[str | int] | None = ..., + umask: int = ..., + pipesize: int = ..., + process_group: int | None = ..., + ) -> Popen[Any]: ... + elif sys.version_info >= (3, 10): + # pipesize is added in 3.10 + @overload + def __new__( + cls, + args: _CMD, + bufsize: int = ..., + executable: StrOrBytesPath | None = ..., + stdin: _FILE | None = ..., + stdout: _FILE | None = ..., + stderr: _FILE | None = ..., + preexec_fn: Callable[[], Any] | None = ..., + close_fds: bool = ..., + shell: bool = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., + universal_newlines: bool = ..., + startupinfo: Any | None = ..., + creationflags: int = ..., + restore_signals: bool = ..., + start_new_session: bool = ..., + pass_fds: Any = ..., + *, + text: bool | None = ..., + encoding: str, + errors: str | None = ..., + user: str | int | None = ..., + group: str | int | None = ..., + extra_groups: Iterable[str | int] | None = ..., + umask: int = ..., + pipesize: int = ..., + ) -> Popen[str]: ... + @overload + def __new__( + cls, + args: _CMD, + bufsize: int = ..., + executable: StrOrBytesPath | None = ..., + stdin: _FILE | None = ..., + stdout: _FILE | None = ..., + stderr: _FILE | None = ..., + preexec_fn: Callable[[], Any] | None = ..., + close_fds: bool = ..., + shell: bool = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., + universal_newlines: bool = ..., + startupinfo: Any | None = ..., + creationflags: int = ..., + restore_signals: bool = ..., + start_new_session: bool = ..., + pass_fds: Any = ..., + *, + text: bool | None = ..., + encoding: str | None = ..., + errors: str, + user: str | int | None = ..., + group: str | int | None = ..., + extra_groups: Iterable[str | int] | None = ..., + umask: int = ..., + pipesize: int = ..., + ) -> Popen[str]: ... + @overload + def __new__( + cls, + args: _CMD, + bufsize: int = ..., + executable: StrOrBytesPath | None = ..., + stdin: _FILE | None = ..., + stdout: _FILE | None = ..., + stderr: _FILE | None = ..., + preexec_fn: Callable[[], Any] | None = ..., + close_fds: bool = ..., + shell: bool = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., + *, + universal_newlines: Literal[True], + startupinfo: Any | None = ..., + creationflags: int = ..., + restore_signals: bool = ..., + start_new_session: bool = ..., + pass_fds: Any = ..., + # where the *real* keyword only args start + text: bool | None = ..., + encoding: str | None = ..., + errors: str | None = ..., + user: str | int | None = ..., + group: str | int | None = ..., + extra_groups: Iterable[str | int] | None = ..., + umask: int = ..., + pipesize: int = ..., + ) -> Popen[str]: ... + @overload + def __new__( + cls, + args: _CMD, + bufsize: int = ..., + executable: StrOrBytesPath | None = ..., + stdin: _FILE | None = ..., + stdout: _FILE | None = ..., + stderr: _FILE | None = ..., + preexec_fn: Callable[[], Any] | None = ..., + close_fds: bool = ..., + shell: bool = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., + universal_newlines: bool = ..., + startupinfo: Any | None = ..., + creationflags: int = ..., + restore_signals: bool = ..., + start_new_session: bool = ..., + pass_fds: Any = ..., + *, + text: Literal[True], + encoding: str | None = ..., + errors: str | None = ..., + user: str | int | None = ..., + group: str | int | None = ..., + extra_groups: Iterable[str | int] | None = ..., + umask: int = ..., + pipesize: int = ..., + ) -> Popen[str]: ... + @overload + def __new__( + cls, + args: _CMD, + bufsize: int = ..., + executable: StrOrBytesPath | None = ..., + stdin: _FILE | None = ..., + stdout: _FILE | None = ..., + stderr: _FILE | None = ..., + preexec_fn: Callable[[], Any] | None = ..., + close_fds: bool = ..., + shell: bool = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., + universal_newlines: Literal[False] = ..., + startupinfo: Any | None = ..., + creationflags: int = ..., + restore_signals: bool = ..., + start_new_session: bool = ..., + pass_fds: Any = ..., + *, + text: Literal[None, False] = ..., + encoding: None = ..., + errors: None = ..., + user: str | int | None = ..., + group: str | int | None = ..., + extra_groups: Iterable[str | int] | None = ..., + umask: int = ..., + pipesize: int = ..., + ) -> Popen[bytes]: ... + @overload + def __new__( + cls, + args: _CMD, + bufsize: int = ..., + executable: StrOrBytesPath | None = ..., + stdin: _FILE | None = ..., + stdout: _FILE | None = ..., + stderr: _FILE | None = ..., + preexec_fn: Callable[[], Any] | None = ..., + close_fds: bool = ..., + shell: bool = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., + universal_newlines: bool = ..., + startupinfo: Any | None = ..., + creationflags: int = ..., + restore_signals: bool = ..., + start_new_session: bool = ..., + pass_fds: Any = ..., + *, + text: bool | None = ..., + encoding: str | None = ..., + errors: str | None = ..., + user: str | int | None = ..., + group: str | int | None = ..., + extra_groups: Iterable[str | int] | None = ..., + umask: int = ..., + pipesize: int = ..., + ) -> Popen[Any]: ... + elif sys.version_info >= (3, 9): + # user, group, extra_groups, umask were added in 3.9 + @overload + def __new__( + cls, + args: _CMD, + bufsize: int = ..., + executable: StrOrBytesPath | None = ..., + stdin: _FILE | None = ..., + stdout: _FILE | None = ..., + stderr: _FILE | None = ..., + preexec_fn: Callable[[], Any] | None = ..., + close_fds: bool = ..., + shell: bool = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., + universal_newlines: bool = ..., + startupinfo: Any | None = ..., + creationflags: int = ..., + restore_signals: bool = ..., + start_new_session: bool = ..., + pass_fds: Any = ..., + *, + text: bool | None = ..., + encoding: str, + errors: str | None = ..., + user: str | int | None = ..., + group: str | int | None = ..., + extra_groups: Iterable[str | int] | None = ..., + umask: int = ..., + ) -> Popen[str]: ... + @overload + def __new__( + cls, + args: _CMD, + bufsize: int = ..., + executable: StrOrBytesPath | None = ..., + stdin: _FILE | None = ..., + stdout: _FILE | None = ..., + stderr: _FILE | None = ..., + preexec_fn: Callable[[], Any] | None = ..., + close_fds: bool = ..., + shell: bool = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., + universal_newlines: bool = ..., + startupinfo: Any | None = ..., + creationflags: int = ..., + restore_signals: bool = ..., + start_new_session: bool = ..., + pass_fds: Any = ..., + *, + text: bool | None = ..., + encoding: str | None = ..., + errors: str, + user: str | int | None = ..., + group: str | int | None = ..., + extra_groups: Iterable[str | int] | None = ..., + umask: int = ..., + ) -> Popen[str]: ... + @overload + def __new__( + cls, + args: _CMD, + bufsize: int = ..., + executable: StrOrBytesPath | None = ..., + stdin: _FILE | None = ..., + stdout: _FILE | None = ..., + stderr: _FILE | None = ..., + preexec_fn: Callable[[], Any] | None = ..., + close_fds: bool = ..., + shell: bool = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., + *, + universal_newlines: Literal[True], + startupinfo: Any | None = ..., + creationflags: int = ..., + restore_signals: bool = ..., + start_new_session: bool = ..., + pass_fds: Any = ..., + # where the *real* keyword only args start + text: bool | None = ..., + encoding: str | None = ..., + errors: str | None = ..., + user: str | int | None = ..., + group: str | int | None = ..., + extra_groups: Iterable[str | int] | None = ..., + umask: int = ..., + ) -> Popen[str]: ... + @overload + def __new__( + cls, + args: _CMD, + bufsize: int = ..., + executable: StrOrBytesPath | None = ..., + stdin: _FILE | None = ..., + stdout: _FILE | None = ..., + stderr: _FILE | None = ..., + preexec_fn: Callable[[], Any] | None = ..., + close_fds: bool = ..., + shell: bool = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., + universal_newlines: bool = ..., + startupinfo: Any | None = ..., + creationflags: int = ..., + restore_signals: bool = ..., + start_new_session: bool = ..., + pass_fds: Any = ..., + *, + text: Literal[True], + encoding: str | None = ..., + errors: str | None = ..., + user: str | int | None = ..., + group: str | int | None = ..., + extra_groups: Iterable[str | int] | None = ..., + umask: int = ..., + ) -> Popen[str]: ... + @overload + def __new__( + cls, + args: _CMD, + bufsize: int = ..., + executable: StrOrBytesPath | None = ..., + stdin: _FILE | None = ..., + stdout: _FILE | None = ..., + stderr: _FILE | None = ..., + preexec_fn: Callable[[], Any] | None = ..., + close_fds: bool = ..., + shell: bool = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., + universal_newlines: Literal[False] = ..., + startupinfo: Any | None = ..., + creationflags: int = ..., + restore_signals: bool = ..., + start_new_session: bool = ..., + pass_fds: Any = ..., + *, + text: Literal[None, False] = ..., + encoding: None = ..., + errors: None = ..., + user: str | int | None = ..., + group: str | int | None = ..., + extra_groups: Iterable[str | int] | None = ..., + umask: int = ..., + ) -> Popen[bytes]: ... + @overload + def __new__( + cls, + args: _CMD, + bufsize: int = ..., + executable: StrOrBytesPath | None = ..., + stdin: _FILE | None = ..., + stdout: _FILE | None = ..., + stderr: _FILE | None = ..., + preexec_fn: Callable[[], Any] | None = ..., + close_fds: bool = ..., + shell: bool = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., + universal_newlines: bool = ..., + startupinfo: Any | None = ..., + creationflags: int = ..., + restore_signals: bool = ..., + start_new_session: bool = ..., + pass_fds: Any = ..., + *, + text: bool | None = ..., + encoding: str | None = ..., + errors: str | None = ..., + user: str | int | None = ..., + group: str | int | None = ..., + extra_groups: Iterable[str | int] | None = ..., + umask: int = ..., + ) -> Popen[Any]: ... + elif sys.version_info >= (3, 7): # text is added in 3.7 @overload def __new__( diff --git a/mypy/typeshed/stdlib/sys.pyi b/mypy/typeshed/stdlib/sys.pyi index 92b806e044209..4e24cbd167d93 100644 --- a/mypy/typeshed/stdlib/sys.pyi +++ b/mypy/typeshed/stdlib/sys.pyi @@ -122,6 +122,9 @@ class _flags(_uninstantiable_structseq, _FlagTuple): if sys.version_info >= (3, 10): @property def warn_default_encoding(self) -> int: ... # undocumented + if sys.version_info >= (3, 11): + @property + def safe_path(self) -> bool: ... float_info: _float_info @@ -320,9 +323,8 @@ class _asyncgen_hooks(structseq[_AsyncgenHook], tuple[_AsyncgenHook, _AsyncgenHo def get_asyncgen_hooks() -> _asyncgen_hooks: ... def set_asyncgen_hooks(firstiter: _AsyncgenHook = ..., finalizer: _AsyncgenHook = ...) -> None: ... -if sys.version_info >= (3, 6): - if sys.platform == "win32": - def _enablelegacywindowsfsencoding() -> None: ... +if sys.platform == "win32": + def _enablelegacywindowsfsencoding() -> None: ... if sys.version_info >= (3, 7): def get_coroutine_origin_tracking_depth() -> int: ... diff --git a/mypy/typeshed/stdlib/tkinter/__init__.pyi b/mypy/typeshed/stdlib/tkinter/__init__.pyi index 66c52107067d4..582503971e159 100644 --- a/mypy/typeshed/stdlib/tkinter/__init__.pyi +++ b/mypy/typeshed/stdlib/tkinter/__init__.pyi @@ -6,7 +6,7 @@ from enum import Enum from tkinter.constants import * from tkinter.font import _FontDescription from types import TracebackType -from typing import Any, Generic, Protocol, TypeVar, Union, overload +from typing import Any, Generic, NamedTuple, Protocol, TypeVar, Union, overload from typing_extensions import Literal, TypeAlias, TypedDict if sys.version_info >= (3, 9): @@ -198,6 +198,14 @@ _ScreenUnits: TypeAlias = str | float # Often the right type instead of int. Ma _XYScrollCommand: TypeAlias = str | Callable[[float, float], Any] # -xscrollcommand and -yscrollcommand in 'options' manual page _TakeFocusValue: TypeAlias = Union[int, Literal[""], Callable[[str], bool | None]] # -takefocus in manual page named 'options' +if sys.version_info >= (3, 11): + class _VersionInfoType(NamedTuple): + major: int + minor: int + micro: int + releaselevel: str + serial: int + class EventType(str, Enum): Activate: str ButtonPress: str @@ -377,6 +385,9 @@ class Misc: def lower(self, belowThis: Any | None = ...) -> None: ... def tkraise(self, aboveThis: Any | None = ...) -> None: ... lift = tkraise + if sys.version_info >= (3, 11): + def info_patchlevel(self) -> _VersionInfoType: ... + def winfo_atom(self, name: str, displayof: Literal[0] | Misc | None = ...) -> int: ... def winfo_atomname(self, id: int, displayof: Literal[0] | Misc | None = ...) -> str: ... def winfo_cells(self) -> int: ... @@ -475,6 +486,8 @@ class Misc: def unbind_class(self, className: str, sequence: str) -> None: ... def mainloop(self, n: int = ...) -> None: ... def quit(self) -> None: ... + @property + def _windowingsystem(self) -> Literal["win32", "aqua", "x11"]: ... def nametowidget(self, name: str | Misc | _tkinter.Tcl_Obj) -> Any: ... def register( self, func: Callable[..., Any], subst: Callable[..., Sequence[Any]] | None = ..., needcleanup: int = ... @@ -1221,8 +1234,9 @@ class Canvas(Widget, XView, YView): def coords(self, __tagOrId: str | _CanvasItemId, __args: list[int] | list[float] | tuple[float, ...]) -> None: ... @overload def coords(self, __tagOrId: str | _CanvasItemId, __x1: float, __y1: float, *args: float) -> None: ... - # create_foo() methods accept coords as a list, a tuple, or as separate arguments. - # Keyword arguments should be the same in each pair of overloads. + # create_foo() methods accept coords as a list or tuple, or as separate arguments. + # Lists and tuples can be flat as in [1, 2, 3, 4], or nested as in [(1, 2), (3, 4)]. + # Keyword arguments should be the same in all overloads of each method. def create_arc(self, *args, **kw) -> _CanvasItemId: ... def create_bitmap(self, *args, **kw) -> _CanvasItemId: ... def create_image(self, *args, **kw) -> _CanvasItemId: ... @@ -1260,7 +1274,43 @@ class Canvas(Widget, XView, YView): @overload def create_line( self, - __coords: tuple[float, float, float, float] | list[int] | list[float], + __xy_pair_0: tuple[float, float], + __xy_pair_1: tuple[float, float], + *, + activedash: str | list[int] | tuple[int, ...] = ..., + activefill: _Color = ..., + activestipple: str = ..., + activewidth: _ScreenUnits = ..., + arrow: Literal["first", "last", "both"] = ..., + arrowshape: tuple[float, float, float] = ..., + capstyle: Literal["round", "projecting", "butt"] = ..., + dash: str | list[int] | tuple[int, ...] = ..., + dashoffset: _ScreenUnits = ..., + disableddash: str | list[int] | tuple[int, ...] = ..., + disabledfill: _Color = ..., + disabledstipple: _Bitmap = ..., + disabledwidth: _ScreenUnits = ..., + fill: _Color = ..., + joinstyle: Literal["round", "bevel", "miter"] = ..., + offset: _ScreenUnits = ..., + smooth: bool = ..., + splinesteps: float = ..., + state: Literal["normal", "active", "disabled"] = ..., + stipple: _Bitmap = ..., + tags: str | list[str] | tuple[str, ...] = ..., + width: _ScreenUnits = ..., + ) -> _CanvasItemId: ... + @overload + def create_line( + self, + __coords: ( + tuple[float, float, float, float] + | tuple[tuple[float, float], tuple[float, float]] + | list[int] + | list[float] + | list[tuple[int, int]] + | list[tuple[float, float]] + ), *, activedash: str | list[int] | tuple[int, ...] = ..., activefill: _Color = ..., @@ -1320,7 +1370,44 @@ class Canvas(Widget, XView, YView): @overload def create_oval( self, - __coords: tuple[float, float, float, float] | list[int] | list[float], + __xy_pair_0: tuple[float, float], + __xy_pair_1: tuple[float, float], + *, + activedash: str | list[int] | tuple[int, ...] = ..., + activefill: _Color = ..., + activeoutline: _Color = ..., + activeoutlinestipple: _Color = ..., + activestipple: str = ..., + activewidth: _ScreenUnits = ..., + dash: str | list[int] | tuple[int, ...] = ..., + dashoffset: _ScreenUnits = ..., + disableddash: str | list[int] | tuple[int, ...] = ..., + disabledfill: _Color = ..., + disabledoutline: _Color = ..., + disabledoutlinestipple: _Color = ..., + disabledstipple: _Bitmap = ..., + disabledwidth: _ScreenUnits = ..., + fill: _Color = ..., + offset: _ScreenUnits = ..., + outline: _Color = ..., + outlineoffset: _ScreenUnits = ..., + outlinestipple: _Bitmap = ..., + state: Literal["normal", "active", "disabled"] = ..., + stipple: _Bitmap = ..., + tags: str | list[str] | tuple[str, ...] = ..., + width: _ScreenUnits = ..., + ) -> _CanvasItemId: ... + @overload + def create_oval( + self, + __coords: ( + tuple[float, float, float, float] + | tuple[tuple[float, float], tuple[float, float]] + | list[int] + | list[float] + | list[tuple[int, int]] + | list[tuple[float, float]] + ), *, activedash: str | list[int] | tuple[int, ...] = ..., activefill: _Color = ..., @@ -1384,7 +1471,47 @@ class Canvas(Widget, XView, YView): @overload def create_polygon( self, - __coords: tuple[float, ...] | list[int] | list[float], + __xy_pair_0: tuple[float, float], + __xy_pair_1: tuple[float, float], + *xy_pairs: tuple[float, float], + activedash: str | list[int] | tuple[int, ...] = ..., + activefill: _Color = ..., + activeoutline: _Color = ..., + activeoutlinestipple: _Color = ..., + activestipple: str = ..., + activewidth: _ScreenUnits = ..., + dash: str | list[int] | tuple[int, ...] = ..., + dashoffset: _ScreenUnits = ..., + disableddash: str | list[int] | tuple[int, ...] = ..., + disabledfill: _Color = ..., + disabledoutline: _Color = ..., + disabledoutlinestipple: _Color = ..., + disabledstipple: _Bitmap = ..., + disabledwidth: _ScreenUnits = ..., + fill: _Color = ..., + joinstyle: Literal["round", "bevel", "miter"] = ..., + offset: _ScreenUnits = ..., + outline: _Color = ..., + outlineoffset: _ScreenUnits = ..., + outlinestipple: _Bitmap = ..., + smooth: bool = ..., + splinesteps: float = ..., + state: Literal["normal", "active", "disabled"] = ..., + stipple: _Bitmap = ..., + tags: str | list[str] | tuple[str, ...] = ..., + width: _ScreenUnits = ..., + ) -> _CanvasItemId: ... + @overload + def create_polygon( + self, + __coords: ( + tuple[float, ...] + | tuple[tuple[float, float], ...] + | list[int] + | list[float] + | list[tuple[int, int]] + | list[tuple[float, float]] + ), *, activedash: str | list[int] | tuple[int, ...] = ..., activefill: _Color = ..., @@ -1448,7 +1575,44 @@ class Canvas(Widget, XView, YView): @overload def create_rectangle( self, - __coords: tuple[float, float, float, float] | list[int] | list[float], + __xy_pair_0: tuple[float, float], + __xy_pair_1: tuple[float, float], + *, + activedash: str | list[int] | tuple[int, ...] = ..., + activefill: _Color = ..., + activeoutline: _Color = ..., + activeoutlinestipple: _Color = ..., + activestipple: str = ..., + activewidth: _ScreenUnits = ..., + dash: str | list[int] | tuple[int, ...] = ..., + dashoffset: _ScreenUnits = ..., + disableddash: str | list[int] | tuple[int, ...] = ..., + disabledfill: _Color = ..., + disabledoutline: _Color = ..., + disabledoutlinestipple: _Color = ..., + disabledstipple: _Bitmap = ..., + disabledwidth: _ScreenUnits = ..., + fill: _Color = ..., + offset: _ScreenUnits = ..., + outline: _Color = ..., + outlineoffset: _ScreenUnits = ..., + outlinestipple: _Bitmap = ..., + state: Literal["normal", "active", "disabled"] = ..., + stipple: _Bitmap = ..., + tags: str | list[str] | tuple[str, ...] = ..., + width: _ScreenUnits = ..., + ) -> _CanvasItemId: ... + @overload + def create_rectangle( + self, + __coords: ( + tuple[float, float, float, float] + | tuple[tuple[float, float], tuple[float, float]] + | list[int] + | list[float] + | list[tuple[int, int]] + | list[tuple[float, float]] + ), *, activedash: str | list[int] | tuple[int, ...] = ..., activefill: _Color = ..., diff --git a/mypy/typeshed/stdlib/types.pyi b/mypy/typeshed/stdlib/types.pyi index 872ed57a7c76c..ed2476e44a865 100644 --- a/mypy/typeshed/stdlib/types.pyi +++ b/mypy/typeshed/stdlib/types.pyi @@ -651,6 +651,10 @@ if sys.version_info >= (3, 9): @property def __parameters__(self) -> tuple[Any, ...]: ... def __init__(self, origin: type, args: Any) -> None: ... + if sys.version_info >= (3, 11): + @property + def __unpacked__(self) -> bool: ... + def __getattr__(self, name: str) -> Any: ... # incomplete if sys.version_info >= (3, 10): diff --git a/mypy/typeshed/stdlib/typing.pyi b/mypy/typeshed/stdlib/typing.pyi index 28b588d79c9bb..37ea55c9f2eff 100644 --- a/mypy/typeshed/stdlib/typing.pyi +++ b/mypy/typeshed/stdlib/typing.pyi @@ -1,6 +1,6 @@ import collections # Needed by aliases like DefaultDict, see mypy issue 2986 import sys -from _typeshed import Self as TypeshedSelf, SupportsKeysAndGetItem +from _typeshed import ReadableBuffer, Self as TypeshedSelf, SupportsKeysAndGetItem from abc import ABCMeta, abstractmethod from types import BuiltinFunctionType, CodeType, FrameType, FunctionType, MethodType, ModuleType, TracebackType from typing_extensions import Literal as _Literal, ParamSpec as _ParamSpec, final as _final @@ -88,6 +88,7 @@ if sys.version_info >= (3, 11): "assert_type", "cast", "clear_overloads", + "dataclass_transform", "final", "get_args", "get_origin", @@ -1079,7 +1080,10 @@ class Match(Generic[AnyStr]): # this match instance. @property def re(self) -> Pattern[AnyStr]: ... - def expand(self, template: AnyStr) -> AnyStr: ... + @overload + def expand(self: Match[str], template: str) -> str: ... + @overload + def expand(self: Match[bytes], template: ReadableBuffer) -> bytes: ... # group() returns "AnyStr" or "AnyStr | None", depending on the pattern. @overload def group(self, __group: _Literal[0] = ...) -> AnyStr: ... @@ -1124,20 +1128,49 @@ class Pattern(Generic[AnyStr]): def groups(self) -> int: ... @property def pattern(self) -> AnyStr: ... - def search(self, string: AnyStr, pos: int = ..., endpos: int = ...) -> Match[AnyStr] | None: ... - def match(self, string: AnyStr, pos: int = ..., endpos: int = ...) -> Match[AnyStr] | None: ... - def fullmatch(self, string: AnyStr, pos: int = ..., endpos: int = ...) -> Match[AnyStr] | None: ... - def split(self, string: AnyStr, maxsplit: int = ...) -> list[AnyStr | Any]: ... - def findall(self, string: AnyStr, pos: int = ..., endpos: int = ...) -> list[Any]: ... - def finditer(self, string: AnyStr, pos: int = ..., endpos: int = ...) -> Iterator[Match[AnyStr]]: ... @overload - def sub(self, repl: AnyStr, string: AnyStr, count: int = ...) -> AnyStr: ... + def search(self: Pattern[str], string: str, pos: int = ..., endpos: int = ...) -> Match[str] | None: ... + @overload + def search(self: Pattern[bytes], string: ReadableBuffer, pos: int = ..., endpos: int = ...) -> Match[bytes] | None: ... + @overload + def match(self: Pattern[str], string: str, pos: int = ..., endpos: int = ...) -> Match[str] | None: ... + @overload + def match(self: Pattern[bytes], string: ReadableBuffer, pos: int = ..., endpos: int = ...) -> Match[bytes] | None: ... + @overload + def fullmatch(self: Pattern[str], string: str, pos: int = ..., endpos: int = ...) -> Match[str] | None: ... + @overload + def fullmatch(self: Pattern[bytes], string: ReadableBuffer, pos: int = ..., endpos: int = ...) -> Match[bytes] | None: ... + @overload + def split(self: Pattern[str], string: str, maxsplit: int = ...) -> list[str | Any]: ... + @overload + def split(self: Pattern[bytes], string: ReadableBuffer, maxsplit: int = ...) -> list[bytes | Any]: ... + # return type depends on the number of groups in the pattern + @overload + def findall(self: Pattern[str], string: str, pos: int = ..., endpos: int = ...) -> list[Any]: ... + @overload + def findall(self: Pattern[bytes], string: ReadableBuffer, pos: int = ..., endpos: int = ...) -> list[Any]: ... + @overload + def finditer(self: Pattern[str], string: str, pos: int = ..., endpos: int = ...) -> Iterator[Match[str]]: ... + @overload + def finditer(self: Pattern[bytes], string: ReadableBuffer, pos: int = ..., endpos: int = ...) -> Iterator[Match[bytes]]: ... + @overload + def sub(self: Pattern[str], repl: str | Callable[[Match[str]], str], string: str, count: int = ...) -> str: ... @overload - def sub(self, repl: Callable[[Match[AnyStr]], AnyStr], string: AnyStr, count: int = ...) -> AnyStr: ... + def sub( + self: Pattern[bytes], + repl: ReadableBuffer | Callable[[Match[bytes]], ReadableBuffer], + string: ReadableBuffer, + count: int = ..., + ) -> bytes: ... @overload - def subn(self, repl: AnyStr, string: AnyStr, count: int = ...) -> tuple[AnyStr, int]: ... + def subn(self: Pattern[str], repl: str | Callable[[Match[str]], str], string: str, count: int = ...) -> tuple[str, int]: ... @overload - def subn(self, repl: Callable[[Match[AnyStr]], AnyStr], string: AnyStr, count: int = ...) -> tuple[AnyStr, int]: ... + def subn( + self: Pattern[bytes], + repl: ReadableBuffer | Callable[[Match[bytes]], ReadableBuffer], + string: ReadableBuffer, + count: int = ..., + ) -> tuple[bytes, int]: ... def __copy__(self) -> Pattern[AnyStr]: ... def __deepcopy__(self, __memo: Any) -> Pattern[AnyStr]: ... if sys.version_info >= (3, 9): @@ -1192,6 +1225,14 @@ if sys.version_info >= (3, 11): def assert_type(__val: _T, __typ: Any) -> _T: ... def clear_overloads() -> None: ... def get_overloads(func: Callable[..., object]) -> Sequence[Callable[..., object]]: ... + def dataclass_transform( + *, + eq_default: bool = ..., + order_default: bool = ..., + kw_only_default: bool = ..., + field_specifiers: tuple[type[Any] | Callable[..., Any], ...] = ..., + **kwargs: Any, + ) -> Callable[[_T], _T]: ... # Type constructors diff --git a/mypy/typeshed/stdlib/typing_extensions.pyi b/mypy/typeshed/stdlib/typing_extensions.pyi index 1c75ec38e75c8..b94daaba9f498 100644 --- a/mypy/typeshed/stdlib/typing_extensions.pyi +++ b/mypy/typeshed/stdlib/typing_extensions.pyi @@ -1,7 +1,7 @@ import abc import sys from _typeshed import Self as TypeshedSelf # see #6932 for why the alias cannot have a leading underscore -from typing import ( # noqa: Y022,Y027 +from typing import ( # noqa: Y022,Y027,Y039 TYPE_CHECKING as TYPE_CHECKING, Any, AsyncContextManager as AsyncContextManager, @@ -201,6 +201,7 @@ if sys.version_info >= (3, 11): assert_never as assert_never, assert_type as assert_type, clear_overloads as clear_overloads, + dataclass_transform as dataclass_transform, get_overloads as get_overloads, reveal_type as reveal_type, ) @@ -224,12 +225,11 @@ else: def __init__(self, name: str) -> None: ... def __iter__(self) -> Any: ... # Unpack[Self] -# Experimental (hopefully these will be in 3.11) -def dataclass_transform( - *, - eq_default: bool = ..., - order_default: bool = ..., - kw_only_default: bool = ..., - field_specifiers: tuple[type[Any] | Callable[..., Any], ...] = ..., - **kwargs: object, -) -> Callable[[_T], _T]: ... + def dataclass_transform( + *, + eq_default: bool = ..., + order_default: bool = ..., + kw_only_default: bool = ..., + field_specifiers: tuple[type[Any] | Callable[..., Any], ...] = ..., + **kwargs: object, + ) -> Callable[[_T], _T]: ... diff --git a/mypy/typeshed/stdlib/urllib/error.pyi b/mypy/typeshed/stdlib/urllib/error.pyi index 48c8287e979a4..7a4de10d7cf65 100644 --- a/mypy/typeshed/stdlib/urllib/error.pyi +++ b/mypy/typeshed/stdlib/urllib/error.pyi @@ -9,6 +9,8 @@ class URLError(IOError): def __init__(self, reason: str | BaseException, filename: str | None = ...) -> None: ... class HTTPError(URLError, addinfourl): + @property + def headers(self) -> Message: ... # type: ignore[override] @property def reason(self) -> str: ... # type: ignore[override] code: int diff --git a/mypy/typeshed/stdlib/warnings.pyi b/mypy/typeshed/stdlib/warnings.pyi index bd7afb2d7cba6..c9c143991e3ad 100644 --- a/mypy/typeshed/stdlib/warnings.pyi +++ b/mypy/typeshed/stdlib/warnings.pyi @@ -1,3 +1,4 @@ +import sys from _warnings import warn as warn, warn_explicit as warn_explicit from collections.abc import Sequence from types import ModuleType, TracebackType @@ -56,12 +57,48 @@ class WarningMessage: ) -> None: ... class catch_warnings: - @overload - def __new__(cls, *, record: Literal[False] = ..., module: ModuleType | None = ...) -> _catch_warnings_without_records: ... - @overload - def __new__(cls, *, record: Literal[True], module: ModuleType | None = ...) -> _catch_warnings_with_records: ... - @overload - def __new__(cls, *, record: bool, module: ModuleType | None = ...) -> catch_warnings: ... + if sys.version_info >= (3, 11): + @overload + def __new__( + cls, + *, + record: Literal[False] = ..., + module: ModuleType | None = ..., + action: _ActionKind | None = ..., + category: type[Warning] = ..., + lineno: int = ..., + append: bool = ..., + ) -> _catch_warnings_without_records: ... + @overload + def __new__( + cls, + *, + record: Literal[True], + module: ModuleType | None = ..., + action: _ActionKind | None = ..., + category: type[Warning] = ..., + lineno: int = ..., + append: bool = ..., + ) -> _catch_warnings_with_records: ... + @overload + def __new__( + cls, + *, + record: bool, + module: ModuleType | None = ..., + action: _ActionKind | None = ..., + category: type[Warning] = ..., + lineno: int = ..., + append: bool = ..., + ) -> catch_warnings: ... + else: + @overload + def __new__(cls, *, record: Literal[False] = ..., module: ModuleType | None = ...) -> _catch_warnings_without_records: ... + @overload + def __new__(cls, *, record: Literal[True], module: ModuleType | None = ...) -> _catch_warnings_with_records: ... + @overload + def __new__(cls, *, record: bool, module: ModuleType | None = ...) -> catch_warnings: ... + def __enter__(self) -> list[WarningMessage] | None: ... def __exit__( self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None diff --git a/mypy/typeshed/stdlib/xml/etree/ElementTree.pyi b/mypy/typeshed/stdlib/xml/etree/ElementTree.pyi index 414530b0a34c0..dacb6fffcc6be 100644 --- a/mypy/typeshed/stdlib/xml/etree/ElementTree.pyi +++ b/mypy/typeshed/stdlib/xml/etree/ElementTree.pyi @@ -319,7 +319,7 @@ def iterparse( class XMLPullParser: def __init__(self, events: Sequence[str] | None = ..., *, _parser: XMLParser | None = ...) -> None: ... - def feed(self, data: bytes) -> None: ... + def feed(self, data: str | bytes) -> None: ... def close(self) -> None: ... def read_events(self) -> Iterator[tuple[str, Element]]: ... diff --git a/mypy/typeshed/stdlib/zipfile.pyi b/mypy/typeshed/stdlib/zipfile.pyi index d5255b15c3c0b..276f8df82a6de 100644 --- a/mypy/typeshed/stdlib/zipfile.pyi +++ b/mypy/typeshed/stdlib/zipfile.pyi @@ -222,6 +222,8 @@ class ZipFile: ) -> None: ... else: def writestr(self, zinfo_or_arcname: str | ZipInfo, data: bytes | str, compress_type: int | None = ...) -> None: ... + if sys.version_info >= (3, 11): + def mkdir(self, zinfo_or_directory: str | ZipInfo, mode: int = ...) -> None: ... class PyZipFile(ZipFile): def __init__( diff --git a/mypy/typeshed/stubs/mypy-extensions/METADATA.toml b/mypy/typeshed/stubs/mypy-extensions/METADATA.toml index 79b51931ee0bc..582104d3a1a7a 100644 --- a/mypy/typeshed/stubs/mypy-extensions/METADATA.toml +++ b/mypy/typeshed/stubs/mypy-extensions/METADATA.toml @@ -1,2 +1 @@ version = "0.4.*" -python2 = true diff --git a/mypy/typeshed/stubs/mypy-extensions/mypy_extensions.pyi b/mypy/typeshed/stubs/mypy-extensions/mypy_extensions.pyi index 33b47244d3856..412c3cb15142f 100644 --- a/mypy/typeshed/stubs/mypy-extensions/mypy_extensions.pyi +++ b/mypy/typeshed/stubs/mypy-extensions/mypy_extensions.pyi @@ -1,7 +1,7 @@ import abc -import sys from _typeshed import Self -from typing import Any, Callable, Generic, ItemsView, KeysView, Mapping, TypeVar, ValuesView +from collections.abc import Callable, ItemsView, KeysView, Mapping, ValuesView +from typing import Any, Generic, TypeVar _T = TypeVar("_T") _U = TypeVar("_U") @@ -15,16 +15,9 @@ class _TypedDict(Mapping[str, object], metaclass=abc.ABCMeta): # Mypy plugin hook for 'pop' expects that 'default' has a type variable type. def pop(self, k: NoReturn, default: _T = ...) -> object: ... # type: ignore def update(self: Self, __m: Self) -> None: ... - if sys.version_info >= (3, 0): - def items(self) -> ItemsView[str, object]: ... - def keys(self) -> KeysView[str]: ... - def values(self) -> ValuesView[object]: ... - else: - def has_key(self, k: str) -> bool: ... - def viewitems(self) -> ItemsView[str, object]: ... - def viewkeys(self) -> KeysView[str]: ... - def viewvalues(self) -> ValuesView[object]: ... - + def items(self) -> ItemsView[str, object]: ... + def keys(self) -> KeysView[str]: ... + def values(self) -> ValuesView[object]: ... def __delitem__(self, k: NoReturn) -> None: ... def TypedDict(typename: str, fields: dict[str, type[Any]], total: bool = ...) -> type[dict[str, Any]]: ... diff --git a/test-data/unit/cmdline.test b/test-data/unit/cmdline.test index a1b4d986b98af..86a975fc4949d 100644 --- a/test-data/unit/cmdline.test +++ b/test-data/unit/cmdline.test @@ -644,10 +644,10 @@ python_version = 3.6 [file int_pow.py] a = 1 b = a + 2 -reveal_type(a**0) # N: Revealed type is "builtins.int" +reveal_type(a**0) # N: Revealed type is "Literal[1]" reveal_type(a**1) # N: Revealed type is "builtins.int" reveal_type(a**2) # N: Revealed type is "builtins.int" -reveal_type(a**-0) # N: Revealed type is "builtins.int" +reveal_type(a**-0) # N: Revealed type is "Literal[1]" reveal_type(a**-1) # N: Revealed type is "builtins.float" reveal_type(a**(-2)) # N: Revealed type is "builtins.float" reveal_type(a**b) # N: Revealed type is "Any" diff --git a/test-data/unit/pythoneval.test b/test-data/unit/pythoneval.test index a3f44fff5e333..b59d50feb9868 100644 --- a/test-data/unit/pythoneval.test +++ b/test-data/unit/pythoneval.test @@ -1005,8 +1005,11 @@ re.subn(bpat, b'', b'')[0] + b'' re.subn(bre, lambda m: b'', b'')[0] + b'' re.subn(bpat, lambda m: b'', b'')[0] + b'' [out] -_program.py:7: error: Value of type variable "AnyStr" of "search" cannot be "Sequence[object]" -_program.py:9: error: Cannot infer type argument 1 of "search" +_testReModuleBytes.py:7: error: No overload variant of "search" matches argument types "bytes", "str" +_testReModuleBytes.py:7: note: Possible overload variants: +_testReModuleBytes.py:7: note: def search(pattern: Union[str, Pattern[str]], string: str, flags: Union[int, RegexFlag] = ...) -> Optional[Match[str]] +_testReModuleBytes.py:7: note: def search(pattern: Union[bytes, Pattern[bytes]], string: Union[bytes, Union[bytearray, memoryview, array[Any], mmap, _CData]], flags: Union[int, RegexFlag] = ...) -> Optional[Match[bytes]] +_testReModuleBytes.py:9: error: Argument 1 to "search" has incompatible type "Pattern[bytes]"; expected "Union[str, Pattern[str]]" [case testReModuleString] # Regression tests for various overloads in the re module -- string version @@ -1029,8 +1032,11 @@ re.subn(spat, '', '')[0] + '' re.subn(sre, lambda m: '', '')[0] + '' re.subn(spat, lambda m: '', '')[0] + '' [out] -_program.py:7: error: Value of type variable "AnyStr" of "search" cannot be "Sequence[object]" -_program.py:9: error: Cannot infer type argument 1 of "search" +_testReModuleString.py:7: error: No overload variant of "search" matches argument types "str", "bytes" +_testReModuleString.py:7: note: Possible overload variants: +_testReModuleString.py:7: note: def search(pattern: Union[str, Pattern[str]], string: str, flags: Union[int, RegexFlag] = ...) -> Optional[Match[str]] +_testReModuleString.py:7: note: def search(pattern: Union[bytes, Pattern[bytes]], string: Union[bytes, Union[bytearray, memoryview, array[Any], mmap, _CData]], flags: Union[int, RegexFlag] = ...) -> Optional[Match[bytes]] +_testReModuleString.py:9: error: Argument 1 to "search" has incompatible type "Pattern[str]"; expected "Union[bytes, Pattern[bytes]]" [case testListSetitemTuple] from typing import List, Tuple From e63501c7a11abc54684bdd59872eb3b092b865ae Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Mon, 16 May 2022 09:18:30 +0100 Subject: [PATCH 291/377] Add test case for fixed dataclass-classmethod crash (#12794) --- test-data/unit/check-dataclasses.test | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test-data/unit/check-dataclasses.test b/test-data/unit/check-dataclasses.test index 4cddc59b01534..7782652d66e51 100644 --- a/test-data/unit/check-dataclasses.test +++ b/test-data/unit/check-dataclasses.test @@ -495,6 +495,19 @@ reveal_type(A.foo("foo")) # N: Revealed type is "builtins.str" [builtins fixtures/dataclasses.pyi] +[case testClassmethodShadowingFieldDoesNotCrash] +# flags: --python-version 3.7 +from dataclasses import dataclass + +# This used to crash -- see #6217 +@dataclass +class Foo: + bar: str + @classmethod # E: Name "bar" already defined on line 7 + def bar(cls) -> "Foo": + return cls('asdf') +[builtins fixtures/dataclasses.pyi] + [case testDataclassesClassVars] # flags: --python-version 3.7 from dataclasses import dataclass From 17aec677e44da4488908680b90e0c145bff67d43 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Mon, 16 May 2022 09:19:55 +0100 Subject: [PATCH 292/377] Add test case for fixed dataclass-in-function crash (#12793) Closes #8703, which is a crash that was fixed by #12762 --- test-data/unit/check-dataclasses.test | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test-data/unit/check-dataclasses.test b/test-data/unit/check-dataclasses.test index 7782652d66e51..771938119fb2a 100644 --- a/test-data/unit/check-dataclasses.test +++ b/test-data/unit/check-dataclasses.test @@ -1566,6 +1566,20 @@ A(a=func).a() A(a=func).a = func # E: Property "a" defined in "A" is read-only [builtins fixtures/dataclasses.pyi] +[case testDataclassInFunctionDoesNotCrash] +# flags: --python-version 3.7 +from dataclasses import dataclass + +def foo(): + @dataclass + class Foo: + foo: int + # This used to crash (see #8703) + # The return type of __call__ here needs to be something undefined + # In order to trigger the crash that existed prior to #12762 + def __call__(self) -> asdf: ... # E: Name "asdf" is not defined +[builtins fixtures/dataclasses.pyi] + [case testDataclassesMultipleInheritanceWithNonDataclass] # flags: --python-version 3.10 from dataclasses import dataclass From 613756bd7e7a41ad14f9a6045da04cfc4612c032 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Mon, 16 May 2022 09:20:43 +0100 Subject: [PATCH 293/377] Add test case for fixed generic-dataclass crash (#12791) Adds a test case for a crash that was fixed by #12762. Closes #12527. --- test-data/unit/check-dataclasses.test | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test-data/unit/check-dataclasses.test b/test-data/unit/check-dataclasses.test index 771938119fb2a..28498fb0190a0 100644 --- a/test-data/unit/check-dataclasses.test +++ b/test-data/unit/check-dataclasses.test @@ -1712,3 +1712,15 @@ c: C[C] d: C[str] # E: Type argument "str" of "C" must be a subtype of "C[Any]" C(x=2) [builtins fixtures/dataclasses.pyi] + +[case testDataclassGenericBoundToInvalidTypeVarDoesNotCrash] +# flags: --python-version 3.7 +import dataclasses +from typing import Generic, TypeVar + +T = TypeVar("T", bound="NotDefined") # E: Name "NotDefined" is not defined + +@dataclasses.dataclass +class C(Generic[T]): + x: float +[builtins fixtures/dataclasses.pyi] From 3b7468ea518ef961d75597d52b183579b0fd83db Mon Sep 17 00:00:00 2001 From: Max Jones Date: Mon, 16 May 2022 09:39:16 -0400 Subject: [PATCH 294/377] Update link in the readme and setup (#12788) --- README.md | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1be59f0b00275..c40a224ea0420 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ We are always happy to answer questions! Here are some good places to ask them: - for general questions about Python typing, try [typing discussions](https://github.com/python/typing/discussions) If you're just getting started, -[the documentation](https://mypy.readthedocs.io/en/stable/introduction.html) +[the documentation](https://mypy.readthedocs.io/en/stable/index.html) and [type hints cheat sheet](https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html) can also help answer questions. diff --git a/setup.py b/setup.py index bba99fec8259a..7999fb20216e8 100644 --- a/setup.py +++ b/setup.py @@ -210,7 +210,7 @@ def run(self): include_package_data=True, project_urls={ 'News': 'http://mypy-lang.org/news.html', - 'Documentation': 'https://mypy.readthedocs.io/en/stable/introduction.html', + 'Documentation': 'https://mypy.readthedocs.io/en/stable/index.html', 'Repository': 'https://github.com/python/mypy', }, ) From e6bbf5f5e44854e1152ab9ddb46daa2608cf4076 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Mon, 16 May 2022 16:36:40 +0100 Subject: [PATCH 295/377] Typeshed cherry-picks: gettext and sqlite3 fixes (#12797) * gettext: Make GNUTranslations.CONTEXT not final (python/typeshed#7841) * sqlite3: Avoid optional type for 'description' (python/typeshed#7842) --- mypy/typeshed/stdlib/gettext.pyi | 2 +- mypy/typeshed/stdlib/sqlite3/dbapi2.pyi | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/mypy/typeshed/stdlib/gettext.pyi b/mypy/typeshed/stdlib/gettext.pyi index d02dda5350b79..829ade96cb405 100644 --- a/mypy/typeshed/stdlib/gettext.pyi +++ b/mypy/typeshed/stdlib/gettext.pyi @@ -96,7 +96,7 @@ class NullTranslations: class GNUTranslations(NullTranslations): LE_MAGIC: Final[int] BE_MAGIC: Final[int] - CONTEXT: Final[str] + CONTEXT: str VERSIONS: Sequence[int] @overload # ignores incompatible overloads diff --git a/mypy/typeshed/stdlib/sqlite3/dbapi2.pyi b/mypy/typeshed/stdlib/sqlite3/dbapi2.pyi index a6ccc9977c1ce..dc00a3971b0fd 100644 --- a/mypy/typeshed/stdlib/sqlite3/dbapi2.pyi +++ b/mypy/typeshed/stdlib/sqlite3/dbapi2.pyi @@ -374,8 +374,9 @@ class Cursor(Iterator[Any]): arraysize: int @property def connection(self) -> Connection: ... + # May be None, but using | Any instead to avoid slightly annoying false positives. @property - def description(self) -> tuple[tuple[str, None, None, None, None, None, None], ...] | None: ... + def description(self) -> tuple[tuple[str, None, None, None, None, None, None], ...] | Any: ... @property def lastrowid(self) -> int | None: ... row_factory: Callable[[Cursor, Row[Any]], object] | None From 85c21599cae51318344c23eecdfec6c3a2a9557a Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Mon, 16 May 2022 16:57:49 +0100 Subject: [PATCH 296/377] Add dataclass InitVar test case (#12798) This test case cover a recent change in functionality: if an attribute is defined as an InitVar, it can't be assigned to. Previously this was supported (probably by accident). --- test-data/unit/check-dataclasses.test | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test-data/unit/check-dataclasses.test b/test-data/unit/check-dataclasses.test index 28498fb0190a0..abfcb79c0cc57 100644 --- a/test-data/unit/check-dataclasses.test +++ b/test-data/unit/check-dataclasses.test @@ -1724,3 +1724,23 @@ T = TypeVar("T", bound="NotDefined") # E: Name "NotDefined" is not defined class C(Generic[T]): x: float [builtins fixtures/dataclasses.pyi] + +[case testDataclassInitVarCannotBeSet] +# flags: --python-version 3.7 +from dataclasses import dataclass, InitVar + +@dataclass +class C: + x: InitVar[int] = 0 + y: InitVar[str] = '' + + def f(self) -> None: + # This works at runtime, but it seems like an abuse of the InitVar + # feature and thus we don't support it + self.x = 1 # E: "C" has no attribute "x" + self.y: str = 'x' # E: "C" has no attribute "y" + +c = C() +c2 = C(x=1) +c.x # E: "C" has no attribute "x" +[builtins fixtures/dataclasses.pyi] From 18a510768bdf552248447d35d15f8e48b1aef53d Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Tue, 17 May 2022 15:46:29 +0100 Subject: [PATCH 297/377] Fix nested namedtuple crash in incremental mode (#12803) Make sure the fullname of a named tuple defined within a method matches the nesting of the definition in the symbol table. Otherwise we'll have a crash during deserialization. In particular, a named tuple defined within a method will now be always stored in the symbol table of the surrounding class, instead of the global symbol table. Previously there was an inconsistency between old-style and new-style syntax. Fix #10913. --- mypy/semanal.py | 23 +++++++----- mypy/semanal_namedtuple.py | 5 ++- test-data/unit/check-incremental.test | 53 +++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 11 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index d68928ef21ad4..a49e7c23edf57 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -1220,7 +1220,7 @@ def analyze_namedtuple_classdef(self, defn: ClassDef) -> bool: is_named_tuple, info = True, defn.info # type: bool, Optional[TypeInfo] else: is_named_tuple, info = self.named_tuple_analyzer.analyze_namedtuple_classdef( - defn, self.is_stub_file) + defn, self.is_stub_file, self.is_func_scope()) if is_named_tuple: if info is None: self.mark_incomplete(defn.name, defn) @@ -1462,7 +1462,10 @@ def prepare_class_def(self, defn: ClassDef, info: Optional[TypeInfo] = None) -> info._fullname = self.qualified_name(defn.name) else: info._fullname = info.name - self.add_symbol(defn.name, defn.info, defn) + local_name = defn.name + if '@' in local_name: + local_name = local_name.split('@')[0] + self.add_symbol(local_name, defn.info, defn) if self.is_nested_within_func_scope(): # We need to preserve local classes, let's store them # in globals under mangled unique names @@ -1471,17 +1474,17 @@ def prepare_class_def(self, defn: ClassDef, info: Optional[TypeInfo] = None) -> # incremental mode and we should avoid it. In general, this logic is too # ad-hoc and needs to be removed/refactored. if '@' not in defn.info._fullname: - local_name = defn.info.name + '@' + str(defn.line) - if defn.info.is_named_tuple: - # Module is already correctly set in _fullname for named tuples. - defn.info._fullname += '@' + str(defn.line) - else: - defn.info._fullname = self.cur_mod_id + '.' + local_name + global_name = defn.info.name + '@' + str(defn.line) + defn.info._fullname = self.cur_mod_id + '.' + global_name else: # Preserve name from previous fine-grained incremental run. - local_name = defn.info.name + global_name = defn.info.name defn.fullname = defn.info._fullname - self.globals[local_name] = SymbolTableNode(GDEF, defn.info) + if defn.info.is_named_tuple: + # Named tuple nested within a class is stored in the class symbol table. + self.add_symbol_skip_local(global_name, defn.info) + else: + self.globals[global_name] = SymbolTableNode(GDEF, defn.info) def make_empty_type_info(self, defn: ClassDef) -> TypeInfo: if (self.is_module_scope() diff --git a/mypy/semanal_namedtuple.py b/mypy/semanal_namedtuple.py index 4e05dfb996053..07863dea2efbe 100644 --- a/mypy/semanal_namedtuple.py +++ b/mypy/semanal_namedtuple.py @@ -53,7 +53,8 @@ def __init__(self, options: Options, api: SemanticAnalyzerInterface) -> None: self.options = options self.api = api - def analyze_namedtuple_classdef(self, defn: ClassDef, is_stub_file: bool + def analyze_namedtuple_classdef(self, defn: ClassDef, is_stub_file: bool, + is_func_scope: bool ) -> Tuple[bool, Optional[TypeInfo]]: """Analyze if given class definition can be a named tuple definition. @@ -70,6 +71,8 @@ def analyze_namedtuple_classdef(self, defn: ClassDef, is_stub_file: bool # This is a valid named tuple, but some types are incomplete. return True, None items, types, default_items = result + if is_func_scope and '@' not in defn.name: + defn.name += '@' + str(defn.line) info = self.build_namedtuple_typeinfo( defn.name, items, types, default_items, defn.line) defn.info = info diff --git a/test-data/unit/check-incremental.test b/test-data/unit/check-incremental.test index caba9b73e5943..c604b386691b7 100644 --- a/test-data/unit/check-incremental.test +++ b/test-data/unit/check-incremental.test @@ -5658,3 +5658,56 @@ class D(C): [out] [out2] tmp/a.py:9: error: Trying to assign name "z" that is not in "__slots__" of type "a.D" + +[case testIncrementalWithDifferentKindsOfNestedTypesWithinMethod] +# flags: --python-version 3.7 + +import a + +[file a.py] +import b + +[file a.py.2] +import b +b.xyz + +[file b.py] +from typing import NamedTuple, NewType +from typing_extensions import TypedDict, TypeAlias +from enum import Enum +from dataclasses import dataclass + +class C: + def f(self) -> None: + class C: + c: int + class NT1(NamedTuple): + c: int + NT2 = NamedTuple("NT2", [("c", int)]) + class NT3(NT1): + pass + class TD(TypedDict): + c: int + TD2 = TypedDict("TD2", {"c": int}) + class E(Enum): + X = 1 + @dataclass + class DC: + c: int + Alias: TypeAlias = NT1 + N = NewType("N", NT1) + + c: C = C() + nt1: NT1 = NT1(c=1) + nt2: NT2 = NT2(c=1) + nt3: NT3 = NT3(c=1) + td: TD = TD(c=1) + td2: TD2 = TD2(c=1) + e: E = E.X + dc: DC = DC(c=1) + al: Alias = Alias(c=1) + n: N = N(NT1(c=1)) + +[builtins fixtures/dict.pyi] +[out2] +tmp/a.py:2: error: "object" has no attribute "xyz" From 7bd6fdd326b6a06795edb46a5c74fc5cdeb87cc9 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Tue, 17 May 2022 18:33:56 +0100 Subject: [PATCH 298/377] [mypyc] Detect always defined attributes (#12600) Use static analysis to find attributes that are always defined. Always defined attributes don't require checks on each access. This makes them faster and also reduces code size. Attributes defined in the class body and assigned to in all code paths in `__init__` are always defined. We need to know all subclasses statically to determine whether `__init__` always defines an attribute in every case, including in subclasses. The analysis looks at `__init__` methods and supports limited inter-procedural analysis over `super().__init__(...)` calls. Otherwise we rely on intra-procedural analysis to keep the analysis fast. As a side effect, `__init__` will now always be called when constructing an object. This means that `copy.copy` (and others like it) won't be supported for native classes unless `__init__` can be called without arguments. `mypyc/analysis/attrdefined.py` has more details about the algorithm in docstrings. Performance impact to selected benchmarks (with clang): - richards +28% - deltablue +10% - hexiom +1% The richards result is probably an outlier. This will also significantly help with native integers (mypyc/mypyc#837, as tracking undefined values would otherwise require extra memory use. Closes mypyc/mypyc#836. --- mypy/copytype.py | 111 +++ mypy/moduleinspect.py | 15 +- mypy/nodes.py | 17 +- mypy/stubtest.py | 2 +- mypy/typeops.py | 4 +- mypy/types.py | 11 - mypyc/analysis/attrdefined.py | 377 ++++++++++ mypyc/analysis/dataflow.py | 129 ++-- mypyc/analysis/selfleaks.py | 153 ++++ mypyc/codegen/emitclass.py | 65 +- mypyc/codegen/emitfunc.py | 81 ++- mypyc/doc/differences_from_python.rst | 37 + mypyc/ir/class_ir.py | 44 ++ mypyc/ir/ops.py | 8 + mypyc/ir/pprint.py | 9 +- mypyc/irbuild/classdef.py | 49 +- mypyc/irbuild/function.py | 2 +- mypyc/irbuild/main.py | 5 +- mypyc/irbuild/mapper.py | 16 +- mypyc/irbuild/prepare.py | 3 + mypyc/test-data/alwaysdefined.test | 732 ++++++++++++++++++++ mypyc/test-data/irbuild-basic.test | 19 +- mypyc/test-data/irbuild-classes.test | 79 ++- mypyc/test-data/irbuild-constant-fold.test | 3 +- mypyc/test-data/irbuild-singledispatch.test | 41 +- mypyc/test-data/irbuild-statements.test | 5 +- mypyc/test-data/run-classes.test | 290 +++++++- mypyc/test-data/run-multimodule.test | 63 ++ mypyc/test/test_alwaysdefined.py | 42 ++ mypyc/test/test_run.py | 1 - mypyc/test/test_serialization.py | 5 +- mypyc/test/testutil.py | 9 +- 32 files changed, 2187 insertions(+), 240 deletions(-) create mode 100644 mypy/copytype.py create mode 100644 mypyc/analysis/attrdefined.py create mode 100644 mypyc/analysis/selfleaks.py create mode 100644 mypyc/test-data/alwaysdefined.test create mode 100644 mypyc/test/test_alwaysdefined.py diff --git a/mypy/copytype.py b/mypy/copytype.py new file mode 100644 index 0000000000000..85d7d531c5a3b --- /dev/null +++ b/mypy/copytype.py @@ -0,0 +1,111 @@ +from typing import Any, cast + +from mypy.types import ( + ProperType, UnboundType, AnyType, NoneType, UninhabitedType, ErasedType, DeletedType, + Instance, TypeVarType, ParamSpecType, PartialType, CallableType, TupleType, TypedDictType, + LiteralType, UnionType, Overloaded, TypeType, TypeAliasType, UnpackType, Parameters, + TypeVarTupleType +) +from mypy.type_visitor import TypeVisitor + + +def copy_type(t: ProperType) -> ProperType: + """Create a shallow copy of a type. + + This can be used to mutate the copy with truthiness information. + + Classes compiled with mypyc don't support copy.copy(), so we need + a custom implementation. + """ + return t.accept(TypeShallowCopier()) + + +class TypeShallowCopier(TypeVisitor[ProperType]): + def visit_unbound_type(self, t: UnboundType) -> ProperType: + return t + + def visit_any(self, t: AnyType) -> ProperType: + return self.copy_common(t, AnyType(t.type_of_any, t.source_any, t.missing_import_name)) + + def visit_none_type(self, t: NoneType) -> ProperType: + return self.copy_common(t, NoneType()) + + def visit_uninhabited_type(self, t: UninhabitedType) -> ProperType: + dup = UninhabitedType(t.is_noreturn) + dup.ambiguous = t.ambiguous + return self.copy_common(t, dup) + + def visit_erased_type(self, t: ErasedType) -> ProperType: + return self.copy_common(t, ErasedType()) + + def visit_deleted_type(self, t: DeletedType) -> ProperType: + return self.copy_common(t, DeletedType(t.source)) + + def visit_instance(self, t: Instance) -> ProperType: + dup = Instance(t.type, t.args, last_known_value=t.last_known_value) + dup.invalid = t.invalid + return self.copy_common(t, dup) + + def visit_type_var(self, t: TypeVarType) -> ProperType: + dup = TypeVarType( + t.name, + t.fullname, + t.id, + values=t.values, + upper_bound=t.upper_bound, + variance=t.variance, + ) + return self.copy_common(t, dup) + + def visit_param_spec(self, t: ParamSpecType) -> ProperType: + dup = ParamSpecType(t.name, t.fullname, t.id, t.flavor, t.upper_bound, prefix=t.prefix) + return self.copy_common(t, dup) + + def visit_parameters(self, t: Parameters) -> ProperType: + dup = Parameters(t.arg_types, t.arg_kinds, t.arg_names, + variables=t.variables, + is_ellipsis_args=t.is_ellipsis_args) + return self.copy_common(t, dup) + + def visit_type_var_tuple(self, t: TypeVarTupleType) -> ProperType: + dup = TypeVarTupleType(t.name, t.fullname, t.id, t.upper_bound) + return self.copy_common(t, dup) + + def visit_unpack_type(self, t: UnpackType) -> ProperType: + dup = UnpackType(t.type) + return self.copy_common(t, dup) + + def visit_partial_type(self, t: PartialType) -> ProperType: + return self.copy_common(t, PartialType(t.type, t.var, t.value_type)) + + def visit_callable_type(self, t: CallableType) -> ProperType: + return self.copy_common(t, t.copy_modified()) + + def visit_tuple_type(self, t: TupleType) -> ProperType: + return self.copy_common(t, TupleType(t.items, t.partial_fallback, implicit=t.implicit)) + + def visit_typeddict_type(self, t: TypedDictType) -> ProperType: + return self.copy_common(t, TypedDictType(t.items, t.required_keys, t.fallback)) + + def visit_literal_type(self, t: LiteralType) -> ProperType: + return self.copy_common(t, LiteralType(value=t.value, fallback=t.fallback)) + + def visit_union_type(self, t: UnionType) -> ProperType: + return self.copy_common(t, UnionType(t.items)) + + def visit_overloaded(self, t: Overloaded) -> ProperType: + return self.copy_common(t, Overloaded(items=t.items)) + + def visit_type_type(self, t: TypeType) -> ProperType: + # Use cast since the type annotations in TypeType are imprecise. + return self.copy_common(t, TypeType(cast(Any, t.item))) + + def visit_type_alias_type(self, t: TypeAliasType) -> ProperType: + assert False, "only ProperTypes supported" + + def copy_common(self, t: ProperType, t2: ProperType) -> ProperType: + t2.line = t.line + t2.column = t.column + t2.can_be_false = t.can_be_false + t2.can_be_true = t.can_be_true + return t2 diff --git a/mypy/moduleinspect.py b/mypy/moduleinspect.py index 2b2068e0b7c5f..326876ec5d43c 100644 --- a/mypy/moduleinspect.py +++ b/mypy/moduleinspect.py @@ -12,19 +12,20 @@ class ModuleProperties: + # Note that all __init__ args must have default values def __init__(self, - name: str, - file: Optional[str], - path: Optional[List[str]], - all: Optional[List[str]], - is_c_module: bool, - subpackages: List[str]) -> None: + name: str = "", + file: Optional[str] = None, + path: Optional[List[str]] = None, + all: Optional[List[str]] = None, + is_c_module: bool = False, + subpackages: Optional[List[str]] = None) -> None: self.name = name # __name__ attribute self.file = file # __file__ attribute self.path = path # __path__ attribute self.all = all # __all__ attribute self.is_c_module = is_c_module - self.subpackages = subpackages + self.subpackages = subpackages or [] def is_c_module(module: ModuleType) -> bool: diff --git a/mypy/nodes.py b/mypy/nodes.py index 4ffa3116a1189..d510cbeeec620 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -668,16 +668,16 @@ class FuncItem(FuncBase): __deletable__ = ('arguments', 'max_pos', 'min_args') def __init__(self, - arguments: List[Argument], - body: 'Block', + arguments: Optional[List[Argument]] = None, + body: Optional['Block'] = None, typ: 'Optional[mypy.types.FunctionLike]' = None) -> None: super().__init__() - self.arguments = arguments - self.arg_names = [None if arg.pos_only else arg.variable.name for arg in arguments] + self.arguments = arguments or [] + self.arg_names = [None if arg.pos_only else arg.variable.name for arg in self.arguments] self.arg_kinds: List[ArgKind] = [arg.kind for arg in self.arguments] self.max_pos: int = ( self.arg_kinds.count(ARG_POS) + self.arg_kinds.count(ARG_OPT)) - self.body: 'Block' = body + self.body: 'Block' = body or Block([]) self.type = typ self.unanalyzed_type = typ self.is_overload: bool = False @@ -725,10 +725,11 @@ class FuncDef(FuncItem, SymbolNode, Statement): 'original_def', ) + # Note that all __init__ args must have default values def __init__(self, - name: str, # Function name - arguments: List[Argument], - body: 'Block', + name: str = '', # Function name + arguments: Optional[List[Argument]] = None, + body: Optional['Block'] = None, typ: 'Optional[mypy.types.FunctionLike]' = None) -> None: super().__init__(arguments, body, typ) self._name = name diff --git a/mypy/stubtest.py b/mypy/stubtest.py index ea0deb35092f9..b7aa6367ef2d7 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -895,7 +895,6 @@ def _resolve_funcitem_from_decorator(dec: nodes.OverloadPart) -> Optional[nodes. Returns None if we can't figure out what that would be. For convenience, this function also accepts FuncItems. - """ if isinstance(dec, nodes.FuncItem): return dec @@ -917,6 +916,7 @@ def apply_decorator_to_funcitem( return func if decorator.fullname == "builtins.classmethod": assert func.arguments[0].variable.name in ("cls", "metacls") + # FuncItem is written so that copy.copy() actually works, even when compiled ret = copy.copy(func) # Remove the cls argument, since it's not present in inspect.signature of classmethods ret.arguments = ret.arguments[1:] diff --git a/mypy/typeops.py b/mypy/typeops.py index e2e44b915c0cf..e8171e2e85ab1 100644 --- a/mypy/typeops.py +++ b/mypy/typeops.py @@ -14,8 +14,7 @@ TupleType, Instance, FunctionLike, Type, CallableType, TypeVarLikeType, Overloaded, TypeVarType, UninhabitedType, FormalArgument, UnionType, NoneType, AnyType, TypeOfAny, TypeType, ProperType, LiteralType, get_proper_type, get_proper_types, - copy_type, TypeAliasType, TypeQuery, ParamSpecType, Parameters, - ENUM_REMOVED_PROPS + TypeAliasType, TypeQuery, ParamSpecType, Parameters, ENUM_REMOVED_PROPS ) from mypy.nodes import ( FuncBase, FuncItem, FuncDef, OverloadedFuncDef, TypeInfo, ARG_STAR, ARG_STAR2, ARG_POS, @@ -23,6 +22,7 @@ ) from mypy.maptype import map_instance_to_supertype from mypy.expandtype import expand_type_by_instance, expand_type +from mypy.copytype import copy_type from mypy.typevars import fill_typevars diff --git a/mypy/types.py b/mypy/types.py index afe1a88e06b17..f0f7add2d92fb 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -1,6 +1,5 @@ """Classes for representing mypy types.""" -import copy import sys from abc import abstractmethod @@ -2893,16 +2892,6 @@ def is_named_instance(t: Type, fullnames: Union[str, Tuple[str, ...]]) -> bool: return isinstance(t, Instance) and t.type.fullname in fullnames -TP = TypeVar('TP', bound=Type) - - -def copy_type(t: TP) -> TP: - """ - Build a copy of the type; used to mutate the copy with truthiness information - """ - return copy.copy(t) - - class InstantiateAliasVisitor(TypeTranslator): def __init__(self, vars: List[str], subs: List[Type]) -> None: self.replacements = {v: s for (v, s) in zip(vars, subs)} diff --git a/mypyc/analysis/attrdefined.py b/mypyc/analysis/attrdefined.py new file mode 100644 index 0000000000000..6187d143711f8 --- /dev/null +++ b/mypyc/analysis/attrdefined.py @@ -0,0 +1,377 @@ +"""Always defined attribute analysis. + +An always defined attribute has some statements in __init__ or the +class body that cause the attribute to be always initialized when an +instance is constructed. It must also not be possible to read the +attribute before initialization, and it can't be deletable. + +We can assume that the value is always defined when reading an always +defined attribute. Otherwise we'll need to raise AttributeError if the +value is undefined (i.e. has the error value). + +We use data flow analysis to figure out attributes that are always +defined. Example: + + class C: + def __init__(self) -> None: + self.x = 0 + if func(): + self.y = 1 + else: + self.y = 2 + self.z = 3 + +In this example, the attributes 'x' and 'y' are always defined, but 'z' +is not. The analysis assumes that we know that there won't be any subclasses. + +The analysis also works if there is a known, closed set of subclasses. +An attribute defined in a base class can only be always defined if it's +also always defined in all subclasses. + +As soon as __init__ contains an op that can 'leak' self to another +function, we will stop inferring always defined attributes, since the +analysis is mostly intra-procedural and only looks at __init__ methods. +The called code could read an uninitialized attribute. Example: + + class C: + def __init__(self) -> None: + self.x = self.foo() + + def foo(self) -> int: + ... + +Now we won't infer 'x' as always defined, since 'foo' might read 'x' +before initialization. + +As an exception to the above limitation, we perform inter-procedural +analysis of super().__init__ calls, since these are very common. + +Our analysis is somewhat optimistic. We assume that nobody calls a +method of a partially uninitialized object through gc.get_objects(), in +particular. Code like this could potentially cause a segfault with a null +pointer dereference. This seems very unlikely to be an issue in practice, +however. + +Accessing an attribute via getattr always checks for undefined attributes +and thus works if the object is partially uninitialized. This can be used +as a workaround if somebody ever needs to inspect partially uninitialized +objects via gc.get_objects(). + +The analysis runs after IR building as a separate pass. Since we only +run this on __init__ methods, this analysis pass will be fairly quick. +""" + +from typing import List, Set, Tuple +from typing_extensions import Final + +from mypyc.ir.ops import ( + Register, Assign, AssignMulti, SetMem, SetAttr, Branch, Return, Unreachable, GetAttr, + Call, RegisterOp, BasicBlock, ControlOp +) +from mypyc.ir.rtypes import RInstance +from mypyc.ir.class_ir import ClassIR +from mypyc.analysis.dataflow import ( + BaseAnalysisVisitor, AnalysisResult, get_cfg, CFG, MAYBE_ANALYSIS, run_analysis +) +from mypyc.analysis.selfleaks import analyze_self_leaks + + +# If True, print out all always-defined attributes of native classes (to aid +# debugging and testing) +dump_always_defined: Final = False + + +def analyze_always_defined_attrs(class_irs: List[ClassIR]) -> None: + """Find always defined attributes all classes of a compilation unit. + + Also tag attribute initialization ops to not decref the previous + value (as this would read a NULL pointer and segfault). + + Update the _always_initialized_attrs, _sometimes_initialized_attrs + and init_self_leak attributes in ClassIR instances. + + This is the main entry point. + """ + seen: Set[ClassIR] = set() + + # First pass: only look at target class and classes in MRO + for cl in class_irs: + analyze_always_defined_attrs_in_class(cl, seen) + + # Second pass: look at all derived class + seen = set() + for cl in class_irs: + update_always_defined_attrs_using_subclasses(cl, seen) + + +def analyze_always_defined_attrs_in_class(cl: ClassIR, seen: Set[ClassIR]) -> None: + if cl in seen: + return + + seen.add(cl) + + if (cl.is_trait + or cl.inherits_python + or cl.allow_interpreted_subclasses + or cl.builtin_base is not None + or cl.children is None + or cl.is_serializable()): + # Give up -- we can't enforce that attributes are always defined. + return + + # First analyze all base classes. Track seen classes to avoid duplicate work. + for base in cl.mro[1:]: + analyze_always_defined_attrs_in_class(base, seen) + + m = cl.get_method('__init__') + if m is None: + cl._always_initialized_attrs = cl.attrs_with_defaults.copy() + cl._sometimes_initialized_attrs = cl.attrs_with_defaults.copy() + return + self_reg = m.arg_regs[0] + cfg = get_cfg(m.blocks) + dirty = analyze_self_leaks(m.blocks, self_reg, cfg) + maybe_defined = analyze_maybe_defined_attrs_in_init( + m.blocks, self_reg, cl.attrs_with_defaults, cfg) + all_attrs: Set[str] = set() + for base in cl.mro: + all_attrs.update(base.attributes) + maybe_undefined = analyze_maybe_undefined_attrs_in_init( + m.blocks, + self_reg, + initial_undefined=all_attrs - cl.attrs_with_defaults, + cfg=cfg) + + always_defined = find_always_defined_attributes( + m.blocks, self_reg, all_attrs, maybe_defined, maybe_undefined, dirty) + always_defined = {a for a in always_defined if not cl.is_deletable(a)} + + cl._always_initialized_attrs = always_defined + if dump_always_defined: + print(cl.name, sorted(always_defined)) + cl._sometimes_initialized_attrs = find_sometimes_defined_attributes( + m.blocks, self_reg, maybe_defined, dirty) + + mark_attr_initialiation_ops(m.blocks, self_reg, maybe_defined, dirty) + + # Check if __init__ can run unpredictable code (leak 'self'). + any_dirty = False + for b in m.blocks: + for i, op in enumerate(b.ops): + if dirty.after[b, i] and not isinstance(op, Return): + any_dirty = True + break + cl.init_self_leak = any_dirty + + +def find_always_defined_attributes(blocks: List[BasicBlock], + self_reg: Register, + all_attrs: Set[str], + maybe_defined: AnalysisResult[str], + maybe_undefined: AnalysisResult[str], + dirty: AnalysisResult[None]) -> Set[str]: + """Find attributes that are always initialized in some basic blocks. + + The analysis results are expected to be up-to-date for the blocks. + + Return a set of always defined attributes. + """ + attrs = all_attrs.copy() + for block in blocks: + for i, op in enumerate(block.ops): + # If an attribute we *read* may be undefined, it isn't always defined. + if isinstance(op, GetAttr) and op.obj is self_reg: + if op.attr in maybe_undefined.before[block, i]: + attrs.discard(op.attr) + # If an attribute we *set* may be sometimes undefined and + # sometimes defined, don't consider it always defined. Unlike + # the get case, it's fine for the attribute to be undefined. + # The set operation will then be treated as initialization. + if isinstance(op, SetAttr) and op.obj is self_reg: + if (op.attr in maybe_undefined.before[block, i] + and op.attr in maybe_defined.before[block, i]): + attrs.discard(op.attr) + # Treat an op that might run arbitrary code as an "exit" + # in terms of the analysis -- we can't do any inference + # afterwards reliably. + if dirty.after[block, i]: + if not dirty.before[block, i]: + attrs = attrs & (maybe_defined.after[block, i] - + maybe_undefined.after[block, i]) + break + if isinstance(op, ControlOp): + for target in op.targets(): + # Gotos/branches can also be "exits". + if not dirty.after[block, i] and dirty.before[target, 0]: + attrs = attrs & (maybe_defined.after[target, 0] - + maybe_undefined.after[target, 0]) + return attrs + + +def find_sometimes_defined_attributes(blocks: List[BasicBlock], + self_reg: Register, + maybe_defined: AnalysisResult[str], + dirty: AnalysisResult[None]) -> Set[str]: + """Find attributes that are sometimes initialized in some basic blocks.""" + attrs: Set[str] = set() + for block in blocks: + for i, op in enumerate(block.ops): + # Only look at possibly defined attributes at exits. + if dirty.after[block, i]: + if not dirty.before[block, i]: + attrs = attrs | maybe_defined.after[block, i] + break + if isinstance(op, ControlOp): + for target in op.targets(): + if not dirty.after[block, i] and dirty.before[target, 0]: + attrs = attrs | maybe_defined.after[target, 0] + return attrs + + +def mark_attr_initialiation_ops(blocks: List[BasicBlock], + self_reg: Register, + maybe_defined: AnalysisResult[str], + dirty: AnalysisResult[None]) -> None: + """Tag all SetAttr ops in the basic blocks that initialize attributes. + + Initialization ops assume that the previous attribute value is the error value, + so there's no need to decref or check for definedness. + """ + for block in blocks: + for i, op in enumerate(block.ops): + if isinstance(op, SetAttr) and op.obj is self_reg: + attr = op.attr + if attr not in maybe_defined.before[block, i] and not dirty.after[block, i]: + op.mark_as_initializer() + + +GenAndKill = Tuple[Set[str], Set[str]] + + +def attributes_initialized_by_init_call(op: Call) -> Set[str]: + """Calculate attributes that are always initialized by a super().__init__ call.""" + self_type = op.fn.sig.args[0].type + assert isinstance(self_type, RInstance) + cl = self_type.class_ir + return {a for base in cl.mro for a in base.attributes if base.is_always_defined(a)} + + +def attributes_maybe_initialized_by_init_call(op: Call) -> Set[str]: + """Calculate attributes that may be initialized by a super().__init__ call.""" + self_type = op.fn.sig.args[0].type + assert isinstance(self_type, RInstance) + cl = self_type.class_ir + return attributes_initialized_by_init_call(op) | cl._sometimes_initialized_attrs + + +class AttributeMaybeDefinedVisitor(BaseAnalysisVisitor[str]): + """Find attributes that may have been defined via some code path. + + Consider initializations in class body and assignments to 'self.x' + and calls to base class '__init__'. + """ + + def __init__(self, self_reg: Register) -> None: + self.self_reg = self_reg + + def visit_branch(self, op: Branch) -> Tuple[Set[str], Set[str]]: + return set(), set() + + def visit_return(self, op: Return) -> Tuple[Set[str], Set[str]]: + return set(), set() + + def visit_unreachable(self, op: Unreachable) -> Tuple[Set[str], Set[str]]: + return set(), set() + + def visit_register_op(self, op: RegisterOp) -> Tuple[Set[str], Set[str]]: + if isinstance(op, SetAttr) and op.obj is self.self_reg: + return {op.attr}, set() + if isinstance(op, Call) and op.fn.class_name and op.fn.name == '__init__': + return attributes_maybe_initialized_by_init_call(op), set() + return set(), set() + + def visit_assign(self, op: Assign) -> Tuple[Set[str], Set[str]]: + return set(), set() + + def visit_assign_multi(self, op: AssignMulti) -> Tuple[Set[str], Set[str]]: + return set(), set() + + def visit_set_mem(self, op: SetMem) -> Tuple[Set[str], Set[str]]: + return set(), set() + + +def analyze_maybe_defined_attrs_in_init(blocks: List[BasicBlock], + self_reg: Register, + attrs_with_defaults: Set[str], + cfg: CFG) -> AnalysisResult[str]: + return run_analysis(blocks=blocks, + cfg=cfg, + gen_and_kill=AttributeMaybeDefinedVisitor(self_reg), + initial=attrs_with_defaults, + backward=False, + kind=MAYBE_ANALYSIS) + + +class AttributeMaybeUndefinedVisitor(BaseAnalysisVisitor[str]): + """Find attributes that may be undefined via some code path. + + Consider initializations in class body, assignments to 'self.x' + and calls to base class '__init__'. + """ + + def __init__(self, self_reg: Register) -> None: + self.self_reg = self_reg + + def visit_branch(self, op: Branch) -> Tuple[Set[str], Set[str]]: + return set(), set() + + def visit_return(self, op: Return) -> Tuple[Set[str], Set[str]]: + return set(), set() + + def visit_unreachable(self, op: Unreachable) -> Tuple[Set[str], Set[str]]: + return set(), set() + + def visit_register_op(self, op: RegisterOp) -> Tuple[Set[str], Set[str]]: + if isinstance(op, SetAttr) and op.obj is self.self_reg: + return set(), {op.attr} + if isinstance(op, Call) and op.fn.class_name and op.fn.name == '__init__': + return set(), attributes_initialized_by_init_call(op) + return set(), set() + + def visit_assign(self, op: Assign) -> Tuple[Set[str], Set[str]]: + return set(), set() + + def visit_assign_multi(self, op: AssignMulti) -> Tuple[Set[str], Set[str]]: + return set(), set() + + def visit_set_mem(self, op: SetMem) -> Tuple[Set[str], Set[str]]: + return set(), set() + + +def analyze_maybe_undefined_attrs_in_init(blocks: List[BasicBlock], + self_reg: Register, + initial_undefined: Set[str], + cfg: CFG) -> AnalysisResult[str]: + return run_analysis(blocks=blocks, + cfg=cfg, + gen_and_kill=AttributeMaybeUndefinedVisitor(self_reg), + initial=initial_undefined, + backward=False, + kind=MAYBE_ANALYSIS) + + +def update_always_defined_attrs_using_subclasses(cl: ClassIR, seen: Set[ClassIR]) -> None: + """Remove attributes not defined in all subclasses from always defined attrs.""" + if cl in seen: + return + if cl.children is None: + # Subclasses are unknown + return + removed = set() + for attr in cl._always_initialized_attrs: + for child in cl.children: + update_always_defined_attrs_using_subclasses(child, seen) + if attr not in child._always_initialized_attrs: + removed.add(attr) + cl._always_initialized_attrs -= removed + seen.add(cl) diff --git a/mypyc/analysis/dataflow.py b/mypyc/analysis/dataflow.py index 3b79f101a670a..053efc7338453 100644 --- a/mypyc/analysis/dataflow.py +++ b/mypyc/analysis/dataflow.py @@ -128,100 +128,100 @@ def __str__(self) -> str: return f'before: {self.before}\nafter: {self.after}\n' -GenAndKill = Tuple[Set[Value], Set[Value]] +GenAndKill = Tuple[Set[T], Set[T]] -class BaseAnalysisVisitor(OpVisitor[GenAndKill]): - def visit_goto(self, op: Goto) -> GenAndKill: +class BaseAnalysisVisitor(OpVisitor[GenAndKill[T]]): + def visit_goto(self, op: Goto) -> GenAndKill[T]: return set(), set() @abstractmethod - def visit_register_op(self, op: RegisterOp) -> GenAndKill: + def visit_register_op(self, op: RegisterOp) -> GenAndKill[T]: raise NotImplementedError @abstractmethod - def visit_assign(self, op: Assign) -> GenAndKill: + def visit_assign(self, op: Assign) -> GenAndKill[T]: raise NotImplementedError @abstractmethod - def visit_assign_multi(self, op: AssignMulti) -> GenAndKill: + def visit_assign_multi(self, op: AssignMulti) -> GenAndKill[T]: raise NotImplementedError @abstractmethod - def visit_set_mem(self, op: SetMem) -> GenAndKill: + def visit_set_mem(self, op: SetMem) -> GenAndKill[T]: raise NotImplementedError - def visit_call(self, op: Call) -> GenAndKill: + def visit_call(self, op: Call) -> GenAndKill[T]: return self.visit_register_op(op) - def visit_method_call(self, op: MethodCall) -> GenAndKill: + def visit_method_call(self, op: MethodCall) -> GenAndKill[T]: return self.visit_register_op(op) - def visit_load_error_value(self, op: LoadErrorValue) -> GenAndKill: + def visit_load_error_value(self, op: LoadErrorValue) -> GenAndKill[T]: return self.visit_register_op(op) - def visit_load_literal(self, op: LoadLiteral) -> GenAndKill: + def visit_load_literal(self, op: LoadLiteral) -> GenAndKill[T]: return self.visit_register_op(op) - def visit_get_attr(self, op: GetAttr) -> GenAndKill: + def visit_get_attr(self, op: GetAttr) -> GenAndKill[T]: return self.visit_register_op(op) - def visit_set_attr(self, op: SetAttr) -> GenAndKill: + def visit_set_attr(self, op: SetAttr) -> GenAndKill[T]: return self.visit_register_op(op) - def visit_load_static(self, op: LoadStatic) -> GenAndKill: + def visit_load_static(self, op: LoadStatic) -> GenAndKill[T]: return self.visit_register_op(op) - def visit_init_static(self, op: InitStatic) -> GenAndKill: + def visit_init_static(self, op: InitStatic) -> GenAndKill[T]: return self.visit_register_op(op) - def visit_tuple_get(self, op: TupleGet) -> GenAndKill: + def visit_tuple_get(self, op: TupleGet) -> GenAndKill[T]: return self.visit_register_op(op) - def visit_tuple_set(self, op: TupleSet) -> GenAndKill: + def visit_tuple_set(self, op: TupleSet) -> GenAndKill[T]: return self.visit_register_op(op) - def visit_box(self, op: Box) -> GenAndKill: + def visit_box(self, op: Box) -> GenAndKill[T]: return self.visit_register_op(op) - def visit_unbox(self, op: Unbox) -> GenAndKill: + def visit_unbox(self, op: Unbox) -> GenAndKill[T]: return self.visit_register_op(op) - def visit_cast(self, op: Cast) -> GenAndKill: + def visit_cast(self, op: Cast) -> GenAndKill[T]: return self.visit_register_op(op) - def visit_raise_standard_error(self, op: RaiseStandardError) -> GenAndKill: + def visit_raise_standard_error(self, op: RaiseStandardError) -> GenAndKill[T]: return self.visit_register_op(op) - def visit_call_c(self, op: CallC) -> GenAndKill: + def visit_call_c(self, op: CallC) -> GenAndKill[T]: return self.visit_register_op(op) - def visit_truncate(self, op: Truncate) -> GenAndKill: + def visit_truncate(self, op: Truncate) -> GenAndKill[T]: return self.visit_register_op(op) - def visit_load_global(self, op: LoadGlobal) -> GenAndKill: + def visit_load_global(self, op: LoadGlobal) -> GenAndKill[T]: return self.visit_register_op(op) - def visit_int_op(self, op: IntOp) -> GenAndKill: + def visit_int_op(self, op: IntOp) -> GenAndKill[T]: return self.visit_register_op(op) - def visit_comparison_op(self, op: ComparisonOp) -> GenAndKill: + def visit_comparison_op(self, op: ComparisonOp) -> GenAndKill[T]: return self.visit_register_op(op) - def visit_load_mem(self, op: LoadMem) -> GenAndKill: + def visit_load_mem(self, op: LoadMem) -> GenAndKill[T]: return self.visit_register_op(op) - def visit_get_element_ptr(self, op: GetElementPtr) -> GenAndKill: + def visit_get_element_ptr(self, op: GetElementPtr) -> GenAndKill[T]: return self.visit_register_op(op) - def visit_load_address(self, op: LoadAddress) -> GenAndKill: + def visit_load_address(self, op: LoadAddress) -> GenAndKill[T]: return self.visit_register_op(op) - def visit_keep_alive(self, op: KeepAlive) -> GenAndKill: + def visit_keep_alive(self, op: KeepAlive) -> GenAndKill[T]: return self.visit_register_op(op) -class DefinedVisitor(BaseAnalysisVisitor): +class DefinedVisitor(BaseAnalysisVisitor[Value]): """Visitor for finding defined registers. Note that this only deals with registers and not temporaries, on @@ -240,19 +240,19 @@ class DefinedVisitor(BaseAnalysisVisitor): def __init__(self, strict_errors: bool = False) -> None: self.strict_errors = strict_errors - def visit_branch(self, op: Branch) -> GenAndKill: + def visit_branch(self, op: Branch) -> GenAndKill[Value]: return set(), set() - def visit_return(self, op: Return) -> GenAndKill: + def visit_return(self, op: Return) -> GenAndKill[Value]: return set(), set() - def visit_unreachable(self, op: Unreachable) -> GenAndKill: + def visit_unreachable(self, op: Unreachable) -> GenAndKill[Value]: return set(), set() - def visit_register_op(self, op: RegisterOp) -> GenAndKill: + def visit_register_op(self, op: RegisterOp) -> GenAndKill[Value]: return set(), set() - def visit_assign(self, op: Assign) -> GenAndKill: + def visit_assign(self, op: Assign) -> GenAndKill[Value]: # Loading an error value may undefine the register. if (isinstance(op.src, LoadErrorValue) and (op.src.undefines or self.strict_errors)): @@ -260,11 +260,11 @@ def visit_assign(self, op: Assign) -> GenAndKill: else: return {op.dest}, set() - def visit_assign_multi(self, op: AssignMulti) -> GenAndKill: + def visit_assign_multi(self, op: AssignMulti) -> GenAndKill[Value]: # Array registers are special and we don't track the definedness of them. return set(), set() - def visit_set_mem(self, op: SetMem) -> GenAndKill: + def visit_set_mem(self, op: SetMem) -> GenAndKill[Value]: return set(), set() @@ -307,31 +307,31 @@ def analyze_must_defined_regs( universe=set(regs)) -class BorrowedArgumentsVisitor(BaseAnalysisVisitor): +class BorrowedArgumentsVisitor(BaseAnalysisVisitor[Value]): def __init__(self, args: Set[Value]) -> None: self.args = args - def visit_branch(self, op: Branch) -> GenAndKill: + def visit_branch(self, op: Branch) -> GenAndKill[Value]: return set(), set() - def visit_return(self, op: Return) -> GenAndKill: + def visit_return(self, op: Return) -> GenAndKill[Value]: return set(), set() - def visit_unreachable(self, op: Unreachable) -> GenAndKill: + def visit_unreachable(self, op: Unreachable) -> GenAndKill[Value]: return set(), set() - def visit_register_op(self, op: RegisterOp) -> GenAndKill: + def visit_register_op(self, op: RegisterOp) -> GenAndKill[Value]: return set(), set() - def visit_assign(self, op: Assign) -> GenAndKill: + def visit_assign(self, op: Assign) -> GenAndKill[Value]: if op.dest in self.args: return set(), {op.dest} return set(), set() - def visit_assign_multi(self, op: AssignMulti) -> GenAndKill: + def visit_assign_multi(self, op: AssignMulti) -> GenAndKill[Value]: return set(), set() - def visit_set_mem(self, op: SetMem) -> GenAndKill: + def visit_set_mem(self, op: SetMem) -> GenAndKill[Value]: return set(), set() @@ -352,26 +352,26 @@ def analyze_borrowed_arguments( universe=borrowed) -class UndefinedVisitor(BaseAnalysisVisitor): - def visit_branch(self, op: Branch) -> GenAndKill: +class UndefinedVisitor(BaseAnalysisVisitor[Value]): + def visit_branch(self, op: Branch) -> GenAndKill[Value]: return set(), set() - def visit_return(self, op: Return) -> GenAndKill: + def visit_return(self, op: Return) -> GenAndKill[Value]: return set(), set() - def visit_unreachable(self, op: Unreachable) -> GenAndKill: + def visit_unreachable(self, op: Unreachable) -> GenAndKill[Value]: return set(), set() - def visit_register_op(self, op: RegisterOp) -> GenAndKill: + def visit_register_op(self, op: RegisterOp) -> GenAndKill[Value]: return set(), {op} if not op.is_void else set() - def visit_assign(self, op: Assign) -> GenAndKill: + def visit_assign(self, op: Assign) -> GenAndKill[Value]: return set(), {op.dest} - def visit_assign_multi(self, op: AssignMulti) -> GenAndKill: + def visit_assign_multi(self, op: AssignMulti) -> GenAndKill[Value]: return set(), {op.dest} - def visit_set_mem(self, op: SetMem) -> GenAndKill: + def visit_set_mem(self, op: SetMem) -> GenAndKill[Value]: return set(), set() @@ -402,33 +402,33 @@ def non_trivial_sources(op: Op) -> Set[Value]: return result -class LivenessVisitor(BaseAnalysisVisitor): - def visit_branch(self, op: Branch) -> GenAndKill: +class LivenessVisitor(BaseAnalysisVisitor[Value]): + def visit_branch(self, op: Branch) -> GenAndKill[Value]: return non_trivial_sources(op), set() - def visit_return(self, op: Return) -> GenAndKill: + def visit_return(self, op: Return) -> GenAndKill[Value]: if not isinstance(op.value, Integer): return {op.value}, set() else: return set(), set() - def visit_unreachable(self, op: Unreachable) -> GenAndKill: + def visit_unreachable(self, op: Unreachable) -> GenAndKill[Value]: return set(), set() - def visit_register_op(self, op: RegisterOp) -> GenAndKill: + def visit_register_op(self, op: RegisterOp) -> GenAndKill[Value]: gen = non_trivial_sources(op) if not op.is_void: return gen, {op} else: return gen, set() - def visit_assign(self, op: Assign) -> GenAndKill: + def visit_assign(self, op: Assign) -> GenAndKill[Value]: return non_trivial_sources(op), {op.dest} - def visit_assign_multi(self, op: AssignMulti) -> GenAndKill: + def visit_assign_multi(self, op: AssignMulti) -> GenAndKill[Value]: return non_trivial_sources(op), {op.dest} - def visit_set_mem(self, op: SetMem) -> GenAndKill: + def visit_set_mem(self, op: SetMem) -> GenAndKill[Value]: return non_trivial_sources(op), set() @@ -452,12 +452,9 @@ def analyze_live_regs(blocks: List[BasicBlock], MAYBE_ANALYSIS = 1 -# TODO the return type of this function is too complicated. Abstract it into its -# own class. - def run_analysis(blocks: List[BasicBlock], cfg: CFG, - gen_and_kill: OpVisitor[Tuple[Set[T], Set[T]]], + gen_and_kill: OpVisitor[GenAndKill[T]], initial: Set[T], kind: int, backward: bool, diff --git a/mypyc/analysis/selfleaks.py b/mypyc/analysis/selfleaks.py new file mode 100644 index 0000000000000..ae3731a40ac30 --- /dev/null +++ b/mypyc/analysis/selfleaks.py @@ -0,0 +1,153 @@ +from typing import List, Set, Tuple + +from mypyc.ir.ops import ( + OpVisitor, Register, Goto, Assign, AssignMulti, SetMem, Call, MethodCall, LoadErrorValue, + LoadLiteral, GetAttr, SetAttr, LoadStatic, InitStatic, TupleGet, TupleSet, Box, Unbox, + Cast, RaiseStandardError, CallC, Truncate, LoadGlobal, IntOp, ComparisonOp, LoadMem, + GetElementPtr, LoadAddress, KeepAlive, Branch, Return, Unreachable, RegisterOp, BasicBlock +) +from mypyc.ir.rtypes import RInstance +from mypyc.analysis.dataflow import MAYBE_ANALYSIS, run_analysis, AnalysisResult, CFG + +GenAndKill = Tuple[Set[None], Set[None]] + +CLEAN: GenAndKill = (set(), set()) +DIRTY: GenAndKill = ({None}, {None}) + + +class SelfLeakedVisitor(OpVisitor[GenAndKill]): + """Analyze whether 'self' may be seen by arbitrary code in '__init__'. + + More formally, the set is not empty if along some path from IR entry point + arbitrary code could have been executed that has access to 'self'. + + (We don't consider access via 'gc.get_objects()'.) + """ + + def __init__(self, self_reg: Register) -> None: + self.self_reg = self_reg + + def visit_goto(self, op: Goto) -> GenAndKill: + return CLEAN + + def visit_branch(self, op: Branch) -> GenAndKill: + return CLEAN + + def visit_return(self, op: Return) -> GenAndKill: + # Consider all exits from the function 'dirty' since they implicitly + # cause 'self' to be returned. + return DIRTY + + def visit_unreachable(self, op: Unreachable) -> GenAndKill: + return CLEAN + + def visit_assign(self, op: Assign) -> GenAndKill: + if op.src is self.self_reg or op.dest is self.self_reg: + return DIRTY + return CLEAN + + def visit_assign_multi(self, op: AssignMulti) -> GenAndKill: + return CLEAN + + def visit_set_mem(self, op: SetMem) -> GenAndKill: + return CLEAN + + def visit_call(self, op: Call) -> GenAndKill: + fn = op.fn + if fn.class_name and fn.name == '__init__': + self_type = op.fn.sig.args[0].type + assert isinstance(self_type, RInstance) + cl = self_type.class_ir + if not cl.init_self_leak: + return CLEAN + return self.check_register_op(op) + + def visit_method_call(self, op: MethodCall) -> GenAndKill: + return self.check_register_op(op) + + def visit_load_error_value(self, op: LoadErrorValue) -> GenAndKill: + return CLEAN + + def visit_load_literal(self, op: LoadLiteral) -> GenAndKill: + return CLEAN + + def visit_get_attr(self, op: GetAttr) -> GenAndKill: + cl = op.class_type.class_ir + if cl.get_method(op.attr): + # Property -- calls a function + return self.check_register_op(op) + return CLEAN + + def visit_set_attr(self, op: SetAttr) -> GenAndKill: + cl = op.class_type.class_ir + if cl.get_method(op.attr): + # Property - calls a function + return self.check_register_op(op) + return CLEAN + + def visit_load_static(self, op: LoadStatic) -> GenAndKill: + return CLEAN + + def visit_init_static(self, op: InitStatic) -> GenAndKill: + return self.check_register_op(op) + + def visit_tuple_get(self, op: TupleGet) -> GenAndKill: + return CLEAN + + def visit_tuple_set(self, op: TupleSet) -> GenAndKill: + return self.check_register_op(op) + + def visit_box(self, op: Box) -> GenAndKill: + return self.check_register_op(op) + + def visit_unbox(self, op: Unbox) -> GenAndKill: + return self.check_register_op(op) + + def visit_cast(self, op: Cast) -> GenAndKill: + return self.check_register_op(op) + + def visit_raise_standard_error(self, op: RaiseStandardError) -> GenAndKill: + return CLEAN + + def visit_call_c(self, op: CallC) -> GenAndKill: + return self.check_register_op(op) + + def visit_truncate(self, op: Truncate) -> GenAndKill: + return CLEAN + + def visit_load_global(self, op: LoadGlobal) -> GenAndKill: + return CLEAN + + def visit_int_op(self, op: IntOp) -> GenAndKill: + return CLEAN + + def visit_comparison_op(self, op: ComparisonOp) -> GenAndKill: + return CLEAN + + def visit_load_mem(self, op: LoadMem) -> GenAndKill: + return CLEAN + + def visit_get_element_ptr(self, op: GetElementPtr) -> GenAndKill: + return CLEAN + + def visit_load_address(self, op: LoadAddress) -> GenAndKill: + return CLEAN + + def visit_keep_alive(self, op: KeepAlive) -> GenAndKill: + return CLEAN + + def check_register_op(self, op: RegisterOp) -> GenAndKill: + if any(src is self.self_reg for src in op.sources()): + return DIRTY + return CLEAN + + +def analyze_self_leaks(blocks: List[BasicBlock], + self_reg: Register, + cfg: CFG) -> AnalysisResult[None]: + return run_analysis(blocks=blocks, + cfg=cfg, + gen_and_kill=SelfLeakedVisitor(self_reg), + initial=set(), + backward=False, + kind=MAYBE_ANALYSIS) diff --git a/mypyc/codegen/emitclass.py b/mypyc/codegen/emitclass.py index 437b50444d633..ef36da3c414e6 100644 --- a/mypyc/codegen/emitclass.py +++ b/mypyc/codegen/emitclass.py @@ -284,7 +284,8 @@ def emit_line() -> None: emitter.emit_line(native_function_header(cl.ctor, emitter) + ';') emit_line() - generate_new_for_class(cl, new_name, vtable_name, setup_name, emitter) + init_fn = cl.get_method('__init__') + generate_new_for_class(cl, new_name, vtable_name, setup_name, init_fn, emitter) emit_line() generate_traverse_for_class(cl, traverse_name, emitter) emit_line() @@ -539,7 +540,7 @@ def generate_setup_for_class(cl: ClassIR, for base in reversed(cl.base_mro): for attr, rtype in base.attributes.items(): - emitter.emit_line('self->{} = {};'.format( + emitter.emit_line(r'self->{} = {};'.format( emitter.attr(attr), emitter.c_undefined_value(rtype))) # Initialize attributes to default values, if necessary @@ -608,8 +609,11 @@ def generate_init_for_class(cl: ClassIR, emitter.emit_line( f'{func_name}(PyObject *self, PyObject *args, PyObject *kwds)') emitter.emit_line('{') - emitter.emit_line('return {}{}(self, args, kwds) != NULL ? 0 : -1;'.format( - PREFIX, init_fn.cname(emitter.names))) + if cl.allow_interpreted_subclasses or cl.builtin_base: + emitter.emit_line('return {}{}(self, args, kwds) != NULL ? 0 : -1;'.format( + PREFIX, init_fn.cname(emitter.names))) + else: + emitter.emit_line('return 0;') emitter.emit_line('}') return func_name @@ -619,6 +623,7 @@ def generate_new_for_class(cl: ClassIR, func_name: str, vtable_name: str, setup_name: str, + init_fn: Optional[FuncIR], emitter: Emitter) -> None: emitter.emit_line('static PyObject *') emitter.emit_line( @@ -633,7 +638,24 @@ def generate_new_for_class(cl: ClassIR, emitter.emit_line('return NULL;') emitter.emit_line('}') - emitter.emit_line(f'return {setup_name}(type);') + if (not init_fn + or cl.allow_interpreted_subclasses + or cl.builtin_base + or cl.is_serializable()): + # Match Python semantics -- __new__ doesn't call __init__. + emitter.emit_line(f'return {setup_name}(type);') + else: + # __new__ of a native class implicitly calls __init__ so that we + # can enforce that instances are always properly initialized. This + # is needed to support always defined attributes. + emitter.emit_line(f'PyObject *self = {setup_name}(type);') + emitter.emit_lines('if (self == NULL)', + ' return NULL;') + emitter.emit_line( + f'PyObject *ret = {PREFIX}{init_fn.cname(emitter.names)}(self, args, kwds);') + emitter.emit_lines('if (ret == NULL)', + ' return NULL;') + emitter.emit_line('return self;') emitter.emit_line('}') @@ -846,12 +868,19 @@ def generate_getter(cl: ClassIR, cl.struct_name(emitter.names))) emitter.emit_line('{') attr_expr = f'self->{attr_field}' - emitter.emit_undefined_attr_check(rtype, attr_expr, '==', unlikely=True) - emitter.emit_line('PyErr_SetString(PyExc_AttributeError,') - emitter.emit_line(' "attribute {} of {} undefined");'.format(repr(attr), - repr(cl.name))) - emitter.emit_line('return NULL;') - emitter.emit_line('}') + + # HACK: Don't consider refcounted values as always defined, since it's possible to + # access uninitialized values via 'gc.get_objects()'. Accessing non-refcounted + # values is benign. + always_defined = cl.is_always_defined(attr) and not rtype.is_refcounted + + if not always_defined: + emitter.emit_undefined_attr_check(rtype, attr_expr, '==', unlikely=True) + emitter.emit_line('PyErr_SetString(PyExc_AttributeError,') + emitter.emit_line(' "attribute {} of {} undefined");'.format(repr(attr), + repr(cl.name))) + emitter.emit_line('return NULL;') + emitter.emit_line('}') emitter.emit_inc_ref(f'self->{attr_field}', rtype) emitter.emit_box(f'self->{attr_field}', 'retval', rtype, declare_dest=True) emitter.emit_line('return retval;') @@ -878,14 +907,22 @@ def generate_setter(cl: ClassIR, emitter.emit_line('return -1;') emitter.emit_line('}') + # HACK: Don't consider refcounted values as always defined, since it's possible to + # access uninitialized values via 'gc.get_objects()'. Accessing non-refcounted + # values is benign. + always_defined = cl.is_always_defined(attr) and not rtype.is_refcounted + if rtype.is_refcounted: attr_expr = f'self->{attr_field}' - emitter.emit_undefined_attr_check(rtype, attr_expr, '!=') - emitter.emit_dec_ref(f'self->{attr_field}', rtype) - emitter.emit_line('}') + if not always_defined: + emitter.emit_undefined_attr_check(rtype, attr_expr, '!=') + emitter.emit_dec_ref('self->{}'.format(attr_field), rtype) + if not always_defined: + emitter.emit_line('}') if deletable: emitter.emit_line('if (value != NULL) {') + if rtype.is_unboxed: emitter.emit_unbox('value', 'tmp', rtype, error=ReturnHandler('-1'), declare_dest=True) elif is_same_type(rtype, object_rprimitive): diff --git a/mypyc/codegen/emitfunc.py b/mypyc/codegen/emitfunc.py index 91b3a539adf57..f4ed657c467ff 100644 --- a/mypyc/codegen/emitfunc.py +++ b/mypyc/codegen/emitfunc.py @@ -12,7 +12,7 @@ LoadStatic, InitStatic, TupleGet, TupleSet, Call, IncRef, DecRef, Box, Cast, Unbox, BasicBlock, Value, MethodCall, Unreachable, NAMESPACE_STATIC, NAMESPACE_TYPE, NAMESPACE_MODULE, RaiseStandardError, CallC, LoadGlobal, Truncate, IntOp, LoadMem, GetElementPtr, - LoadAddress, ComparisonOp, SetMem, Register, LoadLiteral, AssignMulti, KeepAlive + LoadAddress, ComparisonOp, SetMem, Register, LoadLiteral, AssignMulti, KeepAlive, ERR_FALSE ) from mypyc.ir.rtypes import ( RType, RTuple, RArray, is_tagged, is_int32_rprimitive, is_int64_rprimitive, RStruct, @@ -131,6 +131,13 @@ def visit_goto(self, op: Goto) -> None: def visit_branch(self, op: Branch) -> None: true, false = op.true, op.false + if op.op == Branch.IS_ERROR and isinstance(op.value, GetAttr) and not op.negated: + op2 = op.value + if op2.class_type.class_ir.is_always_defined(op2.attr): + # Getting an always defined attribute never fails, so the branch can be omitted. + if false is not self.next_block: + self.emit_line('goto {};'.format(self.label(false))) + return negated = op.negated negated_rare = False if true is self.next_block and op.traceback_entry is None: @@ -302,37 +309,39 @@ def visit_get_attr(self, op: GetAttr) -> None: # Otherwise, use direct or offset struct access. attr_expr = self.get_attr_expr(obj, op, decl_cl) self.emitter.emit_line(f'{dest} = {attr_expr};') - self.emitter.emit_undefined_attr_check( - attr_rtype, dest, '==', unlikely=True - ) - exc_class = 'PyExc_AttributeError' + always_defined = cl.is_always_defined(op.attr) merged_branch = None - branch = self.next_branch() - if branch is not None: - if (branch.value is op - and branch.op == Branch.IS_ERROR - and branch.traceback_entry is not None - and not branch.negated): - # Generate code for the following branch here to avoid - # redundant branches in the generate code. - self.emit_attribute_error(branch, cl.name, op.attr) - self.emit_line('goto %s;' % self.label(branch.true)) - merged_branch = branch - self.emitter.emit_line('}') - if not merged_branch: - self.emitter.emit_line( - 'PyErr_SetString({}, "attribute {} of {} undefined");'.format( - exc_class, repr(op.attr), repr(cl.name))) + if not always_defined: + self.emitter.emit_undefined_attr_check( + attr_rtype, dest, '==', unlikely=True + ) + branch = self.next_branch() + if branch is not None: + if (branch.value is op + and branch.op == Branch.IS_ERROR + and branch.traceback_entry is not None + and not branch.negated): + # Generate code for the following branch here to avoid + # redundant branches in the generate code. + self.emit_attribute_error(branch, cl.name, op.attr) + self.emit_line('goto %s;' % self.label(branch.true)) + merged_branch = branch + self.emitter.emit_line('}') + if not merged_branch: + exc_class = 'PyExc_AttributeError' + self.emitter.emit_line( + 'PyErr_SetString({}, "attribute {} of {} undefined");'.format( + exc_class, repr(op.attr), repr(cl.name))) if attr_rtype.is_refcounted: - if not merged_branch: + if not merged_branch and not always_defined: self.emitter.emit_line('} else {') self.emitter.emit_inc_ref(dest, attr_rtype) if merged_branch: if merged_branch.false is not self.next_block: self.emit_line('goto %s;' % self.label(merged_branch.false)) self.op_index += 1 - else: + elif not always_defined: self.emitter.emit_line('}') def next_branch(self) -> Optional[Branch]: @@ -343,7 +352,8 @@ def next_branch(self) -> Optional[Branch]: return None def visit_set_attr(self, op: SetAttr) -> None: - dest = self.reg(op) + if op.error_kind == ERR_FALSE: + dest = self.reg(op) obj = self.reg(op.obj) src = self.reg(op.src) rtype = op.class_type @@ -351,6 +361,8 @@ def visit_set_attr(self, op: SetAttr) -> None: attr_rtype, decl_cl = cl.attr_details(op.attr) if cl.get_method(op.attr): # Again, use vtable access for properties... + assert not op.is_init and op.error_kind == ERR_FALSE, '%s %d %d %s' % ( + op.attr, op.is_init, op.error_kind, rtype) version = '_TRAIT' if cl.is_trait else '' self.emit_line('%s = CPY_SET_ATTR%s(%s, %s, %d, %s, %s, %s); /* %s */' % ( dest, @@ -365,15 +377,18 @@ def visit_set_attr(self, op: SetAttr) -> None: else: # ...and struct access for normal attributes. attr_expr = self.get_attr_expr(obj, op, decl_cl) - if attr_rtype.is_refcounted: - self.emitter.emit_undefined_attr_check(attr_rtype, attr_expr, '!=') - self.emitter.emit_dec_ref(attr_expr, attr_rtype) - self.emitter.emit_line('}') - # This steal the reference to src, so we don't need to increment the arg - self.emitter.emit_lines( - f'{attr_expr} = {src};', - f'{dest} = 1;', - ) + if not op.is_init: + always_defined = cl.is_always_defined(op.attr) + if not always_defined: + self.emitter.emit_undefined_attr_check(attr_rtype, attr_expr, '!=') + if attr_rtype.is_refcounted: + self.emitter.emit_dec_ref(attr_expr, attr_rtype) + if not always_defined: + self.emitter.emit_line('}') + # This steals the reference to src, so we don't need to increment the arg + self.emitter.emit_line(f'{attr_expr} = {src};') + if op.error_kind == ERR_FALSE: + self.emitter.emit_line(f'{dest} = 1;') PREFIX_MAP: Final = { NAMESPACE_STATIC: STATIC_PREFIX, diff --git a/mypyc/doc/differences_from_python.rst b/mypyc/doc/differences_from_python.rst index 3bebf4049e7cb..16faae60303fc 100644 --- a/mypyc/doc/differences_from_python.rst +++ b/mypyc/doc/differences_from_python.rst @@ -171,6 +171,43 @@ Examples of early and late binding:: var = x # Module-level variable lib.func() # Accessing library that is not compiled +Pickling and copying objects +---------------------------- + +Mypyc tries to enforce that instances native classes are properly +initialized by calling ``__init__`` implicitly when constructing +objects, even if objects are constructed through ``pickle``, +``copy.copy`` or ``copy.deepcopy``, for example. + +If a native class doesn't support calling ``__init__`` without arguments, +you can't pickle or copy instances of the class. Use the +``mypy_extensions.mypyc_attr`` class decorator to override this behavior +and enable pickling through the ``serializable`` flag:: + + from mypy_extensions import mypyc_attr + import pickle + + @mypyc_attr(serializable=True) + class Cls: + def __init__(self, n: int) -> None: + self.n = n + + data = pickle.dumps(Cls(5)) + obj = pickle.loads(data) # OK + +Additional notes: + +* All subclasses inherit the ``serializable`` flag. +* If a class has the ``allow_interpreted_subclasses`` attribute, it + implicitly supports serialization. +* Enabling serialization may slow down attribute access, since compiled + code has to be always prepared to raise ``AttributeError`` in case an + attribute is not defined at runtime. +* If you try to pickle an object without setting the ``serializable`` + flag, you'll get a ``TypeError`` about missing arguments to + ``__init__``. + + Monkey patching --------------- diff --git a/mypyc/ir/class_ir.py b/mypyc/ir/class_ir.py index 2e3e2b15c9301..197b267633d71 100644 --- a/mypyc/ir/class_ir.py +++ b/mypyc/ir/class_ir.py @@ -106,6 +106,19 @@ def __init__(self, name: str, module_name: str, is_trait: bool = False, # Does this class need getseters to be generated for its attributes? (getseters are also # added if is_generated is False) self.needs_getseters = False + # Is this class declared as serializable (supports copy.copy + # and pickle) using @mypyc_attr(serializable=True)? + # + # Additionally, any class with this attribute False but with + # an __init__ that can be called without any arguments is + # *implicitly serializable*. In this case __init__ will be + # called during deserialization without arguments. If this is + # True, we match Python semantics and __init__ won't be called + # during deserialization. + # + # This impacts also all subclasses. Use is_serializable() to + # also consider base classes. + self._serializable = False # If this a subclass of some built-in python class, the name # of the object for that class. We currently only support this # in a few ad-hoc cases. @@ -153,6 +166,19 @@ def __init__(self, name: str, module_name: str, is_trait: bool = False, # None if separate compilation prevents this from working self.children: Optional[List[ClassIR]] = [] + # Instance attributes that are initialized in the class body. + self.attrs_with_defaults: Set[str] = set() + + # Attributes that are always initialized in __init__ or class body + # (inferred in mypyc.analysis.attrdefined using interprocedural analysis) + self._always_initialized_attrs: Set[str] = set() + + # Attributes that are sometimes initialized in __init__ + self._sometimes_initialized_attrs: Set[str] = set() + + # If True, __init__ can make 'self' visible to unanalyzed/arbitrary code + self.init_self_leak = False + def __repr__(self) -> str: return ( "ClassIR(" @@ -231,6 +257,11 @@ def is_deletable(self, name: str) -> bool: return True return False + def is_always_defined(self, name: str) -> bool: + if self.is_deletable(name): + return False + return name in self._always_initialized_attrs + def name_prefix(self, names: NameGenerator) -> str: return names.private_name(self.module_name, self.name) @@ -279,6 +310,9 @@ def concrete_subclasses(self) -> Optional[List['ClassIR']]: # to get stable order. return sorted(concrete, key=lambda c: (len(c.children or []), c.name)) + def is_serializable(self) -> bool: + return any(ci._serializable for ci in self.mro) + def serialize(self) -> JsonDict: return { 'name': self.name, @@ -292,6 +326,7 @@ def serialize(self) -> JsonDict: 'has_dict': self.has_dict, 'allow_interpreted_subclasses': self.allow_interpreted_subclasses, 'needs_getseters': self.needs_getseters, + '_serializable': self._serializable, 'builtin_base': self.builtin_base, 'ctor': self.ctor.serialize(), # We serialize dicts as lists to ensure order is preserved @@ -327,6 +362,10 @@ def serialize(self) -> JsonDict: cir.fullname for cir in self.children ] if self.children is not None else None, 'deletable': self.deletable, + 'attrs_with_defaults': sorted(self.attrs_with_defaults), + '_always_initialized_attrs': sorted(self._always_initialized_attrs), + '_sometimes_initialized_attrs': sorted(self._sometimes_initialized_attrs), + 'init_self_leak': self.init_self_leak, } @classmethod @@ -344,6 +383,7 @@ def deserialize(cls, data: JsonDict, ctx: 'DeserMaps') -> 'ClassIR': ir.has_dict = data['has_dict'] ir.allow_interpreted_subclasses = data['allow_interpreted_subclasses'] ir.needs_getseters = data['needs_getseters'] + ir._serializable = data['_serializable'] ir.builtin_base = data['builtin_base'] ir.ctor = FuncDecl.deserialize(data['ctor'], ctx) ir.attributes = OrderedDict( @@ -376,6 +416,10 @@ def deserialize(cls, data: JsonDict, ctx: 'DeserMaps') -> 'ClassIR': ir.base_mro = [ctx.classes[s] for s in data['base_mro']] ir.children = data['children'] and [ctx.classes[s] for s in data['children']] ir.deletable = data['deletable'] + ir.attrs_with_defaults = set(data['attrs_with_defaults']) + ir._always_initialized_attrs = set(data['_always_initialized_attrs']) + ir._sometimes_initialized_attrs = set(data['_sometimes_initialized_attrs']) + ir.init_self_leak = data['init_self_leak'] return ir diff --git a/mypyc/ir/ops.py b/mypyc/ir/ops.py index ecd2293c657f7..786cb018f96b5 100644 --- a/mypyc/ir/ops.py +++ b/mypyc/ir/ops.py @@ -630,6 +630,14 @@ def __init__(self, obj: Value, attr: str, src: Value, line: int) -> None: assert isinstance(obj.type, RInstance), 'Attribute access not supported: %s' % obj.type self.class_type = obj.type self.type = bool_rprimitive + # If True, we can safely assume that the attribute is previously undefined + # and we don't use a setter + self.is_init = False + + def mark_as_initializer(self) -> None: + self.is_init = True + self.error_kind = ERR_NEVER + self.type = void_rtype def sources(self) -> List[Value]: return [self.obj, self.src] diff --git a/mypyc/ir/pprint.py b/mypyc/ir/pprint.py index aab8dc86664ff..753965cb1e9c4 100644 --- a/mypyc/ir/pprint.py +++ b/mypyc/ir/pprint.py @@ -11,7 +11,7 @@ LoadStatic, InitStatic, TupleGet, TupleSet, IncRef, DecRef, Call, MethodCall, Cast, Box, Unbox, RaiseStandardError, CallC, Truncate, LoadGlobal, IntOp, ComparisonOp, LoadMem, SetMem, GetElementPtr, LoadAddress, Register, Value, OpVisitor, BasicBlock, ControlOp, LoadLiteral, - AssignMulti, KeepAlive, Op + AssignMulti, KeepAlive, Op, ERR_NEVER ) from mypyc.ir.func_ir import FuncIR, all_values_full from mypyc.ir.module_ir import ModuleIRs @@ -80,7 +80,12 @@ def visit_get_attr(self, op: GetAttr) -> str: return self.format('%r = %r.%s', op, op.obj, op.attr) def visit_set_attr(self, op: SetAttr) -> str: - return self.format('%r.%s = %r; %r = is_error', op.obj, op.attr, op.src, op) + if op.is_init: + assert op.error_kind == ERR_NEVER + # Initialization and direct struct access can never fail + return self.format('%r.%s = %r', op.obj, op.attr, op.src) + else: + return self.format('%r.%s = %r; %r = is_error', op.obj, op.attr, op.src, op) def visit_load_static(self, op: LoadStatic) -> str: ann = f' ({repr(op.ann)})' if op.ann else '' diff --git a/mypyc/irbuild/classdef.py b/mypyc/irbuild/classdef.py index 9a458181dc6c3..7cc08b73494fb 100644 --- a/mypyc/irbuild/classdef.py +++ b/mypyc/irbuild/classdef.py @@ -1,7 +1,7 @@ """Transform class definitions from the mypy AST form to IR.""" from abc import abstractmethod -from typing import Callable, List, Optional, Tuple +from typing import Callable, List, Optional, Set, Tuple from typing_extensions import Final from mypy.nodes import ( @@ -214,7 +214,10 @@ def add_attr(self, lvalue: NameExpr, stmt: AssignmentStmt) -> None: self.builder.init_final_static(lvalue, value, self.cdef.name) def finalize(self, ir: ClassIR) -> None: - generate_attr_defaults(self.builder, self.cdef, self.skip_attr_default) + attrs_with_defaults, default_assignments = find_attr_initializers( + self.builder, self.cdef, self.skip_attr_default) + ir.attrs_with_defaults.update(attrs_with_defaults) + generate_attr_defaults_init(self.builder, self.cdef, default_assignments) create_ne_from_eq(self.builder, self.cdef) @@ -524,9 +527,11 @@ def add_non_ext_class_attr(builder: IRBuilder, attr_to_cache.append((lvalue, object_rprimitive)) -def generate_attr_defaults(builder: IRBuilder, cdef: ClassDef, - skip: Optional[Callable[[str, AssignmentStmt], bool]] = None) -> None: - """Generate an initialization method for default attr values (from class vars). +def find_attr_initializers(builder: IRBuilder, + cdef: ClassDef, + skip: Optional[Callable[[str, AssignmentStmt], bool]] = None, + ) -> Tuple[Set[str], List[AssignmentStmt]]: + """Find initializers of attributes in a class body. If provided, the skip arg should be a callable which will return whether to skip generating a default for an attribute. It will be passed the name of @@ -534,7 +539,9 @@ def generate_attr_defaults(builder: IRBuilder, cdef: ClassDef, """ cls = builder.mapper.type_to_ir[cdef.info] if cls.builtin_base: - return + return set(), [] + + attrs_with_defaults = set() # Pull out all assignments in classes in the mro so we can initialize them # TODO: Support nested statements @@ -558,10 +565,30 @@ def generate_attr_defaults(builder: IRBuilder, cdef: ClassDef, if skip is not None and skip(name, stmt): continue + attr_type = cls.attr_type(name) + + # If the attribute is initialized to None and type isn't optional, + # doesn't initialize it to anything (special case for "# type:" comments). + if isinstance(stmt.rvalue, RefExpr) and stmt.rvalue.fullname == 'builtins.None': + if (not is_optional_type(attr_type) and not is_object_rprimitive(attr_type) + and not is_none_rprimitive(attr_type)): + continue + + attrs_with_defaults.add(name) default_assignments.append(stmt) + return attrs_with_defaults, default_assignments + + +def generate_attr_defaults_init(builder: IRBuilder, + cdef: ClassDef, + default_assignments: List[AssignmentStmt]) -> None: + """Generate an initialization method for default attr values (from class vars).""" if not default_assignments: return + cls = builder.mapper.type_to_ir[cdef.info] + if cls.builtin_base: + return with builder.enter_method(cls, '__mypyc_defaults_setup', bool_rprimitive): self_var = builder.self() @@ -571,15 +598,11 @@ def generate_attr_defaults(builder: IRBuilder, cdef: ClassDef, if not stmt.is_final_def and not is_constant(stmt.rvalue): builder.warning('Unsupported default attribute value', stmt.rvalue.line) - # If the attribute is initialized to None and type isn't optional, - # don't initialize it to anything. attr_type = cls.attr_type(lvalue.name) - if isinstance(stmt.rvalue, RefExpr) and stmt.rvalue.fullname == 'builtins.None': - if (not is_optional_type(attr_type) and not is_object_rprimitive(attr_type) - and not is_none_rprimitive(attr_type)): - continue val = builder.coerce(builder.accept(stmt.rvalue), attr_type, stmt.line) - builder.add(SetAttr(self_var, lvalue.name, val, -1)) + init = SetAttr(self_var, lvalue.name, val, -1) + init.mark_as_initializer() + builder.add(init) builder.add(Return(builder.true())) diff --git a/mypyc/irbuild/function.py b/mypyc/irbuild/function.py index 275d3449f8128..2c771df08809c 100644 --- a/mypyc/irbuild/function.py +++ b/mypyc/irbuild/function.py @@ -11,7 +11,7 @@ """ from typing import ( - DefaultDict, NamedTuple, Optional, List, Sequence, Tuple, Union, Dict, + DefaultDict, NamedTuple, Optional, List, Sequence, Tuple, Union, Dict ) from mypy.nodes import ( diff --git a/mypyc/irbuild/main.py b/mypyc/irbuild/main.py index f2c49359b69a0..52c9d5cf32dfe 100644 --- a/mypyc/irbuild/main.py +++ b/mypyc/irbuild/main.py @@ -40,6 +40,7 @@ def f(x: int) -> int: from mypyc.irbuild.builder import IRBuilder from mypyc.irbuild.visitor import IRBuilderVisitor from mypyc.irbuild.mapper import Mapper +from mypyc.analysis.attrdefined import analyze_always_defined_attrs # The stubs for callable contextmanagers are busted so cast it to the @@ -52,7 +53,7 @@ def f(x: int) -> int: def build_ir(modules: List[MypyFile], graph: Graph, types: Dict[Expression, Type], - mapper: 'Mapper', + mapper: Mapper, options: CompilerOptions, errors: Errors) -> ModuleIRs: """Build IR for a set of modules that have been type-checked by mypy.""" @@ -90,6 +91,8 @@ def build_ir(modules: List[MypyFile], result[module.fullname] = module_ir class_irs.extend(builder.classes) + analyze_always_defined_attrs(class_irs) + # Compute vtables. for cir in class_irs: if cir.is_ext_class: diff --git a/mypyc/irbuild/mapper.py b/mypyc/irbuild/mapper.py index 901ea49fc2fae..576eacc141df1 100644 --- a/mypyc/irbuild/mapper.py +++ b/mypyc/irbuild/mapper.py @@ -2,7 +2,7 @@ from typing import Dict, Optional -from mypy.nodes import FuncDef, TypeInfo, SymbolNode, ArgKind, ARG_STAR, ARG_STAR2 +from mypy.nodes import FuncDef, TypeInfo, SymbolNode, RefExpr, ArgKind, ARG_STAR, ARG_STAR2, GDEF from mypy.types import ( Instance, Type, CallableType, LiteralType, TypedDictType, UnboundType, PartialType, UninhabitedType, Overloaded, UnionType, TypeType, AnyType, NoneTyp, TupleType, TypeVarType, @@ -160,3 +160,17 @@ def fdef_to_sig(self, fdef: FuncDef) -> FuncSignature: if fdef.name in ('__eq__', '__ne__', '__lt__', '__gt__', '__le__', '__ge__'): ret = object_rprimitive return FuncSignature(args, ret) + + def is_native_module(self, module: str) -> bool: + """Is the given module one compiled by mypyc?""" + return module in self.group_map + + def is_native_ref_expr(self, expr: RefExpr) -> bool: + if expr.node is None: + return False + if '.' in expr.node.fullname: + return self.is_native_module(expr.node.fullname.rpartition('.')[0]) + return True + + def is_native_module_ref_expr(self, expr: RefExpr) -> bool: + return self.is_native_ref_expr(expr) and expr.kind == GDEF diff --git a/mypyc/irbuild/prepare.py b/mypyc/irbuild/prepare.py index 2cb3deac97002..cc9505853db15 100644 --- a/mypyc/irbuild/prepare.py +++ b/mypyc/irbuild/prepare.py @@ -177,6 +177,9 @@ def prepare_class_def(path: str, module_name: str, cdef: ClassDef, attrs = get_mypyc_attrs(cdef) if attrs.get("allow_interpreted_subclasses") is True: ir.allow_interpreted_subclasses = True + if attrs.get("serializable") is True: + # Supports copy.copy and pickle (including subclasses) + ir._serializable = True # We sort the table for determinism here on Python 3.5 for name, node in sorted(info.names.items()): diff --git a/mypyc/test-data/alwaysdefined.test b/mypyc/test-data/alwaysdefined.test new file mode 100644 index 0000000000000..e8c44d8fc548f --- /dev/null +++ b/mypyc/test-data/alwaysdefined.test @@ -0,0 +1,732 @@ +-- Test cases for always defined attributes. +-- +-- If class C has attributes x and y that are always defined, the output will +-- have a line like this: +-- +-- C: [x, y] + +[case testAlwaysDefinedSimple] +class C: + def __init__(self, x: int) -> None: + self.x = x +[out] +C: [x] + +[case testAlwaysDefinedFail] +class MethodCall: + def __init__(self, x: int) -> None: + self.f() + self.x = x + + def f(self) -> None: + pass + +class FuncCall: + def __init__(self, x: int) -> None: + f(x) + self.x = x + f(self) + self.y = x + +class GetAttr: + x: int + def __init__(self, x: int) -> None: + a = self.x + self.x = x + +class _Base: + def __init__(self) -> None: + f(self) + +class CallSuper(_Base): + def __init__(self, x: int) -> None: + super().__init__() + self.x = x + +class Lambda: + def __init__(self, x: int) -> None: + f = lambda x: x + 1 + self.x = x + g = lambda x: self + self.y = x + +class If: + def __init__(self, x: int) -> None: + self.a = 1 + if x: + self.x = x + else: + self.y = 1 + +class Deletable: + __deletable__ = ('x', 'y') + + def __init__(self) -> None: + self.x = 0 + self.y = 1 + self.z = 2 + +class PrimitiveWithSelf: + def __init__(self, s: str) -> None: + self.x = getattr(self, s) + +def f(a) -> None: pass +[out] +MethodCall: [] +FuncCall: [x] +GetAttr: [] +CallSuper: [] +Lambda: [] +If: [a] +Deletable: [z] +PrimitiveWithSelf: [] + +[case testAlwaysDefinedConditional] +class IfAlways: + def __init__(self, x: int, y: int) -> None: + if x: + self.x = x + self.y = y + elif y: + self.x = y + self.y = x + else: + self.x = 0 + self.y = 0 + self.z = 0 + +class IfSometimes1: + def __init__(self, x: int, y: int) -> None: + if x: + self.x = x + self.y = y + elif y: + self.z = y + self.y = x + else: + self.y = 0 + self.a = 0 + +class IfSometimes2: + def __init__(self, x: int, y: int) -> None: + if x: + self.x = x + self.y = y + +class IfStopAnalysis1: + def __init__(self, x: int, y: int) -> None: + if x: + self.x = x + f(self) + else: + self.x = x + self.y = y + +class IfStopAnalysis2: + def __init__(self, x: int, y: int) -> None: + if x: + self.x = x + else: + self.x = x + f(self) + self.y = y + +class IfStopAnalysis3: + def __init__(self, x: int, y: int) -> None: + if x: + self.x = x + else: + f(self) + self.x = x + self.y = y + +class IfConditionalAndNonConditional1: + def __init__(self, x: int) -> None: + self.x = 0 + if x: + self.x = x + +class IfConditionalAndNonConditional2: + def __init__(self, x: int) -> None: + # x is not considered always defined, since the second assignment may + # either initialize or update. + if x: + self.x = x + self.x = 0 + +def f(a) -> None: pass +[out] +IfAlways: [x, y, z] +IfSometimes1: [y] +IfSometimes2: [y] +IfStopAnalysis1: [x] +IfStopAnalysis2: [x] +IfStopAnalysis3: [] +IfConditionalAndNonConditional1: [x] +IfConditionalAndNonConditional2: [] + +[case testAlwaysDefinedExpressions] +from typing import Dict, List, Set, Optional, cast +from typing_extensions import Final + +import other + +class C: pass + +class Collections: + def __init__(self, x: int) -> None: + self.l = [x] + self.d: Dict[str, str] = {} + self.s: Set[int] = set() + self.d2 = {'x': x} + self.s2 = {x} + self.l2 = [f(), None] * x + self.t = tuple(self.l2) + +class Comparisons: + def __init__(self, y: int, c: C, s: str, o: Optional[str]) -> None: + self.n1 = y < 5 + self.n2 = y == 5 + self.c1 = y is c + self.c2 = y is not c + self.o1 = o is None + self.o2 = o is not None + self.s = s < 'x' + +class BinaryOps: + def __init__(self, x: int, s: str) -> None: + self.a = x + 2 + self.b = x & 2 + self.c = x * 2 + self.d = -x + self.e = 'x' + s + self.f = x << x + +g = 2 + +class LocalsAndGlobals: + def __init__(self, x: int) -> None: + t = x + 1 + self.a = t - t + self.g = g + +class Booleans: + def __init__(self, x: int, b: bool) -> None: + self.a = True + self.b = False + self.c = not b + self.d = b or b + self.e = b and b + +F: Final = 3 + +class ModuleFinal: + def __init__(self) -> None: + self.a = F + self.b = other.Y + +class ClassFinal: + F: Final = 3 + + def __init__(self) -> None: + self.a = ClassFinal.F + +class Literals: + def __init__(self) -> None: + self.a = 'x' + self.b = b'x' + self.c = 2.2 + +class ListComprehension: + def __init__(self, x: List[int]) -> None: + self.a = [i + 1 for i in x] + +class Helper: + def __init__(self, arg) -> None: + self.x = 0 + + def foo(self, arg) -> int: + return 1 + +class AttrAccess: + def __init__(self, o: Helper) -> None: + self.x = o.x + o.x = o.x + 1 + self.y = o.foo(self.x) + o.foo(self) + self.z = 1 + +class Construct: + def __init__(self) -> None: + self.x = Helper(1) + self.y = Helper(self) + +class IsInstance: + def __init__(self, x: object) -> None: + if isinstance(x, str): + self.x = 0 + elif isinstance(x, Helper): + self.x = 1 + elif isinstance(x, (list, tuple)): + self.x = 2 + else: + self.x = 3 + +class Cast: + def __init__(self, x: object) -> None: + self.x = cast(int, x) + self.s = cast(str, x) + self.c = cast(Cast, x) + +class PropertyAccessGetter: + def __init__(self, other: PropertyAccessGetter) -> None: + self.x = other.p + self.y = 1 + self.z = self.p + + @property + def p(self) -> int: + return 0 + +class PropertyAccessSetter: + def __init__(self, other: PropertyAccessSetter) -> None: + other.p = 1 + self.y = 1 + self.z = self.p + + @property + def p(self) -> int: + return 0 + + @p.setter + def p(self, x: int) -> None: + pass + +def f() -> int: + return 0 + +[file other.py] +# Not compiled +from typing_extensions import Final + +Y: Final = 3 + +[out] +C: [] +Collections: [d, d2, l, l2, s, s2, t] +Comparisons: [c1, c2, n1, n2, o1, o2, s] +BinaryOps: [a, b, c, d, e, f] +LocalsAndGlobals: [a, g] +Booleans: [a, b, c, d, e] +ModuleFinal: [a, b] +ClassFinal: [F, a] +Literals: [a, b, c] +ListComprehension: [a] +Helper: [x] +AttrAccess: [x, y] +Construct: [x] +IsInstance: [x] +Cast: [c, s, x] +PropertyAccessGetter: [x, y] +PropertyAccessSetter: [y] + +[case testAlwaysDefinedExpressions2] +from typing import List, Tuple + +class C: + def __init__(self) -> None: + self.x = 0 + +class AttributeRef: + def __init__(self, c: C) -> None: + self.aa = c.x + self.bb = self.aa + if c is not None: + self.z = 0 + self.cc = 0 + self.dd = self.z + +class ListOps: + def __init__(self, x: List[int], n: int) -> None: + self.a = len(x) + self.b = x[n] + self.c = [y + 1 for y in x] + +class TupleOps: + def __init__(self, t: Tuple[int, str]) -> None: + x, y = t + self.x = x + self.y = t[0] + s = x, y + self.z = s + +class IfExpr: + def __init__(self, x: int) -> None: + self.a = 1 if x < 5 else 2 + +class Base: + def __init__(self, x: int) -> None: + self.x = x + +class Derived1(Base): + def __init__(self, y: int) -> None: + self.aa = y + super().__init__(y) + self.bb = y + +class Derived2(Base): + pass + +class Conditionals: + def __init__(self, b: bool, n: int) -> None: + if not (n == 5 or n >= n + 1): + self.a = b + else: + self.a = not b + if b: + self.b = 2 + else: + self.b = 4 + +[out] +C: [x] +AttributeRef: [aa, bb, cc, dd] +ListOps: [a, b, c] +TupleOps: [x, y, z] +IfExpr: [a] +Base: [x] +Derived1: [aa, bb, x] +Derived2: [x] +Conditionals: [a, b] + +[case testAlwaysDefinedStatements] +from typing import Any, List, Optional, Iterable + +class Return: + def __init__(self, x: int) -> None: + self.x = x + if x > 5: + self.y = 1 + return + self.y = 2 + self.z = x + +class While: + def __init__(self, x: int) -> None: + n = 2 + while x > 0: + n *=2 + x -= 1 + self.a = n + while x < 5: + self.b = 1 + self.b += 1 + +class Try: + def __init__(self, x: List[int]) -> None: + self.a = 0 + try: + self.b = x[0] + except: + self.c = x + self.d = 0 + try: + self.e = x[0] + except: + self.e = 1 + +class TryFinally: + def __init__(self, x: List[int]) -> None: + self.a = 0 + try: + self.b = x[0] + finally: + self.c = x + self.d = 0 + try: + self.e = x[0] + finally: + self.e = 1 + +class Assert: + def __init__(self, x: Optional[str], y: int) -> None: + assert x is not None + assert y < 5 + self.a = x + +class For: + def __init__(self, it: Iterable[int]) -> None: + self.x = 0 + for x in it: + self.x += x + for x in it: + self.y = x + +class Assignment1: + def __init__(self, other: Assignment1) -> None: + self.x = 0 + self = other # Give up after assignment to self + self.y = 1 + +class Assignment2: + def __init__(self) -> None: + self.x = 0 + other = self # Give up after self is aliased + self.y = other.x + +class With: + def __init__(self, x: Any) -> None: + self.a = 0 + with x: + self.b = 1 + self.c = 2 + +def f() -> None: + pass + +[out] +Return: [x, y] +While: [a] +-- We could infer 'e' as always defined, but this is tricky, since always defined attribute +-- analysis must be performed earlier than exception handling transform. This would be +-- easy to infer *after* exception handling transform. +Try: [a, d] +-- Again, 'e' could be always defined, but it would be a bit tricky to do it. +TryFinally: [a, c, d] +Assert: [a] +For: [x] +Assignment1: [x] +Assignment2: [x] +-- TODO: Why is not 'b' included? +With: [a, c] + +[case testAlwaysDefinedAttributeDefaults] +class Basic: + x = 0 + +class ClassBodyAndInit: + x = 0 + s = 'x' + + def __init__(self, n: int) -> None: + self.n = 0 + +class AttrWithDefaultAndInit: + x = 0 + + def __init__(self, x: int) -> None: + self.x = x + +class Base: + x = 0 + y = 1 + +class Derived(Base): + y = 2 + z = 3 +[out] +Basic: [x] +ClassBodyAndInit: [n, s, x] +AttrWithDefaultAndInit: [x] +Base: [x, y] +Derived: [x, y, z] + +[case testAlwaysDefinedWithInheritance] +class Base: + def __init__(self, x: int) -> None: + self.x = x + +class Deriv1(Base): + def __init__(self, x: int, y: str) -> None: + super().__init__(x) + self.y = y + +class Deriv2(Base): + def __init__(self, x: int, y: str) -> None: + self.y = y + super().__init__(x) + +class Deriv22(Deriv2): + def __init__(self, x: int, y: str, z: bool) -> None: + super().__init__(x, y) + self.z = False + +class Deriv3(Base): + def __init__(self) -> None: + super().__init__(1) + +class Deriv4(Base): + def __init__(self) -> None: + self.y = 1 + self.x = 2 + +def f(a): pass + +class BaseUnsafe: + def __init__(self, x: int, y: int) -> None: + self.x = x + f(self) # Unknown function + self.y = y + +class DerivUnsafe(BaseUnsafe): + def __init__(self, z: int, zz: int) -> None: + self.z = z + super().__init__(1, 2) # Calls unknown function + self.zz = zz + +class BaseWithDefault: + x = 1 + + def __init__(self) -> None: + self.y = 1 + +class DerivedWithDefault(BaseWithDefault): + def __init__(self) -> None: + super().__init__() + self.z = 1 + +class AlwaysDefinedInBase: + def __init__(self) -> None: + self.x = 1 + self.y = 1 + +class UndefinedInDerived(AlwaysDefinedInBase): + def __init__(self, x: bool) -> None: + self.x = 1 + if x: + self.y = 2 + +class UndefinedInDerived2(UndefinedInDerived): + def __init__(self, x: bool): + if x: + self.y = 2 +[out] +Base: [x] +Deriv1: [x, y] +Deriv2: [x, y] +Deriv22: [x, y, z] +Deriv3: [x] +Deriv4: [x, y] +BaseUnsafe: [x] +DerivUnsafe: [x, z] +BaseWithDefault: [x, y] +DerivedWithDefault: [x, y, z] +AlwaysDefinedInBase: [] +UndefinedInDerived: [] +UndefinedInDerived2: [] + +[case testAlwaysDefinedWithInheritance2] +from mypy_extensions import trait, mypyc_attr + +from interpreted import PythonBase + +class BasePartiallyDefined: + def __init__(self, x: int) -> None: + self.a = 0 + if x: + self.x = x + +class Derived1(BasePartiallyDefined): + def __init__(self, x: int) -> None: + super().__init__(x) + self.y = x + +class BaseUndefined: + x: int + +class DerivedAlwaysDefined(BaseUndefined): + def __init__(self) -> None: + super().__init__() + self.z = 0 + self.x = 2 + +@trait +class MyTrait: + def f(self) -> None: pass + +class SimpleTraitImpl(MyTrait): + def __init__(self) -> None: + super().__init__() + self.x = 0 + +@trait +class TraitWithAttr: + x: int + y: str + +class TraitWithAttrImpl(TraitWithAttr): + def __init__(self) -> None: + self.y = 'x' + +@trait +class TraitWithAttr2: + z: int + +class TraitWithAttrImpl2(TraitWithAttr, TraitWithAttr2): + def __init__(self) -> None: + self.y = 'x' + self.z = 2 + +@mypyc_attr(allow_interpreted_subclasses=True) +class BaseWithGeneralSubclassing: + x = 0 + y: int + def __init__(self, s: str) -> None: + self.s = s + +class Derived2(BaseWithGeneralSubclassing): + def __init__(self) -> None: + super().__init__('x') + self.z = 0 + +class SubclassPythonclass(PythonBase): + def __init__(self) -> None: + self.y = 1 + +class BaseWithSometimesDefined: + def __init__(self, b: bool) -> None: + if b: + self.x = 0 + +class Derived3(BaseWithSometimesDefined): + def __init__(self, b: bool) -> None: + super().__init__(b) + self.x = 1 + +[file interpreted.py] +class PythonBase: + def __init__(self) -> None: + self.x = 0 + +[out] +BasePartiallyDefined: [a] +Derived1: [a, y] +BaseUndefined: [] +DerivedAlwaysDefined: [x, z] +MyTrait: [] +SimpleTraitImpl: [x] +TraitWithAttr: [] +TraitWithAttrImpl: [y] +TraitWithAttr2: [] +TraitWithAttrImpl2: [y, z] +BaseWithGeneralSubclassing: [] +-- TODO: 's' could also be always defined +Derived2: [x, z] +-- Always defined attribute analysis is turned off when inheriting a non-native class. +SubclassPythonclass: [] +BaseWithSometimesDefined: [] +-- TODO: 'x' could also be always defined, but it is a bit tricky to support +Derived3: [] + +[case testAlwaysDefinedWithNesting] +class NestedFunc: + def __init__(self) -> None: + self.x = 0 + def f() -> None: + self.y = 0 + f() + self.z = 1 +[out] +-- TODO: Support nested functions. +NestedFunc: [] +f___init___NestedFunc_obj: [] diff --git a/mypyc/test-data/irbuild-basic.test b/mypyc/test-data/irbuild-basic.test index d3403addecfb1..077abcf2939bd 100644 --- a/mypyc/test-data/irbuild-basic.test +++ b/mypyc/test-data/irbuild-basic.test @@ -2212,11 +2212,11 @@ L3: def PropertyHolder.__init__(self, left, right, is_add): self :: __main__.PropertyHolder left, right :: int - is_add, r0, r1, r2 :: bool + is_add :: bool L0: - self.left = left; r0 = is_error - self.right = right; r1 = is_error - self.is_add = is_add; r2 = is_error + self.left = left + self.right = right + self.is_add = is_add return 1 def PropertyHolder.twice_value(self): self :: __main__.PropertyHolder @@ -2299,9 +2299,8 @@ L0: def BaseProperty.__init__(self, value): self :: __main__.BaseProperty value :: int - r0 :: bool L0: - self._incrementer = value; r0 = is_error + self._incrementer = value return 1 def DerivedProperty.value(self): self :: __main__.DerivedProperty @@ -2351,10 +2350,9 @@ def DerivedProperty.__init__(self, incr_func, value): incr_func :: object value :: int r0 :: None - r1 :: bool L0: r0 = BaseProperty.__init__(self, value) - self._incr_func = incr_func; r1 = is_error + self._incr_func = incr_func return 1 def AgainProperty.next(self): self :: __main__.AgainProperty @@ -3444,10 +3442,9 @@ def f(a: bool) -> int: [out] def C.__mypyc_defaults_setup(__mypyc_self__): __mypyc_self__ :: __main__.C - r0, r1 :: bool L0: - __mypyc_self__.x = 2; r0 = is_error - __mypyc_self__.y = 4; r1 = is_error + __mypyc_self__.x = 2 + __mypyc_self__.y = 4 return 1 def f(a): a :: bool diff --git a/mypyc/test-data/irbuild-classes.test b/mypyc/test-data/irbuild-classes.test index 77943045ffe3a..ca1e289354b2f 100644 --- a/mypyc/test-data/irbuild-classes.test +++ b/mypyc/test-data/irbuild-classes.test @@ -146,16 +146,14 @@ class B(A): [out] def A.__init__(self): self :: __main__.A - r0 :: bool L0: - self.x = 20; r0 = is_error + self.x = 20 return 1 def B.__init__(self): self :: __main__.B - r0, r1 :: bool L0: - self.x = 40; r0 = is_error - self.y = 60; r1 = is_error + self.x = 40 + self.y = 60 return 1 [case testAttrLvalue] @@ -169,9 +167,8 @@ def increment(o: O) -> O: [out] def O.__init__(self): self :: __main__.O - r0 :: bool L0: - self.x = 2; r0 = is_error + self.x = 2 return 1 def increment(o): o :: __main__.O @@ -702,18 +699,16 @@ class B(A): def A.__init__(self, x): self :: __main__.A x :: int - r0 :: bool L0: - self.x = x; r0 = is_error + self.x = x return 1 def B.__init__(self, x, y): self :: __main__.B x, y :: int r0 :: None - r1 :: bool L0: r0 = A.__init__(self, x) - self.y = y; r1 = is_error + self.y = y return 1 [case testClassMethod] @@ -760,18 +755,16 @@ class B(A): def A.__init__(self, x): self :: __main__.A x :: int - r0 :: bool L0: - self.x = x; r0 = is_error + self.x = x return 1 def B.__init__(self, x, y): self :: __main__.B x, y :: int r0 :: None - r1 :: bool L0: r0 = A.__init__(self, x) - self.y = y; r1 = is_error + self.y = y return 1 [case testSuper2] @@ -1077,30 +1070,26 @@ L0: return 1 def A.__mypyc_defaults_setup(__mypyc_self__): __mypyc_self__ :: __main__.A - r0 :: bool L0: - __mypyc_self__.x = 20; r0 = is_error + __mypyc_self__.x = 20 return 1 def B.__mypyc_defaults_setup(__mypyc_self__): __mypyc_self__ :: __main__.B - r0 :: bool - r1 :: dict - r2 :: str - r3 :: object - r4 :: str - r5 :: bool - r6 :: object - r7, r8 :: bool + r0 :: dict + r1 :: str + r2 :: object + r3 :: str + r4 :: object L0: - __mypyc_self__.x = 20; r0 = is_error - r1 = __main__.globals :: static - r2 = 'LOL' - r3 = CPyDict_GetItem(r1, r2) - r4 = cast(str, r3) - __mypyc_self__.y = r4; r5 = is_error - r6 = box(None, 1) - __mypyc_self__.z = r6; r7 = is_error - __mypyc_self__.b = 1; r8 = is_error + __mypyc_self__.x = 20 + r0 = __main__.globals :: static + r1 = 'LOL' + r2 = CPyDict_GetItem(r0, r1) + r3 = cast(str, r2) + __mypyc_self__.y = r3 + r4 = box(None, 1) + __mypyc_self__.z = r4 + __mypyc_self__.b = 1 return 1 [case testSubclassDictSpecalized] @@ -1229,3 +1218,25 @@ def g(c: Type[C], d: Type[D]) -> None: # N: (Hint: Use "x: Final = ..." or "x: ClassVar = ..." to define a class attribute) d.f d.c + +[case testSetAttributeWithDefaultInInit] +class C: + s = '' + + def __init__(self, s: str) -> None: + self.s = s +[out] +def C.__init__(self, s): + self :: __main__.C + s :: str + r0 :: bool +L0: + self.s = s; r0 = is_error + return 1 +def C.__mypyc_defaults_setup(__mypyc_self__): + __mypyc_self__ :: __main__.C + r0 :: str +L0: + r0 = '' + __mypyc_self__.s = r0 + return 1 diff --git a/mypyc/test-data/irbuild-constant-fold.test b/mypyc/test-data/irbuild-constant-fold.test index eab4df4e2b27b..dd75c01443f17 100644 --- a/mypyc/test-data/irbuild-constant-fold.test +++ b/mypyc/test-data/irbuild-constant-fold.test @@ -234,9 +234,8 @@ def f() -> None: [out] def C.__mypyc_defaults_setup(__mypyc_self__): __mypyc_self__ :: __main__.C - r0 :: bool L0: - __mypyc_self__.X = 10; r0 = is_error + __mypyc_self__.X = 10 return 1 def f(): a :: int diff --git a/mypyc/test-data/irbuild-singledispatch.test b/mypyc/test-data/irbuild-singledispatch.test index 8b2e2abd507a4..4e18bbf50d4e2 100644 --- a/mypyc/test-data/irbuild-singledispatch.test +++ b/mypyc/test-data/irbuild-singledispatch.test @@ -14,19 +14,17 @@ L0: return 0 def f_obj.__init__(__mypyc_self__): __mypyc_self__ :: __main__.f_obj - r0 :: dict - r1 :: bool - r2 :: dict - r3 :: str - r4 :: int32 - r5 :: bit + r0, r1 :: dict + r2 :: str + r3 :: int32 + r4 :: bit L0: r0 = PyDict_New() - __mypyc_self__.registry = r0; r1 = is_error - r2 = PyDict_New() - r3 = 'dispatch_cache' - r4 = PyObject_SetAttr(__mypyc_self__, r3, r2) - r5 = r4 >= 0 :: signed + __mypyc_self__.registry = r0 + r1 = PyDict_New() + r2 = 'dispatch_cache' + r3 = PyObject_SetAttr(__mypyc_self__, r2, r1) + r4 = r3 >= 0 :: signed return 1 def f_obj.__call__(__mypyc_self__, arg): __mypyc_self__ :: __main__.f_obj @@ -148,19 +146,17 @@ L0: return 1 def f_obj.__init__(__mypyc_self__): __mypyc_self__ :: __main__.f_obj - r0 :: dict - r1 :: bool - r2 :: dict - r3 :: str - r4 :: int32 - r5 :: bit + r0, r1 :: dict + r2 :: str + r3 :: int32 + r4 :: bit L0: r0 = PyDict_New() - __mypyc_self__.registry = r0; r1 = is_error - r2 = PyDict_New() - r3 = 'dispatch_cache' - r4 = PyObject_SetAttr(__mypyc_self__, r3, r2) - r5 = r4 >= 0 :: signed + __mypyc_self__.registry = r0 + r1 = PyDict_New() + r2 = 'dispatch_cache' + r3 = PyObject_SetAttr(__mypyc_self__, r2, r1) + r4 = r3 >= 0 :: signed return 1 def f_obj.__call__(__mypyc_self__, x): __mypyc_self__ :: __main__.f_obj @@ -259,4 +255,3 @@ L0: r1 = f(r0) r2 = box(None, 1) return r2 - diff --git a/mypyc/test-data/irbuild-statements.test b/mypyc/test-data/irbuild-statements.test index 98a6fa2403595..ab947c956b742 100644 --- a/mypyc/test-data/irbuild-statements.test +++ b/mypyc/test-data/irbuild-statements.test @@ -894,10 +894,9 @@ def delAttributeMultiple() -> None: def Dummy.__init__(self, x, y): self :: __main__.Dummy x, y :: int - r0, r1 :: bool L0: - self.x = x; r0 = is_error - self.y = y; r1 = is_error + self.x = x + self.y = y return 1 def delAttribute(): r0, dummy :: __main__.Dummy diff --git a/mypyc/test-data/run-classes.test b/mypyc/test-data/run-classes.test index e238c2b02284c..ac42aa26cf580 100644 --- a/mypyc/test-data/run-classes.test +++ b/mypyc/test-data/run-classes.test @@ -710,8 +710,7 @@ class B(A): class C(B): def __init__(self, x: int, y: int) -> None: - init = super(C, self).__init__ - init(x, y+1) + super(C, self).__init__(x, y + 1) def foo(self, x: int) -> int: # should go to A, not B @@ -1329,16 +1328,18 @@ assert Nothing2.X == 10 assert Nothing3.X == 10 [case testPickling] -from mypy_extensions import trait +from mypy_extensions import trait, mypyc_attr from typing import Any, TypeVar, Generic def dec(x: Any) -> Any: return x +@mypyc_attr(allow_interpreted_subclasses=True) class A: x: int y: str +@mypyc_attr(allow_interpreted_subclasses=True) class B(A): z: bool @@ -1865,10 +1866,28 @@ class F(D): # # def y(self, val : object) -> None: # # self._y = val +# No inheritance, just plain setter/getter +class G: + def __init__(self, x: int) -> None: + self._x = x + + @property + def x(self) -> int: + return self._x + + @x.setter + def x(self, x: int) -> None: + self._x = x + +class H: + def __init__(self, g: G) -> None: + self.g = g + self.g.x = 5 # Should not be treated as initialization + [file other.py] # Run in both interpreted and compiled mode -from native import A, B, C, D, E, F +from native import A, B, C, D, E, F, G a = A() assert a.x == 0 @@ -1898,6 +1917,9 @@ f = F() assert f.x == 20 f.x = 30 assert f.x == 50 +g = G(4) +g.x = 20 +assert g.x == 20 [file driver.py] # Run the tests in both interpreted and compiled mode @@ -1924,3 +1946,263 @@ from native import A, B, C a = A() b = B() c = C() + +[case testCopyAlwaysDefinedAttributes] +import copy +from typing import Union + +class A: pass + +class C: + def __init__(self, n: int = 0) -> None: + self.n = n + self.s = "" + self.t = ("", 0) + self.u: Union[str, bytes] = '' + self.a = A() + +def test_copy() -> None: + c1 = C() + c1.n = 1 + c1.s = "x" + c2 = copy.copy(c1) + assert c2.n == 1 + assert c2.s == "x" + assert c2.t == ("", 0) + assert c2.u == '' + assert c2.a is c1.a + +[case testNonNativeCallsToDunderNewAndInit] +from typing import Any +from testutil import assertRaises + +count_c = 0 + +class C: + def __init__(self) -> None: + self.x = 'a' # Always defined attribute + global count_c + count_c += 1 + + def get(self) -> str: + return self.x + +def test_no_init_args() -> None: + global count_c + count_c = 0 + + # Use Any to get non-native semantics + cls: Any = C + # __new__ implicitly calls __init__ for native classes + obj = cls.__new__(cls) + assert obj.get() == 'a' + assert count_c == 1 + # Make sure we don't call __init__ twice + obj2 = cls() + assert obj2.get() == 'a' + assert count_c == 2 + +count_d = 0 + +class D: + def __init__(self, x: str) -> None: + self.x = x # Always defined attribute + global count_d + count_d += 1 + + def get(self) -> str: + return self.x + +def test_init_arg() -> None: + global count_d + count_d = 0 + + # Use Any to get non-native semantics + cls: Any = D + # __new__ implicitly calls __init__ for native classes + obj = cls.__new__(cls, 'abc') + assert obj.get() == 'abc' + assert count_d == 1 + # Make sure we don't call __init__ twice + obj2 = cls('x') + assert obj2.get() == 'x' + assert count_d == 2 + # Keyword args should work + obj = cls.__new__(cls, x='abc') + assert obj.get() == 'abc' + assert count_d == 3 + +def test_invalid_init_args() -> None: + # Use Any to get non-native semantics + cls: Any = D + with assertRaises(TypeError): + cls() + with assertRaises(TypeError): + cls(y='x') + with assertRaises(TypeError): + cls(1) + +[case testTryDeletingAlwaysDefinedAttribute] +from typing import Any +from testutil import assertRaises + +class C: + def __init__(self) -> None: + self.x = 0 + +class D(C): + pass + +def test_try_deleting_always_defined_attr() -> None: + c: Any = C() + with assertRaises(AttributeError): + del c.x + d: Any = D() + with assertRaises(AttributeError): + del d.x + +[case testAlwaysDefinedAttributeAndAllowInterpretedSubclasses] +from mypy_extensions import mypyc_attr + +from m import define_interpreted_subclass + +@mypyc_attr(allow_interpreted_subclasses=True) +class Base: + x = 5 + y: int + def __init__(self, s: str) -> None: + self.s = s + +class DerivedNative(Base): + def __init__(self) -> None: + super().__init__('x') + self.z = 3 + +def test_native_subclass() -> None: + o = DerivedNative() + assert o.x == 5 + assert o.s == 'x' + assert o.z == 3 + +def test_interpreted_subclass() -> None: + define_interpreted_subclass(Base) + +[file m.py] +from testutil import assertRaises + +def define_interpreted_subclass(b): + class DerivedInterpreted1(b): + def __init__(self): + # Don't call base class __init__ + pass + d1 = DerivedInterpreted1() + assert d1.x == 5 + with assertRaises(AttributeError): + d1.y + with assertRaises(AttributeError): + d1.s + with assertRaises(AttributeError): + del d1.x + + class DerivedInterpreted1(b): + def __init__(self): + super().__init__('y') + d2 = DerivedInterpreted1() + assert d2.x == 5 + assert d2.s == 'y' + with assertRaises(AttributeError): + d2.y + with assertRaises(AttributeError): + del d2.x + +[case testBaseClassSometimesDefinesAttribute] +class C: + def __init__(self, b: bool) -> None: + if b: + self.x = [1] + +class D(C): + def __init__(self, b: bool) -> None: + super().__init__(b) + self.x = [2] + +def test_base_class() -> None: + c = C(True) + assert c.x == [1] + c = C(False) + try: + c.x + except AttributeError: + return + assert False + +def test_subclass() -> None: + d = D(True) + assert d.x == [2] + d = D(False) + assert d.x == [2] + +[case testSerializableClass] +from mypy_extensions import mypyc_attr +from typing import Any +import copy +from testutil import assertRaises + +@mypyc_attr(serializable=True) +class Base: + def __init__(self, s: str) -> None: + self.s = s + +class Derived(Base): + def __init__(self, s: str, n: int) -> None: + super().__init__(s) + self.n = n + +def test_copy_base() -> None: + o = Base('xyz') + o2 = copy.copy(o) + assert isinstance(o2, Base) + assert o2 is not o + assert o2.s == 'xyz' + +def test_copy_derived() -> None: + d = Derived('xyz', 5) + d2 = copy.copy(d) + assert isinstance(d2, Derived) + assert d2 is not d + assert d2.s == 'xyz' + assert d2.n == 5 + +class NonSerializable: + def __init__(self, s: str) -> None: + self.s = s + +@mypyc_attr(serializable=True) +class SerializableSub(NonSerializable): + def __init__(self, s: str, n: int) -> None: + super().__init__(s) + self.n = n + +def test_serializable_sub_class() -> None: + n = NonSerializable('xyz') + assert n.s == 'xyz' + + with assertRaises(TypeError): + copy.copy(n) + + s = SerializableSub('foo', 6) + s2 = copy.copy(s) + assert s2 is not s + assert s2.s == 'foo' + assert s2.n == 6 + +def test_serializable_sub_class_call_new() -> None: + t: Any = SerializableSub + sub: SerializableSub = t.__new__(t) + with assertRaises(AttributeError): + sub.s + with assertRaises(AttributeError): + sub.n + base: NonSerializable = sub + with assertRaises(AttributeError): + base.s diff --git a/mypyc/test-data/run-multimodule.test b/mypyc/test-data/run-multimodule.test index 6ffa166c57a1c..418af66ba0606 100644 --- a/mypyc/test-data/run-multimodule.test +++ b/mypyc/test-data/run-multimodule.test @@ -799,6 +799,69 @@ import native [rechecked native, other_a] +[case testSeparateCompilationWithUndefinedAttribute] +from other_a import A + +def f() -> None: + a = A() + if a.x == 5: + print(a.y) + print(a.m()) + else: + assert a.x == 6 + try: + print(a.y) + except AttributeError: + print('y undefined') + else: + assert False + + try: + print(a.m()) + except AttributeError: + print('y undefined') + else: + assert False + +[file other_a.py] +from other_b import B + +class A(B): + def __init__(self) -> None: + self.y = 9 + +[file other_a.py.2] +from other_b import B + +class A(B): + x = 6 + + def __init__(self) -> None: + pass + +[file other_b.py] +class B: + x = 5 + + def __init__(self) -> None: + self.y = 7 + + def m(self) -> int: + return self.y + +[file driver.py] +from native import f +f() + +[rechecked native, other_a] + +[out] +9 +9 +[out2] +y undefined +y undefined + [case testIncrementalCompilationWithDeletable] import other_a [file other_a.py] diff --git a/mypyc/test/test_alwaysdefined.py b/mypyc/test/test_alwaysdefined.py new file mode 100644 index 0000000000000..f9a90fabf2a10 --- /dev/null +++ b/mypyc/test/test_alwaysdefined.py @@ -0,0 +1,42 @@ +"""Test cases for inferring always defined attributes in classes.""" + +import os.path + +from mypy.test.config import test_temp_dir +from mypy.test.data import DataDrivenTestCase +from mypy.errors import CompileError + +from mypyc.test.testutil import ( + ICODE_GEN_BUILTINS, use_custom_builtins, MypycDataSuite, build_ir_for_single_file2, + assert_test_output, infer_ir_build_options_from_test_name +) + +files = [ + 'alwaysdefined.test' +] + + +class TestAlwaysDefined(MypycDataSuite): + files = files + base_path = test_temp_dir + + def run_case(self, testcase: DataDrivenTestCase) -> None: + """Perform a runtime checking transformation test case.""" + options = infer_ir_build_options_from_test_name(testcase.name) + if options is None: + # Skipped test case + return + with use_custom_builtins(os.path.join(self.data_prefix, ICODE_GEN_BUILTINS), testcase): + try: + ir = build_ir_for_single_file2(testcase.input, options) + except CompileError as e: + actual = e.messages + else: + actual = [] + for cl in ir.classes: + if cl.name.startswith('_'): + continue + actual.append('{}: [{}]'.format( + cl.name, ', '.join(sorted(cl._always_initialized_attrs)))) + + assert_test_output(testcase, actual, 'Invalid test output', testcase.output) diff --git a/mypyc/test/test_run.py b/mypyc/test/test_run.py index 466815534fdbd..852de8edcf690 100644 --- a/mypyc/test/test_run.py +++ b/mypyc/test/test_run.py @@ -376,7 +376,6 @@ class TestRunSeparate(TestRun): This puts other.py and other_b.py into a compilation group named "stuff". Any files not mentioned in the comment will get single-file groups. """ - separate = True test_name_suffix = '_separate' files = [ diff --git a/mypyc/test/test_serialization.py b/mypyc/test/test_serialization.py index 683bb807620e7..eeef6beb1305a 100644 --- a/mypyc/test/test_serialization.py +++ b/mypyc/test/test_serialization.py @@ -58,7 +58,10 @@ def assert_blobs_same(x: Any, y: Any, trail: Tuple[Any, ...]) -> None: assert x.keys() == y.keys(), f"Keys mismatch at {trail}" for k in x.keys(): assert_blobs_same(x[k], y[k], trail + (k,)) - elif isinstance(x, Iterable) and not isinstance(x, str): + elif isinstance(x, Iterable) and not isinstance(x, (str, set)): + # Special case iterables to generate better assert error messages. + # We can't use this for sets since the ordering is unpredictable, + # and strings should be treated as atomic values. for i, (xv, yv) in enumerate(zip(x, y)): assert_blobs_same(xv, yv, trail + (i,)) elif isinstance(x, RType): diff --git a/mypyc/test/testutil.py b/mypyc/test/testutil.py index c5dc2588a7e20..d5c5dea2d6344 100644 --- a/mypyc/test/testutil.py +++ b/mypyc/test/testutil.py @@ -17,6 +17,7 @@ from mypyc.options import CompilerOptions from mypyc.analysis.ircheck import assert_func_ir_valid from mypyc.ir.func_ir import FuncIR +from mypyc.ir.module_ir import ModuleIR from mypyc.errors import Errors from mypyc.irbuild.main import build_ir from mypyc.irbuild.mapper import Mapper @@ -87,6 +88,12 @@ def perform_test(func: Callable[[DataDrivenTestCase], None], def build_ir_for_single_file(input_lines: List[str], compiler_options: Optional[CompilerOptions] = None) -> List[FuncIR]: + return build_ir_for_single_file2(input_lines, compiler_options).functions + + +def build_ir_for_single_file2(input_lines: List[str], + compiler_options: Optional[CompilerOptions] = None + ) -> ModuleIR: program_text = '\n'.join(input_lines) # By default generate IR compatible with the earliest supported Python C API. @@ -121,7 +128,7 @@ def build_ir_for_single_file(input_lines: List[str], module = list(modules.values())[0] for fn in module.functions: assert_func_ir_valid(fn) - return module.functions + return module def update_testcase_output(testcase: DataDrivenTestCase, output: List[str]) -> None: From 74cfa3d46ae6a9c0033bf95d88462619bc3bc044 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Wed, 18 May 2022 10:52:49 +0100 Subject: [PATCH 299/377] [mypyc] Borrow references during chained attribute access (#12805) If we have multiple native attribute access operations in succession, we can borrow the temporaries. This avoids an incref and decref. For example, when evaluating x.y.z, we don't need to incref the result of x.y. We need to make sure that the objects from which we borrow values are not freed too early by adding keep_alive ops. This is part of a wider reference counting optimization workstream. All the improvements together produced around 5% performance improvement in the richards benchmark. In carefully constructed microbenchmarks 50+% improvements are possible. --- mypyc/codegen/emitfunc.py | 2 +- mypyc/ir/ops.py | 3 +- mypyc/ir/pprint.py | 6 +++- mypyc/irbuild/builder.py | 19 +++++++++-- mypyc/irbuild/expression.py | 18 +++++++++-- mypyc/irbuild/ll_builder.py | 15 +++++++-- mypyc/test-data/irbuild-classes.test | 48 ++++++++++++++++++++++++++++ mypyc/test-data/refcount.test | 33 +++++++++++++++++++ 8 files changed, 133 insertions(+), 11 deletions(-) diff --git a/mypyc/codegen/emitfunc.py b/mypyc/codegen/emitfunc.py index f4ed657c467ff..540c6b6464961 100644 --- a/mypyc/codegen/emitfunc.py +++ b/mypyc/codegen/emitfunc.py @@ -333,7 +333,7 @@ def visit_get_attr(self, op: GetAttr) -> None: 'PyErr_SetString({}, "attribute {} of {} undefined");'.format( exc_class, repr(op.attr), repr(cl.name))) - if attr_rtype.is_refcounted: + if attr_rtype.is_refcounted and not op.is_borrowed: if not merged_branch and not always_defined: self.emitter.emit_line('} else {') self.emitter.emit_inc_ref(dest, attr_rtype) diff --git a/mypyc/ir/ops.py b/mypyc/ir/ops.py index 786cb018f96b5..74a31153f5a41 100644 --- a/mypyc/ir/ops.py +++ b/mypyc/ir/ops.py @@ -599,13 +599,14 @@ class GetAttr(RegisterOp): error_kind = ERR_MAGIC - def __init__(self, obj: Value, attr: str, line: int) -> None: + def __init__(self, obj: Value, attr: str, line: int, *, borrow: bool = False) -> None: super().__init__(line) self.obj = obj self.attr = attr assert isinstance(obj.type, RInstance), 'Attribute access not supported: %s' % obj.type self.class_type = obj.type self.type = obj.type.attr_type(attr) + self.is_borrowed = borrow def sources(self) -> List[Value]: return [self.obj] diff --git a/mypyc/ir/pprint.py b/mypyc/ir/pprint.py index 753965cb1e9c4..c009b1343392a 100644 --- a/mypyc/ir/pprint.py +++ b/mypyc/ir/pprint.py @@ -77,7 +77,11 @@ def visit_load_literal(self, op: LoadLiteral) -> str: return self.format('%r = %s%s', op, prefix, repr(op.value)) def visit_get_attr(self, op: GetAttr) -> str: - return self.format('%r = %r.%s', op, op.obj, op.attr) + if op.is_borrowed: + borrow = 'borrow ' + else: + borrow = '' + return self.format('%r = %s%r.%s', op, borrow, op.obj, op.attr) def visit_set_attr(self, op: SetAttr) -> str: if op.is_init: diff --git a/mypyc/irbuild/builder.py b/mypyc/irbuild/builder.py index 72c03801e326e..0b97bdbee625d 100644 --- a/mypyc/irbuild/builder.py +++ b/mypyc/irbuild/builder.py @@ -141,6 +141,8 @@ def __init__(self, # can also do quick lookups. self.imports: OrderedDict[str, None] = OrderedDict() + self.can_borrow = False + # High-level control def set_module(self, module_name: str, module_path: str) -> None: @@ -152,15 +154,23 @@ def set_module(self, module_name: str, module_path: str) -> None: self.module_path = module_path @overload - def accept(self, node: Expression) -> Value: ... + def accept(self, node: Expression, *, can_borrow: bool = False) -> Value: ... @overload def accept(self, node: Statement) -> None: ... - def accept(self, node: Union[Statement, Expression]) -> Optional[Value]: - """Transform an expression or a statement.""" + def accept(self, node: Union[Statement, Expression], *, + can_borrow: bool = False) -> Optional[Value]: + """Transform an expression or a statement. + + If can_borrow is true, prefer to generate a borrowed reference. + Borrowed references are faster since they don't require reference count + manipulation, but they are only safe to use in specific contexts. + """ with self.catch_errors(node.line): if isinstance(node, Expression): + old_can_borrow = self.can_borrow + self.can_borrow = can_borrow try: res = node.accept(self.visitor) res = self.coerce(res, self.node_type(node), node.line) @@ -170,6 +180,9 @@ def accept(self, node: Union[Statement, Expression]) -> Optional[Value]: # from causing more downstream trouble. except UnsupportedException: res = Register(self.node_type(node)) + self.can_borrow = old_can_borrow + if not can_borrow: + self.builder.flush_keep_alives() return res else: try: diff --git a/mypyc/irbuild/expression.py b/mypyc/irbuild/expression.py index 1a74d71c3b27f..e1d6e31619c81 100644 --- a/mypyc/irbuild/expression.py +++ b/mypyc/irbuild/expression.py @@ -21,7 +21,7 @@ Value, Register, TupleGet, TupleSet, BasicBlock, Assign, LoadAddress, RaiseStandardError ) from mypyc.ir.rtypes import ( - RTuple, object_rprimitive, is_none_rprimitive, int_rprimitive, is_int_rprimitive + RTuple, RInstance, object_rprimitive, is_none_rprimitive, int_rprimitive, is_int_rprimitive ) from mypyc.ir.func_ir import FUNC_CLASSMETHOD, FUNC_STATICMETHOD from mypyc.irbuild.format_str_tokenizer import ( @@ -130,8 +130,19 @@ def transform_member_expr(builder: IRBuilder, expr: MemberExpr) -> Value: if isinstance(expr.node, MypyFile) and expr.node.fullname in builder.imports: return builder.load_module(expr.node.fullname) - obj = builder.accept(expr.expr) + obj_rtype = builder.node_type(expr.expr) + if (isinstance(obj_rtype, RInstance) + and obj_rtype.class_ir.is_ext_class + and obj_rtype.class_ir.has_attr(expr.name) + and not obj_rtype.class_ir.get_method(expr.name)): + # Direct attribute access -> can borrow object + can_borrow = True + else: + can_borrow = False + obj = builder.accept(expr.expr, can_borrow=can_borrow) + rtype = builder.node_type(expr) + # Special case: for named tuples transform attribute access to faster index access. typ = get_proper_type(builder.types.get(expr.expr)) if isinstance(typ, TupleType) and typ.partial_fallback.type.is_named_tuple: @@ -142,7 +153,8 @@ def transform_member_expr(builder: IRBuilder, expr: MemberExpr) -> Value: check_instance_attribute_access_through_class(builder, expr, typ) - return builder.builder.get_attr(obj, expr.name, rtype, expr.line) + borrow = can_borrow and builder.can_borrow + return builder.builder.get_attr(obj, expr.name, rtype, expr.line, borrow=borrow) def check_instance_attribute_access_through_class(builder: IRBuilder, diff --git a/mypyc/irbuild/ll_builder.py b/mypyc/irbuild/ll_builder.py index 1927773489b15..bbc30c233039b 100644 --- a/mypyc/irbuild/ll_builder.py +++ b/mypyc/irbuild/ll_builder.py @@ -105,6 +105,9 @@ def __init__( self.blocks: List[BasicBlock] = [] # Stack of except handler entry blocks self.error_handlers: List[Optional[BasicBlock]] = [None] + # Values that we need to keep alive as long as we have borrowed + # temporaries. Use flush_keep_alives() to mark the end of the live range. + self.keep_alives: List[Value] = [] # Basic operations @@ -145,6 +148,11 @@ def self(self) -> Register: """ return self.args[0] + def flush_keep_alives(self) -> None: + if self.keep_alives: + self.add(KeepAlive(self.keep_alives[:])) + self.keep_alives = [] + # Type conversions def box(self, src: Value) -> Value: @@ -219,11 +227,14 @@ def coerce_nullable(self, src: Value, target_type: RType, line: int) -> Value: # Attribute access - def get_attr(self, obj: Value, attr: str, result_type: RType, line: int) -> Value: + def get_attr(self, obj: Value, attr: str, result_type: RType, line: int, *, + borrow: bool = False) -> Value: """Get a native or Python attribute of an object.""" if (isinstance(obj.type, RInstance) and obj.type.class_ir.is_ext_class and obj.type.class_ir.has_attr(attr)): - return self.add(GetAttr(obj, attr, line)) + if borrow: + self.keep_alives.append(obj) + return self.add(GetAttr(obj, attr, line, borrow=borrow)) elif isinstance(obj.type, RUnion): return self.union_get_attr(obj, obj.type, attr, result_type, line) else: diff --git a/mypyc/test-data/irbuild-classes.test b/mypyc/test-data/irbuild-classes.test index ca1e289354b2f..a5f360928abe1 100644 --- a/mypyc/test-data/irbuild-classes.test +++ b/mypyc/test-data/irbuild-classes.test @@ -1240,3 +1240,51 @@ L0: r0 = '' __mypyc_self__.s = r0 return 1 + +[case testBorrowAttribute] +def f(d: D) -> int: + return d.c.x + +class C: + x: int +class D: + c: C +[out] +def f(d): + d :: __main__.D + r0 :: __main__.C + r1 :: int +L0: + r0 = borrow d.c + r1 = r0.x + keep_alive d + return r1 + +[case testNoBorrowOverPropertyAccess] +class C: + d: D +class D: + @property + def e(self) -> E: + return E() +class E: + x: int +def f(c: C) -> int: + return c.d.e.x +[out] +def D.e(self): + self :: __main__.D + r0 :: __main__.E +L0: + r0 = E() + return r0 +def f(c): + c :: __main__.C + r0 :: __main__.D + r1 :: __main__.E + r2 :: int +L0: + r0 = c.d + r1 = r0.e + r2 = r1.x + return r2 diff --git a/mypyc/test-data/refcount.test b/mypyc/test-data/refcount.test index 909251741a303..965d4066c0b50 100644 --- a/mypyc/test-data/refcount.test +++ b/mypyc/test-data/refcount.test @@ -917,3 +917,36 @@ L0: r5 = unbox(int, r4) dec_ref r4 return r5 + +[case testBorrowAttribute] +def g() -> int: + d = D() + return d.c.x + +def f(d: D) -> int: + return d.c.x + +class C: + x: int +class D: + c: C +[out] +def g(): + r0, d :: __main__.D + r1 :: __main__.C + r2 :: int +L0: + r0 = D() + d = r0 + r1 = borrow d.c + r2 = r1.x + dec_ref d + return r2 +def f(d): + d :: __main__.D + r0 :: __main__.C + r1 :: int +L0: + r0 = borrow d.c + r1 = r0.x + return r1 From 8dac2210f5afedee1c45c6293f20bf9b5c5ec179 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Wed, 18 May 2022 13:03:32 +0100 Subject: [PATCH 300/377] Fix namedtuple crash in unannotated function (#12804) Fixes #11121. --- mypy/semanal_namedtuple.py | 11 +++++++--- test-data/unit/check-incremental.test | 29 +++++++++++++++++++++++++++ test-data/unit/check-namedtuple.test | 14 +++++++++++++ 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/mypy/semanal_namedtuple.py b/mypy/semanal_namedtuple.py index 07863dea2efbe..109ec17cbc899 100644 --- a/mypy/semanal_namedtuple.py +++ b/mypy/semanal_namedtuple.py @@ -186,11 +186,16 @@ def check_namedtuple(self, # Error. Construct dummy return value. if var_name: name = var_name + if is_func_scope: + name += '@' + str(call.line) else: - name = 'namedtuple@' + str(call.line) + name = var_name = 'namedtuple@' + str(call.line) info = self.build_namedtuple_typeinfo(name, [], [], {}, node.line) - self.store_namedtuple_info(info, name, call, is_typed) - return name, info + self.store_namedtuple_info(info, var_name, call, is_typed) + if name != var_name or is_func_scope: + # NOTE: we skip local namespaces since they are not serialized. + self.api.add_symbol_skip_local(name, info) + return var_name, info if not ok: # This is a valid named tuple but some types are not ready. return typename, None diff --git a/test-data/unit/check-incremental.test b/test-data/unit/check-incremental.test index c604b386691b7..79fa1c92c52e5 100644 --- a/test-data/unit/check-incremental.test +++ b/test-data/unit/check-incremental.test @@ -5711,3 +5711,32 @@ class C: [builtins fixtures/dict.pyi] [out2] tmp/a.py:2: error: "object" has no attribute "xyz" + +[case testIncrementalInvalidNamedTupleInUnannotatedFunction] +import a + +[file a.py] +import b + +[file a.py.2] +import b # f + +[file b.py] +from typing import NamedTuple + +def toplevel(fields): + TupleType = NamedTuple("TupleType", fields) + class InheritFromTuple(TupleType): + pass + NT2 = NamedTuple("bad", [('x', int)]) + nt2: NT2 = NT2(x=1) + +class C: + def method(self, fields): + TupleType = NamedTuple("TupleType", fields) + class InheritFromTuple(TupleType): + pass + NT2 = NamedTuple("bad", [('x', int)]) + nt2: NT2 = NT2(x=1) + +[builtins fixtures/tuple.pyi] diff --git a/test-data/unit/check-namedtuple.test b/test-data/unit/check-namedtuple.test index b95cc96f81155..c6f1fe3b1d04a 100644 --- a/test-data/unit/check-namedtuple.test +++ b/test-data/unit/check-namedtuple.test @@ -1120,3 +1120,17 @@ def bar1(c: C1) -> None: reveal_type(c) # N: Revealed type is "Tuple[builtins.int, fallback=__main__.C1]" [builtins fixtures/tuple.pyi] [typing fixtures/typing-namedtuple.pyi] + +[case testInvalidNamedTupleWithinFunction] +from collections import namedtuple + +def f(fields) -> None: + TupleType = namedtuple("TupleType", fields) \ + # E: List or tuple literal expected as the second argument to "namedtuple()" + class InheritFromTuple(TupleType): + pass + t: TupleType + it: InheritFromTuple + NT2 = namedtuple("bad", "x") # E: First argument to namedtuple() should be "NT2", not "bad" + nt2: NT2 = NT2(x=1) +[builtins fixtures/tuple.pyi] From 8e7e81759d3e43199bb0dced94f55157b72b2a49 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Wed, 18 May 2022 17:48:09 +0100 Subject: [PATCH 301/377] Update version to 0.970+dev (#12808) --- mypy/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/version.py b/mypy/version.py index c7b4e30f24202..b46cd5b82a663 100644 --- a/mypy/version.py +++ b/mypy/version.py @@ -5,7 +5,7 @@ # - Release versions have the form "0.NNN". # - Dev versions have the form "0.NNN+dev" (PLUS sign to conform to PEP 440). # - For 1.0 we'll switch back to 1.2.3 form. -__version__ = '0.960+dev' +__version__ = '0.970+dev' base_version = __version__ mypy_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) From f71dba7526b3f5244faaa210302fc20269691056 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 19 May 2022 11:08:50 +0100 Subject: [PATCH 302/377] [mypyc] Borrow operands of several primitives (#12810) Borrow an operand such as `x.y` (attribute of a native class) in various contexts when it's safe to do so. This reduces the number of incref/decref operations we need to perform. This continues work started in #12805. These cases now support borrowing (for some subexpressions, in some contexts): * `x.y is None` * Cast source value * `len(x.y)` (if the operand is a list) * `isinstance(x.y, C)` * `x.y[a.b]` * `x.y.z = 1` --- mypyc/ir/ops.py | 5 +- mypyc/ir/pprint.py | 11 +- mypyc/irbuild/builder.py | 18 +- mypyc/irbuild/expression.py | 56 +++-- mypyc/irbuild/ll_builder.py | 12 +- mypyc/irbuild/specialize.py | 20 +- mypyc/irbuild/statement.py | 5 +- mypyc/test-data/exceptions.test | 22 +- mypyc/test-data/irbuild-classes.test | 28 +-- mypyc/test-data/irbuild-isinstance.test | 40 ++++ mypyc/test-data/irbuild-optional.test | 47 ++-- mypyc/test-data/irbuild-str.test | 113 +++++---- mypyc/test-data/refcount.test | 291 ++++++++++++++++++++++++ mypyc/test-data/run-generators.test | 14 ++ 14 files changed, 539 insertions(+), 143 deletions(-) diff --git a/mypyc/ir/ops.py b/mypyc/ir/ops.py index 74a31153f5a41..d36fcfb9e7ebd 100644 --- a/mypyc/ir/ops.py +++ b/mypyc/ir/ops.py @@ -775,15 +775,18 @@ class Cast(RegisterOp): error_kind = ERR_MAGIC - def __init__(self, src: Value, typ: RType, line: int) -> None: + def __init__(self, src: Value, typ: RType, line: int, *, borrow: bool = False) -> None: super().__init__(line) self.src = src self.type = typ + self.is_borrowed = borrow def sources(self) -> List[Value]: return [self.src] def stolen(self) -> List[Value]: + if self.is_borrowed: + return [] return [self.src] def accept(self, visitor: 'OpVisitor[T]') -> T: diff --git a/mypyc/ir/pprint.py b/mypyc/ir/pprint.py index c009b1343392a..40243dac96e9c 100644 --- a/mypyc/ir/pprint.py +++ b/mypyc/ir/pprint.py @@ -77,11 +77,12 @@ def visit_load_literal(self, op: LoadLiteral) -> str: return self.format('%r = %s%s', op, prefix, repr(op.value)) def visit_get_attr(self, op: GetAttr) -> str: + return self.format('%r = %s%r.%s', op, self.borrow_prefix(op), op.obj, op.attr) + + def borrow_prefix(self, op: Op) -> str: if op.is_borrowed: - borrow = 'borrow ' - else: - borrow = '' - return self.format('%r = %s%r.%s', op, borrow, op.obj, op.attr) + return 'borrow ' + return '' def visit_set_attr(self, op: SetAttr) -> str: if op.is_init: @@ -142,7 +143,7 @@ def visit_method_call(self, op: MethodCall) -> str: return s def visit_cast(self, op: Cast) -> str: - return self.format('%r = cast(%s, %r)', op, op.type, op.src) + return self.format('%r = %scast(%s, %r)', op, self.borrow_prefix(op), op.type, op.src) def visit_box(self, op: Box) -> str: return self.format('%r = box(%s, %r)', op, op.src.type, op.src) diff --git a/mypyc/irbuild/builder.py b/mypyc/irbuild/builder.py index 0b97bdbee625d..c7ef400236b3a 100644 --- a/mypyc/irbuild/builder.py +++ b/mypyc/irbuild/builder.py @@ -182,7 +182,7 @@ def accept(self, node: Union[Statement, Expression], *, res = Register(self.node_type(node)) self.can_borrow = old_can_borrow if not can_borrow: - self.builder.flush_keep_alives() + self.flush_keep_alives() return res else: try: @@ -191,6 +191,9 @@ def accept(self, node: Union[Statement, Expression], *, pass return None + def flush_keep_alives(self) -> None: + self.builder.flush_keep_alives() + # Pass through methods for the most common low-level builder ops, for convenience. def add(self, op: Op) -> Value: @@ -234,7 +237,7 @@ def binary_op(self, lreg: Value, rreg: Value, expr_op: str, line: int) -> Value: return self.builder.binary_op(lreg, rreg, expr_op, line) def coerce(self, src: Value, target_type: RType, line: int, force: bool = False) -> Value: - return self.builder.coerce(src, target_type, line, force) + return self.builder.coerce(src, target_type, line, force, can_borrow=self.can_borrow) def none_object(self) -> Value: return self.builder.none_object() @@ -510,7 +513,8 @@ def get_assignment_target(self, lvalue: Lvalue, return AssignmentTargetIndex(base, index) elif isinstance(lvalue, MemberExpr): # Attribute assignment x.y = e - obj = self.accept(lvalue.expr) + can_borrow = self.is_native_attr_ref(lvalue) + obj = self.accept(lvalue.expr, can_borrow=can_borrow) return AssignmentTargetAttr(obj, lvalue.name) elif isinstance(lvalue, TupleExpr): # Multiple assignment a, ..., b = e @@ -1176,6 +1180,14 @@ def load_module_attr_by_fullname(self, fullname: str, line: int) -> Value: left = self.load_module(module) return self.py_get_attr(left, name, line) + def is_native_attr_ref(self, expr: MemberExpr) -> bool: + """Is expr a direct reference to a native (struct) attribute of an instance?""" + obj_rtype = self.node_type(expr.expr) + return (isinstance(obj_rtype, RInstance) + and obj_rtype.class_ir.is_ext_class + and obj_rtype.class_ir.has_attr(expr.name) + and not obj_rtype.class_ir.get_method(expr.name)) + # Lacks a good type because there wasn't a reasonable type in 3.5 :( def catch_errors(self, line: int) -> Any: return catch_errors(self.module_path, line) diff --git a/mypyc/irbuild/expression.py b/mypyc/irbuild/expression.py index e1d6e31619c81..e1feabb0a4f3f 100644 --- a/mypyc/irbuild/expression.py +++ b/mypyc/irbuild/expression.py @@ -21,7 +21,8 @@ Value, Register, TupleGet, TupleSet, BasicBlock, Assign, LoadAddress, RaiseStandardError ) from mypyc.ir.rtypes import ( - RTuple, RInstance, object_rprimitive, is_none_rprimitive, int_rprimitive, is_int_rprimitive + RTuple, object_rprimitive, is_none_rprimitive, int_rprimitive, is_int_rprimitive, + is_list_rprimitive ) from mypyc.ir.func_ir import FUNC_CLASSMETHOD, FUNC_STATICMETHOD from mypyc.irbuild.format_str_tokenizer import ( @@ -130,17 +131,8 @@ def transform_member_expr(builder: IRBuilder, expr: MemberExpr) -> Value: if isinstance(expr.node, MypyFile) and expr.node.fullname in builder.imports: return builder.load_module(expr.node.fullname) - obj_rtype = builder.node_type(expr.expr) - if (isinstance(obj_rtype, RInstance) - and obj_rtype.class_ir.is_ext_class - and obj_rtype.class_ir.has_attr(expr.name) - and not obj_rtype.class_ir.get_method(expr.name)): - # Direct attribute access -> can borrow object - can_borrow = True - else: - can_borrow = False + can_borrow = builder.is_native_attr_ref(expr) obj = builder.accept(expr.expr, can_borrow=can_borrow) - rtype = builder.node_type(expr) # Special case: for named tuples transform attribute access to faster index access. @@ -418,8 +410,12 @@ def transform_op_expr(builder: IRBuilder, expr: OpExpr) -> Value: def transform_index_expr(builder: IRBuilder, expr: IndexExpr) -> Value: - base = builder.accept(expr.base) index = expr.index + base_type = builder.node_type(expr.base) + is_list = is_list_rprimitive(base_type) + can_borrow_base = is_list and is_borrow_friendly_expr(builder, index) + + base = builder.accept(expr.base, can_borrow=can_borrow_base) if isinstance(base.type, RTuple) and isinstance(index, IntExpr): return builder.add(TupleGet(base, index.value, expr.line)) @@ -429,11 +425,31 @@ def transform_index_expr(builder: IRBuilder, expr: IndexExpr) -> Value: if value: return value - index_reg = builder.accept(expr.index) + index_reg = builder.accept(expr.index, can_borrow=is_list) return builder.gen_method_call( base, '__getitem__', [index_reg], builder.node_type(expr), expr.line) +def is_borrow_friendly_expr(builder: IRBuilder, expr: Expression) -> bool: + """Can the result of the expression borrowed temporarily? + + Borrowing means keeping a reference without incrementing the reference count. + """ + if isinstance(expr, (IntExpr, FloatExpr, StrExpr, BytesExpr)): + # Literals are immportal and can always be borrowed + return True + if isinstance(expr, (UnaryExpr, OpExpr)) and constant_fold_expr(builder, expr) is not None: + # Literal expressions are similar to literals + return True + if isinstance(expr, NameExpr): + if isinstance(expr.node, Var) and expr.kind == LDEF: + # Local variable reference can be borrowed + return True + if isinstance(expr, MemberExpr) and builder.is_native_attr_ref(expr): + return True + return False + + def try_constant_fold(builder: IRBuilder, expr: Expression) -> Optional[Value]: """Return the constant value of an expression if possible. @@ -513,7 +529,8 @@ def transform_conditional_expr(builder: IRBuilder, expr: ConditionalExpr) -> Val def transform_comparison_expr(builder: IRBuilder, e: ComparisonExpr) -> Value: # x in (...)/[...] # x not in (...)/[...] - if (e.operators[0] in ['in', 'not in'] + first_op = e.operators[0] + if (first_op in ['in', 'not in'] and len(e.operators) == 1 and isinstance(e.operands[1], (TupleExpr, ListExpr))): items = e.operands[1].items @@ -560,6 +577,12 @@ def transform_comparison_expr(builder: IRBuilder, e: ComparisonExpr) -> Value: else: return builder.true() + if first_op in ('is', 'is not') and len(e.operators) == 1: + right = e.operands[1] + if isinstance(right, NameExpr) and right.fullname == 'builtins.None': + # Special case 'is None' / 'is not None'. + return translate_is_none(builder, e.operands[0], negated=first_op != 'is') + # TODO: Don't produce an expression when used in conditional context # All of the trickiness here is due to support for chained conditionals # (`e1 < e2 > e3`, etc). `e1 < e2 > e3` is approximately equivalent to @@ -584,6 +607,11 @@ def go(i: int, prev: Value) -> Value: return go(0, builder.accept(e.operands[0])) +def translate_is_none(builder: IRBuilder, expr: Expression, negated: bool) -> Value: + v = builder.accept(expr, can_borrow=True) + return builder.binary_op(v, builder.none_object(), 'is not' if negated else 'is', expr.line) + + def transform_basic_comparison(builder: IRBuilder, op: str, left: Value, diff --git a/mypyc/irbuild/ll_builder.py b/mypyc/irbuild/ll_builder.py index bbc30c233039b..c7d8dc7b3ab2f 100644 --- a/mypyc/irbuild/ll_builder.py +++ b/mypyc/irbuild/ll_builder.py @@ -163,13 +163,17 @@ def box(self, src: Value) -> Value: else: return src - def unbox_or_cast(self, src: Value, target_type: RType, line: int) -> Value: + def unbox_or_cast(self, src: Value, target_type: RType, line: int, *, + can_borrow: bool = False) -> Value: if target_type.is_unboxed: return self.add(Unbox(src, target_type, line)) else: - return self.add(Cast(src, target_type, line)) + if can_borrow: + self.keep_alives.append(src) + return self.add(Cast(src, target_type, line, borrow=can_borrow)) - def coerce(self, src: Value, target_type: RType, line: int, force: bool = False) -> Value: + def coerce(self, src: Value, target_type: RType, line: int, force: bool = False, *, + can_borrow: bool = False) -> Value: """Generate a coercion/cast from one type to other (only if needed). For example, int -> object boxes the source int; int -> int emits nothing; @@ -190,7 +194,7 @@ def coerce(self, src: Value, target_type: RType, line: int, force: bool = False) return self.unbox_or_cast(tmp, target_type, line) if ((not src.type.is_unboxed and target_type.is_unboxed) or not is_subtype(src.type, target_type)): - return self.unbox_or_cast(src, target_type, line) + return self.unbox_or_cast(src, target_type, line, can_borrow=can_borrow) elif force: tmp = Register(target_type) self.add(Assign(tmp, src)) diff --git a/mypyc/irbuild/specialize.py b/mypyc/irbuild/specialize.py index d35039ecc0bc0..1b4aa5e8c8c0b 100644 --- a/mypyc/irbuild/specialize.py +++ b/mypyc/irbuild/specialize.py @@ -25,7 +25,7 @@ ) from mypyc.ir.rtypes import ( RType, RTuple, str_rprimitive, list_rprimitive, dict_rprimitive, set_rprimitive, - bool_rprimitive, c_int_rprimitive, is_dict_rprimitive + bool_rprimitive, c_int_rprimitive, is_dict_rprimitive, is_list_rprimitive ) from mypyc.irbuild.format_str_tokenizer import ( tokenizer_format_call, join_formatted_strings, convert_format_expr_to_str, FormatOp @@ -113,14 +113,19 @@ def translate_len( builder: IRBuilder, expr: CallExpr, callee: RefExpr) -> Optional[Value]: if (len(expr.args) == 1 and expr.arg_kinds == [ARG_POS]): - expr_rtype = builder.node_type(expr.args[0]) + arg = expr.args[0] + expr_rtype = builder.node_type(arg) if isinstance(expr_rtype, RTuple): # len() of fixed-length tuple can be trivially determined # statically, though we still need to evaluate it. - builder.accept(expr.args[0]) + builder.accept(arg) return Integer(len(expr_rtype.types)) else: - obj = builder.accept(expr.args[0]) + if is_list_rprimitive(builder.node_type(arg)): + borrow = True + else: + borrow = False + obj = builder.accept(arg, can_borrow=borrow) return builder.builtin_len(obj, expr.line) return None @@ -429,7 +434,12 @@ def translate_isinstance(builder: IRBuilder, expr: CallExpr, callee: RefExpr) -> irs = builder.flatten_classes(expr.args[1]) if irs is not None: - return builder.builder.isinstance_helper(builder.accept(expr.args[0]), irs, expr.line) + can_borrow = all(ir.is_ext_class + and not ir.inherits_python + and not ir.allow_interpreted_subclasses + for ir in irs) + obj = builder.accept(expr.args[0], can_borrow=can_borrow) + return builder.builder.isinstance_helper(obj, irs, expr.line) return None diff --git a/mypyc/irbuild/statement.py b/mypyc/irbuild/statement.py index 9c9273b0cd769..142a77fbe9461 100644 --- a/mypyc/irbuild/statement.py +++ b/mypyc/irbuild/statement.py @@ -58,8 +58,10 @@ def transform_expression_stmt(builder: IRBuilder, stmt: ExpressionStmt) -> None: if isinstance(stmt.expr, StrExpr): # Docstring. Ignore return - # ExpressionStmts do not need to be coerced like other Expressions. + # ExpressionStmts do not need to be coerced like other Expressions, so we shouldn't + # call builder.accept here. stmt.expr.accept(builder.visitor) + builder.flush_keep_alives() def transform_return_stmt(builder: IRBuilder, stmt: ReturnStmt) -> None: @@ -107,6 +109,7 @@ def transform_assignment_stmt(builder: IRBuilder, stmt: AssignmentStmt) -> None: for lvalue in lvalues: target = builder.get_assignment_target(lvalue) builder.assign(target, rvalue_reg, line) + builder.flush_keep_alives() def is_simple_lvalue(expr: Expression) -> bool: diff --git a/mypyc/test-data/exceptions.test b/mypyc/test-data/exceptions.test index 9d688a4c0651c..8c576b49ce82d 100644 --- a/mypyc/test-data/exceptions.test +++ b/mypyc/test-data/exceptions.test @@ -75,31 +75,28 @@ def f(x): r1 :: bit r2 :: __main__.A r3 :: object - r4, r5 :: bit - r6 :: int + r4 :: bit + r5 :: int L0: - r0 = box(None, 1) + r0 = load_address _Py_NoneStruct r1 = x == r0 if r1 goto L1 else goto L2 :: bool L1: return 2 L2: - inc_ref x - r2 = cast(__main__.A, x) + r2 = borrow cast(__main__.A, x) if is_error(r2) goto L6 (error at f:8) else goto L3 L3: - r3 = box(None, 1) - r4 = r2 == r3 - dec_ref r2 - r5 = r4 ^ 1 - if r5 goto L4 else goto L5 :: bool + r3 = load_address _Py_NoneStruct + r4 = r2 != r3 + if r4 goto L4 else goto L5 :: bool L4: return 4 L5: return 6 L6: - r6 = :: int - return r6 + r5 = :: int + return r5 [case testListSum] from typing import List @@ -518,4 +515,3 @@ L13: L14: dec_ref r9 goto L8 - diff --git a/mypyc/test-data/irbuild-classes.test b/mypyc/test-data/irbuild-classes.test index a5f360928abe1..fcf6ef9574358 100644 --- a/mypyc/test-data/irbuild-classes.test +++ b/mypyc/test-data/irbuild-classes.test @@ -116,22 +116,22 @@ def Node.length(self): self :: __main__.Node r0 :: union[__main__.Node, None] r1 :: object - r2, r3 :: bit - r4 :: union[__main__.Node, None] - r5 :: __main__.Node - r6, r7 :: int + r2 :: bit + r3 :: union[__main__.Node, None] + r4 :: __main__.Node + r5, r6 :: int L0: - r0 = self.next - r1 = box(None, 1) - r2 = r0 == r1 - r3 = r2 ^ 1 - if r3 goto L1 else goto L2 :: bool + r0 = borrow self.next + r1 = load_address _Py_NoneStruct + r2 = r0 != r1 + keep_alive self + if r2 goto L1 else goto L2 :: bool L1: - r4 = self.next - r5 = cast(__main__.Node, r4) - r6 = r5.length() - r7 = CPyTagged_Add(2, r6) - return r7 + r3 = self.next + r4 = cast(__main__.Node, r3) + r5 = r4.length() + r6 = CPyTagged_Add(2, r5) + return r6 L2: return 2 diff --git a/mypyc/test-data/irbuild-isinstance.test b/mypyc/test-data/irbuild-isinstance.test index b340ea302623c..6bb92d0a947e8 100644 --- a/mypyc/test-data/irbuild-isinstance.test +++ b/mypyc/test-data/irbuild-isinstance.test @@ -67,3 +67,43 @@ L2: r4 = r9 L3: return r4 + +[case testBorrowSpecialCaseWithIsinstance] +class C: + s: str + +def g() -> object: + pass + +def f() -> None: + x = g() + if isinstance(x, C): + x.s +[out] +def g(): + r0 :: object +L0: + r0 = box(None, 1) + return r0 +def f(): + r0, x, r1 :: object + r2 :: ptr + r3 :: object + r4 :: bit + r5 :: __main__.C + r6 :: str +L0: + r0 = g() + x = r0 + r1 = __main__.C :: type + r2 = get_element_ptr x ob_type :: PyObject + r3 = load_mem r2 :: builtins.object* + keep_alive x + r4 = r3 == r1 + if r4 goto L1 else goto L2 :: bool +L1: + r5 = borrow cast(__main__.C, x) + r6 = r5.s + keep_alive x +L2: + return 1 diff --git a/mypyc/test-data/irbuild-optional.test b/mypyc/test-data/irbuild-optional.test index cc8653ee3e822..4b1d3d1ffec2b 100644 --- a/mypyc/test-data/irbuild-optional.test +++ b/mypyc/test-data/irbuild-optional.test @@ -13,7 +13,7 @@ def f(x): r0 :: object r1 :: bit L0: - r0 = box(None, 1) + r0 = load_address _Py_NoneStruct r1 = x == r0 if r1 goto L1 else goto L2 :: bool L1: @@ -34,12 +34,11 @@ def f(x: Optional[A]) -> int: def f(x): x :: union[__main__.A, None] r0 :: object - r1, r2 :: bit + r1 :: bit L0: - r0 = box(None, 1) - r1 = x == r0 - r2 = r1 ^ 1 - if r2 goto L1 else goto L2 :: bool + r0 = load_address _Py_NoneStruct + r1 = x != r0 + if r1 goto L1 else goto L2 :: bool L1: return 2 L2: @@ -188,20 +187,19 @@ def f(x): x :: union[__main__.A, None] r0, y :: __main__.A r1 :: object - r2, r3 :: bit - r4, r5 :: __main__.A + r2 :: bit + r3, r4 :: __main__.A L0: r0 = A() y = r0 - r1 = box(None, 1) - r2 = x == r1 - r3 = r2 ^ 1 - if r3 goto L1 else goto L2 :: bool + r1 = load_address _Py_NoneStruct + r2 = x != r1 + if r2 goto L1 else goto L2 :: bool L1: + r3 = cast(__main__.A, x) + y = r3 r4 = cast(__main__.A, x) - y = r4 - r5 = cast(__main__.A, x) - return r5 + return r4 L2: return y @@ -219,8 +217,8 @@ def f(y): x :: union[int, None] r1 :: bit r2, r3 :: object - r4, r5 :: bit - r6 :: int + r4 :: bit + r5 :: int L0: r0 = box(None, 1) x = r0 @@ -230,13 +228,12 @@ L1: r2 = box(int, y) x = r2 L2: - r3 = box(None, 1) - r4 = x == r3 - r5 = r4 ^ 1 - if r5 goto L3 else goto L4 :: bool + r3 = load_address _Py_NoneStruct + r4 = x != r3 + if r4 goto L3 else goto L4 :: bool L3: - r6 = unbox(int, x) - y = r6 + r5 = unbox(int, x) + y = r5 L4: return 1 @@ -272,8 +269,9 @@ L1: r5 = CPyTagged_Add(r4, 2) return r5 L2: - r6 = cast(__main__.A, x) + r6 = borrow cast(__main__.A, x) r7 = r6.a + keep_alive x return r7 L3: unreachable @@ -540,4 +538,3 @@ L0: r3 = r2 L1: return 1 - diff --git a/mypyc/test-data/irbuild-str.test b/mypyc/test-data/irbuild-str.test index bb296c53d2241..63be7250ebd10 100644 --- a/mypyc/test-data/irbuild-str.test +++ b/mypyc/test-data/irbuild-str.test @@ -14,14 +14,14 @@ def do_split(s, sep, max_split): sep :: union[str, None] max_split :: union[int, None] r0, r1, r2 :: object - r3, r4 :: bit - r5 :: object - r6, r7 :: bit - r8 :: str - r9 :: int - r10 :: list - r11 :: str - r12, r13 :: list + r3 :: bit + r4 :: object + r5 :: bit + r6 :: str + r7 :: int + r8 :: list + r9 :: str + r10, r11 :: list L0: if is_error(sep) goto L1 else goto L2 L1: @@ -33,28 +33,27 @@ L3: r1 = box(None, 1) max_split = r1 L4: - r2 = box(None, 1) - r3 = sep == r2 - r4 = r3 ^ 1 - if r4 goto L5 else goto L9 :: bool + r2 = load_address _Py_NoneStruct + r3 = sep != r2 + if r3 goto L5 else goto L9 :: bool L5: - r5 = box(None, 1) - r6 = max_split == r5 - r7 = r6 ^ 1 - if r7 goto L6 else goto L7 :: bool + r4 = load_address _Py_NoneStruct + r5 = max_split != r4 + if r5 goto L6 else goto L7 :: bool L6: - r8 = cast(str, sep) - r9 = unbox(int, max_split) - r10 = CPyStr_Split(s, r8, r9) - return r10 + r6 = cast(str, sep) + r7 = unbox(int, max_split) + r8 = CPyStr_Split(s, r6, r7) + return r8 L7: - r11 = cast(str, sep) - r12 = PyUnicode_Split(s, r11, -1) - return r12 + r9 = cast(str, sep) + r10 = PyUnicode_Split(s, r9, -1) + return r10 L8: L9: - r13 = PyUnicode_Split(s, 0, -1) - return r13 + r11 = PyUnicode_Split(s, 0, -1) + return r11 + [case testStrEquality] def eq(x: str, y: str) -> bool: @@ -106,39 +105,38 @@ L3: [case testStrReplace] from typing import Optional -def do_replace(s: str, old_substr: str, new_substr: str, max_count: Optional[int] = None) -> str: - if max_count is not None: - return s.replace(old_substr, new_substr, max_count) - else: - return s.replace(old_substr, new_substr) +def do_replace(s: str, old_substr: str, new_substr: str, max_count: Optional[int] = None) -> str: + if max_count is not None: + return s.replace(old_substr, new_substr, max_count) + else: + return s.replace(old_substr, new_substr) [out] -def do_replace(s, old_substr, new_substr, max_count): - s, old_substr, new_substr :: str - max_count :: union[int, None] - r0, r1 :: object - r2, r3 :: bit - r4 :: int - r5, r6 :: str -L0: - if is_error(max_count) goto L1 else goto L2 -L1: - r0 = box(None, 1) - max_count = r0 -L2: - r1 = box(None, 1) - r2 = max_count == r1 - r3 = r2 ^ 1 - if r3 goto L3 else goto L4 :: bool -L3: - r4 = unbox(int, max_count) - r5 = CPyStr_Replace(s, old_substr, new_substr, r4) - return r5 -L4: - r6 = PyUnicode_Replace(s, old_substr, new_substr, -1) - return r6 -L5: - unreachable - +def do_replace(s, old_substr, new_substr, max_count): + s, old_substr, new_substr :: str + max_count :: union[int, None] + r0, r1 :: object + r2 :: bit + r3 :: int + r4, r5 :: str +L0: + if is_error(max_count) goto L1 else goto L2 +L1: + r0 = box(None, 1) + max_count = r0 +L2: + r1 = load_address _Py_NoneStruct + r2 = max_count != r1 + if r2 goto L3 else goto L4 :: bool +L3: + r3 = unbox(int, max_count) + r4 = CPyStr_Replace(s, old_substr, new_substr, r3) + return r4 +L4: + r5 = PyUnicode_Replace(s, old_substr, new_substr, -1) + return r5 +L5: + unreachable + [case testStrToBool] def is_true(x: str) -> bool: if x: @@ -314,4 +312,3 @@ L0: r4 = 'backslashreplace' r5 = CPy_Encode(s, r3, r4) return 1 - diff --git a/mypyc/test-data/refcount.test b/mypyc/test-data/refcount.test index 965d4066c0b50..a7ee390c8d74f 100644 --- a/mypyc/test-data/refcount.test +++ b/mypyc/test-data/refcount.test @@ -950,3 +950,294 @@ L0: r0 = borrow d.c r1 = r0.x return r1 + +[case testBorrowAttributeTwice] +def f(e: E) -> int: + return e.d.c.x + +class C: + x: int +class D: + c: C +class E: + d: D +[out] +def f(e): + e :: __main__.E + r0 :: __main__.D + r1 :: __main__.C + r2 :: int +L0: + r0 = borrow e.d + r1 = borrow r0.c + r2 = r1.x + return r2 + +[case testBorrowAttributeIsNone] +from typing import Optional + +def f(c: C) -> bool: + return c.x is not None + +def g(c: C) -> bool: + return c.x is None + +class C: + x: Optional[str] +[out] +def f(c): + c :: __main__.C + r0 :: union[str, None] + r1 :: object + r2 :: bit +L0: + r0 = borrow c.x + r1 = load_address _Py_NoneStruct + r2 = r0 != r1 + return r2 +def g(c): + c :: __main__.C + r0 :: union[str, None] + r1 :: object + r2 :: bit +L0: + r0 = borrow c.x + r1 = load_address _Py_NoneStruct + r2 = r0 == r1 + return r2 + +[case testBorrowAttributeNarrowOptional] +from typing import Optional + +def f(c: C) -> bool: + if c.x is not None: + return c.x.b + return False + +class C: + x: Optional[D] + +class D: + b: bool +[out] +def f(c): + c :: __main__.C + r0 :: union[__main__.D, None] + r1 :: object + r2 :: bit + r3 :: union[__main__.D, None] + r4 :: __main__.D + r5 :: bool +L0: + r0 = borrow c.x + r1 = load_address _Py_NoneStruct + r2 = r0 != r1 + if r2 goto L1 else goto L2 :: bool +L1: + r3 = borrow c.x + r4 = borrow cast(__main__.D, r3) + r5 = r4.b + return r5 +L2: + return 0 + +[case testBorrowLenArgument] +from typing import List + +def f(x: C) -> int: + return len(x.a) + +class C: + a: List[str] +[out] +def f(x): + x :: __main__.C + r0 :: list + r1 :: ptr + r2 :: native_int + r3 :: short_int +L0: + r0 = borrow x.a + r1 = get_element_ptr r0 ob_size :: PyVarObject + r2 = load_mem r1 :: native_int* + r3 = r2 << 1 + return r3 + +[case testBorrowIsinstanceArgument] +from typing import List + +def f(x: C) -> bool: + if isinstance(x.a, D): + return x.a.b + else: + return True + +class C: + a: object + +class D: + b: bool +[out] +def f(x): + x :: __main__.C + r0, r1 :: object + r2 :: ptr + r3 :: object + r4 :: bit + r5 :: object + r6 :: __main__.D + r7 :: bool +L0: + r0 = borrow x.a + r1 = __main__.D :: type + r2 = get_element_ptr r0 ob_type :: PyObject + r3 = load_mem r2 :: builtins.object* + r4 = r3 == r1 + if r4 goto L1 else goto L2 :: bool +L1: + r5 = borrow x.a + r6 = borrow cast(__main__.D, r5) + r7 = r6.b + return r7 +L2: + return 1 + +[case testBorrowListGetItem1] +from typing import List + +def literal_index(x: C) -> str: + return x.a[0] + +def negative_index(x: C) -> str: + return x.a[-1] + +def lvar_index(x: C, n: int) -> str: + return x.a[n] + +class C: + a: List[str] + +[out] +def literal_index(x): + x :: __main__.C + r0 :: list + r1 :: object + r2 :: str +L0: + r0 = borrow x.a + r1 = CPyList_GetItemShort(r0, 0) + r2 = cast(str, r1) + return r2 +def negative_index(x): + x :: __main__.C + r0 :: list + r1 :: object + r2 :: str +L0: + r0 = borrow x.a + r1 = CPyList_GetItemShort(r0, -2) + r2 = cast(str, r1) + return r2 +def lvar_index(x, n): + x :: __main__.C + n :: int + r0 :: list + r1 :: object + r2 :: str +L0: + r0 = borrow x.a + r1 = CPyList_GetItem(r0, n) + r2 = cast(str, r1) + return r2 + +[case testBorrowListGetItem2] +from typing import List + +def attr_index(x: C) -> str: + return x.a[x.n] + +class C: + a: List[str] + n: int +[out] +def attr_index(x): + x :: __main__.C + r0 :: list + r1 :: int + r2 :: object + r3 :: str +L0: + r0 = borrow x.a + r1 = borrow x.n + r2 = CPyList_GetItem(r0, r1) + r3 = cast(str, r2) + return r3 + +[case testCannotBorrowListGetItem] +from typing import List + +def func_index(x: C) -> str: + return x.a[f()] + +def f() -> int: return 0 + +class C: + a: List[str] +[out] +def func_index(x): + x :: __main__.C + r0 :: list + r1 :: int + r2 :: object + r3 :: str +L0: + r0 = x.a + r1 = f() + r2 = CPyList_GetItem(r0, r1) + dec_ref r0 + dec_ref r1 :: int + r3 = cast(str, r2) + return r3 +def f(): +L0: + return 0 + +[case testBorrowSetAttrObject] +from typing import Optional + +def f(x: Optional[C]) -> None: + if x is not None: + x.b = True + +def g(x: D) -> None: + x.c.b = False + +class C: + b: bool + +class D: + c: C +[out] +def f(x): + x :: union[__main__.C, None] + r0 :: object + r1 :: bit + r2 :: __main__.C + r3 :: bool +L0: + r0 = load_address _Py_NoneStruct + r1 = x != r0 + if r1 goto L1 else goto L2 :: bool +L1: + r2 = borrow cast(__main__.C, x) + r2.b = 1; r3 = is_error +L2: + return 1 +def g(x): + x :: __main__.D + r0 :: __main__.C + r1 :: bool +L0: + r0 = borrow x.c + r0.b = 0; r1 = is_error + return 1 diff --git a/mypyc/test-data/run-generators.test b/mypyc/test-data/run-generators.test index b2f244b900086..8aecce6564c89 100644 --- a/mypyc/test-data/run-generators.test +++ b/mypyc/test-data/run-generators.test @@ -581,3 +581,17 @@ except RuntimeError as e: assert str(e) == 'error' else: assert False + +[case testBorrowingInGeneratorNearYield] +from typing import Iterator + +class Foo: + flag: bool + +class C: + foo: Foo + + def genf(self) -> Iterator[None]: + self.foo.flag = True + yield + self.foo.flag = False From 7f4f5b87631dbf4746f81d81e3ccf86bac5901b3 Mon Sep 17 00:00:00 2001 From: Ethan Smith Date: Thu, 19 May 2022 08:02:09 -0700 Subject: [PATCH 303/377] Skip tests that depend on lxml if not installed (#12813) Detect if lxml is importable in the test suite, if it is not, then skip the report tests which depend on it. This is useful for enabling CI on new Python versions that may not have lxml wheels yet. Closes #11662. --- mypy/test/testcheck.py | 8 ++++++++ mypy/test/testcmdline.py | 9 +++++++++ mypy/test/testreports.py | 10 ++++++++++ 3 files changed, 27 insertions(+) diff --git a/mypy/test/testcheck.py b/mypy/test/testcheck.py index f0dc4bc6a6715..cc0c5875f53b8 100644 --- a/mypy/test/testcheck.py +++ b/mypy/test/testcheck.py @@ -21,6 +21,12 @@ from mypy.errors import CompileError from mypy.semanal_main import core_modules +try: + import lxml # type: ignore +except ImportError: + lxml = None + +import pytest # List of files that contain test case descriptions. typecheck_files = [ @@ -117,6 +123,8 @@ class TypeCheckSuite(DataSuite): files = typecheck_files def run_case(self, testcase: DataDrivenTestCase) -> None: + if lxml is None and os.path.basename(testcase.file) == 'check-reports.test': + pytest.skip("Cannot import lxml. Is it installed?") incremental = ('incremental' in testcase.name.lower() or 'incremental' in testcase.file or 'serialize' in testcase.file) diff --git a/mypy/test/testcmdline.py b/mypy/test/testcmdline.py index d58d10087c808..62e258677c7f8 100644 --- a/mypy/test/testcmdline.py +++ b/mypy/test/testcmdline.py @@ -18,6 +18,13 @@ assert_string_arrays_equal, normalize_error_messages, check_test_output_files ) +try: + import lxml # type: ignore +except ImportError: + lxml = None + +import pytest + # Path to Python 3 interpreter python3_path = sys.executable @@ -35,6 +42,8 @@ class PythonCmdlineSuite(DataSuite): native_sep = True def run_case(self, testcase: DataDrivenTestCase) -> None: + if lxml is None and os.path.basename(testcase.file) == 'reports.test': + pytest.skip("Cannot import lxml. Is it installed?") for step in [1] + sorted(testcase.output2): test_python_cmdline(testcase, step) diff --git a/mypy/test/testreports.py b/mypy/test/testreports.py index 75f24d514431a..37dc16a107d59 100644 --- a/mypy/test/testreports.py +++ b/mypy/test/testreports.py @@ -5,11 +5,21 @@ from mypy.report import CoberturaPackage, get_line_rate +try: + import lxml # type: ignore +except ImportError: + lxml = None + +import pytest + + class CoberturaReportSuite(Suite): + @pytest.mark.skipif(lxml is None, reason="Cannot import lxml. Is it installed?") def test_get_line_rate(self) -> None: assert_equal('1.0', get_line_rate(0, 0)) assert_equal('0.3333', get_line_rate(1, 3)) + @pytest.mark.skipif(lxml is None, reason="Cannot import lxml. Is it installed?") def test_as_xml(self) -> None: import lxml.etree as etree # type: ignore From 6c2690e4af5e12d68a5b91f7c9117f783e528277 Mon Sep 17 00:00:00 2001 From: pranavrajpal <78008260+pranavrajpal@users.noreply.github.com> Date: Thu, 19 May 2022 08:04:06 -0700 Subject: [PATCH 304/377] Avoid crashing on invalid python executables (#12812) When an invalid python executable is passed to mypy, show an error message instead of crashing. --- mypy/modulefinder.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/mypy/modulefinder.py b/mypy/modulefinder.py index bee99156a5701..4ab95dd6564f5 100644 --- a/mypy/modulefinder.py +++ b/mypy/modulefinder.py @@ -12,6 +12,8 @@ import sys from enum import Enum, unique +from mypy.errors import CompileError + if sys.version_info >= (3, 11): import tomllib else: @@ -649,9 +651,15 @@ def get_site_packages_dirs(python_executable: Optional[str]) -> Tuple[List[str], else: # Use subprocess to get the package directory of given Python # executable - site_packages = ast.literal_eval( - subprocess.check_output([python_executable, pyinfo.__file__, 'getsitepackages'], - stderr=subprocess.PIPE).decode()) + try: + site_packages = ast.literal_eval( + subprocess.check_output([python_executable, pyinfo.__file__, 'getsitepackages'], + stderr=subprocess.PIPE).decode()) + except OSError as err: + reason = os.strerror(err.errno) + raise CompileError( + [f"mypy: Invalid python executable '{python_executable}': {reason}"] + ) from err return expand_site_packages(site_packages) From e612e440103ec7abdc40d0e41115701362abad21 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Fri, 20 May 2022 14:27:54 +0100 Subject: [PATCH 305/377] Fix crash on type alias definition inside dataclass declaration (#12792) Skip processing a type alias node and generate an error. Fixes #12544. --- mypy/plugins/dataclasses.py | 16 ++++++++++++++- test-data/unit/check-dataclasses.test | 28 +++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/mypy/plugins/dataclasses.py b/mypy/plugins/dataclasses.py index 24077bb4a5490..00c46e1417c53 100644 --- a/mypy/plugins/dataclasses.py +++ b/mypy/plugins/dataclasses.py @@ -5,7 +5,7 @@ from mypy.nodes import ( ARG_OPT, ARG_NAMED, ARG_NAMED_OPT, ARG_POS, ARG_STAR, ARG_STAR2, MDEF, - Argument, AssignmentStmt, CallExpr, Context, Expression, JsonDict, + Argument, AssignmentStmt, CallExpr, TypeAlias, Context, Expression, JsonDict, NameExpr, RefExpr, SymbolTableNode, TempNode, TypeInfo, Var, TypeVarExpr, PlaceholderNode ) @@ -333,6 +333,20 @@ def collect_attributes(self) -> Optional[List[DataclassAttribute]]: node = sym.node assert not isinstance(node, PlaceholderNode) + + if isinstance(node, TypeAlias): + ctx.api.fail( + ( + 'Type aliases inside dataclass definitions ' + 'are not supported at runtime' + ), + node + ) + # Skip processing this node. This doesn't match the runtime behaviour, + # but the only alternative would be to modify the SymbolTable, + # and it's a little hairy to do that in a plugin. + continue + assert isinstance(node, Var) # x: ClassVar[int] is ignored by dataclasses. diff --git a/test-data/unit/check-dataclasses.test b/test-data/unit/check-dataclasses.test index abfcb79c0cc57..972cc4d40a1e2 100644 --- a/test-data/unit/check-dataclasses.test +++ b/test-data/unit/check-dataclasses.test @@ -526,6 +526,34 @@ Application.COUNTER = 1 [builtins fixtures/dataclasses.pyi] +[case testTypeAliasInDataclassDoesNotCrash] +# flags: --python-version 3.7 +from dataclasses import dataclass +from typing import Callable +from typing_extensions import TypeAlias + +@dataclass +class Foo: + x: int + +@dataclass +class One: + S: TypeAlias = Foo # E: Type aliases inside dataclass definitions are not supported at runtime + +a = One() +reveal_type(a.S) # N: Revealed type is "def (x: builtins.int) -> __main__.Foo" +a.S() # E: Missing positional argument "x" in call to "Foo" +reveal_type(a.S(5)) # N: Revealed type is "__main__.Foo" + +@dataclass +class Two: + S: TypeAlias = Callable[[int], str] # E: Type aliases inside dataclass definitions are not supported at runtime + +c = Two() +x = c.S # E: Member "S" is not assignable +reveal_type(x) # N: Revealed type is "Any" +[builtins fixtures/dataclasses.pyi] + [case testDataclassOrdering] # flags: --python-version 3.7 from dataclasses import dataclass From e93be734f4ca51f88f0b46e5c089014e712e1d11 Mon Sep 17 00:00:00 2001 From: Hugues Date: Fri, 20 May 2022 08:37:23 -0700 Subject: [PATCH 306/377] speedup typechecking of nested if expressions (#12700) Deeply nested if/else expressions have a worst-case exponential behavior. This will for instance manifest when returning literal values which cause repeated analysis of conditional branches with subtly different type context for each literal. This can be optimized by observing that a simple literal context will yield the same analysis as its fallback type, and likewise, two literals of the same fallback type will yield the same analysis. In those case we can avoid the repeated analysis and prevent the worst-case exponential behavior. Fixes #9591 --- mypy/checkexpr.py | 25 +++++++++++++++++++++---- mypy/typeops.py | 2 +- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index bfbe961adc7aa..0149f19714770 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -69,7 +69,7 @@ try_expanding_sum_type_to_union, tuple_fallback, make_simplified_union, true_only, false_only, erase_to_union_or_bound, function_type, callable_type, try_getting_str_literals, custom_special_method, - is_literal_type_like, + is_literal_type_like, simple_literal_type, ) from mypy.message_registry import ErrorMessage import mypy.errorcodes as codes @@ -3874,26 +3874,43 @@ def visit_conditional_expr(self, e: ConditionalExpr, allow_none_return: bool = F if_type = self.analyze_cond_branch(if_map, e.if_expr, context=ctx, allow_none_return=allow_none_return) + # we want to keep the narrowest value of if_type for union'ing the branches + # however, it would be silly to pass a literal as a type context. Pass the + # underlying fallback type instead. + if_type_fallback = simple_literal_type(get_proper_type(if_type)) or if_type + # Analyze the right branch using full type context and store the type full_context_else_type = self.analyze_cond_branch(else_map, e.else_expr, context=ctx, allow_none_return=allow_none_return) + if not mypy.checker.is_valid_inferred_type(if_type): # Analyze the right branch disregarding the left branch. else_type = full_context_else_type + # we want to keep the narrowest value of else_type for union'ing the branches + # however, it would be silly to pass a literal as a type context. Pass the + # underlying fallback type instead. + else_type_fallback = simple_literal_type(get_proper_type(else_type)) or else_type # If it would make a difference, re-analyze the left # branch using the right branch's type as context. - if ctx is None or not is_equivalent(else_type, ctx): + if ctx is None or not is_equivalent(else_type_fallback, ctx): # TODO: If it's possible that the previous analysis of # the left branch produced errors that are avoided # using this context, suppress those errors. - if_type = self.analyze_cond_branch(if_map, e.if_expr, context=else_type, + if_type = self.analyze_cond_branch(if_map, e.if_expr, context=else_type_fallback, allow_none_return=allow_none_return) + elif if_type_fallback == ctx: + # There is no point re-running the analysis if if_type is equal to ctx. + # That would be an exact duplicate of the work we just did. + # This optimization is particularly important to avoid exponential blowup with nested + # if/else expressions: https://github.com/python/mypy/issues/9591 + # TODO: would checking for is_proper_subtype also work and cover more cases? + else_type = full_context_else_type else: # Analyze the right branch in the context of the left # branch's type. - else_type = self.analyze_cond_branch(else_map, e.else_expr, context=if_type, + else_type = self.analyze_cond_branch(else_map, e.else_expr, context=if_type_fallback, allow_none_return=allow_none_return) # Only create a union type if the type context is a union, to be mostly diff --git a/mypy/typeops.py b/mypy/typeops.py index e8171e2e85ab1..22ca0b6ec2fe4 100644 --- a/mypy/typeops.py +++ b/mypy/typeops.py @@ -318,7 +318,7 @@ def simple_literal_value_key(t: ProperType) -> Optional[Tuple[str, ...]]: return None -def simple_literal_type(t: ProperType) -> Optional[Instance]: +def simple_literal_type(t: Optional[ProperType]) -> Optional[Instance]: """Extract the underlying fallback Instance type for a simple Literal""" if isinstance(t, Instance) and t.last_known_value is not None: t = t.last_known_value From f7e94ee94c2917fb8e522f16bea226b9d8b8d844 Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Fri, 20 May 2022 17:44:27 +0200 Subject: [PATCH 307/377] Make pybind11 test fixture fully self-contained (#12722) Co-authored-by: Keller Fabian Rudolf (CC-AD/EYC3) --- misc/test-stubgenc.sh | 15 +- test-data/pybind11_mypy_demo/pyproject.toml | 10 ++ test-data/pybind11_mypy_demo/setup.py | 18 ++ test-data/pybind11_mypy_demo/src/main.cpp | 170 ++++++++++++++++++ .../stubgen/pybind11_mypy_demo/__init__.pyi | 0 .../stubgen/pybind11_mypy_demo/basics.pyi | 4 + 6 files changed, 212 insertions(+), 5 deletions(-) create mode 100644 test-data/pybind11_mypy_demo/pyproject.toml create mode 100644 test-data/pybind11_mypy_demo/setup.py create mode 100644 test-data/pybind11_mypy_demo/src/main.cpp rename test-data/{ => pybind11_mypy_demo}/stubgen/pybind11_mypy_demo/__init__.pyi (100%) rename test-data/{ => pybind11_mypy_demo}/stubgen/pybind11_mypy_demo/basics.pyi (95%) diff --git a/misc/test-stubgenc.sh b/misc/test-stubgenc.sh index 175c912e67126..7da135f0bf16f 100755 --- a/misc/test-stubgenc.sh +++ b/misc/test-stubgenc.sh @@ -1,14 +1,19 @@ #!/bin/bash -# This script is expected to be run from root of the mypy repo + +set -e +set -x + +cd "$(dirname $0)/.." # Install dependencies, demo project and mypy python -m pip install -r test-requirements.txt -python -m pip install pybind11-mypy-demo==0.0.1 +python -m pip install ./test-data/pybind11_mypy_demo python -m pip install . # Remove expected stubs and generate new inplace -rm -rf test-data/stubgen/pybind11_mypy_demo -stubgen -p pybind11_mypy_demo -o test-data/stubgen/ +STUBGEN_OUTPUT_FOLDER=./test-data/pybind11_mypy_demo/stubgen +rm -rf $STUBGEN_OUTPUT_FOLDER/* +stubgen -p pybind11_mypy_demo -o $STUBGEN_OUTPUT_FOLDER # Compare generated stubs to expected ones -git diff --exit-code test-data/stubgen/pybind11_mypy_demo +git diff --exit-code $STUBGEN_OUTPUT_FOLDER diff --git a/test-data/pybind11_mypy_demo/pyproject.toml b/test-data/pybind11_mypy_demo/pyproject.toml new file mode 100644 index 0000000000000..878abe731b1b0 --- /dev/null +++ b/test-data/pybind11_mypy_demo/pyproject.toml @@ -0,0 +1,10 @@ +[build-system] +requires = [ + "setuptools>=42", + "wheel", + # Officially supported pybind11 version. This is pinned to guarantee 100% reproducible CI. + # As a result, the version needs to be bumped manually at will. + "pybind11==2.9.2", +] + +build-backend = "setuptools.build_meta" \ No newline at end of file diff --git a/test-data/pybind11_mypy_demo/setup.py b/test-data/pybind11_mypy_demo/setup.py new file mode 100644 index 0000000000000..0da1cfbcef197 --- /dev/null +++ b/test-data/pybind11_mypy_demo/setup.py @@ -0,0 +1,18 @@ +# pybind11 is available at setup time due to pyproject.toml +from pybind11.setup_helpers import Pybind11Extension +from setuptools import setup + +# Documentation: https://pybind11.readthedocs.io/en/stable/compiling.html +ext_modules = [ + Pybind11Extension( + "pybind11_mypy_demo", + ["src/main.cpp"], + cxx_std=17, + ), +] + +setup( + name="pybind11-mypy-demo", + version="0.0.1", + ext_modules=ext_modules, +) diff --git a/test-data/pybind11_mypy_demo/src/main.cpp b/test-data/pybind11_mypy_demo/src/main.cpp new file mode 100644 index 0000000000000..5cedef391b2d3 --- /dev/null +++ b/test-data/pybind11_mypy_demo/src/main.cpp @@ -0,0 +1,170 @@ +/** + * This file contains the pybind11 reference implementation for the stugen tests, + * and was originally inspired by: + * + * https://github.com/sizmailov/pybind11-mypy-demo + * + * Copyright (c) 2016 The Pybind Development Team, All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You are under no obligation whatsoever to provide any bug fixes, patches, or + * upgrades to the features, functionality or performance of the source code + * ("Enhancements") to anyone; however, if you choose to make your Enhancements + * available either publicly, or directly to the author of this software, without + * imposing a separate written license agreement for such Enhancements, then you + * hereby grant the following license: a non-exclusive, royalty-free perpetual + * license to install, use, modify, prepare derivative works, incorporate into + * other computer software, distribute, and sublicense such enhancements or + * derivative works thereof, in binary and source code form. + */ + +#include +#include + +namespace py = pybind11; + +namespace basics { + +int answer() { + return 42; +} + +int sum(int a, int b) { + return a + b; +} + +double midpoint(double left, double right){ + return left + (right - left)/2; +} + +double weighted_midpoint(double left, double right, double alpha=0.5) { + return left + (right - left) * alpha; +} + +struct Point { + + enum class LengthUnit { + mm=0, + pixel, + inch + }; + + enum class AngleUnit { + radian=0, + degree + }; + + Point() : Point(0, 0) {} + Point(double x, double y) : x(x), y(y) {} + + static const Point origin; + static const Point x_axis; + static const Point y_axis; + + static LengthUnit length_unit; + static AngleUnit angle_unit; + + double length() const { + return std::sqrt(x * x + y * y); + } + + double distance_to(double other_x, double other_y) const { + double dx = x - other_x; + double dy = y - other_y; + return std::sqrt(dx*dx + dy*dy); + } + + double distance_to(const Point& other) const { + return distance_to(other.x, other.y); + } + + double x, y; +}; + +const Point Point::origin = Point(0, 0); +const Point Point::x_axis = Point(1, 0); +const Point Point::y_axis = Point(0, 1); + +Point::LengthUnit Point::length_unit = Point::LengthUnit::mm; +Point::AngleUnit Point::angle_unit = Point::AngleUnit::radian; + +} // namespace: basics + +void bind_basics(py::module& basics) { + + using namespace basics; + + // Functions + basics.def("answer", &answer); + basics.def("sum", &sum); + basics.def("midpoint", &midpoint, py::arg("left"), py::arg("right")); + basics.def("weighted_midpoint", weighted_midpoint, py::arg("left"), py::arg("right"), py::arg("alpha")=0.5); + + // Classes + py::class_ pyPoint(basics, "Point"); + py::enum_ pyLengthUnit(pyPoint, "LengthUnit"); + py::enum_ pyAngleUnit(pyPoint, "AngleUnit"); + + pyPoint + .def(py::init<>()) + .def(py::init(), py::arg("x"), py::arg("y")) + .def("distance_to", py::overload_cast(&Point::distance_to, py::const_), py::arg("x"), py::arg("y")) + .def("distance_to", py::overload_cast(&Point::distance_to, py::const_), py::arg("other")) + .def_readwrite("x", &Point::x) + .def_property("y", + [](Point& self){ return self.y; }, + [](Point& self, double value){ self.y = value; } + ) + .def_property_readonly("length", &Point::length) + .def_property_readonly_static("x_axis", [](py::object cls){return Point::x_axis;}) + .def_property_readonly_static("y_axis", [](py::object cls){return Point::y_axis;}) + .def_readwrite_static("length_unit", &Point::length_unit) + .def_property_static("angle_unit", + [](py::object& /*cls*/){ return Point::angle_unit; }, + [](py::object& /*cls*/, Point::AngleUnit value){ Point::angle_unit = value; } + ); + + pyPoint.attr("origin") = Point::origin; + + pyLengthUnit + .value("mm", Point::LengthUnit::mm) + .value("pixel", Point::LengthUnit::pixel) + .value("inch", Point::LengthUnit::inch); + + pyAngleUnit + .value("radian", Point::AngleUnit::radian) + .value("degree", Point::AngleUnit::degree); + + // Module-level attributes + basics.attr("PI") = std::acos(-1); + basics.attr("__version__") = "0.0.1"; +} + +PYBIND11_MODULE(pybind11_mypy_demo, m) { + auto basics = m.def_submodule("basics"); + bind_basics(basics); +} \ No newline at end of file diff --git a/test-data/stubgen/pybind11_mypy_demo/__init__.pyi b/test-data/pybind11_mypy_demo/stubgen/pybind11_mypy_demo/__init__.pyi similarity index 100% rename from test-data/stubgen/pybind11_mypy_demo/__init__.pyi rename to test-data/pybind11_mypy_demo/stubgen/pybind11_mypy_demo/__init__.pyi diff --git a/test-data/stubgen/pybind11_mypy_demo/basics.pyi b/test-data/pybind11_mypy_demo/stubgen/pybind11_mypy_demo/basics.pyi similarity index 95% rename from test-data/stubgen/pybind11_mypy_demo/basics.pyi rename to test-data/pybind11_mypy_demo/stubgen/pybind11_mypy_demo/basics.pyi index 99093fd6087a6..226080ac9d57a 100644 --- a/test-data/stubgen/pybind11_mypy_demo/basics.pyi +++ b/test-data/pybind11_mypy_demo/stubgen/pybind11_mypy_demo/basics.pyi @@ -18,6 +18,8 @@ class Point: def __setstate__(self, state: int) -> None: ... @property def name(self) -> str: ... + @property + def value(self) -> int: ... class LengthUnit: __entries: ClassVar[dict] = ... @@ -34,6 +36,8 @@ class Point: def __setstate__(self, state: int) -> None: ... @property def name(self) -> str: ... + @property + def value(self) -> int: ... angle_unit: ClassVar[Point.AngleUnit] = ... length_unit: ClassVar[Point.LengthUnit] = ... x_axis: ClassVar[Point] = ... # read-only From 1b7e33f7ef4105c7ae495085ec52e15f1fc52c5d Mon Sep 17 00:00:00 2001 From: Hugues Date: Fri, 20 May 2022 08:49:52 -0700 Subject: [PATCH 308/377] checkexpr: cache type of container literals when possible (#12707) When a container (list, set, tuple, or dict) literal expression is used as an argument to an overloaded function it will get repeatedly typechecked. This becomes particularly problematic when the expression is somewhat large, as seen in #9427 To avoid repeated work, add a new cache in ExprChecker, mapping the AST node to the resolved type of the expression. Right now the cache is only used in the fast path, although it could conceivably be leveraged for the slow path as well in a follow-up commit. To further reduce duplicate work, when the fast-path doesn't work, we use the cache to make a note of that, to avoid repeatedly attempting to take the fast path. Fixes #9427 --- mypy/checker.py | 1 + mypy/checkexpr.py | 49 ++++++++++++++++++++++++++++++++++------------- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 109a3b1f15d27..e5abcfcf45416 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -293,6 +293,7 @@ def reset(self) -> None: self._type_maps[1:] = [] self._type_maps[0].clear() self.temp_type_map = None + self.expr_checker.reset() assert self.inferred_attribute_types is None assert self.partial_types == [] diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 0149f19714770..4cc91f9cc123b 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -177,6 +177,9 @@ class ExpressionChecker(ExpressionVisitor[Type]): # Type context for type inference type_context: List[Optional[Type]] + # cache resolved types in some cases + resolved_type: Dict[Expression, ProperType] + strfrm_checker: StringFormatterChecker plugin: Plugin @@ -197,6 +200,11 @@ def __init__(self, self.type_overrides: Dict[Expression, Type] = {} self.strfrm_checker = StringFormatterChecker(self, self.chk, self.msg) + self.resolved_type = {} + + def reset(self) -> None: + self.resolved_type = {} + def visit_name_expr(self, e: NameExpr) -> Type: """Type check a name expression. @@ -3269,13 +3277,13 @@ def apply_type_arguments_to_callable( def visit_list_expr(self, e: ListExpr) -> Type: """Type check a list expression [...].""" - return self.check_lst_expr(e.items, 'builtins.list', '', e) + return self.check_lst_expr(e, 'builtins.list', '') def visit_set_expr(self, e: SetExpr) -> Type: - return self.check_lst_expr(e.items, 'builtins.set', '', e) + return self.check_lst_expr(e, 'builtins.set', '') def fast_container_type( - self, items: List[Expression], container_fullname: str + self, e: Union[ListExpr, SetExpr, TupleExpr], container_fullname: str ) -> Optional[Type]: """ Fast path to determine the type of a list or set literal, @@ -3290,21 +3298,28 @@ def fast_container_type( ctx = self.type_context[-1] if ctx: return None + rt = self.resolved_type.get(e, None) + if rt is not None: + return rt if isinstance(rt, Instance) else None values: List[Type] = [] - for item in items: + for item in e.items: if isinstance(item, StarExpr): # fallback to slow path + self.resolved_type[e] = NoneType() return None values.append(self.accept(item)) vt = join.join_type_list(values) if not allow_fast_container_literal(vt): + self.resolved_type[e] = NoneType() return None - return self.chk.named_generic_type(container_fullname, [vt]) + ct = self.chk.named_generic_type(container_fullname, [vt]) + self.resolved_type[e] = ct + return ct - def check_lst_expr(self, items: List[Expression], fullname: str, - tag: str, context: Context) -> Type: + def check_lst_expr(self, e: Union[ListExpr, SetExpr, TupleExpr], fullname: str, + tag: str) -> Type: # fast path - t = self.fast_container_type(items, fullname) + t = self.fast_container_type(e, fullname) if t: return t @@ -3323,10 +3338,10 @@ def check_lst_expr(self, items: List[Expression], fullname: str, variables=[tv]) out = self.check_call(constructor, [(i.expr if isinstance(i, StarExpr) else i) - for i in items], + for i in e.items], [(nodes.ARG_STAR if isinstance(i, StarExpr) else nodes.ARG_POS) - for i in items], - context)[0] + for i in e.items], + e)[0] return remove_instance_last_known_values(out) def visit_tuple_expr(self, e: TupleExpr) -> Type: @@ -3376,7 +3391,7 @@ def visit_tuple_expr(self, e: TupleExpr) -> Type: else: # A star expression that's not a Tuple. # Treat the whole thing as a variable-length tuple. - return self.check_lst_expr(e.items, 'builtins.tuple', '', e) + return self.check_lst_expr(e, 'builtins.tuple', '') else: if not type_context_items or j >= len(type_context_items): tt = self.accept(item) @@ -3402,6 +3417,9 @@ def fast_dict_type(self, e: DictExpr) -> Optional[Type]: ctx = self.type_context[-1] if ctx: return None + rt = self.resolved_type.get(e, None) + if rt is not None: + return rt if isinstance(rt, Instance) else None keys: List[Type] = [] values: List[Type] = [] stargs: Optional[Tuple[Type, Type]] = None @@ -3415,6 +3433,7 @@ def fast_dict_type(self, e: DictExpr) -> Optional[Type]: ): stargs = (st.args[0], st.args[1]) else: + self.resolved_type[e] = NoneType() return None else: keys.append(self.accept(key)) @@ -3422,10 +3441,14 @@ def fast_dict_type(self, e: DictExpr) -> Optional[Type]: kt = join.join_type_list(keys) vt = join.join_type_list(values) if not (allow_fast_container_literal(kt) and allow_fast_container_literal(vt)): + self.resolved_type[e] = NoneType() return None if stargs and (stargs[0] != kt or stargs[1] != vt): + self.resolved_type[e] = NoneType() return None - return self.chk.named_generic_type('builtins.dict', [kt, vt]) + dt = self.chk.named_generic_type('builtins.dict', [kt, vt]) + self.resolved_type[e] = dt + return dt def visit_dict_expr(self, e: DictExpr) -> Type: """Type check a dict expression. From 37fb21afe937be9da98446557244f3de5424ebf8 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 20 May 2022 16:50:51 +0100 Subject: [PATCH 309/377] Typeshed cherry-pick: Ignore mypy errors in Python 2 builtins and typing (#7894) (#12826) From python/typeshed#7894. --- mypy/typeshed/stdlib/@python2/__builtin__.pyi | 4 ++-- mypy/typeshed/stdlib/@python2/builtins.pyi | 4 ++-- mypy/typeshed/stdlib/@python2/typing.pyi | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mypy/typeshed/stdlib/@python2/__builtin__.pyi b/mypy/typeshed/stdlib/@python2/__builtin__.pyi index d936e08b82660..4ede9dc9d8bd1 100644 --- a/mypy/typeshed/stdlib/@python2/__builtin__.pyi +++ b/mypy/typeshed/stdlib/@python2/__builtin__.pyi @@ -711,7 +711,7 @@ class set(MutableSet[_T], Generic[_T]): def __and__(self, s: AbstractSet[object]) -> set[_T]: ... def __iand__(self: Self, s: AbstractSet[object]) -> Self: ... def __or__(self, s: AbstractSet[_S]) -> set[_T | _S]: ... - def __ior__(self: Self, s: AbstractSet[_T]) -> Self: ... + def __ior__(self: Self, s: AbstractSet[_T]) -> Self: ... # type: ignore[override,misc] @overload def __sub__(self: set[str], s: AbstractSet[Text | None]) -> set[_T]: ... @overload @@ -721,7 +721,7 @@ class set(MutableSet[_T], Generic[_T]): @overload def __isub__(self, s: AbstractSet[_T | None]) -> set[_T]: ... def __xor__(self, s: AbstractSet[_S]) -> set[_T | _S]: ... - def __ixor__(self: Self, s: AbstractSet[_T]) -> Self: ... + def __ixor__(self: Self, s: AbstractSet[_T]) -> Self: ... # type: ignore[override,misc] def __le__(self, s: AbstractSet[object]) -> bool: ... def __lt__(self, s: AbstractSet[object]) -> bool: ... def __ge__(self, s: AbstractSet[object]) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/builtins.pyi b/mypy/typeshed/stdlib/@python2/builtins.pyi index d936e08b82660..4ede9dc9d8bd1 100644 --- a/mypy/typeshed/stdlib/@python2/builtins.pyi +++ b/mypy/typeshed/stdlib/@python2/builtins.pyi @@ -711,7 +711,7 @@ class set(MutableSet[_T], Generic[_T]): def __and__(self, s: AbstractSet[object]) -> set[_T]: ... def __iand__(self: Self, s: AbstractSet[object]) -> Self: ... def __or__(self, s: AbstractSet[_S]) -> set[_T | _S]: ... - def __ior__(self: Self, s: AbstractSet[_T]) -> Self: ... + def __ior__(self: Self, s: AbstractSet[_T]) -> Self: ... # type: ignore[override,misc] @overload def __sub__(self: set[str], s: AbstractSet[Text | None]) -> set[_T]: ... @overload @@ -721,7 +721,7 @@ class set(MutableSet[_T], Generic[_T]): @overload def __isub__(self, s: AbstractSet[_T | None]) -> set[_T]: ... def __xor__(self, s: AbstractSet[_S]) -> set[_T | _S]: ... - def __ixor__(self: Self, s: AbstractSet[_T]) -> Self: ... + def __ixor__(self: Self, s: AbstractSet[_T]) -> Self: ... # type: ignore[override,misc] def __le__(self, s: AbstractSet[object]) -> bool: ... def __lt__(self, s: AbstractSet[object]) -> bool: ... def __ge__(self, s: AbstractSet[object]) -> bool: ... diff --git a/mypy/typeshed/stdlib/@python2/typing.pyi b/mypy/typeshed/stdlib/@python2/typing.pyi index affa82c825a21..d1c9ae574e98f 100644 --- a/mypy/typeshed/stdlib/@python2/typing.pyi +++ b/mypy/typeshed/stdlib/@python2/typing.pyi @@ -239,9 +239,9 @@ class MutableSet(AbstractSet[_T], Generic[_T]): def clear(self) -> None: ... def pop(self) -> _T: ... def remove(self, element: _T) -> None: ... - def __ior__(self: Self, s: AbstractSet[_T]) -> Self: ... + def __ior__(self: Self, s: AbstractSet[_T]) -> Self: ... # type: ignore[override,misc] def __iand__(self: Self, s: AbstractSet[Any]) -> Self: ... - def __ixor__(self: Self, s: AbstractSet[_T]) -> Self: ... + def __ixor__(self: Self, s: AbstractSet[_T]) -> Self: ... # type: ignore[override,misc] def __isub__(self: Self, s: AbstractSet[Any]) -> Self: ... class MappingView(object): From a6166b2f7e8e4cf9d176107277da223e45c3a6a1 Mon Sep 17 00:00:00 2001 From: Hugues Date: Fri, 20 May 2022 08:56:30 -0700 Subject: [PATCH 310/377] FindModuleCache: optionally leverage BuildSourceSet (#12616) Given a large codebase with folder hierarchy of the form ``` foo/ company/ __init__.py foo/ bar/ company/ __init__.py bar/ baz/ company/ __init__.py baz/ ... ``` with >100 toplevel folders, the time spent in load_graph is dominated by find_module because this operation is itself O(n) where n is the number of input files, which ends up being O(n**2) because it is called for every import statement in the codebase and the way find_module work, it will always scan through each and every one of those toplevel directories for each and every import statement of company.* Introduce a fast path that leverages the fact that for imports within the code being typechecked, we already have a mapping of module import path to file path in BuildSourceSet Gated behind a command line flag (--fast-module-lookup) to assuage concerns about subtle issues in module lookup being introduced by this fast path. --- docs/source/command_line.rst | 23 +++++ docs/source/running_mypy.rst | 1 + mypy/build.py | 34 +------ mypy/main.py | 4 + mypy/modulefinder.py | 114 ++++++++++++++++++++- mypy/options.py | 2 + mypy/test/testcheck.py | 1 + test-data/unit/check-modules-fast.test | 136 +++++++++++++++++++++++++ 8 files changed, 283 insertions(+), 32 deletions(-) create mode 100644 test-data/unit/check-modules-fast.test diff --git a/docs/source/command_line.rst b/docs/source/command_line.rst index 1a35d81a7ee9e..908fa799da461 100644 --- a/docs/source/command_line.rst +++ b/docs/source/command_line.rst @@ -212,6 +212,29 @@ imports. By default, mypy will suppress any error messages generated within :pep:`561` compliant packages. Adding this flag will disable this behavior. +.. option:: --fast-module-lookup + + The default logic used to scan through search paths to resolve imports has a + quadratic worse-case behavior in some cases, which is for instance triggered + by a large number of folders sharing a top-level namespace as in: + + foo/ + company/ + foo/ + a.py + bar/ + company/ + bar/ + b.py + baz/ + company/ + baz/ + c.py + ... + + If you are in this situation, you can enable an experimental fast path by + setting the :option:`--fast-module-lookup` option. + .. _platform-configuration: diff --git a/docs/source/running_mypy.rst b/docs/source/running_mypy.rst index 46ad2c65c386a..caf05dcdf258a 100644 --- a/docs/source/running_mypy.rst +++ b/docs/source/running_mypy.rst @@ -516,6 +516,7 @@ same directory on the search path, only the stub file is used. (However, if the files are in different directories, the one found in the earlier directory is used.) + Other advice and best practices ******************************* diff --git a/mypy/build.py b/mypy/build.py index c0b9aff5ab32e..1196356d5bb8b 100644 --- a/mypy/build.py +++ b/mypy/build.py @@ -43,8 +43,8 @@ from mypy.report import Reports # Avoid unconditional slow import from mypy.fixup import fixup_module from mypy.modulefinder import ( - BuildSource, compute_search_paths, FindModuleCache, SearchPaths, ModuleSearchResult, - ModuleNotFoundReason + BuildSource, BuildSourceSet, compute_search_paths, FindModuleCache, SearchPaths, + ModuleSearchResult, ModuleNotFoundReason ) from mypy.nodes import Expression from mypy.options import Options @@ -107,33 +107,6 @@ def __init__(self, manager: 'BuildManager', graph: Graph) -> None: self.errors: List[str] = [] # Filled in by build if desired -class BuildSourceSet: - """Efficiently test a file's membership in the set of build sources.""" - - def __init__(self, sources: List[BuildSource]) -> None: - self.source_text_present = False - self.source_modules: Set[str] = set() - self.source_paths: Set[str] = set() - - for source in sources: - if source.text is not None: - self.source_text_present = True - elif source.path: - self.source_paths.add(source.path) - else: - self.source_modules.add(source.module) - - def is_source(self, file: MypyFile) -> bool: - if file.path and file.path in self.source_paths: - return True - elif file._fullname in self.source_modules: - return True - elif self.source_text_present: - return True - else: - return False - - def build(sources: List[BuildSource], options: Options, alt_lib_path: Optional[str] = None, @@ -630,7 +603,8 @@ def __init__(self, data_dir: str, or options.use_fine_grained_cache) and not has_reporters) self.fscache = fscache - self.find_module_cache = FindModuleCache(self.search_paths, self.fscache, self.options) + self.find_module_cache = FindModuleCache(self.search_paths, self.fscache, self.options, + source_set=self.source_set) self.metastore = create_metastore(options) # a mapping from source files to their corresponding shadow files diff --git a/mypy/main.py b/mypy/main.py index c735bb389a35a..57727821274ed 100644 --- a/mypy/main.py +++ b/mypy/main.py @@ -881,6 +881,10 @@ def add_invertible_flag(flag: str, '--explicit-package-bases', default=False, help="Use current directory and MYPYPATH to determine module names of files passed", group=code_group) + add_invertible_flag( + '--fast-module-lookup', default=False, + help=argparse.SUPPRESS, + group=code_group) code_group.add_argument( "--exclude", action="append", diff --git a/mypy/modulefinder.py b/mypy/modulefinder.py index 4ab95dd6564f5..43cc4fc0a6d33 100644 --- a/mypy/modulefinder.py +++ b/mypy/modulefinder.py @@ -23,6 +23,7 @@ from typing_extensions import Final, TypeAlias as _TypeAlias from mypy.fscache import FileSystemCache +from mypy.nodes import MypyFile from mypy.options import Options from mypy.stubinfo import is_legacy_bundled_package from mypy import pyinfo @@ -126,6 +127,33 @@ def __repr__(self) -> str: self.base_dir) +class BuildSourceSet: + """Helper to efficiently test a file's membership in a set of build sources.""" + + def __init__(self, sources: List[BuildSource]) -> None: + self.source_text_present = False + self.source_modules = {} # type: Dict[str, str] + self.source_paths = set() # type: Set[str] + + for source in sources: + if source.text is not None: + self.source_text_present = True + if source.path: + self.source_paths.add(source.path) + if source.module: + self.source_modules[source.module] = source.path or '' + + def is_source(self, file: MypyFile) -> bool: + if file.path and file.path in self.source_paths: + return True + elif file._fullname in self.source_modules: + return True + elif self.source_text_present: + return True + else: + return False + + class FindModuleCache: """Module finder with integrated cache. @@ -141,8 +169,10 @@ def __init__(self, search_paths: SearchPaths, fscache: Optional[FileSystemCache], options: Optional[Options], - stdlib_py_versions: Optional[StdlibVersions] = None) -> None: + stdlib_py_versions: Optional[StdlibVersions] = None, + source_set: Optional[BuildSourceSet] = None) -> None: self.search_paths = search_paths + self.source_set = source_set self.fscache = fscache or FileSystemCache() # Cache for get_toplevel_possibilities: # search_paths -> (toplevel_id -> list(package_dirs)) @@ -164,6 +194,53 @@ def clear(self) -> None: self.initial_components.clear() self.ns_ancestors.clear() + def find_module_via_source_set(self, id: str) -> Optional[ModuleSearchResult]: + """Fast path to find modules by looking through the input sources + + This is only used when --fast-module-lookup is passed on the command line.""" + if not self.source_set: + return None + + p = self.source_set.source_modules.get(id, None) + if p and self.fscache.isfile(p): + # We need to make sure we still have __init__.py all the way up + # otherwise we might have false positives compared to slow path + # in case of deletion of init files, which is covered by some tests. + # TODO: are there some combination of flags in which this check should be skipped? + d = os.path.dirname(p) + for _ in range(id.count('.')): + if not any(self.fscache.isfile(os.path.join(d, '__init__' + x)) + for x in PYTHON_EXTENSIONS): + return None + d = os.path.dirname(d) + return p + + idx = id.rfind('.') + if idx != -1: + # When we're looking for foo.bar.baz and can't find a matching module + # in the source set, look up for a foo.bar module. + parent = self.find_module_via_source_set(id[:idx]) + if parent is None or not isinstance(parent, str): + return None + + basename, ext = os.path.splitext(parent) + if (not any(parent.endswith('__init__' + x) for x in PYTHON_EXTENSIONS) + and (ext in PYTHON_EXTENSIONS and not self.fscache.isdir(basename))): + # If we do find such a *module* (and crucially, we don't want a package, + # hence the filtering out of __init__ files, and checking for the presence + # of a folder with a matching name), then we can be pretty confident that + # 'baz' will either be a top-level variable in foo.bar, or will not exist. + # + # Either way, spelunking in other search paths for another 'foo.bar.baz' + # module should be avoided because: + # 1. in the unlikely event that one were found, it's highly likely that + # it would be unrelated to the source being typechecked and therefore + # more likely to lead to erroneous results + # 2. as described in _find_module, in some cases the search itself could + # potentially waste significant amounts of time + return ModuleNotFoundReason.NOT_FOUND + return None + def find_lib_path_dirs(self, id: str, lib_path: Tuple[str, ...]) -> PackageDirs: """Find which elements of a lib_path have the directory a module needs to exist. @@ -229,7 +306,7 @@ def find_module(self, id: str, *, fast_path: bool = False) -> ModuleSearchResult elif top_level in self.stdlib_py_versions: use_typeshed = self._typeshed_has_version(top_level) self.results[id] = self._find_module(id, use_typeshed) - if (not fast_path + if (not (fast_path or (self.options is not None and self.options.fast_module_lookup)) and self.results[id] is ModuleNotFoundReason.NOT_FOUND and self._can_find_module_in_parent_dir(id)): self.results[id] = ModuleNotFoundReason.WRONG_WORKING_DIRECTORY @@ -295,6 +372,39 @@ def _can_find_module_in_parent_dir(self, id: str) -> bool: def _find_module(self, id: str, use_typeshed: bool) -> ModuleSearchResult: fscache = self.fscache + # Fast path for any modules in the current source set. + # This is particularly important when there are a large number of search + # paths which share the first (few) component(s) due to the use of namespace + # packages, for instance: + # foo/ + # company/ + # __init__.py + # foo/ + # bar/ + # company/ + # __init__.py + # bar/ + # baz/ + # company/ + # __init__.py + # baz/ + # + # mypy gets [foo/company/foo, bar/company/bar, baz/company/baz, ...] as input + # and computes [foo, bar, baz, ...] as the module search path. + # + # This would result in O(n) search for every import of company.*, leading to + # O(n**2) behavior in load_graph as such imports are unsurprisingly present + # at least once, and usually many more times than that, in each and every file + # being parsed. + # + # Thankfully, such cases are efficiently handled by looking up the module path + # via BuildSourceSet. + p = (self.find_module_via_source_set(id) + if (self.options is not None and self.options.fast_module_lookup) + else None) + if p: + return p + # If we're looking for a module like 'foo.bar.baz', it's likely that most of the # many elements of lib_path don't even have a subdirectory 'foo/bar'. Discover # that only once and cache it for when we look for modules like 'foo.bar.blah' diff --git a/mypy/options.py b/mypy/options.py index b8bc53feb89cb..254af61a06456 100644 --- a/mypy/options.py +++ b/mypy/options.py @@ -293,6 +293,8 @@ def __init__(self) -> None: self.cache_map: Dict[str, Tuple[str, str]] = {} # Don't properly free objects on exit, just kill the current process. self.fast_exit = True + # fast path for finding modules from source set + self.fast_module_lookup = False # Used to transform source code before parsing if not None # TODO: Make the type precise (AnyStr -> AnyStr) self.transform_source: Optional[Callable[[Any], Any]] = None diff --git a/mypy/test/testcheck.py b/mypy/test/testcheck.py index cc0c5875f53b8..279ecdb2d22df 100644 --- a/mypy/test/testcheck.py +++ b/mypy/test/testcheck.py @@ -46,6 +46,7 @@ 'check-multiple-inheritance.test', 'check-super.test', 'check-modules.test', + 'check-modules-fast.test', 'check-typevar-values.test', 'check-unsupported.test', 'check-unreachable-code.test', diff --git a/test-data/unit/check-modules-fast.test b/test-data/unit/check-modules-fast.test new file mode 100644 index 0000000000000..875125c6532b3 --- /dev/null +++ b/test-data/unit/check-modules-fast.test @@ -0,0 +1,136 @@ +-- Type checker test cases dealing with module lookup edge cases +-- to ensure that --fast-module-lookup matches regular lookup behavior + +[case testModuleLookup] +# flags: --fast-module-lookup +import m +reveal_type(m.a) # N: Revealed type is "m.A" + +[file m.py] +class A: pass +a = A() + +[case testModuleLookupStub] +# flags: --fast-module-lookup +import m +reveal_type(m.a) # N: Revealed type is "m.A" + +[file m.pyi] +class A: pass +a = A() + +[case testModuleLookupFromImport] +# flags: --fast-module-lookup +from m import a +reveal_type(a) # N: Revealed type is "m.A" + +[file m.py] +class A: pass +a = A() + +[case testModuleLookupStubFromImport] +# flags: --fast-module-lookup +from m import a +reveal_type(a) # N: Revealed type is "m.A" + +[file m.pyi] +class A: pass +a = A() + + +[case testModuleLookupWeird] +# flags: --fast-module-lookup +from m import a +reveal_type(a) # N: Revealed type is "builtins.object" +reveal_type(a.b) # N: Revealed type is "m.a.B" + +[file m.py] +class A: pass +a = A() + +[file m/__init__.py] +[file m/a.py] +class B: pass +b = B() + + +[case testModuleLookupWeird2] +# flags: --fast-module-lookup +from m.a import b +reveal_type(b) # N: Revealed type is "m.a.B" + +[file m.py] +class A: pass +a = A() + +[file m/__init__.py] +[file m/a.py] +class B: pass +b = B() + + +[case testModuleLookupWeird3] +# flags: --fast-module-lookup +from m.a import b +reveal_type(b) # N: Revealed type is "m.a.B" + +[file m.py] +class A: pass +a = A() +[file m/__init__.py] +class B: pass +a = B() +[file m/a.py] +class B: pass +b = B() + + +[case testModuleLookupWeird4] +# flags: --fast-module-lookup +import m.a +m.a.b # E: "str" has no attribute "b" + +[file m.py] +class A: pass +a = A() +[file m/__init__.py] +class B: pass +a = 'foo' +b = B() +[file m/a.py] +class C: pass +b = C() + + +[case testModuleLookupWeird5] +# flags: --fast-module-lookup +import m.a as ma +reveal_type(ma.b) # N: Revealed type is "m.a.C" + +[file m.py] +class A: pass +a = A() +[file m/__init__.py] +class B: pass +a = 'foo' +b = B() +[file m/a.py] +class C: pass +b = C() + + +[case testModuleLookupWeird6] +# flags: --fast-module-lookup +from m.a import b +reveal_type(b) # N: Revealed type is "m.a.C" + +[file m.py] +class A: pass +a = A() +[file m/__init__.py] +class B: pass +a = 'foo' +b = B() +[file m/a.py] +class C: pass +b = C() From 927a9ba05d7e1ca495c62e555b937e74a01c4e57 Mon Sep 17 00:00:00 2001 From: Ramazan Elsunakev <35545693+relsunkaev@users.noreply.github.com> Date: Fri, 20 May 2022 19:35:31 -0700 Subject: [PATCH 311/377] fix: "variable arguments" error wording (#12827) Fixes #12508 --- mypy/messages.py | 2 +- test-data/unit/check-varargs.test | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/mypy/messages.py b/mypy/messages.py index 70d79384c1a9d..b5f6ca339d6a8 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -944,7 +944,7 @@ def could_not_infer_type_arguments(self, callee_type: CallableType, n: int, self.fail('Cannot infer function type argument', context) def invalid_var_arg(self, typ: Type, context: Context) -> None: - self.fail('List or tuple expected as variable arguments', context) + self.fail('List or tuple expected as variadic arguments', context) def invalid_keyword_var_arg(self, typ: Type, is_mapping: bool, context: Context) -> None: typ = get_proper_type(typ) diff --git a/test-data/unit/check-varargs.test b/test-data/unit/check-varargs.test index d93618b85ba98..4dc10c9f7489c 100644 --- a/test-data/unit/check-varargs.test +++ b/test-data/unit/check-varargs.test @@ -275,7 +275,7 @@ class CC(C): pass a = None # type: A f(*None) -f(*a) # E: List or tuple expected as variable arguments +f(*a) # E: List or tuple expected as variadic arguments f(*(a,)) def f(a: 'A') -> None: @@ -544,9 +544,9 @@ if int(): if int(): b, b = f(b, b, *aa) # E: Argument 3 to "f" has incompatible type "*List[A]"; expected "B" if int(): - a, b = f(a, *a) # E: List or tuple expected as variable arguments + a, b = f(a, *a) # E: List or tuple expected as variadic arguments if int(): - a, b = f(*a) # E: List or tuple expected as variable arguments + a, b = f(*a) # E: List or tuple expected as variadic arguments if int(): a, a = f(*aa) @@ -758,5 +758,5 @@ bar(*good1) bar(*good2) bar(*good3) bar(*bad1) # E: Argument 1 to "bar" has incompatible type "*I[str]"; expected "float" -bar(*bad2) # E: List or tuple expected as variable arguments +bar(*bad2) # E: List or tuple expected as variadic arguments [builtins fixtures/dict.pyi] From f19a711eae747e2e5525bf0b0baaa3d3ae972fbd Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Sat, 21 May 2022 16:00:40 +0200 Subject: [PATCH 312/377] Bring back type annotation support of dunder methods in stub generator (#12828) Fixes #12717 --- mypy/stubgenc.py | 2 +- .../pybind11_mypy_demo/stubgen/pybind11_mypy_demo/basics.pyi | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/mypy/stubgenc.py b/mypy/stubgenc.py index 682ed418ffc77..9f90c7aafe69c 100755 --- a/mypy/stubgenc.py +++ b/mypy/stubgenc.py @@ -288,7 +288,7 @@ def infer_prop_type(docstr: Optional[str]) -> Optional[str]: return None # Ignore special properties/attributes. - if name.startswith('__') and name.endswith('__'): + if is_skipped_attribute(name): return inferred = infer_prop_type(getattr(obj, '__doc__', None)) diff --git a/test-data/pybind11_mypy_demo/stubgen/pybind11_mypy_demo/basics.pyi b/test-data/pybind11_mypy_demo/stubgen/pybind11_mypy_demo/basics.pyi index 226080ac9d57a..ab5a4f4e78d26 100644 --- a/test-data/pybind11_mypy_demo/stubgen/pybind11_mypy_demo/basics.pyi +++ b/test-data/pybind11_mypy_demo/stubgen/pybind11_mypy_demo/basics.pyi @@ -5,6 +5,7 @@ PI: float class Point: class AngleUnit: + __members__: ClassVar[dict] = ... # read-only __entries: ClassVar[dict] = ... degree: ClassVar[Point.AngleUnit] = ... radian: ClassVar[Point.AngleUnit] = ... @@ -22,6 +23,7 @@ class Point: def value(self) -> int: ... class LengthUnit: + __members__: ClassVar[dict] = ... # read-only __entries: ClassVar[dict] = ... inch: ClassVar[Point.LengthUnit] = ... mm: ClassVar[Point.LengthUnit] = ... From 9d63fa52e335bca8322948bb2aedf6253e1df4bb Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sat, 21 May 2022 15:15:17 -0700 Subject: [PATCH 313/377] Run Python 3.11 tests in CI (#12833) Co-authored-by: hauntsaninja <> --- .github/workflows/test.yml | 37 +++++++++++++++++-------------------- test-requirements.txt | 2 +- 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f62dba8cb9c7a..71223846bc38f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -119,23 +119,20 @@ jobs: - name: Test run: tox -e ${{ matrix.toxenv }} --skip-pkg-install -- ${{ matrix.tox_extra_args }} -# TODO: re-enable when `typed-ast` will be fixed for `python==3.11` -# python-nightly: -# runs-on: ubuntu-latest -# name: Test suite with Python nightly -# steps: -# - uses: actions/checkout@v2 -# - uses: actions/setup-python@v2 -# with: -# python-version: '3.11-dev' -# - name: Install tox -# run: | -# pip install -U pip==21.2.3 setuptools -# pip install --upgrade 'setuptools!=50' virtualenv==20.4.7 tox==3.20.1 -# - name: Setup tox environment -# run: tox -e py --notest -# - name: Test -# run: tox -e py --skip-pkg-install -- "-n 2" -# continue-on-error: true -# - name: Mark as a success -# run: exit 0 + python-nightly: + runs-on: ubuntu-latest + name: Test suite with Python nightly + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: '3.11-dev' + - name: Install tox + run: pip install --upgrade 'setuptools!=50' 'virtualenv>=20.6.0' tox==3.24.5 + - name: Setup tox environment + run: tox -e py --notest + - name: Test + run: tox -e py --skip-pkg-install -- "-n 2" + continue-on-error: true + - name: Mark as a success + run: exit 0 diff --git a/test-requirements.txt b/test-requirements.txt index a3d11872fd5ca..3d7835e38f144 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -12,7 +12,7 @@ pytest-xdist>=1.34.0 pytest-forked>=1.3.0,<2.0.0 pytest-cov>=2.10.0,<3.0.0 py>=1.5.2 -typed_ast>=1.4.0,<2; python_version>='3.8' +typed_ast>=1.5.4,<2; python_version>='3.8' virtualenv>=20.6.0 setuptools!=50 importlib-metadata>=4.6.1,<5.0.0 From 19e9f2136fd46c662f1066a4894edf48173942f4 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sun, 22 May 2022 06:43:07 -0700 Subject: [PATCH 314/377] stubtest: allow ellipsis as default argument (#12838) Resolves #12819 --- mypy/stubtest.py | 2 ++ mypy/test/teststubtest.py | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/mypy/stubtest.py b/mypy/stubtest.py index b7aa6367ef2d7..567f6f8c788a9 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -419,6 +419,8 @@ def _verify_arg_default_value( and stub_type is not None # Avoid false positives for marker objects and type(runtime_arg.default) != object + # And ellipsis + and runtime_arg.default is not ... and not is_subtype_helper(runtime_type, stub_type) ): yield ( diff --git a/mypy/test/teststubtest.py b/mypy/test/teststubtest.py index de48c9ce2723d..50b3f90c8fad9 100644 --- a/mypy/test/teststubtest.py +++ b/mypy/test/teststubtest.py @@ -43,6 +43,7 @@ def __getitem__(self, typeargs: Any) -> object: ... Callable: _SpecialForm = ... Generic: _SpecialForm = ... +Protocol: _SpecialForm = ... class TypeVar: def __init__(self, name, covariant: bool = ..., contravariant: bool = ...) -> None: ... @@ -1020,6 +1021,27 @@ class _Options(TypedDict): error="opt3", ) + @collect_cases + def test_protocol(self) -> Iterator[Case]: + if sys.version_info < (3, 7): + return + yield Case( + stub=""" + from typing_extensions import Protocol + + class X(Protocol): + def foo(self, x: int, y: bytes = ...) -> str: ... + """, + runtime=""" + from typing_extensions import Protocol + + class X(Protocol): + def foo(self, x: int, y: bytes = ...) -> str: ... + """, + # TODO: this should not be an error, #12820 + error="X.__init__" + ) + def remove_color_code(s: str) -> str: return re.sub("\\x1b.*?m", "", s) # this works! From 205d256584f16013602c71a4696bbaa356942fb8 Mon Sep 17 00:00:00 2001 From: pranavrajpal <78008260+pranavrajpal@users.noreply.github.com> Date: Sun, 22 May 2022 15:17:45 -0700 Subject: [PATCH 315/377] [mypyc] Remove unnecessary max call for python version (#12848) We don't support running on Python 3.5 or lower anymore, so the max call is unnecessary because the current version will always be greater than or equal to (3, 6). --- mypyc/test/test_run.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/mypyc/test/test_run.py b/mypyc/test/test_run.py index 852de8edcf690..1eafd2d4c8033 100644 --- a/mypyc/test/test_run.py +++ b/mypyc/test/test_run.py @@ -174,11 +174,7 @@ def run_case_step(self, testcase: DataDrivenTestCase, incremental_step: int) -> options.use_builtins_fixtures = True options.show_traceback = True options.strict_optional = True - # N.B: We try to (and ought to!) run with the current - # version of python, since we are going to link and run - # against the current version of python. - # But a lot of the tests use type annotations so we can't say it is 3.5. - options.python_version = max(sys.version_info[:2], (3, 6)) + options.python_version = sys.version_info[:2] options.export_types = True options.preserve_asts = True options.incremental = self.separate From 16d27a2628ef8837f8d180c1e9d248d4c3f2fe4c Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sun, 22 May 2022 17:26:34 -0700 Subject: [PATCH 316/377] stubtest: add --version (#12852) Suggested in #12825 Co-authored-by: hauntsaninja <> --- mypy/stubtest.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mypy/stubtest.py b/mypy/stubtest.py index 567f6f8c788a9..c1bdcb3437a45 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -23,6 +23,7 @@ import mypy.modulefinder import mypy.state import mypy.types +import mypy.version from mypy import nodes from mypy.config_parser import parse_config_file from mypy.options import Options @@ -1471,6 +1472,9 @@ def parse_options(args: List[str]) -> argparse.Namespace: parser.add_argument( "--check-typeshed", action="store_true", help="Check all stdlib modules in typeshed" ) + parser.add_argument( + "--version", action="version", version="%(prog)s " + mypy.version.__version__ + ) return parser.parse_args(args) From c986e54124b967587fbc674029ebe503c75d3a60 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sun, 22 May 2022 17:40:11 -0700 Subject: [PATCH 317/377] Use async def in pythoneval tests (#12834) Co-authored-by: hauntsaninja <> --- test-data/unit/pythoneval-asyncio.test | 221 +++++++++++-------------- 1 file changed, 97 insertions(+), 124 deletions(-) diff --git a/test-data/unit/pythoneval-asyncio.test b/test-data/unit/pythoneval-asyncio.test index b3400fe6010e7..11a61756a8246 100644 --- a/test-data/unit/pythoneval-asyncio.test +++ b/test-data/unit/pythoneval-asyncio.test @@ -4,7 +4,7 @@ -- These are mostly regression tests -- no attempt is made to make these -- complete. -- --- This test file check Asyncio and yield from interaction +-- This test file checks Asyncio and await interaction [case testImportAsyncio] import asyncio @@ -17,12 +17,11 @@ from typing import Any, Generator import asyncio from asyncio import Future -@asyncio.coroutine -def greet_every_two_seconds() -> 'Generator[Any, None, None]': +async def greet_every_two_seconds() -> None: n = 0 while n < 5: print('Prev', n) - yield from asyncio.sleep(0.1) + await asyncio.sleep(0.01) print('After', n) n += 1 @@ -44,19 +43,17 @@ Prev 4 After 4 [case testCoroutineCallingOtherCoroutine] -from typing import Generator, Any +from typing import Any import asyncio from asyncio import Future -@asyncio.coroutine -def compute(x: int, y: int) -> 'Generator[Any, None, int]': +async def compute(x: int, y: int) -> int: print("Compute %s + %s ..." % (x, y)) - yield from asyncio.sleep(0.1) + await asyncio.sleep(0.01) return x + y # Here the int is wrapped in Future[int] -@asyncio.coroutine -def print_sum(x: int, y: int) -> 'Generator[Any, None, None]': - result = yield from compute(x, y) # The type of result will be int (is extracted from Future[int] +async def print_sum(x: int, y: int) -> None: + result = await compute(x, y) # The type of result will be int (is extracted from Future[int] print("%s + %s = %s" % (x, y, result)) loop = asyncio.get_event_loop() @@ -67,13 +64,12 @@ Compute 1 + 2 ... 1 + 2 = 3 [case testCoroutineChangingFuture] -from typing import Generator, Any +from typing import Any import asyncio from asyncio import Future -@asyncio.coroutine -def slow_operation(future: 'Future[str]') -> 'Generator[Any, None, None]': - yield from asyncio.sleep(0.1) +async def slow_operation(future: 'Future[str]') -> None: + await asyncio.sleep(0.01) future.set_result('Future is done!') loop = asyncio.get_event_loop() @@ -87,13 +83,12 @@ Future is done! [case testFunctionAssignedAsCallback] import typing -from typing import Generator, Any +from typing import Any import asyncio from asyncio import Future, AbstractEventLoop -@asyncio.coroutine -def slow_operation(future: 'Future[str]') -> 'Generator[Any, None, None]': - yield from asyncio.sleep(1) +async def slow_operation(future: 'Future[str]') -> None: + await asyncio.sleep(1) future.set_result('Callback works!') def got_result(future: 'Future[str]') -> None: @@ -113,15 +108,14 @@ Callback works! [case testMultipleTasks] import typing -from typing import Generator, Any +from typing import Any import asyncio from asyncio import Task, Future -@asyncio.coroutine -def factorial(name, number) -> 'Generator[Any, None, None]': +async def factorial(name, number) -> None: f = 1 for i in range(2, number+1): print("Task %s: Compute factorial(%s)..." % (name, i)) - yield from asyncio.sleep(0.1) + await asyncio.sleep(0.01) f *= i print("Task %s: factorial(%s) = %s" % (name, number, f)) @@ -146,30 +140,26 @@ Task C: factorial(4) = 24 [case testConcatenatedCoroutines] import typing -from typing import Generator, Any +from typing import Any import asyncio from asyncio import Future -@asyncio.coroutine -def h4() -> 'Generator[Any, None, int]': - x = yield from future +async def h4() -> int: + x = await future return x -@asyncio.coroutine -def h3() -> 'Generator[Any, None, int]': - x = yield from h4() +async def h3() -> int: + x = await h4() print("h3: %s" % x) return x -@asyncio.coroutine -def h2() -> 'Generator[Any, None, int]': - x = yield from h3() +async def h2() -> int: + x = await h3() print("h2: %s" % x) return x -@asyncio.coroutine -def h() -> 'Generator[Any, None, None]': - x = yield from h2() +async def h() -> None: + x = await h2() print("h: %s" % x) loop = asyncio.get_event_loop() @@ -186,30 +176,27 @@ Outside 42 [case testConcatenatedCoroutinesReturningFutures] import typing -from typing import Generator, Any +from typing import Any import asyncio from asyncio import Future -@asyncio.coroutine -def h4() -> 'Generator[Any, None, Future[int]]': - yield from asyncio.sleep(0.1) +async def h4() -> "Future[int]": + await asyncio.sleep(0.01) f = asyncio.Future() #type: Future[int] return f -@asyncio.coroutine -def h3() -> 'Generator[Any, None, Future[Future[int]]]': - x = yield from h4() +async def h3() -> "Future[Future[int]]": + x = await h4() x.set_result(42) f = asyncio.Future() #type: Future[Future[int]] f.set_result(x) return f -@asyncio.coroutine -def h() -> 'Generator[Any, None, None]': +async def h() -> None: print("Before") - x = yield from h3() - y = yield from x - z = yield from y + x = await h3() + y = await x + z = await y print(z) def normalize(future): # The str conversion seems inconsistent; not sure exactly why. Normalize @@ -230,7 +217,7 @@ Future> [case testCoroutineWithOwnClass] import typing -from typing import Generator, Any +from typing import Any import asyncio from asyncio import Future @@ -238,9 +225,8 @@ class A: def __init__(self, x: int) -> None: self.x = x -@asyncio.coroutine -def h() -> 'Generator[Any, None, None]': - x = yield from future +async def h() -> None: + x = await future print("h: %s" % x.x) loop = asyncio.get_event_loop() @@ -256,20 +242,19 @@ Outside 42 -- Errors -[case testErrorAssigningCoroutineThatDontReturn] -from typing import Generator, Any +[case testErrorAssigningCoroutineThatDontReturn-xfail] +# https://github.com/python/mypy/issues/12837 +from typing import Any import asyncio from asyncio import Future -@asyncio.coroutine -def greet() -> 'Generator[Any, None, None]': - yield from asyncio.sleep(0.2) +async def greet() -> None: + await asyncio.sleep(0.2) print('Hello World') -@asyncio.coroutine -def test() -> 'Generator[Any, None, None]': - yield from greet() - x = yield from greet() # Error +async def test() -> None: + await greet() + x = await greet() # Error loop = asyncio.get_event_loop() try: @@ -280,19 +265,17 @@ finally: _program.py:13: error: Function does not return a value [case testErrorReturnIsNotTheSameType] -from typing import Generator, Any +from typing import Any import asyncio from asyncio import Future -@asyncio.coroutine -def compute(x: int, y: int) -> 'Generator[Any, None, int]': +async def compute(x: int, y: int) -> int: print("Compute %s + %s ..." % (x, y)) - yield from asyncio.sleep(0.1) + await asyncio.sleep(0.01) return str(x + y) # Error -@asyncio.coroutine -def print_sum(x: int, y: int) -> 'Generator[Any, None, None]': - result = yield from compute(x, y) +async def print_sum(x: int, y: int) -> None: + result = await compute(x, y) print("%s + %s = %s" % (x, y, result)) loop = asyncio.get_event_loop() @@ -300,16 +283,15 @@ loop.run_until_complete(print_sum(1, 2)) loop.close() [out] -_program.py:9: error: Incompatible return value type (got "str", expected "int") +_program.py:8: error: Incompatible return value type (got "str", expected "int") [case testErrorSetFutureDifferentInternalType] -from typing import Generator, Any +from typing import Any import asyncio from asyncio import Future -@asyncio.coroutine -def slow_operation(future: 'Future[str]') -> 'Generator[Any, None, None]': - yield from asyncio.sleep(1) +async def slow_operation(future: 'Future[str]') -> None: + await asyncio.sleep(1) future.set_result(42) # Error loop = asyncio.get_event_loop() @@ -319,17 +301,16 @@ loop.run_until_complete(future) print(future.result()) loop.close() [out] -_program.py:8: error: Argument 1 to "set_result" of "Future" has incompatible type "int"; expected "str" +_program.py:7: error: Argument 1 to "set_result" of "Future" has incompatible type "int"; expected "str" [case testErrorUsingDifferentFutureType] -from typing import Any, Generator +from typing import Any import asyncio from asyncio import Future -@asyncio.coroutine -def slow_operation(future: 'Future[int]') -> 'Generator[Any, None, None]': - yield from asyncio.sleep(1) +async def slow_operation(future: 'Future[int]') -> None: + await asyncio.sleep(1) future.set_result(42) loop = asyncio.get_event_loop() @@ -339,16 +320,15 @@ loop.run_until_complete(future) print(future.result()) loop.close() [out] -_program.py:12: error: Argument 1 to "slow_operation" has incompatible type "Future[str]"; expected "Future[int]" +_program.py:11: error: Argument 1 to "slow_operation" has incompatible type "Future[str]"; expected "Future[int]" [case testErrorUsingDifferentFutureTypeAndSetFutureDifferentInternalType] -from typing import Generator, Any +from typing import Any import asyncio from asyncio import Future -@asyncio.coroutine -def slow_operation(future: 'Future[int]') -> 'Generator[Any, None, None]': - yield from asyncio.sleep(1) +async def slow_operation(future: 'Future[int]') -> None: + await asyncio.sleep(1) future.set_result('42') #Try to set an str as result to a Future[int] loop = asyncio.get_event_loop() @@ -358,18 +338,17 @@ loop.run_until_complete(future) print(future.result()) loop.close() [out] -_program.py:8: error: Argument 1 to "set_result" of "Future" has incompatible type "str"; expected "int" -_program.py:12: error: Argument 1 to "slow_operation" has incompatible type "Future[str]"; expected "Future[int]" +_program.py:7: error: Argument 1 to "set_result" of "Future" has incompatible type "str"; expected "int" +_program.py:11: error: Argument 1 to "slow_operation" has incompatible type "Future[str]"; expected "Future[int]" [case testErrorSettingCallbackWithDifferentFutureType] import typing -from typing import Generator, Any +from typing import Any import asyncio from asyncio import Future, AbstractEventLoop -@asyncio.coroutine -def slow_operation(future: 'Future[str]') -> 'Generator[Any, None, None]': - yield from asyncio.sleep(1) +async def slow_operation(future: 'Future[str]') -> None: + await asyncio.sleep(1) future.set_result('Future is done!') def got_result(future: 'Future[int]') -> None: @@ -386,7 +365,7 @@ try: finally: loop.close() [out] -_program.py:18: error: Argument 1 to "add_done_callback" of "Future" has incompatible type "Callable[[Future[int]], None]"; expected "Callable[[Future[str]], Any]" +_program.py:17: error: Argument 1 to "add_done_callback" of "Future" has incompatible type "Callable[[Future[int]], None]"; expected "Callable[[Future[str]], Any]" [case testErrorOneMoreFutureInReturnType] import typing @@ -394,26 +373,23 @@ from typing import Any, Generator import asyncio from asyncio import Future -@asyncio.coroutine -def h4() -> 'Generator[Any, None, Future[int]]': - yield from asyncio.sleep(1) +async def h4() -> Future[int]: + await asyncio.sleep(1) f = asyncio.Future() #type: Future[int] return f -@asyncio.coroutine -def h3() -> 'Generator[Any, None, Future[Future[Future[int]]]]': - x = yield from h4() +async def h3() -> Future[Future[Future[int]]]: + x = await h4() x.set_result(42) f = asyncio.Future() #type: Future[Future[int]] f.set_result(x) return f -@asyncio.coroutine -def h() -> 'Generator[Any, None, None]': +async def h() -> None: print("Before") - x = yield from h3() - y = yield from x - z = yield from y + x = await h3() + y = await x + z = await y print(z) print(y) print(x) @@ -422,33 +398,30 @@ loop = asyncio.get_event_loop() loop.run_until_complete(h()) loop.close() [out] -_program.py:18: error: Incompatible return value type (got "Future[Future[int]]", expected "Future[Future[Future[int]]]") +_program.py:16: error: Incompatible return value type (got "Future[Future[int]]", expected "Future[Future[Future[int]]]") [case testErrorOneLessFutureInReturnType] import typing -from typing import Any, Generator +from typing import Any import asyncio from asyncio import Future -@asyncio.coroutine -def h4() -> 'Generator[Any, None, Future[int]]': - yield from asyncio.sleep(1) +async def h4() -> Future[int]: + await asyncio.sleep(1) f = asyncio.Future() #type: Future[int] return f -@asyncio.coroutine -def h3() -> 'Generator[Any, None, Future[int]]': - x = yield from h4() +async def h3() -> Future[int]: + x = await h4() x.set_result(42) f = asyncio.Future() #type: Future[Future[int]] f.set_result(x) return f -@asyncio.coroutine -def h() -> 'Generator[Any, None, None]': +async def h() -> None: print("Before") - x = yield from h3() - y = yield from x + x = await h3() + y = await x print(y) print(x) @@ -456,11 +429,11 @@ loop = asyncio.get_event_loop() loop.run_until_complete(h()) loop.close() [out] -_program.py:18: error: Incompatible return value type (got "Future[Future[int]]", expected "Future[int]") +_program.py:16: error: Incompatible return value type (got "Future[Future[int]]", expected "Future[int]") [case testErrorAssignmentDifferentType] import typing -from typing import Generator, Any +from typing import Any import asyncio from asyncio import Future @@ -472,9 +445,8 @@ class B: def __init__(self, x: int) -> None: self.x = x -@asyncio.coroutine -def h() -> 'Generator[Any, None, None]': - x = yield from future # type: B # Error +async def h() -> None: + x = await future # type: B # Error print("h: %s" % x.x) loop = asyncio.get_event_loop() @@ -483,7 +455,7 @@ future.set_result(A(42)) loop.run_until_complete(h()) loop.close() [out] -_program.py:16: error: Incompatible types in assignment (expression has type "A", variable has type "B") +_program.py:15: error: Incompatible types in assignment (expression has type "A", variable has type "B") [case testForwardRefToBadAsyncShouldNotCrash_newsemanal] from typing import TypeVar @@ -496,10 +468,11 @@ def test() -> None: reveal_type(bad) bad(0) -@asyncio.coroutine -def bad(arg: P) -> T: +async def bad(arg: P) -> T: pass [out] -_program.py:8: note: Revealed type is "def [T] (arg: P?) -> T`-1" -_program.py:12: error: Variable "_testForwardRefToBadAsyncShouldNotCrash_newsemanal.P" is not valid as a type -_program.py:12: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +_program.py:8: note: Revealed type is "def [T] (arg: P?) -> typing.Coroutine[Any, Any, T`-1]" +_program.py:9: error: Value of type "Coroutine[Any, Any, ]" must be used +_program.py:9: note: Are you missing an await? +_program.py:11: error: Variable "_testForwardRefToBadAsyncShouldNotCrash_newsemanal.P" is not valid as a type +_program.py:11: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases From 3c0409203a59eccb0e04caca7bef97c3e1e83ba7 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Mon, 23 May 2022 13:15:18 +0100 Subject: [PATCH 318/377] [mypyc] Borrow even more things (#12817) Borrow operands of tagged integer operations to reduce the number of incref/decref operations (when it's safe to do so). Borrow the results in list get item operations, similar to what we've been doing with get attribute operations. --- mypyc/irbuild/ast_helpers.py | 94 ++++++++++ mypyc/irbuild/builder.py | 80 ++------ mypyc/irbuild/expression.py | 55 +++--- mypyc/irbuild/ll_builder.py | 32 +++- mypyc/irbuild/statement.py | 20 +- mypyc/irbuild/targets.py | 3 +- mypyc/lib-rt/CPy.h | 2 + mypyc/lib-rt/int_ops.c | 7 +- mypyc/lib-rt/list_ops.c | 41 +++++ mypyc/primitives/list_ops.py | 22 ++- mypyc/test-data/exceptions.test | 3 +- mypyc/test-data/irbuild-basic.test | 16 +- mypyc/test-data/irbuild-classes.test | 49 ++++- mypyc/test-data/irbuild-generics.test | 3 +- mypyc/test-data/irbuild-lists.test | 5 +- mypyc/test-data/refcount.test | 253 +++++++++++++++++++++++++- mypyc/test-data/run-lists.test | 25 +++ 17 files changed, 587 insertions(+), 123 deletions(-) create mode 100644 mypyc/irbuild/ast_helpers.py diff --git a/mypyc/irbuild/ast_helpers.py b/mypyc/irbuild/ast_helpers.py new file mode 100644 index 0000000000000..8c9ca186e46ae --- /dev/null +++ b/mypyc/irbuild/ast_helpers.py @@ -0,0 +1,94 @@ +"""IRBuilder AST transform helpers shared between expressions and statements. + +Shared code that is tightly coupled to mypy ASTs can be put here instead of +making mypyc.irbuild.builder larger. +""" + +from mypy.nodes import ( + Expression, MemberExpr, Var, IntExpr, FloatExpr, StrExpr, BytesExpr, NameExpr, OpExpr, + UnaryExpr, ComparisonExpr, LDEF +) +from mypyc.ir.ops import BasicBlock +from mypyc.ir.rtypes import is_tagged +from mypyc.irbuild.builder import IRBuilder +from mypyc.irbuild.constant_fold import constant_fold_expr + + +def process_conditional(self: IRBuilder, e: Expression, true: BasicBlock, + false: BasicBlock) -> None: + if isinstance(e, OpExpr) and e.op in ['and', 'or']: + if e.op == 'and': + # Short circuit 'and' in a conditional context. + new = BasicBlock() + process_conditional(self, e.left, new, false) + self.activate_block(new) + process_conditional(self, e.right, true, false) + else: + # Short circuit 'or' in a conditional context. + new = BasicBlock() + process_conditional(self, e.left, true, new) + self.activate_block(new) + process_conditional(self, e.right, true, false) + elif isinstance(e, UnaryExpr) and e.op == 'not': + process_conditional(self, e.expr, false, true) + else: + res = maybe_process_conditional_comparison(self, e, true, false) + if res: + return + # Catch-all for arbitrary expressions. + reg = self.accept(e) + self.add_bool_branch(reg, true, false) + + +def maybe_process_conditional_comparison(self: IRBuilder, + e: Expression, + true: BasicBlock, + false: BasicBlock) -> bool: + """Transform simple tagged integer comparisons in a conditional context. + + Return True if the operation is supported (and was transformed). Otherwise, + do nothing and return False. + + Args: + e: Arbitrary expression + true: Branch target if comparison is true + false: Branch target if comparison is false + """ + if not isinstance(e, ComparisonExpr) or len(e.operands) != 2: + return False + ltype = self.node_type(e.operands[0]) + rtype = self.node_type(e.operands[1]) + if not is_tagged(ltype) or not is_tagged(rtype): + return False + op = e.operators[0] + if op not in ('==', '!=', '<', '<=', '>', '>='): + return False + left_expr = e.operands[0] + right_expr = e.operands[1] + borrow_left = is_borrow_friendly_expr(self, right_expr) + left = self.accept(left_expr, can_borrow=borrow_left) + right = self.accept(right_expr, can_borrow=True) + # "left op right" for two tagged integers + self.builder.compare_tagged_condition(left, right, op, true, false, e.line) + return True + + +def is_borrow_friendly_expr(self: IRBuilder, expr: Expression) -> bool: + """Can the result of the expression borrowed temporarily? + + Borrowing means keeping a reference without incrementing the reference count. + """ + if isinstance(expr, (IntExpr, FloatExpr, StrExpr, BytesExpr)): + # Literals are immortal and can always be borrowed + return True + if (isinstance(expr, (UnaryExpr, OpExpr, NameExpr, MemberExpr)) and + constant_fold_expr(self, expr) is not None): + # Literal expressions are similar to literals + return True + if isinstance(expr, NameExpr): + if isinstance(expr.node, Var) and expr.kind == LDEF: + # Local variable reference can be borrowed + return True + if isinstance(expr, MemberExpr) and self.is_native_attr_ref(expr): + return True + return False diff --git a/mypyc/irbuild/builder.py b/mypyc/irbuild/builder.py index c7ef400236b3a..c1662d2fdac2c 100644 --- a/mypyc/irbuild/builder.py +++ b/mypyc/irbuild/builder.py @@ -14,15 +14,15 @@ from mypyc.irbuild.prepare import RegisterImplInfo from typing import Callable, Dict, List, Tuple, Optional, Union, Sequence, Set, Any, Iterator -from typing_extensions import overload +from typing_extensions import overload, Final from mypy.backports import OrderedDict from mypy.build import Graph from mypy.nodes import ( MypyFile, SymbolNode, Statement, OpExpr, IntExpr, NameExpr, LDEF, Var, UnaryExpr, CallExpr, IndexExpr, Expression, MemberExpr, RefExpr, Lvalue, TupleExpr, - TypeInfo, Decorator, OverloadedFuncDef, StarExpr, ComparisonExpr, GDEF, - ArgKind, ARG_POS, ARG_NAMED, FuncDef, + TypeInfo, Decorator, OverloadedFuncDef, StarExpr, + GDEF, ArgKind, ARG_POS, ARG_NAMED, FuncDef, ) from mypy.types import ( Type, Instance, TupleType, UninhabitedType, get_proper_type @@ -40,7 +40,7 @@ from mypyc.ir.rtypes import ( RType, RTuple, RInstance, c_int_rprimitive, int_rprimitive, dict_rprimitive, none_rprimitive, is_none_rprimitive, object_rprimitive, is_object_rprimitive, - str_rprimitive, is_tagged, is_list_rprimitive, is_tuple_rprimitive, c_pyssize_t_rprimitive + str_rprimitive, is_list_rprimitive, is_tuple_rprimitive, c_pyssize_t_rprimitive ) from mypyc.ir.func_ir import FuncIR, INVALID_FUNC_DEF, RuntimeArg, FuncSignature, FuncDecl from mypyc.ir.class_ir import ClassIR, NonExtClassInfo @@ -67,6 +67,11 @@ from mypyc.irbuild.util import is_constant +# These int binary operations can borrow their operands safely, since the +# primitives take this into consideration. +int_borrow_friendly_op: Final = {'+', '-', '==', '!=', '<', '<=', '>', '>='} + + class IRVisitor(ExpressionVisitor[Value], StatementVisitor[None]): pass @@ -287,7 +292,7 @@ def gen_method_call(self, arg_kinds: Optional[List[ArgKind]] = None, arg_names: Optional[List[Optional[str]]] = None) -> Value: return self.builder.gen_method_call( - base, name, arg_values, result_type, line, arg_kinds, arg_names + base, name, arg_values, result_type, line, arg_kinds, arg_names, self.can_borrow ) def load_module(self, name: str) -> Value: @@ -515,7 +520,7 @@ def get_assignment_target(self, lvalue: Lvalue, # Attribute assignment x.y = e can_borrow = self.is_native_attr_ref(lvalue) obj = self.accept(lvalue.expr, can_borrow=can_borrow) - return AssignmentTargetAttr(obj, lvalue.name) + return AssignmentTargetAttr(obj, lvalue.name, can_borrow=can_borrow) elif isinstance(lvalue, TupleExpr): # Multiple assignment a, ..., b = e star_idx: Optional[int] = None @@ -535,7 +540,10 @@ def get_assignment_target(self, lvalue: Lvalue, assert False, 'Unsupported lvalue: %r' % lvalue - def read(self, target: Union[Value, AssignmentTarget], line: int = -1) -> Value: + def read(self, + target: Union[Value, AssignmentTarget], + line: int = -1, + can_borrow: bool = False) -> Value: if isinstance(target, Value): return target if isinstance(target, AssignmentTargetRegister): @@ -548,7 +556,8 @@ def read(self, target: Union[Value, AssignmentTarget], line: int = -1) -> Value: assert False, target.base.type if isinstance(target, AssignmentTargetAttr): if isinstance(target.obj.type, RInstance) and target.obj.type.class_ir.is_ext_class: - return self.add(GetAttr(target.obj, target.attr, line)) + borrow = can_borrow and target.can_borrow + return self.add(GetAttr(target.obj, target.attr, line, borrow=borrow)) else: return self.py_get_attr(target.obj, target.attr, line) @@ -915,61 +924,6 @@ def shortcircuit_expr(self, expr: OpExpr) -> Value: expr.line ) - # Conditional expressions - - def process_conditional(self, e: Expression, true: BasicBlock, false: BasicBlock) -> None: - if isinstance(e, OpExpr) and e.op in ['and', 'or']: - if e.op == 'and': - # Short circuit 'and' in a conditional context. - new = BasicBlock() - self.process_conditional(e.left, new, false) - self.activate_block(new) - self.process_conditional(e.right, true, false) - else: - # Short circuit 'or' in a conditional context. - new = BasicBlock() - self.process_conditional(e.left, true, new) - self.activate_block(new) - self.process_conditional(e.right, true, false) - elif isinstance(e, UnaryExpr) and e.op == 'not': - self.process_conditional(e.expr, false, true) - else: - res = self.maybe_process_conditional_comparison(e, true, false) - if res: - return - # Catch-all for arbitrary expressions. - reg = self.accept(e) - self.add_bool_branch(reg, true, false) - - def maybe_process_conditional_comparison(self, - e: Expression, - true: BasicBlock, - false: BasicBlock) -> bool: - """Transform simple tagged integer comparisons in a conditional context. - - Return True if the operation is supported (and was transformed). Otherwise, - do nothing and return False. - - Args: - e: Arbitrary expression - true: Branch target if comparison is true - false: Branch target if comparison is false - """ - if not isinstance(e, ComparisonExpr) or len(e.operands) != 2: - return False - ltype = self.node_type(e.operands[0]) - rtype = self.node_type(e.operands[1]) - if not is_tagged(ltype) or not is_tagged(rtype): - return False - op = e.operators[0] - if op not in ('==', '!=', '<', '<=', '>', '>='): - return False - left = self.accept(e.operands[0]) - right = self.accept(e.operands[1]) - # "left op right" for two tagged integers - self.builder.compare_tagged_condition(left, right, op, true, false, e.line) - return True - # Basic helpers def flatten_classes(self, arg: Union[RefExpr, TupleExpr]) -> Optional[List[ClassIR]]: diff --git a/mypyc/irbuild/expression.py b/mypyc/irbuild/expression.py index e1feabb0a4f3f..76e4db62a4656 100644 --- a/mypyc/irbuild/expression.py +++ b/mypyc/irbuild/expression.py @@ -40,12 +40,13 @@ from mypyc.primitives.str_ops import str_slice_op from mypyc.primitives.int_ops import int_comparison_op_mapping from mypyc.irbuild.specialize import apply_function_specialization, apply_method_specialization -from mypyc.irbuild.builder import IRBuilder +from mypyc.irbuild.builder import IRBuilder, int_borrow_friendly_op from mypyc.irbuild.for_helpers import ( translate_list_comprehension, translate_set_comprehension, comprehension_helper ) from mypyc.irbuild.constant_fold import constant_fold_expr +from mypyc.irbuild.ast_helpers import is_borrow_friendly_expr, process_conditional # Name and attribute references @@ -404,6 +405,15 @@ def transform_op_expr(builder: IRBuilder, expr: OpExpr) -> Value: if folded: return folded + # Special case some int ops to allow borrowing operands. + if (is_int_rprimitive(builder.node_type(expr.left)) + and is_int_rprimitive(builder.node_type(expr.right))): + if expr.op in int_borrow_friendly_op: + borrow_left = is_borrow_friendly_expr(builder, expr.right) + left = builder.accept(expr.left, can_borrow=borrow_left) + right = builder.accept(expr.right, can_borrow=True) + return builder.binary_op(left, right, expr.op, expr.line) + return builder.binary_op( builder.accept(expr.left), builder.accept(expr.right), expr.op, expr.line ) @@ -430,26 +440,6 @@ def transform_index_expr(builder: IRBuilder, expr: IndexExpr) -> Value: base, '__getitem__', [index_reg], builder.node_type(expr), expr.line) -def is_borrow_friendly_expr(builder: IRBuilder, expr: Expression) -> bool: - """Can the result of the expression borrowed temporarily? - - Borrowing means keeping a reference without incrementing the reference count. - """ - if isinstance(expr, (IntExpr, FloatExpr, StrExpr, BytesExpr)): - # Literals are immportal and can always be borrowed - return True - if isinstance(expr, (UnaryExpr, OpExpr)) and constant_fold_expr(builder, expr) is not None: - # Literal expressions are similar to literals - return True - if isinstance(expr, NameExpr): - if isinstance(expr.node, Var) and expr.kind == LDEF: - # Local variable reference can be borrowed - return True - if isinstance(expr, MemberExpr) and builder.is_native_attr_ref(expr): - return True - return False - - def try_constant_fold(builder: IRBuilder, expr: Expression) -> Optional[Value]: """Return the constant value of an expression if possible. @@ -504,7 +494,7 @@ def try_gen_slice_op(builder: IRBuilder, base: Value, index: SliceExpr) -> Optio def transform_conditional_expr(builder: IRBuilder, expr: ConditionalExpr) -> Value: if_body, else_body, next_block = BasicBlock(), BasicBlock(), BasicBlock() - builder.process_conditional(expr.cond, if_body, else_body) + process_conditional(builder, expr.cond, if_body, else_body) expr_type = builder.node_type(expr) # Having actual Phi nodes would be really nice here! target = Register(expr_type) @@ -577,11 +567,22 @@ def transform_comparison_expr(builder: IRBuilder, e: ComparisonExpr) -> Value: else: return builder.true() - if first_op in ('is', 'is not') and len(e.operators) == 1: - right = e.operands[1] - if isinstance(right, NameExpr) and right.fullname == 'builtins.None': - # Special case 'is None' / 'is not None'. - return translate_is_none(builder, e.operands[0], negated=first_op != 'is') + if len(e.operators) == 1: + # Special some common simple cases + if first_op in ('is', 'is not'): + right_expr = e.operands[1] + if isinstance(right_expr, NameExpr) and right_expr.fullname == 'builtins.None': + # Special case 'is None' / 'is not None'. + return translate_is_none(builder, e.operands[0], negated=first_op != 'is') + left_expr = e.operands[0] + if is_int_rprimitive(builder.node_type(left_expr)): + right_expr = e.operands[1] + if is_int_rprimitive(builder.node_type(right_expr)): + if first_op in int_borrow_friendly_op: + borrow_left = is_borrow_friendly_expr(builder, right_expr) + left = builder.accept(left_expr, can_borrow=borrow_left) + right = builder.accept(right_expr, can_borrow=True) + return builder.compare_tagged(left, right, first_op, e.line) # TODO: Don't produce an expression when used in conditional context # All of the trickiness here is due to support for chained conditionals diff --git a/mypyc/irbuild/ll_builder.py b/mypyc/irbuild/ll_builder.py index c7d8dc7b3ab2f..d5154707538b7 100644 --- a/mypyc/irbuild/ll_builder.py +++ b/mypyc/irbuild/ll_builder.py @@ -725,7 +725,8 @@ def gen_method_call(self, result_type: Optional[RType], line: int, arg_kinds: Optional[List[ArgKind]] = None, - arg_names: Optional[List[Optional[str]]] = None) -> Value: + arg_names: Optional[List[Optional[str]]] = None, + can_borrow: bool = False) -> Value: """Generate either a native or Python method call.""" # If we have *args, then fallback to Python method call. if arg_kinds is not None and any(kind.is_star() for kind in arg_kinds): @@ -759,7 +760,8 @@ def gen_method_call(self, # Try to do a special-cased method call if not arg_kinds or arg_kinds == [ARG_POS] * len(arg_values): - target = self.translate_special_method_call(base, name, arg_values, result_type, line) + target = self.translate_special_method_call( + base, name, arg_values, result_type, line, can_borrow=can_borrow) if target: return target @@ -968,12 +970,14 @@ def compare_tagged_condition(self, is_short_int_rprimitive(rhs.type)))): # We can skip the tag check check = self.comparison_op(lhs, rhs, int_comparison_op_mapping[op][0], line) + self.flush_keep_alives() self.add(Branch(check, true, false, Branch.BOOL)) return op_type, c_func_desc, negate_result, swap_op = int_comparison_op_mapping[op] int_block, short_int_block = BasicBlock(), BasicBlock() check_lhs = self.check_tagged_short_int(lhs, line, negated=True) if is_eq or is_short_int_rprimitive(rhs.type): + self.flush_keep_alives() self.add(Branch(check_lhs, int_block, short_int_block, Branch.BOOL)) else: # For non-equality logical ops (less/greater than, etc.), need to check both sides @@ -981,6 +985,7 @@ def compare_tagged_condition(self, self.add(Branch(check_lhs, int_block, rhs_block, Branch.BOOL)) self.activate_block(rhs_block) check_rhs = self.check_tagged_short_int(rhs, line, negated=True) + self.flush_keep_alives() self.add(Branch(check_rhs, int_block, short_int_block, Branch.BOOL)) # Arbitrary integers (slow path) self.activate_block(int_block) @@ -992,6 +997,7 @@ def compare_tagged_condition(self, if negate_result: self.add(Branch(call, false, true, Branch.BOOL)) else: + self.flush_keep_alives() self.add(Branch(call, true, false, Branch.BOOL)) # Short integers (fast path) self.activate_block(short_int_block) @@ -1313,6 +1319,13 @@ def call_c(self, error_kind = ERR_NEVER target = self.add(CallC(desc.c_function_name, coerced, desc.return_type, desc.steals, desc.is_borrowed, error_kind, line, var_arg_idx)) + if desc.is_borrowed: + # If the result is borrowed, force the arguments to be + # kept alive afterwards, as otherwise the result might be + # immediately freed, at the risk of a dangling pointer. + for arg in coerced: + if not isinstance(arg, (Integer, LoadLiteral)): + self.keep_alives.append(arg) if desc.error_kind == ERR_NEG_INT: comp = ComparisonOp(target, Integer(0, desc.return_type, line), @@ -1332,20 +1345,22 @@ def call_c(self, # and so we can't just coerce it. result = self.none() else: - result = self.coerce(target, result_type, line) + result = self.coerce(target, result_type, line, can_borrow=desc.is_borrowed) return result def matching_call_c(self, candidates: List[CFunctionDescription], args: List[Value], line: int, - result_type: Optional[RType] = None) -> Optional[Value]: + result_type: Optional[RType] = None, + can_borrow: bool = False) -> Optional[Value]: matching: Optional[CFunctionDescription] = None for desc in candidates: if len(desc.arg_types) != len(args): continue - if all(is_subtype(actual.type, formal) - for actual, formal in zip(args, desc.arg_types)): + if (all(is_subtype(actual.type, formal) + for actual, formal in zip(args, desc.arg_types)) and + (not desc.is_borrowed or can_borrow)): if matching: assert matching.priority != desc.priority, 'Ambiguous:\n1) {}\n2) {}'.format( matching, desc) @@ -1500,7 +1515,8 @@ def translate_special_method_call(self, name: str, args: List[Value], result_type: Optional[RType], - line: int) -> Optional[Value]: + line: int, + can_borrow: bool = False) -> Optional[Value]: """Translate a method call which is handled nongenerically. These are special in the sense that we have code generated specifically for them. @@ -1511,7 +1527,7 @@ def translate_special_method_call(self, """ call_c_ops_candidates = method_call_ops.get(name, []) call_c_op = self.matching_call_c(call_c_ops_candidates, [base_reg] + args, - line, result_type) + line, result_type, can_borrow=can_borrow) return call_c_op def translate_eq_cmp(self, diff --git a/mypyc/irbuild/statement.py b/mypyc/irbuild/statement.py index 142a77fbe9461..93dc5f24158fd 100644 --- a/mypyc/irbuild/statement.py +++ b/mypyc/irbuild/statement.py @@ -20,7 +20,7 @@ Assign, Unreachable, RaiseStandardError, LoadErrorValue, BasicBlock, TupleGet, Value, Register, Branch, NO_TRACEBACK_LINE_NO ) -from mypyc.ir.rtypes import RInstance, exc_rtuple +from mypyc.ir.rtypes import RInstance, exc_rtuple, is_tagged from mypyc.primitives.generic_ops import py_delattr_op from mypyc.primitives.misc_ops import type_op, import_from_op from mypyc.primitives.exc_ops import ( @@ -35,7 +35,8 @@ ExceptNonlocalControl, FinallyNonlocalControl, TryFinallyNonlocalControl ) from mypyc.irbuild.for_helpers import for_loop_helper -from mypyc.irbuild.builder import IRBuilder +from mypyc.irbuild.builder import IRBuilder, int_borrow_friendly_op +from mypyc.irbuild.ast_helpers import process_conditional, is_borrow_friendly_expr GenFunc = Callable[[], None] @@ -119,9 +120,16 @@ def is_simple_lvalue(expr: Expression) -> bool: def transform_operator_assignment_stmt(builder: IRBuilder, stmt: OperatorAssignmentStmt) -> None: """Operator assignment statement such as x += 1""" builder.disallow_class_assignments([stmt.lvalue], stmt.line) + if (is_tagged(builder.node_type(stmt.lvalue)) + and is_tagged(builder.node_type(stmt.rvalue)) + and stmt.op in int_borrow_friendly_op): + can_borrow = (is_borrow_friendly_expr(builder, stmt.rvalue) + and is_borrow_friendly_expr(builder, stmt.lvalue)) + else: + can_borrow = False target = builder.get_assignment_target(stmt.lvalue) - target_value = builder.read(target, stmt.line) - rreg = builder.accept(stmt.rvalue) + target_value = builder.read(target, stmt.line, can_borrow=can_borrow) + rreg = builder.accept(stmt.rvalue, can_borrow=can_borrow) # the Python parser strips the '=' from operator assignment statements, so re-add it op = stmt.op + '=' res = builder.binary_op(target_value, rreg, op, stmt.line) @@ -207,7 +215,7 @@ def transform_if_stmt(builder: IRBuilder, stmt: IfStmt) -> None: # If statements are normalized assert len(stmt.expr) == 1 - builder.process_conditional(stmt.expr[0], if_body, else_body) + process_conditional(builder, stmt.expr[0], if_body, else_body) builder.activate_block(if_body) builder.accept(stmt.body[0]) builder.goto(next) @@ -226,7 +234,7 @@ def transform_while_stmt(builder: IRBuilder, s: WhileStmt) -> None: # Split block so that we get a handle to the top of the loop. builder.goto_and_activate(top) - builder.process_conditional(s.expr, body, normal_loop_exit) + process_conditional(builder, s.expr, body, normal_loop_exit) builder.activate_block(body) builder.accept(s.body) diff --git a/mypyc/irbuild/targets.py b/mypyc/irbuild/targets.py index f6346d4fa7e7d..f2daa701f7e85 100644 --- a/mypyc/irbuild/targets.py +++ b/mypyc/irbuild/targets.py @@ -35,9 +35,10 @@ def __init__(self, base: Value, index: Value) -> None: class AssignmentTargetAttr(AssignmentTarget): """obj.attr as assignment target""" - def __init__(self, obj: Value, attr: str) -> None: + def __init__(self, obj: Value, attr: str, can_borrow: bool = False) -> None: self.obj = obj self.attr = attr + self.can_borrow = can_borrow if isinstance(obj.type, RInstance) and obj.type.class_ir.has_attr(attr): # Native attribute reference self.obj_type: RType = obj.type diff --git a/mypyc/lib-rt/CPy.h b/mypyc/lib-rt/CPy.h index 4c0f91a5707ec..0fdd6b0a27ccc 100644 --- a/mypyc/lib-rt/CPy.h +++ b/mypyc/lib-rt/CPy.h @@ -340,6 +340,8 @@ PyObject *CPyList_Build(Py_ssize_t len, ...); PyObject *CPyList_GetItem(PyObject *list, CPyTagged index); PyObject *CPyList_GetItemUnsafe(PyObject *list, CPyTagged index); PyObject *CPyList_GetItemShort(PyObject *list, CPyTagged index); +PyObject *CPyList_GetItemBorrow(PyObject *list, CPyTagged index); +PyObject *CPyList_GetItemShortBorrow(PyObject *list, CPyTagged index); bool CPyList_SetItem(PyObject *list, CPyTagged index, PyObject *value); bool CPyList_SetItemUnsafe(PyObject *list, CPyTagged index, PyObject *value); PyObject *CPyList_PopLast(PyObject *obj); diff --git a/mypyc/lib-rt/int_ops.c b/mypyc/lib-rt/int_ops.c index edf0631416198..caf0fe0b53918 100644 --- a/mypyc/lib-rt/int_ops.c +++ b/mypyc/lib-rt/int_ops.c @@ -250,8 +250,11 @@ bool CPyTagged_IsEq_(CPyTagged left, CPyTagged right) { if (CPyTagged_CheckShort(right)) { return false; } else { - int result = PyObject_RichCompareBool(CPyTagged_LongAsObject(left), - CPyTagged_LongAsObject(right), Py_EQ); + PyObject *left_obj = CPyTagged_AsObject(left); + PyObject *right_obj = CPyTagged_AsObject(right); + int result = PyObject_RichCompareBool(left_obj, right_obj, Py_EQ); + Py_DECREF(left_obj); + Py_DECREF(right_obj); if (result == -1) { CPyError_OutOfMemory(); } diff --git a/mypyc/lib-rt/list_ops.c b/mypyc/lib-rt/list_ops.c index 28547cfd7b60b..885c1a3366f3e 100644 --- a/mypyc/lib-rt/list_ops.c +++ b/mypyc/lib-rt/list_ops.c @@ -52,6 +52,24 @@ PyObject *CPyList_GetItemShort(PyObject *list, CPyTagged index) { return result; } +PyObject *CPyList_GetItemShortBorrow(PyObject *list, CPyTagged index) { + Py_ssize_t n = CPyTagged_ShortAsSsize_t(index); + Py_ssize_t size = PyList_GET_SIZE(list); + if (n >= 0) { + if (n >= size) { + PyErr_SetString(PyExc_IndexError, "list index out of range"); + return NULL; + } + } else { + n += size; + if (n < 0) { + PyErr_SetString(PyExc_IndexError, "list index out of range"); + return NULL; + } + } + return PyList_GET_ITEM(list, n); +} + PyObject *CPyList_GetItem(PyObject *list, CPyTagged index) { if (CPyTagged_CheckShort(index)) { Py_ssize_t n = CPyTagged_ShortAsSsize_t(index); @@ -77,6 +95,29 @@ PyObject *CPyList_GetItem(PyObject *list, CPyTagged index) { } } +PyObject *CPyList_GetItemBorrow(PyObject *list, CPyTagged index) { + if (CPyTagged_CheckShort(index)) { + Py_ssize_t n = CPyTagged_ShortAsSsize_t(index); + Py_ssize_t size = PyList_GET_SIZE(list); + if (n >= 0) { + if (n >= size) { + PyErr_SetString(PyExc_IndexError, "list index out of range"); + return NULL; + } + } else { + n += size; + if (n < 0) { + PyErr_SetString(PyExc_IndexError, "list index out of range"); + return NULL; + } + } + return PyList_GET_ITEM(list, n); + } else { + PyErr_SetString(PyExc_OverflowError, CPYTHON_LARGE_INT_ERRMSG); + return NULL; + } +} + bool CPyList_SetItem(PyObject *list, CPyTagged index, PyObject *value) { if (CPyTagged_CheckShort(index)) { Py_ssize_t n = CPyTagged_ShortAsSsize_t(index); diff --git a/mypyc/primitives/list_ops.py b/mypyc/primitives/list_ops.py index 3988511c97721..78955f70f1648 100644 --- a/mypyc/primitives/list_ops.py +++ b/mypyc/primitives/list_ops.py @@ -55,7 +55,7 @@ c_function_name='CPyList_GetItem', error_kind=ERR_MAGIC) -# Version with no int bounds check for when it is known to be short +# list[index] version with no int bounds check for when it is known to be short method_op( name='__getitem__', arg_types=[list_rprimitive, short_int_rprimitive], @@ -64,6 +64,26 @@ error_kind=ERR_MAGIC, priority=2) +# list[index] that produces a borrowed result +method_op( + name='__getitem__', + arg_types=[list_rprimitive, int_rprimitive], + return_type=object_rprimitive, + c_function_name='CPyList_GetItemBorrow', + error_kind=ERR_MAGIC, + is_borrowed=True, + priority=3) + +# list[index] that produces a borrowed result and index is known to be short +method_op( + name='__getitem__', + arg_types=[list_rprimitive, short_int_rprimitive], + return_type=object_rprimitive, + c_function_name='CPyList_GetItemShortBorrow', + error_kind=ERR_MAGIC, + is_borrowed=True, + priority=4) + # This is unsafe because it assumes that the index is a non-negative short integer # that is in-bounds for the list. list_get_item_unsafe_op = custom_op( diff --git a/mypyc/test-data/exceptions.test b/mypyc/test-data/exceptions.test index 8c576b49ce82d..8b186e234c5e2 100644 --- a/mypyc/test-data/exceptions.test +++ b/mypyc/test-data/exceptions.test @@ -135,11 +135,10 @@ L4: r5 = i < l :: signed if r5 goto L5 else goto L10 :: bool L5: - r6 = CPyList_GetItem(a, i) + r6 = CPyList_GetItemBorrow(a, i) if is_error(r6) goto L11 (error at sum:6) else goto L6 L6: r7 = unbox(int, r6) - dec_ref r6 if is_error(r7) goto L11 (error at sum:6) else goto L7 L7: r8 = CPyTagged_Add(sum, r7) diff --git a/mypyc/test-data/irbuild-basic.test b/mypyc/test-data/irbuild-basic.test index 077abcf2939bd..8e54b25b673bf 100644 --- a/mypyc/test-data/irbuild-basic.test +++ b/mypyc/test-data/irbuild-basic.test @@ -2197,15 +2197,17 @@ L0: r0 = self.is_add if r0 goto L1 else goto L2 :: bool L1: - r1 = self.left - r2 = self.right + r1 = borrow self.left + r2 = borrow self.right r3 = CPyTagged_Add(r1, r2) + keep_alive self, self r4 = r3 goto L3 L2: - r5 = self.left - r6 = self.right + r5 = borrow self.left + r6 = borrow self.right r7 = CPyTagged_Subtract(r5, r6) + keep_alive self, self r4 = r7 L3: return r4 @@ -2292,8 +2294,9 @@ def BaseProperty.next(self): r0, r1 :: int r2 :: __main__.BaseProperty L0: - r0 = self._incrementer + r0 = borrow self._incrementer r1 = CPyTagged_Add(r0, 2) + keep_alive self r2 = BaseProperty(r1) return r2 def BaseProperty.__init__(self, value): @@ -2483,9 +2486,10 @@ def g(a, b, c): r2, r3 :: int L0: r0 = a.__getitem__(c) - r1 = CPyList_GetItem(b, c) + r1 = CPyList_GetItemBorrow(b, c) r2 = unbox(int, r1) r3 = CPyTagged_Add(r0, r2) + keep_alive b, c return r3 [case testTypeAlias_toplevel] diff --git a/mypyc/test-data/irbuild-classes.test b/mypyc/test-data/irbuild-classes.test index fcf6ef9574358..5a574ac443542 100644 --- a/mypyc/test-data/irbuild-classes.test +++ b/mypyc/test-data/irbuild-classes.test @@ -59,8 +59,9 @@ L0: r5 = CPyList_GetItemShort(a, 0) r6 = cast(__main__.C, r5) d = r6 - r7 = d.x + r7 = borrow d.x r8 = CPyTagged_Add(r7, 2) + keep_alive d return r8 [case testMethodCall] @@ -175,7 +176,7 @@ def increment(o): r0, r1 :: int r2 :: bool L0: - r0 = o.x + r0 = borrow o.x r1 = CPyTagged_Add(r0, 2) o.x = r1; r2 = is_error return o @@ -1288,3 +1289,47 @@ L0: r1 = r0.e r2 = r1.x return r2 + +[case testBorrowResultOfCustomGetItemInIfStatement] +from typing import List + +class C: + def __getitem__(self, x: int) -> List[int]: + return [] + +def f(x: C) -> None: + # In this case the keep_alive must come before the branch, as otherwise + # reference count transform will get confused. + if x[1][0] == 2: + y = 1 + else: + y = 2 +[out] +def C.__getitem__(self, x): + self :: __main__.C + x :: int + r0 :: list +L0: + r0 = PyList_New(0) + return r0 +def f(x): + x :: __main__.C + r0 :: list + r1 :: object + r2 :: int + r3 :: bit + y :: int +L0: + r0 = x.__getitem__(2) + r1 = CPyList_GetItemShortBorrow(r0, 0) + r2 = unbox(int, r1) + r3 = r2 == 4 + keep_alive r0 + if r3 goto L1 else goto L2 :: bool +L1: + y = 2 + goto L3 +L2: + y = 4 +L3: + return 1 diff --git a/mypyc/test-data/irbuild-generics.test b/mypyc/test-data/irbuild-generics.test index 10f8e737d6392..fe4a949927174 100644 --- a/mypyc/test-data/irbuild-generics.test +++ b/mypyc/test-data/irbuild-generics.test @@ -62,9 +62,10 @@ L0: c = r0 r1 = object 1 c.x = r1; r2 = is_error - r3 = c.x + r3 = borrow c.x r4 = unbox(int, r3) r5 = CPyTagged_Add(4, r4) + keep_alive c return 1 [case testGenericMethod] diff --git a/mypyc/test-data/irbuild-lists.test b/mypyc/test-data/irbuild-lists.test index 3173469c8db6f..47f7ada709e36 100644 --- a/mypyc/test-data/irbuild-lists.test +++ b/mypyc/test-data/irbuild-lists.test @@ -38,10 +38,11 @@ def f(x): r2 :: object r3 :: int L0: - r0 = CPyList_GetItemShort(x, 0) - r1 = cast(list, r0) + r0 = CPyList_GetItemShortBorrow(x, 0) + r1 = borrow cast(list, r0) r2 = CPyList_GetItemShort(r1, 2) r3 = unbox(int, r2) + keep_alive x, r0 return r3 [case testListSet] diff --git a/mypyc/test-data/refcount.test b/mypyc/test-data/refcount.test index a7ee390c8d74f..ce365fc50e7ee 100644 --- a/mypyc/test-data/refcount.test +++ b/mypyc/test-data/refcount.test @@ -1153,14 +1153,20 @@ L0: [case testBorrowListGetItem2] from typing import List -def attr_index(x: C) -> str: +def attr_before_index(x: C) -> str: return x.a[x.n] +def attr_after_index(a: List[C], i: int) -> int: + return a[i].n + +def attr_after_index_literal(a: List[C]) -> int: + return a[0].n + class C: a: List[str] n: int [out] -def attr_index(x): +def attr_before_index(x): x :: __main__.C r0 :: list r1 :: int @@ -1172,6 +1178,27 @@ L0: r2 = CPyList_GetItem(r0, r1) r3 = cast(str, r2) return r3 +def attr_after_index(a, i): + a :: list + i :: int + r0 :: object + r1 :: __main__.C + r2 :: int +L0: + r0 = CPyList_GetItemBorrow(a, i) + r1 = borrow cast(__main__.C, r0) + r2 = r1.n + return r2 +def attr_after_index_literal(a): + a :: list + r0 :: object + r1 :: __main__.C + r2 :: int +L0: + r0 = CPyList_GetItemShortBorrow(a, 0) + r1 = borrow cast(__main__.C, r0) + r2 = r1.n + return r2 [case testCannotBorrowListGetItem] from typing import List @@ -1202,6 +1229,37 @@ def f(): L0: return 0 +[case testBorrowListGetItemKeepAlive] +from typing import List + +def f() -> str: + a = [C()] + return a[0].s + +class C: + s: str +[out] +def f(): + r0 :: __main__.C + r1 :: list + r2, r3 :: ptr + a :: list + r4 :: object + r5 :: __main__.C + r6 :: str +L0: + r0 = C() + r1 = PyList_New(1) + r2 = get_element_ptr r1 ob_item :: PyListObject + r3 = load_mem r2 :: ptr* + set_mem r3, r0 :: builtins.object* + a = r1 + r4 = CPyList_GetItemShortBorrow(a, 0) + r5 = borrow cast(__main__.C, r4) + r6 = r5.s + dec_ref a + return r6 + [case testBorrowSetAttrObject] from typing import Optional @@ -1241,3 +1299,194 @@ L0: r0 = borrow x.c r0.b = 0; r1 = is_error return 1 + +[case testBorrowIntEquality] +def add(c: C) -> bool: + return c.x == c.y + +class C: + x: int + y: int +[out] +def add(c): + c :: __main__.C + r0, r1 :: int + r2 :: native_int + r3, r4 :: bit + r5 :: bool + r6 :: bit +L0: + r0 = borrow c.x + r1 = borrow c.y + r2 = r0 & 1 + r3 = r2 == 0 + if r3 goto L1 else goto L2 :: bool +L1: + r4 = r0 == r1 + r5 = r4 + goto L3 +L2: + r6 = CPyTagged_IsEq_(r0, r1) + r5 = r6 +L3: + return r5 + +[case testBorrowIntLessThan] +def add(c: C) -> bool: + return c.x < c.y + +class C: + x: int + y: int +[out] +def add(c): + c :: __main__.C + r0, r1 :: int + r2 :: native_int + r3 :: bit + r4 :: native_int + r5, r6, r7 :: bit + r8 :: bool + r9 :: bit +L0: + r0 = borrow c.x + r1 = borrow c.y + r2 = r0 & 1 + r3 = r2 == 0 + r4 = r1 & 1 + r5 = r4 == 0 + r6 = r3 & r5 + if r6 goto L1 else goto L2 :: bool +L1: + r7 = r0 < r1 :: signed + r8 = r7 + goto L3 +L2: + r9 = CPyTagged_IsLt_(r0, r1) + r8 = r9 +L3: + return r8 + +[case testBorrowIntCompareFinal] +from typing_extensions import Final + +X: Final = 10 + +def add(c: C) -> bool: + return c.x == X + +class C: + x: int +[out] +def add(c): + c :: __main__.C + r0 :: int + r1 :: native_int + r2, r3 :: bit + r4 :: bool + r5 :: bit +L0: + r0 = borrow c.x + r1 = r0 & 1 + r2 = r1 == 0 + if r2 goto L1 else goto L2 :: bool +L1: + r3 = r0 == 20 + r4 = r3 + goto L3 +L2: + r5 = CPyTagged_IsEq_(r0, 20) + r4 = r5 +L3: + return r4 + +[case testBorrowIntArithmetic] +def add(c: C) -> int: + return c.x + c.y + +def sub(c: C) -> int: + return c.x - c.y + +class C: + x: int + y: int +[out] +def add(c): + c :: __main__.C + r0, r1, r2 :: int +L0: + r0 = borrow c.x + r1 = borrow c.y + r2 = CPyTagged_Add(r0, r1) + return r2 +def sub(c): + c :: __main__.C + r0, r1, r2 :: int +L0: + r0 = borrow c.x + r1 = borrow c.y + r2 = CPyTagged_Subtract(r0, r1) + return r2 + +[case testBorrowIntComparisonInIf] +def add(c: C, n: int) -> bool: + if c.x == c.y: + return True + return False + +class C: + x: int + y: int +[out] +def add(c, n): + c :: __main__.C + n, r0, r1 :: int + r2 :: native_int + r3, r4, r5 :: bit +L0: + r0 = borrow c.x + r1 = borrow c.y + r2 = r0 & 1 + r3 = r2 != 0 + if r3 goto L1 else goto L2 :: bool +L1: + r4 = CPyTagged_IsEq_(r0, r1) + if r4 goto L3 else goto L4 :: bool +L2: + r5 = r0 == r1 + if r5 goto L3 else goto L4 :: bool +L3: + return 1 +L4: + return 0 + +[case testBorrowIntInPlaceOp] +def add(c: C, n: int) -> None: + c.x += n + +def sub(c: C, n: int) -> None: + c.x -= c.y + +class C: + x: int + y: int +[out] +def add(c, n): + c :: __main__.C + n, r0, r1 :: int + r2 :: bool +L0: + r0 = borrow c.x + r1 = CPyTagged_Add(r0, n) + c.x = r1; r2 = is_error + return 1 +def sub(c, n): + c :: __main__.C + n, r0, r1, r2 :: int + r3 :: bool +L0: + r0 = borrow c.x + r1 = borrow c.y + r2 = CPyTagged_Subtract(r0, r1) + c.x = r2; r3 = is_error + return 1 diff --git a/mypyc/test-data/run-lists.test b/mypyc/test-data/run-lists.test index c98ab91711238..84d5ee121a200 100644 --- a/mypyc/test-data/run-lists.test +++ b/mypyc/test-data/run-lists.test @@ -379,8 +379,33 @@ def test() -> None: source_str = "abcd" f = list("str:" + x for x in source_str) assert f == ["str:a", "str:b", "str:c", "str:d"] + [case testNextBug] from typing import List, Optional def test(x: List[int]) -> None: res = next((i for i in x), None) + +[case testListGetItemWithBorrow] +from typing import List + +class D: + def __init__(self, n: int) -> None: + self.n = n + +class C: + def __init__(self, d: D) -> None: + self.d = d + +def test_index_with_literal() -> None: + d1 = D(1) + d2 = D(2) + a = [C(d1), C(d2)] + d = a[0].d + assert d is d1 + d = a[1].d + assert d is d2 + d = a[-1].d + assert d is d2 + d = a[-2].d + assert d is d1 From c8efeed44d4c90cc05cf196f6315410fda468d70 Mon Sep 17 00:00:00 2001 From: 97littleleaf11 <11172084+97littleleaf11@users.noreply.github.com> Date: Mon, 23 May 2022 22:17:37 +0800 Subject: [PATCH 319/377] [mypyc] Fix Python 3.11 C API errors (#12850) Closes mypyc/mypyc#931 Closes mypyc/mypyc#923 Related CPython modification: python/cpython#89874 python/cpython#31530 --- mypyc/lib-rt/exc_ops.c | 9 ++++++++- mypyc/lib-rt/misc_ops.c | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/mypyc/lib-rt/exc_ops.c b/mypyc/lib-rt/exc_ops.c index 2e1f4fb668637..1b679199bc0f6 100644 --- a/mypyc/lib-rt/exc_ops.c +++ b/mypyc/lib-rt/exc_ops.c @@ -75,7 +75,7 @@ void CPy_RestoreExcInfo(tuple_T3OOO info) { } bool CPy_ExceptionMatches(PyObject *type) { - return PyErr_GivenExceptionMatches(CPy_ExcState()->exc_type, type); + return PyErr_GivenExceptionMatches((PyObject *)Py_TYPE(CPy_ExcState()->exc_value), type); } PyObject *CPy_GetExcValue(void) { @@ -189,6 +189,13 @@ void CPy_TypeError(const char *expected, PyObject *value) { } } +// The PyFrameObject type definition (struct _frame) has been moved +// to the internal C API: to the pycore_frame.h header file. +// https://github.com/python/cpython/pull/31530 +#if PY_VERSION_HEX >= 0x030b00a6 +#include "internal/pycore_frame.h" +#endif + // This function is basically exactly the same with _PyTraceback_Add // which is available in all the versions we support. // We're continuing to use this because we'll probably optimize this later. diff --git a/mypyc/lib-rt/misc_ops.c b/mypyc/lib-rt/misc_ops.c index dcce89d907201..fea38eca9d901 100644 --- a/mypyc/lib-rt/misc_ops.c +++ b/mypyc/lib-rt/misc_ops.c @@ -45,7 +45,7 @@ int CPy_YieldFromErrorHandle(PyObject *iter, PyObject **outp) { _Py_IDENTIFIER(close); _Py_IDENTIFIER(throw); - PyObject *exc_type = CPy_ExcState()->exc_type; + PyObject *exc_type = (PyObject *)Py_TYPE(CPy_ExcState()->exc_value); PyObject *type, *value, *traceback; PyObject *_m; PyObject *res; From 040f3ab64a86efcf7093ada1b13842e56715f243 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Mon, 23 May 2022 15:18:58 +0100 Subject: [PATCH 320/377] [mypyc] Generate smaller code for casts (#12839) Merge a cast op followed by a branch that does an error check and adds a traceback entry. Since casts are very common, this reduces the size of the generated code a fair amount. Old code generated for a cast: ``` if (likely(PyUnicode_Check(cpy_r_x))) cpy_r_r0 = cpy_r_x; else { CPy_TypeError("str", cpy_r_x); cpy_r_r0 = NULL; } if (unlikely(cpy_r_r0 == NULL)) { CPy_AddTraceback("t/t.py", "foo", 2, CPyStatic_globals); goto CPyL2; } ``` New code: ``` if (likely(PyUnicode_Check(cpy_r_x))) cpy_r_r0 = cpy_r_x; else { CPy_TypeErrorTraceback("t/t.py", "foo", 2, CPyStatic_globals, "str", cpy_r_x); goto CPyL2; } ``` --- mypyc/codegen/emit.py | 156 ++++++++++++++++++++++------- mypyc/codegen/emitfunc.py | 35 ++++--- mypyc/lib-rt/CPy.h | 2 + mypyc/lib-rt/exc_ops.c | 7 ++ mypyc/test-data/run-functions.test | 15 +++ mypyc/test/test_emitfunc.py | 109 +++++++++++++++++++- mypyc/test/test_emitwrapper.py | 3 +- 7 files changed, 270 insertions(+), 57 deletions(-) diff --git a/mypyc/codegen/emit.py b/mypyc/codegen/emit.py index 94ea940ca3e6e..0815dd3c3bd0e 100644 --- a/mypyc/codegen/emit.py +++ b/mypyc/codegen/emit.py @@ -2,6 +2,8 @@ from mypy.backports import OrderedDict from typing import List, Set, Dict, Optional, Callable, Union, Tuple +from typing_extensions import Final + import sys from mypyc.common import ( @@ -23,6 +25,10 @@ from mypyc.sametype import is_same_type from mypyc.codegen.literals import Literals +# Whether to insert debug asserts for all error handling, to quickly +# catch errors propagating without exceptions set. +DEBUG_ERRORS: Final = False + class HeaderDeclaration: """A representation of a declaration in C. @@ -104,6 +110,20 @@ def __init__(self, label: str) -> None: self.label = label +class TracebackAndGotoHandler(ErrorHandler): + """Add traceback item and goto label on error.""" + + def __init__(self, + label: str, + source_path: str, + module_name: str, + traceback_entry: Tuple[str, int]) -> None: + self.label = label + self.source_path = source_path + self.module_name = module_name + self.traceback_entry = traceback_entry + + class ReturnHandler(ErrorHandler): """Return a constant value on error.""" @@ -439,18 +459,6 @@ def emit_cast(self, likely: If the cast is likely to succeed (can be False for unions) """ error = error or AssignHandler() - if isinstance(error, AssignHandler): - handle_error = '%s = NULL;' % dest - elif isinstance(error, GotoHandler): - handle_error = 'goto %s;' % error.label - else: - assert isinstance(error, ReturnHandler) - handle_error = 'return %s;' % error.value - if raise_exception: - raise_exc = f'CPy_TypeError("{self.pretty_name(typ)}", {src}); ' - err = raise_exc + handle_error - else: - err = handle_error # Special case casting *from* optional if src_type and is_optional_type(src_type) and not is_object_rprimitive(typ): @@ -465,9 +473,9 @@ def emit_cast(self, self.emit_arg_check(src, dest, typ, check.format(src), optional) self.emit_lines( f' {dest} = {src};', - 'else {', - err, - '}') + 'else {') + self.emit_cast_error_handler(error, src, dest, typ, raise_exception) + self.emit_line('}') return # TODO: Verify refcount handling. @@ -500,9 +508,9 @@ def emit_cast(self, self.emit_arg_check(src, dest, typ, check.format(prefix, src), optional) self.emit_lines( f' {dest} = {src};', - 'else {', - err, - '}') + 'else {') + self.emit_cast_error_handler(error, src, dest, typ, raise_exception) + self.emit_line('}') elif is_bytes_rprimitive(typ): if declare_dest: self.emit_line(f'PyObject *{dest};') @@ -512,9 +520,9 @@ def emit_cast(self, self.emit_arg_check(src, dest, typ, check.format(src, src), optional) self.emit_lines( f' {dest} = {src};', - 'else {', - err, - '}') + 'else {') + self.emit_cast_error_handler(error, src, dest, typ, raise_exception) + self.emit_line('}') elif is_tuple_rprimitive(typ): if declare_dest: self.emit_line(f'{self.ctype(typ)} {dest};') @@ -525,9 +533,9 @@ def emit_cast(self, check.format(src), optional) self.emit_lines( f' {dest} = {src};', - 'else {', - err, - '}') + 'else {') + self.emit_cast_error_handler(error, src, dest, typ, raise_exception) + self.emit_line('}') elif isinstance(typ, RInstance): if declare_dest: self.emit_line(f'PyObject *{dest};') @@ -551,10 +559,10 @@ def emit_cast(self, check = f'(likely{check})' self.emit_arg_check(src, dest, typ, check, optional) self.emit_lines( - f' {dest} = {src};', - 'else {', - err, - '}') + f' {dest} = {src};'.format(dest, src), + 'else {') + self.emit_cast_error_handler(error, src, dest, typ, raise_exception) + self.emit_line('}') elif is_none_rprimitive(typ): if declare_dest: self.emit_line(f'PyObject *{dest};') @@ -565,9 +573,9 @@ def emit_cast(self, check.format(src), optional) self.emit_lines( f' {dest} = {src};', - 'else {', - err, - '}') + 'else {') + self.emit_cast_error_handler(error, src, dest, typ, raise_exception) + self.emit_line('}') elif is_object_rprimitive(typ): if declare_dest: self.emit_line(f'PyObject *{dest};') @@ -576,21 +584,51 @@ def emit_cast(self, if optional: self.emit_line('}') elif isinstance(typ, RUnion): - self.emit_union_cast(src, dest, typ, declare_dest, err, optional, src_type) + self.emit_union_cast(src, dest, typ, declare_dest, error, optional, src_type, + raise_exception) elif isinstance(typ, RTuple): assert not optional - self.emit_tuple_cast(src, dest, typ, declare_dest, err, src_type) + self.emit_tuple_cast(src, dest, typ, declare_dest, error, src_type) else: assert False, 'Cast not implemented: %s' % typ + def emit_cast_error_handler(self, + error: ErrorHandler, + src: str, + dest: str, + typ: RType, + raise_exception: bool) -> None: + if raise_exception: + if isinstance(error, TracebackAndGotoHandler): + # Merge raising and emitting traceback entry into a single call. + self.emit_type_error_traceback( + error.source_path, error.module_name, error.traceback_entry, + typ=typ, + src=src) + self.emit_line('goto %s;' % error.label) + return + self.emit_line('CPy_TypeError("{}", {}); '.format(self.pretty_name(typ), src)) + if isinstance(error, AssignHandler): + self.emit_line('%s = NULL;' % dest) + elif isinstance(error, GotoHandler): + self.emit_line('goto %s;' % error.label) + elif isinstance(error, TracebackAndGotoHandler): + self.emit_line('%s = NULL;' % dest) + self.emit_traceback(error.source_path, error.module_name, error.traceback_entry) + self.emit_line('goto %s;' % error.label) + else: + assert isinstance(error, ReturnHandler) + self.emit_line('return %s;' % error.value) + def emit_union_cast(self, src: str, dest: str, typ: RUnion, declare_dest: bool, - err: str, + error: ErrorHandler, optional: bool, - src_type: Optional[RType]) -> None: + src_type: Optional[RType], + raise_exception: bool) -> None: """Emit cast to a union type. The arguments are similar to emit_cast. @@ -613,11 +651,11 @@ def emit_union_cast(self, likely=False) self.emit_line(f'if ({dest} != NULL) goto {good_label};') # Handle cast failure. - self.emit_line(err) + self.emit_cast_error_handler(error, src, dest, typ, raise_exception) self.emit_label(good_label) def emit_tuple_cast(self, src: str, dest: str, typ: RTuple, declare_dest: bool, - err: str, src_type: Optional[RType]) -> None: + error: ErrorHandler, src_type: Optional[RType]) -> None: """Emit cast to a tuple type. The arguments are similar to emit_cast. @@ -740,7 +778,8 @@ def emit_unbox(self, self.emit_line('} else {') cast_temp = self.temp_name() - self.emit_tuple_cast(src, cast_temp, typ, declare_dest=True, err='', src_type=None) + self.emit_tuple_cast(src, cast_temp, typ, declare_dest=True, error=error, + src_type=None) self.emit_line(f'if (unlikely({cast_temp} == NULL)) {{') # self.emit_arg_check(src, dest, typ, @@ -886,3 +925,44 @@ def emit_gc_clear(self, target: str, rtype: RType) -> None: self.emit_line(f'Py_CLEAR({target});') else: assert False, 'emit_gc_clear() not implemented for %s' % repr(rtype) + + def emit_traceback(self, + source_path: str, + module_name: str, + traceback_entry: Tuple[str, int]) -> None: + return self._emit_traceback('CPy_AddTraceback', source_path, module_name, traceback_entry) + + def emit_type_error_traceback( + self, + source_path: str, + module_name: str, + traceback_entry: Tuple[str, int], + *, + typ: RType, + src: str) -> None: + func = 'CPy_TypeErrorTraceback' + type_str = f'"{self.pretty_name(typ)}"' + return self._emit_traceback( + func, source_path, module_name, traceback_entry, type_str=type_str, src=src) + + def _emit_traceback(self, + func: str, + source_path: str, + module_name: str, + traceback_entry: Tuple[str, int], + type_str: str = '', + src: str = '') -> None: + globals_static = self.static_name('globals', module_name) + line = '%s("%s", "%s", %d, %s' % ( + func, + source_path.replace("\\", "\\\\"), + traceback_entry[0], + traceback_entry[1], + globals_static) + if type_str: + assert src + line += f', {type_str}, {src}' + line += ');' + self.emit_line(line) + if DEBUG_ERRORS: + self.emit_line('assert(PyErr_Occurred() != NULL && "failure w/o err!");') diff --git a/mypyc/codegen/emitfunc.py b/mypyc/codegen/emitfunc.py index 540c6b6464961..7b44b22d6cc11 100644 --- a/mypyc/codegen/emitfunc.py +++ b/mypyc/codegen/emitfunc.py @@ -6,7 +6,7 @@ from mypyc.common import ( REG_PREFIX, NATIVE_PREFIX, STATIC_PREFIX, TYPE_PREFIX, MODULE_PREFIX, ) -from mypyc.codegen.emit import Emitter +from mypyc.codegen.emit import Emitter, TracebackAndGotoHandler, DEBUG_ERRORS from mypyc.ir.ops import ( Op, OpVisitor, Goto, Branch, Return, Assign, Integer, LoadErrorValue, GetAttr, SetAttr, LoadStatic, InitStatic, TupleGet, TupleSet, Call, IncRef, DecRef, Box, Cast, Unbox, @@ -23,10 +23,6 @@ from mypyc.ir.pprint import generate_names_for_ir from mypyc.analysis.blockfreq import frequently_executed_blocks -# Whether to insert debug asserts for all error handling, to quickly -# catch errors propagating without exceptions set. -DEBUG_ERRORS = False - def native_function_type(fn: FuncIR, emitter: Emitter) -> str: args = ', '.join(emitter.ctype(arg.type) for arg in fn.args) or 'void' @@ -322,7 +318,7 @@ def visit_get_attr(self, op: GetAttr) -> None: and branch.traceback_entry is not None and not branch.negated): # Generate code for the following branch here to avoid - # redundant branches in the generate code. + # redundant branches in the generated code. self.emit_attribute_error(branch, cl.name, op.attr) self.emit_line('goto %s;' % self.label(branch.true)) merged_branch = branch @@ -485,8 +481,24 @@ def visit_box(self, op: Box) -> None: self.emitter.emit_box(self.reg(op.src), self.reg(op), op.src.type, can_borrow=True) def visit_cast(self, op: Cast) -> None: + branch = self.next_branch() + handler = None + if branch is not None: + if (branch.value is op + and branch.op == Branch.IS_ERROR + and branch.traceback_entry is not None + and not branch.negated + and branch.false is self.next_block): + # Generate code also for the following branch here to avoid + # redundant branches in the generated code. + handler = TracebackAndGotoHandler(self.label(branch.true), + self.source_path, + self.module_name, + branch.traceback_entry) + self.op_index += 1 + self.emitter.emit_cast(self.reg(op.src), self.reg(op), op.type, - src_type=op.src.type) + src_type=op.src.type, error=handler) def visit_unbox(self, op: Unbox) -> None: self.emitter.emit_unbox(self.reg(op.src), self.reg(op), op.type) @@ -647,14 +659,7 @@ def emit_declaration(self, line: str) -> None: def emit_traceback(self, op: Branch) -> None: if op.traceback_entry is not None: - globals_static = self.emitter.static_name('globals', self.module_name) - self.emit_line('CPy_AddTraceback("%s", "%s", %d, %s);' % ( - self.source_path.replace("\\", "\\\\"), - op.traceback_entry[0], - op.traceback_entry[1], - globals_static)) - if DEBUG_ERRORS: - self.emit_line('assert(PyErr_Occurred() != NULL && "failure w/o err!");') + self.emitter.emit_traceback(self.source_path, self.module_name, op.traceback_entry) def emit_attribute_error(self, op: Branch, class_name: str, attr: str) -> None: assert op.traceback_entry is not None diff --git a/mypyc/lib-rt/CPy.h b/mypyc/lib-rt/CPy.h index 0fdd6b0a27ccc..f482e09cbe796 100644 --- a/mypyc/lib-rt/CPy.h +++ b/mypyc/lib-rt/CPy.h @@ -500,6 +500,8 @@ void _CPy_GetExcInfo(PyObject **p_type, PyObject **p_value, PyObject **p_traceba void CPyError_OutOfMemory(void); void CPy_TypeError(const char *expected, PyObject *value); void CPy_AddTraceback(const char *filename, const char *funcname, int line, PyObject *globals); +void CPy_TypeErrorTraceback(const char *filename, const char *funcname, int line, + PyObject *globals, const char *expected, PyObject *value); void CPy_AttributeError(const char *filename, const char *funcname, const char *classname, const char *attrname, int line, PyObject *globals); diff --git a/mypyc/lib-rt/exc_ops.c b/mypyc/lib-rt/exc_ops.c index 1b679199bc0f6..b23a04b266570 100644 --- a/mypyc/lib-rt/exc_ops.c +++ b/mypyc/lib-rt/exc_ops.c @@ -233,6 +233,13 @@ void CPy_AddTraceback(const char *filename, const char *funcname, int line, PyOb _PyErr_ChainExceptions(exc, val, tb); } +CPy_NOINLINE +void CPy_TypeErrorTraceback(const char *filename, const char *funcname, int line, + PyObject *globals, const char *expected, PyObject *value) { + CPy_TypeError(expected, value); + CPy_AddTraceback(filename, funcname, line, globals); +} + void CPy_AttributeError(const char *filename, const char *funcname, const char *classname, const char *attrname, int line, PyObject *globals) { char buf[500]; diff --git a/mypyc/test-data/run-functions.test b/mypyc/test-data/run-functions.test index 77e9c9ed32f78..b6277c9e8ec41 100644 --- a/mypyc/test-data/run-functions.test +++ b/mypyc/test-data/run-functions.test @@ -1220,3 +1220,18 @@ def sub(s: str, f: Callable[[str], str]) -> str: ... def sub(s: bytes, f: Callable[[bytes], bytes]) -> bytes: ... def sub(s, f): return f(s) + +[case testContextManagerSpecialCase] +from typing import Generator, Callable, Iterator +from contextlib import contextmanager + +@contextmanager +def f() -> Iterator[None]: + yield + +def g() -> None: + a = [''] + with f(): + a.pop() + +g() diff --git a/mypyc/test/test_emitfunc.py b/mypyc/test/test_emitfunc.py index 0bb4dc68e8af3..fe47af2300d72 100644 --- a/mypyc/test/test_emitfunc.py +++ b/mypyc/test/test_emitfunc.py @@ -9,7 +9,7 @@ from mypyc.ir.ops import ( BasicBlock, Goto, Return, Integer, Assign, AssignMulti, IncRef, DecRef, Branch, Call, Unbox, Box, TupleGet, GetAttr, SetAttr, Op, Value, CallC, IntOp, LoadMem, - GetElementPtr, LoadAddress, ComparisonOp, SetMem, Register, Unreachable + GetElementPtr, LoadAddress, ComparisonOp, SetMem, Register, Unreachable, Cast ) from mypyc.ir.rtypes import ( RTuple, RInstance, RType, RArray, int_rprimitive, bool_rprimitive, list_rprimitive, @@ -312,7 +312,9 @@ def test_get_attr_merged(self) -> None: CPyTagged_INCREF(cpy_r_r0); goto CPyL9; """, - next_branch=branch) + next_branch=branch, + skip_next=True, + ) def test_set_attr(self) -> None: self.assert_emit( @@ -440,13 +442,110 @@ def test_long_signed(self) -> None: self.assert_emit(Assign(a, Integer(-(1 << 31), int64_rprimitive)), """cpy_r_a = -2147483648LL;""") + def test_cast_and_branch_merge(self) -> None: + op = Cast(self.r, dict_rprimitive, 1) + next_block = BasicBlock(9) + branch = Branch(op, BasicBlock(8), next_block, Branch.IS_ERROR) + branch.traceback_entry = ('foobar', 123) + self.assert_emit( + op, + """\ +if (likely(PyDict_Check(cpy_r_r))) + cpy_r_r0 = cpy_r_r; +else { + CPy_TypeErrorTraceback("prog.py", "foobar", 123, CPyStatic_prog___globals, "dict", cpy_r_r); + goto CPyL8; +} +""", + next_block=next_block, + next_branch=branch, + skip_next=True, + ) + + def test_cast_and_branch_no_merge_1(self) -> None: + op = Cast(self.r, dict_rprimitive, 1) + branch = Branch(op, BasicBlock(8), BasicBlock(9), Branch.IS_ERROR) + branch.traceback_entry = ('foobar', 123) + self.assert_emit( + op, + """\ + if (likely(PyDict_Check(cpy_r_r))) + cpy_r_r0 = cpy_r_r; + else { + CPy_TypeError("dict", cpy_r_r); + cpy_r_r0 = NULL; + } + """, + next_block=BasicBlock(10), + next_branch=branch, + skip_next=False, + ) + + def test_cast_and_branch_no_merge_2(self) -> None: + op = Cast(self.r, dict_rprimitive, 1) + next_block = BasicBlock(9) + branch = Branch(op, BasicBlock(8), next_block, Branch.IS_ERROR) + branch.negated = True + branch.traceback_entry = ('foobar', 123) + self.assert_emit( + op, + """\ + if (likely(PyDict_Check(cpy_r_r))) + cpy_r_r0 = cpy_r_r; + else { + CPy_TypeError("dict", cpy_r_r); + cpy_r_r0 = NULL; + } + """, + next_block=next_block, + next_branch=branch, + ) + + def test_cast_and_branch_no_merge_3(self) -> None: + op = Cast(self.r, dict_rprimitive, 1) + next_block = BasicBlock(9) + branch = Branch(op, BasicBlock(8), next_block, Branch.BOOL) + branch.traceback_entry = ('foobar', 123) + self.assert_emit( + op, + """\ + if (likely(PyDict_Check(cpy_r_r))) + cpy_r_r0 = cpy_r_r; + else { + CPy_TypeError("dict", cpy_r_r); + cpy_r_r0 = NULL; + } + """, + next_block=next_block, + next_branch=branch, + ) + + def test_cast_and_branch_no_merge_4(self) -> None: + op = Cast(self.r, dict_rprimitive, 1) + next_block = BasicBlock(9) + branch = Branch(op, BasicBlock(8), next_block, Branch.IS_ERROR) + self.assert_emit( + op, + """\ + if (likely(PyDict_Check(cpy_r_r))) + cpy_r_r0 = cpy_r_r; + else { + CPy_TypeError("dict", cpy_r_r); + cpy_r_r0 = NULL; + } + """, + next_block=next_block, + next_branch=branch, + ) + def assert_emit(self, op: Op, expected: str, next_block: Optional[BasicBlock] = None, *, rare: bool = False, - next_branch: Optional[Branch] = None) -> None: + next_branch: Optional[Branch] = None, + skip_next: bool = False) -> None: block = BasicBlock(0) block.ops.append(op) value_names = generate_names_for_ir(self.registers, [block]) @@ -476,6 +575,10 @@ def assert_emit(self, expected_lines = [line.strip(' ') for line in expected_lines] assert_string_arrays_equal(expected_lines, actual_lines, msg='Generated code unexpected') + if skip_next: + assert visitor.op_index == 1 + else: + assert visitor.op_index == 0 def assert_emit_binary_op(self, op: str, diff --git a/mypyc/test/test_emitwrapper.py b/mypyc/test/test_emitwrapper.py index de04123b7e55a..3eb1be37bfb68 100644 --- a/mypyc/test/test_emitwrapper.py +++ b/mypyc/test/test_emitwrapper.py @@ -22,7 +22,8 @@ def test_check_list(self) -> None: 'if (likely(PyList_Check(obj_x)))', ' arg_x = obj_x;', 'else {', - ' CPy_TypeError("list", obj_x); return NULL;', + ' CPy_TypeError("list", obj_x);', + ' return NULL;', '}', ], lines) From 291c39d5587d96b8f42fcebb3a6aa65e9eff1276 Mon Sep 17 00:00:00 2001 From: 97littleleaf11 <11172084+97littleleaf11@users.noreply.github.com> Date: Mon, 23 May 2022 23:53:39 +0800 Subject: [PATCH 321/377] Sync pythoncapi_compat.h (#12859) --- mypyc/lib-rt/pythoncapi_compat.h | 226 +++++++++++++++++++++---------- 1 file changed, 158 insertions(+), 68 deletions(-) diff --git a/mypyc/lib-rt/pythoncapi_compat.h b/mypyc/lib-rt/pythoncapi_compat.h index c9191a1d7a579..f22e92f7358f8 100644 --- a/mypyc/lib-rt/pythoncapi_compat.h +++ b/mypyc/lib-rt/pythoncapi_compat.h @@ -4,10 +4,10 @@ // Copyright Contributors to the pythoncapi_compat project. // // Homepage: -// https://github.com/pythoncapi/pythoncapi_compat +// https://github.com/python/pythoncapi_compat // // Latest version: -// https://raw.githubusercontent.com/pythoncapi/pythoncapi_compat/master/pythoncapi_compat.h +// https://raw.githubusercontent.com/python/pythoncapi_compat/master/pythoncapi_compat.h // // SPDX-License-Identifier: 0BSD @@ -26,27 +26,32 @@ extern "C" { // the inline keyword in C (only in C++): use __inline instead. #if (defined(_MSC_VER) && _MSC_VER < 1900 \ && !defined(__cplusplus) && !defined(inline)) -# define PYCAPI_COMPAT_INLINE(TYPE static __inline TYPE +# define PYCAPI_COMPAT_STATIC_INLINE(TYPE) static __inline TYPE #else # define PYCAPI_COMPAT_STATIC_INLINE(TYPE) static inline TYPE #endif -// C++ compatibility -#ifdef __cplusplus -# define PYCAPI_COMPAT_CAST(TYPE, EXPR) reinterpret_cast(EXPR) -# define PYCAPI_COMPAT_NULL nullptr -#else -# define PYCAPI_COMPAT_CAST(TYPE, EXPR) (TYPE)(EXPR) -# define PYCAPI_COMPAT_NULL NULL +// C++ compatibility: _Py_CAST() and _Py_NULL +#ifndef _Py_CAST +# ifdef __cplusplus +# define _Py_CAST(type, expr) \ + const_cast(reinterpret_cast(expr)) +# else +# define _Py_CAST(type, expr) ((type)(expr)) +# endif +#endif +#ifndef _Py_NULL +# ifdef __cplusplus +# define _Py_NULL nullptr +# else +# define _Py_NULL NULL +# endif #endif // Cast argument to PyObject* type. #ifndef _PyObject_CAST -# define _PyObject_CAST(op) PYCAPI_COMPAT_CAST(PyObject*, op) -#endif -#ifndef _PyObject_CAST_CONST -# define _PyObject_CAST_CONST(op) PYCAPI_COMPAT_CAST(const PyObject*, op) +# define _PyObject_CAST(op) _Py_CAST(PyObject*, op) #endif @@ -74,30 +79,6 @@ _Py_XNewRef(PyObject *obj) #endif -// See https://bugs.python.org/issue42522 -#if !defined(_Py_StealRef) -PYCAPI_COMPAT_STATIC_INLINE(PyObject*) -__Py_StealRef(PyObject *obj) -{ - Py_DECREF(obj); - return obj; -} -#define _Py_StealRef(obj) __Py_StealRef(_PyObject_CAST(obj)) -#endif - - -// See https://bugs.python.org/issue42522 -#if !defined(_Py_XStealRef) -PYCAPI_COMPAT_STATIC_INLINE(PyObject*) -__Py_XStealRef(PyObject *obj) -{ - Py_XDECREF(obj); - return obj; -} -#define _Py_XStealRef(obj) __Py_XStealRef(_PyObject_CAST(obj)) -#endif - - // bpo-39573 added Py_SET_REFCNT() to Python 3.9.0a4 #if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_REFCNT) PYCAPI_COMPAT_STATIC_INLINE(void) @@ -171,27 +152,28 @@ _Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size) PYCAPI_COMPAT_STATIC_INLINE(PyCodeObject*) PyFrame_GetCode(PyFrameObject *frame) { - assert(frame != PYCAPI_COMPAT_NULL); - assert(frame->f_code != PYCAPI_COMPAT_NULL); - return PYCAPI_COMPAT_CAST(PyCodeObject*, Py_NewRef(frame->f_code)); + assert(frame != _Py_NULL); + assert(frame->f_code != _Py_NULL); + return _Py_CAST(PyCodeObject*, Py_NewRef(frame->f_code)); } #endif PYCAPI_COMPAT_STATIC_INLINE(PyCodeObject*) _PyFrame_GetCodeBorrow(PyFrameObject *frame) { - return PYCAPI_COMPAT_CAST(PyCodeObject *, - _Py_StealRef(PyFrame_GetCode(frame))); + PyCodeObject *code = PyFrame_GetCode(frame); + Py_DECREF(code); + return code; } -// bpo-40421 added PyFrame_GetCode() to Python 3.9.0b1 +// bpo-40421 added PyFrame_GetBack() to Python 3.9.0b1 #if PY_VERSION_HEX < 0x030900B1 && !defined(PYPY_VERSION) PYCAPI_COMPAT_STATIC_INLINE(PyFrameObject*) PyFrame_GetBack(PyFrameObject *frame) { - assert(frame != PYCAPI_COMPAT_NULL); - return PYCAPI_COMPAT_CAST(PyFrameObject*, Py_XNewRef(frame->f_back)); + assert(frame != _Py_NULL); + return _Py_CAST(PyFrameObject*, Py_XNewRef(frame->f_back)); } #endif @@ -199,8 +181,66 @@ PyFrame_GetBack(PyFrameObject *frame) PYCAPI_COMPAT_STATIC_INLINE(PyFrameObject*) _PyFrame_GetBackBorrow(PyFrameObject *frame) { - return PYCAPI_COMPAT_CAST(PyFrameObject *, - _Py_XStealRef(PyFrame_GetBack(frame))); + PyFrameObject *back = PyFrame_GetBack(frame); + Py_XDECREF(back); + return back; +} +#endif + + +// bpo-40421 added PyFrame_GetLocals() to Python 3.11.0a7 +#if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION) +PYCAPI_COMPAT_STATIC_INLINE(PyObject*) +PyFrame_GetLocals(PyFrameObject *frame) +{ +#if PY_VERSION_HEX >= 0x030400B1 + if (PyFrame_FastToLocalsWithError(frame) < 0) { + return NULL; + } +#else + PyFrame_FastToLocals(frame); +#endif + return Py_NewRef(frame->f_locals); +} +#endif + + +// bpo-40421 added PyFrame_GetGlobals() to Python 3.11.0a7 +#if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION) +PYCAPI_COMPAT_STATIC_INLINE(PyObject*) +PyFrame_GetGlobals(PyFrameObject *frame) +{ + return Py_NewRef(frame->f_globals); +} +#endif + + +// bpo-40421 added PyFrame_GetBuiltins() to Python 3.11.0a7 +#if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION) +PYCAPI_COMPAT_STATIC_INLINE(PyObject*) +PyFrame_GetBuiltins(PyFrameObject *frame) +{ + return Py_NewRef(frame->f_builtins); +} +#endif + + +// bpo-40421 added PyFrame_GetLasti() to Python 3.11.0b1 +#if PY_VERSION_HEX < 0x030B00B1 && !defined(PYPY_VERSION) +PYCAPI_COMPAT_STATIC_INLINE(int) +PyFrame_GetLasti(PyFrameObject *frame) +{ +#if PY_VERSION_HEX >= 0x030A00A7 + // bpo-27129: Since Python 3.10.0a7, f_lasti is an instruction offset, + // not a bytes offset anymore. Python uses 16-bit "wordcode" (2 bytes) + // instructions. + if (frame->f_lasti < 0) { + return -1; + } + return frame->f_lasti * 2; +#else + return frame->f_lasti; +#endif } #endif @@ -210,7 +250,7 @@ _PyFrame_GetBackBorrow(PyFrameObject *frame) PYCAPI_COMPAT_STATIC_INLINE(PyInterpreterState *) PyThreadState_GetInterpreter(PyThreadState *tstate) { - assert(tstate != PYCAPI_COMPAT_NULL); + assert(tstate != _Py_NULL); return tstate->interp; } #endif @@ -221,8 +261,8 @@ PyThreadState_GetInterpreter(PyThreadState *tstate) PYCAPI_COMPAT_STATIC_INLINE(PyFrameObject*) PyThreadState_GetFrame(PyThreadState *tstate) { - assert(tstate != PYCAPI_COMPAT_NULL); - return PYCAPI_COMPAT_CAST(PyFrameObject *, Py_XNewRef(tstate->frame)); + assert(tstate != _Py_NULL); + return _Py_CAST(PyFrameObject *, Py_XNewRef(tstate->frame)); } #endif @@ -230,8 +270,9 @@ PyThreadState_GetFrame(PyThreadState *tstate) PYCAPI_COMPAT_STATIC_INLINE(PyFrameObject*) _PyThreadState_GetFrameBorrow(PyThreadState *tstate) { - return PYCAPI_COMPAT_CAST(PyFrameObject*, - _Py_XStealRef(PyThreadState_GetFrame(tstate))); + PyFrameObject *frame = PyThreadState_GetFrame(tstate); + Py_XDECREF(frame); + return frame; } #endif @@ -245,11 +286,11 @@ PyInterpreterState_Get(void) PyInterpreterState *interp; tstate = PyThreadState_GET(); - if (tstate == PYCAPI_COMPAT_NULL) { + if (tstate == _Py_NULL) { Py_FatalError("GIL released (tstate is NULL)"); } interp = tstate->interp; - if (interp == PYCAPI_COMPAT_NULL) { + if (interp == _Py_NULL) { Py_FatalError("no current interpreter"); } return interp; @@ -262,7 +303,7 @@ PyInterpreterState_Get(void) PYCAPI_COMPAT_STATIC_INLINE(uint64_t) PyThreadState_GetID(PyThreadState *tstate) { - assert(tstate != PYCAPI_COMPAT_NULL); + assert(tstate != _Py_NULL); return tstate->id; } #endif @@ -286,8 +327,8 @@ PyThreadState_EnterTracing(PyThreadState *tstate) PYCAPI_COMPAT_STATIC_INLINE(void) PyThreadState_LeaveTracing(PyThreadState *tstate) { - int use_tracing = (tstate->c_tracefunc != PYCAPI_COMPAT_NULL - || tstate->c_profilefunc != PYCAPI_COMPAT_NULL); + int use_tracing = (tstate->c_tracefunc != _Py_NULL + || tstate->c_profilefunc != _Py_NULL); tstate->tracing--; #if PY_VERSION_HEX >= 0x030A00A1 tstate->cframe->use_tracing = use_tracing; @@ -322,11 +363,11 @@ PyObject_CallOneArg(PyObject *func, PyObject *arg) // bpo-1635741 added PyModule_AddObjectRef() to Python 3.10.0a3 #if PY_VERSION_HEX < 0x030A00A3 PYCAPI_COMPAT_STATIC_INLINE(int) -PyModule_AddObjectRef(PyObject *mod, const char *name, PyObject *value) +PyModule_AddObjectRef(PyObject *module, const char *name, PyObject *value) { int res; Py_XINCREF(value); - res = PyModule_AddObject(mod, name, value); + res = PyModule_AddObject(module, name, value); if (res < 0) { Py_XDECREF(value); } @@ -338,7 +379,7 @@ PyModule_AddObjectRef(PyObject *mod, const char *name, PyObject *value) // bpo-40024 added PyModule_AddType() to Python 3.9.0a5 #if PY_VERSION_HEX < 0x030900A5 PYCAPI_COMPAT_STATIC_INLINE(int) -PyModule_AddType(PyObject *mod, PyTypeObject *type) +PyModule_AddType(PyObject *module, PyTypeObject *type) { const char *name, *dot; @@ -348,13 +389,13 @@ PyModule_AddType(PyObject *mod, PyTypeObject *type) // inline _PyType_Name() name = type->tp_name; - assert(name != PYCAPI_COMPAT_NULL); + assert(name != _Py_NULL); dot = strrchr(name, '.'); - if (dot != PYCAPI_COMPAT_NULL) { + if (dot != _Py_NULL) { name = dot + 1; } - return PyModule_AddObjectRef(mod, name, _PyObject_CAST(type)); + return PyModule_AddObjectRef(module, name, _PyObject_CAST(type)); } #endif @@ -375,7 +416,7 @@ PyObject_GC_IsTracked(PyObject* obj) PYCAPI_COMPAT_STATIC_INLINE(int) PyObject_GC_IsFinalized(PyObject *obj) { - PyGC_Head *gc = PYCAPI_COMPAT_CAST(PyGC_Head *, obj) - 1; + PyGC_Head *gc = _Py_CAST(PyGC_Head*, obj) - 1; return (PyObject_IS_GC(obj) && _PyGCHead_FINALIZED(gc)); } #endif @@ -384,10 +425,59 @@ PyObject_GC_IsFinalized(PyObject *obj) // bpo-39573 added Py_IS_TYPE() to Python 3.9.0a4 #if PY_VERSION_HEX < 0x030900A4 && !defined(Py_IS_TYPE) PYCAPI_COMPAT_STATIC_INLINE(int) -_Py_IS_TYPE(const PyObject *ob, const PyTypeObject *type) { - return ob->ob_type == type; +_Py_IS_TYPE(PyObject *ob, PyTypeObject *type) { + return Py_TYPE(ob) == type; +} +#define Py_IS_TYPE(ob, type) _Py_IS_TYPE(_PyObject_CAST(ob), type) +#endif + + +// bpo-46906 added PyFloat_Pack2() and PyFloat_Unpack2() to Python 3.11a7. +// bpo-11734 added _PyFloat_Pack2() and _PyFloat_Unpack2() to Python 3.6.0b1. +// Python 3.11a2 moved _PyFloat_Pack2() and _PyFloat_Unpack2() to the internal +// C API: Python 3.11a2-3.11a6 versions are not supported. +#if 0x030600B1 <= PY_VERSION_HEX && PY_VERSION_HEX <= 0x030B00A1 && !defined(PYPY_VERSION) +PYCAPI_COMPAT_STATIC_INLINE(int) +PyFloat_Pack2(double x, char *p, int le) +{ return _PyFloat_Pack2(x, (unsigned char*)p, le); } + +PYCAPI_COMPAT_STATIC_INLINE(double) +PyFloat_Unpack2(const char *p, int le) +{ return _PyFloat_Unpack2((const unsigned char *)p, le); } +#endif + + +// bpo-46906 added PyFloat_Pack4(), PyFloat_Pack8(), PyFloat_Unpack4() and +// PyFloat_Unpack8() to Python 3.11a7. +// Python 3.11a2 moved _PyFloat_Pack4(), _PyFloat_Pack8(), _PyFloat_Unpack4() +// and _PyFloat_Unpack8() to the internal C API: Python 3.11a2-3.11a6 versions +// are not supported. +#if PY_VERSION_HEX <= 0x030B00A1 && !defined(PYPY_VERSION) +PYCAPI_COMPAT_STATIC_INLINE(int) +PyFloat_Pack4(double x, char *p, int le) +{ return _PyFloat_Pack4(x, (unsigned char*)p, le); } + +PYCAPI_COMPAT_STATIC_INLINE(int) +PyFloat_Pack8(double x, char *p, int le) +{ return _PyFloat_Pack8(x, (unsigned char*)p, le); } + +PYCAPI_COMPAT_STATIC_INLINE(double) +PyFloat_Unpack4(const char *p, int le) +{ return _PyFloat_Unpack4((const unsigned char *)p, le); } + +PYCAPI_COMPAT_STATIC_INLINE(double) +PyFloat_Unpack8(const char *p, int le) +{ return _PyFloat_Unpack8((const unsigned char *)p, le); } +#endif + + +// gh-92154 added PyCode_GetCode() to Python 3.11.0b1 +#if PY_VERSION_HEX < 0x030B00B1 && !defined(PYPY_VERSION) +PYCAPI_COMPAT_STATIC_INLINE(PyObject*) +PyCode_GetCode(PyCodeObject *code) +{ + return Py_NewRef(code->co_code); } -#define Py_IS_TYPE(ob, type) _Py_IS_TYPE(_PyObject_CAST_CONST(ob), type) #endif From 24ef8d06a1edad9074990624dd6d955a9e0c0561 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Mon, 23 May 2022 09:18:55 -0700 Subject: [PATCH 322/377] Friendlier errors for PEP 612 (#12832) Co-authored-by: hauntsaninja <> --- mypy/typeanal.py | 14 +++++++++++--- test-data/unit/check-parameter-specification.test | 3 ++- test-data/unit/semanal-errors.test | 3 ++- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/mypy/typeanal.py b/mypy/typeanal.py index 98e37bd0aa400..bd0f684653b2f 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -944,9 +944,13 @@ def analyze_callable_type(self, t: UnboundType) -> Type: ) if maybe_ret is None: # Callable[?, RET] (where ? is something invalid) - # TODO(PEP612): change error to mention paramspec, once we actually have some - # support for it - self.fail('The first argument to Callable must be a list of types or "..."', t) + self.fail( + 'The first argument to Callable must be a ' + 'list of types, parameter specification, or "..."', t) + self.note( + 'See https://mypy.readthedocs.io/en/stable/kinds_of_types.html#callable-types-and-lambdas', # noqa: E501 + t + ) return AnyType(TypeOfAny.from_error) ret = maybe_ret else: @@ -1180,6 +1184,10 @@ def anal_type(self, t: Type, nested: bool = True, *, allow_param_spec: bool = Fa and analyzed.flavor == ParamSpecFlavor.BARE): if analyzed.prefix.arg_types: self.fail('Invalid location for Concatenate', t) + self.note( + 'You can use Concatenate as the first argument to Callable', + t + ) else: self.fail(f'Invalid location for ParamSpec "{analyzed.name}"', t) self.note( diff --git a/test-data/unit/check-parameter-specification.test b/test-data/unit/check-parameter-specification.test index 28b08aa7122f5..4dae329782637 100644 --- a/test-data/unit/check-parameter-specification.test +++ b/test-data/unit/check-parameter-specification.test @@ -25,7 +25,8 @@ def foo1(x: Callable[P, int]) -> Callable[P, str]: ... def foo2(x: P) -> P: ... # E: Invalid location for ParamSpec "P" \ # N: You can use ParamSpec as the first argument to Callable, e.g., 'Callable[P, int]' -def foo3(x: Concatenate[int, P]) -> int: ... # E: Invalid location for Concatenate +def foo3(x: Concatenate[int, P]) -> int: ... # E: Invalid location for Concatenate \ + # N: You can use Concatenate as the first argument to Callable def foo4(x: List[P]) -> None: ... # E: Invalid location for ParamSpec "P" \ # N: You can use ParamSpec as the first argument to Callable, e.g., 'Callable[P, int]' diff --git a/test-data/unit/semanal-errors.test b/test-data/unit/semanal-errors.test index 14bc24f03a7b2..a1ff4ec1c3e71 100644 --- a/test-data/unit/semanal-errors.test +++ b/test-data/unit/semanal-errors.test @@ -867,7 +867,8 @@ x = None # type: Callable[int, str] y = None # type: Callable[int] z = None # type: Callable[int, int, int] [out] -main:2: error: The first argument to Callable must be a list of types or "..." +main:2: error: The first argument to Callable must be a list of types, parameter specification, or "..." +main:2: note: See https://mypy.readthedocs.io/en/stable/kinds_of_types.html#callable-types-and-lambdas main:3: error: Please use "Callable[[], ]" or "Callable" main:4: error: Please use "Callable[[], ]" or "Callable" From 405efd23e483c214cb1293700ef2008aacf8e2ca Mon Sep 17 00:00:00 2001 From: 97littleleaf11 <11172084+97littleleaf11@users.noreply.github.com> Date: Wed, 25 May 2022 20:37:58 +0800 Subject: [PATCH 323/377] [mypyc] Use PyObject_CallNoArgs and PyObject_CallOneArg (#12862) Use PyObject_CallNoArgs and PyObject_CallOneArg to replace PyObject_CallFunctionObjArgs in lib-rt, since the new API costs less memory according to python/cpython#13890 (comment) Also remove the macro in pythonsupport.h since the two API are already covered by pythoncapi_compat.h. --- mypyc/lib-rt/exc_ops.c | 2 +- mypyc/lib-rt/misc_ops.c | 4 ++-- mypyc/lib-rt/pythonsupport.h | 8 ++------ 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/mypyc/lib-rt/exc_ops.c b/mypyc/lib-rt/exc_ops.c index b23a04b266570..8c69664ae8786 100644 --- a/mypyc/lib-rt/exc_ops.c +++ b/mypyc/lib-rt/exc_ops.c @@ -7,7 +7,7 @@ void CPy_Raise(PyObject *exc) { if (PyObject_IsInstance(exc, (PyObject *)&PyType_Type)) { - PyObject *obj = PyObject_CallFunctionObjArgs(exc, NULL); + PyObject *obj = PyObject_CallNoArgs(exc); if (!obj) return; PyErr_SetObject(exc, obj); diff --git a/mypyc/lib-rt/misc_ops.c b/mypyc/lib-rt/misc_ops.c index fea38eca9d901..b0a40bbd49316 100644 --- a/mypyc/lib-rt/misc_ops.c +++ b/mypyc/lib-rt/misc_ops.c @@ -54,7 +54,7 @@ int CPy_YieldFromErrorHandle(PyObject *iter, PyObject **outp) if (PyErr_GivenExceptionMatches(exc_type, PyExc_GeneratorExit)) { _m = _PyObject_GetAttrId(iter, &PyId_close); if (_m) { - res = PyObject_CallFunctionObjArgs(_m, NULL); + res = PyObject_CallNoArgs(_m); Py_DECREF(_m); if (!res) return 2; @@ -360,7 +360,7 @@ CPyDataclass_SleightOfHand(PyObject *dataclass_dec, PyObject *tp, } /* Run the @dataclass descriptor */ - res = PyObject_CallFunctionObjArgs(dataclass_dec, tp, NULL); + res = PyObject_CallOneArg(dataclass_dec, tp); if (!res) { goto fail; } diff --git a/mypyc/lib-rt/pythonsupport.h b/mypyc/lib-rt/pythonsupport.h index c4091dada7fdc..09ef9757dd764 100644 --- a/mypyc/lib-rt/pythonsupport.h +++ b/mypyc/lib-rt/pythonsupport.h @@ -350,7 +350,7 @@ CPyGen_SetStopIterationValue(PyObject *value) return 0; } /* Construct an exception instance manually with - * PyObject_CallFunctionObjArgs and pass it to PyErr_SetObject. + * PyObject_CallOneArg and pass it to PyErr_SetObject. * * We do this to handle a situation when "value" is a tuple, in which * case PyErr_SetObject would set the value of StopIteration to @@ -358,7 +358,7 @@ CPyGen_SetStopIterationValue(PyObject *value) * * (See PyErr_SetObject/_PyErr_CreateException code for details.) */ - e = PyObject_CallFunctionObjArgs(PyExc_StopIteration, value, NULL); + e = PyObject_CallOneArg(PyExc_StopIteration, value); if (e == NULL) { return -1; } @@ -410,10 +410,6 @@ _CPyObject_HasAttrId(PyObject *v, _Py_Identifier *name) { _PyObject_CallMethodIdObjArgs((self), (name), NULL) #define _PyObject_CallMethodIdOneArg(self, name, arg) \ _PyObject_CallMethodIdObjArgs((self), (name), (arg), NULL) -#define PyObject_CallNoArgs(callable) \ - PyObject_CallFunctionObjArgs((callable), NULL) -#define PyObject_CallOneArg(callable, arg) \ - PyObject_CallFunctionObjArgs((callable), (arg), NULL) #endif #endif From 87e73feb0ac85d9d0d55ad4e367876d0c7fbe0a2 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Wed, 25 May 2022 10:11:42 -0700 Subject: [PATCH 324/377] Disallow assignments to awaited coroutines that do not return (#12853) Resolves #12837 Co-authored-by: hauntsaninja <> --- mypy/checkexpr.py | 11 ++++++++--- test-data/unit/pythoneval-asyncio.test | 5 ++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 4cc91f9cc123b..b9c657e83e636 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -3987,6 +3987,8 @@ def accept(self, typ = self.visit_yield_from_expr(node, allow_none_return=True) elif allow_none_return and isinstance(node, ConditionalExpr): typ = self.visit_conditional_expr(node, allow_none_return=True) + elif allow_none_return and isinstance(node, AwaitExpr): + typ = self.visit_await_expr(node, allow_none_return=True) else: typ = node.accept(self) except Exception as err: @@ -4099,15 +4101,18 @@ def visit_yield_expr(self, e: YieldExpr) -> Type: 'actual type', 'expected type') return self.chk.get_generator_receive_type(return_type, False) - def visit_await_expr(self, e: AwaitExpr) -> Type: + def visit_await_expr(self, e: AwaitExpr, allow_none_return: bool = False) -> Type: expected_type = self.type_context[-1] if expected_type is not None: expected_type = self.chk.named_generic_type('typing.Awaitable', [expected_type]) actual_type = get_proper_type(self.accept(e.expr, expected_type)) if isinstance(actual_type, AnyType): return AnyType(TypeOfAny.from_another_any, source_any=actual_type) - return self.check_awaitable_expr(actual_type, e, - message_registry.INCOMPATIBLE_TYPES_IN_AWAIT) + ret = self.check_awaitable_expr(actual_type, e, + message_registry.INCOMPATIBLE_TYPES_IN_AWAIT) + if not allow_none_return and isinstance(get_proper_type(ret), NoneType): + self.chk.msg.does_not_return_value(None, e) + return ret def check_awaitable_expr(self, t: Type, ctx: Context, msg: Union[str, ErrorMessage]) -> Type: """Check the argument to `await` and extract the type of value. diff --git a/test-data/unit/pythoneval-asyncio.test b/test-data/unit/pythoneval-asyncio.test index 11a61756a8246..72e4bc9cc9dd0 100644 --- a/test-data/unit/pythoneval-asyncio.test +++ b/test-data/unit/pythoneval-asyncio.test @@ -242,8 +242,7 @@ Outside 42 -- Errors -[case testErrorAssigningCoroutineThatDontReturn-xfail] -# https://github.com/python/mypy/issues/12837 +[case testErrorAssigningCoroutineThatDontReturn] from typing import Any import asyncio from asyncio import Future @@ -262,7 +261,7 @@ try: finally: loop.close() [out] -_program.py:13: error: Function does not return a value +_program.py:11: error: Function does not return a value [case testErrorReturnIsNotTheSameType] from typing import Any From 4024748bff83237dbbe7da4750fe4c6e993af235 Mon Sep 17 00:00:00 2001 From: pranavrajpal <78008260+pranavrajpal@users.noreply.github.com> Date: Wed, 25 May 2022 10:14:36 -0700 Subject: [PATCH 325/377] [mypyc] Clean up support for debugging mypyc runtests (#12849) Add a --mypyc-debug option to pytest that compiles a test normally and then runs the resulting binary in the debugger specified. The support for debugging runtests was already somewhat there. This just cleans it up and adds a pytest option to use it. --- mypy/test/data.py | 13 +++++++++++++ mypyc/test/test_run.py | 22 +++++++++++----------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/mypy/test/data.py b/mypy/test/data.py index de7e38693f237..18d25fc74c04b 100644 --- a/mypy/test/data.py +++ b/mypy/test/data.py @@ -11,11 +11,17 @@ import pytest from typing import List, Tuple, Set, Optional, Iterator, Any, Dict, NamedTuple, Union, Pattern +from typing_extensions import Final from mypy.test.config import test_data_prefix, test_temp_dir, PREFIX root_dir = os.path.normpath(PREFIX) +# Debuggers that we support for debugging mypyc run tests +# implementation of using each of these debuggers is in test_run.py +# TODO: support more debuggers +SUPPORTED_DEBUGGERS: Final = ["gdb", "lldb"] + # File modify/create operation: copy module contents from source_path. class UpdateFile(NamedTuple): @@ -549,6 +555,13 @@ def pytest_addoption(parser: Any) -> None: help='Set the verbose flag when creating mypy Options') group.addoption('--mypyc-showc', action='store_true', default=False, help='Display C code on mypyc test failures') + group.addoption( + "--mypyc-debug", + default=None, + dest="debugger", + choices=SUPPORTED_DEBUGGERS, + help="Run the first mypyc run test with the specified debugger", + ) # This function name is special to pytest. See diff --git a/mypyc/test/test_run.py b/mypyc/test/test_run.py index 1eafd2d4c8033..4013c30c8bc83 100644 --- a/mypyc/test/test_run.py +++ b/mypyc/test/test_run.py @@ -3,7 +3,6 @@ import ast import glob import os.path -import platform import re import subprocess import contextlib @@ -272,19 +271,20 @@ def run_case_step(self, testcase: DataDrivenTestCase, incremental_step: int) -> env = os.environ.copy() env['MYPYC_RUN_BENCH'] = '1' if bench else '0' - # XXX: This is an ugly hack. - if 'MYPYC_RUN_GDB' in os.environ: - if platform.system() == 'Darwin': + debugger = testcase.config.getoption('debugger') + if debugger: + if debugger == 'lldb': subprocess.check_call(['lldb', '--', sys.executable, driver_path], env=env) - assert False, ("Test can't pass in lldb mode. (And remember to pass -s to " - "pytest)") - elif platform.system() == 'Linux': + elif debugger == 'gdb': subprocess.check_call(['gdb', '--args', sys.executable, driver_path], env=env) - assert False, ("Test can't pass in gdb mode. (And remember to pass -s to " - "pytest)") else: - assert False, 'Unsupported OS' - + assert False, 'Unsupported debugger' + # TODO: find a way to automatically disable capturing + # stdin/stdout when in debugging mode + assert False, ( + "Test can't pass in debugging mode. " + "(Make sure to pass -s to pytest to interact with the debugger)" + ) proc = subprocess.Popen([sys.executable, driver_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env) output = proc.communicate()[0].decode('utf8') From b55dcf534c07eb4d25bbbf7f5ba67f5edf5d0a92 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Wed, 25 May 2022 22:43:13 -0700 Subject: [PATCH 326/377] stubtest: check typevar and paramspec (#12851) Came up in #12825 --- mypy/stubtest.py | 30 ++++++++++++++++++++++++++++-- mypy/test/teststubtest.py | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 4 deletions(-) diff --git a/mypy/stubtest.py b/mypy/stubtest.py index c1bdcb3437a45..6406921fbb8ab 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -12,6 +12,8 @@ import re import sys import types +import typing +import typing_extensions import warnings from functools import singledispatch from pathlib import Path @@ -867,8 +869,32 @@ def verify_overloadedfuncdef( def verify_typevarexpr( stub: nodes.TypeVarExpr, runtime: MaybeMissing[Any], object_path: List[str] ) -> Iterator[Error]: - if False: - yield None + if isinstance(runtime, Missing): + # We seem to insert these typevars into NamedTuple stubs, but they + # don't exist at runtime. Just ignore! + if stub.name == "_NT": + return + yield Error(object_path, "is not present at runtime", stub, runtime) + return + if not isinstance(runtime, TypeVar): + yield Error(object_path, "is not a TypeVar", stub, runtime) + return + + +@verify.register(nodes.ParamSpecExpr) +def verify_paramspecexpr( + stub: nodes.ParamSpecExpr, runtime: MaybeMissing[Any], object_path: List[str] +) -> Iterator[Error]: + if isinstance(runtime, Missing): + yield Error(object_path, "is not present at runtime", stub, runtime) + return + maybe_paramspec_types = ( + getattr(typing, "ParamSpec", None), getattr(typing_extensions, "ParamSpec", None) + ) + paramspec_types = tuple([t for t in maybe_paramspec_types if t is not None]) + if not paramspec_types or not isinstance(runtime, paramspec_types): + yield Error(object_path, "is not a ParamSpec", stub, runtime) + return def _verify_readonly_property(stub: nodes.Decorator, runtime: Any) -> Iterator[str]: diff --git a/mypy/test/teststubtest.py b/mypy/test/teststubtest.py index 50b3f90c8fad9..6ba07fc50cfd5 100644 --- a/mypy/test/teststubtest.py +++ b/mypy/test/teststubtest.py @@ -48,6 +48,9 @@ def __getitem__(self, typeargs: Any) -> object: ... class TypeVar: def __init__(self, name, covariant: bool = ..., contravariant: bool = ...) -> None: ... +class ParamSpec: + def __init__(self, name: str) -> None: ... + _T = TypeVar("_T") _T_co = TypeVar("_T_co", covariant=True) _K = TypeVar("_K") @@ -329,8 +332,8 @@ def test_default_value(self) -> Iterator[Case]: yield Case( stub=""" from typing import TypeVar - T = TypeVar("T", bound=str) - def f6(text: T = ...) -> None: ... + _T = TypeVar("_T", bound=str) + def f6(text: _T = ...) -> None: ... """, runtime="def f6(text = None): pass", error="f6", @@ -1042,6 +1045,33 @@ def foo(self, x: int, y: bytes = ...) -> str: ... error="X.__init__" ) + @collect_cases + def test_type_var(self) -> Iterator[Case]: + yield Case( + stub="from typing import TypeVar", runtime="from typing import TypeVar", error=None + ) + yield Case( + stub="A = TypeVar('A')", + runtime="A = TypeVar('A')", + error=None, + ) + yield Case( + stub="B = TypeVar('B')", + runtime="B = 5", + error="B", + ) + if sys.version_info >= (3, 10): + yield Case( + stub="from typing import ParamSpec", + runtime="from typing import ParamSpec", + error=None + ) + yield Case( + stub="C = ParamSpec('C')", + runtime="C = ParamSpec('C')", + error=None, + ) + def remove_color_code(s: str) -> str: return re.sub("\\x1b.*?m", "", s) # this works! From 0054046c8c147a5190769bde21eb08615c16038e Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 26 May 2022 14:43:40 +0100 Subject: [PATCH 327/377] Fix crash with nested attrs class (#12872) Fixes #12868. --- mypy/semanal.py | 4 +++- test-data/unit/check-attr.test | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index a49e7c23edf57..e00913a8cde46 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4505,7 +4505,9 @@ class C: """ # TODO: Forward reference to name imported in class body is not # caught. - assert self.statement # we are at class scope + if self.statement is None: + # Assume it's fine -- don't have enough context to check + return True return (node is None or self.is_textually_before_statement(node) or not self.is_defined_in_current_module(node.fullname) diff --git a/test-data/unit/check-attr.test b/test-data/unit/check-attr.test index fdb0da7e0fce4..021be93bdd21d 100644 --- a/test-data/unit/check-attr.test +++ b/test-data/unit/check-attr.test @@ -1734,3 +1734,18 @@ class C: # E: Unsupported converter, only named functions and types are currently supported ) [builtins fixtures/dict.pyi] + +[case testAttrsNestedClass] +from typing import List +import attr + +@attr.s +class C: + @attr.s + class D: + pass + x = attr.ib(type=List[D]) + +c = C(x=[C.D()]) +reveal_type(c.x) # N: Revealed type is "builtins.list[__main__.C.D]" +[builtins fixtures/list.pyi] From d3ef642a0c2cc5b4784c2c632cee9bdcfa10e8b2 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 27 May 2022 10:12:56 +0100 Subject: [PATCH 328/377] [mypyc] Replace integer floor division by a power of two with a shift (#12870) In a microbenchmark right shift was a bit faster. --- mypyc/irbuild/expression.py | 13 +++++++++++ mypyc/test-data/irbuild-int.test | 38 +++++++++++++++++++++++++++++++ mypyc/test-data/run-integers.test | 18 +++++++++++++++ 3 files changed, 69 insertions(+) diff --git a/mypyc/irbuild/expression.py b/mypyc/irbuild/expression.py index 76e4db62a4656..49a5dd38089a5 100644 --- a/mypyc/irbuild/expression.py +++ b/mypyc/irbuild/expression.py @@ -408,6 +408,8 @@ def transform_op_expr(builder: IRBuilder, expr: OpExpr) -> Value: # Special case some int ops to allow borrowing operands. if (is_int_rprimitive(builder.node_type(expr.left)) and is_int_rprimitive(builder.node_type(expr.right))): + if expr.op == '//': + expr = try_optimize_int_floor_divide(expr) if expr.op in int_borrow_friendly_op: borrow_left = is_borrow_friendly_expr(builder, expr.right) left = builder.accept(expr.left, can_borrow=borrow_left) @@ -419,6 +421,17 @@ def transform_op_expr(builder: IRBuilder, expr: OpExpr) -> Value: ) +def try_optimize_int_floor_divide(expr: OpExpr) -> OpExpr: + """Replace // with a power of two with a right shift, if possible.""" + if not isinstance(expr.right, IntExpr): + return expr + divisor = expr.right.value + shift = divisor.bit_length() - 1 + if 0 < shift < 28 and divisor == (1 << shift): + return OpExpr('>>', expr.left, IntExpr(shift)) + return expr + + def transform_index_expr(builder: IRBuilder, expr: IndexExpr) -> Value: index = expr.index base_type = builder.node_type(expr.base) diff --git a/mypyc/test-data/irbuild-int.test b/mypyc/test-data/irbuild-int.test index ea943eef2c693..8bf43cfa4923d 100644 --- a/mypyc/test-data/irbuild-int.test +++ b/mypyc/test-data/irbuild-int.test @@ -117,3 +117,41 @@ L5: r8 = x L6: return r8 + +[case testIntFloorDivideByPowerOfTwo] +def divby1(x: int) -> int: + return x // 1 +def divby2(x: int) -> int: + return x // 2 +def divby3(x: int) -> int: + return x // 3 +def divby4(x: int) -> int: + return x // 4 +def divby8(x: int) -> int: + return x // 8 +[out] +def divby1(x): + x, r0 :: int +L0: + r0 = CPyTagged_FloorDivide(x, 2) + return r0 +def divby2(x): + x, r0 :: int +L0: + r0 = CPyTagged_Rshift(x, 2) + return r0 +def divby3(x): + x, r0 :: int +L0: + r0 = CPyTagged_FloorDivide(x, 6) + return r0 +def divby4(x): + x, r0 :: int +L0: + r0 = CPyTagged_Rshift(x, 4) + return r0 +def divby8(x): + x, r0 :: int +L0: + r0 = CPyTagged_Rshift(x, 6) + return r0 diff --git a/mypyc/test-data/run-integers.test b/mypyc/test-data/run-integers.test index b9668d6dec9f7..74e7cd6b8fb74 100644 --- a/mypyc/test-data/run-integers.test +++ b/mypyc/test-data/run-integers.test @@ -172,6 +172,8 @@ assert test_isinstance_int_and_not_bool(True) == False assert test_isinstance_int_and_not_bool(1) == True [case testIntOps] +from typing import Any + def check_and(x: int, y: int) -> None: # eval() can be trusted to calculate expected result expected = eval('{} & {}'.format(x, y)) @@ -428,6 +430,22 @@ def test_constant_fold() -> None: n64 = -(1 << 64) + int() assert n64 == -(1 << 64) +def div_by_2(x: int) -> int: + return x // 2 + +def div_by_3(x: int) -> int: + return x // 3 + +def div_by_4(x: int) -> int: + return x // 4 + +def test_floor_divide_by_literal() -> None: + for i in range(-100, 100): + i_boxed: Any = i + assert div_by_2(i) == i_boxed // int('2') + assert div_by_3(i) == i_boxed // int('3') + assert div_by_4(i) == i_boxed // int('4') + [case testIntMinMax] def test_int_min_max() -> None: x: int = 200 From 07edc92b71918f8975357b98c2df96a7a2f2aead Mon Sep 17 00:00:00 2001 From: Erik Kemperman Date: Fri, 27 May 2022 11:22:14 +0200 Subject: [PATCH 329/377] Put filelock around PEP 561 tests (fixes #12615) (#12857) Fixes #12615. As discussed in the linked issue, this PR would put a filesystem-based lock around the pip install steps of the suite of PEP561 testcases, to address race conditions. It introduces a test-dependency on tox-dev/py-filelock. I used 3.0.0 as a lower bound, simply because that's what the tox version mentioned in tox.ini specifies as its lower bound. However from the release history it seems that Python 3.6 support was dropped in 3.4.2, hence the second line in the requirements. I ended up just adding the location of the lock file to .gitignore -- I guess it would be possible to try and remove it after the suite has run, e.g. with atexit.register, but I didn't want to make this complicated. --- .gitignore | 1 + mypy/test/config.py | 9 +++++++++ mypy/test/testpep561.py | 17 +++++++++++------ runtests.py | 6 +++++- test-requirements.txt | 2 ++ 5 files changed, 28 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 3c0f60cfae4f2..b2306b96036f2 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ venv/ .mypy_cache/ .incremental_checker_cache.json .cache +test-data/packages/.pip_lock dmypy.json .dmypy.json diff --git a/mypy/test/config.py b/mypy/test/config.py index d76eadd72ed81..0c2dfc9a21a9f 100644 --- a/mypy/test/config.py +++ b/mypy/test/config.py @@ -15,3 +15,12 @@ # This is *within* the tempfile.TemporaryDirectory that is chroot'ed per testcase. # It is also hard-coded in numerous places, so don't change it. test_temp_dir = 'tmp' + +# The PEP 561 tests do a bunch of pip installs which, even though they operate +# on distinct temporary virtual environments, run into race conditions on shared +# file-system state. To make this work reliably in parallel mode, we'll use a +# FileLock courtesy of the tox-dev/py-filelock package. +# Ref. https://github.com/python/mypy/issues/12615 +# Ref. mypy/test/testpep561.py +pip_lock = os.path.join(package_path, '.pip_lock') +pip_timeout = 60 diff --git a/mypy/test/testpep561.py b/mypy/test/testpep561.py index a49c7e8e58746..e5c79762d2c2a 100644 --- a/mypy/test/testpep561.py +++ b/mypy/test/testpep561.py @@ -1,4 +1,5 @@ from contextlib import contextmanager +import filelock import os import pytest import re @@ -9,7 +10,7 @@ from typing import Tuple, List, Generator import mypy.api -from mypy.test.config import package_path +from mypy.test.config import package_path, pip_lock, pip_timeout from mypy.util import try_find_python2_interpreter from mypy.test.data import DataDrivenTestCase, DataSuite from mypy.test.config import test_temp_dir @@ -77,11 +78,15 @@ def install_package(pkg: str, env = {'PIP_BUILD': dir} # Inherit environment for Windows env.update(os.environ) - proc = subprocess.run(install_cmd, - cwd=working_dir, - stdout=PIPE, - stderr=PIPE, - env=env) + try: + with filelock.FileLock(pip_lock, timeout=pip_timeout): + proc = subprocess.run(install_cmd, + cwd=working_dir, + stdout=PIPE, + stderr=PIPE, + env=env) + except filelock.Timeout as err: + raise Exception("Failed to acquire {}".format(pip_lock)) from err if proc.returncode != 0: raise Exception(proc.stdout.decode('utf-8') + proc.stderr.decode('utf-8')) diff --git a/runtests.py b/runtests.py index 871a214ef0c1e..1f4167f2bd34d 100755 --- a/runtests.py +++ b/runtests.py @@ -58,11 +58,15 @@ 'pytest-slow': ['pytest', '-q', '-k', ' or '.join( [SAMPLES, TYPESHED, - PEP561, DAEMON, MYPYC_EXTERNAL, MYPYC_COMMAND_LINE, ERROR_STREAM])], + + # Test cases that might take minutes to run + 'pytest-slower': ['pytest', '-q', '-k', ' or '.join( + [PEP561])], + # Test cases to run in typeshed CI 'typeshed-ci': ['pytest', '-q', '-k', ' or '.join([CMDLINE, EVALUATION, diff --git a/test-requirements.txt b/test-requirements.txt index 3d7835e38f144..4b6c1751cacfa 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,6 +1,8 @@ -r mypy-requirements.txt -r build-requirements.txt attrs>=18.0 +filelock>=3.0.0,<3.4.2; python_version<'3.7' +filelock>=3.0.0; python_version>='3.7' flake8==3.9.2 flake8-bugbear==22.3.20 flake8-pyi>=20.5 From e661890c5bbf2dbfa72d59f7a6c182531b2c2ae6 Mon Sep 17 00:00:00 2001 From: KotlinIsland <65446343+KotlinIsland@users.noreply.github.com> Date: Sat, 28 May 2022 18:16:49 +1000 Subject: [PATCH 330/377] stubtest: add error summary, other output nits (#12855) Co-authored-by: KotlinIsland Co-authored-by: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Co-authored-by: hauntsaninja <> --- mypy/messages.py | 10 +--- mypy/stubtest.py | 120 ++++++++++++++++++++++++++------------ mypy/test/teststubtest.py | 55 ++++++++++++----- mypy/util.py | 21 ++++--- 4 files changed, 137 insertions(+), 69 deletions(-) diff --git a/mypy/messages.py b/mypy/messages.py index b5f6ca339d6a8..b60f40bce5610 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -42,7 +42,7 @@ ) from mypy.sametypes import is_same_type from mypy.typeops import separate_union_literals -from mypy.util import unmangle +from mypy.util import unmangle, plural_s from mypy.errorcodes import ErrorCode from mypy import message_registry, errorcodes as codes @@ -2110,14 +2110,6 @@ def strip_quotes(s: str) -> str: return s -def plural_s(s: Union[int, Sequence[Any]]) -> str: - count = s if isinstance(s, int) else len(s) - if count > 1: - return 's' - else: - return '' - - def format_string_list(lst: List[str]) -> str: assert len(lst) > 0 if len(lst) == 1: diff --git a/mypy/stubtest.py b/mypy/stubtest.py index 6406921fbb8ab..a85e9335a60db 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -9,12 +9,14 @@ import enum import importlib import inspect +import os import re import sys import types import typing import typing_extensions import warnings +from contextlib import redirect_stdout, redirect_stderr from functools import singledispatch from pathlib import Path from typing import Any, Dict, Generic, Iterator, List, Optional, Tuple, TypeVar, Union, cast @@ -29,7 +31,7 @@ from mypy import nodes from mypy.config_parser import parse_config_file from mypy.options import Options -from mypy.util import FancyFormatter, bytes_to_human_readable_repr, is_dunder +from mypy.util import FancyFormatter, bytes_to_human_readable_repr, plural_s, is_dunder class Missing: @@ -53,6 +55,10 @@ def _style(message: str, **kwargs: Any) -> str: return _formatter.style(message, **kwargs) +class StubtestFailure(Exception): + pass + + class Error: def __init__( self, @@ -163,19 +169,20 @@ def test_module(module_name: str) -> Iterator[Error]: """ stub = get_stub(module_name) if stub is None: - yield Error([module_name], "failed to find stubs", MISSING, None) + yield Error([module_name], "failed to find stubs", MISSING, None, runtime_desc="N/A") return try: - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - runtime = importlib.import_module(module_name) - # Also run the equivalent of `from module import *` - # This could have the additional effect of loading not-yet-loaded submodules - # mentioned in __all__ - __import__(module_name, fromlist=["*"]) + with open(os.devnull, "w") as devnull: + with warnings.catch_warnings(), redirect_stdout(devnull), redirect_stderr(devnull): + warnings.simplefilter("ignore") + runtime = importlib.import_module(module_name) + # Also run the equivalent of `from module import *` + # This could have the additional effect of loading not-yet-loaded submodules + # mentioned in __all__ + __import__(module_name, fromlist=["*"]) except Exception as e: - yield Error([module_name], f"failed to import: {e}", stub, MISSING) + yield Error([module_name], f"failed to import, {type(e).__name__}: {e}", stub, MISSING) return with warnings.catch_warnings(): @@ -944,7 +951,11 @@ def apply_decorator_to_funcitem( ) or decorator.fullname in mypy.types.OVERLOAD_NAMES: return func if decorator.fullname == "builtins.classmethod": - assert func.arguments[0].variable.name in ("cls", "metacls") + if func.arguments[0].variable.name not in ("cls", "mcs", "metacls"): + raise StubtestFailure( + f"unexpected class argument name {func.arguments[0].variable.name!r} " + f"in {dec.fullname}" + ) # FuncItem is written so that copy.copy() actually works, even when compiled ret = copy.copy(func) # Remove the cls argument, since it's not present in inspect.signature of classmethods @@ -1274,26 +1285,16 @@ def build_stubs(modules: List[str], options: Options, find_submodules: bool = Fa sources.extend(found_sources) all_modules.extend(s.module for s in found_sources if s.module not in all_modules) - try: - res = mypy.build.build(sources=sources, options=options) - except mypy.errors.CompileError as e: - output = [ - _style("error: ", color="red", bold=True), - "not checking stubs due to failed mypy compile:\n", - str(e), - ] - print("".join(output)) - raise RuntimeError from e - if res.errors: - output = [ - _style("error: ", color="red", bold=True), - "not checking stubs due to mypy build errors:\n", - ] - print("".join(output) + "\n".join(res.errors)) - raise RuntimeError + if sources: + try: + res = mypy.build.build(sources=sources, options=options) + except mypy.errors.CompileError as e: + raise StubtestFailure(f"failed mypy compile:\n{e}") from e + if res.errors: + raise StubtestFailure("mypy build errors:\n" + "\n".join(res.errors)) - global _all_stubs - _all_stubs = res.files + global _all_stubs + _all_stubs = res.files return all_modules @@ -1355,7 +1356,21 @@ def strip_comments(s: str) -> str: yield entry -def test_stubs(args: argparse.Namespace, use_builtins_fixtures: bool = False) -> int: +class _Arguments: + modules: List[str] + concise: bool + ignore_missing_stub: bool + ignore_positional_only: bool + allowlist: List[str] + generate_allowlist: bool + ignore_unused_allowlist: bool + mypy_config_file: str + custom_typeshed_dir: str + check_typeshed: bool + version: str + + +def test_stubs(args: _Arguments, use_builtins_fixtures: bool = False) -> int: """This is stubtest! It's time to test the stubs!""" # Load the allowlist. This is a series of strings corresponding to Error.object_desc # Values in the dict will store whether we used the allowlist entry or not. @@ -1371,13 +1386,23 @@ def test_stubs(args: argparse.Namespace, use_builtins_fixtures: bool = False) -> modules = args.modules if args.check_typeshed: - assert not args.modules, "Cannot pass both --check-typeshed and a list of modules" + if args.modules: + print( + _style("error:", color="red", bold=True), + "cannot pass both --check-typeshed and a list of modules", + ) + return 1 modules = get_typeshed_stdlib_modules(args.custom_typeshed_dir) # typeshed added a stub for __main__, but that causes stubtest to check itself annoying_modules = {"antigravity", "this", "__main__"} modules = [m for m in modules if m not in annoying_modules] - assert modules, "No modules to check" + if not modules: + print( + _style("error:", color="red", bold=True), + "no modules to check", + ) + return 1 options = Options() options.incremental = False @@ -1392,10 +1417,15 @@ def set_strict_flags() -> None: # not needed yet try: modules = build_stubs(modules, options, find_submodules=not args.check_typeshed) - except RuntimeError: + except StubtestFailure as stubtest_failure: + print( + _style("error:", color="red", bold=True), + f"not checking stubs due to {stubtest_failure}", + ) return 1 exit_code = 0 + error_count = 0 for module in modules: for error in test_module(module): # Filter errors @@ -1421,6 +1451,7 @@ def set_strict_flags() -> None: # not needed yet generated_allowlist.add(error.object_desc) continue print(error.get_description(concise=args.concise)) + error_count += 1 # Print unused allowlist entries if not args.ignore_unused_allowlist: @@ -1429,6 +1460,7 @@ def set_strict_flags() -> None: # not needed yet # This lets us allowlist errors that don't manifest at all on some systems if not allowlist[w] and not allowlist_regexes[w].fullmatch(""): exit_code = 1 + error_count += 1 print(f"note: unused allowlist entry {w}") # Print the generated allowlist @@ -1436,11 +1468,27 @@ def set_strict_flags() -> None: # not needed yet for e in sorted(generated_allowlist): print(e) exit_code = 0 + elif not args.concise: + if error_count: + print( + _style( + f"Found {error_count} error{plural_s(error_count)}" + f" (checked {len(modules)} module{plural_s(modules)})", + color="red", bold=True + ) + ) + else: + print( + _style( + f"Success: no issues found in {len(modules)} module{plural_s(modules)}", + color="green", bold=True + ) + ) return exit_code -def parse_options(args: List[str]) -> argparse.Namespace: +def parse_options(args: List[str]) -> _Arguments: parser = argparse.ArgumentParser( description="Compares stubs to objects introspected from the runtime." ) @@ -1502,7 +1550,7 @@ def parse_options(args: List[str]) -> argparse.Namespace: "--version", action="version", version="%(prog)s " + mypy.version.__version__ ) - return parser.parse_args(args) + return parser.parse_args(args, namespace=_Arguments()) def main() -> int: diff --git a/mypy/test/teststubtest.py b/mypy/test/teststubtest.py index 6ba07fc50cfd5..727bbac83cf1f 100644 --- a/mypy/test/teststubtest.py +++ b/mypy/test/teststubtest.py @@ -809,7 +809,7 @@ def test_missing_no_runtime_all(self) -> Iterator[Case]: @collect_cases def test_non_public_1(self) -> Iterator[Case]: yield Case( - stub="__all__: list[str]", runtime="", error="test_module.__all__" + stub="__all__: list[str]", runtime="", error=f"{TEST_MODULE_NAME}.__all__" ) # dummy case yield Case(stub="_f: int", runtime="def _f(): ...", error="_f") @@ -1085,9 +1085,11 @@ def test_output(self) -> None: options=[], ) expected = ( - 'error: {0}.bad is inconsistent, stub argument "number" differs from runtime ' - 'argument "num"\nStub: at line 1\ndef (number: builtins.int, text: builtins.str)\n' - "Runtime: at line 1 in file {0}.py\ndef (num, text)\n\n".format(TEST_MODULE_NAME) + f'error: {TEST_MODULE_NAME}.bad is inconsistent, stub argument "number" differs ' + 'from runtime argument "num"\n' + 'Stub: at line 1\ndef (number: builtins.int, text: builtins.str)\n' + f"Runtime: at line 1 in file {TEST_MODULE_NAME}.py\ndef (num, text)\n\n" + 'Found 1 error (checked 1 module)\n' ) assert remove_color_code(output) == expected @@ -1106,17 +1108,17 @@ def test_ignore_flags(self) -> None: output = run_stubtest( stub="", runtime="__all__ = ['f']\ndef f(): pass", options=["--ignore-missing-stub"] ) - assert not output + assert output == 'Success: no issues found in 1 module\n' output = run_stubtest( stub="", runtime="def f(): pass", options=["--ignore-missing-stub"] ) - assert not output + assert output == 'Success: no issues found in 1 module\n' output = run_stubtest( stub="def f(__a): ...", runtime="def f(a): pass", options=["--ignore-positional-only"] ) - assert not output + assert output == 'Success: no issues found in 1 module\n' def test_allowlist(self) -> None: # Can't use this as a context because Windows @@ -1130,18 +1132,21 @@ def test_allowlist(self) -> None: runtime="def bad(asdf, text): pass", options=["--allowlist", allowlist.name], ) - assert not output + assert output == 'Success: no issues found in 1 module\n' # test unused entry detection output = run_stubtest(stub="", runtime="", options=["--allowlist", allowlist.name]) - assert output == f"note: unused allowlist entry {TEST_MODULE_NAME}.bad\n" + assert output == ( + f"note: unused allowlist entry {TEST_MODULE_NAME}.bad\n" + "Found 1 error (checked 1 module)\n" + ) output = run_stubtest( stub="", runtime="", options=["--allowlist", allowlist.name, "--ignore-unused-allowlist"], ) - assert not output + assert output == 'Success: no issues found in 1 module\n' # test regex matching with open(allowlist.name, mode="w+") as f: @@ -1166,8 +1171,9 @@ def also_bad(asdf): pass ), options=["--allowlist", allowlist.name, "--generate-allowlist"], ) - assert output == "note: unused allowlist entry unused.*\n{}.also_bad\n".format( - TEST_MODULE_NAME + assert output == ( + f"note: unused allowlist entry unused.*\n" + f"{TEST_MODULE_NAME}.also_bad\n" ) finally: os.unlink(allowlist.name) @@ -1189,7 +1195,11 @@ def test_missing_stubs(self) -> None: output = io.StringIO() with contextlib.redirect_stdout(output): test_stubs(parse_options(["not_a_module"])) - assert "error: not_a_module failed to find stubs" in remove_color_code(output.getvalue()) + assert remove_color_code(output.getvalue()) == ( + "error: not_a_module failed to find stubs\n" + "Stub:\nMISSING\nRuntime:\nN/A\n\n" + "Found 1 error (checked 1 module)\n" + ) def test_get_typeshed_stdlib_modules(self) -> None: stdlib = mypy.stubtest.get_typeshed_stdlib_modules(None, (3, 6)) @@ -1223,8 +1233,23 @@ def test_config_file(self) -> None: ) output = run_stubtest(stub=stub, runtime=runtime, options=[]) assert remove_color_code(output) == ( - "error: test_module.temp variable differs from runtime type Literal[5]\n" + f"error: {TEST_MODULE_NAME}.temp variable differs from runtime type Literal[5]\n" "Stub: at line 2\n_decimal.Decimal\nRuntime:\n5\n\n" + "Found 1 error (checked 1 module)\n" ) output = run_stubtest(stub=stub, runtime=runtime, options=[], config_file=config_file) - assert output == "" + assert output == "Success: no issues found in 1 module\n" + + def test_no_modules(self) -> None: + output = io.StringIO() + with contextlib.redirect_stdout(output): + test_stubs(parse_options([])) + assert remove_color_code(output.getvalue()) == "error: no modules to check\n" + + def test_module_and_typeshed(self) -> None: + output = io.StringIO() + with contextlib.redirect_stdout(output): + test_stubs(parse_options(["--check-typeshed", "some_module"])) + assert remove_color_code(output.getvalue()) == ( + "error: cannot pass both --check-typeshed and a list of modules\n" + ) diff --git a/mypy/util.py b/mypy/util.py index c207fb7e18cd0..03db281ef6152 100644 --- a/mypy/util.py +++ b/mypy/util.py @@ -11,7 +11,7 @@ import time from typing import ( - TypeVar, List, Tuple, Optional, Dict, Sequence, Iterable, Container, IO, Callable + TypeVar, List, Tuple, Optional, Dict, Sequence, Iterable, Container, IO, Callable, Union, Sized ) from typing_extensions import Final, Type, Literal @@ -724,8 +724,7 @@ def format_success(self, n_sources: int, use_color: bool = True) -> str: n_sources is total number of files passed directly on command line, i.e. excluding stubs and followed imports. """ - msg = 'Success: no issues found in {}' \ - ' source file{}'.format(n_sources, 's' if n_sources != 1 else '') + msg = f'Success: no issues found in {n_sources} source file{plural_s(n_sources)}' if not use_color: return msg return self.style(msg, 'green', bold=True) @@ -735,15 +734,11 @@ def format_error( blockers: bool = False, use_color: bool = True ) -> str: """Format a short summary in case of errors.""" - - msg = 'Found {} error{} in {} file{}'.format( - n_errors, 's' if n_errors != 1 else '', - n_files, 's' if n_files != 1 else '' - ) + msg = f'Found {n_errors} error{plural_s(n_errors)} in {n_files} file{plural_s(n_files)}' if blockers: msg += ' (errors prevented further checking)' else: - msg += f" (checked {n_sources} source file{'s' if n_sources != 1 else ''})" + msg += f" (checked {n_sources} source file{plural_s(n_sources)})" if not use_color: return msg return self.style(msg, 'red', bold=True) @@ -773,3 +768,11 @@ def unnamed_function(name: Optional[str]) -> bool: def time_spent_us(t0: float) -> int: return int((time.perf_counter() - t0) * 1e6) + + +def plural_s(s: Union[int, Sized]) -> str: + count = s if isinstance(s, int) else len(s) + if count > 1: + return 's' + else: + return '' From f08c57eb1cf16bb3fb999323bd3f139bd178fd10 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sat, 28 May 2022 01:35:19 -0700 Subject: [PATCH 331/377] stubtest: do not treat py files as source for mypy definitions (#12889) Authored by @KotlinIsland Co-authored-by: KotlinIsland --- mypy/stubtest.py | 3 ++- mypy/test/teststubtest.py | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/mypy/stubtest.py b/mypy/stubtest.py index a85e9335a60db..e87ba447f27aa 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -1301,7 +1301,8 @@ def build_stubs(modules: List[str], options: Options, find_submodules: bool = Fa def get_stub(module: str) -> Optional[nodes.MypyFile]: """Returns a stub object for the given module, if we've built one.""" - return _all_stubs.get(module) + stub = _all_stubs.get(module) + return stub if stub and stub.is_stub else None def get_typeshed_stdlib_modules( diff --git a/mypy/test/teststubtest.py b/mypy/test/teststubtest.py index 727bbac83cf1f..1121afc2fcd25 100644 --- a/mypy/test/teststubtest.py +++ b/mypy/test/teststubtest.py @@ -1201,6 +1201,18 @@ def test_missing_stubs(self) -> None: "Found 1 error (checked 1 module)\n" ) + def test_missing_only_stubs(self) -> None: + with use_tmp_dir(TEST_MODULE_NAME): + with open(f"{TEST_MODULE_NAME}.py", "w") as f: + f.write("a = 1") + output = io.StringIO() + with contextlib.redirect_stdout(output): + test_stubs(parse_options([TEST_MODULE_NAME])) + assert ( + f"error: {TEST_MODULE_NAME} failed to find stubs" + in remove_color_code(output.getvalue()) + ) + def test_get_typeshed_stdlib_modules(self) -> None: stdlib = mypy.stubtest.get_typeshed_stdlib_modules(None, (3, 6)) assert "builtins" in stdlib From 74b35bef35ad5a7b1aa635f52ffcfd850eadc589 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sat, 28 May 2022 03:10:22 -0700 Subject: [PATCH 332/377] stubtest: revert to allow mixed stubs and inline types, add test (#12896) Reverts #12889 Co-authored-by: hauntsaninja <> --- mypy/stubtest.py | 3 +-- mypy/test/teststubtest.py | 10 +++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/mypy/stubtest.py b/mypy/stubtest.py index e87ba447f27aa..a85e9335a60db 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -1301,8 +1301,7 @@ def build_stubs(modules: List[str], options: Options, find_submodules: bool = Fa def get_stub(module: str) -> Optional[nodes.MypyFile]: """Returns a stub object for the given module, if we've built one.""" - stub = _all_stubs.get(module) - return stub if stub and stub.is_stub else None + return _all_stubs.get(module) def get_typeshed_stdlib_modules( diff --git a/mypy/test/teststubtest.py b/mypy/test/teststubtest.py index 1121afc2fcd25..72944f44414cf 100644 --- a/mypy/test/teststubtest.py +++ b/mypy/test/teststubtest.py @@ -1201,17 +1201,17 @@ def test_missing_stubs(self) -> None: "Found 1 error (checked 1 module)\n" ) - def test_missing_only_stubs(self) -> None: + def test_only_py(self) -> None: + # in this case, stubtest will check the py against itself + # this is useful to support packages with a mix of stubs and inline types with use_tmp_dir(TEST_MODULE_NAME): with open(f"{TEST_MODULE_NAME}.py", "w") as f: f.write("a = 1") output = io.StringIO() with contextlib.redirect_stdout(output): test_stubs(parse_options([TEST_MODULE_NAME])) - assert ( - f"error: {TEST_MODULE_NAME} failed to find stubs" - in remove_color_code(output.getvalue()) - ) + output_str = remove_color_code(output.getvalue()) + assert output_str == 'Success: no issues found in 1 module\n' def test_get_typeshed_stdlib_modules(self) -> None: stdlib = mypy.stubtest.get_typeshed_stdlib_modules(None, (3, 6)) From 568b98a6f08205cd364a2511f8c8873f67e8b879 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Sun, 29 May 2022 01:00:33 +0100 Subject: [PATCH 333/377] CONTRIBUTING.md: improve setup docs, especially on Windows (#12898) --- CONTRIBUTING.md | 52 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index eafefe346d01b..c51e812c64926 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,48 +17,64 @@ articulated in the [Python Community Code of Conduct](https://www.python.org/psf ### Setup -Run the following: +#### (1) Clone the mypy repository and enter into it ``` -# Clone the mypy repository git clone https://github.com/python/mypy.git - -# Enter the repository cd mypy +``` -# Create then activate a virtual environment +#### (2) Create then activate a virtual environment +``` +# On Windows, the commands may be slightly different. For more details, see +# https://docs.python.org/3/library/venv.html#creating-virtual-environments python3 -m venv venv source venv/bin/activate +``` -# Install the test requirements and the project +#### (3) Install the test requirements and the project +``` python3 -m pip install -r test-requirements.txt python3 -m pip install -e . -hash -r +hash -r # This resets shell PATH cache, not necessary on Windows ``` ### Running tests -Once setup, you should be able to run tests: -``` -python3 runtests.py -``` +Running the full test suite can take a while, and usually isn't necessary when +preparing a PR. Once you file a PR, the full test suite will run on GitHub. +You'll then be able to see any test failures, and make any necessary changes to +your PR. -To use mypy to check mypy's own code, run: +However, if you wish to do so, you can run the full test suite +like this: ``` -python3 runtests.py self -# or equivalently: -python3 -m mypy --config-file mypy_self_check.ini -p mypy +python3 runtests.py ``` -You can also use `tox` to run tests, for instance: +You can also use `tox` to run tests (`tox` handles setting up the test environment for you): ``` tox -e py ``` -The easiest way to run a single test is: +Some useful commands for running specific tests include: ``` +# Use mypy to check mypy's own code +python3 runtests.py self +# or equivalently: +python3 -m mypy --config-file mypy_self_check.ini -p mypy + +# Run a single test from the test suite pytest -n0 -k 'test_name' + +# Run all test cases in the "test-data/unit/check-dataclasses.test" file +pytest mypy/test/testcheck.py::TypeCheckSuite::check-dataclasses.test + +# Run the linter +flake8 ``` -There's more useful information on writing and running tests [here](test-data/unit/README.md) + +For an in-depth guide on running and writing tests, +see [the README in the test-data directory](test-data/unit/README.md). ## First time contributors From 2051024c07cd361352e081884db0a061221a9aab Mon Sep 17 00:00:00 2001 From: Erik Kemperman Date: Sun, 29 May 2022 21:44:59 +0200 Subject: [PATCH 334/377] Make PEP561 tests opt-in (fix #12879) (#12883) --- runtests.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/runtests.py b/runtests.py index 1f4167f2bd34d..57542f7d458d8 100755 --- a/runtests.py +++ b/runtests.py @@ -36,9 +36,14 @@ ] +# This must be enabled by explicitly including 'pytest-extra' on the command line +PYTEST_OPT_IN = [PEP561] + + # These must be enabled by explicitly including 'mypyc-extra' on the command line. MYPYC_OPT_IN = [MYPYC_RUN, MYPYC_RUN_MULTI] + # We split the pytest run into three parts to improve test # parallelization. Each run should have tests that each take a roughly similar # time to run. @@ -64,14 +69,14 @@ ERROR_STREAM])], # Test cases that might take minutes to run - 'pytest-slower': ['pytest', '-q', '-k', ' or '.join( - [PEP561])], + 'pytest-extra': ['pytest', '-q', '-k', ' or '.join(PYTEST_OPT_IN)], # Test cases to run in typeshed CI 'typeshed-ci': ['pytest', '-q', '-k', ' or '.join([CMDLINE, EVALUATION, SAMPLES, TYPESHED])], + # Mypyc tests that aren't run by default, since they are slow and rarely # fail for commits that don't touch mypyc 'mypyc-extra': ['pytest', '-q', '-k', ' or '.join(MYPYC_OPT_IN)], @@ -80,7 +85,8 @@ # Stop run immediately if these commands fail FAST_FAIL = ['self', 'lint'] -DEFAULT_COMMANDS = [cmd for cmd in cmds if cmd not in ('mypyc-extra', 'typeshed-ci')] +EXTRA_COMMANDS = ('pytest-extra', 'mypyc-extra', 'typeshed-ci') +DEFAULT_COMMANDS = [cmd for cmd in cmds if cmd not in EXTRA_COMMANDS] assert all(cmd in cmds for cmd in FAST_FAIL) @@ -124,7 +130,8 @@ def main() -> None: if not set(args).issubset(cmds): print("usage:", prog, " ".join('[%s]' % k for k in cmds)) print() - print('Run the given tests. If given no arguments, run everything except mypyc-extra.') + print('Run the given tests. If given no arguments, run everything except' + + ' pytest-extra and mypyc-extra.') exit(1) if not args: From 35b4d8a0279e91ef6cc0db126844ddcf263b161f Mon Sep 17 00:00:00 2001 From: Erik Kemperman Date: Mon, 30 May 2022 08:46:17 +0200 Subject: [PATCH 335/377] Fix docs CI, formatting in command_line.rst (#12905) --- .github/workflows/docs.yml | 2 +- docs/source/command_line.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 79560db2d09ba..c4f36d609e744 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -22,7 +22,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-python@v2 with: - python-version: '3.10' + python-version: '3.7' - name: Install tox run: pip install --upgrade 'setuptools!=50' 'virtualenv>=20.6.0' tox==3.24.5 - name: Setup tox environment diff --git a/docs/source/command_line.rst b/docs/source/command_line.rst index 908fa799da461..10416766f2615 100644 --- a/docs/source/command_line.rst +++ b/docs/source/command_line.rst @@ -216,7 +216,7 @@ imports. The default logic used to scan through search paths to resolve imports has a quadratic worse-case behavior in some cases, which is for instance triggered - by a large number of folders sharing a top-level namespace as in: + by a large number of folders sharing a top-level namespace as in:: foo/ company/ @@ -230,7 +230,7 @@ imports. company/ baz/ c.py - ... + ... If you are in this situation, you can enable an experimental fast path by setting the :option:`--fast-module-lookup` option. From b07018cd024cc9d15d7fc977148c2adb5c3e5527 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Mon, 30 May 2022 13:08:01 +0100 Subject: [PATCH 336/377] Run dataclass plugin before checking type var bounds (#12908) The plugin may add attributes that are needed to perform the bound check. Fixes #12876. --- mypy/semanal_main.py | 7 +++---- test-data/unit/check-dataclasses.test | 18 +++++++++++++++++ test-data/unit/fine-grained.test | 28 +++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/mypy/semanal_main.py b/mypy/semanal_main.py index bb0af8edc46f6..305d1a058d76f 100644 --- a/mypy/semanal_main.py +++ b/mypy/semanal_main.py @@ -82,10 +82,10 @@ def semantic_analysis_for_scc(graph: 'Graph', scc: List[str], errors: Errors) -> # We use patch callbacks to fix up things when we expect relatively few # callbacks to be required. apply_semantic_analyzer_patches(patches) - # This pass might need fallbacks calculated above. - check_type_arguments(graph, scc, errors) # Run class decorator hooks (they requite complete MROs and no placeholders). apply_class_plugin_hooks(graph, scc, errors) + # This pass might need fallbacks calculated above and the results of hooks. + check_type_arguments(graph, scc, errors) calculate_class_properties(graph, scc, errors) check_blockers(graph, scc) # Clean-up builtins, so that TypeVar etc. are not accessible without importing. @@ -133,10 +133,9 @@ def semantic_analysis_for_targets( process_top_level_function(analyzer, state, state.id, n.node.fullname, n.node, n.active_typeinfo, patches) apply_semantic_analyzer_patches(patches) - + apply_class_plugin_hooks(graph, [state.id], state.manager.errors) check_type_arguments_in_targets(nodes, state, state.manager.errors) calculate_class_properties(graph, [state.id], state.manager.errors) - apply_class_plugin_hooks(graph, [state.id], state.manager.errors) def restore_saved_attrs(saved_attrs: SavedAttributes) -> None: diff --git a/test-data/unit/check-dataclasses.test b/test-data/unit/check-dataclasses.test index 972cc4d40a1e2..fb1b4a1e8b464 100644 --- a/test-data/unit/check-dataclasses.test +++ b/test-data/unit/check-dataclasses.test @@ -1772,3 +1772,21 @@ c = C() c2 = C(x=1) c.x # E: "C" has no attribute "x" [builtins fixtures/dataclasses.pyi] + +[case testDataclassCheckTypeVarBounds] +# flags: --python-version 3.7 +from dataclasses import dataclass +from typing import Protocol, Dict, TypeVar, Generic + +class DataclassProtocol(Protocol): + __dataclass_fields__: Dict + +T = TypeVar("T", bound=DataclassProtocol) + +@dataclass +class MyDataclass: + x: int = 1 + +class MyGeneric(Generic[T]): ... +class MyClass(MyGeneric[MyDataclass]): ... +[builtins fixtures/dataclasses.pyi] diff --git a/test-data/unit/fine-grained.test b/test-data/unit/fine-grained.test index fa6dc52262ddd..c2bd67320f3ff 100644 --- a/test-data/unit/fine-grained.test +++ b/test-data/unit/fine-grained.test @@ -9734,6 +9734,7 @@ class C: [out] == main:5: error: Unsupported left operand type for + ("str") + [case testNoneAttribute] from typing import Generic, TypeVar @@ -9759,3 +9760,30 @@ class ExampleClass(Generic[T]): self.example_attribute = None [out] == + +[case testDataclassCheckTypeVarBoundsInReprocess] +# flags: --python-version 3.7 +from dataclasses import dataclass +from typing import Protocol, Dict, TypeVar, Generic +from m import x + +class DataclassProtocol(Protocol): + __dataclass_fields__: Dict + +T = TypeVar("T", bound=DataclassProtocol) + +@dataclass +class MyDataclass: + x: int = 1 + +class MyGeneric(Generic[T]): ... +class MyClass(MyGeneric[MyDataclass]): ... + +[file m.py] +x: int +[file m.py.2] +x: str + +[builtins fixtures/dataclasses.pyi] +[out] +== From 2004ae023b9d3628d9f09886cbbc20868aee8554 Mon Sep 17 00:00:00 2001 From: Ashley Whetter Date: Mon, 30 May 2022 12:42:24 -0700 Subject: [PATCH 337/377] Search sys.path for PEP-561 compliant packages (#11143) Closes #5701 This replaces the old hand crafted search code that was more fragile. --- mypy/main.py | 6 +- mypy/modulefinder.py | 110 ++++-------------- mypy/pyinfo.py | 42 ++++--- mypy/test/testcmdline.py | 3 + mypy/test/testmodulefinder.py | 10 +- .../modulefinder-site-packages/baz.pth | 1 - .../modulefinder-site-packages/dne.pth | 1 - .../modulefinder-site-packages/ignored.pth | 3 - .../modulefinder-site-packages/neighbor.pth | 1 - test-data/unit/cmdline.test | 26 +++++ 10 files changed, 80 insertions(+), 123 deletions(-) delete mode 100644 test-data/packages/modulefinder-site-packages/baz.pth delete mode 100644 test-data/packages/modulefinder-site-packages/dne.pth delete mode 100644 test-data/packages/modulefinder-site-packages/ignored.pth delete mode 100644 test-data/packages/modulefinder-site-packages/neighbor.pth diff --git a/mypy/main.py b/mypy/main.py index 57727821274ed..14b318ead3e7a 100644 --- a/mypy/main.py +++ b/mypy/main.py @@ -16,7 +16,7 @@ from mypy import util from mypy.modulefinder import ( BuildSource, FindModuleCache, SearchPaths, - get_site_packages_dirs, mypy_path, + get_search_dirs, mypy_path, ) from mypy.find_sources import create_source_list, InvalidSourceList from mypy.fscache import FileSystemCache @@ -1043,10 +1043,10 @@ def set_strict_flags() -> None: # Set target. if special_opts.modules + special_opts.packages: options.build_type = BuildType.MODULE - egg_dirs, site_packages = get_site_packages_dirs(options.python_executable) + search_dirs = get_search_dirs(options.python_executable) search_paths = SearchPaths((os.getcwd(),), tuple(mypy_path() + options.mypy_path), - tuple(egg_dirs + site_packages), + tuple(search_dirs), ()) targets = [] # TODO: use the same cache that the BuildManager will diff --git a/mypy/modulefinder.py b/mypy/modulefinder.py index 43cc4fc0a6d33..8b3dc2e72084a 100644 --- a/mypy/modulefinder.py +++ b/mypy/modulefinder.py @@ -19,7 +19,7 @@ else: import tomli as tomllib -from typing import Dict, Iterator, List, NamedTuple, Optional, Set, Tuple, Union +from typing import Dict, List, NamedTuple, Optional, Set, Tuple, Union from typing_extensions import Final, TypeAlias as _TypeAlias from mypy.fscache import FileSystemCache @@ -330,6 +330,9 @@ def _find_module_non_stub_helper(self, components: List[str], elif not plausible_match and (self.fscache.isdir(dir_path) or self.fscache.isfile(dir_path + ".py")): plausible_match = True + # If this is not a directory then we can't traverse further into it + if not self.fscache.isdir(dir_path): + break if is_legacy_bundled_package(components[0], self.python_major_ver): if (len(components) == 1 or (self.find_module(components[0]) is @@ -724,97 +727,32 @@ def default_lib_path(data_dir: str, @functools.lru_cache(maxsize=None) -def get_prefixes(python_executable: Optional[str]) -> Tuple[str, str]: - """Get the sys.base_prefix and sys.prefix for the given python. - - This runs a subprocess call to get the prefix paths of the given Python executable. - To avoid repeatedly calling a subprocess (which can be slow!) we - lru_cache the results. - """ - if python_executable is None: - return '', '' - elif python_executable == sys.executable: - # Use running Python's package dirs - return pyinfo.getprefixes() - else: - # Use subprocess to get the package directory of given Python - # executable - return ast.literal_eval( - subprocess.check_output([python_executable, pyinfo.__file__, 'getprefixes'], - stderr=subprocess.PIPE).decode()) - - -@functools.lru_cache(maxsize=None) -def get_site_packages_dirs(python_executable: Optional[str]) -> Tuple[List[str], List[str]]: +def get_search_dirs(python_executable: Optional[str]) -> List[str]: """Find package directories for given python. - This runs a subprocess call, which generates a list of the egg directories, and the site - package directories. To avoid repeatedly calling a subprocess (which can be slow!) we + This runs a subprocess call, which generates a list of the directories in sys.path. + To avoid repeatedly calling a subprocess (which can be slow!) we lru_cache the results. """ if python_executable is None: - return [], [] + return [] elif python_executable == sys.executable: # Use running Python's package dirs - site_packages = pyinfo.getsitepackages() + sys_path = pyinfo.getsearchdirs() else: # Use subprocess to get the package directory of given Python # executable try: - site_packages = ast.literal_eval( - subprocess.check_output([python_executable, pyinfo.__file__, 'getsitepackages'], + sys_path = ast.literal_eval( + subprocess.check_output([python_executable, pyinfo.__file__, 'getsearchdirs'], stderr=subprocess.PIPE).decode()) except OSError as err: reason = os.strerror(err.errno) raise CompileError( [f"mypy: Invalid python executable '{python_executable}': {reason}"] ) from err - return expand_site_packages(site_packages) - - -def expand_site_packages(site_packages: List[str]) -> Tuple[List[str], List[str]]: - """Expands .pth imports in site-packages directories""" - egg_dirs: List[str] = [] - for dir in site_packages: - if not os.path.isdir(dir): - continue - pth_filenames = sorted(name for name in os.listdir(dir) if name.endswith(".pth")) - for pth_filename in pth_filenames: - egg_dirs.extend(_parse_pth_file(dir, pth_filename)) - - return egg_dirs, site_packages - - -def _parse_pth_file(dir: str, pth_filename: str) -> Iterator[str]: - """ - Mimics a subset of .pth import hook from Lib/site.py - See https://github.com/python/cpython/blob/3.5/Lib/site.py#L146-L185 - """ - - pth_file = os.path.join(dir, pth_filename) - try: - f = open(pth_file) - except OSError: - return - with f: - for line in f.readlines(): - if line.startswith("#"): - # Skip comment lines - continue - if line.startswith(("import ", "import\t")): - # import statements in .pth files are not supported - continue - - yield _make_abspath(line.rstrip(), dir) - - -def _make_abspath(path: str, root: str) -> str: - """Take a path and make it absolute relative to root if not already absolute.""" - if os.path.isabs(path): - return os.path.normpath(path) - else: - return os.path.join(root, os.path.normpath(path)) + return sys_path def add_py2_mypypath_entries(mypypath: List[str]) -> List[str]: @@ -903,27 +841,21 @@ def compute_search_paths(sources: List[BuildSource], if options.python_version[0] == 2: mypypath = add_py2_mypypath_entries(mypypath) - egg_dirs, site_packages = get_site_packages_dirs(options.python_executable) - base_prefix, prefix = get_prefixes(options.python_executable) - is_venv = base_prefix != prefix - for site_dir in site_packages: - assert site_dir not in lib_path - if (site_dir in mypypath or - any(p.startswith(site_dir + os.path.sep) for p in mypypath) or - os.path.altsep and any(p.startswith(site_dir + os.path.altsep) for p in mypypath)): - print(f"{site_dir} is in the MYPYPATH. Please remove it.", file=sys.stderr) + search_dirs = get_search_dirs(options.python_executable) + for search_dir in search_dirs: + assert search_dir not in lib_path + if (search_dir in mypypath or + any(p.startswith(search_dir + os.path.sep) for p in mypypath) or + (os.path.altsep + and any(p.startswith(search_dir + os.path.altsep) for p in mypypath))): + print(f"{search_dir} is in the MYPYPATH. Please remove it.", file=sys.stderr) print("See https://mypy.readthedocs.io/en/stable/running_mypy.html" "#how-mypy-handles-imports for more info", file=sys.stderr) sys.exit(1) - elif site_dir in python_path and (is_venv and not site_dir.startswith(prefix)): - print("{} is in the PYTHONPATH. Please change directory" - " so it is not.".format(site_dir), - file=sys.stderr) - sys.exit(1) return SearchPaths(python_path=tuple(reversed(python_path)), mypy_path=tuple(mypypath), - package_path=tuple(egg_dirs + site_packages), + package_path=tuple(search_dirs), typeshed_path=tuple(lib_path)) diff --git a/mypy/pyinfo.py b/mypy/pyinfo.py index ab2d3286bd5cf..c129063a01a47 100644 --- a/mypy/pyinfo.py +++ b/mypy/pyinfo.py @@ -6,41 +6,39 @@ library found in Python 2. This file is run each mypy run, so it should be kept as fast as possible. """ -import site +import os import sys +import sysconfig if __name__ == '__main__': sys.path = sys.path[1:] # we don't want to pick up mypy.types MYPY = False if MYPY: - from typing import List, Tuple + from typing import List -def getprefixes(): - # type: () -> Tuple[str, str] - return getattr(sys, "base_prefix", sys.prefix), sys.prefix - - -def getsitepackages(): +def getsearchdirs(): # type: () -> List[str] - res = [] - if hasattr(site, 'getsitepackages'): - res.extend(site.getsitepackages()) - - if hasattr(site, 'getusersitepackages') and site.ENABLE_USER_SITE: - res.insert(0, site.getusersitepackages()) - else: - from distutils.sysconfig import get_python_lib - res = [get_python_lib()] - return res + # Do not include things from the standard library + # because those should come from typeshed. + stdlib_zip = os.path.join( + sys.base_exec_prefix, + getattr(sys, "platlibdir", "lib"), + "python{}{}.zip".format(sys.version_info.major, sys.version_info.minor) + ) + stdlib = sysconfig.get_path("stdlib") + stdlib_ext = os.path.join(stdlib, "lib-dynload") + cwd = os.path.abspath(os.getcwd()) + excludes = set([cwd, stdlib_zip, stdlib, stdlib_ext]) + + abs_sys_path = (os.path.abspath(p) for p in sys.path) + return [p for p in abs_sys_path if p not in excludes] if __name__ == '__main__': - if sys.argv[-1] == 'getsitepackages': - print(repr(getsitepackages())) - elif sys.argv[-1] == 'getprefixes': - print(repr(getprefixes())) + if sys.argv[-1] == 'getsearchdirs': + print(repr(getsearchdirs())) else: print("ERROR: incorrect argument to pyinfo.py.", file=sys.stderr) sys.exit(1) diff --git a/mypy/test/testcmdline.py b/mypy/test/testcmdline.py index 62e258677c7f8..9983dc554323a 100644 --- a/mypy/test/testcmdline.py +++ b/mypy/test/testcmdline.py @@ -65,7 +65,10 @@ def test_python_cmdline(testcase: DataDrivenTestCase, step: int) -> None: fixed = [python3_path, '-m', 'mypy'] env = os.environ.copy() env.pop('COLUMNS', None) + extra_path = os.path.join(os.path.abspath(test_temp_dir), 'pypath') env['PYTHONPATH'] = PREFIX + if os.path.isdir(extra_path): + env['PYTHONPATH'] += os.pathsep + extra_path process = subprocess.Popen(fixed + args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, diff --git a/mypy/test/testmodulefinder.py b/mypy/test/testmodulefinder.py index d26e7c1efe0c7..fc80893659c2d 100644 --- a/mypy/test/testmodulefinder.py +++ b/mypy/test/testmodulefinder.py @@ -5,7 +5,6 @@ FindModuleCache, SearchPaths, ModuleNotFoundReason, - expand_site_packages ) from mypy.test.helpers import Suite, assert_equal @@ -149,12 +148,17 @@ def setUp(self) -> None: "modulefinder-site-packages", )) - egg_dirs, site_packages = expand_site_packages([self.package_dir]) + package_paths = ( + os.path.join(self.package_dir, "baz"), + os.path.join(self.package_dir, "..", "not-a-directory"), + os.path.join(self.package_dir, "..", "modulefinder-src"), + self.package_dir, + ) self.search_paths = SearchPaths( python_path=(), mypy_path=(os.path.join(data_path, "pkg1"),), - package_path=tuple(egg_dirs + site_packages), + package_path=tuple(package_paths), typeshed_path=(), ) options = Options() diff --git a/test-data/packages/modulefinder-site-packages/baz.pth b/test-data/packages/modulefinder-site-packages/baz.pth deleted file mode 100644 index 76018072e09c5..0000000000000 --- a/test-data/packages/modulefinder-site-packages/baz.pth +++ /dev/null @@ -1 +0,0 @@ -baz diff --git a/test-data/packages/modulefinder-site-packages/dne.pth b/test-data/packages/modulefinder-site-packages/dne.pth deleted file mode 100644 index 1d88f1e3c6f1f..0000000000000 --- a/test-data/packages/modulefinder-site-packages/dne.pth +++ /dev/null @@ -1 +0,0 @@ -../does_not_exist diff --git a/test-data/packages/modulefinder-site-packages/ignored.pth b/test-data/packages/modulefinder-site-packages/ignored.pth deleted file mode 100644 index 0aa17eb504c17..0000000000000 --- a/test-data/packages/modulefinder-site-packages/ignored.pth +++ /dev/null @@ -1,3 +0,0 @@ -# Includes comment lines and -import statements -# That are ignored by the .pth parser diff --git a/test-data/packages/modulefinder-site-packages/neighbor.pth b/test-data/packages/modulefinder-site-packages/neighbor.pth deleted file mode 100644 index a39c0061648c5..0000000000000 --- a/test-data/packages/modulefinder-site-packages/neighbor.pth +++ /dev/null @@ -1 +0,0 @@ -../modulefinder-src diff --git a/test-data/unit/cmdline.test b/test-data/unit/cmdline.test index 86a975fc4949d..016d215027aee 100644 --- a/test-data/unit/cmdline.test +++ b/test-data/unit/cmdline.test @@ -365,6 +365,32 @@ main.py:6: error: Unsupported operand types for + ("int" and "str") main.py:7: error: Module has no attribute "y" main.py:8: error: Unsupported operand types for + (Module and "int") +[case testConfigFollowImportsSysPath] +# cmd: mypy main.py +[file main.py] +from a import x +x + 0 +x + '' # E +import a +a.x + 0 +a.x + '' # E +a.y # E +a + 0 # E +[file mypy.ini] +\[mypy] +follow_imports = normal +no_silence_site_packages = True +[file pypath/a/__init__.py] +x = 0 +x += '' # Error reported here +[file pypath/a/py.typed] +[out] +pypath/a/__init__.py:2: error: Unsupported operand types for + ("int" and "str") +main.py:3: error: Unsupported operand types for + ("int" and "str") +main.py:6: error: Unsupported operand types for + ("int" and "str") +main.py:7: error: Module has no attribute "y" +main.py:8: error: Unsupported operand types for + (Module and "int") + [case testConfigFollowImportsSilent] # cmd: mypy main.py [file main.py] From 0628e09ede4c81b913e859c750c581fbb85fa481 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Mon, 30 May 2022 17:04:49 -0700 Subject: [PATCH 338/377] mypy_primer: report lines truncated (#12910) Co-authored-by: hauntsaninja <> --- .github/workflows/mypy_primer_comment.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/mypy_primer_comment.yml b/.github/workflows/mypy_primer_comment.yml index 36977862eebe5..3c208d5990a13 100644 --- a/.github/workflows/mypy_primer_comment.yml +++ b/.github/workflows/mypy_primer_comment.yml @@ -51,7 +51,9 @@ jobs: let data = fs.readFileSync('fulldiff.txt', { encoding: 'utf8' }) // posting comment fails if too long, so truncate if (data.length > 30000) { - data = data.substring(0, 30000) + `\n\n... (truncated ${data.length - 30000} chars) ...\n` + let truncated_data = data.substring(0, 30000) + let lines_truncated = data.split('\n').length - truncated_data.split('\n').length + data = truncated_data + `\n\n... (truncated ${lines_truncated} lines) ...\n` } console.log("Diff from mypy_primer:") From c2055280ab8f41382a584dc186099755b3cf014e Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Tue, 31 May 2022 16:21:22 -0700 Subject: [PATCH 339/377] Remove failing test on Python 3.11 (#12917) asyncio.coroutine has been removed. I don't think this test case is particularly useful. Co-authored-by: hauntsaninja <> --- test-data/unit/stubgen.test | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/test-data/unit/stubgen.test b/test-data/unit/stubgen.test index 927cc5617c756..a7c2ae6d21fdd 100644 --- a/test-data/unit/stubgen.test +++ b/test-data/unit/stubgen.test @@ -1364,23 +1364,6 @@ class F: @t.coroutine def g(): ... -[case testCoroutineSpecialCase_import] -import asyncio - -__all__ = ['C'] - -@asyncio.coroutine -def f(): - pass - -class C: - def f(self): - pass -[out] -import asyncio - -class C: - def f(self) -> None: ... -- Tests for stub generation from semantically analyzed trees. -- These tests are much slower, so use the `_semanal` suffix only when needed. From 1636a0549670e1b75e2987c16ef26ebf91dfbde9 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Wed, 1 Jun 2022 12:48:17 +0100 Subject: [PATCH 340/377] [mypyc] Simplify code generated for SetAttr and non-pointer type (#12916) Previously we sometimes generated an if statement with an empty body. --- mypyc/codegen/emitfunc.py | 7 ++++--- mypyc/test/test_emitfunc.py | 7 +++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/mypyc/codegen/emitfunc.py b/mypyc/codegen/emitfunc.py index 7b44b22d6cc11..ce428daaee719 100644 --- a/mypyc/codegen/emitfunc.py +++ b/mypyc/codegen/emitfunc.py @@ -373,12 +373,13 @@ def visit_set_attr(self, op: SetAttr) -> None: else: # ...and struct access for normal attributes. attr_expr = self.get_attr_expr(obj, op, decl_cl) - if not op.is_init: + if not op.is_init and attr_rtype.is_refcounted: + # This is not an initalization (where we know that the attribute was + # previously undefined), so decref the old value. always_defined = cl.is_always_defined(op.attr) if not always_defined: self.emitter.emit_undefined_attr_check(attr_rtype, attr_expr, '!=') - if attr_rtype.is_refcounted: - self.emitter.emit_dec_ref(attr_expr, attr_rtype) + self.emitter.emit_dec_ref(attr_expr, attr_rtype) if not always_defined: self.emitter.emit_line('}') # This steals the reference to src, so we don't need to increment the arg diff --git a/mypyc/test/test_emitfunc.py b/mypyc/test/test_emitfunc.py index fe47af2300d72..96d9155214b30 100644 --- a/mypyc/test/test_emitfunc.py +++ b/mypyc/test/test_emitfunc.py @@ -326,6 +326,13 @@ def test_set_attr(self) -> None: cpy_r_r0 = 1; """) + def test_set_attr_non_refcounted(self) -> None: + self.assert_emit( + SetAttr(self.r, 'x', self.b, 1), + """((mod___AObject *)cpy_r_r)->_x = cpy_r_b; + cpy_r_r0 = 1; + """) + def test_dict_get_item(self) -> None: self.assert_emit(CallC(dict_get_item_op.c_function_name, [self.d, self.o2], dict_get_item_op.return_type, dict_get_item_op.steals, From d21c5abcfba7cbae4398bdc075471e2ecc565e1d Mon Sep 17 00:00:00 2001 From: jhance Date: Thu, 2 Jun 2022 13:34:06 -0700 Subject: [PATCH 341/377] Treat generators with await as async. (#12925) Treat generators with await as async. --- mypy/checkexpr.py | 5 +++-- mypy/traverser.py | 16 ++++++++++++++++ test-data/unit/check-async-await.test | 11 +++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index b9c657e83e636..67c7ada55c1a4 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -14,6 +14,7 @@ make_optional_type, ) from mypy.semanal_enum import ENUM_BASES +from mypy.traverser import has_await_expression from mypy.types import ( Type, AnyType, CallableType, Overloaded, NoneType, TypeVarType, TupleType, TypedDictType, Instance, ErasedType, UnionType, @@ -3798,8 +3799,8 @@ def visit_set_comprehension(self, e: SetComprehension) -> Type: def visit_generator_expr(self, e: GeneratorExpr) -> Type: # If any of the comprehensions use async for, the expression will return an async generator - # object - if any(e.is_async): + # object, or if the left-side expression uses await. + if any(e.is_async) or has_await_expression(e.left_expr): typ = 'typing.AsyncGenerator' # received type is always None in async generator expressions additional_args: List[Type] = [NoneType()] diff --git a/mypy/traverser.py b/mypy/traverser.py index d9681bdd81baa..d4e87b820dfbc 100644 --- a/mypy/traverser.py +++ b/mypy/traverser.py @@ -18,6 +18,7 @@ ConditionalExpr, TypeApplication, ExecStmt, Import, ImportFrom, LambdaExpr, ComparisonExpr, OverloadedFuncDef, YieldFromExpr, YieldExpr, StarExpr, BackquoteExpr, AwaitExpr, PrintStmt, SuperExpr, Node, REVEAL_TYPE, + Expression, ) @@ -397,6 +398,21 @@ def has_yield_expression(fdef: FuncBase) -> bool: return seeker.found +class AwaitSeeker(TraverserVisitor): + def __init__(self) -> None: + super().__init__() + self.found = False + + def visit_await_expr(self, o: AwaitExpr) -> None: + self.found = True + + +def has_await_expression(expr: Expression) -> bool: + seeker = AwaitSeeker() + expr.accept(seeker) + return seeker.found + + class ReturnCollector(FuncCollectorBase): def __init__(self) -> None: super().__init__() diff --git a/test-data/unit/check-async-await.test b/test-data/unit/check-async-await.test index a9c6507bceef3..4d856db869a7b 100644 --- a/test-data/unit/check-async-await.test +++ b/test-data/unit/check-async-await.test @@ -864,3 +864,14 @@ async with C() as x: # E: "async with" outside async function [builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] + +[case testAsyncGeneratorExpressionAwait] +from typing import AsyncGenerator + +async def f() -> AsyncGenerator[int, None]: + async def g(x: int) -> int: + return x + + return (await g(x) for x in [1, 2, 3]) + +[typing fixtures/typing-async.pyi] From 9a35fdc94c71f6c427624b9b4d51f7495cbb97f9 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 3 Jun 2022 11:27:56 +0100 Subject: [PATCH 342/377] [mypyc] Support type checking native ints (#12881) Add minimal support for type checking native int types. Currently `mypy_extensions.i32` and `mypy_extensions.i64` are supported, but adding additional types will be easy. Summary of key type checking properties: 1. Coercion both *from* `int` and *to* `int` is supported. 2. Native int types are "sticky" -- operations involving both a native int and a regular int result in a native int. 3. Different native int types can't be mixed without explicit conversions. Work on mypyc/mypyc#837. See the issue for a more detailed description of the feature. I'll add support for compiling native integers in separate PRs. Native ints only work in tests without using hacks, since `mypy_extensions` doesn't include them yet. --- mypy/checkexpr.py | 6 +- mypy/fixup.py | 3 +- mypy/join.py | 22 +-- mypy/meet.py | 13 +- mypy/nodes.py | 22 ++- mypy/semanal_classprop.py | 22 ++- mypy/semanal_main.py | 5 +- mypy/server/astdiff.py | 2 +- mypy/server/astmerge.py | 3 +- mypy/subtypes.py | 11 +- mypy/test/testcheck.py | 1 + test-data/unit/check-native-int.test | 151 ++++++++++++++++++++ test-data/unit/fixtures/dict.pyi | 1 + test-data/unit/lib-stub/mypy_extensions.pyi | 66 ++++++++- test-data/unit/semanal-types.test | 2 +- 15 files changed, 299 insertions(+), 31 deletions(-) create mode 100644 test-data/unit/check-native-int.test diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 67c7ada55c1a4..193e56b6002f7 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -2586,13 +2586,17 @@ def lookup_definer(typ: Instance, attr_name: str) -> Optional[str]: elif (is_subtype(right_type, left_type) and isinstance(left_type, Instance) and isinstance(right_type, Instance) + and left_type.type.alt_promote is not right_type.type and lookup_definer(left_type, op_name) != lookup_definer(right_type, rev_op_name)): - # When we do "A() + B()" where B is a subclass of B, we'll actually try calling + # When we do "A() + B()" where B is a subclass of A, we'll actually try calling # B's __radd__ method first, but ONLY if B explicitly defines or overrides the # __radd__ method. # # This mechanism lets subclasses "refine" the expected outcome of the operation, even # if they're located on the RHS. + # + # As a special case, the alt_promote check makes sure that we don't use the + # __radd__ method of int if the LHS is a native int type. variants_raw = [ (right_op, right_type, left_expr), diff --git a/mypy/fixup.py b/mypy/fixup.py index 1f04c2b181fa9..85c1df079a5a5 100644 --- a/mypy/fixup.py +++ b/mypy/fixup.py @@ -48,7 +48,8 @@ def visit_type_info(self, info: TypeInfo) -> None: for base in info.bases: base.accept(self.type_fixer) if info._promote: - info._promote.accept(self.type_fixer) + for p in info._promote: + p.accept(self.type_fixer) if info.tuple_type: info.tuple_type.accept(self.type_fixer) if info.typeddict_type: diff --git a/mypy/join.py b/mypy/join.py index 94d0afc434f9e..70c250a7703c3 100644 --- a/mypy/join.py +++ b/mypy/join.py @@ -87,10 +87,13 @@ def join_instances(self, t: Instance, s: Instance) -> ProperType: def join_instances_via_supertype(self, t: Instance, s: Instance) -> ProperType: # Give preference to joins via duck typing relationship, so that # join(int, float) == float, for example. - if t.type._promote and is_subtype(t.type._promote, s): - return join_types(t.type._promote, s, self) - elif s.type._promote and is_subtype(s.type._promote, t): - return join_types(t, s.type._promote, self) + for p in t.type._promote: + if is_subtype(p, s): + return join_types(p, s, self) + for p in s.type._promote: + if is_subtype(p, t): + return join_types(t, p, self) + # Compute the "best" supertype of t when joined with s. # The definition of "best" may evolve; for now it is the one with # the longest MRO. Ties are broken by using the earlier base. @@ -101,11 +104,12 @@ def join_instances_via_supertype(self, t: Instance, s: Instance) -> ProperType: if best is None or is_better(res, best): best = res assert best is not None - promote = get_proper_type(t.type._promote) - if isinstance(promote, Instance): - res = self.join_instances(promote, s) - if is_better(res, best): - best = res + for promote in t.type._promote: + promote = get_proper_type(promote) + if isinstance(promote, Instance): + res = self.join_instances(promote, s) + if is_better(res, best): + best = res return best diff --git a/mypy/meet.py b/mypy/meet.py index 2602f0c1abd89..583503bdf6142 100644 --- a/mypy/meet.py +++ b/mypy/meet.py @@ -86,7 +86,12 @@ def narrow_declared_type(declared: Type, narrowed: Type) -> Type: and narrowed.type.is_metaclass()): # We'd need intersection types, so give up. return declared - elif isinstance(declared, (Instance, TupleType, TypeType, LiteralType)): + elif isinstance(declared, Instance): + if declared.type.alt_promote: + # Special case: low-level integer type can't be narrowed + return declared + return meet_types(declared, narrowed) + elif isinstance(declared, (TupleType, TypeType, LiteralType)): return meet_types(declared, narrowed) elif isinstance(declared, TypedDictType) and isinstance(narrowed, Instance): # Special case useful for selecting TypedDicts from unions using isinstance(x, dict). @@ -574,6 +579,12 @@ def visit_instance(self, t: Instance) -> ProperType: else: return NoneType() else: + alt_promote = t.type.alt_promote + if alt_promote and alt_promote is self.s.type: + return t + alt_promote = self.s.type.alt_promote + if alt_promote and alt_promote is t.type: + return self.s if is_subtype(t, self.s): return t elif is_subtype(self.s, t): diff --git a/mypy/nodes.py b/mypy/nodes.py index d510cbeeec620..abc8666e390db 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -2566,7 +2566,7 @@ class is generic then it will be a type constructor of higher kind. 'deletable_attributes', 'slots', 'assuming', 'assuming_proper', 'inferring', 'is_enum', 'fallback_to_any', 'type_vars', 'has_param_spec_type', 'bases', '_promote', 'tuple_type', 'is_named_tuple', 'typeddict_type', - 'is_newtype', 'is_intersection', 'metadata', + 'is_newtype', 'is_intersection', 'metadata', 'alt_promote', ) _fullname: Bogus[str] # Fully qualified name @@ -2658,7 +2658,17 @@ class is generic then it will be a type constructor of higher kind. # even though it's not a subclass in Python. The non-standard # `@_promote` decorator introduces this, and there are also # several builtin examples, in particular `int` -> `float`. - _promote: Optional["mypy.types.Type"] + _promote: List["mypy.types.Type"] + + # This is used for promoting native integer types such as 'i64' to + # 'int'. (_promote is used for the other direction.) This only + # supports one-step promotions (e.g., i64 -> int, not + # i64 -> int -> float, and this isn't used to promote in joins. + # + # This results in some unintuitive results, such as that even + # though i64 is compatible with int and int is compatible with + # float, i64 is *not* compatible with float. + alt_promote: Optional["TypeInfo"] # Representation of a Tuple[...] base class, if the class has any # (e.g., for named tuples). If this is not None, the actual Type @@ -2718,7 +2728,8 @@ def __init__(self, names: 'SymbolTable', defn: ClassDef, module_name: str) -> No self.is_final = False self.is_enum = False self.fallback_to_any = False - self._promote = None + self._promote = [] + self.alt_promote = None self.tuple_type = None self.is_named_tuple = False self.typeddict_type = None @@ -2897,7 +2908,7 @@ def serialize(self) -> JsonDict: 'has_param_spec_type': self.has_param_spec_type, 'bases': [b.serialize() for b in self.bases], 'mro': [c.fullname for c in self.mro], - '_promote': None if self._promote is None else self._promote.serialize(), + '_promote': [p.serialize() for p in self._promote], 'declared_metaclass': (None if self.declared_metaclass is None else self.declared_metaclass.serialize()), 'metaclass_type': @@ -2924,8 +2935,7 @@ def deserialize(cls, data: JsonDict) -> 'TypeInfo': ti.type_vars = data['type_vars'] ti.has_param_spec_type = data['has_param_spec_type'] ti.bases = [mypy.types.Instance.deserialize(b) for b in data['bases']] - ti._promote = (None if data['_promote'] is None - else mypy.types.deserialize_type(data['_promote'])) + ti._promote = [mypy.types.deserialize_type(p) for p in data['_promote']] ti.declared_metaclass = (None if data['declared_metaclass'] is None else mypy.types.Instance.deserialize(data['declared_metaclass'])) ti.metaclass_type = (None if data['metaclass_type'] is None diff --git a/mypy/semanal_classprop.py b/mypy/semanal_classprop.py index e985b55a20d1b..5344f321420f0 100644 --- a/mypy/semanal_classprop.py +++ b/mypy/semanal_classprop.py @@ -146,20 +146,21 @@ def calculate_class_vars(info: TypeInfo) -> None: node.is_classvar = True -def add_type_promotion(info: TypeInfo, module_names: SymbolTable, options: Options) -> None: +def add_type_promotion(info: TypeInfo, module_names: SymbolTable, options: Options, + builtin_names: SymbolTable) -> None: """Setup extra, ad-hoc subtyping relationships between classes (promotion). This includes things like 'int' being compatible with 'float'. """ defn = info.defn - promote_target: Optional[Type] = None + promote_targets: List[Type] = [] for decorator in defn.decorators: if isinstance(decorator, CallExpr): analyzed = decorator.analyzed if isinstance(analyzed, PromoteExpr): # _promote class decorator (undocumented feature). - promote_target = analyzed.type - if not promote_target: + promote_targets.append(analyzed.type) + if not promote_targets: promotions = (TYPE_PROMOTIONS_PYTHON3 if options.python_version[0] >= 3 else TYPE_PROMOTIONS_PYTHON2) if defn.fullname in promotions: @@ -168,5 +169,14 @@ def add_type_promotion(info: TypeInfo, module_names: SymbolTable, options: Optio if target_sym: target_info = target_sym.node assert isinstance(target_info, TypeInfo) - promote_target = Instance(target_info, []) - defn.info._promote = promote_target + promote_targets.append(Instance(target_info, [])) + # Special case the promotions between 'int' and native integer types. + # These have promotions going both ways, such as from 'int' to 'i64' + # and 'i64' to 'int', for convenience. + if defn.fullname == 'mypy_extensions.i64' or defn.fullname == 'mypy_extensions.i32': + int_sym = builtin_names['int'] + assert isinstance(int_sym.node, TypeInfo) + int_sym.node._promote.append(Instance(defn.info, [])) + defn.info.alt_promote = int_sym.node + if promote_targets: + defn.info._promote.extend(promote_targets) diff --git a/mypy/semanal_main.py b/mypy/semanal_main.py index 305d1a058d76f..b25aa0e225a6d 100644 --- a/mypy/semanal_main.py +++ b/mypy/semanal_main.py @@ -435,6 +435,8 @@ def apply_hooks_to_class(self: SemanticAnalyzer, def calculate_class_properties(graph: 'Graph', scc: List[str], errors: Errors) -> None: + builtins = graph['builtins'].tree + assert builtins for module in scc: state = graph[module] tree = state.tree @@ -445,7 +447,8 @@ def calculate_class_properties(graph: 'Graph', scc: List[str], errors: Errors) - calculate_class_abstract_status(node.node, tree.is_stub, errors) check_protocol_status(node.node, errors) calculate_class_vars(node.node) - add_type_promotion(node.node, tree.names, graph[module].options) + add_type_promotion(node.node, tree.names, graph[module].options, + builtins.names) def check_blockers(graph: 'Graph', scc: List[str]) -> None: diff --git a/mypy/server/astdiff.py b/mypy/server/astdiff.py index 1f3b68fbde1b4..1f1c6b65f385b 100644 --- a/mypy/server/astdiff.py +++ b/mypy/server/astdiff.py @@ -220,7 +220,7 @@ def snapshot_definition(node: Optional[SymbolNode], # but this currently seems a bit ad hoc. tuple(snapshot_type(tdef) for tdef in node.defn.type_vars), [snapshot_type(base) for base in node.bases], - snapshot_optional_type(node._promote)) + [snapshot_type(p) for p in node._promote]) prefix = node.fullname symbol_table = snapshot_symbol_table(prefix, node.names) # Special dependency for abstract attribute handling. diff --git a/mypy/server/astmerge.py b/mypy/server/astmerge.py index 4d684e226b21b..be69b3c00d97c 100644 --- a/mypy/server/astmerge.py +++ b/mypy/server/astmerge.py @@ -307,7 +307,8 @@ def process_type_info(self, info: Optional[TypeInfo]) -> None: return self.fixup_type(info.declared_metaclass) self.fixup_type(info.metaclass_type) - self.fixup_type(info._promote) + for target in info._promote: + self.fixup_type(target) self.fixup_type(info.tuple_type) self.fixup_type(info.typeddict_type) info.defn.info = self.fixup(info) diff --git a/mypy/subtypes.py b/mypy/subtypes.py index bbde38c5f92fc..8b7b3153ecafd 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -270,9 +270,15 @@ def visit_instance(self, left: Instance) -> bool: return True if not self.ignore_promotions: for base in left.type.mro: - if base._promote and self._is_subtype(base._promote, self.right): + if base._promote and any(self._is_subtype(p, self.right) + for p in base._promote): TypeState.record_subtype_cache_entry(self._subtype_kind, left, right) return True + # Special case: Low-level integer types are compatible with 'int'. We can't + # use promotions, since 'int' is already promoted to low-level integer types, + # and we can't have circular promotions. + if left.type.alt_promote is right.type: + return True rname = right.type.fullname # Always try a nominal check if possible, # there might be errors that a user wants to silence *once*. @@ -1415,7 +1421,8 @@ def visit_instance(self, left: Instance) -> bool: return True if not self.ignore_promotions: for base in left.type.mro: - if base._promote and self._is_proper_subtype(base._promote, right): + if base._promote and any(self._is_proper_subtype(p, right) + for p in base._promote): TypeState.record_subtype_cache_entry(self._subtype_kind, left, right) return True diff --git a/mypy/test/testcheck.py b/mypy/test/testcheck.py index 279ecdb2d22df..ddcb78df81003 100644 --- a/mypy/test/testcheck.py +++ b/mypy/test/testcheck.py @@ -105,6 +105,7 @@ 'check-singledispatch.test', 'check-slots.test', 'check-formatting.test', + 'check-native-int.test', ] # Tests that use Python 3.8-only AST features (like expression-scoped ignores): diff --git a/test-data/unit/check-native-int.test b/test-data/unit/check-native-int.test new file mode 100644 index 0000000000000..14bea5d715c3b --- /dev/null +++ b/test-data/unit/check-native-int.test @@ -0,0 +1,151 @@ +[case testNativeIntBasics] +from mypy_extensions import i32, i64 + +def f(x: int) -> i32: + return i32(x) + +def g(x: i32) -> None: + pass + +reveal_type(i32(1) + i32(2)) # N: Revealed type is "mypy_extensions.i32" +reveal_type(i64(1) + i64(2)) # N: Revealed type is "mypy_extensions.i64" +i32(1) + i64(2) # E: Unsupported operand types for + ("i32" and "i64") +i64(1) + i32(2) # E: Unsupported operand types for + ("i64" and "i32") +g(i32(2)) +g(i64(2)) # E: Argument 1 to "g" has incompatible type "i64"; expected "i32" +[builtins fixtures/dict.pyi] + +[case testNativeIntCoercions] +from mypy_extensions import i32, i64 + +def f1(x: int) -> None: pass +def f2(x: i32) -> None: pass + +a: i32 = 1 +b: i64 = 2 +c: i64 = a # E: Incompatible types in assignment (expression has type "i32", variable has type "i64") +d: i64 = i64(a) +e: i32 = b # E: Incompatible types in assignment (expression has type "i64", variable has type "i32") +f: i32 = i32(b) +g: int = a +h: int = b + +f1(1) +f1(a) +f1(b) +f2(1) +f2(g) +f2(h) +f2(a) +f2(b) # E: Argument 1 to "f2" has incompatible type "i64"; expected "i32" +[builtins fixtures/dict.pyi] + +[case testNativeIntJoins] +from typing import TypeVar, Any +from mypy_extensions import i32, i64 + +T = TypeVar('T') + +def join(x: T, y: T) -> T: return x + +n32: i32 = 0 +n64: i64 = 1 +n = 2 + +reveal_type(join(n32, n)) # N: Revealed type is "mypy_extensions.i32" +reveal_type(join(n, n32)) # N: Revealed type is "mypy_extensions.i32" +reveal_type(join(n64, n)) # N: Revealed type is "mypy_extensions.i64" +reveal_type(join(n, n64)) # N: Revealed type is "mypy_extensions.i64" +# i32 and i64 aren't treated as compatible +reveal_type(join(n32, n64)) # N: Revealed type is "builtins.object" +reveal_type(join(n64, n32)) # N: Revealed type is "builtins.object" + +a: Any +reveal_type(join(n, a)) # N: Revealed type is "Any" +reveal_type(join(n32, a)) # N: Revealed type is "Any" +reveal_type(join(a, n64)) # N: Revealed type is "Any" +reveal_type(join(n64, a)) # N: Revealed type is "Any" +reveal_type(join(a, n64)) # N: Revealed type is "Any" +[builtins fixtures/dict.pyi] + +[case testNativeIntMeets] +# flags: --strict-optional +from typing import TypeVar, Callable, Any +from mypy_extensions import i32, i64 + +T = TypeVar('T') + +def f32(x: i32) -> None: pass +def f64(x: i64) -> None: pass +def f(x: int) -> None: pass +def fa(x: Any) -> None: pass + +def meet(c1: Callable[[T], None], c2: Callable[[T], None]) -> T: + pass + +reveal_type(meet(f32, f)) # N: Revealed type is "mypy_extensions.i32" +reveal_type(meet(f, f32)) # N: Revealed type is "mypy_extensions.i32" +reveal_type(meet(f64, f)) # N: Revealed type is "mypy_extensions.i64" +reveal_type(meet(f, f64)) # N: Revealed type is "mypy_extensions.i64" +reveal_type(meet(f32, f64)) # N: Revealed type is "" +reveal_type(meet(f64, f32)) # N: Revealed type is "" + +reveal_type(meet(f, fa)) # N: Revealed type is "builtins.int" +reveal_type(meet(f32, fa)) # N: Revealed type is "mypy_extensions.i32" +reveal_type(meet(fa, f32)) # N: Revealed type is "mypy_extensions.i32" +reveal_type(meet(f64, fa)) # N: Revealed type is "mypy_extensions.i64" +reveal_type(meet(fa, f64)) # N: Revealed type is "mypy_extensions.i64" +[builtins fixtures/dict.pyi] + +[case testNativeIntCoerceInArithmetic] +from mypy_extensions import i32, i64 + +reveal_type(i32(1) + 1) # N: Revealed type is "mypy_extensions.i32" +reveal_type(1 + i32(1)) # N: Revealed type is "mypy_extensions.i32" +reveal_type(i64(1) + 1) # N: Revealed type is "mypy_extensions.i64" +reveal_type(1 + i64(1)) # N: Revealed type is "mypy_extensions.i64" +n = int() +reveal_type(i32(1) + n) # N: Revealed type is "mypy_extensions.i32" +reveal_type(n + i32(1)) # N: Revealed type is "mypy_extensions.i32" +[builtins fixtures/dict.pyi] + +[case testNativeIntNoNarrowing] +from mypy_extensions import i32 + +x: i32 = 1 +if int(): + x = 2 + reveal_type(x) # N: Revealed type is "mypy_extensions.i32" +reveal_type(x) # N: Revealed type is "mypy_extensions.i32" + +y = 1 +if int(): + y = i32(1) + reveal_type(y) # N: Revealed type is "mypy_extensions.i32" +reveal_type(y) # N: Revealed type is "builtins.int" +[builtins fixtures/dict.pyi] + +[case testNativeIntFloatConversion] +# flags: --strict-optional +from typing import TypeVar, Callable +from mypy_extensions import i32 + +x: i32 = 1.1 # E: Incompatible types in assignment (expression has type "float", variable has type "i32") +y: float = i32(1) # E: Incompatible types in assignment (expression has type "i32", variable has type "float") + +T = TypeVar('T') + +def join(x: T, y: T) -> T: return x + +reveal_type(join(x, y)) # N: Revealed type is "builtins.object" +reveal_type(join(y, x)) # N: Revealed type is "builtins.object" + +def meet(c1: Callable[[T], None], c2: Callable[[T], None]) -> T: + pass + +def ff(x: float) -> None: pass +def fi32(x: i32) -> None: pass + +reveal_type(meet(ff, fi32)) # N: Revealed type is "" +reveal_type(meet(fi32, ff)) # N: Revealed type is "" +[builtins fixtures/dict.pyi] diff --git a/test-data/unit/fixtures/dict.pyi b/test-data/unit/fixtures/dict.pyi index 9e7cb6f8c70d9..48c16f262f3ec 100644 --- a/test-data/unit/fixtures/dict.pyi +++ b/test-data/unit/fixtures/dict.pyi @@ -33,6 +33,7 @@ class dict(Mapping[KT, VT]): class int: # for convenience def __add__(self, x: Union[int, complex]) -> int: pass + def __radd__(self, x: int) -> int: pass def __sub__(self, x: Union[int, complex]) -> int: pass def __neg__(self) -> int: pass real: int diff --git a/test-data/unit/lib-stub/mypy_extensions.pyi b/test-data/unit/lib-stub/mypy_extensions.pyi index 306d217f478ee..6274163c497dc 100644 --- a/test-data/unit/lib-stub/mypy_extensions.pyi +++ b/test-data/unit/lib-stub/mypy_extensions.pyi @@ -1,6 +1,7 @@ # NOTE: Requires fixtures/dict.pyi from typing import ( - Any, Dict, Type, TypeVar, Optional, Any, Generic, Mapping, NoReturn as NoReturn, Iterator + Any, Dict, Type, TypeVar, Optional, Any, Generic, Mapping, NoReturn as NoReturn, Iterator, + Union ) import sys @@ -48,3 +49,66 @@ def trait(cls: Any) -> Any: ... mypyc_attr: Any class FlexibleAlias(Generic[_T, _U]): ... + +if sys.version_info >= (3, 0): + _Int = Union[int, i32, i64] + + class i32: + def __init__(self, x: _Int) -> None: ... + def __add__(self, x: i32) -> i32: ... + def __radd__(self, x: i32) -> i32: ... + def __sub__(self, x: i32) -> i32: ... + def __rsub__(self, x: i32) -> i32: ... + def __mul__(self, x: i32) -> i32: ... + def __rmul__(self, x: i32) -> i32: ... + def __floordiv__(self, x: i32) -> i32: ... + def __rfloordiv__(self, x: i32) -> i32: ... + def __mod__(self, x: i32) -> i32: ... + def __rmod__(self, x: i32) -> i32: ... + def __and__(self, x: i32) -> i32: ... + def __rand__(self, x: i32) -> i32: ... + def __or__(self, x: i32) -> i32: ... + def __ror__(self, x: i32) -> i32: ... + def __xor__(self, x: i32) -> i32: ... + def __rxor__(self, x: i32) -> i32: ... + def __lshift__(self, x: i32) -> i32: ... + def __rlshift__(self, x: i32) -> i32: ... + def __rshift__(self, x: i32) -> i32: ... + def __rrshift__(self, x: i32) -> i32: ... + def __neg__(self) -> i32: ... + def __invert__(self) -> i32: ... + def __pos__(self) -> i32: ... + def __lt__(self, x: i32) -> bool: ... + def __le__(self, x: i32) -> bool: ... + def __ge__(self, x: i32) -> bool: ... + def __gt__(self, x: i32) -> bool: ... + + class i64: + def __init__(self, x: _Int) -> None: ... + def __add__(self, x: i64) -> i64: ... + def __radd__(self, x: i64) -> i64: ... + def __sub__(self, x: i64) -> i64: ... + def __rsub__(self, x: i64) -> i64: ... + def __mul__(self, x: i64) -> i64: ... + def __rmul__(self, x: i64) -> i64: ... + def __floordiv__(self, x: i64) -> i64: ... + def __rfloordiv__(self, x: i64) -> i64: ... + def __mod__(self, x: i64) -> i64: ... + def __rmod__(self, x: i64) -> i64: ... + def __and__(self, x: i64) -> i64: ... + def __rand__(self, x: i64) -> i64: ... + def __or__(self, x: i64) -> i64: ... + def __ror__(self, x: i64) -> i64: ... + def __xor__(self, x: i64) -> i64: ... + def __rxor__(self, x: i64) -> i64: ... + def __lshift__(self, x: i64) -> i64: ... + def __rlshift__(self, x: i64) -> i64: ... + def __rshift__(self, x: i64) -> i64: ... + def __rrshift__(self, x: i64) -> i64: ... + def __neg__(self) -> i64: ... + def __invert__(self) -> i64: ... + def __pos__(self) -> i64: ... + def __lt__(self, x: i64) -> bool: ... + def __le__(self, x: i64) -> bool: ... + def __ge__(self, x: i64) -> bool: ... + def __gt__(self, x: i64) -> bool: ... diff --git a/test-data/unit/semanal-types.test b/test-data/unit/semanal-types.test index f2cd737b1a6cd..d832772f5f81e 100644 --- a/test-data/unit/semanal-types.test +++ b/test-data/unit/semanal-types.test @@ -1421,7 +1421,7 @@ MypyFile:1( ImportFrom:1(typing, [_promote]) ClassDef:3( S - Promote(builtins.str) + Promote([builtins.str]) Decorators( PromoteExpr:2(builtins.str)) PassStmt:3())) From 8153e47b45247c81ba9792ab46ab788513613f6b Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Sat, 4 Jun 2022 16:27:57 +0100 Subject: [PATCH 343/377] Fix bug in constraints solver regarding `ParamSpec` upper bounds (#12938) Fixes #12930 --- mypy/constraints.py | 2 ++ test-data/unit/check-parameter-specification.test | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/mypy/constraints.py b/mypy/constraints.py index 9a6d87575bdc8..4d95277333758 100644 --- a/mypy/constraints.py +++ b/mypy/constraints.py @@ -571,6 +571,8 @@ def visit_instance(self, template: Instance) -> List[Constraint]: if not actual.values: return infer_constraints(template, actual.upper_bound, self.direction) return [] + elif isinstance(actual, ParamSpecType): + return infer_constraints(template, actual.upper_bound, self.direction) else: return [] diff --git a/test-data/unit/check-parameter-specification.test b/test-data/unit/check-parameter-specification.test index 4dae329782637..682ce93cb7eaa 100644 --- a/test-data/unit/check-parameter-specification.test +++ b/test-data/unit/check-parameter-specification.test @@ -1066,16 +1066,21 @@ def run_job(job: Job[...]) -> T: ... [builtins fixtures/tuple.pyi] [case testTupleAndDictOperationsOnParamSpecArgsAndKwargs] -from typing import Callable +from typing import Callable, Iterator, Iterable, TypeVar, Tuple from typing_extensions import ParamSpec P = ParamSpec('P') +T = TypeVar('T') +def enumerate(x: Iterable[T]) -> Iterator[Tuple[int, T]]: ... def func(callback: Callable[P, str]) -> Callable[P, str]: def inner(*args: P.args, **kwargs: P.kwargs) -> str: reveal_type(args[5]) # N: Revealed type is "builtins.object" for a in args: reveal_type(a) # N: Revealed type is "builtins.object" + for idx, a in enumerate(args): + reveal_type(idx) # N: Revealed type is "builtins.int" + reveal_type(a) # N: Revealed type is "builtins.object" b = 'foo' in args reveal_type(b) # N: Revealed type is "builtins.bool" reveal_type(args.count(42)) # N: Revealed type is "builtins.int" From 9611e2d0b1d9130ca1591febdd60a3523cf739eb Mon Sep 17 00:00:00 2001 From: Hal Blackburn Date: Sun, 5 Jun 2022 07:57:38 +0100 Subject: [PATCH 344/377] Fix sidebar logo not loading in HTML docs (#12939) The mypy logo wasn't loading on https://mypy.readthedocs.io/ because it's referenced via an http:// (not https) URL. The logo's URL is http://mypy-lang.org/static/mypy_light.svg; that server is not accessible via https, so I've moved mypy_light.svg into docs/source and referenced it from there. The project README also referenced the logo via the same URL, so for consistency, the README now points at the same logo file in docs/source. (Although the README's logo did load because GitHub proxies external resources referenced in markdown files). --- README.md | 2 +- docs/source/conf.py | 2 +- docs/source/mypy_light.svg | 99 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 docs/source/mypy_light.svg diff --git a/README.md b/README.md index c40a224ea0420..e9f11833d0d19 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -mypy logo +mypy logo Mypy: Static Typing for Python ======================================= diff --git a/docs/source/conf.py b/docs/source/conf.py index 5c3bf94c2f8c0..6f6b8b276d60a 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -122,7 +122,7 @@ # The name of an image file (relative to this directory) to place at the top # of the sidebar. -html_logo = "http://mypy-lang.org/static/mypy_light.svg" +html_logo = "mypy_light.svg" # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 diff --git a/docs/source/mypy_light.svg b/docs/source/mypy_light.svg new file mode 100644 index 0000000000000..4eaf65dbf3445 --- /dev/null +++ b/docs/source/mypy_light.svg @@ -0,0 +1,99 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + From 7e38877750c04abfd436e6ad98da23d6deca4e8f Mon Sep 17 00:00:00 2001 From: Jingchen Ye <11172084+97littleleaf11@users.noreply.github.com> Date: Mon, 6 Jun 2022 08:16:52 +0800 Subject: [PATCH 345/377] Update badge for build status (#12941) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e9f11833d0d19..9a63090e95a79 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Mypy: Static Typing for Python [![Stable Version](https://img.shields.io/pypi/v/mypy?color=blue)](https://pypi.org/project/mypy/) [![Downloads](https://img.shields.io/pypi/dm/mypy)](https://pypistats.org/packages/mypy) -[![Build Status](https://api.travis-ci.com/python/mypy.svg?branch=master)](https://travis-ci.com/python/mypy) +[![Build Status](https://github.com/python/mypy/actions/workflows/test.yml/badge.svg)](https://github.com/python/mypy/actions) [![Documentation Status](https://readthedocs.org/projects/mypy/badge/?version=latest)](https://mypy.readthedocs.io/en/latest/?badge=latest) [![Chat at https://gitter.im/python/typing](https://badges.gitter.im/python/typing.svg)](https://gitter.im/python/typing?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Checked with mypy](http://www.mypy-lang.org/static/mypy_badge.svg)](http://mypy-lang.org/) From c3e32e33b37b13d08182b71dedba5c184e4ee216 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Tue, 7 Jun 2022 18:16:37 +0100 Subject: [PATCH 346/377] Fix crash on redefined class variable annotated with `Final[]` (#12951) --- mypy/checker.py | 15 ++++++++------- test-data/unit/check-final.test | 8 ++++++++ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index e5abcfcf45416..688fbd28739d4 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -2715,13 +2715,14 @@ def check_final(self, if is_final_decl and self.scope.active_class(): lv = lvs[0] assert isinstance(lv, RefExpr) - assert isinstance(lv.node, Var) - if (lv.node.final_unset_in_class and not lv.node.final_set_in_init and - not self.is_stub and # It is OK to skip initializer in stub files. - # Avoid extra error messages, if there is no type in Final[...], - # then we already reported the error about missing r.h.s. - isinstance(s, AssignmentStmt) and s.type is not None): - self.msg.final_without_value(s) + if lv.node is not None: + assert isinstance(lv.node, Var) + if (lv.node.final_unset_in_class and not lv.node.final_set_in_init and + not self.is_stub and # It is OK to skip initializer in stub files. + # Avoid extra error messages, if there is no type in Final[...], + # then we already reported the error about missing r.h.s. + isinstance(s, AssignmentStmt) and s.type is not None): + self.msg.final_without_value(s) for lv in lvs: if isinstance(lv, RefExpr) and isinstance(lv.node, Var): name = lv.node.name diff --git a/test-data/unit/check-final.test b/test-data/unit/check-final.test index 2f298ad1be3bf..da034caced767 100644 --- a/test-data/unit/check-final.test +++ b/test-data/unit/check-final.test @@ -1109,3 +1109,11 @@ class A(ABC): @final # E: Method B is both abstract and final @abstractmethod def B(self) -> None: ... + +[case testFinalClassVariableRedefinitionDoesNotCrash] +# This used to crash -- see #12950 +from typing import Final + +class MyClass: + a: None + a: Final[int] = 1 # E: Cannot redefine an existing name as final # E: Name "a" already defined on line 5 From 9b4bce9065cbef6185fbc77f2849b63dc9e5e293 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Wed, 8 Jun 2022 00:49:11 +0100 Subject: [PATCH 347/377] Improve handling of overloads with ParamSpec (#12953) --- mypy/meet.py | 26 ++++++++++++----------- test-data/unit/check-overloading.test | 30 +++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/mypy/meet.py b/mypy/meet.py index 583503bdf6142..ebaf0f675ef13 100644 --- a/mypy/meet.py +++ b/mypy/meet.py @@ -6,7 +6,7 @@ TupleType, TypedDictType, ErasedType, UnionType, PartialType, DeletedType, UninhabitedType, TypeType, TypeOfAny, Overloaded, FunctionLike, LiteralType, ProperType, get_proper_type, get_proper_types, TypeAliasType, TypeGuardedType, - ParamSpecType, Parameters, UnpackType, TypeVarTupleType, + ParamSpecType, Parameters, UnpackType, TypeVarTupleType, TypeVarLikeType ) from mypy.subtypes import is_equivalent, is_subtype, is_callable_compatible, is_proper_subtype from mypy.erasetype import erase_type @@ -117,8 +117,8 @@ def get_possible_variants(typ: Type) -> List[Type]: If this function receives any other type, we return a list containing just that original type. (E.g. pretend the type was contained within a singleton union). - The only exception is regular TypeVars: we return a list containing that TypeVar's - upper bound. + The only current exceptions are regular TypeVars and ParamSpecs. For these "TypeVarLike"s, + we return a list containing that TypeVarLike's upper bound. This function is useful primarily when checking to see if two types are overlapping: the algorithm to check if two unions are overlapping is fundamentally the same as @@ -134,6 +134,8 @@ def get_possible_variants(typ: Type) -> List[Type]: return typ.values else: return [typ.upper_bound] + elif isinstance(typ, ParamSpecType): + return [typ.upper_bound] elif isinstance(typ, UnionType): return list(typ.items) elif isinstance(typ, Overloaded): @@ -244,36 +246,36 @@ def _is_overlapping_types(left: Type, right: Type) -> bool: right_possible = get_possible_variants(right) # We start by checking multi-variant types like Unions first. We also perform - # the same logic if either type happens to be a TypeVar. + # the same logic if either type happens to be a TypeVar/ParamSpec/TypeVarTuple. # - # Handling the TypeVars now lets us simulate having them bind to the corresponding + # Handling the TypeVarLikes now lets us simulate having them bind to the corresponding # type -- if we deferred these checks, the "return-early" logic of the other # checks will prevent us from detecting certain overlaps. # - # If both types are singleton variants (and are not TypeVars), we've hit the base case: + # If both types are singleton variants (and are not TypeVarLikes), we've hit the base case: # we skip these checks to avoid infinitely recursing. - def is_none_typevar_overlap(t1: Type, t2: Type) -> bool: + def is_none_typevarlike_overlap(t1: Type, t2: Type) -> bool: t1, t2 = get_proper_types((t1, t2)) - return isinstance(t1, NoneType) and isinstance(t2, TypeVarType) + return isinstance(t1, NoneType) and isinstance(t2, TypeVarLikeType) if prohibit_none_typevar_overlap: - if is_none_typevar_overlap(left, right) or is_none_typevar_overlap(right, left): + if is_none_typevarlike_overlap(left, right) or is_none_typevarlike_overlap(right, left): return False if (len(left_possible) > 1 or len(right_possible) > 1 - or isinstance(left, TypeVarType) or isinstance(right, TypeVarType)): + or isinstance(left, TypeVarLikeType) or isinstance(right, TypeVarLikeType)): for l in left_possible: for r in right_possible: if _is_overlapping_types(l, r): return True return False - # Now that we've finished handling TypeVars, we're free to end early + # Now that we've finished handling TypeVarLikes, we're free to end early # if one one of the types is None and we're running in strict-optional mode. # (None only overlaps with None in strict-optional mode). # - # We must perform this check after the TypeVar checks because + # We must perform this check after the TypeVarLike checks because # a TypeVar could be bound to None, for example. if state.strict_optional and isinstance(left, NoneType) != isinstance(right, NoneType): diff --git a/test-data/unit/check-overloading.test b/test-data/unit/check-overloading.test index 8259f2754bce8..312d7a6cc7aec 100644 --- a/test-data/unit/check-overloading.test +++ b/test-data/unit/check-overloading.test @@ -6506,3 +6506,33 @@ if True: @overload def f3(g: D) -> D: ... def f3(g): ... # E: Name "f3" already defined on line 32 + +[case testOverloadingWithParamSpec] +from typing import TypeVar, Callable, Any, overload +from typing_extensions import ParamSpec, Concatenate + +P = ParamSpec("P") +R = TypeVar("R") + +@overload +def func(x: Callable[Concatenate[Any, P], R]) -> Callable[P, R]: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types +@overload +def func(x: Callable[P, R]) -> Callable[Concatenate[str, P], R]: ... +def func(x: Callable[..., R]) -> Callable[..., R]: ... + +def foo(arg1: str, arg2: int) -> bytes: ... +reveal_type(func(foo)) # N: Revealed type is "def (arg2: builtins.int) -> builtins.bytes" + +def bar() -> int: ... +reveal_type(func(bar)) # N: Revealed type is "def (builtins.str) -> builtins.int" + +baz: Callable[[str, str], str] = lambda x, y: 'baz' +reveal_type(func(baz)) # N: Revealed type is "def (builtins.str) -> builtins.str" + +eggs = lambda: 'eggs' +reveal_type(func(eggs)) # N: Revealed type is "def (builtins.str) -> builtins.str" + +spam: Callable[..., str] = lambda x, y: 'baz' +reveal_type(func(spam)) # N: Revealed type is "def (*Any, **Any) -> Any" + +[builtins fixtures/paramspec.pyi] From 3833277fc292c9d4a514337b244d146228f1776e Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Thu, 9 Jun 2022 13:40:30 -0700 Subject: [PATCH 348/377] Raise minimum filelock version (#12960) This is the version of filelock that includes py.typed Co-authored-by: hauntsaninja <> --- test-requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test-requirements.txt b/test-requirements.txt index 4b6c1751cacfa..c50705dff7399 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,8 +1,8 @@ -r mypy-requirements.txt -r build-requirements.txt attrs>=18.0 -filelock>=3.0.0,<3.4.2; python_version<'3.7' -filelock>=3.0.0; python_version>='3.7' +filelock>=3.3.0,<3.4.2; python_version<'3.7' +filelock>=3.3.0; python_version>='3.7' flake8==3.9.2 flake8-bugbear==22.3.20 flake8-pyi>=20.5 From 9ccd081550010700341a46f0e08b8954e5beef70 Mon Sep 17 00:00:00 2001 From: jhance Date: Fri, 10 Jun 2022 09:10:11 -0700 Subject: [PATCH 349/377] Support inferring Unpack mixed with other items (#12769) The main substance here modifies mypy/constraints.py to not assume that template.items has length 1 in the case that there is an unpack. We instead assume that that there is only a singular unpack, and do a former pass to find what index it is in, and then resolve the unpack to the corresponding subset of whatever tuple we are matching against. --- mypy/constraints.py | 69 ++++++++++++++++++++----- mypy/expandtype.py | 2 + mypy/type_visitor.py | 2 +- mypy/typeops.py | 20 ++++++- test-data/unit/check-typevar-tuple.test | 67 ++++++++++++++++++++++++ 5 files changed, 143 insertions(+), 17 deletions(-) diff --git a/mypy/constraints.py b/mypy/constraints.py index 4d95277333758..2f071e13a0025 100644 --- a/mypy/constraints.py +++ b/mypy/constraints.py @@ -702,20 +702,46 @@ def visit_tuple_type(self, template: TupleType) -> List[Constraint]: isinstance(actual, Instance) and actual.type.fullname == "builtins.tuple" ) - if len(template.items) == 1: - item = get_proper_type(template.items[0]) - if isinstance(item, UnpackType): - unpacked_type = get_proper_type(item.type) - if isinstance(unpacked_type, TypeVarTupleType): - if ( - isinstance(actual, (TupleType, AnyType)) - or is_varlength_tuple - ): - return [Constraint( - type_var=unpacked_type.id, - op=self.direction, - target=actual, - )] + unpack_index = find_unpack_in_tuple(template) + + if unpack_index is not None: + unpack_item = get_proper_type(template.items[unpack_index]) + assert isinstance(unpack_item, UnpackType) + + unpacked_type = get_proper_type(unpack_item.type) + if isinstance(unpacked_type, TypeVarTupleType): + if is_varlength_tuple: + # This case is only valid when the unpack is the only + # item in the tuple. + # + # TODO: We should support this in the case that all the items + # in the tuple besides the unpack have the same type as the + # varlength tuple's type. E.g. Tuple[int, ...] should be valid + # where we expect Tuple[int, Unpack[Ts]], but not for Tuple[str, Unpack[Ts]]. + assert len(template.items) == 1 + + if ( + isinstance(actual, (TupleType, AnyType)) + or is_varlength_tuple + ): + modified_actual = actual + if isinstance(actual, TupleType): + # Exclude the items from before and after the unpack index. + head = unpack_index + tail = len(template.items) - unpack_index - 1 + if tail: + modified_actual = actual.copy_modified( + items=actual.items[head:-tail], + ) + else: + modified_actual = actual.copy_modified( + items=actual.items[head:], + ) + return [Constraint( + type_var=unpacked_type.id, + op=self.direction, + target=modified_actual, + )] if isinstance(actual, TupleType) and len(actual.items) == len(template.items): res: List[Constraint] = [] @@ -828,3 +854,18 @@ def find_matching_overload_items(overloaded: Overloaded, # it maintains backward compatibility. res = items[:] return res + + +def find_unpack_in_tuple(t: TupleType) -> Optional[int]: + unpack_index: Optional[int] = None + for i, item in enumerate(t.items): + proper_item = get_proper_type(item) + if isinstance(proper_item, UnpackType): + # We cannot fail here, so we must check this in an earlier + # semanal phase. + # Funky code here avoids mypyc narrowing the type of unpack_index. + old_index = unpack_index + assert old_index is None + # Don't return so that we can also sanity check there is only one. + unpack_index = i + return unpack_index diff --git a/mypy/expandtype.py b/mypy/expandtype.py index 985114a53051f..ce43aeaeb6e50 100644 --- a/mypy/expandtype.py +++ b/mypy/expandtype.py @@ -161,6 +161,8 @@ def expand_unpack(self, t: UnpackType) -> Optional[Union[List[Type], Instance, A return repl elif isinstance(repl, TypeVarTupleType): return [UnpackType(typ=repl)] + elif isinstance(repl, UnpackType): + return [repl] elif isinstance(repl, UninhabitedType): return None else: diff --git a/mypy/type_visitor.py b/mypy/type_visitor.py index 85701a51f1280..79b4cb12d512a 100644 --- a/mypy/type_visitor.py +++ b/mypy/type_visitor.py @@ -209,7 +209,7 @@ def visit_partial_type(self, t: PartialType) -> Type: return t def visit_unpack_type(self, t: UnpackType) -> Type: - return t.type.accept(self) + return UnpackType(t.type.accept(self)) def visit_callable_type(self, t: CallableType) -> Type: return t.copy_modified(arg_types=self.translate_types(t.arg_types), diff --git a/mypy/typeops.py b/mypy/typeops.py index 22ca0b6ec2fe4..835c8f0a72291 100644 --- a/mypy/typeops.py +++ b/mypy/typeops.py @@ -14,7 +14,8 @@ TupleType, Instance, FunctionLike, Type, CallableType, TypeVarLikeType, Overloaded, TypeVarType, UninhabitedType, FormalArgument, UnionType, NoneType, AnyType, TypeOfAny, TypeType, ProperType, LiteralType, get_proper_type, get_proper_types, - TypeAliasType, TypeQuery, ParamSpecType, Parameters, ENUM_REMOVED_PROPS + TypeAliasType, TypeQuery, ParamSpecType, Parameters, UnpackType, TypeVarTupleType, + ENUM_REMOVED_PROPS, ) from mypy.nodes import ( FuncBase, FuncItem, FuncDef, OverloadedFuncDef, TypeInfo, ARG_STAR, ARG_STAR2, ARG_POS, @@ -42,7 +43,22 @@ def tuple_fallback(typ: TupleType) -> Instance: info = typ.partial_fallback.type if info.fullname != 'builtins.tuple': return typ.partial_fallback - return Instance(info, [join_type_list(typ.items)]) + items = [] + for item in typ.items: + proper_type = get_proper_type(item) + if isinstance(proper_type, UnpackType): + unpacked_type = get_proper_type(proper_type.type) + if isinstance(unpacked_type, TypeVarTupleType): + items.append(unpacked_type.upper_bound) + elif isinstance(unpacked_type, TupleType): + # TODO: might make sense to do recursion here to support nested unpacks + # of tuple constants + items.extend(unpacked_type.items) + else: + raise NotImplementedError + else: + items.append(item) + return Instance(info, [join_type_list(items)]) def type_object_type_from_function(signature: FunctionLike, diff --git a/test-data/unit/check-typevar-tuple.test b/test-data/unit/check-typevar-tuple.test index ed11e5b53263c..e98f5a69001e5 100644 --- a/test-data/unit/check-typevar-tuple.test +++ b/test-data/unit/check-typevar-tuple.test @@ -27,3 +27,70 @@ reveal_type(g(args, args2)) # N: Revealed type is "Tuple[builtins.int, builtins reveal_type(g(args, args3)) # N: Revealed type is "builtins.tuple[builtins.object, ...]" reveal_type(g(any, any)) # N: Revealed type is "Any" [builtins fixtures/tuple.pyi] + +[case testTypeVarTupleMixed] +from typing import Tuple +from typing_extensions import Unpack, TypeVarTuple + +Ts = TypeVarTuple("Ts") + +def to_str(i: int) -> str: + ... + +def f(a: Tuple[int, Unpack[Ts]]) -> Tuple[str, Unpack[Ts]]: + return (to_str(a[0]),) + a[1:] + +def g(a: Tuple[Unpack[Ts], int]) -> Tuple[Unpack[Ts], str]: + return a[:-1] + (to_str(a[-1]),) + +def h(a: Tuple[bool, int, Unpack[Ts], str, object]) -> Tuple[Unpack[Ts]]: + return a[2:-2] + +empty = () +bad_args: Tuple[str, str] +var_len_tuple: Tuple[int, ...] + +f_args: Tuple[int, str] +f_args2: Tuple[int] +f_args3: Tuple[int, str, bool] + +reveal_type(f(f_args)) # N: Revealed type is "Tuple[builtins.str, builtins.str]" +reveal_type(f(f_args2)) # N: Revealed type is "Tuple[builtins.str]" +reveal_type(f(f_args3)) # N: Revealed type is "Tuple[builtins.str, builtins.str, builtins.bool]" +f(empty) # E: Argument 1 to "f" has incompatible type "Tuple[]"; expected "Tuple[int]" +f(bad_args) # E: Argument 1 to "f" has incompatible type "Tuple[str, str]"; expected "Tuple[int, str]" +# TODO: This hits a crash where we assert len(templates.items) == 1. See visit_tuple_type +# in mypy/constraints.py. +#f(var_len_tuple) + +g_args: Tuple[str, int] +reveal_type(g(g_args)) # N: Revealed type is "Tuple[builtins.str, builtins.str]" + +h_args: Tuple[bool, int, str, int, str, object] +reveal_type(h(h_args)) # N: Revealed type is "Tuple[builtins.str, builtins.int]" +[builtins fixtures/tuple.pyi] + +[case testTypeVarTupleChaining] +from typing import Tuple +from typing_extensions import Unpack, TypeVarTuple + +Ts = TypeVarTuple("Ts") + +def to_str(i: int) -> str: + ... + +def f(a: Tuple[int, Unpack[Ts]]) -> Tuple[str, Unpack[Ts]]: + return (to_str(a[0]),) + a[1:] + +def g(a: Tuple[bool, int, Unpack[Ts], str, object]) -> Tuple[str, Unpack[Ts]]: + return f(a[1:-2]) + +def h(a: Tuple[bool, int, Unpack[Ts], str, object]) -> Tuple[str, Unpack[Ts]]: + x = f(a[1:-2]) + return x + +args: Tuple[bool, int, str, int, str, object] +reveal_type(g(args)) # N: Revealed type is "Tuple[builtins.str, builtins.str, builtins.int]" +reveal_type(h(args)) # N: Revealed type is "Tuple[builtins.str, builtins.str, builtins.int]" +[builtins fixtures/tuple.pyi] + From ddbea6988c0913c70ed16cd2fda6064e301b4b63 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Sat, 11 Jun 2022 19:19:19 +0100 Subject: [PATCH 350/377] [mypyc] Foundational work to help support native ints (#12884) Some IR and codegen changes that help with native int support. This was split off from a branch with a working implementation of native ints to make reviewing easier. Some tests and primitives are missing here and I will include them in follow-up PRs. Summary of major changes below. 1) Allow ambiguous error returns from functions. Since all values of `i64` values are valid return values, none can be reserved for errors. The approach here is to have the error value overlap a valid value, and use `PyErr_Occurred()` as a secondary check to make sure it actually was an error. 2) Add `Extend` op which extends a value to a larger integer type with either zero or sign extension. 3) Improve subtype checking with native int types. 4) Fill in other minor gaps in IR and codegen support for native ints. Work on mypyc/mypyc#837. --- mypyc/analysis/dataflow.py | 5 +- mypyc/analysis/ircheck.py | 5 +- mypyc/analysis/selfleaks.py | 6 +- mypyc/codegen/emit.py | 35 ++++++++++-- mypyc/codegen/emitfunc.py | 25 ++++++++- mypyc/ir/ops.py | 101 +++++++++++++++++++++++++++------ mypyc/ir/pprint.py | 9 ++- mypyc/ir/rtypes.py | 103 +++++++++++++++++++++++++++++----- mypyc/irbuild/ll_builder.py | 2 +- mypyc/subtype.py | 9 ++- mypyc/test/test_emitfunc.py | 38 +++++++++++-- mypyc/test/test_subtype.py | 21 ++++++- mypyc/transform/exceptions.py | 33 ++++++++++- 13 files changed, 335 insertions(+), 57 deletions(-) diff --git a/mypyc/analysis/dataflow.py b/mypyc/analysis/dataflow.py index 053efc7338453..528c04af546fa 100644 --- a/mypyc/analysis/dataflow.py +++ b/mypyc/analysis/dataflow.py @@ -9,7 +9,7 @@ BasicBlock, OpVisitor, Assign, AssignMulti, Integer, LoadErrorValue, RegisterOp, Goto, Branch, Return, Call, Box, Unbox, Cast, Op, Unreachable, TupleGet, TupleSet, GetAttr, SetAttr, LoadLiteral, LoadStatic, InitStatic, MethodCall, RaiseStandardError, CallC, LoadGlobal, - Truncate, IntOp, LoadMem, GetElementPtr, LoadAddress, ComparisonOp, SetMem, KeepAlive + Truncate, IntOp, LoadMem, GetElementPtr, LoadAddress, ComparisonOp, SetMem, KeepAlive, Extend ) from mypyc.ir.func_ir import all_values @@ -199,6 +199,9 @@ def visit_call_c(self, op: CallC) -> GenAndKill[T]: def visit_truncate(self, op: Truncate) -> GenAndKill[T]: return self.visit_register_op(op) + def visit_extend(self, op: Extend) -> GenAndKill[T]: + return self.visit_register_op(op) + def visit_load_global(self, op: LoadGlobal) -> GenAndKill[T]: return self.visit_register_op(op) diff --git a/mypyc/analysis/ircheck.py b/mypyc/analysis/ircheck.py index 6c8e8d7f18e5b..8217d9865c4bb 100644 --- a/mypyc/analysis/ircheck.py +++ b/mypyc/analysis/ircheck.py @@ -7,7 +7,7 @@ InitStatic, TupleGet, TupleSet, IncRef, DecRef, Call, MethodCall, Cast, Box, Unbox, RaiseStandardError, CallC, Truncate, LoadGlobal, IntOp, ComparisonOp, LoadMem, SetMem, GetElementPtr, LoadAddress, KeepAlive, Register, Integer, - BaseAssign + BaseAssign, Extend ) from mypyc.ir.rtypes import ( RType, RPrimitive, RUnion, is_object_rprimitive, RInstance, RArray, @@ -326,6 +326,9 @@ def visit_call_c(self, op: CallC) -> None: def visit_truncate(self, op: Truncate) -> None: pass + def visit_extend(self, op: Extend) -> None: + pass + def visit_load_global(self, op: LoadGlobal) -> None: pass diff --git a/mypyc/analysis/selfleaks.py b/mypyc/analysis/selfleaks.py index ae3731a40ac30..4ba6cfb28eb39 100644 --- a/mypyc/analysis/selfleaks.py +++ b/mypyc/analysis/selfleaks.py @@ -4,7 +4,8 @@ OpVisitor, Register, Goto, Assign, AssignMulti, SetMem, Call, MethodCall, LoadErrorValue, LoadLiteral, GetAttr, SetAttr, LoadStatic, InitStatic, TupleGet, TupleSet, Box, Unbox, Cast, RaiseStandardError, CallC, Truncate, LoadGlobal, IntOp, ComparisonOp, LoadMem, - GetElementPtr, LoadAddress, KeepAlive, Branch, Return, Unreachable, RegisterOp, BasicBlock + GetElementPtr, LoadAddress, KeepAlive, Branch, Return, Unreachable, RegisterOp, BasicBlock, + Extend ) from mypyc.ir.rtypes import RInstance from mypyc.analysis.dataflow import MAYBE_ANALYSIS, run_analysis, AnalysisResult, CFG @@ -115,6 +116,9 @@ def visit_call_c(self, op: CallC) -> GenAndKill: def visit_truncate(self, op: Truncate) -> GenAndKill: return CLEAN + def visit_extend(self, op: Extend) -> GenAndKill: + return CLEAN + def visit_load_global(self, op: LoadGlobal) -> GenAndKill: return CLEAN diff --git a/mypyc/codegen/emit.py b/mypyc/codegen/emit.py index 0815dd3c3bd0e..b1f886ee3f5f8 100644 --- a/mypyc/codegen/emit.py +++ b/mypyc/codegen/emit.py @@ -17,7 +17,8 @@ is_list_rprimitive, is_dict_rprimitive, is_set_rprimitive, is_tuple_rprimitive, is_none_rprimitive, is_object_rprimitive, object_rprimitive, is_str_rprimitive, int_rprimitive, is_optional_type, optional_value_type, is_int32_rprimitive, - is_int64_rprimitive, is_bit_rprimitive, is_range_rprimitive, is_bytes_rprimitive + is_int64_rprimitive, is_bit_rprimitive, is_range_rprimitive, is_bytes_rprimitive, + is_fixed_width_rtype ) from mypyc.ir.func_ir import FuncDecl from mypyc.ir.class_ir import ClassIR, all_concrete_classes @@ -479,9 +480,16 @@ def emit_cast(self, return # TODO: Verify refcount handling. - if (is_list_rprimitive(typ) or is_dict_rprimitive(typ) or is_set_rprimitive(typ) - or is_str_rprimitive(typ) or is_range_rprimitive(typ) or is_float_rprimitive(typ) - or is_int_rprimitive(typ) or is_bool_rprimitive(typ) or is_bit_rprimitive(typ)): + if (is_list_rprimitive(typ) + or is_dict_rprimitive(typ) + or is_set_rprimitive(typ) + or is_str_rprimitive(typ) + or is_range_rprimitive(typ) + or is_float_rprimitive(typ) + or is_int_rprimitive(typ) + or is_bool_rprimitive(typ) + or is_bit_rprimitive(typ) + or is_fixed_width_rtype(typ)): if declare_dest: self.emit_line(f'PyObject *{dest};') if is_list_rprimitive(typ): @@ -496,12 +504,13 @@ def emit_cast(self, prefix = 'PyRange' elif is_float_rprimitive(typ): prefix = 'CPyFloat' - elif is_int_rprimitive(typ): + elif is_int_rprimitive(typ) or is_fixed_width_rtype(typ): + # TODO: Range check for fixed-width types? prefix = 'PyLong' elif is_bool_rprimitive(typ) or is_bit_rprimitive(typ): prefix = 'PyBool' else: - assert False, 'unexpected primitive type' + assert False, f'unexpected primitive type: {typ}' check = '({}_Check({}))' if likely: check = f'(likely{check})' @@ -765,6 +774,20 @@ def emit_unbox(self, self.emit_line(failure) self.emit_line('} else') self.emit_line(f' {dest} = 1;') + elif is_int64_rprimitive(typ): + # Whether we are borrowing or not makes no difference. + if declare_dest: + self.emit_line(f'int64_t {dest};') + self.emit_line(f'{dest} = CPyLong_AsInt64({src});') + # TODO: Handle 'optional' + # TODO: Handle 'failure' + elif is_int32_rprimitive(typ): + # Whether we are borrowing or not makes no difference. + if declare_dest: + self.emit_line('int32_t {};'.format(dest)) + self.emit_line('{} = CPyLong_AsInt32({});'.format(dest, src)) + # TODO: Handle 'optional' + # TODO: Handle 'failure' elif isinstance(typ, RTuple): self.declare_tuple_struct(typ) if declare_dest: diff --git a/mypyc/codegen/emitfunc.py b/mypyc/codegen/emitfunc.py index ce428daaee719..683bf3e7a034f 100644 --- a/mypyc/codegen/emitfunc.py +++ b/mypyc/codegen/emitfunc.py @@ -12,7 +12,8 @@ LoadStatic, InitStatic, TupleGet, TupleSet, Call, IncRef, DecRef, Box, Cast, Unbox, BasicBlock, Value, MethodCall, Unreachable, NAMESPACE_STATIC, NAMESPACE_TYPE, NAMESPACE_MODULE, RaiseStandardError, CallC, LoadGlobal, Truncate, IntOp, LoadMem, GetElementPtr, - LoadAddress, ComparisonOp, SetMem, Register, LoadLiteral, AssignMulti, KeepAlive, ERR_FALSE + LoadAddress, ComparisonOp, SetMem, Register, LoadLiteral, AssignMulti, KeepAlive, Extend, + ERR_FALSE ) from mypyc.ir.rtypes import ( RType, RTuple, RArray, is_tagged, is_int32_rprimitive, is_int64_rprimitive, RStruct, @@ -210,6 +211,10 @@ def visit_assign(self, op: Assign) -> None: # clang whines about self assignment (which we might generate # for some casts), so don't emit it. if dest != src: + # We sometimes assign from an integer prepresentation of a pointer + # to a real pointer, and C compilers insist on a cast. + if op.src.type.is_unboxed and not op.dest.type.is_unboxed: + src = f'(void *){src}' self.emit_line(f'{dest} = {src};') def visit_assign_multi(self, op: AssignMulti) -> None: @@ -538,6 +543,15 @@ def visit_truncate(self, op: Truncate) -> None: # for C backend the generated code are straight assignments self.emit_line(f"{dest} = {value};") + def visit_extend(self, op: Extend) -> None: + dest = self.reg(op) + value = self.reg(op.src) + if op.signed: + src_cast = self.emit_signed_int_cast(op.src.type) + else: + src_cast = self.emit_unsigned_int_cast(op.src.type) + self.emit_line("{} = {}{};".format(dest, src_cast, value)) + def visit_load_global(self, op: LoadGlobal) -> None: dest = self.reg(op) ann = '' @@ -551,6 +565,10 @@ def visit_int_op(self, op: IntOp) -> None: dest = self.reg(op) lhs = self.reg(op.lhs) rhs = self.reg(op.rhs) + if op.op == IntOp.RIGHT_SHIFT: + # Signed right shift + lhs = self.emit_signed_int_cast(op.lhs.type) + lhs + rhs = self.emit_signed_int_cast(op.rhs.type) + rhs self.emit_line(f'{dest} = {lhs} {op.op_str[op.op]} {rhs};') def visit_comparison_op(self, op: ComparisonOp) -> None: @@ -624,7 +642,10 @@ def reg(self, reg: Value) -> str: s = str(val) if val >= (1 << 31): # Avoid overflowing signed 32-bit int - s += 'ULL' + if val >= (1 << 63): + s += 'ULL' + else: + s += 'LL' elif val == -(1 << 63): # Avoid overflowing C integer literal s = '(-9223372036854775807LL - 1)' diff --git a/mypyc/ir/ops.py b/mypyc/ir/ops.py index d36fcfb9e7ebd..8474b5ab58e2a 100644 --- a/mypyc/ir/ops.py +++ b/mypyc/ir/ops.py @@ -21,7 +21,7 @@ RType, RInstance, RTuple, RArray, RVoid, is_bool_rprimitive, is_int_rprimitive, is_short_int_rprimitive, is_none_rprimitive, object_rprimitive, bool_rprimitive, short_int_rprimitive, int_rprimitive, void_rtype, pointer_rprimitive, is_pointer_rprimitive, - bit_rprimitive, is_bit_rprimitive + bit_rprimitive, is_bit_rprimitive, is_fixed_width_rtype ) if TYPE_CHECKING: @@ -90,6 +90,9 @@ def terminator(self) -> 'ControlOp': ERR_FALSE: Final = 2 # Always fails ERR_ALWAYS: Final = 3 +# Like ERR_MAGIC, but the magic return overlaps with a possible return value, and +# an extra PyErr_Occurred() check is also required +ERR_MAGIC_OVERLAPPING: Final = 4 # Hack: using this line number for an op will suppress it in tracebacks NO_TRACEBACK_LINE_NO = -10000 @@ -489,14 +492,17 @@ class Call(RegisterOp): The call target can be a module-level function or a class. """ - error_kind = ERR_MAGIC - def __init__(self, fn: 'FuncDecl', args: Sequence[Value], line: int) -> None: - super().__init__(line) self.fn = fn self.args = list(args) assert len(self.args) == len(fn.sig.args) self.type = fn.sig.ret_type + ret_type = fn.sig.ret_type + if not ret_type.error_overlap: + self.error_kind = ERR_MAGIC + else: + self.error_kind = ERR_MAGIC_OVERLAPPING + super().__init__(line) def sources(self) -> List[Value]: return list(self.args[:]) @@ -508,14 +514,11 @@ def accept(self, visitor: 'OpVisitor[T]') -> T: class MethodCall(RegisterOp): """Native method call obj.method(arg, ...)""" - error_kind = ERR_MAGIC - def __init__(self, obj: Value, method: str, args: List[Value], line: int = -1) -> None: - super().__init__(line) self.obj = obj self.method = method self.args = args @@ -524,7 +527,13 @@ def __init__(self, method_ir = self.receiver_type.class_ir.method_sig(method) assert method_ir is not None, "{} doesn't have method {}".format( self.receiver_type.name, method) - self.type = method_ir.ret_type + ret_type = method_ir.ret_type + self.type = ret_type + if not ret_type.error_overlap: + self.error_kind = ERR_MAGIC + else: + self.error_kind = ERR_MAGIC_OVERLAPPING + super().__init__(line) def sources(self) -> List[Value]: return self.args[:] + [self.obj] @@ -605,8 +614,11 @@ def __init__(self, obj: Value, attr: str, line: int, *, borrow: bool = False) -> self.attr = attr assert isinstance(obj.type, RInstance), 'Attribute access not supported: %s' % obj.type self.class_type = obj.type - self.type = obj.type.attr_type(attr) - self.is_borrowed = borrow + attr_type = obj.type.attr_type(attr) + self.type = attr_type + if is_fixed_width_rtype(attr_type): + self.error_kind = ERR_NEVER + self.is_borrowed = borrow and attr_type.is_refcounted def sources(self) -> List[Value]: return [self.obj] @@ -829,12 +841,14 @@ class Unbox(RegisterOp): representation. Only supported for types with an unboxed representation. """ - error_kind = ERR_MAGIC - def __init__(self, src: Value, typ: RType, line: int) -> None: - super().__init__(line) self.src = src self.type = typ + if not typ.error_overlap: + self.error_kind = ERR_MAGIC + else: + self.error_kind = ERR_MAGIC_OVERLAPPING + super().__init__(line) def sources(self) -> List[Value]: return [self.src] @@ -924,22 +938,20 @@ class Truncate(RegisterOp): Truncate a value from type with more bits to type with less bits. - Both src_type and dst_type should be non-reference counted integer - types or bool. Note that int_rprimitive is reference counted so - it should never be used here. + dst_type and src_type can be native integer types, bools or tagged + integers. Tagged integers should have the tag bit unset. """ error_kind = ERR_NEVER def __init__(self, src: Value, - src_type: RType, dst_type: RType, line: int = -1) -> None: super().__init__(line) self.src = src - self.src_type = src_type self.type = dst_type + self.src_type = src.type def sources(self) -> List[Value]: return [self.src] @@ -951,6 +963,41 @@ def accept(self, visitor: 'OpVisitor[T]') -> T: return visitor.visit_truncate(self) +class Extend(RegisterOp): + """result = extend src from src_type to dst_type + + Extend a value from a type with fewer bits to a type with more bits. + + dst_type and src_type can be native integer types, bools or tagged + integers. Tagged integers should have the tag bit unset. + + If 'signed' is true, perform sign extension. Otherwise, the result will be + zero extended. + """ + + error_kind = ERR_NEVER + + def __init__(self, + src: Value, + dst_type: RType, + signed: bool, + line: int = -1) -> None: + super().__init__(line) + self.src = src + self.type = dst_type + self.src_type = src.type + self.signed = signed + + def sources(self) -> List[Value]: + return [self.src] + + def stolen(self) -> List[Value]: + return [] + + def accept(self, visitor: 'OpVisitor[T]') -> T: + return visitor.visit_extend(self) + + class LoadGlobal(RegisterOp): """Load a low-level global variable/pointer. @@ -1035,6 +1082,11 @@ def accept(self, visitor: 'OpVisitor[T]') -> T: return visitor.visit_int_op(self) +# We can't have this in the IntOp class body, because of +# https://github.com/mypyc/mypyc/issues/932. +int_op_to_id: Final = {op: op_id for op_id, op in IntOp.op_str.items()} + + class ComparisonOp(RegisterOp): """Low-level comparison op for integers and pointers. @@ -1076,6 +1128,15 @@ class ComparisonOp(RegisterOp): UGE: '>=', } + signed_ops: Final = { + '==': EQ, + '!=': NEQ, + '<': SLT, + '>': SGT, + '<=': SLE, + '>=': SGE, + } + def __init__(self, lhs: Value, rhs: Value, op: int, line: int = -1) -> None: super().__init__(line) self.type = bit_rprimitive @@ -1327,6 +1388,10 @@ def visit_call_c(self, op: CallC) -> T: def visit_truncate(self, op: Truncate) -> T: raise NotImplementedError + @abstractmethod + def visit_extend(self, op: Extend) -> T: + raise NotImplementedError + @abstractmethod def visit_load_global(self, op: LoadGlobal) -> T: raise NotImplementedError diff --git a/mypyc/ir/pprint.py b/mypyc/ir/pprint.py index 40243dac96e9c..e6cd721e4c27f 100644 --- a/mypyc/ir/pprint.py +++ b/mypyc/ir/pprint.py @@ -11,7 +11,7 @@ LoadStatic, InitStatic, TupleGet, TupleSet, IncRef, DecRef, Call, MethodCall, Cast, Box, Unbox, RaiseStandardError, CallC, Truncate, LoadGlobal, IntOp, ComparisonOp, LoadMem, SetMem, GetElementPtr, LoadAddress, Register, Value, OpVisitor, BasicBlock, ControlOp, LoadLiteral, - AssignMulti, KeepAlive, Op, ERR_NEVER + AssignMulti, KeepAlive, Op, Extend, ERR_NEVER ) from mypyc.ir.func_ir import FuncIR, all_values_full from mypyc.ir.module_ir import ModuleIRs @@ -172,6 +172,13 @@ def visit_call_c(self, op: CallC) -> str: def visit_truncate(self, op: Truncate) -> str: return self.format("%r = truncate %r: %t to %t", op, op.src, op.src_type, op.type) + def visit_extend(self, op: Extend) -> str: + if op.signed: + extra = ' signed' + else: + extra = '' + return self.format("%r = extend%s %r: %t to %t", op, extra, op.src, op.src_type, op.type) + def visit_load_global(self, op: LoadGlobal) -> str: ann = f' ({repr(op.ann)})' if op.ann else '' return self.format('%r = load_global %s :: static%s', op, op.identifier, ann) diff --git a/mypyc/ir/rtypes.py b/mypyc/ir/rtypes.py index 2c875d7c8f01d..010e25976f1c1 100644 --- a/mypyc/ir/rtypes.py +++ b/mypyc/ir/rtypes.py @@ -45,11 +45,21 @@ class RType: is_unboxed = False # This is the C undefined value for this type. It's used for initialization # if there's no value yet, and for function return value on error/exception. + # + # TODO: This shouldn't be specific to C or a string c_undefined: str # If unboxed: does the unboxed version use reference counting? is_refcounted = True # C type; use Emitter.ctype() to access _ctype: str + # If True, error/undefined value overlaps with a valid value. To + # detect an exception, PyErr_Occurred() must be used in addition + # to checking for error value as the return value of a function. + # + # For example, no i64 value can be reserved for error value, so we + # pick an arbitrary value (e.g. -113) to signal error, but this is + # also a valid non-error value. + error_overlap = False @abstractmethod def accept(self, visitor: 'RTypeVisitor[T]') -> T: @@ -173,29 +183,40 @@ class RPrimitive(RType): def __init__(self, name: str, + *, is_unboxed: bool, is_refcounted: bool, + is_native_int: bool = False, + is_signed: bool = False, ctype: str = 'PyObject *', - size: int = PLATFORM_SIZE) -> None: + size: int = PLATFORM_SIZE, + error_overlap: bool = False) -> None: RPrimitive.primitive_map[name] = self self.name = name self.is_unboxed = is_unboxed - self._ctype = ctype self.is_refcounted = is_refcounted + self.is_native_int = is_native_int + self.is_signed = is_signed + self._ctype = ctype self.size = size - # TODO: For low-level integers, they actually don't have undefined values - # we need to figure out some way to represent here. + self.error_overlap = error_overlap if ctype == 'CPyTagged': self.c_undefined = 'CPY_INT_TAG' - elif ctype in ('int32_t', 'int64_t', 'CPyPtr', 'uint32_t', 'uint64_t'): + elif ctype in ('int32_t', 'int64_t'): + # This is basically an arbitrary value that is pretty + # unlikely to overlap with a real value. + self.c_undefined = '-113' + elif ctype in ('CPyPtr', 'uint32_t', 'uint64_t'): + # TODO: For low-level integers, we need to invent an overlapping + # error value, similar to int64_t above. self.c_undefined = '0' elif ctype == 'PyObject *': # Boxed types use the null pointer as the error value. self.c_undefined = 'NULL' elif ctype == 'char': self.c_undefined = '2' - elif ctype == 'PyObject **': + elif ctype in ('PyObject **', 'void *'): self.c_undefined = 'NULL' else: assert False, 'Unrecognized ctype: %r' % ctype @@ -265,16 +286,42 @@ def __hash__(self) -> int: # Low level integer types (correspond to C integer types) int32_rprimitive: Final = RPrimitive( - "int32", is_unboxed=True, is_refcounted=False, ctype="int32_t", size=4 + "int32", + is_unboxed=True, + is_refcounted=False, + is_native_int=True, + is_signed=True, + ctype="int32_t", + size=4, + error_overlap=True, ) int64_rprimitive: Final = RPrimitive( - "int64", is_unboxed=True, is_refcounted=False, ctype="int64_t", size=8 + "int64", + is_unboxed=True, + is_refcounted=False, + is_native_int=True, + is_signed=True, + ctype="int64_t", + size=8, + error_overlap=True, ) uint32_rprimitive: Final = RPrimitive( - "uint32", is_unboxed=True, is_refcounted=False, ctype="uint32_t", size=4 + "uint32", + is_unboxed=True, + is_refcounted=False, + is_native_int=True, + is_signed=False, + ctype="uint32_t", + size=4, ) uint64_rprimitive: Final = RPrimitive( - "uint64", is_unboxed=True, is_refcounted=False, ctype="uint64_t", size=8 + "uint64", + is_unboxed=True, + is_refcounted=False, + is_native_int=True, + is_signed=False, + ctype="uint64_t", + size=8, ) # The C 'int' type @@ -282,16 +329,34 @@ def __hash__(self) -> int: if IS_32_BIT_PLATFORM: c_size_t_rprimitive = uint32_rprimitive - c_pyssize_t_rprimitive = RPrimitive('native_int', is_unboxed=True, is_refcounted=False, - ctype='int32_t', size=4) + c_pyssize_t_rprimitive = RPrimitive( + 'native_int', + is_unboxed=True, + is_refcounted=False, + is_native_int=True, + is_signed=True, + ctype='int32_t', + size=4, + ) else: c_size_t_rprimitive = uint64_rprimitive - c_pyssize_t_rprimitive = RPrimitive('native_int', is_unboxed=True, is_refcounted=False, - ctype='int64_t', size=8) + c_pyssize_t_rprimitive = RPrimitive( + 'native_int', + is_unboxed=True, + is_refcounted=False, + is_native_int=True, + is_signed=True, + ctype='int64_t', + size=8, + ) -# Low level pointer, represented as integer in C backends +# Untyped pointer, represented as integer in the C backend pointer_rprimitive: Final = RPrimitive("ptr", is_unboxed=True, is_refcounted=False, ctype="CPyPtr") +# Untyped pointer, represented as void * in the C backend +c_pointer_rprimitive: Final = RPrimitive("c_ptr", is_unboxed=False, is_refcounted=False, + ctype="void *") + # Floats are represent as 'float' PyObject * values. (In the future # we'll likely switch to a more efficient, unboxed representation.) float_rprimitive: Final = RPrimitive("builtins.float", is_unboxed=False, is_refcounted=True) @@ -361,6 +426,10 @@ def is_int64_rprimitive(rtype: RType) -> bool: (rtype is c_pyssize_t_rprimitive and rtype._ctype == 'int64_t')) +def is_fixed_width_rtype(rtype: RType) -> bool: + return is_int32_rprimitive(rtype) or is_int64_rprimitive(rtype) + + def is_uint32_rprimitive(rtype: RType) -> bool: return rtype is uint32_rprimitive @@ -445,6 +514,10 @@ def visit_rprimitive(self, t: 'RPrimitive') -> str: return 'I' elif t._ctype == 'char': return 'C' + elif t._ctype == 'int64_t': + return '8' # "8 byte integer" + elif t._ctype == 'int32_t': + return '4' # "4 byte integer" assert not t.is_unboxed, f"{t} unexpected unboxed type" return 'O' diff --git a/mypyc/irbuild/ll_builder.py b/mypyc/irbuild/ll_builder.py index d5154707538b7..20c8e3a80acfb 100644 --- a/mypyc/irbuild/ll_builder.py +++ b/mypyc/irbuild/ll_builder.py @@ -1337,7 +1337,7 @@ def call_c(self, if desc.truncated_type is None: result = target else: - truncate = self.add(Truncate(target, desc.return_type, desc.truncated_type)) + truncate = self.add(Truncate(target, desc.truncated_type)) result = truncate if result_type and not is_runtime_subtype(result.type, result_type): if is_none_rprimitive(result_type): diff --git a/mypyc/subtype.py b/mypyc/subtype.py index 7e852f33bf4a1..4ba8f6301c63e 100644 --- a/mypyc/subtype.py +++ b/mypyc/subtype.py @@ -3,7 +3,7 @@ from mypyc.ir.rtypes import ( RType, RInstance, RPrimitive, RTuple, RVoid, RTypeVisitor, RUnion, RStruct, RArray, is_bool_rprimitive, is_int_rprimitive, is_tuple_rprimitive, is_short_int_rprimitive, - is_object_rprimitive, is_bit_rprimitive + is_object_rprimitive, is_bit_rprimitive, is_tagged, is_fixed_width_rtype ) @@ -43,14 +43,17 @@ def visit_runion(self, left: RUnion) -> bool: def visit_rprimitive(self, left: RPrimitive) -> bool: right = self.right if is_bool_rprimitive(left): - if is_int_rprimitive(right): + if is_tagged(right) or is_fixed_width_rtype(right): return True elif is_bit_rprimitive(left): - if is_bool_rprimitive(right) or is_int_rprimitive(right): + if is_bool_rprimitive(right) or is_tagged(right) or is_fixed_width_rtype(right): return True elif is_short_int_rprimitive(left): if is_int_rprimitive(right): return True + elif is_fixed_width_rtype(left): + if is_int_rprimitive(right): + return True return left is right def visit_rtuple(self, left: RTuple) -> bool: diff --git a/mypyc/test/test_emitfunc.py b/mypyc/test/test_emitfunc.py index 96d9155214b30..8ea0906aec613 100644 --- a/mypyc/test/test_emitfunc.py +++ b/mypyc/test/test_emitfunc.py @@ -9,7 +9,7 @@ from mypyc.ir.ops import ( BasicBlock, Goto, Return, Integer, Assign, AssignMulti, IncRef, DecRef, Branch, Call, Unbox, Box, TupleGet, GetAttr, SetAttr, Op, Value, CallC, IntOp, LoadMem, - GetElementPtr, LoadAddress, ComparisonOp, SetMem, Register, Unreachable, Cast + GetElementPtr, LoadAddress, ComparisonOp, SetMem, Register, Unreachable, Cast, Extend ) from mypyc.ir.rtypes import ( RTuple, RInstance, RType, RArray, int_rprimitive, bool_rprimitive, list_rprimitive, @@ -31,6 +31,7 @@ from mypyc.primitives.int_ops import int_neg_op from mypyc.subtype import is_subtype from mypyc.namegen import NameGenerator +from mypyc.common import PLATFORM_SIZE class TestFunctionEmitterVisitor(unittest.TestCase): @@ -258,11 +259,11 @@ def test_list_set_item(self) -> None: list_set_item_op.is_borrowed, list_set_item_op.error_kind, 55), """cpy_r_r0 = CPyList_SetItem(cpy_r_l, cpy_r_n, cpy_r_o);""") - def test_box(self) -> None: + def test_box_int(self) -> None: self.assert_emit(Box(self.n), """cpy_r_r0 = CPyTagged_StealAsObject(cpy_r_n);""") - def test_unbox(self) -> None: + def test_unbox_int(self) -> None: self.assert_emit(Unbox(self.m, int_rprimitive, 55), """if (likely(PyLong_Check(cpy_r_m))) cpy_r_r0 = CPyTagged_FromObject(cpy_r_m); @@ -271,6 +272,14 @@ def test_unbox(self) -> None: } """) + def test_box_i64(self) -> None: + self.assert_emit(Box(self.i64), + """cpy_r_r0 = PyLong_FromLongLong(cpy_r_i64);""") + + def test_unbox_i64(self) -> None: + self.assert_emit(Unbox(self.o, int64_rprimitive, 55), + """cpy_r_r0 = CPyLong_AsInt64(cpy_r_o);""") + def test_list_append(self) -> None: self.assert_emit(CallC(list_append_op.c_function_name, [self.l, self.o], list_append_op.return_type, list_append_op.steals, @@ -382,7 +391,9 @@ def test_int_op(self) -> None: self.assert_emit(IntOp(short_int_rprimitive, self.s1, self.s2, IntOp.LEFT_SHIFT, 1), """cpy_r_r0 = cpy_r_s1 << cpy_r_s2;""") self.assert_emit(IntOp(short_int_rprimitive, self.s1, self.s2, IntOp.RIGHT_SHIFT, 1), - """cpy_r_r0 = cpy_r_s1 >> cpy_r_s2;""") + """cpy_r_r0 = (Py_ssize_t)cpy_r_s1 >> (Py_ssize_t)cpy_r_s2;""") + self.assert_emit(IntOp(short_int_rprimitive, self.i64, self.i64_1, IntOp.RIGHT_SHIFT, 1), + """cpy_r_r0 = cpy_r_i64 >> cpy_r_i64_1;""") def test_comparison_op(self) -> None: # signed @@ -438,7 +449,7 @@ def test_assign_multi(self) -> None: def test_long_unsigned(self) -> None: a = Register(int64_rprimitive, 'a') self.assert_emit(Assign(a, Integer(1 << 31, int64_rprimitive)), - """cpy_r_a = 2147483648ULL;""") + """cpy_r_a = 2147483648LL;""") self.assert_emit(Assign(a, Integer((1 << 31) - 1, int64_rprimitive)), """cpy_r_a = 2147483647;""") @@ -545,6 +556,23 @@ def test_cast_and_branch_no_merge_4(self) -> None: next_branch=branch, ) + def test_extend(self) -> None: + a = Register(int32_rprimitive, 'a') + self.assert_emit(Extend(a, int64_rprimitive, signed=True), + """cpy_r_r0 = cpy_r_a;""") + self.assert_emit(Extend(a, int64_rprimitive, signed=False), + """cpy_r_r0 = (uint32_t)cpy_r_a;""") + if PLATFORM_SIZE == 4: + self.assert_emit(Extend(self.n, int64_rprimitive, signed=True), + """cpy_r_r0 = (Py_ssize_t)cpy_r_n;""") + self.assert_emit(Extend(self.n, int64_rprimitive, signed=False), + """cpy_r_r0 = cpy_r_n;""") + if PLATFORM_SIZE == 8: + self.assert_emit(Extend(a, int_rprimitive, signed=True), + """cpy_r_r0 = cpy_r_a;""") + self.assert_emit(Extend(a, int_rprimitive, signed=False), + """cpy_r_r0 = (uint32_t)cpy_r_a;""") + def assert_emit(self, op: Op, expected: str, diff --git a/mypyc/test/test_subtype.py b/mypyc/test/test_subtype.py index e106a1eaa4b73..e006e5425174d 100644 --- a/mypyc/test/test_subtype.py +++ b/mypyc/test/test_subtype.py @@ -2,7 +2,10 @@ import unittest -from mypyc.ir.rtypes import bit_rprimitive, bool_rprimitive, int_rprimitive +from mypyc.ir.rtypes import ( + bit_rprimitive, bool_rprimitive, int_rprimitive, int64_rprimitive, int32_rprimitive, + short_int_rprimitive +) from mypyc.subtype import is_subtype from mypyc.rt_subtype import is_runtime_subtype @@ -11,10 +14,26 @@ class TestSubtype(unittest.TestCase): def test_bit(self) -> None: assert is_subtype(bit_rprimitive, bool_rprimitive) assert is_subtype(bit_rprimitive, int_rprimitive) + assert is_subtype(bit_rprimitive, short_int_rprimitive) + assert is_subtype(bit_rprimitive, int64_rprimitive) + assert is_subtype(bit_rprimitive, int32_rprimitive) def test_bool(self) -> None: assert not is_subtype(bool_rprimitive, bit_rprimitive) assert is_subtype(bool_rprimitive, int_rprimitive) + assert is_subtype(bool_rprimitive, short_int_rprimitive) + assert is_subtype(bool_rprimitive, int64_rprimitive) + assert is_subtype(bool_rprimitive, int32_rprimitive) + + def test_int64(self) -> None: + assert is_subtype(int64_rprimitive, int_rprimitive) + assert not is_subtype(int64_rprimitive, short_int_rprimitive) + assert not is_subtype(int64_rprimitive, int32_rprimitive) + + def test_int32(self) -> None: + assert is_subtype(int32_rprimitive, int_rprimitive) + assert not is_subtype(int32_rprimitive, short_int_rprimitive) + assert not is_subtype(int32_rprimitive, int64_rprimitive) class TestRuntimeSubtype(unittest.TestCase): diff --git a/mypyc/transform/exceptions.py b/mypyc/transform/exceptions.py index 52b25aceffe39..e845de1fcf191 100644 --- a/mypyc/transform/exceptions.py +++ b/mypyc/transform/exceptions.py @@ -12,11 +12,14 @@ from typing import List, Optional from mypyc.ir.ops import ( - Value, BasicBlock, LoadErrorValue, Return, Branch, RegisterOp, Integer, ERR_NEVER, ERR_MAGIC, - ERR_FALSE, ERR_ALWAYS, NO_TRACEBACK_LINE_NO + Value, BasicBlock, LoadErrorValue, Return, Branch, RegisterOp, ComparisonOp, CallC, + Integer, ERR_NEVER, ERR_MAGIC, ERR_FALSE, ERR_ALWAYS, ERR_MAGIC_OVERLAPPING, + NO_TRACEBACK_LINE_NO ) from mypyc.ir.func_ir import FuncIR from mypyc.ir.rtypes import bool_rprimitive +from mypyc.primitives.registry import CFunctionDescription +from mypyc.primitives.exc_ops import err_occurred_op def insert_exception_handling(ir: FuncIR) -> None: @@ -81,6 +84,20 @@ def split_blocks_at_errors(blocks: List[BasicBlock], # this is a hack to represent the always fail # semantics, using a temporary bool with value false target = Integer(0, bool_rprimitive) + elif op.error_kind == ERR_MAGIC_OVERLAPPING: + errvalue = Integer(int(target.type.c_undefined), rtype=op.type) + comp = ComparisonOp(target, errvalue, ComparisonOp.EQ) + cur_block.ops.append(comp) + new_block2 = BasicBlock() + new_blocks.append(new_block2) + branch = Branch(comp, true_label=new_block2, false_label=new_block, + op=Branch.BOOL) + cur_block.ops.append(branch) + cur_block = new_block2 + target = primitive_call(err_occurred_op, [], target.line) + cur_block.ops.append(target) + variant = Branch.IS_ERROR + negated = True else: assert False, 'unknown error kind %d' % op.error_kind @@ -101,3 +118,15 @@ def split_blocks_at_errors(blocks: List[BasicBlock], cur_block = new_block return new_blocks + + +def primitive_call(desc: CFunctionDescription, args: List[Value], line: int) -> CallC: + return CallC( + desc.c_function_name, + [], + desc.return_type, + desc.steals, + desc.is_borrowed, + desc.error_kind, + line, + ) From 132b8e527730b654a3f3d04684bebc9daff6cabd Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Tue, 14 Jun 2022 13:19:08 -0700 Subject: [PATCH 351/377] Update stubinfo for py.typed and removed packages (#12959) https://github.com/python/typeshed/pull/8042 https://github.com/python/typeshed/pull/8043 https://github.com/python/typeshed/pull/8044 https://github.com/python/typeshed/pull/8045 https://github.com/python/typeshed/pull/8046 https://github.com/python/typeshed/pull/8040 Co-authored-by: hauntsaninja <> --- mypy/stubinfo.py | 5 ----- mypy/test/teststubinfo.py | 4 ++-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/mypy/stubinfo.py b/mypy/stubinfo.py index d1bcb4a6c157f..fb034162c7dc5 100644 --- a/mypy/stubinfo.py +++ b/mypy/stubinfo.py @@ -29,8 +29,6 @@ def is_legacy_bundled_package(prefix: str, py_version: int) -> bool: 'bleach': StubInfo('types-bleach'), 'boto': StubInfo('types-boto'), 'cachetools': StubInfo('types-cachetools'), - 'certifi': StubInfo('types-certifi'), - 'characteristic': StubInfo('types-characteristic'), 'chardet': StubInfo('types-chardet'), 'click_spinner': StubInfo('types-click-spinner'), 'concurrent': StubInfo('types-futures', py_version=2), @@ -46,10 +44,7 @@ def is_legacy_bundled_package(prefix: str, py_version: int) -> bool: 'emoji': StubInfo('types-emoji'), 'enum': StubInfo('types-enum34', py_version=2), 'fb303': StubInfo('types-fb303', py_version=2), - 'filelock': StubInfo('types-filelock', py_version=3), 'first': StubInfo('types-first'), - 'freezegun': StubInfo('types-freezegun', py_version=3), - 'frozendict': StubInfo('types-frozendict', py_version=3), 'geoip2': StubInfo('types-geoip2'), 'gflags': StubInfo('types-python-gflags'), 'google.protobuf': StubInfo('types-protobuf'), diff --git a/mypy/test/teststubinfo.py b/mypy/test/teststubinfo.py index 62346ce2bc9fe..e00a68a24df0d 100644 --- a/mypy/test/teststubinfo.py +++ b/mypy/test/teststubinfo.py @@ -8,8 +8,8 @@ def test_is_legacy_bundled_packages(self) -> None: assert not is_legacy_bundled_package('foobar_asdf', 2) assert not is_legacy_bundled_package('foobar_asdf', 3) - assert is_legacy_bundled_package('certifi', 2) - assert is_legacy_bundled_package('certifi', 3) + assert is_legacy_bundled_package('pycurl', 2) + assert is_legacy_bundled_package('pycurl', 3) assert is_legacy_bundled_package('scribe', 2) assert not is_legacy_bundled_package('scribe', 3) From 145d8a41b17ab1ba8707589be9cb5d56bbebd0ea Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Thu, 16 Jun 2022 10:51:45 +0100 Subject: [PATCH 352/377] Add a short note when an error may be fixed by adding an await (#12958) I only cover few most common situations. If this will show to be useful, we can expand the scope of this note. --- mypy/checker.py | 54 ++++++++++++++++++++++++- mypy/checkexpr.py | 11 +++++- mypy/checkmember.py | 41 +++++++++++++++---- mypy/messages.py | 3 ++ test-data/unit/check-async-await.test | 55 ++++++++++++++++++++++++++ test-data/unit/deps.test | 5 ++- test-data/unit/pythoneval-asyncio.test | 1 + 7 files changed, 158 insertions(+), 12 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 688fbd28739d4..39f3fa42942d4 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -12,7 +12,7 @@ from typing_extensions import Final, TypeAlias as _TypeAlias from mypy.backports import nullcontext -from mypy.errors import Errors, report_internal_error +from mypy.errors import Errors, report_internal_error, ErrorWatcher from mypy.nodes import ( SymbolTable, Statement, MypyFile, Var, Expression, Lvalue, Node, OverloadedFuncDef, FuncDef, FuncItem, FuncBase, TypeInfo, @@ -38,7 +38,7 @@ is_named_instance, union_items, TypeQuery, LiteralType, is_optional, remove_optional, TypeTranslator, StarType, get_proper_type, ProperType, get_proper_types, is_literal_type, TypeAliasType, TypeGuardedType, ParamSpecType, - OVERLOAD_NAMES, + OVERLOAD_NAMES, UnboundType ) from mypy.sametypes import is_same_type from mypy.messages import ( @@ -276,6 +276,10 @@ def __init__(self, errors: Errors, modules: Dict[str, MypyFile], options: Option # argument through various `checker` and `checkmember` functions. self._is_final_def = False + # This flag is set when we run type-check or attribute access check for the purpose + # of giving a note on possibly missing "await". It is used to avoid infinite recursion. + self.checking_missing_await = False + @property def type_context(self) -> List[Optional[Type]]: return self.expr_checker.type_context @@ -5285,8 +5289,54 @@ def check_subtype(self, call = find_member('__call__', supertype, subtype, is_operator=True) assert call is not None self.msg.note_call(supertype, call, context, code=code) + self.check_possible_missing_await(subtype, supertype, context) return False + def get_precise_awaitable_type(self, typ: Type, local_errors: ErrorWatcher) -> Optional[Type]: + """If type implements Awaitable[X] with non-Any X, return X. + + In all other cases return None. This method must be called in context + of local_errors. + """ + if isinstance(get_proper_type(typ), PartialType): + # Partial types are special, ignore them here. + return None + try: + aw_type = self.expr_checker.check_awaitable_expr( + typ, Context(), '', ignore_binder=True + ) + except KeyError: + # This is a hack to speed up tests by not including Awaitable in all typing stubs. + return None + if local_errors.has_new_errors(): + return None + if isinstance(get_proper_type(aw_type), (AnyType, UnboundType)): + return None + return aw_type + + @contextmanager + def checking_await_set(self) -> Iterator[None]: + self.checking_missing_await = True + try: + yield + finally: + self.checking_missing_await = False + + def check_possible_missing_await( + self, subtype: Type, supertype: Type, context: Context + ) -> None: + """Check if the given type becomes a subtype when awaited.""" + if self.checking_missing_await: + # Avoid infinite recursion. + return + with self.checking_await_set(), self.msg.filter_errors() as local_errors: + aw_type = self.get_precise_awaitable_type(subtype, local_errors) + if aw_type is None: + return + if not self.check_subtype(aw_type, supertype, context): + return + self.msg.possible_missing_await(context) + def contains_none(self, t: Type) -> bool: t = get_proper_type(t) return ( diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 193e56b6002f7..055aba8de08b6 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -1573,6 +1573,7 @@ def check_arg(self, outer_context=outer_context) self.msg.incompatible_argument_note(original_caller_type, callee_type, context, code=code) + self.chk.check_possible_missing_await(caller_type, callee_type, context) def check_overload_call(self, callee: Overloaded, @@ -4119,7 +4120,9 @@ def visit_await_expr(self, e: AwaitExpr, allow_none_return: bool = False) -> Typ self.chk.msg.does_not_return_value(None, e) return ret - def check_awaitable_expr(self, t: Type, ctx: Context, msg: Union[str, ErrorMessage]) -> Type: + def check_awaitable_expr( + self, t: Type, ctx: Context, msg: Union[str, ErrorMessage], ignore_binder: bool = False + ) -> Type: """Check the argument to `await` and extract the type of value. Also used by `async for` and `async with`. @@ -4131,7 +4134,11 @@ def check_awaitable_expr(self, t: Type, ctx: Context, msg: Union[str, ErrorMessa generator = self.check_method_call_by_name('__await__', t, [], [], ctx)[0] ret_type = self.chk.get_generator_return_type(generator, False) ret_type = get_proper_type(ret_type) - if isinstance(ret_type, UninhabitedType) and not ret_type.ambiguous: + if ( + not ignore_binder + and isinstance(ret_type, UninhabitedType) + and not ret_type.ambiguous + ): self.chk.binder.unreachable() return ret_type diff --git a/mypy/checkmember.py b/mypy/checkmember.py index 964ab301d171d..2172361ea2f00 100644 --- a/mypy/checkmember.py +++ b/mypy/checkmember.py @@ -171,7 +171,38 @@ def _analyze_member_access(name: str, return AnyType(TypeOfAny.from_error) if mx.chk.should_suppress_optional_error([typ]): return AnyType(TypeOfAny.from_error) - return mx.msg.has_no_attr(mx.original_type, typ, name, mx.context, mx.module_symbol_table) + return report_missing_attribute(mx.original_type, typ, name, mx) + + +def may_be_awaitable_attribute( + name: str, + typ: Type, + mx: MemberContext, + override_info: Optional[TypeInfo] = None +) -> bool: + """Check if the given type has the attribute when awaited.""" + if mx.chk.checking_missing_await: + # Avoid infinite recursion. + return False + with mx.chk.checking_await_set(), mx.msg.filter_errors() as local_errors: + aw_type = mx.chk.get_precise_awaitable_type(typ, local_errors) + if aw_type is None: + return False + _ = _analyze_member_access(name, aw_type, mx, override_info) + return not local_errors.has_new_errors() + + +def report_missing_attribute( + original_type: Type, + typ: Type, + name: str, + mx: MemberContext, + override_info: Optional[TypeInfo] = None +) -> Type: + res_type = mx.msg.has_no_attr(original_type, typ, name, mx.context, mx.module_symbol_table) + if may_be_awaitable_attribute(name, typ, mx, override_info): + mx.msg.possible_missing_await(mx.context) + return res_type # The several functions that follow implement analyze_member_access for various @@ -438,9 +469,7 @@ def analyze_member_var_access(name: str, else: if mx.chk and mx.chk.should_suppress_optional_error([itype]): return AnyType(TypeOfAny.from_error) - return mx.msg.has_no_attr( - mx.original_type, itype, name, mx.context, mx.module_symbol_table - ) + return report_missing_attribute(mx.original_type, itype, name, mx) def check_final_member(name: str, info: TypeInfo, msg: MessageBuilder, ctx: Context) -> None: @@ -851,9 +880,7 @@ def analyze_enum_class_attribute_access(itype: Instance, ) -> Optional[Type]: # Skip these since Enum will remove it if name in ENUM_REMOVED_PROPS: - return mx.msg.has_no_attr( - mx.original_type, itype, name, mx.context, mx.module_symbol_table - ) + return report_missing_attribute(mx.original_type, itype, name, mx) # For other names surrendered by underscores, we don't make them Enum members if name.startswith('__') and name.endswith("__") and name.replace('_', '') != '': return None diff --git a/mypy/messages.py b/mypy/messages.py index b60f40bce5610..1d6641c00a615 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -806,6 +806,9 @@ def unpacking_strings_disallowed(self, context: Context) -> None: def type_not_iterable(self, type: Type, context: Context) -> None: self.fail(f'{format_type(type)} object is not iterable', context) + def possible_missing_await(self, context: Context) -> None: + self.note('Maybe you forgot to use "await"?', context) + def incompatible_operator_assignment(self, op: str, context: Context) -> None: self.fail(f'Result type of {op} incompatible in assignment', diff --git a/test-data/unit/check-async-await.test b/test-data/unit/check-async-await.test index 4d856db869a7b..950c64098cf08 100644 --- a/test-data/unit/check-async-await.test +++ b/test-data/unit/check-async-await.test @@ -865,6 +865,60 @@ async with C() as x: # E: "async with" outside async function [builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] +[case testAwaitMissingNote] +# flags: --python-version 3.7 +from typing import Generic, TypeVar, Generator, Any, Awaitable, Type + +class C: + x: int +class D(C): ... + +async def foo() -> D: ... +def g(x: C) -> None: ... + +T = TypeVar("T") +class Custom(Generic[T]): + def __await__(self) -> Generator[Any, Any, T]: ... + +class Sub(Custom[T]): ... + +async def test(x: Sub[D], tx: Type[Sub[D]]) -> None: + foo().x # E: "Coroutine[Any, Any, D]" has no attribute "x" \ + # N: Maybe you forgot to use "await"? + (await foo()).x + foo().bad # E: "Coroutine[Any, Any, D]" has no attribute "bad" + + g(foo()) # E: Argument 1 to "g" has incompatible type "Coroutine[Any, Any, D]"; expected "C" \ + # N: Maybe you forgot to use "await"? + g(await foo()) + unknown: Awaitable[Any] + g(unknown) # E: Argument 1 to "g" has incompatible type "Awaitable[Any]"; expected "C" + + x.x # E: "Sub[D]" has no attribute "x" \ + # N: Maybe you forgot to use "await"? + (await x).x + x.bad # E: "Sub[D]" has no attribute "bad" + + a: C = x # E: Incompatible types in assignment (expression has type "Sub[D]", variable has type "C") \ + # N: Maybe you forgot to use "await"? + b: C = await x + unknown2: Awaitable[Any] + d: C = unknown2 # E: Incompatible types in assignment (expression has type "Awaitable[Any]", variable has type "C") + + # The notes are not show for Type[...] (because awaiting them will not work) + tx.x # E: "Type[Sub[D]]" has no attribute "x" + a2: C = tx # E: Incompatible types in assignment (expression has type "Type[Sub[D]]", variable has type "C") + +class F: + def __await__(self: T) -> Generator[Any, Any, T]: ... +class G(F): ... + +# This should not crash. +x: int = G() # E: Incompatible types in assignment (expression has type "G", variable has type "int") + +[builtins fixtures/async_await.pyi] +[typing fixtures/typing-async.pyi] + [case testAsyncGeneratorExpressionAwait] from typing import AsyncGenerator @@ -874,4 +928,5 @@ async def f() -> AsyncGenerator[int, None]: return (await g(x) for x in [1, 2, 3]) +[builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] diff --git a/test-data/unit/deps.test b/test-data/unit/deps.test index fd593a975ca07..53156b6f4f48b 100644 --- a/test-data/unit/deps.test +++ b/test-data/unit/deps.test @@ -872,6 +872,8 @@ c.y # type: ignore -> m -> m -> m + -> + -> typing.Awaitable [case testIgnoredMissingInstanceAttribute] from a import C @@ -879,10 +881,11 @@ C().x # type: ignore [file a.py] class C: pass [out] + -> -> m -> m -> m - -> m + -> m, typing.Awaitable -> m [case testIgnoredMissingClassAttribute] diff --git a/test-data/unit/pythoneval-asyncio.test b/test-data/unit/pythoneval-asyncio.test index 72e4bc9cc9dd0..97dd9d4f0a55d 100644 --- a/test-data/unit/pythoneval-asyncio.test +++ b/test-data/unit/pythoneval-asyncio.test @@ -429,6 +429,7 @@ loop.run_until_complete(h()) loop.close() [out] _program.py:16: error: Incompatible return value type (got "Future[Future[int]]", expected "Future[int]") +_program.py:16: note: Maybe you forgot to use "await"? [case testErrorAssignmentDifferentType] import typing From eb1b1e007e7fd1e976e6dd0f49a71b662a30a2d6 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 16 Jun 2022 18:42:20 +0100 Subject: [PATCH 353/377] [mypyc] Native int primitives (#12973) Add various C primitives that will be used to support native ints. The primitives aren't used for anything yet. I'll prepare follow-up PRs that use the primitives and include tests. I'm splitting these into a separate PR to make this easier to review. All of these are tested in my local branch, at least to a basic level. Most of these are fairly straightforward, but we need to jump through some hoops to make the semantics of // and % operators compatible with Python semantics when using negative operands. Work on mypyc/mypyc#837. --- mypyc/lib-rt/CPy.h | 17 +++++ mypyc/lib-rt/int_ops.c | 135 +++++++++++++++++++++++++++++++++++ mypyc/lib-rt/list_ops.c | 58 +++++++++++++++ mypyc/lib-rt/mypyc_util.h | 3 + mypyc/primitives/int_ops.py | 61 +++++++++++++++- mypyc/primitives/list_ops.py | 33 ++++++++- 6 files changed, 303 insertions(+), 4 deletions(-) diff --git a/mypyc/lib-rt/CPy.h b/mypyc/lib-rt/CPy.h index f482e09cbe796..ca8bc31140af4 100644 --- a/mypyc/lib-rt/CPy.h +++ b/mypyc/lib-rt/CPy.h @@ -122,6 +122,7 @@ static inline size_t CPy_FindAttrOffset(PyTypeObject *trait, CPyVTableItem *vtab CPyTagged CPyTagged_FromSsize_t(Py_ssize_t value); CPyTagged CPyTagged_FromVoidPtr(void *ptr); +CPyTagged CPyTagged_FromInt64(int64_t value); CPyTagged CPyTagged_FromObject(PyObject *object); CPyTagged CPyTagged_StealFromObject(PyObject *object); CPyTagged CPyTagged_BorrowFromObject(PyObject *object); @@ -150,6 +151,13 @@ PyObject *CPyLong_FromStrWithBase(PyObject *o, CPyTagged base); PyObject *CPyLong_FromStr(PyObject *o); PyObject *CPyLong_FromFloat(PyObject *o); PyObject *CPyBool_Str(bool b); +int64_t CPyLong_AsInt64(PyObject *o); +int64_t CPyInt64_Divide(int64_t x, int64_t y); +int64_t CPyInt64_Remainder(int64_t x, int64_t y); +int32_t CPyLong_AsInt32(PyObject *o); +int32_t CPyInt32_Divide(int32_t x, int32_t y); +int32_t CPyInt32_Remainder(int32_t x, int32_t y); +void CPyInt32_Overflow(void); static inline int CPyTagged_CheckLong(CPyTagged x) { return x & CPY_INT_TAG; @@ -193,6 +201,12 @@ static inline bool CPyTagged_TooBig(Py_ssize_t value) { && (value >= 0 || value < CPY_TAGGED_MIN); } +static inline bool CPyTagged_TooBigInt64(int64_t value) { + // Micro-optimized for the common case where it fits. + return (uint64_t)value > CPY_TAGGED_MAX + && (value >= 0 || value < CPY_TAGGED_MIN); +} + static inline bool CPyTagged_IsAddOverflow(CPyTagged sum, CPyTagged left, CPyTagged right) { // This check was copied from some of my old code I believe that it works :-) return (Py_ssize_t)(sum ^ left) < 0 && (Py_ssize_t)(sum ^ right) < 0; @@ -342,8 +356,11 @@ PyObject *CPyList_GetItemUnsafe(PyObject *list, CPyTagged index); PyObject *CPyList_GetItemShort(PyObject *list, CPyTagged index); PyObject *CPyList_GetItemBorrow(PyObject *list, CPyTagged index); PyObject *CPyList_GetItemShortBorrow(PyObject *list, CPyTagged index); +PyObject *CPyList_GetItemInt64(PyObject *list, int64_t index); +PyObject *CPyList_GetItemInt64Borrow(PyObject *list, int64_t index); bool CPyList_SetItem(PyObject *list, CPyTagged index, PyObject *value); bool CPyList_SetItemUnsafe(PyObject *list, CPyTagged index, PyObject *value); +bool CPyList_SetItemInt64(PyObject *list, int64_t index, PyObject *value); PyObject *CPyList_PopLast(PyObject *obj); PyObject *CPyList_Pop(PyObject *obj, CPyTagged index); CPyTagged CPyList_Count(PyObject *obj, PyObject *value); diff --git a/mypyc/lib-rt/int_ops.c b/mypyc/lib-rt/int_ops.c index caf0fe0b53918..42e6908384f64 100644 --- a/mypyc/lib-rt/int_ops.c +++ b/mypyc/lib-rt/int_ops.c @@ -35,6 +35,15 @@ CPyTagged CPyTagged_FromVoidPtr(void *ptr) { } } +CPyTagged CPyTagged_FromInt64(int64_t value) { + if (unlikely(CPyTagged_TooBigInt64(value))) { + PyObject *object = PyLong_FromLongLong(value); + return ((CPyTagged)object) | CPY_INT_TAG; + } else { + return value << 1; + } +} + CPyTagged CPyTagged_FromObject(PyObject *object) { int overflow; // The overflow check knows about CPyTagged's width @@ -504,3 +513,129 @@ CPyTagged CPyTagged_Lshift(CPyTagged left, CPyTagged right) { } return CPyTagged_StealFromObject(result); } + +int64_t CPyLong_AsInt64(PyObject *o) { + if (likely(PyLong_Check(o))) { + PyLongObject *lobj = (PyLongObject *)o; + Py_ssize_t size = Py_SIZE(lobj); + if (likely(size == 1)) { + // Fast path + return lobj->ob_digit[0]; + } else if (likely(size == 0)) { + return 0; + } + } + // Slow path + int overflow; + int64_t result = PyLong_AsLongLongAndOverflow(o, &overflow); + if (result == -1) { + if (PyErr_Occurred()) { + return CPY_LL_INT_ERROR; + } else if (overflow) { + PyErr_SetString(PyExc_OverflowError, "int too large to convert to i64"); + return CPY_LL_INT_ERROR; + } + } + return result; +} + +int64_t CPyInt64_Divide(int64_t x, int64_t y) { + if (y == 0) { + PyErr_SetString(PyExc_ZeroDivisionError, "integer division or modulo by zero"); + return CPY_LL_INT_ERROR; + } + if (y == -1 && x == -1LL << 63) { + PyErr_SetString(PyExc_OverflowError, "integer division overflow"); + return CPY_LL_INT_ERROR; + } + int64_t d = x / y; + // Adjust for Python semantics + if (((x < 0) != (y < 0)) && d * y != x) { + d--; + } + return d; +} + +int64_t CPyInt64_Remainder(int64_t x, int64_t y) { + if (y == 0) { + PyErr_SetString(PyExc_ZeroDivisionError, "integer division or modulo by zero"); + return CPY_LL_INT_ERROR; + } + // Edge case: avoid core dump + if (y == -1 && x == -1LL << 63) { + return 0; + } + int64_t d = x % y; + // Adjust for Python semantics + if (((x < 0) != (y < 0)) && d != 0) { + d += y; + } + return d; +} + +int32_t CPyLong_AsInt32(PyObject *o) { + if (likely(PyLong_Check(o))) { + PyLongObject *lobj = (PyLongObject *)o; + Py_ssize_t size = lobj->ob_base.ob_size; + if (likely(size == 1)) { + // Fast path + return lobj->ob_digit[0]; + } else if (likely(size == 0)) { + return 0; + } + } + // Slow path + int overflow; + long result = PyLong_AsLongAndOverflow(o, &overflow); + if (result > 0x7fffffffLL || result < -0x80000000LL) { + overflow = 1; + result = -1; + } + if (result == -1) { + if (PyErr_Occurred()) { + return CPY_LL_INT_ERROR; + } else if (overflow) { + PyErr_SetString(PyExc_OverflowError, "int too large to convert to i32"); + return CPY_LL_INT_ERROR; + } + } + return result; +} + +int32_t CPyInt32_Divide(int32_t x, int32_t y) { + if (y == 0) { + PyErr_SetString(PyExc_ZeroDivisionError, "integer division or modulo by zero"); + return CPY_LL_INT_ERROR; + } + if (y == -1 && x == -1LL << 31) { + PyErr_SetString(PyExc_OverflowError, "integer division overflow"); + return CPY_LL_INT_ERROR; + } + int32_t d = x / y; + // Adjust for Python semantics + if (((x < 0) != (y < 0)) && d * y != x) { + d--; + } + return d; +} + +int32_t CPyInt32_Remainder(int32_t x, int32_t y) { + if (y == 0) { + PyErr_SetString(PyExc_ZeroDivisionError, "integer division or modulo by zero"); + return CPY_LL_INT_ERROR; + } + // Edge case: avoid core dump + if (y == -1 && x == -1LL << 31) { + return 0; + } + int32_t d = x % y; + // Adjust for Python semantics + if (((x < 0) != (y < 0)) && d != 0) { + d += y; + } + return d; +} + +void CPyInt32_Overflow() { + PyErr_SetString(PyExc_OverflowError, "int too large to convert to i32"); +} diff --git a/mypyc/lib-rt/list_ops.c b/mypyc/lib-rt/list_ops.c index 885c1a3366f3e..cb72662e22eee 100644 --- a/mypyc/lib-rt/list_ops.c +++ b/mypyc/lib-rt/list_ops.c @@ -118,6 +118,44 @@ PyObject *CPyList_GetItemBorrow(PyObject *list, CPyTagged index) { } } +PyObject *CPyList_GetItemInt64(PyObject *list, int64_t index) { + size_t size = PyList_GET_SIZE(list); + if (likely((uint64_t)index < size)) { + PyObject *result = PyList_GET_ITEM(list, index); + Py_INCREF(result); + return result; + } + if (index >= 0) { + PyErr_SetString(PyExc_IndexError, "list index out of range"); + return NULL; + } + index += size; + if (index < 0) { + PyErr_SetString(PyExc_IndexError, "list index out of range"); + return NULL; + } + PyObject *result = PyList_GET_ITEM(list, index); + Py_INCREF(result); + return result; +} + +PyObject *CPyList_GetItemInt64Borrow(PyObject *list, int64_t index) { + size_t size = PyList_GET_SIZE(list); + if (likely((uint64_t)index < size)) { + return PyList_GET_ITEM(list, index); + } + if (index >= 0) { + PyErr_SetString(PyExc_IndexError, "list index out of range"); + return NULL; + } + index += size; + if (index < 0) { + PyErr_SetString(PyExc_IndexError, "list index out of range"); + return NULL; + } + return PyList_GET_ITEM(list, index); +} + bool CPyList_SetItem(PyObject *list, CPyTagged index, PyObject *value) { if (CPyTagged_CheckShort(index)) { Py_ssize_t n = CPyTagged_ShortAsSsize_t(index); @@ -145,6 +183,26 @@ bool CPyList_SetItem(PyObject *list, CPyTagged index, PyObject *value) { } } +bool CPyList_SetItemInt64(PyObject *list, int64_t index, PyObject *value) { + size_t size = PyList_GET_SIZE(list); + if (unlikely((uint64_t)index >= size)) { + if (index > 0) { + PyErr_SetString(PyExc_IndexError, "list assignment index out of range"); + return false; + } + index += size; + if (index < 0) { + PyErr_SetString(PyExc_IndexError, "list assignment index out of range"); + return false; + } + } + // PyList_SET_ITEM doesn't decref the old element, so we do + Py_DECREF(PyList_GET_ITEM(list, index)); + // N.B: Steals reference + PyList_SET_ITEM(list, index, value); + return true; +} + // This function should only be used to fill in brand new lists. bool CPyList_SetItemUnsafe(PyObject *list, CPyTagged index, PyObject *value) { if (CPyTagged_CheckShort(index)) { diff --git a/mypyc/lib-rt/mypyc_util.h b/mypyc/lib-rt/mypyc_util.h index 6c4a94f8811ca..0fae239cbb9ec 100644 --- a/mypyc/lib-rt/mypyc_util.h +++ b/mypyc/lib-rt/mypyc_util.h @@ -53,6 +53,9 @@ typedef PyObject CPyModule; // Tag bit used for long integers #define CPY_INT_TAG 1 +// Error value for fixed-width (low-level) integers +#define CPY_LL_INT_ERROR -113 + typedef void (*CPyVTableItem)(void); static inline CPyTagged CPyTagged_ShortFromInt(int x) { diff --git a/mypyc/primitives/int_ops.py b/mypyc/primitives/int_ops.py index 44703528976c3..ad33de059f026 100644 --- a/mypyc/primitives/int_ops.py +++ b/mypyc/primitives/int_ops.py @@ -9,10 +9,11 @@ """ from typing import Dict, NamedTuple -from mypyc.ir.ops import ERR_NEVER, ERR_MAGIC, ComparisonOp +from mypyc.ir.ops import ERR_NEVER, ERR_MAGIC, ERR_MAGIC_OVERLAPPING, ERR_ALWAYS, ComparisonOp from mypyc.ir.rtypes import ( int_rprimitive, bool_rprimitive, float_rprimitive, object_rprimitive, - str_rprimitive, bit_rprimitive, RType + str_rprimitive, bit_rprimitive, int64_rprimitive, int32_rprimitive, void_rtype, RType, + c_pyssize_t_rprimitive ) from mypyc.primitives.registry import ( load_address_op, unary_op, CFunctionDescription, function_op, binary_op, custom_op @@ -165,3 +166,59 @@ def int_unary_op(name: str, c_function_name: str) -> CFunctionDescription: '>': IntComparisonOpDescription(ComparisonOp.SGT, int_less_than_, False, True), '>=': IntComparisonOpDescription(ComparisonOp.SGE, int_less_than_, True, False), } + +int64_divide_op = custom_op( + arg_types=[int64_rprimitive, int64_rprimitive], + return_type=int64_rprimitive, + c_function_name='CPyInt64_Divide', + error_kind=ERR_MAGIC_OVERLAPPING) + +int64_mod_op = custom_op( + arg_types=[int64_rprimitive, int64_rprimitive], + return_type=int64_rprimitive, + c_function_name='CPyInt64_Remainder', + error_kind=ERR_MAGIC_OVERLAPPING) + +int32_divide_op = custom_op( + arg_types=[int32_rprimitive, int32_rprimitive], + return_type=int32_rprimitive, + c_function_name='CPyInt32_Divide', + error_kind=ERR_MAGIC_OVERLAPPING) + +int32_mod_op = custom_op( + arg_types=[int32_rprimitive, int32_rprimitive], + return_type=int32_rprimitive, + c_function_name='CPyInt32_Remainder', + error_kind=ERR_MAGIC_OVERLAPPING) + +# Convert tagged int (as PyObject *) to i64 +int_to_int64_op = custom_op( + arg_types=[object_rprimitive], + return_type=int64_rprimitive, + c_function_name='CPyLong_AsInt64', + error_kind=ERR_MAGIC_OVERLAPPING) + +ssize_t_to_int_op = custom_op( + arg_types=[c_pyssize_t_rprimitive], + return_type=int_rprimitive, + c_function_name='CPyTagged_FromSsize_t', + error_kind=ERR_MAGIC) + +int64_to_int_op = custom_op( + arg_types=[int64_rprimitive], + return_type=int_rprimitive, + c_function_name='CPyTagged_FromInt64', + error_kind=ERR_MAGIC) + +# Convert tagged int (as PyObject *) to i32 +int_to_int32_op = custom_op( + arg_types=[object_rprimitive], + return_type=int32_rprimitive, + c_function_name='CPyLong_AsInt32', + error_kind=ERR_MAGIC_OVERLAPPING) + +int32_overflow = custom_op( + arg_types=[], + return_type=void_rtype, + c_function_name='CPyInt32_Overflow', + error_kind=ERR_ALWAYS) diff --git a/mypyc/primitives/list_ops.py b/mypyc/primitives/list_ops.py index 78955f70f1648..2bba4207cd27b 100644 --- a/mypyc/primitives/list_ops.py +++ b/mypyc/primitives/list_ops.py @@ -3,7 +3,7 @@ from mypyc.ir.ops import ERR_MAGIC, ERR_NEVER, ERR_FALSE from mypyc.ir.rtypes import ( int_rprimitive, short_int_rprimitive, list_rprimitive, object_rprimitive, c_int_rprimitive, - c_pyssize_t_rprimitive, bit_rprimitive + c_pyssize_t_rprimitive, bit_rprimitive, int64_rprimitive ) from mypyc.primitives.registry import ( load_address_op, function_op, binary_op, method_op, custom_op, ERR_NEG_INT @@ -55,7 +55,7 @@ c_function_name='CPyList_GetItem', error_kind=ERR_MAGIC) -# list[index] version with no int bounds check for when it is known to be short +# list[index] version with no int tag check for when it is known to be short method_op( name='__getitem__', arg_types=[list_rprimitive, short_int_rprimitive], @@ -84,6 +84,25 @@ is_borrowed=True, priority=4) +# Version with native int index +method_op( + name='__getitem__', + arg_types=[list_rprimitive, int64_rprimitive], + return_type=object_rprimitive, + c_function_name='CPyList_GetItemInt64', + error_kind=ERR_MAGIC, + priority=5) + +# Version with native int index +method_op( + name='__getitem__', + arg_types=[list_rprimitive, int64_rprimitive], + return_type=object_rprimitive, + c_function_name='CPyList_GetItemInt64Borrow', + is_borrowed=True, + error_kind=ERR_MAGIC, + priority=6) + # This is unsafe because it assumes that the index is a non-negative short integer # that is in-bounds for the list. list_get_item_unsafe_op = custom_op( @@ -101,6 +120,16 @@ error_kind=ERR_FALSE, steals=[False, False, True]) +# list[index_i64] = obj +method_op( + name='__setitem__', + arg_types=[list_rprimitive, int64_rprimitive, object_rprimitive], + return_type=bit_rprimitive, + c_function_name='CPyList_SetItemInt64', + error_kind=ERR_FALSE, + steals=[False, False, True], + priority=2) + # PyList_SET_ITEM does no error checking, # and should only be used to fill in brand new lists. new_list_set_item_op = custom_op( From 5039c0fe44a7592b2fcb07cead49d921ecea211f Mon Sep 17 00:00:00 2001 From: t4lz <12370607+t4lz@users.noreply.github.com> Date: Thu, 23 Jun 2022 04:40:53 +0200 Subject: [PATCH 354/377] Support unannotated converters for attr.ib (#12815) ### Description Fixes #6172 If an unannotated converter function or a lambda expression is passed as a converter to `attr.ib()`, instead of giving an error, just take the type of the respective argument of the generated `__init__()` function to be `Any`, as suggested by @JelleZijlstra and @cgebbe. ## Test Plan Add two tests: one that tests the example from the issue of an unannotated function, and one that tests an example with a lambda expression as a converter. Co-authored-by: t4lz Co-authored-by: Tal Zwick Co-authored-by: Jelle Zijlstra --- mypy/plugins/attrs.py | 189 ++++++++++++++++++--------------- test-data/unit/check-attr.test | 37 ++++++- 2 files changed, 134 insertions(+), 92 deletions(-) diff --git a/mypy/plugins/attrs.py b/mypy/plugins/attrs.py index dbce8a4021410..06c11f130f11a 100644 --- a/mypy/plugins/attrs.py +++ b/mypy/plugins/attrs.py @@ -12,7 +12,7 @@ TupleExpr, ListExpr, NameExpr, CallExpr, RefExpr, FuncDef, is_class_var, TempNode, Decorator, MemberExpr, Expression, SymbolTableNode, MDEF, JsonDict, OverloadedFuncDef, ARG_NAMED_OPT, ARG_NAMED, - TypeVarExpr, PlaceholderNode + TypeVarExpr, PlaceholderNode, LambdaExpr ) from mypy.plugin import SemanticAnalyzerPluginInterface from mypy.plugins.common import ( @@ -60,19 +60,16 @@ class Converter: """Holds information about a `converter=` argument""" def __init__(self, - type: Optional[Type] = None, - is_attr_converters_optional: bool = False, - is_invalid_converter: bool = False) -> None: - self.type = type - self.is_attr_converters_optional = is_attr_converters_optional - self.is_invalid_converter = is_invalid_converter + init_type: Optional[Type] = None, + ) -> None: + self.init_type = init_type class Attribute: """The value of an attr.ib() call.""" def __init__(self, name: str, info: TypeInfo, - has_default: bool, init: bool, kw_only: bool, converter: Converter, + has_default: bool, init: bool, kw_only: bool, converter: Optional[Converter], context: Context, init_type: Optional[Type]) -> None: self.name = name @@ -88,54 +85,35 @@ def argument(self, ctx: 'mypy.plugin.ClassDefContext') -> Argument: """Return this attribute as an argument to __init__.""" assert self.init - init_type = self.init_type or self.info[self.name].type - - if self.converter.type and not self.converter.is_invalid_converter: - # When a converter is set the init_type is overridden by the first argument - # of the converter method. - converter_type = self.converter.type - init_type = None - converter_type = get_proper_type(converter_type) - if isinstance(converter_type, CallableType) and converter_type.arg_types: - init_type = converter_type.arg_types[0] - elif isinstance(converter_type, Overloaded): - types: List[Type] = [] - for item in converter_type.items: - # Walk the overloads looking for methods that can accept one argument. - num_arg_types = len(item.arg_types) - if not num_arg_types: - continue - if num_arg_types > 1 and any(kind == ARG_POS for kind in item.arg_kinds[1:]): - continue - types.append(item.arg_types[0]) - # Make a union of all the valid types. - if types: - init_type = make_simplified_union(types) - - if self.converter.is_attr_converters_optional and init_type: - # If the converter was attr.converter.optional(type) then add None to - # the allowed init_type. - init_type = UnionType.make_union([init_type, NoneType()]) - - if not init_type: + init_type: Optional[Type] = None + if self.converter: + if self.converter.init_type: + init_type = self.converter.init_type + else: ctx.api.fail("Cannot determine __init__ type from converter", self.context) init_type = AnyType(TypeOfAny.from_error) - elif self.converter.is_invalid_converter: - # This means we had a converter but it's not of a type we can infer. - init_type = AnyType(TypeOfAny.from_error) + else: # There is no converter, the init type is the normal type. + init_type = self.init_type or self.info[self.name].type + unannotated = False if init_type is None: - if ctx.api.options.disallow_untyped_defs: - # This is a compromise. If you don't have a type here then the - # __init__ will be untyped. But since the __init__ is added it's - # pointing at the decorator. So instead we also show the error in the - # assignment, which is where you would fix the issue. - node = self.info[self.name].node - assert node is not None - ctx.api.msg.need_annotation_for_var(node, self.context) - + unannotated = True # Convert type not set to Any. init_type = AnyType(TypeOfAny.unannotated) + else: + proper_type = get_proper_type(init_type) + if isinstance(proper_type, AnyType): + if proper_type.type_of_any == TypeOfAny.unannotated: + unannotated = True + + if unannotated and ctx.api.options.disallow_untyped_defs: + # This is a compromise. If you don't have a type here then the + # __init__ will be untyped. But since the __init__ is added it's + # pointing at the decorator. So instead we also show the error in the + # assignment, which is where you would fix the issue. + node = self.info[self.name].node + assert node is not None + ctx.api.msg.need_annotation_for_var(node, self.context) if self.kw_only: arg_kind = ARG_NAMED_OPT if self.has_default else ARG_NAMED @@ -154,9 +132,9 @@ def serialize(self) -> JsonDict: 'has_default': self.has_default, 'init': self.init, 'kw_only': self.kw_only, - 'converter_type': self.converter.type.serialize() if self.converter.type else None, - 'converter_is_attr_converters_optional': self.converter.is_attr_converters_optional, - 'converter_is_invalid_converter': self.converter.is_invalid_converter, + 'has_converter': self.converter is not None, + 'converter_init_type': self.converter.init_type.serialize() + if self.converter and self.converter.init_type else None, 'context_line': self.context.line, 'context_column': self.context.column, 'init_type': self.init_type.serialize() if self.init_type else None, @@ -169,17 +147,16 @@ def deserialize(cls, info: TypeInfo, """Return the Attribute that was serialized.""" raw_init_type = data['init_type'] init_type = deserialize_and_fixup_type(raw_init_type, api) if raw_init_type else None + raw_converter_init_type = data['converter_init_type'] + converter_init_type = (deserialize_and_fixup_type(raw_converter_init_type, api) + if raw_converter_init_type else None) - converter_type = None - if data['converter_type']: - converter_type = deserialize_and_fixup_type(data['converter_type'], api) return Attribute(data['name'], info, data['has_default'], data['init'], data['kw_only'], - Converter(converter_type, data['converter_is_attr_converters_optional'], - data['converter_is_invalid_converter']), + Converter(converter_init_type) if data['has_converter'] else None, Context(line=data['context_line'], column=data['context_column']), init_type) @@ -542,7 +519,7 @@ def _attribute_from_auto_attrib(ctx: 'mypy.plugin.ClassDefContext', has_rhs = not isinstance(rvalue, TempNode) sym = ctx.cls.info.names.get(name) init_type = sym.type if sym else None - return Attribute(name, ctx.cls.info, has_rhs, True, kw_only, Converter(), stmt, init_type) + return Attribute(name, ctx.cls.info, has_rhs, True, kw_only, None, stmt, init_type) def _attribute_from_attrib_maker(ctx: 'mypy.plugin.ClassDefContext', @@ -613,40 +590,76 @@ def _attribute_from_attrib_maker(ctx: 'mypy.plugin.ClassDefContext', def _parse_converter(ctx: 'mypy.plugin.ClassDefContext', - converter: Optional[Expression]) -> Converter: + converter_expr: Optional[Expression]) -> Optional[Converter]: """Return the Converter object from an Expression.""" # TODO: Support complex converters, e.g. lambdas, calls, etc. - if converter: - if isinstance(converter, RefExpr) and converter.node: - if (isinstance(converter.node, FuncDef) - and converter.node.type - and isinstance(converter.node.type, FunctionLike)): - return Converter(converter.node.type) - elif (isinstance(converter.node, OverloadedFuncDef) - and is_valid_overloaded_converter(converter.node)): - return Converter(converter.node.type) - elif isinstance(converter.node, TypeInfo): - from mypy.checkmember import type_object_type # To avoid import cycle. - return Converter(type_object_type(converter.node, ctx.api.named_type)) - - if (isinstance(converter, CallExpr) - and isinstance(converter.callee, RefExpr) - and converter.callee.fullname in attr_optional_converters - and converter.args - and converter.args[0]): - # Special handling for attr.converters.optional(type) - # We extract the type and add make the init_args Optional in Attribute.argument - argument = _parse_converter(ctx, converter.args[0]) - argument.is_attr_converters_optional = True - return argument - + if not converter_expr: + return None + converter_info = Converter() + if (isinstance(converter_expr, CallExpr) + and isinstance(converter_expr.callee, RefExpr) + and converter_expr.callee.fullname in attr_optional_converters + and converter_expr.args + and converter_expr.args[0]): + # Special handling for attr.converters.optional(type) + # We extract the type and add make the init_args Optional in Attribute.argument + converter_expr = converter_expr.args[0] + is_attr_converters_optional = True + else: + is_attr_converters_optional = False + + converter_type: Optional[Type] = None + if isinstance(converter_expr, RefExpr) and converter_expr.node: + if isinstance(converter_expr.node, FuncDef): + if converter_expr.node.type and isinstance(converter_expr.node.type, FunctionLike): + converter_type = converter_expr.node.type + else: # The converter is an unannotated function. + converter_info.init_type = AnyType(TypeOfAny.unannotated) + return converter_info + elif (isinstance(converter_expr.node, OverloadedFuncDef) + and is_valid_overloaded_converter(converter_expr.node)): + converter_type = converter_expr.node.type + elif isinstance(converter_expr.node, TypeInfo): + from mypy.checkmember import type_object_type # To avoid import cycle. + converter_type = type_object_type(converter_expr.node, ctx.api.named_type) + if isinstance(converter_expr, LambdaExpr): + # TODO: should we send a fail if converter_expr.min_args > 1? + converter_info.init_type = AnyType(TypeOfAny.unannotated) + return converter_info + + if not converter_type: # Signal that we have an unsupported converter. ctx.api.fail( - "Unsupported converter, only named functions and types are currently supported", - converter + "Unsupported converter, only named functions, types and lambdas are currently " + "supported", + converter_expr ) - return Converter(None, is_invalid_converter=True) - return Converter(None) + converter_info.init_type = AnyType(TypeOfAny.from_error) + return converter_info + + converter_type = get_proper_type(converter_type) + if isinstance(converter_type, CallableType) and converter_type.arg_types: + converter_info.init_type = converter_type.arg_types[0] + elif isinstance(converter_type, Overloaded): + types: List[Type] = [] + for item in converter_type.items: + # Walk the overloads looking for methods that can accept one argument. + num_arg_types = len(item.arg_types) + if not num_arg_types: + continue + if num_arg_types > 1 and any(kind == ARG_POS for kind in item.arg_kinds[1:]): + continue + types.append(item.arg_types[0]) + # Make a union of all the valid types. + if types: + converter_info.init_type = make_simplified_union(types) + + if is_attr_converters_optional and converter_info.init_type: + # If the converter was attr.converter.optional(type) then add None to + # the allowed init_type. + converter_info.init_type = UnionType.make_union([converter_info.init_type, NoneType()]) + + return converter_info def is_valid_overloaded_converter(defn: OverloadedFuncDef) -> bool: diff --git a/test-data/unit/check-attr.test b/test-data/unit/check-attr.test index 021be93bdd21d..4e09e10a67269 100644 --- a/test-data/unit/check-attr.test +++ b/test-data/unit/check-attr.test @@ -878,9 +878,9 @@ def factory(default: int): ... @attr.s class C: - x: str = attr.ib(converter=thing.do_it) # E: Unsupported converter, only named functions and types are currently supported - y: str = attr.ib(converter=lambda x: x) # E: Unsupported converter, only named functions and types are currently supported - z: str = attr.ib(converter=factory(8)) # E: Unsupported converter, only named functions and types are currently supported + x: str = attr.ib(converter=thing.do_it) # E: Unsupported converter, only named functions, types and lambdas are currently supported + y: str = attr.ib(converter=lambda x: x) + z: str = attr.ib(converter=factory(8)) # E: Unsupported converter, only named functions, types and lambdas are currently supported reveal_type(C) # N: Revealed type is "def (x: Any, y: Any, z: Any) -> __main__.C" [builtins fixtures/list.pyi] @@ -1731,10 +1731,39 @@ class C: name: Union[str, None] = attr.ib(default=None) options: Mapping[str, Mapping[str, Any]] = attr.ib( default=None, converter=default_if_none(factory=dict) \ - # E: Unsupported converter, only named functions and types are currently supported + # E: Unsupported converter, only named functions, types and lambdas are currently supported ) [builtins fixtures/dict.pyi] +[case testAttrsUnannotatedConverter] +import attr + +def foo(value): + return value.split() + +@attr.s +class Bar: + field = attr.ib(default=None, converter=foo) + +reveal_type(Bar) # N: Revealed type is "def (field: Any =) -> __main__.Bar" +bar = Bar("Hello") +reveal_type(bar.field) # N: Revealed type is "Any" + +[builtins fixtures/tuple.pyi] + +[case testAttrsLambdaConverter] +import attr + +@attr.s +class Bar: + name: str = attr.ib(converter=lambda s: s.lower()) + +reveal_type(Bar) # N: Revealed type is "def (name: Any) -> __main__.Bar" +bar = Bar("Hello") +reveal_type(bar.name) # N: Revealed type is "builtins.str" + +[builtins fixtures/tuple.pyi] + [case testAttrsNestedClass] from typing import List import attr From e046e20882916f7c18b20cf7502b8c420fbe859b Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Fri, 24 Jun 2022 05:07:49 -0700 Subject: [PATCH 355/377] Disallow undesirable implicit reexport with ImportFrom (#12704) Fixes #12689 We always hid e.g. `import concurrent`, but looks like mypy never hid `from concurrent import futures`. It's possible this fix is pretty breaking for users, let's see what primer thinks. I last touched this logic in #11707, which fixed cases involving implicitly reexported symbols that shared the name of a module Co-authored-by: hauntsaninja <> --- mypy/semanal.py | 12 ++++++++---- test-data/unit/check-modules.test | 22 ++++++++++++++++++++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index e00913a8cde46..684d1f0601aba 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -1900,10 +1900,14 @@ def process_imported_symbol(self, fullname: str, module_public: bool, context: ImportBase) -> None: - module_hidden = not module_public and not ( - # `from package import module` should work regardless of whether package - # re-exports module - isinstance(node.node, MypyFile) and fullname in self.modules + module_hidden = not module_public and ( + # `from package import submodule` should work regardless of whether package + # re-exports submodule, so we shouldn't hide it + not isinstance(node.node, MypyFile) + or fullname not in self.modules + # but given `from somewhere import random_unrelated_module` we should hide + # random_unrelated_module + or not fullname.startswith(self.cur_mod_id + ".") ) if isinstance(node.node, PlaceholderNode): diff --git a/test-data/unit/check-modules.test b/test-data/unit/check-modules.test index 67767a9114e15..609a1b8ce0b02 100644 --- a/test-data/unit/check-modules.test +++ b/test-data/unit/check-modules.test @@ -1929,6 +1929,28 @@ from package import mod as mod from package import mod as internal_detail [builtins fixtures/module.pyi] +[case testNoReExportUnrelatedModule] +from mod2 import unrelated # E: Module "mod2" has no attribute "unrelated" + +[file mod1/__init__.pyi] +[file mod1/unrelated.pyi] +x: int + +[file mod2.pyi] +from mod1 import unrelated +[builtins fixtures/module.pyi] + +[case testNoReExportUnrelatedSiblingPrefix] +from pkg.unrel import unrelated # E: Module "pkg.unrel" has no attribute "unrelated" + +[file pkg/__init__.pyi] +[file pkg/unrelated.pyi] +x: int + +[file pkg/unrel.pyi] +from pkg import unrelated +[builtins fixtures/module.pyi] + [case testNoReExportChildStubs] import mod from mod import C, D # E: Module "mod" has no attribute "C" From 203bd64d8c14e8ddbed7911eb6f8f8aa61d728de Mon Sep 17 00:00:00 2001 From: Wesley Collin Wright Date: Fri, 24 Jun 2022 13:14:14 +0000 Subject: [PATCH 356/377] Replace hard crash with typecheck error when subclass method has the same name as type alias (#13015) Work on #5425 Co-authored-by: Wesley Wright --- mypy/checker.py | 3 ++- test-data/unit/check-classes.test | 28 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/mypy/checker.py b/mypy/checker.py index 39f3fa42942d4..62dd15da896ce 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -1600,7 +1600,8 @@ def check_method_override_for_base_with_name( else: original_type = NoneType() else: - assert False, str(base_attr.node) + # Will always fail to typecheck below, since we know the node is a method + original_type = NoneType() if isinstance(original_node, (FuncDef, OverloadedFuncDef)): original_class_or_static = original_node.is_class or original_node.is_static elif isinstance(original_node, Decorator): diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index 5c1e8dfa44f46..ee560de892084 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -7300,3 +7300,31 @@ def identity_wrapper(func: FuncT) -> FuncT: def foo(self: Any) -> str: return "" +[case testParentClassWithTypeAliasAndSubclassWithMethod] +from typing import Any, Callable, TypeVar + +class Parent: + foo = Callable[..., int] + class bar: + pass + import typing as baz + foobar = TypeVar("foobar") + +class Child(Parent): + def foo(self, val: int) -> int: # E: Signature of "foo" incompatible with supertype "Parent" + return val + def bar(self, val: str) -> str: # E: Signature of "bar" incompatible with supertype "Parent" + return val + def baz(self, val: float) -> float: # E: Signature of "baz" incompatible with supertype "Parent" + return val + def foobar(self) -> bool: # E: Signature of "foobar" incompatible with supertype "Parent" + return False + +x: Parent.foo = lambda: 5 +y: Parent.bar = Parent.bar() +z: Parent.baz.Any = 1 +child = Child() +a: int = child.foo(1) +b: str = child.bar("abc") +c: float = child.baz(3.4) +d: bool = child.foobar() From f663828a66900a438c4a4be6f036c95c46636551 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sun, 26 Jun 2022 13:18:59 +0530 Subject: [PATCH 357/377] stubtest: better formatting for runtime objects (#13023) Co-authored-by: hauntsaninja <> --- mypy/stubtest.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mypy/stubtest.py b/mypy/stubtest.py index a85e9335a60db..2fbd0027c8b06 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -55,6 +55,12 @@ def _style(message: str, **kwargs: Any) -> str: return _formatter.style(message, **kwargs) +def _truncate(message: str, length: int) -> str: + if len(message) > length: + return message[:length - 3] + "..." + return message + + class StubtestFailure(Exception): pass @@ -86,7 +92,7 @@ def __init__( self.stub_object = stub_object self.runtime_object = runtime_object self.stub_desc = stub_desc or str(getattr(stub_object, "type", stub_object)) - self.runtime_desc = runtime_desc or str(runtime_object) + self.runtime_desc = runtime_desc or _truncate(repr(runtime_object), 100) def is_missing_stub(self) -> bool: """Whether or not the error is for something missing from the stub.""" From 1c1f3495772a4f02c7a0e646466d2c35a69c9813 Mon Sep 17 00:00:00 2001 From: bruno messias Date: Sun, 26 Jun 2022 11:49:10 -0300 Subject: [PATCH 358/377] Exposes `end_col_offset` attr from python AST (#12972) Co-authored-by: Jelle Zijlstra --- mypy/fastparse.py | 2 ++ mypy/fastparse2.py | 1 + mypy/nodes.py | 28 +++++++++++++++++++--------- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/mypy/fastparse.py b/mypy/fastparse.py index 242b6d260c1ef..b5b31a60b539d 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -373,6 +373,8 @@ def set_line(self, node: N, n: AstNode) -> N: node.line = n.lineno node.column = n.col_offset node.end_line = getattr(n, "end_lineno", None) if isinstance(n, ast3.expr) else None + node.end_column = getattr(n, "end_col_offset", None) if isinstance(n, ast3.expr) else None + return node def translate_opt_expr_list(self, l: Sequence[Optional[AST]]) -> List[Optional[Expression]]: diff --git a/mypy/fastparse2.py b/mypy/fastparse2.py index e42a1e3c52c58..cc8d9599b7418 100644 --- a/mypy/fastparse2.py +++ b/mypy/fastparse2.py @@ -599,6 +599,7 @@ def visit_ClassDef(self, n: ast27.ClassDef) -> ClassDef: cdef.line = n.lineno + len(n.decorator_list) cdef.column = n.col_offset cdef.end_line = n.lineno + cdef.end_column = None self.class_and_function_stack.pop() return cdef diff --git a/mypy/nodes.py b/mypy/nodes.py index abc8666e390db..f54564154e2c1 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -23,17 +23,19 @@ class Context: """Base type for objects that are valid as error message locations.""" - __slots__ = ('line', 'column', 'end_line') + __slots__ = ('line', 'column', 'end_line', 'end_column') def __init__(self, line: int = -1, column: int = -1) -> None: self.line = line self.column = column self.end_line: Optional[int] = None + self.end_column: Optional[int] = None def set_line(self, target: Union['Context', int], column: Optional[int] = None, - end_line: Optional[int] = None) -> None: + end_line: Optional[int] = None, + end_column: Optional[int] = None) -> None: """If target is a node, pull line (and column) information into this node. If column is specified, this will override any column information coming from a node. @@ -44,6 +46,7 @@ def set_line(self, self.line = target.line self.column = target.column self.end_line = target.end_line + self.end_column = target.end_column if column is not None: self.column = column @@ -51,6 +54,9 @@ def set_line(self, if end_line is not None: self.end_line = end_line + if end_column is not None: + self.end_column = end_column + def get_line(self) -> int: """Don't use. Use x.line.""" return self.line @@ -631,13 +637,16 @@ def __init__(self, def set_line(self, target: Union[Context, int], column: Optional[int] = None, - end_line: Optional[int] = None) -> None: - super().set_line(target, column, end_line) + end_line: Optional[int] = None, + end_column: Optional[int] = None) -> None: + super().set_line(target, column, end_line, end_column) if self.initializer and self.initializer.line < 0: - self.initializer.set_line(self.line, self.column, self.end_line) + self.initializer.set_line( + self.line, self.column, self.end_line, self.end_column) - self.variable.set_line(self.line, self.column, self.end_line) + self.variable.set_line( + self.line, self.column, self.end_line, self.end_column) FUNCITEM_FLAGS: Final = FUNCBASE_FLAGS + [ @@ -698,10 +707,11 @@ def max_fixed_argc(self) -> int: def set_line(self, target: Union[Context, int], column: Optional[int] = None, - end_line: Optional[int] = None) -> None: - super().set_line(target, column, end_line) + end_line: Optional[int] = None, + end_column: Optional[int] = None) -> None: + super().set_line(target, column, end_line, end_column) for arg in self.arguments: - arg.set_line(self.line, self.column, self.end_line) + arg.set_line(self.line, self.column, self.end_line, end_column) def is_dynamic(self) -> bool: return self.type is None From a4ae0adb6fb0872042e0459f915254140df28b5e Mon Sep 17 00:00:00 2001 From: denballakh <47365157+denballakh@users.noreply.github.com> Date: Tue, 28 Jun 2022 08:50:02 +0300 Subject: [PATCH 359/377] Remove slots already defined in base class (#13028) --- mypy/nodes.py | 4 ++-- mypy/types.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mypy/nodes.py b/mypy/nodes.py index f54564154e2c1..180d35eb9cf49 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -3101,7 +3101,7 @@ def f(x: B[T]) -> T: ... # without T, Any would be used here within functions that can't be looked up from the symbol table) """ __slots__ = ('target', '_fullname', 'alias_tvars', 'no_args', 'normalized', - 'line', 'column', '_is_recursive', 'eager') + '_is_recursive', 'eager') def __init__(self, target: 'mypy.types.Type', fullname: str, line: int, column: int, *, @@ -3209,7 +3209,7 @@ class C(Sequence[C]): ... something that can support general recursive types. """ - __slots__ = ('_fullname', 'node', 'line', 'becomes_typeinfo') + __slots__ = ('_fullname', 'node', 'becomes_typeinfo') def __init__(self, fullname: str, node: Node, line: int, *, becomes_typeinfo: bool = False) -> None: diff --git a/mypy/types.py b/mypy/types.py index f0f7add2d92fb..f5cdb951daacf 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -258,7 +258,7 @@ class Node: can be represented in a tree-like manner. """ - __slots__ = ('alias', 'args', 'line', 'column', 'type_ref') + __slots__ = ('alias', 'args', 'type_ref') def __init__(self, alias: Optional[mypy.nodes.TypeAlias], args: List[Type], line: int = -1, column: int = -1) -> None: @@ -1838,7 +1838,7 @@ class Overloaded(FunctionLike): implementation. """ - __slots__ = ('_items', 'fallback') + __slots__ = ('_items',) _items: List[CallableType] # Must not be empty From 1c03e1068f4b1f79aa760639cd12e631783dadcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Perrin?= Date: Wed, 29 Jun 2022 13:26:30 +0100 Subject: [PATCH 360/377] Fix "attribute 'arguments' of 'FuncDef' undefined" incremental crash (#12324) When deserializing from cache, FuncDef.arguments is not set, so check before use. --- mypy/messages.py | 4 +++- mypy/nodes.py | 2 +- mypy/types.py | 19 +++++++++--------- test-data/unit/check-modules.test | 32 +++++++++++++++++++++++++++++++ 4 files changed, 45 insertions(+), 12 deletions(-) diff --git a/mypy/messages.py b/mypy/messages.py index 1d6641c00a615..628c2cbaf0a44 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -1978,7 +1978,9 @@ def [T <: int] f(self, x: int, y: T) -> None s += ' = ...' # If we got a "special arg" (i.e: self, cls, etc...), prepend it to the arg list - if isinstance(tp.definition, FuncDef) and tp.definition.name is not None: + if (isinstance(tp.definition, FuncDef) and + tp.definition.name is not None and + hasattr(tp.definition, 'arguments')): definition_args = [arg.variable.name for arg in tp.definition.arguments] if definition_args and tp.arg_names != definition_args \ and len(definition_args) > 0 and definition_args[0]: diff --git a/mypy/nodes.py b/mypy/nodes.py index 180d35eb9cf49..660adcc63053f 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -658,7 +658,7 @@ def set_line(self, class FuncItem(FuncBase): """Base class for nodes usable as overloaded function items.""" - __slots__ = ('arguments', # Note that can be None if deserialized (type is a lie!) + __slots__ = ('arguments', # Note that can be unset if deserialized (type is a lie!) 'arg_names', # Names of arguments 'arg_kinds', # Kinds of arguments 'min_args', # Minimum number of arguments diff --git a/mypy/types.py b/mypy/types.py index f5cdb951daacf..4c595d9105a12 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -1524,16 +1524,15 @@ def __init__(self, # after serialization, but it is useful in error messages. # TODO: decide how to add more info here (file, line, column) # without changing interface hash. - self.def_extras = { - 'first_arg': ( - definition.arguments[0].variable.name - if (getattr(definition, 'arguments', None) - and definition.arg_names - and definition.info - and not definition.is_static) - else None - ), - } + first_arg: Optional[str] = None + if (definition.arg_names and + definition.info and + not definition.is_static): + if getattr(definition, 'arguments', None): + first_arg = definition.arguments[0].variable.name + else: + first_arg = definition.arg_names[0] + self.def_extras = {'first_arg': first_arg} else: self.def_extras = {} self.type_guard = type_guard diff --git a/test-data/unit/check-modules.test b/test-data/unit/check-modules.test index 609a1b8ce0b02..17e5386a0b6da 100644 --- a/test-data/unit/check-modules.test +++ b/test-data/unit/check-modules.test @@ -3212,3 +3212,35 @@ from dir1 import * from .test2 import * [file dir1/test2.py] from test1 import aaaa # E: Module "test1" has no attribute "aaaa" + +[case testIncompatibleOverrideFromCachedModuleIncremental] +import b +[file a.py] +class Foo: + def frobnicate(self, *args, **kwargs): pass +[file b.py] +from a import Foo +class Bar(Foo): + def frobnicate(self) -> None: pass +[file b.py.2] +from a import Foo +class Bar(Foo): + def frobnicate(self, *args) -> None: pass +[file b.py.3] +from a import Foo +class Bar(Foo): + def frobnicate(self, *args) -> None: pass # type: ignore[override] # I know +[builtins fixtures/tuple.pyi] +[builtins fixtures/dict.pyi] +[out1] +tmp/b.py:3: error: Signature of "frobnicate" incompatible with supertype "Foo" +tmp/b.py:3: note: Superclass: +tmp/b.py:3: note: def frobnicate(self, *args: Any, **kwargs: Any) -> Any +tmp/b.py:3: note: Subclass: +tmp/b.py:3: note: def frobnicate(self) -> None +[out2] +tmp/b.py:3: error: Signature of "frobnicate" incompatible with supertype "Foo" +tmp/b.py:3: note: Superclass: +tmp/b.py:3: note: def frobnicate(self, *args: Any, **kwargs: Any) -> Any +tmp/b.py:3: note: Subclass: +tmp/b.py:3: note: def frobnicate(self, *args: Any) -> None From 914297e9486b141c01b34593938fdf423d892cef Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Wed, 29 Jun 2022 20:51:08 +0530 Subject: [PATCH 361/377] stubtest: find submodules missing from stubs (#13030) Co-authored-by: hauntsaninja <> --- mypy/stubtest.py | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/mypy/stubtest.py b/mypy/stubtest.py index 2fbd0027c8b06..3928ee009f7fb 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -10,6 +10,7 @@ import importlib import inspect import os +import pkgutil import re import sys import types @@ -164,6 +165,17 @@ def get_description(self, concise: bool = False) -> str: # Core logic # ==================== +def silent_import_module(module_name: str) -> types.ModuleType: + with open(os.devnull, "w") as devnull: + with warnings.catch_warnings(), redirect_stdout(devnull), redirect_stderr(devnull): + warnings.simplefilter("ignore") + runtime = importlib.import_module(module_name) + # Also run the equivalent of `from module import *` + # This could have the additional effect of loading not-yet-loaded submodules + # mentioned in __all__ + __import__(module_name, fromlist=["*"]) + return runtime + def test_module(module_name: str) -> Iterator[Error]: """Tests a given module's stub against introspecting it at runtime. @@ -175,18 +187,14 @@ def test_module(module_name: str) -> Iterator[Error]: """ stub = get_stub(module_name) if stub is None: - yield Error([module_name], "failed to find stubs", MISSING, None, runtime_desc="N/A") + runtime_desc = repr(sys.modules[module_name]) if module_name in sys.modules else "N/A" + yield Error( + [module_name], "failed to find stubs", MISSING, None, runtime_desc=runtime_desc + ) return try: - with open(os.devnull, "w") as devnull: - with warnings.catch_warnings(), redirect_stdout(devnull), redirect_stderr(devnull): - warnings.simplefilter("ignore") - runtime = importlib.import_module(module_name) - # Also run the equivalent of `from module import *` - # This could have the additional effect of loading not-yet-loaded submodules - # mentioned in __all__ - __import__(module_name, fromlist=["*"]) + runtime = silent_import_module(module_name) except Exception as e: yield Error([module_name], f"failed to import, {type(e).__name__}: {e}", stub, MISSING) return @@ -1289,7 +1297,18 @@ def build_stubs(modules: List[str], options: Options, find_submodules: bool = Fa else: found_sources = find_module_cache.find_modules_recursive(module) sources.extend(found_sources) + # find submodules via mypy all_modules.extend(s.module for s in found_sources if s.module not in all_modules) + # find submodules via pkgutil + try: + runtime = silent_import_module(module) + all_modules.extend( + m.name + for m in pkgutil.walk_packages(runtime.__path__, runtime.__name__ + ".") + if m.name not in all_modules + ) + except Exception: + pass if sources: try: From 86aefb14ffb92975ccd312f12c65919b26002c8d Mon Sep 17 00:00:00 2001 From: Richard Si <63936253+ichard26@users.noreply.github.com> Date: Sun, 3 Jul 2022 17:15:14 -0400 Subject: [PATCH 362/377] [mypyc] Add LoadAddress primitive op for PySet_Type & PyFrozenSet_Type (#13057) This also fixes https://github.com/mypyc/mypyc/issues/917 RE above, the root issue is that mypyc didn't know builtins.set was a built-in name, so it guessed it comes from the module globals. This didn't blow up anything up somehow... until the dataclasses commit[^1] which made the `__annotations__` logic for dataclasses try to better preserve the type annotations (previously they would be erased to builtins.type). This new logic would use `load_type` to load `builtins.set` (so it can be put in `__annotations__`) which went poorly as only types registered with `load_address_op` are considered built-ins. [^1]: https://github.com/python/mypy/commit/1bcfc041bb767ee93e90676b0a61f3e40267e858 --- mypyc/primitives/set_ops.py | 16 +++++++++++++++- mypyc/test-data/fixtures/ir.py | 10 ++++++++-- mypyc/test-data/run-python37.test | 10 ++++++++-- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/mypyc/primitives/set_ops.py b/mypyc/primitives/set_ops.py index 70d59d749070c..5d18e45ad528b 100644 --- a/mypyc/primitives/set_ops.py +++ b/mypyc/primitives/set_ops.py @@ -1,6 +1,8 @@ """Primitive set (and frozenset) ops.""" -from mypyc.primitives.registry import function_op, method_op, binary_op, ERR_NEG_INT +from mypyc.primitives.registry import ( + load_address_op, function_op, method_op, binary_op, ERR_NEG_INT +) from mypyc.ir.ops import ERR_MAGIC, ERR_FALSE from mypyc.ir.rtypes import ( object_rprimitive, bool_rprimitive, set_rprimitive, c_int_rprimitive, pointer_rprimitive, @@ -8,6 +10,18 @@ ) +# Get the 'builtins.set' type object. +load_address_op( + name='builtins.set', + type=object_rprimitive, + src='PySet_Type') + +# Get the 'builtins.frozenset' tyoe object. +load_address_op( + name='builtins.frozenset', + type=object_rprimitive, + src='PyFrozenSet_Type') + # Construct an empty set. new_set_op = function_op( name='builtins.set', diff --git a/mypyc/test-data/fixtures/ir.py b/mypyc/test-data/fixtures/ir.py index a6914ccc36e56..d8c4333cafad8 100644 --- a/mypyc/test-data/fixtures/ir.py +++ b/mypyc/test-data/fixtures/ir.py @@ -3,7 +3,7 @@ from typing import ( TypeVar, Generic, List, Iterator, Iterable, Dict, Optional, Tuple, Any, Set, - overload, Mapping, Union, Callable, Sequence, + overload, Mapping, Union, Callable, Sequence, FrozenSet ) T = TypeVar('T') @@ -211,7 +211,13 @@ def discard(self, x: T) -> None: pass def clear(self) -> None: pass def pop(self) -> T: pass def update(self, x: Iterable[S]) -> None: pass - def __or__(self, s: Set[S]) -> Set[Union[T, S]]: ... + def __or__(self, s: Union[Set[S], FrozenSet[S]]) -> Set[Union[T, S]]: ... + +class frozenset(Generic[T]): + def __init__(self, i: Optional[Iterable[T]] = None) -> None: pass + def __iter__(self) -> Iterator[T]: pass + def __len__(self) -> int: pass + def __or__(self, s: Union[Set[S], FrozenSet[S]]) -> FrozenSet[Union[T, S]]: ... class slice: pass diff --git a/mypyc/test-data/run-python37.test b/mypyc/test-data/run-python37.test index 734e116c13354..5bf2c29263e1d 100644 --- a/mypyc/test-data/run-python37.test +++ b/mypyc/test-data/run-python37.test @@ -3,7 +3,7 @@ [case testRunDataclass] import dataclasses from dataclasses import dataclass, field -from typing import Set, List, Callable, Any +from typing import Set, FrozenSet, List, Callable, Any @dataclass class Person1: @@ -68,8 +68,13 @@ class Person4: def name(self) -> str: return self._name +@dataclass +class Person5: + friends: Set[str] = field(default_factory=set) + parents: FrozenSet[str] = frozenset() + [file other.py] -from native import Person1, Person1b, Person2, Person3, Person4, testBool +from native import Person1, Person1b, Person2, Person3, Person4, Person5, testBool i1 = Person1(age = 5, name = 'robot') assert i1.age == 5 assert i1.name == 'robot' @@ -117,6 +122,7 @@ assert i8 > i9 assert Person1.__annotations__ == {'age': int, 'name': str} assert Person2.__annotations__ == {'age': int, 'name': str} +assert Person5.__annotations__ == {'friends': set, 'parents': frozenset} [file driver.py] import sys From eaf60916a494ff8d36cab05331205d2d4bfe38bc Mon Sep 17 00:00:00 2001 From: Poruri Sai Rahul Date: Wed, 6 Jul 2022 15:05:03 +0100 Subject: [PATCH 363/377] docs: remove duplicate word (#13080) --- docs/source/running_mypy.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/running_mypy.rst b/docs/source/running_mypy.rst index caf05dcdf258a..afcc8c588ab36 100644 --- a/docs/source/running_mypy.rst +++ b/docs/source/running_mypy.rst @@ -205,7 +205,7 @@ will continue to be of type ``Any``. 1. To suppress a *single* missing import error, add a ``# type: ignore`` at the end of the line containing the import. -2. To suppress *all* missing import imports errors from a single library, add +2. To suppress *all* missing import errors from a single library, add a section to your :ref:`mypy config file ` for that library setting :confval:`ignore_missing_imports` to True. For example, suppose your codebase makes heavy use of an (untyped) library named ``foobar``. You can silence From 7a6ecd3c96b61a9df59fa580acade0fde2a77d90 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Fri, 8 Jul 2022 16:07:54 +0530 Subject: [PATCH 364/377] Sync typeshed (#12982) * Sync typeshed Source commit: https://github.com/python/typeshed/commit/91d6383d9d1ca38157ce46bb498a11347658db1d * fix tests Co-authored-by: hauntsaninja <> --- mypy/typeshed/stdlib/@python2/ssl.pyi | 7 +- mypy/typeshed/stdlib/VERSIONS | 1 + mypy/typeshed/stdlib/__future__.pyi | 40 +- mypy/typeshed/stdlib/_ast.pyi | 2 + mypy/typeshed/stdlib/_codecs.pyi | 63 +- mypy/typeshed/stdlib/_dummy_thread.pyi | 10 + mypy/typeshed/stdlib/_dummy_threading.pyi | 74 +-- mypy/typeshed/stdlib/_imp.pyi | 10 +- mypy/typeshed/stdlib/_pydecimal.pyi | 118 ++-- mypy/typeshed/stdlib/_typeshed/__init__.pyi | 22 +- mypy/typeshed/stdlib/_weakrefset.pyi | 7 +- mypy/typeshed/stdlib/argparse.pyi | 131 +++-- mypy/typeshed/stdlib/array.pyi | 20 +- mypy/typeshed/stdlib/ast.pyi | 3 + mypy/typeshed/stdlib/asyncio/__init__.pyi | 1 + mypy/typeshed/stdlib/asyncio/base_events.pyi | 147 ++++- mypy/typeshed/stdlib/asyncio/constants.pyi | 4 + mypy/typeshed/stdlib/asyncio/events.pyi | 202 ++++++- mypy/typeshed/stdlib/asyncio/exceptions.pyi | 32 +- mypy/typeshed/stdlib/asyncio/futures.pyi | 1 + mypy/typeshed/stdlib/asyncio/locks.pyi | 59 +- mypy/typeshed/stdlib/asyncio/mixins.pyi | 4 +- mypy/typeshed/stdlib/asyncio/protocols.pyi | 3 +- mypy/typeshed/stdlib/asyncio/queues.pyi | 6 +- mypy/typeshed/stdlib/asyncio/runners.pyi | 27 +- mypy/typeshed/stdlib/asyncio/sslproto.pyi | 74 ++- mypy/typeshed/stdlib/asyncio/streams.pyi | 5 + mypy/typeshed/stdlib/asyncio/taskgroups.pyi | 5 +- mypy/typeshed/stdlib/asyncio/tasks.pyi | 18 +- mypy/typeshed/stdlib/asyncio/timeouts.pyi | 19 + mypy/typeshed/stdlib/asyncio/trsock.pyi | 2 +- mypy/typeshed/stdlib/base64.pyi | 65 +-- mypy/typeshed/stdlib/bdb.pyi | 5 + mypy/typeshed/stdlib/binascii.pyi | 7 +- mypy/typeshed/stdlib/builtins.pyi | 213 +++++-- mypy/typeshed/stdlib/calendar.pyi | 88 +-- mypy/typeshed/stdlib/cgi.pyi | 50 +- mypy/typeshed/stdlib/codecs.pyi | 98 +--- mypy/typeshed/stdlib/collections/__init__.pyi | 45 +- .../stdlib/concurrent/futures/process.pyi | 48 +- mypy/typeshed/stdlib/contextlib.pyi | 80 +-- mypy/typeshed/stdlib/contextvars.pyi | 5 +- mypy/typeshed/stdlib/csv.pyi | 11 +- mypy/typeshed/stdlib/ctypes/__init__.pyi | 2 +- mypy/typeshed/stdlib/dataclasses.pyi | 67 ++- mypy/typeshed/stdlib/difflib.pyi | 11 +- mypy/typeshed/stdlib/dis.pyi | 28 +- .../stdlib/distutils/command/check.pyi | 3 +- mypy/typeshed/stdlib/distutils/filelist.pyi | 12 +- mypy/typeshed/stdlib/enum.pyi | 67 ++- mypy/typeshed/stdlib/filecmp.pyi | 14 +- mypy/typeshed/stdlib/fileinput.pyi | 240 +++++++- mypy/typeshed/stdlib/fractions.pyi | 7 +- mypy/typeshed/stdlib/ftplib.pyi | 2 +- mypy/typeshed/stdlib/functools.pyi | 69 +-- mypy/typeshed/stdlib/genericpath.pyi | 4 +- mypy/typeshed/stdlib/gettext.pyi | 141 ++--- mypy/typeshed/stdlib/graphlib.pyi | 7 +- mypy/typeshed/stdlib/hmac.pyi | 2 +- mypy/typeshed/stdlib/imaplib.pyi | 2 +- mypy/typeshed/stdlib/importlib/abc.pyi | 16 + .../stdlib/importlib/metadata/__init__.pyi | 41 +- .../stdlib/importlib/metadata/_meta.pyi | 6 +- mypy/typeshed/stdlib/importlib/resources.pyi | 42 +- mypy/typeshed/stdlib/io.pyi | 64 +-- mypy/typeshed/stdlib/itertools.pyi | 2 +- .../stdlib/lib2to3/pgen2/tokenize.pyi | 216 +++---- mypy/typeshed/stdlib/locale.pyi | 8 +- mypy/typeshed/stdlib/logging/__init__.pyi | 20 +- mypy/typeshed/stdlib/logging/handlers.pyi | 3 + mypy/typeshed/stdlib/macpath.pyi | 35 ++ mypy/typeshed/stdlib/macurl2path.pyi | 2 + mypy/typeshed/stdlib/mailbox.pyi | 7 +- mypy/typeshed/stdlib/mmap.pyi | 2 +- mypy/typeshed/stdlib/modulefinder.pyi | 13 +- .../stdlib/multiprocessing/__init__.pyi | 118 ++-- .../stdlib/multiprocessing/managers.pyi | 82 ++- .../stdlib/multiprocessing/shared_memory.pyi | 7 +- mypy/typeshed/stdlib/ntpath.pyi | 131 ++--- mypy/typeshed/stdlib/operator.pyi | 172 ++---- mypy/typeshed/stdlib/optparse.pyi | 5 +- mypy/typeshed/stdlib/os/__init__.pyi | 13 +- mypy/typeshed/stdlib/pdb.pyi | 6 +- mypy/typeshed/stdlib/pickle.pyi | 247 +++----- mypy/typeshed/stdlib/posixpath.pyi | 39 +- mypy/typeshed/stdlib/pydoc.pyi | 42 +- mypy/typeshed/stdlib/pyexpat/__init__.pyi | 3 + mypy/typeshed/stdlib/pyexpat/errors.pyi | 9 + mypy/typeshed/stdlib/random.pyi | 86 +-- mypy/typeshed/stdlib/re.pyi | 129 ++--- mypy/typeshed/stdlib/shutil.pyi | 12 +- mypy/typeshed/stdlib/smtplib.pyi | 49 +- mypy/typeshed/stdlib/socket.pyi | 64 ++- mypy/typeshed/stdlib/socketserver.pyi | 48 +- mypy/typeshed/stdlib/sqlite3/dbapi2.pyi | 18 +- mypy/typeshed/stdlib/sre_constants.pyi | 3 +- mypy/typeshed/stdlib/sre_parse.pyi | 8 +- mypy/typeshed/stdlib/ssl.pyi | 7 +- mypy/typeshed/stdlib/statistics.pyi | 76 +-- mypy/typeshed/stdlib/string.pyi | 3 + mypy/typeshed/stdlib/subprocess.pyi | 246 ++++---- mypy/typeshed/stdlib/symtable.pyi | 7 +- mypy/typeshed/stdlib/sys.pyi | 3 + mypy/typeshed/stdlib/tarfile.pyi | 4 +- mypy/typeshed/stdlib/tempfile.pyi | 130 +++-- mypy/typeshed/stdlib/termios.pyi | 3 + mypy/typeshed/stdlib/threading.pyi | 114 ++-- mypy/typeshed/stdlib/tkinter/__init__.pyi | 70 +-- mypy/typeshed/stdlib/tkinter/ttk.pyi | 82 +-- mypy/typeshed/stdlib/token.pyi | 351 +++--------- mypy/typeshed/stdlib/tokenize.pyi | 376 +++--------- mypy/typeshed/stdlib/traceback.pyi | 47 +- mypy/typeshed/stdlib/turtle.pyi | 21 +- mypy/typeshed/stdlib/types.pyi | 332 +++++------ mypy/typeshed/stdlib/typing.pyi | 540 +++--------------- mypy/typeshed/stdlib/typing_extensions.pyi | 4 +- mypy/typeshed/stdlib/unicodedata.pyi | 3 + mypy/typeshed/stdlib/unittest/__init__.pyi | 80 +-- mypy/typeshed/stdlib/unittest/async_case.pyi | 8 + mypy/typeshed/stdlib/unittest/case.pyi | 72 ++- mypy/typeshed/stdlib/unittest/mock.pyi | 8 +- mypy/typeshed/stdlib/urllib/parse.pyi | 3 +- mypy/typeshed/stdlib/urllib/request.pyi | 9 + .../typeshed/stdlib/xml/etree/ElementTree.pyi | 129 ++--- mypy/typeshed/stdlib/xml/sax/handler.pyi | 40 +- mypy/typeshed/stdlib/xmlrpc/server.pyi | 5 +- mypy/typeshed/stdlib/zipfile.pyi | 82 +-- .../stubs/mypy-extensions/mypy_extensions.pyi | 38 +- test-data/unit/cmdline.test | 14 +- 129 files changed, 3480 insertions(+), 3705 deletions(-) create mode 100644 mypy/typeshed/stdlib/asyncio/timeouts.pyi diff --git a/mypy/typeshed/stdlib/@python2/ssl.pyi b/mypy/typeshed/stdlib/@python2/ssl.pyi index 2c6b325672496..edc22ff1515a8 100644 --- a/mypy/typeshed/stdlib/@python2/ssl.pyi +++ b/mypy/typeshed/stdlib/@python2/ssl.pyi @@ -225,7 +225,12 @@ class SSLContext: def load_verify_locations( self, cafile: StrPath | None = ..., capath: StrPath | None = ..., cadata: Text | bytes | None = ... ) -> None: ... - def get_ca_certs(self, binary_form: bool = ...) -> list[_PeerCertRetDictType] | list[bytes]: ... + @overload + def get_ca_certs(self, binary_form: Literal[False] = ...) -> list[_PeerCertRetDictType]: ... + @overload + def get_ca_certs(self, binary_form: Literal[True]) -> list[bytes]: ... + @overload + def get_ca_certs(self, binary_form: bool = ...) -> Any: ... def set_default_verify_paths(self) -> None: ... def set_ciphers(self, __cipherlist: str) -> None: ... def set_alpn_protocols(self, alpn_protocols: Iterable[str]) -> None: ... diff --git a/mypy/typeshed/stdlib/VERSIONS b/mypy/typeshed/stdlib/VERSIONS index eefc7b895436f..acf392d978162 100644 --- a/mypy/typeshed/stdlib/VERSIONS +++ b/mypy/typeshed/stdlib/VERSIONS @@ -70,6 +70,7 @@ asyncio.runners: 3.7- asyncio.staggered: 3.8- asyncio.taskgroups: 3.11- asyncio.threads: 3.9- +asyncio.timeouts: 3.11- asyncio.trsock: 3.8- asyncore: 2.7- atexit: 2.7- diff --git a/mypy/typeshed/stdlib/__future__.pyi b/mypy/typeshed/stdlib/__future__.pyi index 1a465c3e213dd..52941a0c52293 100644 --- a/mypy/typeshed/stdlib/__future__.pyi +++ b/mypy/typeshed/stdlib/__future__.pyi @@ -21,30 +21,18 @@ if sys.version_info >= (3, 7): all_feature_names: list[str] # undocumented +__all__ = [ + "all_feature_names", + "absolute_import", + "division", + "generators", + "nested_scopes", + "print_function", + "unicode_literals", + "with_statement", + "barry_as_FLUFL", + "generator_stop", +] + if sys.version_info >= (3, 7): - __all__ = [ - "all_feature_names", - "absolute_import", - "division", - "generators", - "nested_scopes", - "print_function", - "unicode_literals", - "with_statement", - "barry_as_FLUFL", - "generator_stop", - "annotations", - ] -else: - __all__ = [ - "all_feature_names", - "absolute_import", - "division", - "generators", - "nested_scopes", - "print_function", - "unicode_literals", - "with_statement", - "barry_as_FLUFL", - "generator_stop", - ] + __all__ += ["annotations"] diff --git a/mypy/typeshed/stdlib/_ast.pyi b/mypy/typeshed/stdlib/_ast.pyi index 1305b0c94d9bd..81cb9ffbf26e7 100644 --- a/mypy/typeshed/stdlib/_ast.pyi +++ b/mypy/typeshed/stdlib/_ast.pyi @@ -415,6 +415,8 @@ class Tuple(expr): __match_args__ = ("elts", "ctx") elts: list[expr] ctx: expr_context + if sys.version_info >= (3, 9): + dims: list[expr] class expr_context(AST): ... diff --git a/mypy/typeshed/stdlib/_codecs.pyi b/mypy/typeshed/stdlib/_codecs.pyi index e335f6d5119a6..8fabf94d827ef 100644 --- a/mypy/typeshed/stdlib/_codecs.pyi +++ b/mypy/typeshed/stdlib/_codecs.pyi @@ -1,22 +1,71 @@ import codecs import sys from collections.abc import Callable -from typing import Any -from typing_extensions import TypeAlias +from typing import overload +from typing_extensions import Literal, TypeAlias # This type is not exposed; it is defined in unicodeobject.c class _EncodingMap: def size(self) -> int: ... _MapT: TypeAlias = dict[int, int] | _EncodingMap -_Handler: TypeAlias = Callable[[Exception], tuple[str, int]] +_Handler: TypeAlias = Callable[[UnicodeError], tuple[str | bytes, int]] +_SearchFunction: TypeAlias = Callable[[str], codecs.CodecInfo | None] + +def register(__search_function: _SearchFunction) -> None: ... + +if sys.version_info >= (3, 10): + def unregister(__search_function: _SearchFunction) -> None: ... -def register(__search_function: Callable[[str], Any]) -> None: ... def register_error(__errors: str, __handler: _Handler) -> None: ... -def lookup(__encoding: str) -> codecs.CodecInfo: ... def lookup_error(__name: str) -> _Handler: ... -def decode(obj: Any, encoding: str = ..., errors: str | None = ...) -> Any: ... -def encode(obj: Any, encoding: str = ..., errors: str | None = ...) -> Any: ... + +# The type ignore on `encode` and `decode` is to avoid issues with overlapping overloads, for more details, see #300 +# https://docs.python.org/3/library/codecs.html#binary-transforms +_BytesToBytesEncoding: TypeAlias = Literal[ + "base64", + "base_64", + "base64_codec", + "bz2", + "bz2_codec", + "hex", + "hex_codec", + "quopri", + "quotedprintable", + "quoted_printable", + "quopri_codec", + "uu", + "uu_codec", + "zip", + "zlib", + "zlib_codec", +] +# https://docs.python.org/3/library/codecs.html#text-transforms +_StrToStrEncoding: TypeAlias = Literal["rot13", "rot_13"] + +@overload +def encode(obj: bytes, encoding: _BytesToBytesEncoding, errors: str = ...) -> bytes: ... +@overload +def encode(obj: str, encoding: _StrToStrEncoding, errors: str = ...) -> str: ... # type: ignore[misc] +@overload +def encode(obj: str, encoding: str = ..., errors: str = ...) -> bytes: ... +@overload +def decode(obj: bytes, encoding: _BytesToBytesEncoding, errors: str = ...) -> bytes: ... # type: ignore[misc] +@overload +def decode(obj: str, encoding: _StrToStrEncoding, errors: str = ...) -> str: ... + +# these are documented as text encodings but in practice they also accept str as input +@overload +def decode( + obj: str, encoding: Literal["unicode_escape", "unicode-escape", "raw_unicode_escape", "raw-unicode-escape"], errors: str = ... +) -> str: ... + +# hex is officially documented as a bytes to bytes encoding, but it appears to also work with str +@overload +def decode(obj: str, encoding: Literal["hex", "hex_codec"], errors: str = ...) -> bytes: ... +@overload +def decode(obj: bytes, encoding: str = ..., errors: str = ...) -> str: ... +def lookup(__encoding: str) -> codecs.CodecInfo: ... def charmap_build(__map: str) -> _MapT: ... def ascii_decode(__data: bytes, __errors: str | None = ...) -> tuple[str, int]: ... def ascii_encode(__str: str, __errors: str | None = ...) -> tuple[bytes, int]: ... diff --git a/mypy/typeshed/stdlib/_dummy_thread.pyi b/mypy/typeshed/stdlib/_dummy_thread.pyi index f257b758eeab3..4bcf84964add9 100644 --- a/mypy/typeshed/stdlib/_dummy_thread.pyi +++ b/mypy/typeshed/stdlib/_dummy_thread.pyi @@ -1,7 +1,13 @@ +import sys from collections.abc import Callable from types import TracebackType from typing import Any, NoReturn +__all__ = ["error", "start_new_thread", "exit", "get_ident", "allocate_lock", "interrupt_main", "LockType"] + +if sys.version_info >= (3, 7): + __all__ += ["RLock"] + TIMEOUT_MAX: int error = RuntimeError @@ -20,4 +26,8 @@ class LockType: def release(self) -> bool: ... def locked(self) -> bool: ... +if sys.version_info >= (3, 7): + class RLock(LockType): + def release(self) -> None: ... # type: ignore[override] + def interrupt_main() -> None: ... diff --git a/mypy/typeshed/stdlib/_dummy_threading.pyi b/mypy/typeshed/stdlib/_dummy_threading.pyi index 2daceaedd4add..6f888b3dda709 100644 --- a/mypy/typeshed/stdlib/_dummy_threading.pyi +++ b/mypy/typeshed/stdlib/_dummy_threading.pyi @@ -10,56 +10,32 @@ _TF: TypeAlias = Callable[[FrameType, str, Any], Callable[..., Any] | None] _PF: TypeAlias = Callable[[FrameType, str, Any], None] _T = TypeVar("_T") +__all__ = [ + "get_ident", + "active_count", + "Condition", + "current_thread", + "enumerate", + "main_thread", + "TIMEOUT_MAX", + "Event", + "Lock", + "RLock", + "Semaphore", + "BoundedSemaphore", + "Thread", + "Barrier", + "BrokenBarrierError", + "Timer", + "ThreadError", + "setprofile", + "settrace", + "local", + "stack_size", +] + if sys.version_info >= (3, 8): - __all__ = [ - "get_ident", - "active_count", - "Condition", - "current_thread", - "enumerate", - "main_thread", - "TIMEOUT_MAX", - "Event", - "Lock", - "RLock", - "Semaphore", - "BoundedSemaphore", - "Thread", - "Barrier", - "BrokenBarrierError", - "Timer", - "ThreadError", - "setprofile", - "settrace", - "local", - "stack_size", - "excepthook", - "ExceptHookArgs", - ] -else: - __all__ = [ - "get_ident", - "active_count", - "Condition", - "current_thread", - "enumerate", - "main_thread", - "TIMEOUT_MAX", - "Event", - "Lock", - "RLock", - "Semaphore", - "BoundedSemaphore", - "Thread", - "Barrier", - "BrokenBarrierError", - "Timer", - "ThreadError", - "setprofile", - "settrace", - "local", - "stack_size", - ] + __all__ += ["ExceptHookArgs", "excepthook"] def active_count() -> int: ... def current_thread() -> Thread: ... diff --git a/mypy/typeshed/stdlib/_imp.pyi b/mypy/typeshed/stdlib/_imp.pyi index e2bbb9385ceb0..856188dfbcd2a 100644 --- a/mypy/typeshed/stdlib/_imp.pyi +++ b/mypy/typeshed/stdlib/_imp.pyi @@ -1,10 +1,12 @@ import sys import types +from _typeshed import ReadableBuffer from importlib.machinery import ModuleSpec from typing import Any if sys.version_info >= (3, 7): check_hash_based_pycs: str + def source_hash(key: int, source: ReadableBuffer) -> bytes: ... def create_builtin(__spec: ModuleSpec) -> types.ModuleType: ... def create_dynamic(__spec: ModuleSpec, __file: Any = ...) -> types.ModuleType: ... @@ -12,10 +14,16 @@ def acquire_lock() -> None: ... def exec_builtin(__mod: types.ModuleType) -> int: ... def exec_dynamic(__mod: types.ModuleType) -> int: ... def extension_suffixes() -> list[str]: ... -def get_frozen_object(__name: str) -> types.CodeType: ... def init_frozen(__name: str) -> types.ModuleType: ... def is_builtin(__name: str) -> int: ... def is_frozen(__name: str) -> bool: ... def is_frozen_package(__name: str) -> bool: ... def lock_held() -> bool: ... def release_lock() -> None: ... + +if sys.version_info >= (3, 11): + def find_frozen(__name: str, *, withdata: bool = ...) -> tuple[memoryview | None, bool, str | None] | None: ... + def get_frozen_object(__name: str, __data: ReadableBuffer | None = ...) -> types.CodeType: ... + +else: + def get_frozen_object(__name: str) -> types.CodeType: ... diff --git a/mypy/typeshed/stdlib/_pydecimal.pyi b/mypy/typeshed/stdlib/_pydecimal.pyi index 90dbef1dc2e2d..0d639bc164d4e 100644 --- a/mypy/typeshed/stdlib/_pydecimal.pyi +++ b/mypy/typeshed/stdlib/_pydecimal.pyi @@ -4,82 +4,44 @@ import sys # However, in all likelihood, the differences are inconsequential from _decimal import * +__all__ = [ + "Decimal", + "Context", + "DecimalTuple", + "DefaultContext", + "BasicContext", + "ExtendedContext", + "DecimalException", + "Clamped", + "InvalidOperation", + "DivisionByZero", + "Inexact", + "Rounded", + "Subnormal", + "Overflow", + "Underflow", + "FloatOperation", + "DivisionImpossible", + "InvalidContext", + "ConversionSyntax", + "DivisionUndefined", + "ROUND_DOWN", + "ROUND_HALF_UP", + "ROUND_HALF_EVEN", + "ROUND_CEILING", + "ROUND_FLOOR", + "ROUND_UP", + "ROUND_HALF_DOWN", + "ROUND_05UP", + "setcontext", + "getcontext", + "localcontext", + "MAX_PREC", + "MAX_EMAX", + "MIN_EMIN", + "MIN_ETINY", + "HAVE_THREADS", +] + if sys.version_info >= (3, 7): - __all__ = [ - "Decimal", - "Context", - "DecimalTuple", - "DefaultContext", - "BasicContext", - "ExtendedContext", - "DecimalException", - "Clamped", - "InvalidOperation", - "DivisionByZero", - "Inexact", - "Rounded", - "Subnormal", - "Overflow", - "Underflow", - "FloatOperation", - "DivisionImpossible", - "InvalidContext", - "ConversionSyntax", - "DivisionUndefined", - "ROUND_DOWN", - "ROUND_HALF_UP", - "ROUND_HALF_EVEN", - "ROUND_CEILING", - "ROUND_FLOOR", - "ROUND_UP", - "ROUND_HALF_DOWN", - "ROUND_05UP", - "setcontext", - "getcontext", - "localcontext", - "MAX_PREC", - "MAX_EMAX", - "MIN_EMIN", - "MIN_ETINY", - "HAVE_THREADS", - "HAVE_CONTEXTVAR", - ] -else: - __all__ = [ - "Decimal", - "Context", - "DecimalTuple", - "DefaultContext", - "BasicContext", - "ExtendedContext", - "DecimalException", - "Clamped", - "InvalidOperation", - "DivisionByZero", - "Inexact", - "Rounded", - "Subnormal", - "Overflow", - "Underflow", - "FloatOperation", - "DivisionImpossible", - "InvalidContext", - "ConversionSyntax", - "DivisionUndefined", - "ROUND_DOWN", - "ROUND_HALF_UP", - "ROUND_HALF_EVEN", - "ROUND_CEILING", - "ROUND_FLOOR", - "ROUND_UP", - "ROUND_HALF_DOWN", - "ROUND_05UP", - "setcontext", - "getcontext", - "localcontext", - "MAX_PREC", - "MAX_EMAX", - "MIN_EMIN", - "MIN_ETINY", - "HAVE_THREADS", - ] + __all__ += ["HAVE_CONTEXTVAR"] diff --git a/mypy/typeshed/stdlib/_typeshed/__init__.pyi b/mypy/typeshed/stdlib/_typeshed/__init__.pyi index d5e0c691e8c00..162c405222245 100644 --- a/mypy/typeshed/stdlib/_typeshed/__init__.pyi +++ b/mypy/typeshed/stdlib/_typeshed/__init__.pyi @@ -10,8 +10,8 @@ import sys from collections.abc import Awaitable, Container, Iterable, Set as AbstractSet from os import PathLike from types import TracebackType -from typing import Any, Generic, Protocol, TypeVar, Union -from typing_extensions import Final, Literal, TypeAlias, final +from typing import Any, AnyStr, Generic, Protocol, TypeVar, Union +from typing_extensions import Final, Literal, LiteralString, TypeAlias, final _KT = TypeVar("_KT") _KT_co = TypeVar("_KT_co", covariant=True) @@ -26,6 +26,9 @@ _T_contra = TypeVar("_T_contra", contravariant=True) # def __enter__(self: Self) -> Self: ... Self = TypeVar("Self") # noqa: Y001 +# covariant version of typing.AnyStr, useful for protocols +AnyStr_co = TypeVar("AnyStr_co", str, bytes, covariant=True) # noqa: Y001 + # For partially known annotations. Usually, fields where type annotations # haven't been added are left unannotated, but in some situations this # isn't possible or a type is already partially known. In cases like these, @@ -66,8 +69,14 @@ SupportsRichComparisonT = TypeVar("SupportsRichComparisonT", bound=SupportsRichC # Dunder protocols -class SupportsAdd(Protocol): - def __add__(self, __x: Any) -> Any: ... +class SupportsAdd(Protocol[_T_contra, _T_co]): + def __add__(self, __x: _T_contra) -> _T_co: ... + +class SupportsRAdd(Protocol[_T_contra, _T_co]): + def __radd__(self, __x: _T_contra) -> _T_co: ... + +class SupportsSub(Protocol[_T_contra, _T_co]): + def __sub__(self, __x: _T_contra) -> _T_co: ... class SupportsDivMod(Protocol[_T_contra, _T_co]): def __divmod__(self, __other: _T_contra) -> _T_co: ... @@ -112,9 +121,9 @@ class SupportsItemAccess(SupportsGetItem[_KT_contra, _VT], Protocol[_KT_contra, def __setitem__(self, __k: _KT_contra, __v: _VT) -> None: ... def __delitem__(self, __v: _KT_contra) -> None: ... -# These aliases are simple strings in Python 2. StrPath: TypeAlias = str | PathLike[str] # stable BytesPath: TypeAlias = bytes | PathLike[bytes] # stable +GenericPath: TypeAlias = AnyStr | PathLike[AnyStr] StrOrBytesPath: TypeAlias = str | bytes | PathLike[str] | PathLike[bytes] # stable OpenTextModeUpdating: TypeAlias = Literal[ @@ -248,3 +257,6 @@ class structseq(Generic[_T_co]): # but only has any meaning if you supply it a dict where the keys are strings. # https://github.com/python/typeshed/pull/6560#discussion_r767149830 def __new__(cls: type[Self], sequence: Iterable[_T_co], dict: dict[str, Any] = ...) -> Self: ... + +# Superset of typing.AnyStr that also inclues LiteralString +AnyOrLiteralStr = TypeVar("AnyOrLiteralStr", str, bytes, LiteralString) # noqa: Y001 diff --git a/mypy/typeshed/stdlib/_weakrefset.pyi b/mypy/typeshed/stdlib/_weakrefset.pyi index 382dbdeb6c8a0..9e9269758b005 100644 --- a/mypy/typeshed/stdlib/_weakrefset.pyi +++ b/mypy/typeshed/stdlib/_weakrefset.pyi @@ -1,7 +1,7 @@ import sys from _typeshed import Self from collections.abc import Iterable, Iterator, MutableSet -from typing import Any, Generic, TypeVar +from typing import Any, Generic, TypeVar, overload if sys.version_info >= (3, 9): from types import GenericAlias @@ -12,7 +12,10 @@ _S = TypeVar("_S") _T = TypeVar("_T") class WeakSet(MutableSet[_T], Generic[_T]): - def __init__(self, data: Iterable[_T] | None = ...) -> None: ... + @overload + def __init__(self, data: None = ...) -> None: ... + @overload + def __init__(self, data: Iterable[_T]) -> None: ... def add(self, item: _T) -> None: ... def clear(self) -> None: ... def discard(self, item: _T) -> None: ... diff --git a/mypy/typeshed/stdlib/argparse.pyi b/mypy/typeshed/stdlib/argparse.pyi index 759027d3a8900..4f6cb67209881 100644 --- a/mypy/typeshed/stdlib/argparse.pyi +++ b/mypy/typeshed/stdlib/argparse.pyi @@ -3,47 +3,28 @@ from collections.abc import Callable, Generator, Iterable, Sequence from typing import IO, Any, Generic, NewType, NoReturn, Pattern, Protocol, TypeVar, overload from typing_extensions import Literal, TypeAlias +__all__ = [ + "ArgumentParser", + "ArgumentError", + "ArgumentTypeError", + "FileType", + "HelpFormatter", + "ArgumentDefaultsHelpFormatter", + "RawDescriptionHelpFormatter", + "RawTextHelpFormatter", + "MetavarTypeHelpFormatter", + "Namespace", + "Action", + "ONE_OR_MORE", + "OPTIONAL", + "PARSER", + "REMAINDER", + "SUPPRESS", + "ZERO_OR_MORE", +] + if sys.version_info >= (3, 9): - __all__ = [ - "ArgumentParser", - "ArgumentError", - "ArgumentTypeError", - "BooleanOptionalAction", - "FileType", - "HelpFormatter", - "ArgumentDefaultsHelpFormatter", - "RawDescriptionHelpFormatter", - "RawTextHelpFormatter", - "MetavarTypeHelpFormatter", - "Namespace", - "Action", - "ONE_OR_MORE", - "OPTIONAL", - "PARSER", - "REMAINDER", - "SUPPRESS", - "ZERO_OR_MORE", - ] -else: - __all__ = [ - "ArgumentParser", - "ArgumentError", - "ArgumentTypeError", - "FileType", - "HelpFormatter", - "ArgumentDefaultsHelpFormatter", - "RawDescriptionHelpFormatter", - "RawTextHelpFormatter", - "MetavarTypeHelpFormatter", - "Namespace", - "Action", - "ONE_OR_MORE", - "OPTIONAL", - "PARSER", - "REMAINDER", - "SUPPRESS", - "ZERO_OR_MORE", - ] + __all__ += ["BooleanOptionalAction"] _T = TypeVar("_T") _ActionT = TypeVar("_ActionT", bound=Action) @@ -212,7 +193,7 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): title: str = ..., description: str | None = ..., prog: str = ..., - parser_class: type[_ArgumentParserT] = ..., + parser_class: type[_ArgumentParserT], action: type[Action] = ..., option_string: str = ..., dest: str | None = ..., @@ -241,7 +222,7 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): title: str = ..., description: str | None = ..., prog: str = ..., - parser_class: type[_ArgumentParserT] = ..., + parser_class: type[_ArgumentParserT], action: type[Action] = ..., option_string: str = ..., dest: str | None = ..., @@ -309,7 +290,7 @@ class HelpFormatter: def format_help(self) -> str: ... def _join_parts(self, part_strings: Iterable[str]) -> str: ... def _format_usage( - self, usage: str, actions: Iterable[Action], groups: Iterable[_ArgumentGroup], prefix: str | None + self, usage: str | None, actions: Iterable[Action], groups: Iterable[_ArgumentGroup], prefix: str | None ) -> str: ... def _format_actions_usage(self, actions: Iterable[Action], groups: Iterable[_ArgumentGroup]) -> str: ... def _format_text(self, text: str) -> str: ... @@ -409,16 +390,28 @@ class _StoreAction(Action): ... # undocumented class _StoreConstAction(Action): - def __init__( - self, - option_strings: Sequence[str], - dest: str, - const: Any, - default: Any = ..., - required: bool = ..., - help: str | None = ..., - metavar: str | tuple[str, ...] | None = ..., - ) -> None: ... + if sys.version_info >= (3, 11): + def __init__( + self, + option_strings: Sequence[str], + dest: str, + const: Any | None = ..., + default: Any = ..., + required: bool = ..., + help: str | None = ..., + metavar: str | tuple[str, ...] | None = ..., + ) -> None: ... + else: + def __init__( + self, + option_strings: Sequence[str], + dest: str, + const: Any, + default: Any = ..., + required: bool = ..., + help: str | None = ..., + metavar: str | tuple[str, ...] | None = ..., + ) -> None: ... # undocumented class _StoreTrueAction(_StoreConstAction): @@ -437,16 +430,28 @@ class _AppendAction(Action): ... # undocumented class _AppendConstAction(Action): - def __init__( - self, - option_strings: Sequence[str], - dest: str, - const: Any, - default: Any = ..., - required: bool = ..., - help: str | None = ..., - metavar: str | tuple[str, ...] | None = ..., - ) -> None: ... + if sys.version_info >= (3, 11): + def __init__( + self, + option_strings: Sequence[str], + dest: str, + const: Any | None = ..., + default: Any = ..., + required: bool = ..., + help: str | None = ..., + metavar: str | tuple[str, ...] | None = ..., + ) -> None: ... + else: + def __init__( + self, + option_strings: Sequence[str], + dest: str, + const: Any, + default: Any = ..., + required: bool = ..., + help: str | None = ..., + metavar: str | tuple[str, ...] | None = ..., + ) -> None: ... # undocumented class _CountAction(Action): diff --git a/mypy/typeshed/stdlib/array.pyi b/mypy/typeshed/stdlib/array.pyi index d69f02d338cf4..4797bd0670084 100644 --- a/mypy/typeshed/stdlib/array.pyi +++ b/mypy/typeshed/stdlib/array.pyi @@ -1,9 +1,9 @@ import sys -from _typeshed import Self +from _typeshed import ReadableBuffer, Self, SupportsRead, SupportsWrite from collections.abc import Iterable # pytype crashes if array inherits from collections.abc.MutableSequence instead of typing.MutableSequence -from typing import Any, BinaryIO, Generic, MutableSequence, TypeVar, overload # noqa: Y027 +from typing import Any, Generic, MutableSequence, TypeVar, overload # noqa: Y027 from typing_extensions import Literal, SupportsIndex, TypeAlias _IntTypeCode: TypeAlias = Literal["b", "B", "h", "H", "i", "I", "l", "L", "q", "Q"] @@ -21,20 +21,22 @@ class array(MutableSequence[_T], Generic[_T]): @property def itemsize(self) -> int: ... @overload - def __init__(self: array[int], __typecode: _IntTypeCode, __initializer: bytes | Iterable[_T] = ...) -> None: ... + def __init__(self: array[int], __typecode: _IntTypeCode, __initializer: bytes | Iterable[int] = ...) -> None: ... @overload - def __init__(self: array[float], __typecode: _FloatTypeCode, __initializer: bytes | Iterable[_T] = ...) -> None: ... + def __init__(self: array[float], __typecode: _FloatTypeCode, __initializer: bytes | Iterable[float] = ...) -> None: ... @overload - def __init__(self: array[str], __typecode: _UnicodeTypeCode, __initializer: bytes | Iterable[_T] = ...) -> None: ... + def __init__(self: array[str], __typecode: _UnicodeTypeCode, __initializer: bytes | Iterable[str] = ...) -> None: ... @overload - def __init__(self, typecode: str, __initializer: bytes | Iterable[_T] = ...) -> None: ... + def __init__(self, __typecode: str, __initializer: Iterable[_T]) -> None: ... + @overload + def __init__(self, __typecode: str, __initializer: bytes = ...) -> None: ... def append(self, __v: _T) -> None: ... def buffer_info(self) -> tuple[int, int]: ... def byteswap(self) -> None: ... def count(self, __v: _T) -> int: ... def extend(self, __bb: Iterable[_T]) -> None: ... - def frombytes(self, __buffer: bytes) -> None: ... - def fromfile(self, __f: BinaryIO, __n: int) -> None: ... + def frombytes(self, __buffer: ReadableBuffer) -> None: ... + def fromfile(self, __f: SupportsRead[bytes], __n: int) -> None: ... def fromlist(self, __list: list[_T]) -> None: ... def fromunicode(self, __ustr: str) -> None: ... if sys.version_info >= (3, 10): @@ -47,7 +49,7 @@ class array(MutableSequence[_T], Generic[_T]): def remove(self, __v: _T) -> None: ... def reverse(self) -> None: ... def tobytes(self) -> bytes: ... - def tofile(self, __f: BinaryIO) -> None: ... + def tofile(self, __f: SupportsWrite[bytes]) -> None: ... def tolist(self) -> list[_T]: ... def tounicode(self) -> str: ... if sys.version_info < (3, 9): diff --git a/mypy/typeshed/stdlib/ast.pyi b/mypy/typeshed/stdlib/ast.pyi index 199e4f2acb68a..3a54d158affd3 100644 --- a/mypy/typeshed/stdlib/ast.pyi +++ b/mypy/typeshed/stdlib/ast.pyi @@ -259,3 +259,6 @@ if sys.version_info >= (3, 8): def get_source_segment(source: str, node: AST, *, padded: bool = ...) -> str | None: ... def walk(node: AST) -> Iterator[AST]: ... + +if sys.version_info >= (3, 9): + def main() -> None: ... diff --git a/mypy/typeshed/stdlib/asyncio/__init__.pyi b/mypy/typeshed/stdlib/asyncio/__init__.pyi index 2f4823b22b244..24a86caed66e3 100644 --- a/mypy/typeshed/stdlib/asyncio/__init__.pyi +++ b/mypy/typeshed/stdlib/asyncio/__init__.pyi @@ -24,6 +24,7 @@ if sys.version_info >= (3, 9): if sys.version_info >= (3, 11): from .taskgroups import * + from .timeouts import * if sys.platform == "win32": from .windows_events import * diff --git a/mypy/typeshed/stdlib/asyncio/base_events.pyi b/mypy/typeshed/stdlib/asyncio/base_events.pyi index 7742651fea2ab..310a9f5855912 100644 --- a/mypy/typeshed/stdlib/asyncio/base_events.pyi +++ b/mypy/typeshed/stdlib/asyncio/base_events.pyi @@ -1,6 +1,6 @@ import ssl import sys -from _typeshed import FileDescriptorLike +from _typeshed import FileDescriptorLike, WriteableBuffer from asyncio.events import AbstractEventLoop, AbstractServer, Handle, TimerHandle from asyncio.futures import Future from asyncio.protocols import BaseProtocol @@ -29,7 +29,18 @@ _ProtocolFactory: TypeAlias = Callable[[], BaseProtocol] _SSLContext: TypeAlias = bool | None | ssl.SSLContext class Server(AbstractServer): - if sys.version_info >= (3, 7): + if sys.version_info >= (3, 11): + def __init__( + self, + loop: AbstractEventLoop, + sockets: Iterable[socket], + protocol_factory: _ProtocolFactory, + ssl_context: _SSLContext, + backlog: int, + ssl_handshake_timeout: float | None, + ssl_shutdown_timeout: float | None = ..., + ) -> None: ... + elif sys.version_info >= (3, 7): def __init__( self, loop: AbstractEventLoop, @@ -39,12 +50,13 @@ class Server(AbstractServer): backlog: int, ssl_handshake_timeout: float | None, ) -> None: ... + else: + def __init__(self, loop: AbstractEventLoop, sockets: list[socket]) -> None: ... + if sys.version_info >= (3, 7): def get_loop(self) -> AbstractEventLoop: ... def is_serving(self) -> bool: ... async def start_serving(self) -> None: ... async def serve_forever(self) -> None: ... - else: - def __init__(self, loop: AbstractEventLoop, sockets: list[socket]) -> None: ... if sys.version_info >= (3, 8): @property def sockets(self) -> tuple[socket, ...]: ... @@ -86,7 +98,11 @@ class BaseEventLoop(AbstractEventLoop): # Future methods def create_future(self) -> Future[Any]: ... # Tasks methods - if sys.version_info >= (3, 8): + if sys.version_info >= (3, 11): + def create_task( + self, coro: Coroutine[Any, Any, _T] | Generator[Any, None, _T], *, name: object = ..., context: Context | None = ... + ) -> Task[_T]: ... + elif sys.version_info >= (3, 8): def create_task(self, coro: Coroutine[Any, Any, _T] | Generator[Any, None, _T], *, name: object = ...) -> Task[_T]: ... else: def create_task(self, coro: Coroutine[Any, Any, _T] | Generator[Any, None, _T]) -> Task[_T]: ... @@ -113,7 +129,46 @@ class BaseEventLoop(AbstractEventLoop): flags: int = ..., ) -> list[tuple[AddressFamily, SocketKind, int, str, tuple[str, int] | tuple[str, int, int, int]]]: ... async def getnameinfo(self, sockaddr: tuple[str, int] | tuple[str, int, int, int], flags: int = ...) -> tuple[str, str]: ... - if sys.version_info >= (3, 8): + if sys.version_info >= (3, 11): + @overload + async def create_connection( + self, + protocol_factory: Callable[[], _ProtocolT], + host: str = ..., + port: int = ..., + *, + ssl: _SSLContext = ..., + family: int = ..., + proto: int = ..., + flags: int = ..., + sock: None = ..., + local_addr: tuple[str, int] | None = ..., + server_hostname: str | None = ..., + ssl_handshake_timeout: float | None = ..., + ssl_shutdown_timeout: float | None = ..., + happy_eyeballs_delay: float | None = ..., + interleave: int | None = ..., + ) -> tuple[BaseTransport, _ProtocolT]: ... + @overload + async def create_connection( + self, + protocol_factory: Callable[[], _ProtocolT], + host: None = ..., + port: None = ..., + *, + ssl: _SSLContext = ..., + family: int = ..., + proto: int = ..., + flags: int = ..., + sock: socket, + local_addr: None = ..., + server_hostname: str | None = ..., + ssl_handshake_timeout: float | None = ..., + ssl_shutdown_timeout: float | None = ..., + happy_eyeballs_delay: float | None = ..., + interleave: int | None = ..., + ) -> tuple[BaseTransport, _ProtocolT]: ... + elif sys.version_info >= (3, 8): @overload async def create_connection( self, @@ -214,10 +269,7 @@ class BaseEventLoop(AbstractEventLoop): local_addr: None = ..., server_hostname: str | None = ..., ) -> tuple[BaseTransport, _ProtocolT]: ... - if sys.version_info >= (3, 7): - async def sock_sendfile( - self, sock: socket, file: IO[bytes], offset: int = ..., count: int | None = ..., *, fallback: bool | None = ... - ) -> int: ... + if sys.version_info >= (3, 11): @overload async def create_server( self, @@ -233,6 +285,7 @@ class BaseEventLoop(AbstractEventLoop): reuse_address: bool | None = ..., reuse_port: bool | None = ..., ssl_handshake_timeout: float | None = ..., + ssl_shutdown_timeout: float | None = ..., start_serving: bool = ..., ) -> Server: ... @overload @@ -250,8 +303,20 @@ class BaseEventLoop(AbstractEventLoop): reuse_address: bool | None = ..., reuse_port: bool | None = ..., ssl_handshake_timeout: float | None = ..., + ssl_shutdown_timeout: float | None = ..., start_serving: bool = ..., ) -> Server: ... + async def start_tls( + self, + transport: BaseTransport, + protocol: BaseProtocol, + sslcontext: ssl.SSLContext, + *, + server_side: bool = ..., + server_hostname: str | None = ..., + ssl_handshake_timeout: float | None = ..., + ssl_shutdown_timeout: float | None = ..., + ) -> BaseTransport: ... async def connect_accepted_socket( self, protocol_factory: Callable[[], _ProtocolT], @@ -259,10 +324,43 @@ class BaseEventLoop(AbstractEventLoop): *, ssl: _SSLContext = ..., ssl_handshake_timeout: float | None = ..., + ssl_shutdown_timeout: float | None = ..., ) -> tuple[BaseTransport, _ProtocolT]: ... - async def sendfile( - self, transport: BaseTransport, file: IO[bytes], offset: int = ..., count: int | None = ..., *, fallback: bool = ... - ) -> int: ... + elif sys.version_info >= (3, 7): + @overload + async def create_server( + self, + protocol_factory: _ProtocolFactory, + host: str | Sequence[str] | None = ..., + port: int = ..., + *, + family: int = ..., + flags: int = ..., + sock: None = ..., + backlog: int = ..., + ssl: _SSLContext = ..., + reuse_address: bool | None = ..., + reuse_port: bool | None = ..., + ssl_handshake_timeout: float | None = ..., + start_serving: bool = ..., + ) -> Server: ... + @overload + async def create_server( + self, + protocol_factory: _ProtocolFactory, + host: None = ..., + port: None = ..., + *, + family: int = ..., + flags: int = ..., + sock: socket = ..., + backlog: int = ..., + ssl: _SSLContext = ..., + reuse_address: bool | None = ..., + reuse_port: bool | None = ..., + ssl_handshake_timeout: float | None = ..., + start_serving: bool = ..., + ) -> Server: ... async def start_tls( self, transport: BaseTransport, @@ -273,6 +371,14 @@ class BaseEventLoop(AbstractEventLoop): server_hostname: str | None = ..., ssl_handshake_timeout: float | None = ..., ) -> BaseTransport: ... + async def connect_accepted_socket( + self, + protocol_factory: Callable[[], _ProtocolT], + sock: socket, + *, + ssl: _SSLContext = ..., + ssl_handshake_timeout: float | None = ..., + ) -> tuple[BaseTransport, _ProtocolT]: ... else: @overload async def create_server( @@ -307,6 +413,13 @@ class BaseEventLoop(AbstractEventLoop): async def connect_accepted_socket( self, protocol_factory: Callable[[], _ProtocolT], sock: socket, *, ssl: _SSLContext = ... ) -> tuple[BaseTransport, _ProtocolT]: ... + if sys.version_info >= (3, 7): + async def sock_sendfile( + self, sock: socket, file: IO[bytes], offset: int = ..., count: int | None = ..., *, fallback: bool | None = ... + ) -> int: ... + async def sendfile( + self, transport: BaseTransport, file: IO[bytes], offset: int = ..., count: int | None = ..., *, fallback: bool = ... + ) -> int: ... if sys.version_info >= (3, 11): async def create_datagram_endpoint( # type: ignore[override] self, @@ -378,10 +491,12 @@ class BaseEventLoop(AbstractEventLoop): def remove_reader(self, fd: FileDescriptorLike) -> bool: ... def add_writer(self, fd: FileDescriptorLike, callback: Callable[..., Any], *args: Any) -> None: ... def remove_writer(self, fd: FileDescriptorLike) -> bool: ... + # The sock_* methods (and probably some others) are not actually implemented on + # BaseEventLoop, only on subclasses. We list them here for now for convenience. # Completion based I/O methods returning Futures prior to 3.7 if sys.version_info >= (3, 7): async def sock_recv(self, sock: socket, nbytes: int) -> bytes: ... - async def sock_recv_into(self, sock: socket, buf: bytearray) -> int: ... + async def sock_recv_into(self, sock: socket, buf: WriteableBuffer) -> int: ... async def sock_sendall(self, sock: socket, data: bytes) -> None: ... async def sock_connect(self, sock: socket, address: _Address) -> None: ... async def sock_accept(self, sock: socket) -> tuple[socket, _RetAddress]: ... @@ -390,6 +505,10 @@ class BaseEventLoop(AbstractEventLoop): def sock_sendall(self, sock: socket, data: bytes) -> Future[None]: ... def sock_connect(self, sock: socket, address: _Address) -> Future[None]: ... def sock_accept(self, sock: socket) -> Future[tuple[socket, _RetAddress]]: ... + if sys.version_info >= (3, 11): + async def sock_recvfrom(self, sock: socket, bufsize: int) -> bytes: ... + async def sock_recvfrom_into(self, sock: socket, buf: WriteableBuffer, nbytes: int = ...) -> int: ... + async def sock_sendto(self, sock: socket, data: bytes, address: _Address) -> None: ... # Signal handling. def add_signal_handler(self, sig: int, callback: Callable[..., Any], *args: Any) -> None: ... def remove_signal_handler(self, sig: int) -> bool: ... diff --git a/mypy/typeshed/stdlib/asyncio/constants.pyi b/mypy/typeshed/stdlib/asyncio/constants.pyi index 230cf4faf4837..1fa643c7414b2 100644 --- a/mypy/typeshed/stdlib/asyncio/constants.pyi +++ b/mypy/typeshed/stdlib/asyncio/constants.pyi @@ -8,6 +8,10 @@ DEBUG_STACK_DEPTH: Literal[10] if sys.version_info >= (3, 7): SSL_HANDSHAKE_TIMEOUT: float SENDFILE_FALLBACK_READBUFFER_SIZE: Literal[262144] +if sys.version_info >= (3, 11): + SSL_SHUTDOWN_TIMEOUT: float + FLOW_CONTROL_HIGH_WATER_SSL_READ: Literal[256] + FLOW_CONTROL_HIGH_WATER_SSL_WRITE: Literal[512] class _SendfileMode(enum.Enum): UNSUPPORTED: int diff --git a/mypy/typeshed/stdlib/asyncio/events.pyi b/mypy/typeshed/stdlib/asyncio/events.pyi index ae566234160b4..8396f0957a1eb 100644 --- a/mypy/typeshed/stdlib/asyncio/events.pyi +++ b/mypy/typeshed/stdlib/asyncio/events.pyi @@ -1,6 +1,6 @@ import ssl import sys -from _typeshed import FileDescriptorLike, Self +from _typeshed import FileDescriptorLike, Self, WriteableBuffer from abc import ABCMeta, abstractmethod from collections.abc import Awaitable, Callable, Coroutine, Generator, Sequence from socket import AddressFamily, SocketKind, _Address, _RetAddress, socket @@ -184,7 +184,16 @@ class AbstractEventLoop: @abstractmethod def create_future(self) -> Future[Any]: ... # Tasks methods - if sys.version_info >= (3, 8): + if sys.version_info >= (3, 11): + @abstractmethod + def create_task( + self, + coro: Coroutine[Any, Any, _T] | Generator[Any, None, _T], + *, + name: str | None = ..., + context: Context | None = ..., + ) -> Task[_T]: ... + elif sys.version_info >= (3, 8): @abstractmethod def create_task( self, coro: Coroutine[Any, Any, _T] | Generator[Any, None, _T], *, name: str | None = ... @@ -223,7 +232,48 @@ class AbstractEventLoop: ) -> list[tuple[AddressFamily, SocketKind, int, str, tuple[str, int] | tuple[str, int, int, int]]]: ... @abstractmethod async def getnameinfo(self, sockaddr: tuple[str, int] | tuple[str, int, int, int], flags: int = ...) -> tuple[str, str]: ... - if sys.version_info >= (3, 8): + if sys.version_info >= (3, 11): + @overload + @abstractmethod + async def create_connection( + self, + protocol_factory: Callable[[], _ProtocolT], + host: str = ..., + port: int = ..., + *, + ssl: _SSLContext = ..., + family: int = ..., + proto: int = ..., + flags: int = ..., + sock: None = ..., + local_addr: tuple[str, int] | None = ..., + server_hostname: str | None = ..., + ssl_handshake_timeout: float | None = ..., + ssl_shutdown_timeout: float | None = ..., + happy_eyeballs_delay: float | None = ..., + interleave: int | None = ..., + ) -> tuple[BaseTransport, _ProtocolT]: ... + @overload + @abstractmethod + async def create_connection( + self, + protocol_factory: Callable[[], _ProtocolT], + host: None = ..., + port: None = ..., + *, + ssl: _SSLContext = ..., + family: int = ..., + proto: int = ..., + flags: int = ..., + sock: socket, + local_addr: None = ..., + server_hostname: str | None = ..., + ssl_handshake_timeout: float | None = ..., + ssl_shutdown_timeout: float | None = ..., + happy_eyeballs_delay: float | None = ..., + interleave: int | None = ..., + ) -> tuple[BaseTransport, _ProtocolT]: ... + elif sys.version_info >= (3, 8): @overload @abstractmethod async def create_connection( @@ -330,11 +380,7 @@ class AbstractEventLoop: local_addr: None = ..., server_hostname: str | None = ..., ) -> tuple[BaseTransport, _ProtocolT]: ... - if sys.version_info >= (3, 7): - @abstractmethod - async def sock_sendfile( - self, sock: socket, file: IO[bytes], offset: int = ..., count: int | None = ..., *, fallback: bool | None = ... - ) -> int: ... + if sys.version_info >= (3, 11): @overload @abstractmethod async def create_server( @@ -351,6 +397,7 @@ class AbstractEventLoop: reuse_address: bool | None = ..., reuse_port: bool | None = ..., ssl_handshake_timeout: float | None = ..., + ssl_shutdown_timeout: float | None = ..., start_serving: bool = ..., ) -> Server: ... @overload @@ -369,18 +416,21 @@ class AbstractEventLoop: reuse_address: bool | None = ..., reuse_port: bool | None = ..., ssl_handshake_timeout: float | None = ..., + ssl_shutdown_timeout: float | None = ..., start_serving: bool = ..., ) -> Server: ... - async def create_unix_connection( + @abstractmethod + async def start_tls( self, - protocol_factory: Callable[[], _ProtocolT], - path: str | None = ..., + transport: BaseTransport, + protocol: BaseProtocol, + sslcontext: ssl.SSLContext, *, - ssl: _SSLContext = ..., - sock: socket | None = ..., + server_side: bool = ..., server_hostname: str | None = ..., ssl_handshake_timeout: float | None = ..., - ) -> tuple[BaseTransport, _ProtocolT]: ... + ssl_shutdown_timeout: float | None = ..., + ) -> BaseTransport: ... async def create_unix_server( self, protocol_factory: _ProtocolFactory, @@ -390,12 +440,46 @@ class AbstractEventLoop: backlog: int = ..., ssl: _SSLContext = ..., ssl_handshake_timeout: float | None = ..., + ssl_shutdown_timeout: float | None = ..., start_serving: bool = ..., ) -> Server: ... + elif sys.version_info >= (3, 7): + @overload @abstractmethod - async def sendfile( - self, transport: BaseTransport, file: IO[bytes], offset: int = ..., count: int | None = ..., *, fallback: bool = ... - ) -> int: ... + async def create_server( + self, + protocol_factory: _ProtocolFactory, + host: str | Sequence[str] | None = ..., + port: int = ..., + *, + family: int = ..., + flags: int = ..., + sock: None = ..., + backlog: int = ..., + ssl: _SSLContext = ..., + reuse_address: bool | None = ..., + reuse_port: bool | None = ..., + ssl_handshake_timeout: float | None = ..., + start_serving: bool = ..., + ) -> Server: ... + @overload + @abstractmethod + async def create_server( + self, + protocol_factory: _ProtocolFactory, + host: None = ..., + port: None = ..., + *, + family: int = ..., + flags: int = ..., + sock: socket = ..., + backlog: int = ..., + ssl: _SSLContext = ..., + reuse_address: bool | None = ..., + reuse_port: bool | None = ..., + ssl_handshake_timeout: float | None = ..., + start_serving: bool = ..., + ) -> Server: ... @abstractmethod async def start_tls( self, @@ -407,6 +491,17 @@ class AbstractEventLoop: server_hostname: str | None = ..., ssl_handshake_timeout: float | None = ..., ) -> BaseTransport: ... + async def create_unix_server( + self, + protocol_factory: _ProtocolFactory, + path: str | None = ..., + *, + sock: socket | None = ..., + backlog: int = ..., + ssl: _SSLContext = ..., + ssl_handshake_timeout: float | None = ..., + start_serving: bool = ..., + ) -> Server: ... else: @overload @abstractmethod @@ -440,24 +535,76 @@ class AbstractEventLoop: reuse_address: bool | None = ..., reuse_port: bool | None = ..., ) -> Server: ... + async def create_unix_server( + self, + protocol_factory: _ProtocolFactory, + path: str, + *, + sock: socket | None = ..., + backlog: int = ..., + ssl: _SSLContext = ..., + ) -> Server: ... + if sys.version_info >= (3, 11): + async def connect_accepted_socket( + self, + protocol_factory: Callable[[], _ProtocolT], + sock: socket, + *, + ssl: _SSLContext = ..., + ssl_handshake_timeout: float | None = ..., + ssl_shutdown_timeout: float | None = ..., + ) -> tuple[BaseTransport, _ProtocolT]: ... + elif sys.version_info >= (3, 10): + async def connect_accepted_socket( + self, + protocol_factory: Callable[[], _ProtocolT], + sock: socket, + *, + ssl: _SSLContext = ..., + ssl_handshake_timeout: float | None = ..., + ) -> tuple[BaseTransport, _ProtocolT]: ... + if sys.version_info >= (3, 11): async def create_unix_connection( self, protocol_factory: Callable[[], _ProtocolT], - path: str, + path: str | None = ..., *, ssl: _SSLContext = ..., sock: socket | None = ..., server_hostname: str | None = ..., + ssl_handshake_timeout: float | None = ..., + ssl_shutdown_timeout: float | None = ..., ) -> tuple[BaseTransport, _ProtocolT]: ... - async def create_unix_server( + elif sys.version_info >= (3, 7): + async def create_unix_connection( self, - protocol_factory: _ProtocolFactory, - path: str, + protocol_factory: Callable[[], _ProtocolT], + path: str | None = ..., *, + ssl: _SSLContext = ..., sock: socket | None = ..., - backlog: int = ..., + server_hostname: str | None = ..., + ssl_handshake_timeout: float | None = ..., + ) -> tuple[BaseTransport, _ProtocolT]: ... + else: + async def create_unix_connection( + self, + protocol_factory: Callable[[], _ProtocolT], + path: str, + *, ssl: _SSLContext = ..., - ) -> Server: ... + sock: socket | None = ..., + server_hostname: str | None = ..., + ) -> tuple[BaseTransport, _ProtocolT]: ... + if sys.version_info >= (3, 7): + @abstractmethod + async def sock_sendfile( + self, sock: socket, file: IO[bytes], offset: int = ..., count: int | None = ..., *, fallback: bool | None = ... + ) -> int: ... + @abstractmethod + async def sendfile( + self, transport: BaseTransport, file: IO[bytes], offset: int = ..., count: int | None = ..., *, fallback: bool = ... + ) -> int: ... @abstractmethod async def create_datagram_endpoint( @@ -529,7 +676,7 @@ class AbstractEventLoop: @abstractmethod async def sock_recv(self, sock: socket, nbytes: int) -> bytes: ... @abstractmethod - async def sock_recv_into(self, sock: socket, buf: bytearray) -> int: ... + async def sock_recv_into(self, sock: socket, buf: WriteableBuffer) -> int: ... @abstractmethod async def sock_sendall(self, sock: socket, data: bytes) -> None: ... @abstractmethod @@ -545,6 +692,13 @@ class AbstractEventLoop: def sock_connect(self, sock: socket, address: _Address) -> Future[None]: ... @abstractmethod def sock_accept(self, sock: socket) -> Future[tuple[socket, _RetAddress]]: ... + if sys.version_info >= (3, 11): + @abstractmethod + async def sock_recvfrom(self, sock: socket, bufsize: int) -> bytes: ... + @abstractmethod + async def sock_recvfrom_into(self, sock: socket, buf: WriteableBuffer, nbytes: int = ...) -> int: ... + @abstractmethod + async def sock_sendto(self, sock: socket, data: bytes, address: _Address) -> None: ... # Signal handling. @abstractmethod def add_signal_handler(self, sig: int, callback: Callable[..., Any], *args: Any) -> None: ... diff --git a/mypy/typeshed/stdlib/asyncio/exceptions.pyi b/mypy/typeshed/stdlib/asyncio/exceptions.pyi index a1bc2c16ab1fc..075fbb805bb96 100644 --- a/mypy/typeshed/stdlib/asyncio/exceptions.pyi +++ b/mypy/typeshed/stdlib/asyncio/exceptions.pyi @@ -1,11 +1,24 @@ -__all__ = ( - "CancelledError", - "InvalidStateError", - "TimeoutError", - "IncompleteReadError", - "LimitOverrunError", - "SendfileNotAvailableError", -) +import sys + +if sys.version_info >= (3, 11): + __all__ = ( + "BrokenBarrierError", + "CancelledError", + "InvalidStateError", + "TimeoutError", + "IncompleteReadError", + "LimitOverrunError", + "SendfileNotAvailableError", + ) +else: + __all__ = ( + "CancelledError", + "InvalidStateError", + "TimeoutError", + "IncompleteReadError", + "LimitOverrunError", + "SendfileNotAvailableError", + ) class CancelledError(BaseException): ... class TimeoutError(Exception): ... @@ -20,3 +33,6 @@ class IncompleteReadError(EOFError): class LimitOverrunError(Exception): consumed: int def __init__(self, message: str, consumed: int) -> None: ... + +if sys.version_info >= (3, 11): + class BrokenBarrierError(RuntimeError): ... diff --git a/mypy/typeshed/stdlib/asyncio/futures.pyi b/mypy/typeshed/stdlib/asyncio/futures.pyi index 692d263f673ba..21bfe86e44c6f 100644 --- a/mypy/typeshed/stdlib/asyncio/futures.pyi +++ b/mypy/typeshed/stdlib/asyncio/futures.pyi @@ -55,6 +55,7 @@ class Future(Awaitable[_T], Iterable[_T]): def __del__(self) -> None: ... if sys.version_info >= (3, 7): def get_loop(self) -> AbstractEventLoop: ... + @property def _callbacks(self: Self) -> list[tuple[Callable[[Self], Any], Context]]: ... def add_done_callback(self: Self, __fn: Callable[[Self], Any], *, context: Context | None = ...) -> None: ... else: diff --git a/mypy/typeshed/stdlib/asyncio/locks.pyi b/mypy/typeshed/stdlib/asyncio/locks.pyi index 2758e0c469196..269602c7bc669 100644 --- a/mypy/typeshed/stdlib/asyncio/locks.pyi +++ b/mypy/typeshed/stdlib/asyncio/locks.pyi @@ -1,4 +1,6 @@ +import enum import sys +from _typeshed import Self from collections import deque from collections.abc import Callable, Generator from types import TracebackType @@ -8,7 +10,12 @@ from typing_extensions import Literal from .events import AbstractEventLoop from .futures import Future -if sys.version_info >= (3, 7): +if sys.version_info >= (3, 11): + from .mixins import _LoopBoundMixin + +if sys.version_info >= (3, 11): + __all__ = ("Lock", "Event", "Condition", "Semaphore", "BoundedSemaphore", "Barrier") +elif sys.version_info >= (3, 7): __all__ = ("Lock", "Event", "Condition", "Semaphore", "BoundedSemaphore") else: __all__ = ["Lock", "Event", "Condition", "Semaphore", "BoundedSemaphore"] @@ -40,20 +47,32 @@ else: ) -> None: ... class Lock(_ContextManagerMixin): - def __init__(self, *, loop: AbstractEventLoop | None = ...) -> None: ... + if sys.version_info >= (3, 11): + def __init__(self) -> None: ... + else: + def __init__(self, *, loop: AbstractEventLoop | None = ...) -> None: ... + def locked(self) -> bool: ... async def acquire(self) -> Literal[True]: ... def release(self) -> None: ... class Event: - def __init__(self, *, loop: AbstractEventLoop | None = ...) -> None: ... + if sys.version_info >= (3, 11): + def __init__(self) -> None: ... + else: + def __init__(self, *, loop: AbstractEventLoop | None = ...) -> None: ... + def is_set(self) -> bool: ... def set(self) -> None: ... def clear(self) -> None: ... async def wait(self) -> Literal[True]: ... class Condition(_ContextManagerMixin): - def __init__(self, lock: Lock | None = ..., *, loop: AbstractEventLoop | None = ...) -> None: ... + if sys.version_info >= (3, 11): + def __init__(self, lock: Lock | None = ...) -> None: ... + else: + def __init__(self, lock: Lock | None = ..., *, loop: AbstractEventLoop | None = ...) -> None: ... + def locked(self) -> bool: ... async def acquire(self) -> Literal[True]: ... def release(self) -> None: ... @@ -65,11 +84,39 @@ class Condition(_ContextManagerMixin): class Semaphore(_ContextManagerMixin): _value: int _waiters: deque[Future[Any]] - def __init__(self, value: int = ..., *, loop: AbstractEventLoop | None = ...) -> None: ... + if sys.version_info >= (3, 11): + def __init__(self, value: int = ...) -> None: ... + else: + def __init__(self, value: int = ..., *, loop: AbstractEventLoop | None = ...) -> None: ... + def locked(self) -> bool: ... async def acquire(self) -> Literal[True]: ... def release(self) -> None: ... def _wake_up_next(self) -> None: ... class BoundedSemaphore(Semaphore): - def __init__(self, value: int = ..., *, loop: AbstractEventLoop | None = ...) -> None: ... + if sys.version_info >= (3, 11): + def __init__(self, value: int = ...) -> None: ... + else: + def __init__(self, value: int = ..., *, loop: AbstractEventLoop | None = ...) -> None: ... + +if sys.version_info >= (3, 11): + class _BarrierState(enum.Enum): # undocumented + FILLING: str + DRAINING: str + RESETTING: str + BROKEN: str + + class Barrier(_LoopBoundMixin): + def __init__(self, parties: int) -> None: ... + async def __aenter__(self: Self) -> Self: ... + async def __aexit__(self, *args: object) -> None: ... + async def wait(self) -> int: ... + async def abort(self) -> None: ... + async def reset(self) -> None: ... + @property + def parties(self) -> int: ... + @property + def n_waiting(self) -> int: ... + @property + def broken(self) -> bool: ... diff --git a/mypy/typeshed/stdlib/asyncio/mixins.pyi b/mypy/typeshed/stdlib/asyncio/mixins.pyi index 4c11865c8968f..3e04f2b375181 100644 --- a/mypy/typeshed/stdlib/asyncio/mixins.pyi +++ b/mypy/typeshed/stdlib/asyncio/mixins.pyi @@ -1,7 +1,9 @@ +import sys import threading from typing import NoReturn _global_lock: threading.Lock class _LoopBoundMixin: - def __init__(self, *, loop: NoReturn = ...) -> None: ... + if sys.version_info < (3, 11): + def __init__(self, *, loop: NoReturn = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/asyncio/protocols.pyi b/mypy/typeshed/stdlib/asyncio/protocols.pyi index 7b5169702dbac..e2fc118947bc3 100644 --- a/mypy/typeshed/stdlib/asyncio/protocols.pyi +++ b/mypy/typeshed/stdlib/asyncio/protocols.pyi @@ -1,4 +1,5 @@ import sys +from _typeshed import ReadableBuffer from asyncio import transports from typing import Any @@ -19,7 +20,7 @@ class Protocol(BaseProtocol): if sys.version_info >= (3, 7): class BufferedProtocol(BaseProtocol): - def get_buffer(self, sizehint: int) -> bytearray: ... + def get_buffer(self, sizehint: int) -> ReadableBuffer: ... def buffer_updated(self, nbytes: int) -> None: ... def eof_received(self) -> bool | None: ... diff --git a/mypy/typeshed/stdlib/asyncio/queues.pyi b/mypy/typeshed/stdlib/asyncio/queues.pyi index 93ea9d9fc6fec..0e1a0b2808dfa 100644 --- a/mypy/typeshed/stdlib/asyncio/queues.pyi +++ b/mypy/typeshed/stdlib/asyncio/queues.pyi @@ -16,7 +16,11 @@ class QueueFull(Exception): ... _T = TypeVar("_T") class Queue(Generic[_T]): - def __init__(self, maxsize: int = ..., *, loop: AbstractEventLoop | None = ...) -> None: ... + if sys.version_info >= (3, 11): + def __init__(self, maxsize: int = ...) -> None: ... + else: + def __init__(self, maxsize: int = ..., *, loop: AbstractEventLoop | None = ...) -> None: ... + def _init(self, maxsize: int) -> None: ... def _get(self) -> _T: ... def _put(self, item: _T) -> None: ... diff --git a/mypy/typeshed/stdlib/asyncio/runners.pyi b/mypy/typeshed/stdlib/asyncio/runners.pyi index 32cd839f2f797..49d236bbee9e0 100644 --- a/mypy/typeshed/stdlib/asyncio/runners.pyi +++ b/mypy/typeshed/stdlib/asyncio/runners.pyi @@ -1,11 +1,28 @@ import sys -from collections.abc import Awaitable -from typing import TypeVar +from _typeshed import Self +from collections.abc import Callable, Coroutine +from contextvars import Context +from typing import Any, TypeVar -__all__ = ("run",) +from .events import AbstractEventLoop + +if sys.version_info >= (3, 11): + __all__ = ("Runner", "run") +else: + __all__ = ("run",) _T = TypeVar("_T") + +if sys.version_info >= (3, 11): + class Runner: + def __init__(self, *, debug: bool | None = ..., loop_factory: Callable[[], AbstractEventLoop] | None = ...) -> None: ... + def __enter__(self: Self) -> Self: ... + def __exit__(self, exc_type: object, exc_val: object, exc_tb: object) -> None: ... + def close(self) -> None: ... + def get_loop(self) -> AbstractEventLoop: ... + def run(self, coro: Coroutine[Any, Any, _T], *, context: Context | None = ...) -> _T: ... + if sys.version_info >= (3, 8): - def run(main: Awaitable[_T], *, debug: bool | None = ...) -> _T: ... + def run(main: Coroutine[Any, Any, _T], *, debug: bool | None = ...) -> _T: ... else: - def run(main: Awaitable[_T], *, debug: bool = ...) -> _T: ... + def run(main: Coroutine[Any, Any, _T], *, debug: bool = ...) -> _T: ... diff --git a/mypy/typeshed/stdlib/asyncio/sslproto.pyi b/mypy/typeshed/stdlib/asyncio/sslproto.pyi index 619e329bfb436..77807743f7498 100644 --- a/mypy/typeshed/stdlib/asyncio/sslproto.pyi +++ b/mypy/typeshed/stdlib/asyncio/sslproto.pyi @@ -2,17 +2,36 @@ import ssl import sys from collections import deque from collections.abc import Callable +from enum import Enum from typing import Any, ClassVar -from typing_extensions import Literal +from typing_extensions import Literal, TypeAlias from . import constants, events, futures, protocols, transports def _create_transport_context(server_side: bool, server_hostname: str | None) -> ssl.SSLContext: ... -_UNWRAPPED: Literal["UNWRAPPED"] -_DO_HANDSHAKE: Literal["DO_HANDSHAKE"] -_WRAPPED: Literal["WRAPPED"] -_SHUTDOWN: Literal["SHUTDOWN"] +if sys.version_info >= (3, 11): + SSLAgainErrors: tuple[type[ssl.SSLWantReadError], type[ssl.SSLSyscallError]] + + class SSLProtocolState(Enum): + UNWRAPPED: str + DO_HANDSHAKE: str + WRAPPED: str + FLUSHING: str + SHUTDOWN: str + + class AppProtocolState(Enum): + STATE_INIT: str + STATE_CON_MADE: str + STATE_EOF: str + STATE_CON_LOST: str + def add_flowcontrol_defaults(high: int | None, low: int | None, kb: int) -> tuple[int, int]: ... + +else: + _UNWRAPPED: Literal["UNWRAPPED"] + _DO_HANDSHAKE: Literal["DO_HANDSHAKE"] + _WRAPPED: Literal["WRAPPED"] + _SHUTDOWN: Literal["SHUTDOWN"] class _SSLPipe: @@ -70,8 +89,20 @@ class _SSLProtocolTransport(transports._FlowControlMixin, transports.Transport): def write(self, data: bytes) -> None: ... def can_write_eof(self) -> Literal[False]: ... def abort(self) -> None: ... + if sys.version_info >= (3, 11): + def get_write_buffer_limits(self) -> tuple[int, int]: ... + def get_read_buffer_limits(self) -> tuple[int, int]: ... + def set_read_buffer_limits(self, high: int | None = ..., low: int | None = ...) -> None: ... + def get_read_buffer_size(self) -> int: ... -class SSLProtocol(protocols.Protocol): +if sys.version_info >= (3, 11): + _SSLProtocolBase: TypeAlias = protocols.BufferedProtocol +else: + _SSLProtocolBase: TypeAlias = protocols.Protocol + +class SSLProtocol(_SSLProtocolBase): + if sys.version_info >= (3, 11): + max_size: ClassVar[int] _server_side: bool _server_hostname: str | None @@ -92,7 +123,20 @@ class SSLProtocol(protocols.Protocol): _app_protocol: protocols.BaseProtocol _app_protocol_is_buffer: bool - if sys.version_info >= (3, 7): + if sys.version_info >= (3, 11): + def __init__( + self, + loop: events.AbstractEventLoop, + app_protocol: protocols.BaseProtocol, + sslcontext: ssl.SSLContext, + waiter: futures.Future[Any], + server_side: bool = ..., + server_hostname: str | None = ..., + call_connection_made: bool = ..., + ssl_handshake_timeout: int | None = ..., + ssl_shutdown_timeout: float | None = ..., + ) -> None: ... + elif sys.version_info >= (3, 7): def __init__( self, loop: events.AbstractEventLoop, @@ -123,17 +167,25 @@ class SSLProtocol(protocols.Protocol): def connection_lost(self, exc: BaseException | None) -> None: ... def pause_writing(self) -> None: ... def resume_writing(self) -> None: ... - def data_received(self, data: bytes) -> None: ... def eof_received(self) -> None: ... def _get_extra_info(self, name: str, default: Any | None = ...) -> Any: ... def _start_shutdown(self) -> None: ... - def _write_appdata(self, data: bytes) -> None: ... + if sys.version_info >= (3, 11): + def _write_appdata(self, list_of_data: list[bytes]) -> None: ... + else: + def _write_appdata(self, data: bytes) -> None: ... + def _start_handshake(self) -> None: ... if sys.version_info >= (3, 7): def _check_handshake_timeout(self) -> None: ... def _on_handshake_complete(self, handshake_exc: BaseException | None) -> None: ... - def _process_write_backlog(self) -> None: ... def _fatal_error(self, exc: BaseException, message: str = ...) -> None: ... - def _finalize(self) -> None: ... def _abort(self) -> None: ... + if sys.version_info >= (3, 11): + def buffer_updated(self, nbytes: int) -> None: ... + def get_buffer(self, n: int) -> memoryview: ... + else: + def _finalize(self) -> None: ... + def _process_write_backlog(self) -> None: ... + def data_received(self, data: bytes) -> None: ... diff --git a/mypy/typeshed/stdlib/asyncio/streams.pyi b/mypy/typeshed/stdlib/asyncio/streams.pyi index 14a6d2c4d8fe8..0f24d01d50cfa 100644 --- a/mypy/typeshed/stdlib/asyncio/streams.pyi +++ b/mypy/typeshed/stdlib/asyncio/streams.pyi @@ -1,3 +1,4 @@ +import ssl import sys from _typeshed import Self, StrPath from collections.abc import AsyncIterator, Awaitable, Callable, Iterable, Sequence @@ -179,6 +180,10 @@ class StreamWriter: def get_extra_info(self, name: str, default: Any = ...) -> Any: ... async def drain(self) -> None: ... + if sys.version_info >= (3, 11): + async def start_tls( + self, sslcontext: ssl.SSLContext, *, server_hostname: str | None = ..., ssl_handshake_timeout: float | None = ... + ) -> None: ... class StreamReader(AsyncIterator[bytes]): def __init__(self, limit: int = ..., loop: events.AbstractEventLoop | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/asyncio/taskgroups.pyi b/mypy/typeshed/stdlib/asyncio/taskgroups.pyi index 58e3d41e53f11..9b2f15506c50d 100644 --- a/mypy/typeshed/stdlib/asyncio/taskgroups.pyi +++ b/mypy/typeshed/stdlib/asyncio/taskgroups.pyi @@ -2,6 +2,7 @@ from _typeshed import Self from collections.abc import Coroutine, Generator +from contextvars import Context from types import TracebackType from typing import Any, TypeVar @@ -15,4 +16,6 @@ class TaskGroup: def __init__(self) -> None: ... async def __aenter__(self: Self) -> Self: ... async def __aexit__(self, et: type[BaseException] | None, exc: BaseException | None, tb: TracebackType | None) -> None: ... - def create_task(self, coro: Generator[Any, None, _T] | Coroutine[Any, Any, _T], *, name: str | None = ...) -> Task[_T]: ... + def create_task( + self, coro: Generator[Any, None, _T] | Coroutine[Any, Any, _T], *, name: str | None = ..., context: Context | None = ... + ) -> Task[_T]: ... diff --git a/mypy/typeshed/stdlib/asyncio/tasks.pyi b/mypy/typeshed/stdlib/asyncio/tasks.pyi index 4a8e565afb2fc..d7119b0400baf 100644 --- a/mypy/typeshed/stdlib/asyncio/tasks.pyi +++ b/mypy/typeshed/stdlib/asyncio/tasks.pyi @@ -10,6 +10,8 @@ from .futures import Future if sys.version_info >= (3, 9): from types import GenericAlias +if sys.version_info >= (3, 11): + from contextvars import Context if sys.version_info >= (3, 7): __all__ = ( @@ -268,7 +270,10 @@ def run_coroutine_threadsafe(coro: _FutureT[_T], loop: AbstractEventLoop) -> con if sys.version_info >= (3, 10): def shield(arg: _FutureT[_T]) -> Future[_T]: ... - async def sleep(delay: float, result: _T = ...) -> _T: ... + @overload + async def sleep(delay: float) -> None: ... + @overload + async def sleep(delay: float, result: _T) -> _T: ... @overload async def wait(fs: Iterable[_FT], *, timeout: float | None = ..., return_when: str = ...) -> tuple[set[_FT], set[_FT]]: ... # type: ignore[misc] @overload @@ -279,7 +284,10 @@ if sys.version_info >= (3, 10): else: def shield(arg: _FutureT[_T], *, loop: AbstractEventLoop | None = ...) -> Future[_T]: ... - async def sleep(delay: float, result: _T = ..., *, loop: AbstractEventLoop | None = ...) -> _T: ... + @overload + async def sleep(delay: float, *, loop: AbstractEventLoop | None = ...) -> None: ... + @overload + async def sleep(delay: float, result: _T, *, loop: AbstractEventLoop | None = ...) -> _T: ... @overload async def wait( # type: ignore[misc] fs: Iterable[_FT], *, loop: AbstractEventLoop | None = ..., timeout: float | None = ..., return_when: str = ... @@ -329,7 +337,11 @@ class Task(Future[_T], Generic[_T]): if sys.version_info >= (3, 7): def all_tasks(loop: AbstractEventLoop | None = ...) -> set[Task[Any]]: ... - if sys.version_info >= (3, 8): + if sys.version_info >= (3, 11): + def create_task( + coro: Generator[Any, None, _T] | Coroutine[Any, Any, _T], *, name: str | None = ..., context: Context | None = ... + ) -> Task[_T]: ... + elif sys.version_info >= (3, 8): def create_task(coro: Generator[Any, None, _T] | Coroutine[Any, Any, _T], *, name: str | None = ...) -> Task[_T]: ... else: def create_task(coro: Generator[Any, None, _T] | Coroutine[Any, Any, _T]) -> Task[_T]: ... diff --git a/mypy/typeshed/stdlib/asyncio/timeouts.pyi b/mypy/typeshed/stdlib/asyncio/timeouts.pyi new file mode 100644 index 0000000000000..be516b5851d1e --- /dev/null +++ b/mypy/typeshed/stdlib/asyncio/timeouts.pyi @@ -0,0 +1,19 @@ +from _typeshed import Self +from types import TracebackType +from typing_extensions import final + +__all__ = ("Timeout", "timeout", "timeout_at") + +@final +class Timeout: + def __init__(self, when: float | None) -> None: ... + def when(self) -> float | None: ... + def reschedule(self, when: float | None) -> None: ... + def expired(self) -> bool: ... + async def __aenter__(self: Self) -> Self: ... + async def __aexit__( + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> None: ... + +def timeout(delay: float | None) -> Timeout: ... +def timeout_at(when: float | None) -> Timeout: ... diff --git a/mypy/typeshed/stdlib/asyncio/trsock.pyi b/mypy/typeshed/stdlib/asyncio/trsock.pyi index 20df2a78a5abb..b8972e43d2554 100644 --- a/mypy/typeshed/stdlib/asyncio/trsock.pyi +++ b/mypy/typeshed/stdlib/asyncio/trsock.pyi @@ -14,7 +14,6 @@ _CMSG: TypeAlias = tuple[int, int, bytes] class TransportSocket: def __init__(self, sock: socket.socket) -> None: ... - def _na(self, what: str) -> None: ... @property def family(self) -> int: ... @property @@ -41,6 +40,7 @@ class TransportSocket: def gettimeout(self) -> float | None: ... def setblocking(self, flag: bool) -> None: ... if sys.version_info < (3, 11): + def _na(self, what: str) -> None: ... def accept(self) -> tuple[socket.socket, _RetAddress]: ... def connect(self, address: _Address | bytes) -> None: ... def connect_ex(self, address: _Address | bytes) -> int: ... diff --git a/mypy/typeshed/stdlib/base64.pyi b/mypy/typeshed/stdlib/base64.pyi index ceed7d018d82d..c2ec85cac40a5 100644 --- a/mypy/typeshed/stdlib/base64.pyi +++ b/mypy/typeshed/stdlib/base64.pyi @@ -2,50 +2,29 @@ import sys from _typeshed import ReadableBuffer from typing import IO +__all__ = [ + "encode", + "decode", + "encodebytes", + "decodebytes", + "b64encode", + "b64decode", + "b32encode", + "b32decode", + "b16encode", + "b16decode", + "b85encode", + "b85decode", + "a85encode", + "a85decode", + "standard_b64encode", + "standard_b64decode", + "urlsafe_b64encode", + "urlsafe_b64decode", +] + if sys.version_info >= (3, 10): - __all__ = [ - "encode", - "decode", - "encodebytes", - "decodebytes", - "b64encode", - "b64decode", - "b32encode", - "b32decode", - "b32hexencode", - "b32hexdecode", - "b16encode", - "b16decode", - "b85encode", - "b85decode", - "a85encode", - "a85decode", - "standard_b64encode", - "standard_b64decode", - "urlsafe_b64encode", - "urlsafe_b64decode", - ] -else: - __all__ = [ - "encode", - "decode", - "encodebytes", - "decodebytes", - "b64encode", - "b64decode", - "b32encode", - "b32decode", - "b16encode", - "b16decode", - "b85encode", - "b85decode", - "a85encode", - "a85decode", - "standard_b64encode", - "standard_b64decode", - "urlsafe_b64encode", - "urlsafe_b64decode", - ] + __all__ += ["b32hexencode", "b32hexdecode"] def b64encode(s: ReadableBuffer, altchars: ReadableBuffer | None = ...) -> bytes: ... def b64decode(s: str | ReadableBuffer, altchars: ReadableBuffer | None = ..., validate: bool = ...) -> bytes: ... diff --git a/mypy/typeshed/stdlib/bdb.pyi b/mypy/typeshed/stdlib/bdb.pyi index bbd0f20af6c80..f4d1875efb698 100644 --- a/mypy/typeshed/stdlib/bdb.pyi +++ b/mypy/typeshed/stdlib/bdb.pyi @@ -1,3 +1,4 @@ +import sys from _typeshed import ExcInfo from collections.abc import Callable, Iterable, Mapping from types import CodeType, FrameType, TracebackType @@ -86,6 +87,10 @@ class Breakpoint: def __init__( self, file: str, line: int, temporary: bool = ..., cond: str | None = ..., funcname: str | None = ... ) -> None: ... + if sys.version_info >= (3, 11): + @staticmethod + def clearBreakpoints() -> None: ... + def deleteMe(self) -> None: ... def enable(self) -> None: ... def disable(self) -> None: ... diff --git a/mypy/typeshed/stdlib/binascii.pyi b/mypy/typeshed/stdlib/binascii.pyi index 53f72ad6a88f8..0656794d39d91 100644 --- a/mypy/typeshed/stdlib/binascii.pyi +++ b/mypy/typeshed/stdlib/binascii.pyi @@ -14,7 +14,12 @@ if sys.version_info >= (3, 7): else: def b2a_uu(__data: ReadableBuffer) -> bytes: ... -def a2b_base64(__data: _AsciiBuffer) -> bytes: ... +if sys.version_info >= (3, 11): + def a2b_base64(__data: _AsciiBuffer, *, strict_mode: bool = ...) -> bytes: ... + +else: + def a2b_base64(__data: _AsciiBuffer) -> bytes: ... + def b2a_base64(__data: ReadableBuffer, *, newline: bool = ...) -> bytes: ... def a2b_qp(data: _AsciiBuffer, header: bool = ...) -> bytes: ... def b2a_qp(data: ReadableBuffer, quotetabs: bool = ..., istext: bool = ..., header: bool = ...) -> bytes: ... diff --git a/mypy/typeshed/stdlib/builtins.pyi b/mypy/typeshed/stdlib/builtins.pyi index d3d34c72fcfcc..577d5fd99e36c 100644 --- a/mypy/typeshed/stdlib/builtins.pyi +++ b/mypy/typeshed/stdlib/builtins.pyi @@ -3,6 +3,7 @@ import types from _ast import AST from _collections_abc import dict_items, dict_keys, dict_values from _typeshed import ( + AnyStr_co, OpenBinaryMode, OpenBinaryModeReading, OpenBinaryModeUpdating, @@ -19,6 +20,7 @@ from _typeshed import ( SupportsKeysAndGetItem, SupportsLenAndGetItem, SupportsNext, + SupportsRAdd, SupportsRDivMod, SupportsRichComparison, SupportsRichComparisonT, @@ -52,7 +54,7 @@ from typing import ( # noqa: Y027 TypeVar, overload, ) -from typing_extensions import Literal, SupportsIndex, TypeAlias, TypeGuard, final +from typing_extensions import Literal, LiteralString, SupportsIndex, TypeAlias, TypeGuard, final if sys.version_info >= (3, 9): from types import GenericAlias @@ -398,21 +400,39 @@ class str(Sequence[str]): def __new__(cls: type[Self], object: object = ...) -> Self: ... @overload def __new__(cls: type[Self], object: ReadableBuffer, encoding: str = ..., errors: str = ...) -> Self: ... - def capitalize(self) -> str: ... - def casefold(self) -> str: ... - def center(self, __width: SupportsIndex, __fillchar: str = ...) -> str: ... + @overload + def capitalize(self: LiteralString) -> LiteralString: ... + @overload + def capitalize(self) -> str: ... # type: ignore[misc] + @overload + def casefold(self: LiteralString) -> LiteralString: ... + @overload + def casefold(self) -> str: ... # type: ignore[misc] + @overload + def center(self: LiteralString, __width: SupportsIndex, __fillchar: LiteralString = ...) -> LiteralString: ... + @overload + def center(self, __width: SupportsIndex, __fillchar: str = ...) -> str: ... # type: ignore[misc] def count(self, x: str, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...) -> int: ... def encode(self, encoding: str = ..., errors: str = ...) -> bytes: ... def endswith( self, __suffix: str | tuple[str, ...], __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> bool: ... if sys.version_info >= (3, 8): - def expandtabs(self, tabsize: SupportsIndex = ...) -> str: ... + @overload + def expandtabs(self: LiteralString, tabsize: SupportsIndex = ...) -> LiteralString: ... + @overload + def expandtabs(self, tabsize: SupportsIndex = ...) -> str: ... # type: ignore[misc] else: - def expandtabs(self, tabsize: int = ...) -> str: ... + @overload + def expandtabs(self: LiteralString, tabsize: int = ...) -> LiteralString: ... + @overload + def expandtabs(self, tabsize: int = ...) -> str: ... # type: ignore[misc] def find(self, __sub: str, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...) -> int: ... - def format(self, *args: object, **kwargs: object) -> str: ... + @overload + def format(self: LiteralString, *args: LiteralString, **kwargs: LiteralString) -> LiteralString: ... + @overload + def format(self, *args: object, **kwargs: object) -> str: ... # type: ignore[misc] def format_map(self, map: _FormatMapMapping) -> str: ... def index(self, __sub: str, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...) -> int: ... def isalnum(self) -> bool: ... @@ -429,40 +449,102 @@ class str(Sequence[str]): def isspace(self) -> bool: ... def istitle(self) -> bool: ... def isupper(self) -> bool: ... - def join(self, __iterable: Iterable[str]) -> str: ... - def ljust(self, __width: SupportsIndex, __fillchar: str = ...) -> str: ... - def lower(self) -> str: ... - def lstrip(self, __chars: str | None = ...) -> str: ... - def partition(self, __sep: str) -> tuple[str, str, str]: ... - def replace(self, __old: str, __new: str, __count: SupportsIndex = ...) -> str: ... + @overload + def join(self: LiteralString, __iterable: Iterable[LiteralString]) -> LiteralString: ... + @overload + def join(self, __iterable: Iterable[str]) -> str: ... # type: ignore[misc] + @overload + def ljust(self: LiteralString, __width: SupportsIndex, __fillchar: LiteralString = ...) -> LiteralString: ... + @overload + def ljust(self, __width: SupportsIndex, __fillchar: str = ...) -> str: ... # type: ignore[misc] + @overload + def lower(self: LiteralString) -> LiteralString: ... + @overload + def lower(self) -> str: ... # type: ignore[misc] + @overload + def lstrip(self: LiteralString, __chars: LiteralString | None = ...) -> LiteralString: ... + @overload + def lstrip(self, __chars: str | None = ...) -> str: ... # type: ignore[misc] + @overload + def partition(self: LiteralString, __sep: LiteralString) -> tuple[LiteralString, LiteralString, LiteralString]: ... + @overload + def partition(self, __sep: str) -> tuple[str, str, str]: ... # type: ignore[misc] + @overload + def replace( + self: LiteralString, __old: LiteralString, __new: LiteralString, __count: SupportsIndex = ... + ) -> LiteralString: ... + @overload + def replace(self, __old: str, __new: str, __count: SupportsIndex = ...) -> str: ... # type: ignore[misc] if sys.version_info >= (3, 9): - def removeprefix(self, __prefix: str) -> str: ... - def removesuffix(self, __suffix: str) -> str: ... + @overload + def removeprefix(self: LiteralString, __prefix: LiteralString) -> LiteralString: ... + @overload + def removeprefix(self, __prefix: str) -> str: ... # type: ignore[misc] + @overload + def removesuffix(self: LiteralString, __suffix: LiteralString) -> LiteralString: ... + @overload + def removesuffix(self, __suffix: str) -> str: ... # type: ignore[misc] def rfind(self, __sub: str, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...) -> int: ... def rindex(self, __sub: str, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...) -> int: ... - def rjust(self, __width: SupportsIndex, __fillchar: str = ...) -> str: ... - def rpartition(self, __sep: str) -> tuple[str, str, str]: ... - def rsplit(self, sep: str | None = ..., maxsplit: SupportsIndex = ...) -> list[str]: ... - def rstrip(self, __chars: str | None = ...) -> str: ... - def split(self, sep: str | None = ..., maxsplit: SupportsIndex = ...) -> list[str]: ... - def splitlines(self, keepends: bool = ...) -> list[str]: ... + @overload + def rjust(self: LiteralString, __width: SupportsIndex, __fillchar: LiteralString = ...) -> LiteralString: ... + @overload + def rjust(self, __width: SupportsIndex, __fillchar: str = ...) -> str: ... # type: ignore[misc] + @overload + def rpartition(self: LiteralString, __sep: LiteralString) -> tuple[LiteralString, LiteralString, LiteralString]: ... + @overload + def rpartition(self, __sep: str) -> tuple[str, str, str]: ... # type: ignore[misc] + @overload + def rsplit(self: LiteralString, sep: LiteralString | None = ..., maxsplit: SupportsIndex = ...) -> list[LiteralString]: ... + @overload + def rsplit(self, sep: str | None = ..., maxsplit: SupportsIndex = ...) -> list[str]: ... # type: ignore[misc] + @overload + def rstrip(self: LiteralString, __chars: LiteralString | None = ...) -> LiteralString: ... + @overload + def rstrip(self, __chars: str | None = ...) -> str: ... # type: ignore[misc] + @overload + def split(self: LiteralString, sep: LiteralString | None = ..., maxsplit: SupportsIndex = ...) -> list[LiteralString]: ... + @overload + def split(self, sep: str | None = ..., maxsplit: SupportsIndex = ...) -> list[str]: ... # type: ignore[misc] + @overload + def splitlines(self: LiteralString, keepends: bool = ...) -> list[LiteralString]: ... + @overload + def splitlines(self, keepends: bool = ...) -> list[str]: ... # type: ignore[misc] def startswith( self, __prefix: str | tuple[str, ...], __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> bool: ... - def strip(self, __chars: str | None = ...) -> str: ... - def swapcase(self) -> str: ... - def title(self) -> str: ... + @overload + def strip(self: LiteralString, __chars: LiteralString | None = ...) -> LiteralString: ... + @overload + def strip(self, __chars: str | None = ...) -> str: ... # type: ignore[misc] + @overload + def swapcase(self: LiteralString) -> LiteralString: ... + @overload + def swapcase(self) -> str: ... # type: ignore[misc] + @overload + def title(self: LiteralString) -> LiteralString: ... + @overload + def title(self) -> str: ... # type: ignore[misc] def translate(self, __table: Mapping[int, int | str | None] | Sequence[int | str | None]) -> str: ... - def upper(self) -> str: ... - def zfill(self, __width: SupportsIndex) -> str: ... + @overload + def upper(self: LiteralString) -> LiteralString: ... + @overload + def upper(self) -> str: ... # type: ignore[misc] + @overload + def zfill(self: LiteralString, __width: SupportsIndex) -> LiteralString: ... + @overload + def zfill(self, __width: SupportsIndex) -> str: ... # type: ignore[misc] @staticmethod @overload def maketrans(__x: dict[int, _T] | dict[str, _T] | dict[str | int, _T]) -> dict[int, _T]: ... @staticmethod @overload def maketrans(__x: str, __y: str, __z: str | None = ...) -> dict[int, int | None]: ... - def __add__(self, __s: str) -> str: ... + @overload + def __add__(self: LiteralString, __s: LiteralString) -> LiteralString: ... + @overload + def __add__(self, __s: str) -> str: ... # type: ignore[misc] # Incompatible with Sequence.__contains__ def __contains__(self, __o: str) -> bool: ... # type: ignore[override] def __eq__(self, __x: object) -> bool: ... @@ -470,14 +552,26 @@ class str(Sequence[str]): def __getitem__(self, __i: SupportsIndex | slice) -> str: ... def __gt__(self, __x: str) -> bool: ... def __hash__(self) -> int: ... - def __iter__(self) -> Iterator[str]: ... + @overload + def __iter__(self: LiteralString) -> Iterator[LiteralString]: ... + @overload + def __iter__(self) -> Iterator[str]: ... # type: ignore[misc] def __le__(self, __x: str) -> bool: ... def __len__(self) -> int: ... def __lt__(self, __x: str) -> bool: ... - def __mod__(self, __x: Any) -> str: ... - def __mul__(self, __n: SupportsIndex) -> str: ... + @overload + def __mod__(self: LiteralString, __x: LiteralString | tuple[LiteralString, ...]) -> LiteralString: ... + @overload + def __mod__(self, __x: Any) -> str: ... # type: ignore[misc] + @overload + def __mul__(self: LiteralString, __n: SupportsIndex) -> LiteralString: ... + @overload + def __mul__(self, __n: SupportsIndex) -> str: ... # type: ignore[misc] def __ne__(self, __x: object) -> bool: ... - def __rmul__(self, __n: SupportsIndex) -> str: ... + @overload + def __rmul__(self: LiteralString, __n: SupportsIndex) -> LiteralString: ... + @overload + def __rmul__(self, __n: SupportsIndex) -> str: ... # type: ignore[misc] def __getnewargs__(self) -> tuple[str]: ... class bytes(ByteString): @@ -871,11 +965,16 @@ class list(MutableSequence[_T], Generic[_T]): def extend(self, __iterable: Iterable[_T]) -> None: ... def pop(self, __index: SupportsIndex = ...) -> _T: ... # Signature of `list.index` should be kept in line with `collections.UserList.index()` + # and multiprocessing.managers.ListProxy.index() def index(self, __value: _T, __start: SupportsIndex = ..., __stop: SupportsIndex = ...) -> int: ... def count(self, __value: _T) -> int: ... def insert(self, __index: SupportsIndex, __object: _T) -> None: ... def remove(self, __value: _T) -> None: ... # Signature of `list.sort` should be kept inline with `collections.UserList.sort()` + # and multiprocessing.managers.ListProxy.sort() + # + # Use list[SupportsRichComparisonT] for the first overload rather than [SupportsRichComparison] + # to work around invariance @overload def sort(self: list[SupportsRichComparisonT], *, key: None = ..., reverse: bool = ...) -> None: ... @overload @@ -908,8 +1007,9 @@ class list(MutableSequence[_T], Generic[_T]): class dict(MutableMapping[_KT, _VT], Generic[_KT, _VT]): # __init__ should be kept roughly in line with `collections.UserDict.__init__`, which has similar semantics + # Also multiprocessing.managers.SyncManager.dict() @overload - def __init__(self: dict[_KT, _VT]) -> None: ... + def __init__(self) -> None: ... @overload def __init__(self: dict[str, _VT], **kwargs: _VT) -> None: ... @overload @@ -962,7 +1062,10 @@ class dict(MutableMapping[_KT, _VT], Generic[_KT, _VT]): def __ior__(self: Self, __value: Iterable[tuple[_KT, _VT]]) -> Self: ... class set(MutableSet[_T], Generic[_T]): - def __init__(self, __iterable: Iterable[_T] = ...) -> None: ... + @overload + def __init__(self) -> None: ... + @overload + def __init__(self, __iterable: Iterable[_T]) -> None: ... def add(self, __element: _T) -> None: ... def copy(self) -> set[_T]: ... def difference(self, *s: Iterable[Any]) -> set[_T]: ... @@ -998,7 +1101,10 @@ class set(MutableSet[_T], Generic[_T]): def __class_getitem__(cls, __item: Any) -> GenericAlias: ... class frozenset(AbstractSet[_T_co], Generic[_T_co]): - def __init__(self, __iterable: Iterable[_T_co] = ...) -> None: ... + @overload + def __new__(cls: type[Self]) -> Self: ... + @overload + def __new__(cls: type[Self], __iterable: Iterable[_T_co]) -> Self: ... def copy(self) -> frozenset[_T_co]: ... def difference(self, *s: Iterable[object]) -> frozenset[_T_co]: ... def intersection(self, *s: Iterable[object]) -> frozenset[_T_co]: ... @@ -1092,10 +1198,8 @@ def chr(__i: int) -> str: ... # We define this here instead of using os.PathLike to avoid import cycle issues. # See https://github.com/python/typeshed/pull/991#issuecomment-288160993 -_AnyStr_co = TypeVar("_AnyStr_co", str, bytes, covariant=True) - -class _PathLike(Protocol[_AnyStr_co]): - def __fspath__(self) -> _AnyStr_co: ... +class _PathLike(Protocol[AnyStr_co]): + def __fspath__(self) -> AnyStr_co: ... if sys.version_info >= (3, 10): def aiter(__async_iterable: SupportsAiter[_SupportsAnextT]) -> _SupportsAnextT: ... @@ -1534,19 +1638,35 @@ def sorted( @overload def sorted(__iterable: Iterable[_T], *, key: Callable[[_T], SupportsRichComparison], reverse: bool = ...) -> list[_T]: ... -_SumT = TypeVar("_SumT", bound=SupportsAdd) -_SumS = TypeVar("_SumS", bound=SupportsAdd) +_AddableT1 = TypeVar("_AddableT1", bound=SupportsAdd[Any, Any]) +_AddableT2 = TypeVar("_AddableT2", bound=SupportsAdd[Any, Any]) + +class _SupportsSumWithNoDefaultGiven(SupportsAdd[Any, Any], SupportsRAdd[int, Any], Protocol): ... + +_SupportsSumNoDefaultT = TypeVar("_SupportsSumNoDefaultT", bound=_SupportsSumWithNoDefaultGiven) + +# In general, the return type of `x + x` is *not* guaranteed to be the same type as x. +# However, we can't express that in the stub for `sum()` +# without creating many false-positive errors (see #7578). +# Instead, we special-case the most common example of this: bool. +if sys.version_info >= (3, 8): + @overload + def sum(__iterable: Iterable[bool], start: int = ...) -> int: ... # type: ignore[misc] + +else: + @overload + def sum(__iterable: Iterable[bool], __start: int = ...) -> int: ... # type: ignore[misc] @overload -def sum(__iterable: Iterable[_SumT]) -> _SumT | Literal[0]: ... +def sum(__iterable: Iterable[_SupportsSumNoDefaultT]) -> _SupportsSumNoDefaultT | Literal[0]: ... if sys.version_info >= (3, 8): @overload - def sum(__iterable: Iterable[_SumT], start: _SumS) -> _SumT | _SumS: ... + def sum(__iterable: Iterable[_AddableT1], start: _AddableT2) -> _AddableT1 | _AddableT2: ... else: @overload - def sum(__iterable: Iterable[_SumT], __start: _SumS) -> _SumT | _SumS: ... + def sum(__iterable: Iterable[_AddableT1], __start: _AddableT2) -> _AddableT1 | _AddableT2: ... # The argument to `vars()` has to have a `__dict__` attribute, so can't be annotated with `object` # (A "SupportsDunderDict" protocol doesn't work) @@ -1654,10 +1774,13 @@ class BaseException: __context__: BaseException | None __suppress_context__: bool __traceback__: TracebackType | None - if sys.version_info >= (3, 11): - __note__: str | None def __init__(self, *args: object) -> None: ... + def __setstate__(self, __state: dict[str, Any] | None) -> None: ... def with_traceback(self: Self, __tb: TracebackType | None) -> Self: ... + if sys.version_info >= (3, 11): + # only present after add_note() is called + __notes__: list[str] + def add_note(self, __note: str) -> None: ... class GeneratorExit(BaseException): ... class KeyboardInterrupt(BaseException): ... diff --git a/mypy/typeshed/stdlib/calendar.pyi b/mypy/typeshed/stdlib/calendar.pyi index c7e0a6b4606f2..00b7054ba60a8 100644 --- a/mypy/typeshed/stdlib/calendar.pyi +++ b/mypy/typeshed/stdlib/calendar.pyi @@ -4,67 +4,35 @@ from collections.abc import Iterable, Sequence from time import struct_time from typing_extensions import Literal, TypeAlias +__all__ = [ + "IllegalMonthError", + "IllegalWeekdayError", + "setfirstweekday", + "firstweekday", + "isleap", + "leapdays", + "weekday", + "monthrange", + "monthcalendar", + "prmonth", + "month", + "prcal", + "calendar", + "timegm", + "month_name", + "month_abbr", + "day_name", + "day_abbr", + "Calendar", + "TextCalendar", + "HTMLCalendar", + "LocaleTextCalendar", + "LocaleHTMLCalendar", + "weekheader", +] + if sys.version_info >= (3, 10): - __all__ = [ - "IllegalMonthError", - "IllegalWeekdayError", - "setfirstweekday", - "firstweekday", - "isleap", - "leapdays", - "weekday", - "monthrange", - "monthcalendar", - "prmonth", - "month", - "prcal", - "calendar", - "timegm", - "month_name", - "month_abbr", - "day_name", - "day_abbr", - "Calendar", - "TextCalendar", - "HTMLCalendar", - "LocaleTextCalendar", - "LocaleHTMLCalendar", - "weekheader", - "FRIDAY", - "MONDAY", - "SATURDAY", - "SUNDAY", - "THURSDAY", - "TUESDAY", - "WEDNESDAY", - ] -else: - __all__ = [ - "IllegalMonthError", - "IllegalWeekdayError", - "setfirstweekday", - "firstweekday", - "isleap", - "leapdays", - "weekday", - "monthrange", - "monthcalendar", - "prmonth", - "month", - "prcal", - "calendar", - "timegm", - "month_name", - "month_abbr", - "day_name", - "day_abbr", - "Calendar", - "TextCalendar", - "HTMLCalendar", - "LocaleTextCalendar", - "LocaleHTMLCalendar", - "weekheader", - ] + __all__ += ["FRIDAY", "MONDAY", "SATURDAY", "SUNDAY", "THURSDAY", "TUESDAY", "WEDNESDAY"] _LocaleType: TypeAlias = tuple[str | None, str | None] diff --git a/mypy/typeshed/stdlib/cgi.pyi b/mypy/typeshed/stdlib/cgi.pyi index 5e7bebc2a7f8a..59c0a27067f1d 100644 --- a/mypy/typeshed/stdlib/cgi.pyi +++ b/mypy/typeshed/stdlib/cgi.pyi @@ -5,39 +5,23 @@ from collections.abc import Iterable, Iterator, Mapping from types import TracebackType from typing import IO, Any, Protocol -if sys.version_info >= (3, 8): - __all__ = [ - "MiniFieldStorage", - "FieldStorage", - "parse", - "parse_multipart", - "parse_header", - "test", - "print_exception", - "print_environ", - "print_form", - "print_directory", - "print_arguments", - "print_environ_usage", - ] -else: - __all__ = [ - "MiniFieldStorage", - "FieldStorage", - "parse", - "parse_qs", - "parse_qsl", - "parse_multipart", - "parse_header", - "test", - "print_exception", - "print_environ", - "print_form", - "print_directory", - "print_arguments", - "print_environ_usage", - "escape", - ] +__all__ = [ + "MiniFieldStorage", + "FieldStorage", + "parse", + "parse_multipart", + "parse_header", + "test", + "print_exception", + "print_environ", + "print_form", + "print_directory", + "print_arguments", + "print_environ_usage", +] + +if sys.version_info < (3, 8): + __all__ += ["parse_qs", "parse_qsl", "escape"] def parse( fp: IO[Any] | None = ..., diff --git a/mypy/typeshed/stdlib/codecs.pyi b/mypy/typeshed/stdlib/codecs.pyi index bba7703c7d330..64d1c93ba3a32 100644 --- a/mypy/typeshed/stdlib/codecs.pyi +++ b/mypy/typeshed/stdlib/codecs.pyi @@ -1,10 +1,11 @@ -import sys import types from _typeshed import Self from abc import abstractmethod -from collections.abc import Callable, Generator, Iterable, Iterator -from typing import IO, Any, BinaryIO, Protocol, TextIO, overload -from typing_extensions import Literal, TypeAlias +from collections.abc import Callable, Generator, Iterable +from typing import Any, BinaryIO, Protocol, TextIO +from typing_extensions import Literal + +from _codecs import * __all__ = [ "register", @@ -58,6 +59,18 @@ BOM32_LE: Literal[b"\xff\xfe"] BOM64_BE: Literal[b"\x00\x00\xfe\xff"] BOM64_LE: Literal[b"\xff\xfe\x00\x00"] +class _WritableStream(Protocol): + def write(self, __data: bytes) -> object: ... + def seek(self, __offset: int, __whence: int) -> object: ... + def close(self) -> object: ... + +class _ReadableStream(Protocol): + def read(self, __size: int = ...) -> bytes: ... + def seek(self, __offset: int, __whence: int) -> object: ... + def close(self) -> object: ... + +class _Stream(_WritableStream, _ReadableStream, Protocol): ... + # TODO: this only satisfies the most common interface, where # bytes is the raw form and str is the cooked form. # In the long run, both should become template parameters maybe? @@ -71,10 +84,10 @@ class _Decoder(Protocol): def __call__(self, input: bytes, errors: str = ...) -> tuple[str, int]: ... # signature of Codec().decode class _StreamReader(Protocol): - def __call__(self, stream: IO[bytes], errors: str = ...) -> StreamReader: ... + def __call__(self, stream: _ReadableStream, errors: str = ...) -> StreamReader: ... class _StreamWriter(Protocol): - def __call__(self, stream: IO[bytes], errors: str = ...) -> StreamWriter: ... + def __call__(self, stream: _WritableStream, errors: str = ...) -> StreamWriter: ... class _IncrementalEncoder(Protocol): def __call__(self, errors: str = ...) -> IncrementalEncoder: ... @@ -82,49 +95,6 @@ class _IncrementalEncoder(Protocol): class _IncrementalDecoder(Protocol): def __call__(self, errors: str = ...) -> IncrementalDecoder: ... -# The type ignore on `encode` and `decode` is to avoid issues with overlapping overloads, for more details, see #300 -# https://docs.python.org/3/library/codecs.html#binary-transforms -_BytesToBytesEncoding: TypeAlias = Literal[ - "base64", - "base_64", - "base64_codec", - "bz2", - "bz2_codec", - "hex", - "hex_codec", - "quopri", - "quotedprintable", - "quoted_printable", - "quopri_codec", - "uu", - "uu_codec", - "zip", - "zlib", - "zlib_codec", -] -# https://docs.python.org/3/library/codecs.html#text-transforms -_StrToStrEncoding: TypeAlias = Literal["rot13", "rot_13"] - -@overload -def encode(obj: bytes, encoding: _BytesToBytesEncoding, errors: str = ...) -> bytes: ... -@overload -def encode(obj: str, encoding: _StrToStrEncoding, errors: str = ...) -> str: ... # type: ignore[misc] -@overload -def encode(obj: str, encoding: str = ..., errors: str = ...) -> bytes: ... -@overload -def decode(obj: bytes, encoding: _BytesToBytesEncoding, errors: str = ...) -> bytes: ... # type: ignore[misc] -@overload -def decode(obj: str, encoding: _StrToStrEncoding, errors: str = ...) -> str: ... - -# hex is officially documented as a bytes to bytes encoding, but it appears to also work with str -@overload -def decode(obj: str, encoding: Literal["hex", "hex_codec"], errors: str = ...) -> bytes: ... -@overload -def decode(obj: bytes, encoding: str = ..., errors: str = ...) -> str: ... -def lookup(__encoding: str) -> CodecInfo: ... -def utf_16_be_decode(__data: bytes, __errors: str | None = ..., __final: bool = ...) -> tuple[str, int]: ... # undocumented -def utf_16_be_encode(__str: str, __errors: str | None = ...) -> tuple[bytes, int]: ... # undocumented - class CodecInfo(tuple[_Encoder, _Decoder, _StreamReader, _StreamWriter]): @property def encode(self) -> _Encoder: ... @@ -158,17 +128,13 @@ def getincrementalencoder(encoding: str) -> _IncrementalEncoder: ... def getincrementaldecoder(encoding: str) -> _IncrementalDecoder: ... def getreader(encoding: str) -> _StreamReader: ... def getwriter(encoding: str) -> _StreamWriter: ... -def register(__search_function: Callable[[str], CodecInfo | None]) -> None: ... def open( filename: str, mode: str = ..., encoding: str | None = ..., errors: str = ..., buffering: int = ... ) -> StreamReaderWriter: ... -def EncodedFile(file: IO[bytes], data_encoding: str, file_encoding: str | None = ..., errors: str = ...) -> StreamRecoder: ... +def EncodedFile(file: _Stream, data_encoding: str, file_encoding: str | None = ..., errors: str = ...) -> StreamRecoder: ... def iterencode(iterator: Iterable[str], encoding: str, errors: str = ...) -> Generator[bytes, None, None]: ... def iterdecode(iterator: Iterable[bytes], encoding: str, errors: str = ...) -> Generator[str, None, None]: ... -if sys.version_info >= (3, 10): - def unregister(__search_function: Callable[[str], CodecInfo | None]) -> None: ... - BOM: Literal[b"\xff\xfe", b"\xfe\xff"] # depends on `sys.byteorder` BOM_BE: Literal[b"\xfe\xff"] BOM_LE: Literal[b"\xff\xfe"] @@ -180,11 +146,6 @@ BOM_UTF32: Literal[b"\xff\xfe\x00\x00", b"\x00\x00\xfe\xff"] # depends on `sys. BOM_UTF32_BE: Literal[b"\x00\x00\xfe\xff"] BOM_UTF32_LE: Literal[b"\xff\xfe\x00\x00"] -# It is expected that different actions be taken depending on which of the -# three subclasses of `UnicodeError` is actually ...ed. However, the Union -# is still needed for at least one of the cases. -def register_error(__errors: str, __handler: Callable[[UnicodeError], tuple[str | bytes, int]]) -> None: ... -def lookup_error(__name: str) -> Callable[[UnicodeError], tuple[str | bytes, int]]: ... def strict_errors(exception: UnicodeError) -> tuple[str | bytes, int]: ... def replace_errors(exception: UnicodeError) -> tuple[str | bytes, int]: ... def ignore_errors(exception: UnicodeError) -> tuple[str | bytes, int]: ... @@ -235,8 +196,9 @@ class BufferedIncrementalDecoder(IncrementalDecoder): # TODO: it is not possible to specify the requirement that all other # attributes and methods are passed-through from the stream. class StreamWriter(Codec): + stream: _WritableStream errors: str - def __init__(self, stream: IO[bytes], errors: str = ...) -> None: ... + def __init__(self, stream: _WritableStream, errors: str = ...) -> None: ... def write(self, object: str) -> None: ... def writelines(self, list: Iterable[str]) -> None: ... def reset(self) -> None: ... @@ -244,9 +206,10 @@ class StreamWriter(Codec): def __exit__(self, type: type[BaseException] | None, value: BaseException | None, tb: types.TracebackType | None) -> None: ... def __getattr__(self, name: str, getattr: Callable[[str], Any] = ...) -> Any: ... -class StreamReader(Codec, Iterator[str]): +class StreamReader(Codec): + stream: _ReadableStream errors: str - def __init__(self, stream: IO[bytes], errors: str = ...) -> None: ... + def __init__(self, stream: _ReadableStream, errors: str = ...) -> None: ... def read(self, size: int = ..., chars: int = ..., firstline: bool = ...) -> str: ... def readline(self, size: int | None = ..., keepends: bool = ...) -> str: ... def readlines(self, sizehint: int | None = ..., keepends: bool = ...) -> list[str]: ... @@ -260,7 +223,8 @@ class StreamReader(Codec, Iterator[str]): # Doesn't actually inherit from TextIO, but wraps a BinaryIO to provide text reading and writing # and delegates attributes to the underlying binary stream with __getattr__. class StreamReaderWriter(TextIO): - def __init__(self, stream: IO[bytes], Reader: _StreamReader, Writer: _StreamWriter, errors: str = ...) -> None: ... + stream: _Stream + def __init__(self, stream: _Stream, Reader: _StreamReader, Writer: _StreamWriter, errors: str = ...) -> None: ... def read(self, size: int = ...) -> str: ... def readline(self, size: int | None = ...) -> str: ... def readlines(self, sizehint: int | None = ...) -> list[str]: ... @@ -287,13 +251,7 @@ class StreamReaderWriter(TextIO): class StreamRecoder(BinaryIO): def __init__( - self, - stream: IO[bytes], - encode: _Encoder, - decode: _Decoder, - Reader: _StreamReader, - Writer: _StreamWriter, - errors: str = ..., + self, stream: _Stream, encode: _Encoder, decode: _Decoder, Reader: _StreamReader, Writer: _StreamWriter, errors: str = ... ) -> None: ... def read(self, size: int = ...) -> bytes: ... def readline(self, size: int | None = ...) -> bytes: ... diff --git a/mypy/typeshed/stdlib/collections/__init__.pyi b/mypy/typeshed/stdlib/collections/__init__.pyi index 2e88c0d8f4743..5fff9f48c4899 100644 --- a/mypy/typeshed/stdlib/collections/__init__.pyi +++ b/mypy/typeshed/stdlib/collections/__init__.pyi @@ -14,6 +14,35 @@ else: __all__ = ["ChainMap", "Counter", "OrderedDict", "UserDict", "UserList", "UserString", "defaultdict", "deque", "namedtuple"] +if sys.version_info < (3, 7): + __all__ += [ + "Awaitable", + "Coroutine", + "AsyncIterable", + "AsyncIterator", + "AsyncGenerator", + "Hashable", + "Iterable", + "Iterator", + "Generator", + "Reversible", + "Sized", + "Container", + "Callable", + "Collection", + "Set", + "MutableSet", + "Mapping", + "MutableMapping", + "MappingView", + "KeysView", + "ItemsView", + "ValuesView", + "Sequence", + "MutableSequence", + "ByteString", + ] + _S = TypeVar("_S") _T = TypeVar("_T") _T1 = TypeVar("_T1") @@ -43,7 +72,7 @@ class UserDict(MutableMapping[_KT, _VT], Generic[_KT, _VT]): data: dict[_KT, _VT] # __init__ should be kept roughly in line with `dict.__init__`, which has the same semantics @overload - def __init__(self: UserDict[_KT, _VT], __dict: None = ...) -> None: ... + def __init__(self, __dict: None = ...) -> None: ... @overload def __init__(self: UserDict[str, _VT], __dict: None = ..., **kwargs: _VT) -> None: ... @overload @@ -82,7 +111,10 @@ class UserDict(MutableMapping[_KT, _VT], Generic[_KT, _VT]): class UserList(MutableSequence[_T]): data: list[_T] - def __init__(self, initlist: Iterable[_T] | None = ...) -> None: ... + @overload + def __init__(self, initlist: None = ...) -> None: ... + @overload + def __init__(self, initlist: Iterable[_T]) -> None: ... def __lt__(self, other: list[_T] | UserList[_T]) -> bool: ... def __le__(self, other: list[_T] | UserList[_T]) -> bool: ... def __gt__(self, other: list[_T] | UserList[_T]) -> bool: ... @@ -214,7 +246,10 @@ class UserString(Sequence[UserString]): class deque(MutableSequence[_T], Generic[_T]): @property def maxlen(self) -> int | None: ... - def __init__(self, iterable: Iterable[_T] = ..., maxlen: int | None = ...) -> None: ... + @overload + def __init__(self, *, maxlen: int | None = ...) -> None: ... + @overload + def __init__(self, iterable: Iterable[_T], maxlen: int | None = ...) -> None: ... def append(self, __x: _T) -> None: ... def appendleft(self, __x: _T) -> None: ... def copy(self: Self) -> Self: ... @@ -248,7 +283,7 @@ class deque(MutableSequence[_T], Generic[_T]): class Counter(dict[_T, int], Generic[_T]): @overload - def __init__(self: Counter[_T], __iterable: None = ...) -> None: ... + def __init__(self, __iterable: None = ...) -> None: ... @overload def __init__(self: Counter[str], __iterable: None = ..., **kwargs: int) -> None: ... @overload @@ -340,7 +375,7 @@ class OrderedDict(dict[_KT, _VT], Reversible[_KT], Generic[_KT, _VT]): class defaultdict(dict[_KT, _VT], Generic[_KT, _VT]): default_factory: Callable[[], _VT] | None @overload - def __init__(self: defaultdict[_KT, _VT]) -> None: ... + def __init__(self) -> None: ... @overload def __init__(self: defaultdict[str, _VT], **kwargs: _VT) -> None: ... @overload diff --git a/mypy/typeshed/stdlib/concurrent/futures/process.pyi b/mypy/typeshed/stdlib/concurrent/futures/process.pyi index 4cfa8276897f0..1dd2ee0a6105d 100644 --- a/mypy/typeshed/stdlib/concurrent/futures/process.pyi +++ b/mypy/typeshed/stdlib/concurrent/futures/process.pyi @@ -53,7 +53,13 @@ class _ResultItem: work_id: int exception: Exception result: Any - def __init__(self, work_id: int, exception: Exception | None = ..., result: Any | None = ...) -> None: ... + if sys.version_info >= (3, 11): + exit_pid: int | None + def __init__( + self, work_id: int, exception: Exception | None = ..., result: Any | None = ..., exit_pid: int | None = ... + ) -> None: ... + else: + def __init__(self, work_id: int, exception: Exception | None = ..., result: Any | None = ...) -> None: ... class _CallItem: work_id: int @@ -86,11 +92,31 @@ if sys.version_info >= (3, 7): def _get_chunks(*iterables: Any, chunksize: int) -> Generator[tuple[Any, ...], None, None]: ... def _process_chunk(fn: Callable[..., Any], chunk: tuple[Any, None, None]) -> Generator[Any, None, None]: ... -def _sendback_result( - result_queue: SimpleQueue[_WorkItem[Any]], work_id: int, result: Any | None = ..., exception: Exception | None = ... -) -> None: ... -if sys.version_info >= (3, 7): +if sys.version_info >= (3, 11): + def _sendback_result( + result_queue: SimpleQueue[_WorkItem[Any]], + work_id: int, + result: Any | None = ..., + exception: Exception | None = ..., + exit_pid: int | None = ..., + ) -> None: ... + +else: + def _sendback_result( + result_queue: SimpleQueue[_WorkItem[Any]], work_id: int, result: Any | None = ..., exception: Exception | None = ... + ) -> None: ... + +if sys.version_info >= (3, 11): + def _process_worker( + call_queue: Queue[_CallItem], + result_queue: SimpleQueue[_ResultItem], + initializer: Callable[..., None] | None, + initargs: tuple[Any, ...], + max_tasks: int | None = ..., + ) -> None: ... + +elif sys.version_info >= (3, 7): def _process_worker( call_queue: Queue[_CallItem], result_queue: SimpleQueue[_ResultItem], @@ -153,7 +179,17 @@ class ProcessPoolExecutor(Executor): _executor_manager_thread_wakeup: _ThreadWakeup _result_queue: SimpleQueue[Any] _work_ids: Queue[Any] - if sys.version_info >= (3, 7): + if sys.version_info >= (3, 11): + def __init__( + self, + max_workers: int | None = ..., + mp_context: BaseContext | None = ..., + initializer: Callable[..., None] | None = ..., + initargs: tuple[Any, ...] = ..., + *, + max_tasks_per_child: int | None = ..., + ) -> None: ... + elif sys.version_info >= (3, 7): def __init__( self, max_workers: int | None = ..., diff --git a/mypy/typeshed/stdlib/contextlib.pyi b/mypy/typeshed/stdlib/contextlib.pyi index 1b6ee4298174c..81213b9540932 100644 --- a/mypy/typeshed/stdlib/contextlib.pyi +++ b/mypy/typeshed/stdlib/contextlib.pyi @@ -5,65 +5,25 @@ from types import TracebackType from typing import IO, Any, ContextManager, Generic, Protocol, TypeVar, overload # noqa: Y027 from typing_extensions import ParamSpec, TypeAlias +__all__ = [ + "contextmanager", + "closing", + "AbstractContextManager", + "ContextDecorator", + "ExitStack", + "redirect_stdout", + "redirect_stderr", + "suppress", +] + +if sys.version_info >= (3, 7): + __all__ += ["AbstractAsyncContextManager", "AsyncExitStack", "asynccontextmanager", "nullcontext"] + +if sys.version_info >= (3, 10): + __all__ += ["aclosing"] + if sys.version_info >= (3, 11): - __all__ = [ - "asynccontextmanager", - "contextmanager", - "closing", - "nullcontext", - "AbstractContextManager", - "AbstractAsyncContextManager", - "AsyncExitStack", - "ContextDecorator", - "ExitStack", - "redirect_stdout", - "redirect_stderr", - "suppress", - "aclosing", - "chdir", - ] -elif sys.version_info >= (3, 10): - __all__ = [ - "asynccontextmanager", - "contextmanager", - "closing", - "nullcontext", - "AbstractContextManager", - "AbstractAsyncContextManager", - "AsyncExitStack", - "ContextDecorator", - "ExitStack", - "redirect_stdout", - "redirect_stderr", - "suppress", - "aclosing", - ] -elif sys.version_info >= (3, 7): - __all__ = [ - "asynccontextmanager", - "contextmanager", - "closing", - "nullcontext", - "AbstractContextManager", - "AbstractAsyncContextManager", - "AsyncExitStack", - "ContextDecorator", - "ExitStack", - "redirect_stdout", - "redirect_stderr", - "suppress", - ] -else: - __all__ = [ - "contextmanager", - "closing", - "AbstractContextManager", - "ContextDecorator", - "ExitStack", - "redirect_stdout", - "redirect_stderr", - "suppress", - ] + __all__ += ["chdir"] AbstractContextManager = ContextManager if sys.version_info >= (3, 7): @@ -163,7 +123,7 @@ class _RedirectStream(AbstractContextManager[_T_io]): class redirect_stdout(_RedirectStream[_T_io]): ... class redirect_stderr(_RedirectStream[_T_io]): ... -class ExitStack(AbstractContextManager[ExitStack]): +class ExitStack: def __init__(self) -> None: ... def enter_context(self, cm: AbstractContextManager[_T]) -> _T: ... def push(self, exit: _CM_EF) -> _CM_EF: ... @@ -179,7 +139,7 @@ if sys.version_info >= (3, 7): _ExitCoroFunc: TypeAlias = Callable[[type[BaseException] | None, BaseException | None, TracebackType | None], Awaitable[bool]] _ACM_EF = TypeVar("_ACM_EF", bound=AbstractAsyncContextManager[Any] | _ExitCoroFunc) - class AsyncExitStack(AbstractAsyncContextManager[AsyncExitStack]): + class AsyncExitStack: def __init__(self) -> None: ... def enter_context(self, cm: AbstractContextManager[_T]) -> _T: ... async def enter_async_context(self, cm: AbstractAsyncContextManager[_T]) -> _T: ... diff --git a/mypy/typeshed/stdlib/contextvars.pyi b/mypy/typeshed/stdlib/contextvars.pyi index 341cd8491caf0..266d96bce6ffd 100644 --- a/mypy/typeshed/stdlib/contextvars.pyi +++ b/mypy/typeshed/stdlib/contextvars.pyi @@ -14,7 +14,10 @@ _P = ParamSpec("_P") @final class ContextVar(Generic[_T]): - def __init__(self, name: str, *, default: _T = ...) -> None: ... + @overload + def __init__(self, name: str) -> None: ... + @overload + def __init__(self, name: str, *, default: _T) -> None: ... @property def name(self) -> str: ... @overload diff --git a/mypy/typeshed/stdlib/csv.pyi b/mypy/typeshed/stdlib/csv.pyi index de69c71ad9412..e9552c759c16e 100644 --- a/mypy/typeshed/stdlib/csv.pyi +++ b/mypy/typeshed/stdlib/csv.pyi @@ -31,6 +31,9 @@ if sys.version_info >= (3, 8): else: from collections import OrderedDict as _DictReadMapping +if sys.version_info >= (3, 12): + from types import GenericAlias + __all__ = [ "QUOTE_MINIMAL", "QUOTE_ALL", @@ -76,7 +79,7 @@ class unix_dialect(Dialect): lineterminator: str quoting: _QuotingType -class DictReader(Generic[_T], Iterator[_DictReadMapping[_T, str]]): +class DictReader(Generic[_T], Iterator[_DictReadMapping[_T | Any, str | Any]]): fieldnames: Sequence[_T] | None restkey: str | None restval: str | None @@ -120,7 +123,9 @@ class DictReader(Generic[_T], Iterator[_DictReadMapping[_T, str]]): strict: bool = ..., ) -> None: ... def __iter__(self: Self) -> Self: ... - def __next__(self) -> _DictReadMapping[_T, str]: ... + def __next__(self) -> _DictReadMapping[_T | Any, str | Any]: ... + if sys.version_info >= (3, 12): + def __class_getitem__(cls, item: Any) -> GenericAlias: ... class DictWriter(Generic[_T]): fieldnames: Collection[_T] @@ -151,6 +156,8 @@ class DictWriter(Generic[_T]): def writerow(self, rowdict: Mapping[_T, Any]) -> Any: ... def writerows(self, rowdicts: Iterable[Mapping[_T, Any]]) -> None: ... + if sys.version_info >= (3, 12): + def __class_getitem__(cls, item: Any) -> GenericAlias: ... class Sniffer: preferred: list[str] diff --git a/mypy/typeshed/stdlib/ctypes/__init__.pyi b/mypy/typeshed/stdlib/ctypes/__init__.pyi index 53a382ec0e718..ee26cbddefe44 100644 --- a/mypy/typeshed/stdlib/ctypes/__init__.pyi +++ b/mypy/typeshed/stdlib/ctypes/__init__.pyi @@ -164,7 +164,7 @@ def POINTER(type: type[_CT]) -> type[pointer[_CT]]: ... class pointer(Generic[_CT], _PointerLike, _CData): _type_: type[_CT] contents: _CT - def __init__(self, arg: _CT = ...) -> None: ... + def __init__(self, arg: _CT) -> None: ... @overload def __getitem__(self, __i: int) -> _CT: ... @overload diff --git a/mypy/typeshed/stdlib/dataclasses.pyi b/mypy/typeshed/stdlib/dataclasses.pyi index 1cbf998dd3034..04ae771fc0643 100644 --- a/mypy/typeshed/stdlib/dataclasses.pyi +++ b/mypy/typeshed/stdlib/dataclasses.pyi @@ -12,37 +12,23 @@ if sys.version_info >= (3, 9): _T = TypeVar("_T") _T_co = TypeVar("_T_co", covariant=True) +__all__ = [ + "dataclass", + "field", + "Field", + "FrozenInstanceError", + "InitVar", + "MISSING", + "fields", + "asdict", + "astuple", + "make_dataclass", + "replace", + "is_dataclass", +] + if sys.version_info >= (3, 10): - __all__ = [ - "dataclass", - "field", - "Field", - "FrozenInstanceError", - "InitVar", - "KW_ONLY", - "MISSING", - "fields", - "asdict", - "astuple", - "make_dataclass", - "replace", - "is_dataclass", - ] -else: - __all__ = [ - "dataclass", - "field", - "Field", - "FrozenInstanceError", - "InitVar", - "MISSING", - "fields", - "asdict", - "astuple", - "make_dataclass", - "replace", - "is_dataclass", - ] + __all__ += ["KW_ONLY"] # define _MISSING_TYPE as an enum within the type stubs, # even though that is not really its type at runtime @@ -240,7 +226,26 @@ class InitVar(Generic[_T]): @overload def __class_getitem__(cls, type: Any) -> InitVar[Any]: ... -if sys.version_info >= (3, 10): +if sys.version_info >= (3, 11): + def make_dataclass( + cls_name: str, + fields: Iterable[str | tuple[str, type] | tuple[str, type, Any]], + *, + bases: tuple[type, ...] = ..., + namespace: dict[str, Any] | None = ..., + init: bool = ..., + repr: bool = ..., + eq: bool = ..., + order: bool = ..., + unsafe_hash: bool = ..., + frozen: bool = ..., + match_args: bool = ..., + kw_only: bool = ..., + slots: bool = ..., + weakref_slot: bool = ..., + ) -> type: ... + +elif sys.version_info >= (3, 10): def make_dataclass( cls_name: str, fields: Iterable[str | tuple[str, type] | tuple[str, type, Any]], diff --git a/mypy/typeshed/stdlib/difflib.pyi b/mypy/typeshed/stdlib/difflib.pyi index 87e3768034bf3..854a53d433aef 100644 --- a/mypy/typeshed/stdlib/difflib.pyi +++ b/mypy/typeshed/stdlib/difflib.pyi @@ -28,8 +28,17 @@ class Match(NamedTuple): size: int class SequenceMatcher(Generic[_T]): + @overload + def __init__(self, isjunk: Callable[[_T], bool] | None, a: Sequence[_T], b: Sequence[_T], autojunk: bool = ...) -> None: ... + @overload + def __init__(self, *, a: Sequence[_T], b: Sequence[_T], autojunk: bool = ...) -> None: ... + @overload def __init__( - self, isjunk: Callable[[_T], bool] | None = ..., a: Sequence[_T] = ..., b: Sequence[_T] = ..., autojunk: bool = ... + self: SequenceMatcher[str], + isjunk: Callable[[str], bool] | None = ..., + a: Sequence[str] = ..., + b: Sequence[str] = ..., + autojunk: bool = ..., ) -> None: ... def set_seqs(self, a: Sequence[_T], b: Sequence[_T]) -> None: ... def set_seq1(self, a: Sequence[_T]) -> None: ... diff --git a/mypy/typeshed/stdlib/dis.pyi b/mypy/typeshed/stdlib/dis.pyi index 9a99d44986688..0b78e17b360b7 100644 --- a/mypy/typeshed/stdlib/dis.pyi +++ b/mypy/typeshed/stdlib/dis.pyi @@ -80,9 +80,12 @@ class Bytecode: first_line: int | None = ..., current_offset: int | None = ..., show_caches: bool = ..., + adaptive: bool = ..., ) -> None: ... @classmethod - def from_traceback(cls: type[Self], tb: types.TracebackType, *, show_caches: bool = ...) -> Self: ... + def from_traceback( + cls: type[Self], tb: types.TracebackType, *, show_caches: bool = ..., adaptive: bool = ... + ) -> Self: ... else: def __init__( self, x: _HaveCodeOrStringType, *, first_line: int | None = ..., current_offset: int | None = ... @@ -103,7 +106,12 @@ def code_info(x: _HaveCodeOrStringType) -> str: ... if sys.version_info >= (3, 11): def dis( - x: _HaveCodeOrStringType | None = ..., *, file: IO[str] | None = ..., depth: int | None = ..., show_caches: bool = ... + x: _HaveCodeOrStringType | None = ..., + *, + file: IO[str] | None = ..., + depth: int | None = ..., + show_caches: bool = ..., + adaptive: bool = ..., ) -> None: ... elif sys.version_info >= (3, 7): @@ -113,10 +121,18 @@ else: def dis(x: _HaveCodeOrStringType | None = ..., *, file: IO[str] | None = ...) -> None: ... if sys.version_info >= (3, 11): - def disassemble(co: _HaveCodeType, lasti: int = ..., *, file: IO[str] | None = ..., show_caches: bool = ...) -> None: ... - def disco(co: _HaveCodeType, lasti: int = ..., *, file: IO[str] | None = ..., show_caches: bool = ...) -> None: ... - def distb(tb: types.TracebackType | None = ..., *, file: IO[str] | None = ..., show_caches: bool = ...) -> None: ... - def get_instructions(x: _HaveCodeType, *, first_line: int | None = ..., show_caches: bool = ...) -> Iterator[Instruction]: ... + def disassemble( + co: _HaveCodeType, lasti: int = ..., *, file: IO[str] | None = ..., show_caches: bool = ..., adaptive: bool = ... + ) -> None: ... + def disco( + co: _HaveCodeType, lasti: int = ..., *, file: IO[str] | None = ..., show_caches: bool = ..., adaptive: bool = ... + ) -> None: ... + def distb( + tb: types.TracebackType | None = ..., *, file: IO[str] | None = ..., show_caches: bool = ..., adaptive: bool = ... + ) -> None: ... + def get_instructions( + x: _HaveCodeType, *, first_line: int | None = ..., show_caches: bool = ..., adaptive: bool = ... + ) -> Iterator[Instruction]: ... else: def disassemble(co: _HaveCodeType, lasti: int = ..., *, file: IO[str] | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/distutils/command/check.pyi b/mypy/typeshed/stdlib/distutils/command/check.pyi index 36895d2c16f1c..cdbe40fff71d1 100644 --- a/mypy/typeshed/stdlib/distutils/command/check.pyi +++ b/mypy/typeshed/stdlib/distutils/command/check.pyi @@ -1,8 +1,9 @@ from typing import Any +from typing_extensions import TypeAlias from ..cmd import Command -_Reporter = Any # really docutils.utils.Reporter +_Reporter: TypeAlias = Any # really docutils.utils.Reporter # Only defined if docutils is installed. class SilentReporter(_Reporter): diff --git a/mypy/typeshed/stdlib/distutils/filelist.pyi b/mypy/typeshed/stdlib/distutils/filelist.pyi index 361cb13f0c478..d8b87e2515095 100644 --- a/mypy/typeshed/stdlib/distutils/filelist.pyi +++ b/mypy/typeshed/stdlib/distutils/filelist.pyi @@ -17,34 +17,34 @@ class FileList: def process_template_line(self, line: str) -> None: ... @overload def include_pattern( - self, pattern: str, anchor: int | bool = ..., prefix: str | None = ..., is_regex: Literal[0, False] = ... + self, pattern: str, anchor: bool | Literal[0, 1] = ..., prefix: str | None = ..., is_regex: Literal[0, False] = ... ) -> bool: ... @overload def include_pattern(self, pattern: str | Pattern[str], *, is_regex: Literal[True, 1] = ...) -> bool: ... @overload def include_pattern( - self, pattern: str | Pattern[str], anchor: int | bool = ..., prefix: str | None = ..., is_regex: int | bool = ... + self, pattern: str | Pattern[str], anchor: bool | Literal[0, 1] = ..., prefix: str | None = ..., is_regex: int = ... ) -> bool: ... @overload def exclude_pattern( - self, pattern: str, anchor: int | bool = ..., prefix: str | None = ..., is_regex: Literal[0, False] = ... + self, pattern: str, anchor: bool | Literal[0, 1] = ..., prefix: str | None = ..., is_regex: Literal[0, False] = ... ) -> bool: ... @overload def exclude_pattern(self, pattern: str | Pattern[str], *, is_regex: Literal[True, 1] = ...) -> bool: ... @overload def exclude_pattern( - self, pattern: str | Pattern[str], anchor: int | bool = ..., prefix: str | None = ..., is_regex: int | bool = ... + self, pattern: str | Pattern[str], anchor: bool | Literal[0, 1] = ..., prefix: str | None = ..., is_regex: int = ... ) -> bool: ... def findall(dir: str = ...) -> list[str]: ... def glob_to_re(pattern: str) -> str: ... @overload def translate_pattern( - pattern: str, anchor: int | bool = ..., prefix: str | None = ..., is_regex: Literal[False, 0] = ... + pattern: str, anchor: bool | Literal[0, 1] = ..., prefix: str | None = ..., is_regex: Literal[False, 0] = ... ) -> Pattern[str]: ... @overload def translate_pattern(pattern: str | Pattern[str], *, is_regex: Literal[True, 1] = ...) -> Pattern[str]: ... @overload def translate_pattern( - pattern: str | Pattern[str], anchor: int | bool = ..., prefix: str | None = ..., is_regex: int | bool = ... + pattern: str | Pattern[str], anchor: bool | Literal[0, 1] = ..., prefix: str | None = ..., is_regex: int = ... ) -> Pattern[str]: ... diff --git a/mypy/typeshed/stdlib/enum.pyi b/mypy/typeshed/stdlib/enum.pyi index 9ebeba37ab711..6063dc47b004a 100644 --- a/mypy/typeshed/stdlib/enum.pyi +++ b/mypy/typeshed/stdlib/enum.pyi @@ -1,44 +1,37 @@ import sys import types -from _typeshed import Self +from _typeshed import Self, SupportsKeysAndGetItem from abc import ABCMeta from builtins import property as _builtins_property from collections.abc import Iterable, Iterator, Mapping from typing import Any, Generic, TypeVar, overload from typing_extensions import Literal, TypeAlias +__all__ = ["EnumMeta", "Enum", "IntEnum", "Flag", "IntFlag", "auto", "unique"] + if sys.version_info >= (3, 11): - __all__ = [ - "EnumType", - "EnumMeta", - "Enum", - "IntEnum", - "StrEnum", - "Flag", - "IntFlag", - "ReprEnum", - "auto", - "unique", - "property", - "verify", - "member", - "nonmember", - "FlagBoundary", - "STRICT", + __all__ += [ "CONFORM", + "CONTINUOUS", "EJECT", - "KEEP", - "global_flag_repr", - "global_enum_repr", - "global_str", - "global_enum", "EnumCheck", - "CONTINUOUS", + "EnumType", + "FlagBoundary", + "KEEP", "NAMED_FLAGS", + "ReprEnum", + "STRICT", + "StrEnum", "UNIQUE", + "global_enum", + "global_enum_repr", + "global_flag_repr", + "global_str", + "member", + "nonmember", + "property", + "verify", ] -else: - __all__ = ["EnumMeta", "Enum", "IntEnum", "Flag", "IntFlag", "auto", "unique"] _EnumMemberT = TypeVar("_EnumMemberT") _EnumerationT = TypeVar("_EnumerationT", bound=type[Enum]) @@ -68,6 +61,16 @@ if sys.version_info >= (3, 11): class _EnumDict(dict[str, Any]): def __init__(self) -> None: ... def __setitem__(self, key: str, value: Any) -> None: ... + if sys.version_info >= (3, 11): + # See comment above `typing.MutableMapping.update` + # for why overloads are preferable to a Union here + # + # Unlike with MutableMapping.update(), the first argument is required, + # hence the type: ignore + @overload # type: ignore[override] + def update(self, members: SupportsKeysAndGetItem[str, Any], **more_members: Any) -> None: ... + @overload + def update(self, members: Iterable[tuple[str, Any]], **more_members: Any) -> None: ... # Note: EnumMeta actually subclasses type directly, not ABCMeta. # This is a temporary workaround to allow multiple creation of enums with builtins @@ -213,15 +216,21 @@ class Flag(Enum): def __and__(self: Self, other: Self) -> Self: ... def __xor__(self: Self, other: Self) -> Self: ... def __invert__(self: Self) -> Self: ... + if sys.version_info >= (3, 11): + def __iter__(self: Self) -> Iterator[Self]: ... + def __len__(self) -> int: ... + __ror__ = __or__ + __rand__ = __and__ + __rxor__ = __xor__ class IntFlag(int, Flag): def __new__(cls: type[Self], value: int) -> Self: ... def __or__(self: Self, other: int) -> Self: ... def __and__(self: Self, other: int) -> Self: ... def __xor__(self: Self, other: int) -> Self: ... - def __ror__(self: Self, other: int) -> Self: ... - def __rand__(self: Self, other: int) -> Self: ... - def __rxor__(self: Self, other: int) -> Self: ... + __ror__ = __or__ + __rand__ = __and__ + __rxor__ = __xor__ if sys.version_info >= (3, 11): class StrEnum(str, ReprEnum): diff --git a/mypy/typeshed/stdlib/filecmp.pyi b/mypy/typeshed/stdlib/filecmp.pyi index a6747dd504a33..dd4a0628b026d 100644 --- a/mypy/typeshed/stdlib/filecmp.pyi +++ b/mypy/typeshed/stdlib/filecmp.pyi @@ -1,7 +1,6 @@ import sys -from _typeshed import StrOrBytesPath +from _typeshed import GenericPath, StrOrBytesPath from collections.abc import Callable, Iterable, Sequence -from os import PathLike from typing import Any, AnyStr, Generic from typing_extensions import Literal @@ -13,19 +12,16 @@ __all__ = ["clear_cache", "cmp", "dircmp", "cmpfiles", "DEFAULT_IGNORES"] DEFAULT_IGNORES: list[str] BUFSIZE: Literal[8192] -def cmp(f1: StrOrBytesPath, f2: StrOrBytesPath, shallow: int | bool = ...) -> bool: ... +def cmp(f1: StrOrBytesPath, f2: StrOrBytesPath, shallow: bool | Literal[0, 1] = ...) -> bool: ... def cmpfiles( - a: AnyStr | PathLike[AnyStr], - b: AnyStr | PathLike[AnyStr], - common: Iterable[AnyStr | PathLike[AnyStr]], - shallow: int | bool = ..., + a: GenericPath[AnyStr], b: GenericPath[AnyStr], common: Iterable[GenericPath[AnyStr]], shallow: bool | Literal[0, 1] = ... ) -> tuple[list[AnyStr], list[AnyStr], list[AnyStr]]: ... class dircmp(Generic[AnyStr]): def __init__( self, - a: AnyStr | PathLike[AnyStr], - b: AnyStr | PathLike[AnyStr], + a: GenericPath[AnyStr], + b: GenericPath[AnyStr], ignore: Sequence[AnyStr] | None = ..., hide: Sequence[AnyStr] | None = ..., ) -> None: ... diff --git a/mypy/typeshed/stdlib/fileinput.pyi b/mypy/typeshed/stdlib/fileinput.pyi index 0ef8c14ddaac1..e0babbcd40cce 100644 --- a/mypy/typeshed/stdlib/fileinput.pyi +++ b/mypy/typeshed/stdlib/fileinput.pyi @@ -1,8 +1,12 @@ import sys -from _typeshed import Self, StrOrBytesPath +from _typeshed import AnyStr_co, Self, StrOrBytesPath from collections.abc import Callable, Iterable, Iterator from types import TracebackType -from typing import IO, Any, AnyStr, Generic +from typing import IO, Any, AnyStr, Generic, Protocol, overload +from typing_extensions import Literal, TypeAlias + +if sys.version_info >= (3, 9): + from types import GenericAlias __all__ = [ "input", @@ -19,40 +23,131 @@ __all__ = [ "hook_encoded", ] -if sys.version_info >= (3, 9): - from types import GenericAlias +if sys.version_info >= (3, 11): + _TextMode: TypeAlias = Literal["r"] +else: + _TextMode: TypeAlias = Literal["r", "rU", "U"] + +class _HasReadlineAndFileno(Protocol[AnyStr_co]): + def readline(self) -> AnyStr_co: ... + def fileno(self) -> int: ... if sys.version_info >= (3, 10): + # encoding and errors are added + @overload def input( files: StrOrBytesPath | Iterable[StrOrBytesPath] | None = ..., inplace: bool = ..., backup: str = ..., *, - mode: str = ..., - openhook: Callable[[StrOrBytesPath, str], IO[AnyStr]] = ..., + mode: _TextMode = ..., + openhook: Callable[[StrOrBytesPath, str], _HasReadlineAndFileno[str]] | None = ..., encoding: str | None = ..., errors: str | None = ..., - ) -> FileInput[AnyStr]: ... + ) -> FileInput[str]: ... + @overload + def input( + files: StrOrBytesPath | Iterable[StrOrBytesPath] | None = ..., + inplace: bool = ..., + backup: str = ..., + *, + mode: Literal["rb"], + openhook: Callable[[StrOrBytesPath, str], _HasReadlineAndFileno[bytes]] | None = ..., + encoding: None = ..., + errors: None = ..., + ) -> FileInput[bytes]: ... + @overload + def input( + files: StrOrBytesPath | Iterable[StrOrBytesPath] | None = ..., + inplace: bool = ..., + backup: str = ..., + *, + mode: str, + openhook: Callable[[StrOrBytesPath, str], _HasReadlineAndFileno[Any]] | None = ..., + encoding: str | None = ..., + errors: str | None = ..., + ) -> FileInput[Any]: ... elif sys.version_info >= (3, 8): + # bufsize is dropped and mode and openhook become keyword-only + @overload + def input( + files: StrOrBytesPath | Iterable[StrOrBytesPath] | None = ..., + inplace: bool = ..., + backup: str = ..., + *, + mode: _TextMode = ..., + openhook: Callable[[StrOrBytesPath, str], _HasReadlineAndFileno[str]] | None = ..., + ) -> FileInput[str]: ... + @overload def input( files: StrOrBytesPath | Iterable[StrOrBytesPath] | None = ..., inplace: bool = ..., backup: str = ..., *, - mode: str = ..., - openhook: Callable[[StrOrBytesPath, str], IO[AnyStr]] = ..., - ) -> FileInput[AnyStr]: ... + mode: Literal["rb"], + openhook: Callable[[StrOrBytesPath, str], _HasReadlineAndFileno[bytes]] | None = ..., + ) -> FileInput[bytes]: ... + @overload + def input( + files: StrOrBytesPath | Iterable[StrOrBytesPath] | None = ..., + inplace: bool = ..., + backup: str = ..., + *, + mode: str, + openhook: Callable[[StrOrBytesPath, str], _HasReadlineAndFileno[Any]] | None = ..., + ) -> FileInput[Any]: ... else: + @overload + def input( + files: StrOrBytesPath | Iterable[StrOrBytesPath] | None = ..., + inplace: bool = ..., + backup: str = ..., + bufsize: int = ..., + mode: _TextMode = ..., + openhook: Callable[[StrOrBytesPath, str], _HasReadlineAndFileno[str]] | None = ..., + ) -> FileInput[str]: ... + # Because mode isn't keyword-only here yet, we need two overloads each for + # the bytes case and the fallback case. + @overload + def input( + files: StrOrBytesPath | Iterable[StrOrBytesPath] | None = ..., + inplace: bool = ..., + backup: str = ..., + bufsize: int = ..., + *, + mode: Literal["rb"], + openhook: Callable[[StrOrBytesPath, str], _HasReadlineAndFileno[bytes]] | None = ..., + ) -> FileInput[bytes]: ... + @overload + def input( + files: StrOrBytesPath | Iterable[StrOrBytesPath] | None, + inplace: bool, + backup: str, + bufsize: int, + mode: Literal["rb"], + openhook: Callable[[StrOrBytesPath, str], _HasReadlineAndFileno[bytes]] | None = ..., + ) -> FileInput[bytes]: ... + @overload def input( files: StrOrBytesPath | Iterable[StrOrBytesPath] | None = ..., inplace: bool = ..., backup: str = ..., bufsize: int = ..., - mode: str = ..., - openhook: Callable[[StrOrBytesPath, str], IO[AnyStr]] = ..., - ) -> FileInput[AnyStr]: ... + *, + mode: str, + openhook: Callable[[StrOrBytesPath, str], _HasReadlineAndFileno[Any]] | None = ..., + ) -> FileInput[Any]: ... + @overload + def input( + files: StrOrBytesPath | Iterable[StrOrBytesPath] | None, + inplace: bool, + backup: str, + bufsize: int, + mode: str, + openhook: Callable[[StrOrBytesPath, str], _HasReadlineAndFileno[Any]] | None = ..., + ) -> FileInput[Any]: ... def close() -> None: ... def nextfile() -> None: ... @@ -65,36 +160,131 @@ def isstdin() -> bool: ... class FileInput(Iterator[AnyStr], Generic[AnyStr]): if sys.version_info >= (3, 10): + # encoding and errors are added + @overload def __init__( - self, - files: None | StrOrBytesPath | Iterable[StrOrBytesPath] = ..., + self: FileInput[str], + files: StrOrBytesPath | Iterable[StrOrBytesPath] | None = ..., inplace: bool = ..., backup: str = ..., *, - mode: str = ..., - openhook: Callable[[StrOrBytesPath, str], IO[AnyStr]] = ..., + mode: _TextMode = ..., + openhook: Callable[[StrOrBytesPath, str], _HasReadlineAndFileno[str]] | None = ..., encoding: str | None = ..., errors: str | None = ..., ) -> None: ... + @overload + def __init__( + self: FileInput[bytes], + files: StrOrBytesPath | Iterable[StrOrBytesPath] | None = ..., + inplace: bool = ..., + backup: str = ..., + *, + mode: Literal["rb"], + openhook: Callable[[StrOrBytesPath, str], _HasReadlineAndFileno[bytes]] | None = ..., + encoding: None = ..., + errors: None = ..., + ) -> None: ... + @overload + def __init__( + self: FileInput[Any], + files: StrOrBytesPath | Iterable[StrOrBytesPath] | None = ..., + inplace: bool = ..., + backup: str = ..., + *, + mode: str, + openhook: Callable[[StrOrBytesPath, str], _HasReadlineAndFileno[Any]] | None = ..., + encoding: str | None = ..., + errors: str | None = ..., + ) -> None: ... + elif sys.version_info >= (3, 8): + # bufsize is dropped and mode and openhook become keyword-only + @overload + def __init__( + self: FileInput[str], + files: StrOrBytesPath | Iterable[StrOrBytesPath] | None = ..., + inplace: bool = ..., + backup: str = ..., + *, + mode: _TextMode = ..., + openhook: Callable[[StrOrBytesPath, str], _HasReadlineAndFileno[str]] | None = ..., + ) -> None: ... + @overload + def __init__( + self: FileInput[bytes], + files: StrOrBytesPath | Iterable[StrOrBytesPath] | None = ..., + inplace: bool = ..., + backup: str = ..., + *, + mode: Literal["rb"], + openhook: Callable[[StrOrBytesPath, str], _HasReadlineAndFileno[bytes]] | None = ..., + ) -> None: ... + @overload def __init__( - self, - files: None | StrOrBytesPath | Iterable[StrOrBytesPath] = ..., + self: FileInput[Any], + files: StrOrBytesPath | Iterable[StrOrBytesPath] | None = ..., inplace: bool = ..., backup: str = ..., *, - mode: str = ..., - openhook: Callable[[StrOrBytesPath, str], IO[AnyStr]] = ..., + mode: str, + openhook: Callable[[StrOrBytesPath, str], _HasReadlineAndFileno[Any]] | None = ..., ) -> None: ... + else: + @overload def __init__( - self, - files: None | StrOrBytesPath | Iterable[StrOrBytesPath] = ..., + self: FileInput[str], + files: StrOrBytesPath | Iterable[StrOrBytesPath] | None = ..., inplace: bool = ..., backup: str = ..., bufsize: int = ..., - mode: str = ..., - openhook: Callable[[StrOrBytesPath, str], IO[AnyStr]] = ..., + mode: _TextMode = ..., + openhook: Callable[[StrOrBytesPath, str], _HasReadlineAndFileno[str]] | None = ..., + ) -> None: ... + # Because mode isn't keyword-only here yet, we need two overloads each for + # the bytes case and the fallback case. + @overload + def __init__( + self: FileInput[bytes], + files: StrOrBytesPath | Iterable[StrOrBytesPath] | None = ..., + inplace: bool = ..., + backup: str = ..., + bufsize: int = ..., + *, + mode: Literal["rb"], + openhook: Callable[[StrOrBytesPath, str], _HasReadlineAndFileno[bytes]] | None = ..., + ) -> None: ... + @overload + def __init__( + self: FileInput[bytes], + files: StrOrBytesPath | Iterable[StrOrBytesPath] | None, + inplace: bool, + backup: str, + bufsize: int, + mode: Literal["rb"], + openhook: Callable[[StrOrBytesPath, str], _HasReadlineAndFileno[bytes]] | None = ..., + ) -> None: ... + @overload + def __init__( + self: FileInput[Any], + files: StrOrBytesPath | Iterable[StrOrBytesPath] | None = ..., + inplace: bool = ..., + backup: str = ..., + bufsize: int = ..., + *, + mode: str, + openhook: Callable[[StrOrBytesPath, str], _HasReadlineAndFileno[Any]] | None = ..., + ) -> None: ... + @overload + def __init__( + self: FileInput[Any], + files: StrOrBytesPath | Iterable[StrOrBytesPath] | None, + inplace: bool, + backup: str, + bufsize: int, + mode: str, + openhook: Callable[[StrOrBytesPath, str], _HasReadlineAndFileno[Any]] | None = ..., ) -> None: ... def __del__(self) -> None: ... diff --git a/mypy/typeshed/stdlib/fractions.pyi b/mypy/typeshed/stdlib/fractions.pyi index 0d787a011f5b1..fb64c659224ab 100644 --- a/mypy/typeshed/stdlib/fractions.pyi +++ b/mypy/typeshed/stdlib/fractions.pyi @@ -1,9 +1,10 @@ import sys from _typeshed import Self +from collections.abc import Callable from decimal import Decimal from numbers import Integral, Rational, Real from typing import Any, overload -from typing_extensions import Literal, TypeAlias +from typing_extensions import Literal, SupportsIndex, TypeAlias _ComparableNum: TypeAlias = int | float | Decimal | Real @@ -118,7 +119,7 @@ class Fraction(Rational): @overload def __pow__(self, b: complex) -> complex: ... @overload - def __rpow__(self, a: int | float | Fraction) -> float: ... + def __rpow__(self, a: float | Fraction) -> float: ... @overload def __rpow__(self, a: complex) -> complex: ... def __pos__(self) -> Fraction: ... @@ -141,7 +142,7 @@ class Fraction(Rational): def __copy__(self: Self) -> Self: ... def __deepcopy__(self: Self, memo: Any) -> Self: ... if sys.version_info >= (3, 11): - def __int__(self) -> int: ... + def __int__(self, _index: Callable[[SupportsIndex], int] = ...) -> int: ... # Not actually defined within fractions.py, but provides more useful # overrides @property diff --git a/mypy/typeshed/stdlib/ftplib.pyi b/mypy/typeshed/stdlib/ftplib.pyi index 925ad5884700d..49c680a6f0c71 100644 --- a/mypy/typeshed/stdlib/ftplib.pyi +++ b/mypy/typeshed/stdlib/ftplib.pyi @@ -70,7 +70,7 @@ class FTP: def getwelcome(self) -> str: ... def set_debuglevel(self, level: int) -> None: ... def debug(self, level: int) -> None: ... - def set_pasv(self, val: bool | int) -> None: ... + def set_pasv(self, val: bool | Literal[0, 1]) -> None: ... def sanitize(self, s: str) -> str: ... def putline(self, line: str) -> None: ... def putcmd(self, line: str) -> None: ... diff --git a/mypy/typeshed/stdlib/functools.pyi b/mypy/typeshed/stdlib/functools.pyi index 44feeed63f6ac..3003ef061a84d 100644 --- a/mypy/typeshed/stdlib/functools.pyi +++ b/mypy/typeshed/stdlib/functools.pyi @@ -1,6 +1,6 @@ import sys import types -from _typeshed import Self, SupportsAllComparisons, SupportsItems +from _typeshed import IdentityFunction, Self, SupportsAllComparisons, SupportsItems from collections.abc import Callable, Hashable, Iterable, Sequence, Sized from typing import Any, Generic, NamedTuple, TypeVar, overload from typing_extensions import Literal, TypeAlias, final @@ -8,52 +8,25 @@ from typing_extensions import Literal, TypeAlias, final if sys.version_info >= (3, 9): from types import GenericAlias - __all__ = [ - "update_wrapper", - "wraps", - "WRAPPER_ASSIGNMENTS", - "WRAPPER_UPDATES", - "total_ordering", - "cache", - "cmp_to_key", - "lru_cache", - "reduce", - "partial", - "partialmethod", - "singledispatch", - "singledispatchmethod", - "cached_property", - ] -elif sys.version_info >= (3, 8): - __all__ = [ - "update_wrapper", - "wraps", - "WRAPPER_ASSIGNMENTS", - "WRAPPER_UPDATES", - "total_ordering", - "cmp_to_key", - "lru_cache", - "reduce", - "partial", - "partialmethod", - "singledispatch", - "singledispatchmethod", - "cached_property", - ] -else: - __all__ = [ - "update_wrapper", - "wraps", - "WRAPPER_ASSIGNMENTS", - "WRAPPER_UPDATES", - "total_ordering", - "cmp_to_key", - "lru_cache", - "reduce", - "partial", - "partialmethod", - "singledispatch", - ] +__all__ = [ + "update_wrapper", + "wraps", + "WRAPPER_ASSIGNMENTS", + "WRAPPER_UPDATES", + "total_ordering", + "cmp_to_key", + "lru_cache", + "reduce", + "partial", + "partialmethod", + "singledispatch", +] + +if sys.version_info >= (3, 8): + __all__ += ["cached_property", "singledispatchmethod"] + +if sys.version_info >= (3, 9): + __all__ += ["cache"] _AnyCallable: TypeAlias = Callable[..., Any] @@ -95,7 +68,7 @@ WRAPPER_ASSIGNMENTS: tuple[ WRAPPER_UPDATES: tuple[Literal["__dict__"]] def update_wrapper(wrapper: _T, wrapped: _AnyCallable, assigned: Sequence[str] = ..., updated: Sequence[str] = ...) -> _T: ... -def wraps(wrapped: _AnyCallable, assigned: Sequence[str] = ..., updated: Sequence[str] = ...) -> Callable[[_T], _T]: ... +def wraps(wrapped: _AnyCallable, assigned: Sequence[str] = ..., updated: Sequence[str] = ...) -> IdentityFunction: ... def total_ordering(cls: type[_T]) -> type[_T]: ... def cmp_to_key(mycmp: Callable[[_T, _T], int]) -> Callable[[_T], SupportsAllComparisons]: ... diff --git a/mypy/typeshed/stdlib/genericpath.pyi b/mypy/typeshed/stdlib/genericpath.pyi index 984d0c3cf51e5..911d582fd538f 100644 --- a/mypy/typeshed/stdlib/genericpath.pyi +++ b/mypy/typeshed/stdlib/genericpath.pyi @@ -2,7 +2,7 @@ import os from _typeshed import BytesPath, StrOrBytesPath, StrPath, SupportsRichComparisonT from collections.abc import Sequence from typing import overload -from typing_extensions import Literal +from typing_extensions import Literal, LiteralString __all__ = [ "commonprefix", @@ -22,6 +22,8 @@ __all__ = [ # Iterable[T], so that list[T] | Literal[""] could be used as a return # type. But because this only works when T is str, we need Sequence[T] instead. @overload +def commonprefix(m: Sequence[LiteralString]) -> LiteralString: ... +@overload def commonprefix(m: Sequence[StrPath]) -> str: ... @overload def commonprefix(m: Sequence[BytesPath]) -> bytes | Literal[""]: ... diff --git a/mypy/typeshed/stdlib/gettext.pyi b/mypy/typeshed/stdlib/gettext.pyi index 829ade96cb405..3c07abeb2d8a2 100644 --- a/mypy/typeshed/stdlib/gettext.pyi +++ b/mypy/typeshed/stdlib/gettext.pyi @@ -1,72 +1,30 @@ +import io import sys from _typeshed import StrPath -from collections.abc import Container, Iterable, Sequence +from collections.abc import Callable, Container, Iterable, Sequence from typing import Any, Protocol, TypeVar, overload from typing_extensions import Final, Literal -if sys.version_info >= (3, 11): - __all__ = [ - "NullTranslations", - "GNUTranslations", - "Catalog", - "bindtextdomain", - "find", - "translation", - "install", - "textdomain", - "dgettext", - "dngettext", - "gettext", - "ngettext", - "pgettext", - "dpgettext", - "npgettext", - "dnpgettext", - ] -elif sys.version_info >= (3, 8): - __all__ = [ - "NullTranslations", - "GNUTranslations", - "Catalog", - "find", - "translation", - "install", - "textdomain", - "bindtextdomain", - "bind_textdomain_codeset", - "dgettext", - "dngettext", - "gettext", - "lgettext", - "ldgettext", - "ldngettext", - "lngettext", - "ngettext", - "pgettext", - "dpgettext", - "npgettext", - "dnpgettext", - ] -else: - __all__ = [ - "NullTranslations", - "GNUTranslations", - "Catalog", - "find", - "translation", - "install", - "textdomain", - "bindtextdomain", - "bind_textdomain_codeset", - "dgettext", - "dngettext", - "gettext", - "lgettext", - "ldgettext", - "ldngettext", - "lngettext", - "ngettext", - ] +__all__ = [ + "NullTranslations", + "GNUTranslations", + "Catalog", + "find", + "translation", + "install", + "textdomain", + "bindtextdomain", + "dgettext", + "dngettext", + "gettext", + "ngettext", +] + +if sys.version_info < (3, 11): + __all__ += ["bind_textdomain_codeset", "ldgettext", "ldngettext", "lgettext", "lngettext"] + +if sys.version_info >= (3, 8): + __all__ += ["dnpgettext", "dpgettext", "npgettext", "pgettext"] class _TranslationsReader(Protocol): def read(self) -> bytes: ... @@ -78,9 +36,7 @@ class NullTranslations: def _parse(self, fp: _TranslationsReader) -> None: ... def add_fallback(self, fallback: NullTranslations) -> None: ... def gettext(self, message: str) -> str: ... - def lgettext(self, message: str) -> str: ... def ngettext(self, msgid1: str, msgid2: str, n: int) -> str: ... - def lngettext(self, msgid1: str, msgid2: str, n: int) -> str: ... if sys.version_info >= (3, 8): def pgettext(self, context: str, message: str) -> str: ... def npgettext(self, context: str, msgid1: str, msgid2: str, n: int) -> str: ... @@ -90,6 +46,8 @@ class NullTranslations: if sys.version_info < (3, 11): def output_charset(self) -> str | None: ... def set_output_charset(self, charset: str) -> None: ... + def lgettext(self, message: str) -> str: ... + def lngettext(self, msgid1: str, msgid2: str, n: int) -> str: ... def install(self, names: Container[str] | None = ...) -> None: ... @@ -110,7 +68,7 @@ def find( @overload def find(domain: str, localedir: StrPath | None = ..., languages: Iterable[str] | None = ..., all: bool = ...) -> Any: ... -_T = TypeVar("_T") +_NullTranslationsT = TypeVar("_NullTranslationsT", bound=NullTranslations) if sys.version_info >= (3, 11): @overload @@ -119,25 +77,34 @@ if sys.version_info >= (3, 11): localedir: StrPath | None = ..., languages: Iterable[str] | None = ..., class_: None = ..., - fallback: bool = ..., - ) -> NullTranslations: ... + fallback: Literal[False] = ..., + ) -> GNUTranslations: ... @overload def translation( domain: str, localedir: StrPath | None = ..., languages: Iterable[str] | None = ..., - class_: type[_T] = ..., + *, + class_: Callable[[io.BufferedReader], _NullTranslationsT], + fallback: Literal[False] = ..., + ) -> _NullTranslationsT: ... + @overload + def translation( + domain: str, + localedir: StrPath | None, + languages: Iterable[str] | None, + class_: Callable[[io.BufferedReader], _NullTranslationsT], fallback: Literal[False] = ..., - ) -> _T: ... + ) -> _NullTranslationsT: ... @overload def translation( domain: str, localedir: StrPath | None = ..., languages: Iterable[str] | None = ..., - class_: type[Any] = ..., - fallback: Literal[True] = ..., - ) -> Any: ... - def install(domain: str, localedir: StrPath | None = ..., names: Container[str] | None = ...) -> None: ... + class_: Callable[[io.BufferedReader], NullTranslations] | None = ..., + fallback: bool = ..., + ) -> NullTranslations: ... + def install(domain: str, localedir: StrPath | None = ..., *, names: Container[str] | None = ...) -> None: ... else: @overload @@ -146,27 +113,37 @@ else: localedir: StrPath | None = ..., languages: Iterable[str] | None = ..., class_: None = ..., - fallback: bool = ..., + fallback: Literal[False] = ..., codeset: str | None = ..., - ) -> NullTranslations: ... + ) -> GNUTranslations: ... @overload def translation( domain: str, localedir: StrPath | None = ..., languages: Iterable[str] | None = ..., - class_: type[_T] = ..., + *, + class_: Callable[[io.BufferedReader], _NullTranslationsT], + fallback: Literal[False] = ..., + codeset: str | None = ..., + ) -> _NullTranslationsT: ... + @overload + def translation( + domain: str, + localedir: StrPath | None, + languages: Iterable[str] | None, + class_: Callable[[io.BufferedReader], _NullTranslationsT], fallback: Literal[False] = ..., codeset: str | None = ..., - ) -> _T: ... + ) -> _NullTranslationsT: ... @overload def translation( domain: str, localedir: StrPath | None = ..., languages: Iterable[str] | None = ..., - class_: type[Any] = ..., - fallback: Literal[True] = ..., + class_: Callable[[io.BufferedReader], NullTranslations] | None = ..., + fallback: bool = ..., codeset: str | None = ..., - ) -> Any: ... + ) -> NullTranslations: ... def install( domain: str, localedir: StrPath | None = ..., codeset: str | None = ..., names: Container[str] | None = ... ) -> None: ... diff --git a/mypy/typeshed/stdlib/graphlib.pyi b/mypy/typeshed/stdlib/graphlib.pyi index 2fca402bf9068..4c6959decc4be 100644 --- a/mypy/typeshed/stdlib/graphlib.pyi +++ b/mypy/typeshed/stdlib/graphlib.pyi @@ -1,7 +1,7 @@ import sys from _typeshed import SupportsItems from collections.abc import Iterable -from typing import Any, Generic, TypeVar +from typing import Any, Generic, TypeVar, overload __all__ = ["TopologicalSorter", "CycleError"] @@ -11,7 +11,10 @@ if sys.version_info >= (3, 11): from types import GenericAlias class TopologicalSorter(Generic[_T]): - def __init__(self, graph: SupportsItems[_T, Iterable[_T]] | None = ...) -> None: ... + @overload + def __init__(self, graph: None = ...) -> None: ... + @overload + def __init__(self, graph: SupportsItems[_T, Iterable[_T]]) -> None: ... def add(self, node: _T, *predecessors: _T) -> None: ... def prepare(self) -> None: ... def is_active(self) -> bool: ... diff --git a/mypy/typeshed/stdlib/hmac.pyi b/mypy/typeshed/stdlib/hmac.pyi index 858e46a71b681..a7bf15493f0b8 100644 --- a/mypy/typeshed/stdlib/hmac.pyi +++ b/mypy/typeshed/stdlib/hmac.pyi @@ -42,4 +42,4 @@ def compare_digest(__a: ReadableBuffer, __b: ReadableBuffer) -> bool: ... def compare_digest(__a: AnyStr, __b: AnyStr) -> bool: ... if sys.version_info >= (3, 7): - def digest(key: bytes, msg: ReadableBuffer, digest: str) -> bytes: ... + def digest(key: bytes, msg: ReadableBuffer, digest: _DigestMod) -> bytes: ... diff --git a/mypy/typeshed/stdlib/imaplib.pyi b/mypy/typeshed/stdlib/imaplib.pyi index eef1c19577695..b082100774c0e 100644 --- a/mypy/typeshed/stdlib/imaplib.pyi +++ b/mypy/typeshed/stdlib/imaplib.pyi @@ -169,7 +169,7 @@ class _Authenticator: def encode(self, inp: bytes) -> str: ... def decode(self, inp: str) -> bytes: ... -def Internaldate2tuple(resp: str) -> time.struct_time: ... +def Internaldate2tuple(resp: bytes) -> time.struct_time: ... def Int2AP(num: int) -> str: ... def ParseFlags(resp: str) -> tuple[str, ...]: ... def Time2Internaldate(date_time: float | time.struct_time | str) -> str: ... diff --git a/mypy/typeshed/stdlib/importlib/abc.pyi b/mypy/typeshed/stdlib/importlib/abc.pyi index 63fd02f7b3d51..805910329b64a 100644 --- a/mypy/typeshed/stdlib/importlib/abc.pyi +++ b/mypy/typeshed/stdlib/importlib/abc.pyi @@ -16,6 +16,22 @@ from io import BufferedRandom, BufferedReader, BufferedWriter, FileIO, TextIOWra from typing import IO, Any, BinaryIO, NoReturn, Protocol, overload, runtime_checkable from typing_extensions import Literal, TypeAlias +if sys.version_info >= (3, 11): + __all__ = [ + "Loader", + "Finder", + "MetaPathFinder", + "PathEntryFinder", + "ResourceLoader", + "InspectLoader", + "ExecutionLoader", + "FileLoader", + "SourceLoader", + "ResourceReader", + "Traversable", + "TraversableResources", + ] + _Path: TypeAlias = bytes | str class Finder(metaclass=ABCMeta): ... diff --git a/mypy/typeshed/stdlib/importlib/metadata/__init__.pyi b/mypy/typeshed/stdlib/importlib/metadata/__init__.pyi index 1f32f0770b375..6466ce0a23ac0 100644 --- a/mypy/typeshed/stdlib/importlib/metadata/__init__.pyi +++ b/mypy/typeshed/stdlib/importlib/metadata/__init__.pyi @@ -9,34 +9,21 @@ from os import PathLike from pathlib import Path from typing import Any, ClassVar, NamedTuple, Pattern, overload +__all__ = [ + "Distribution", + "DistributionFinder", + "PackageNotFoundError", + "distribution", + "distributions", + "entry_points", + "files", + "metadata", + "requires", + "version", +] + if sys.version_info >= (3, 10): - __all__ = [ - "Distribution", - "DistributionFinder", - "PackageMetadata", - "PackageNotFoundError", - "distribution", - "distributions", - "entry_points", - "files", - "metadata", - "packages_distributions", - "requires", - "version", - ] -else: - __all__ = [ - "Distribution", - "DistributionFinder", - "PackageNotFoundError", - "distribution", - "distributions", - "entry_points", - "files", - "metadata", - "requires", - "version", - ] + __all__ += ["PackageMetadata", "packages_distributions"] if sys.version_info >= (3, 10): from importlib.metadata._meta import PackageMetadata as PackageMetadata diff --git a/mypy/typeshed/stdlib/importlib/metadata/_meta.pyi b/mypy/typeshed/stdlib/importlib/metadata/_meta.pyi index a1101df0d5ced..6a7cd858c80bf 100644 --- a/mypy/typeshed/stdlib/importlib/metadata/_meta.pyi +++ b/mypy/typeshed/stdlib/importlib/metadata/_meta.pyi @@ -1,3 +1,4 @@ +import sys from collections.abc import Iterator from typing import Any, Protocol, TypeVar @@ -14,6 +15,9 @@ class PackageMetadata(Protocol): class SimplePath(Protocol): def joinpath(self) -> SimplePath: ... - def __div__(self) -> SimplePath: ... def parent(self) -> SimplePath: ... def read_text(self) -> str: ... + if sys.version_info >= (3, 11): + def __truediv__(self) -> SimplePath: ... + else: + def __div__(self) -> SimplePath: ... diff --git a/mypy/typeshed/stdlib/importlib/resources.pyi b/mypy/typeshed/stdlib/importlib/resources.pyi index 04d7e8dcc967f..28ca107f41951 100644 --- a/mypy/typeshed/stdlib/importlib/resources.pyi +++ b/mypy/typeshed/stdlib/importlib/resources.pyi @@ -7,40 +7,20 @@ from types import ModuleType from typing import Any, BinaryIO, TextIO from typing_extensions import TypeAlias +__all__ = ["Package", "Resource", "contents", "is_resource", "open_binary", "open_text", "path", "read_binary", "read_text"] + +if sys.version_info >= (3, 9): + __all__ += ["as_file", "files"] + if sys.version_info >= (3, 10): - __all__ = [ - "Package", - "Resource", - "ResourceReader", - "as_file", - "contents", - "files", - "is_resource", - "open_binary", - "open_text", - "path", - "read_binary", - "read_text", - ] -elif sys.version_info >= (3, 9): - __all__ = [ - "Package", - "Resource", - "as_file", - "contents", - "files", - "is_resource", - "open_binary", - "open_text", - "path", - "read_binary", - "read_text", - ] -else: - __all__ = ["Package", "Resource", "contents", "is_resource", "open_binary", "open_text", "path", "read_binary", "read_text"] + __all__ += ["ResourceReader"] Package: TypeAlias = str | ModuleType -Resource: TypeAlias = str | os.PathLike[Any] + +if sys.version_info >= (3, 11): + Resource: TypeAlias = str +else: + Resource: TypeAlias = str | os.PathLike[Any] def open_binary(package: Package, resource: Resource) -> BinaryIO: ... def open_text(package: Package, resource: Resource, encoding: str = ..., errors: str = ...) -> TextIO: ... diff --git a/mypy/typeshed/stdlib/io.pyi b/mypy/typeshed/stdlib/io.pyi index 327fd0d94a4d2..0670b65fe359d 100644 --- a/mypy/typeshed/stdlib/io.pyi +++ b/mypy/typeshed/stdlib/io.pyi @@ -8,49 +8,29 @@ from types import TracebackType from typing import IO, Any, BinaryIO, TextIO from typing_extensions import Literal +__all__ = [ + "BlockingIOError", + "open", + "IOBase", + "RawIOBase", + "FileIO", + "BytesIO", + "StringIO", + "BufferedIOBase", + "BufferedReader", + "BufferedWriter", + "BufferedRWPair", + "BufferedRandom", + "TextIOBase", + "TextIOWrapper", + "UnsupportedOperation", + "SEEK_SET", + "SEEK_CUR", + "SEEK_END", +] + if sys.version_info >= (3, 8): - __all__ = [ - "BlockingIOError", - "open", - "open_code", - "IOBase", - "RawIOBase", - "FileIO", - "BytesIO", - "StringIO", - "BufferedIOBase", - "BufferedReader", - "BufferedWriter", - "BufferedRWPair", - "BufferedRandom", - "TextIOBase", - "TextIOWrapper", - "UnsupportedOperation", - "SEEK_SET", - "SEEK_CUR", - "SEEK_END", - ] -else: - __all__ = [ - "BlockingIOError", - "open", - "IOBase", - "RawIOBase", - "FileIO", - "BytesIO", - "StringIO", - "BufferedIOBase", - "BufferedReader", - "BufferedWriter", - "BufferedRWPair", - "BufferedRandom", - "TextIOBase", - "TextIOWrapper", - "UnsupportedOperation", - "SEEK_SET", - "SEEK_CUR", - "SEEK_END", - ] + __all__ += ["open_code"] DEFAULT_BUFFER_SIZE: Literal[8192] diff --git a/mypy/typeshed/stdlib/itertools.pyi b/mypy/typeshed/stdlib/itertools.pyi index 43a0e8038d692..7299ee8200db0 100644 --- a/mypy/typeshed/stdlib/itertools.pyi +++ b/mypy/typeshed/stdlib/itertools.pyi @@ -18,7 +18,7 @@ _T4 = TypeVar("_T4") _T5 = TypeVar("_T5") _T6 = TypeVar("_T6") -_Step: TypeAlias = int | float | SupportsFloat | SupportsInt | SupportsIndex | SupportsComplex +_Step: TypeAlias = SupportsFloat | SupportsInt | SupportsIndex | SupportsComplex _Predicate: TypeAlias = Callable[[_T], object] diff --git a/mypy/typeshed/stdlib/lib2to3/pgen2/tokenize.pyi b/mypy/typeshed/stdlib/lib2to3/pgen2/tokenize.pyi index a998ad5fe49e3..34df53994c92d 100644 --- a/mypy/typeshed/stdlib/lib2to3/pgen2/tokenize.pyi +++ b/mypy/typeshed/stdlib/lib2to3/pgen2/tokenize.pyi @@ -3,149 +3,79 @@ from collections.abc import Callable, Iterable, Iterator from lib2to3.pgen2.token import * from typing_extensions import TypeAlias -if sys.version_info >= (3, 8): - __all__ = [ - "AMPER", - "AMPEREQUAL", - "ASYNC", - "AT", - "ATEQUAL", - "AWAIT", - "BACKQUOTE", - "CIRCUMFLEX", - "CIRCUMFLEXEQUAL", - "COLON", - "COLONEQUAL", - "COMMA", - "COMMENT", - "DEDENT", - "DOT", - "DOUBLESLASH", - "DOUBLESLASHEQUAL", - "DOUBLESTAR", - "DOUBLESTAREQUAL", - "ENDMARKER", - "EQEQUAL", - "EQUAL", - "ERRORTOKEN", - "GREATER", - "GREATEREQUAL", - "INDENT", - "ISEOF", - "ISNONTERMINAL", - "ISTERMINAL", - "LBRACE", - "LEFTSHIFT", - "LEFTSHIFTEQUAL", - "LESS", - "LESSEQUAL", - "LPAR", - "LSQB", - "MINEQUAL", - "MINUS", - "NAME", - "NEWLINE", - "NL", - "NOTEQUAL", - "NT_OFFSET", - "NUMBER", - "N_TOKENS", - "OP", - "PERCENT", - "PERCENTEQUAL", - "PLUS", - "PLUSEQUAL", - "RARROW", - "RBRACE", - "RIGHTSHIFT", - "RIGHTSHIFTEQUAL", - "RPAR", - "RSQB", - "SEMI", - "SLASH", - "SLASHEQUAL", - "STAR", - "STAREQUAL", - "STRING", - "TILDE", - "VBAR", - "VBAREQUAL", - "tok_name", - "tokenize", - "generate_tokens", - "untokenize", - ] -else: - __all__ = [ - "AMPER", - "AMPEREQUAL", - "ASYNC", - "AT", - "ATEQUAL", - "AWAIT", - "BACKQUOTE", - "CIRCUMFLEX", - "CIRCUMFLEXEQUAL", - "COLON", - "COMMA", - "COMMENT", - "DEDENT", - "DOT", - "DOUBLESLASH", - "DOUBLESLASHEQUAL", - "DOUBLESTAR", - "DOUBLESTAREQUAL", - "ENDMARKER", - "EQEQUAL", - "EQUAL", - "ERRORTOKEN", - "GREATER", - "GREATEREQUAL", - "INDENT", - "ISEOF", - "ISNONTERMINAL", - "ISTERMINAL", - "LBRACE", - "LEFTSHIFT", - "LEFTSHIFTEQUAL", - "LESS", - "LESSEQUAL", - "LPAR", - "LSQB", - "MINEQUAL", - "MINUS", - "NAME", - "NEWLINE", - "NL", - "NOTEQUAL", - "NT_OFFSET", - "NUMBER", - "N_TOKENS", - "OP", - "PERCENT", - "PERCENTEQUAL", - "PLUS", - "PLUSEQUAL", - "RARROW", - "RBRACE", - "RIGHTSHIFT", - "RIGHTSHIFTEQUAL", - "RPAR", - "RSQB", - "SEMI", - "SLASH", - "SLASHEQUAL", - "STAR", - "STAREQUAL", - "STRING", - "TILDE", - "VBAR", - "VBAREQUAL", - "tok_name", - "tokenize", - "generate_tokens", - "untokenize", - ] +__all__ = [ + "AMPER", + "AMPEREQUAL", + "ASYNC", + "AT", + "ATEQUAL", + "AWAIT", + "BACKQUOTE", + "CIRCUMFLEX", + "CIRCUMFLEXEQUAL", + "COLON", + "COMMA", + "COMMENT", + "DEDENT", + "DOT", + "DOUBLESLASH", + "DOUBLESLASHEQUAL", + "DOUBLESTAR", + "DOUBLESTAREQUAL", + "ENDMARKER", + "EQEQUAL", + "EQUAL", + "ERRORTOKEN", + "GREATER", + "GREATEREQUAL", + "INDENT", + "ISEOF", + "ISNONTERMINAL", + "ISTERMINAL", + "LBRACE", + "LEFTSHIFT", + "LEFTSHIFTEQUAL", + "LESS", + "LESSEQUAL", + "LPAR", + "LSQB", + "MINEQUAL", + "MINUS", + "NAME", + "NEWLINE", + "NL", + "NOTEQUAL", + "NT_OFFSET", + "NUMBER", + "N_TOKENS", + "OP", + "PERCENT", + "PERCENTEQUAL", + "PLUS", + "PLUSEQUAL", + "RARROW", + "RBRACE", + "RIGHTSHIFT", + "RIGHTSHIFTEQUAL", + "RPAR", + "RSQB", + "SEMI", + "SLASH", + "SLASHEQUAL", + "STAR", + "STAREQUAL", + "STRING", + "TILDE", + "VBAR", + "VBAREQUAL", + "tok_name", + "tokenize", + "generate_tokens", + "untokenize", +] + +if sys.version_info >= (3, 7): + __all__ += ["COLONEQUAL"] _Coord: TypeAlias = tuple[int, int] _TokenEater: TypeAlias = Callable[[int, str, _Coord, _Coord, str], None] diff --git a/mypy/typeshed/stdlib/locale.pyi b/mypy/typeshed/stdlib/locale.pyi index 959054e847a8c..393ddcbda8419 100644 --- a/mypy/typeshed/stdlib/locale.pyi +++ b/mypy/typeshed/stdlib/locale.pyi @@ -29,6 +29,9 @@ __all__ = [ "CHAR_MAX", ] +if sys.version_info >= (3, 11): + __all__ += ["getencoding"] + # This module defines a function "str()", which is why "str" can't be used # as a type annotation or type alias. from builtins import str as _str @@ -126,7 +129,7 @@ if sys.version_info >= (3, 7): else: def format_string(f: _str, val: Any, grouping: bool = ...) -> _str: ... -def currency(val: int | float | Decimal, symbol: bool = ..., grouping: bool = ..., international: bool = ...) -> _str: ... +def currency(val: float | Decimal, symbol: bool = ..., grouping: bool = ..., international: bool = ...) -> _str: ... def delocalize(string: _str) -> _str: ... def atof(string: _str, func: Callable[[_str], float] = ...) -> float: ... def atoi(string: _str) -> int: ... @@ -143,6 +146,9 @@ if sys.platform == "linux" or sys.platform == "darwin": def bindtextdomain(__domain: _str, __dir: StrPath | None) -> _str: ... def bind_textdomain_codeset(__domain: _str, __codeset: _str | None) -> _str | None: ... +if sys.version_info >= (3, 11): + def getencoding() -> _str: ... + locale_alias: dict[_str, _str] # undocumented locale_encoding_alias: dict[_str, _str] # undocumented windows_locale: dict[int, _str] # undocumented diff --git a/mypy/typeshed/stdlib/logging/__init__.pyi b/mypy/typeshed/stdlib/logging/__init__.pyi index 6ad4cd4f94e76..6a8f66871a67f 100644 --- a/mypy/typeshed/stdlib/logging/__init__.pyi +++ b/mypy/typeshed/stdlib/logging/__init__.pyi @@ -9,6 +9,9 @@ from types import FrameType, TracebackType from typing import Any, ClassVar, Generic, Pattern, TextIO, TypeVar, Union, overload from typing_extensions import Literal, TypeAlias +if sys.version_info >= (3, 11): + from types import GenericAlias + __all__ = [ "BASIC_FORMAT", "BufferingFormatter", @@ -54,6 +57,9 @@ __all__ = [ "raiseExceptions", ] +if sys.version_info >= (3, 11): + __all__ += ["getLevelNamesMapping"] + _SysExcInfoType: TypeAlias = Union[tuple[type[BaseException], BaseException, TracebackType | None], tuple[None, None, None]] _ExcInfoType: TypeAlias = None | bool | _SysExcInfoType | BaseException _ArgsType: TypeAlias = tuple[object, ...] | Mapping[str, object] @@ -407,6 +413,8 @@ class LogRecord: sinfo: str | None = ..., ) -> None: ... def getMessage(self) -> str: ... + # Allows setting contextual information on LogRecord objects as per the docs, see #7833 + def __setattr__(self, __name: str, __value: Any) -> None: ... _L = TypeVar("_L", bound=Logger | LoggerAdapter[Any]) @@ -593,6 +601,8 @@ class LoggerAdapter(Generic[_L]): ) -> None: ... # undocumented @property def name(self) -> str: ... # undocumented + if sys.version_info >= (3, 11): + def __class_getitem__(cls, item: Any) -> GenericAlias: ... def getLogger(name: str | None = ...) -> Logger: ... def getLoggerClass() -> type[Logger]: ... @@ -706,6 +716,10 @@ else: def addLevelName(level: int, levelName: str) -> None: ... def getLevelName(level: _Level) -> Any: ... + +if sys.version_info >= (3, 11): + def getLevelNamesMapping() -> dict[str, int]: ... + def makeLogRecord(dict: Mapping[str, object]) -> LogRecord: ... if sys.version_info >= (3, 9): @@ -769,6 +783,8 @@ class StreamHandler(Handler, Generic[_StreamT]): def __init__(self: StreamHandler[_StreamT], stream: _StreamT) -> None: ... if sys.version_info >= (3, 7): def setStream(self, stream: _StreamT) -> _StreamT | None: ... + if sys.version_info >= (3, 11): + def __class_getitem__(cls, item: Any) -> GenericAlias: ... class FileHandler(StreamHandler[TextIOWrapper]): baseFilename: str # undocumented @@ -818,8 +834,8 @@ class PercentStyle: # undocumented def format(self, record: Any) -> str: ... class StrFormatStyle(PercentStyle): # undocumented - fmt_spec = Any - field_spec = Any + fmt_spec: Pattern[str] + field_spec: Pattern[str] class StringTemplateStyle(PercentStyle): # undocumented _tpl: Template diff --git a/mypy/typeshed/stdlib/logging/handlers.pyi b/mypy/typeshed/stdlib/logging/handlers.pyi index 6402361490003..d3ea29075b813 100644 --- a/mypy/typeshed/stdlib/logging/handlers.pyi +++ b/mypy/typeshed/stdlib/logging/handlers.pyi @@ -181,6 +181,9 @@ class SysLogHandler(Handler): facility_names: ClassVar[dict[str, int]] # undocumented priority_map: ClassVar[dict[str, str]] # undocumented def __init__(self, address: tuple[str, int] | str = ..., facility: int = ..., socktype: SocketKind | None = ...) -> None: ... + if sys.version_info >= (3, 11): + def createSocket(self) -> None: ... + def encodePriority(self, facility: int | str, priority: int | str) -> int: ... def mapPriority(self, levelName: str) -> str: ... diff --git a/mypy/typeshed/stdlib/macpath.pyi b/mypy/typeshed/stdlib/macpath.pyi index 2512e086b735a..37821f44b2008 100644 --- a/mypy/typeshed/stdlib/macpath.pyi +++ b/mypy/typeshed/stdlib/macpath.pyi @@ -34,6 +34,41 @@ from posixpath import ( ) from typing import AnyStr, overload +__all__ = [ + "normcase", + "isabs", + "join", + "splitdrive", + "split", + "splitext", + "basename", + "dirname", + "commonprefix", + "getsize", + "getmtime", + "getatime", + "getctime", + "islink", + "exists", + "lexists", + "isdir", + "isfile", + "expanduser", + "expandvars", + "normpath", + "abspath", + "curdir", + "pardir", + "sep", + "pathsep", + "defpath", + "altsep", + "extsep", + "devnull", + "realpath", + "supports_unicode_filenames", +] + altsep: str | None @overload diff --git a/mypy/typeshed/stdlib/macurl2path.pyi b/mypy/typeshed/stdlib/macurl2path.pyi index 6aac6dfeace5f..af74b11c78504 100644 --- a/mypy/typeshed/stdlib/macurl2path.pyi +++ b/mypy/typeshed/stdlib/macurl2path.pyi @@ -1,3 +1,5 @@ +__all__ = ["url2pathname", "pathname2url"] + def url2pathname(pathname: str) -> str: ... def pathname2url(pathname: str) -> str: ... def _pncomp2url(component: str | bytes) -> str: ... diff --git a/mypy/typeshed/stdlib/mailbox.pyi b/mypy/typeshed/stdlib/mailbox.pyi index 64183cd0b3a41..3169e8cfa6897 100644 --- a/mypy/typeshed/stdlib/mailbox.pyi +++ b/mypy/typeshed/stdlib/mailbox.pyi @@ -46,9 +46,10 @@ class Mailbox(Generic[_MessageT]): _path: bytes | str # undocumented _factory: Callable[[IO[Any]], _MessageT] | None # undocumented - def __init__( - self, path: StrOrBytesPath, factory: Callable[[IO[Any]], _MessageT] | None = ..., create: bool = ... - ) -> None: ... + @overload + def __init__(self, path: StrOrBytesPath, factory: Callable[[IO[Any]], _MessageT], create: bool = ...) -> None: ... + @overload + def __init__(self, path: StrOrBytesPath, factory: None = ..., create: bool = ...) -> None: ... @abstractmethod def add(self, message: _MessageData) -> str: ... @abstractmethod diff --git a/mypy/typeshed/stdlib/mmap.pyi b/mypy/typeshed/stdlib/mmap.pyi index 96bb01a271fc7..8dbec23888387 100644 --- a/mypy/typeshed/stdlib/mmap.pyi +++ b/mypy/typeshed/stdlib/mmap.pyi @@ -79,6 +79,7 @@ if sys.version_info >= (3, 8) and sys.platform != "win32": MADV_SEQUENTIAL: int MADV_WILLNEED: int MADV_DONTNEED: int + MADV_FREE: int if sys.platform == "linux": MADV_REMOVE: int @@ -94,7 +95,6 @@ if sys.version_info >= (3, 8) and sys.platform != "win32": MADV_NOHUGEPAGE: int MADV_DONTDUMP: int MADV_DODUMP: int - MADV_FREE: int # This Values are defined for FreeBSD but type checkers do not support conditions for these if sys.platform != "linux" and sys.platform != "darwin": diff --git a/mypy/typeshed/stdlib/modulefinder.pyi b/mypy/typeshed/stdlib/modulefinder.pyi index cd01e0e1381fb..caed7efadccc3 100644 --- a/mypy/typeshed/stdlib/modulefinder.pyi +++ b/mypy/typeshed/stdlib/modulefinder.pyi @@ -3,12 +3,13 @@ from collections.abc import Container, Iterable, Iterator, Sequence from types import CodeType from typing import IO, Any -LOAD_CONST: int # undocumented -IMPORT_NAME: int # undocumented -STORE_NAME: int # undocumented -STORE_GLOBAL: int # undocumented -STORE_OPS: tuple[int, int] # undocumented -EXTENDED_ARG: int # undocumented +if sys.version_info < (3, 11): + LOAD_CONST: int # undocumented + IMPORT_NAME: int # undocumented + STORE_NAME: int # undocumented + STORE_GLOBAL: int # undocumented + STORE_OPS: tuple[int, int] # undocumented + EXTENDED_ARG: int # undocumented packagePathMap: dict[str, list[str]] # undocumented diff --git a/mypy/typeshed/stdlib/multiprocessing/__init__.pyi b/mypy/typeshed/stdlib/multiprocessing/__init__.pyi index 87ceda10573d0..41af971bc6198 100644 --- a/mypy/typeshed/stdlib/multiprocessing/__init__.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/__init__.pyi @@ -29,85 +29,47 @@ if sys.version_info >= (3, 8): if sys.platform != "win32": from multiprocessing.context import ForkContext, ForkServerContext +__all__ = [ + "Array", + "AuthenticationError", + "Barrier", + "BoundedSemaphore", + "BufferTooShort", + "Condition", + "Event", + "JoinableQueue", + "Lock", + "Manager", + "Pipe", + "Pool", + "Process", + "ProcessError", + "Queue", + "RLock", + "RawArray", + "RawValue", + "Semaphore", + "SimpleQueue", + "TimeoutError", + "Value", + "active_children", + "allow_connection_pickling", + "cpu_count", + "current_process", + "freeze_support", + "get_all_start_methods", + "get_context", + "get_logger", + "get_start_method", + "log_to_stderr", + "reducer", + "set_executable", + "set_forkserver_preload", + "set_start_method", +] + if sys.version_info >= (3, 8): - __all__ = [ - "Array", - "AuthenticationError", - "Barrier", - "BoundedSemaphore", - "BufferTooShort", - "Condition", - "Event", - "JoinableQueue", - "Lock", - "Manager", - "Pipe", - "Pool", - "Process", - "ProcessError", - "Queue", - "RLock", - "RawArray", - "RawValue", - "Semaphore", - "SimpleQueue", - "TimeoutError", - "Value", - "active_children", - "allow_connection_pickling", - "cpu_count", - "current_process", - "freeze_support", - "get_all_start_methods", - "get_context", - "get_logger", - "get_start_method", - "parent_process", - "log_to_stderr", - "reducer", - "set_executable", - "set_forkserver_preload", - "set_start_method", - ] -else: - __all__ = [ - "Array", - "AuthenticationError", - "Barrier", - "BoundedSemaphore", - "BufferTooShort", - "Condition", - "Event", - "JoinableQueue", - "Lock", - "Manager", - "Pipe", - "Pool", - "Process", - "ProcessError", - "Queue", - "RLock", - "RawArray", - "RawValue", - "Semaphore", - "SimpleQueue", - "TimeoutError", - "Value", - "active_children", - "allow_connection_pickling", - "cpu_count", - "current_process", - "freeze_support", - "get_all_start_methods", - "get_context", - "get_logger", - "get_start_method", - "log_to_stderr", - "reducer", - "set_executable", - "set_forkserver_preload", - "set_start_method", - ] + __all__ += ["parent_process"] # The following type aliases can be used to annotate the return values of # the corresponding functions. They are not defined at runtime. diff --git a/mypy/typeshed/stdlib/multiprocessing/managers.pyi b/mypy/typeshed/stdlib/multiprocessing/managers.pyi index b8d5ddda0f35e..212ffcbf5a3ab 100644 --- a/mypy/typeshed/stdlib/multiprocessing/managers.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/managers.pyi @@ -1,12 +1,11 @@ import queue import sys import threading -from _typeshed import Self -from builtins import dict as _dict, list as _list # Conflicts with method names -from collections.abc import Callable, Iterable, Mapping, Sequence +from _typeshed import Self, SupportsKeysAndGetItem, SupportsRichComparison, SupportsRichComparisonT +from collections.abc import Callable, Iterable, Iterator, Mapping, MutableMapping, MutableSequence, Sequence from types import TracebackType -from typing import Any, AnyStr, Generic, TypeVar -from typing_extensions import TypeAlias +from typing import Any, AnyStr, ClassVar, Generic, TypeVar, overload +from typing_extensions import SupportsIndex, TypeAlias from .connection import Connection from .context import BaseContext @@ -66,6 +65,62 @@ class ValueProxy(BaseProxy, Generic[_T]): if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... +class DictProxy(BaseProxy, MutableMapping[_KT, _VT]): + __builtins__: ClassVar[dict[str, Any]] + def __len__(self) -> int: ... + def __getitem__(self, __k: _KT) -> _VT: ... + def __setitem__(self, __k: _KT, __v: _VT) -> None: ... + def __delitem__(self, __v: _KT) -> None: ... + def __iter__(self) -> Iterator[_KT]: ... + def copy(self) -> dict[_KT, _VT]: ... + @overload + def get(self, __key: _KT) -> _VT | None: ... + @overload + def get(self, __key: _KT, __default: _VT | _T) -> _VT | _T: ... + @overload + def pop(self, __key: _KT) -> _VT: ... + @overload + def pop(self, __key: _KT, __default: _VT | _T) -> _VT | _T: ... + def keys(self) -> list[_KT]: ... # type: ignore[override] + def values(self) -> list[tuple[_KT, _VT]]: ... # type: ignore[override] + def items(self) -> list[_VT]: ... # type: ignore[override] + if sys.version_info < (3, 7): + def has_key(self, k: _KT) -> bool: ... + +class BaseListProxy(BaseProxy, MutableSequence[_T]): + __builtins__: ClassVar[dict[str, Any]] + def __len__(self) -> int: ... + def __add__(self, __x: list[_T]) -> list[_T]: ... + def __delitem__(self, __i: SupportsIndex | slice) -> None: ... + @overload + def __getitem__(self, __i: SupportsIndex) -> _T: ... + @overload + def __getitem__(self, __s: slice) -> list[_T]: ... + @overload + def __setitem__(self, __i: SupportsIndex, __o: _T) -> None: ... + @overload + def __setitem__(self, __s: slice, __o: Iterable[_T]) -> None: ... + def __mul__(self, __n: SupportsIndex) -> list[_T]: ... + def __rmul__(self, __n: SupportsIndex) -> list[_T]: ... + def __reversed__(self) -> Iterator[_T]: ... + def append(self, __object: _T) -> None: ... + def extend(self, __iterable: Iterable[_T]) -> None: ... + def pop(self, __index: SupportsIndex = ...) -> _T: ... + def index(self, __value: _T, __start: SupportsIndex = ..., __stop: SupportsIndex = ...) -> int: ... + def count(self, __value: _T) -> int: ... + def insert(self, __index: SupportsIndex, __object: _T) -> None: ... + def remove(self, __value: _T) -> None: ... + # Use BaseListProxy[SupportsRichComparisonT] for the first overload rather than [SupportsRichComparison] + # to work around invariance + @overload + def sort(self: BaseListProxy[SupportsRichComparisonT], *, key: None = ..., reverse: bool = ...) -> None: ... + @overload + def sort(self, *, key: Callable[[_T], SupportsRichComparison], reverse: bool = ...) -> None: ... + +class ListProxy(BaseListProxy[_T]): + def __iadd__(self: Self, __x: Iterable[_T]) -> Self: ... # type: ignore[override] + def __imul__(self: Self, __n: SupportsIndex) -> Self: ... # type: ignore[override] + # Returned by BaseManager.get_server() class Server: address: Any @@ -124,8 +179,21 @@ class SyncManager(BaseManager): def Semaphore(self, value: Any = ...) -> threading.Semaphore: ... def Array(self, typecode: Any, sequence: Sequence[_T]) -> Sequence[_T]: ... def Value(self, typecode: Any, value: _T) -> ValueProxy[_T]: ... - def dict(self, sequence: Mapping[_KT, _VT] = ...) -> _dict[_KT, _VT]: ... - def list(self, sequence: Sequence[_T] = ...) -> _list[_T]: ... + # Overloads are copied from builtins.dict.__init__ + @overload + def dict(self) -> DictProxy[Any, Any]: ... + @overload + def dict(self, **kwargs: _VT) -> DictProxy[str, _VT]: ... + @overload + def dict(self, __map: SupportsKeysAndGetItem[_KT, _VT], **kwargs: _VT) -> DictProxy[_KT, _VT]: ... + @overload + def dict(self, __iterable: Iterable[tuple[_KT, _VT]], **kwargs: _VT) -> DictProxy[_KT, _VT]: ... + @overload + def dict(self, __iterable: Iterable[list[str]]) -> DictProxy[str, str]: ... + @overload + def list(self, __sequence: Sequence[_T]) -> ListProxy[_T]: ... + @overload + def list(self) -> ListProxy[Any]: ... class RemoteError(Exception): ... diff --git a/mypy/typeshed/stdlib/multiprocessing/shared_memory.pyi b/mypy/typeshed/stdlib/multiprocessing/shared_memory.pyi index 76ccedaf478e9..3ce0ca3863cc1 100644 --- a/mypy/typeshed/stdlib/multiprocessing/shared_memory.pyi +++ b/mypy/typeshed/stdlib/multiprocessing/shared_memory.pyi @@ -1,7 +1,7 @@ import sys from _typeshed import Self from collections.abc import Iterable -from typing import Any, Generic, TypeVar +from typing import Any, Generic, TypeVar, overload if sys.version_info >= (3, 9): from types import GenericAlias @@ -23,7 +23,10 @@ class SharedMemory: class ShareableList(Generic[_SLT]): shm: SharedMemory - def __init__(self, sequence: Iterable[_SLT] | None = ..., *, name: str | None = ...) -> None: ... + @overload + def __init__(self, sequence: None = ..., *, name: str | None = ...) -> None: ... + @overload + def __init__(self, sequence: Iterable[_SLT], *, name: str | None = ...) -> None: ... def __getitem__(self, position: int) -> _SLT: ... def __setitem__(self, position: int, value: _SLT) -> None: ... def __reduce__(self: Self) -> tuple[Self, tuple[_SLT, ...]]: ... diff --git a/mypy/typeshed/stdlib/ntpath.pyi b/mypy/typeshed/stdlib/ntpath.pyi index ffe5cc1e5a2dd..78aa2346835c9 100644 --- a/mypy/typeshed/stdlib/ntpath.pyi +++ b/mypy/typeshed/stdlib/ntpath.pyi @@ -43,99 +43,62 @@ from posixpath import ( supports_unicode_filenames as supports_unicode_filenames, ) from typing import AnyStr, overload +from typing_extensions import LiteralString -if sys.version_info >= (3, 7) or sys.platform != "win32": - __all__ = [ - "normcase", - "isabs", - "join", - "splitdrive", - "split", - "splitext", - "basename", - "dirname", - "commonprefix", - "getsize", - "getmtime", - "getatime", - "getctime", - "islink", - "exists", - "lexists", - "isdir", - "isfile", - "ismount", - "expanduser", - "expandvars", - "normpath", - "abspath", - "curdir", - "pardir", - "sep", - "pathsep", - "defpath", - "altsep", - "extsep", - "devnull", - "realpath", - "supports_unicode_filenames", - "relpath", - "samefile", - "sameopenfile", - "samestat", - "commonpath", - ] -else: - __all__ = [ - "normcase", - "isabs", - "join", - "splitdrive", - "split", - "splitext", - "basename", - "dirname", - "commonprefix", - "getsize", - "getmtime", - "getatime", - "getctime", - "islink", - "exists", - "lexists", - "isdir", - "isfile", - "ismount", - "expanduser", - "expandvars", - "normpath", - "abspath", - "splitunc", - "curdir", - "pardir", - "sep", - "pathsep", - "defpath", - "altsep", - "extsep", - "devnull", - "realpath", - "supports_unicode_filenames", - "relpath", - "samefile", - "sameopenfile", - "samestat", - "commonpath", - ] +__all__ = [ + "normcase", + "isabs", + "join", + "splitdrive", + "split", + "splitext", + "basename", + "dirname", + "commonprefix", + "getsize", + "getmtime", + "getatime", + "getctime", + "islink", + "exists", + "lexists", + "isdir", + "isfile", + "ismount", + "expanduser", + "expandvars", + "normpath", + "abspath", + "curdir", + "pardir", + "sep", + "pathsep", + "defpath", + "altsep", + "extsep", + "devnull", + "realpath", + "supports_unicode_filenames", + "relpath", + "samefile", + "sameopenfile", + "samestat", + "commonpath", +] + +if sys.version_info < (3, 7): + __all__ += ["splitunc"] def splitunc(p: AnyStr) -> tuple[AnyStr, AnyStr]: ... # deprecated -altsep: str +altsep: LiteralString # First parameter is not actually pos-only, # but must be defined as pos-only in the stub or cross-platform code doesn't type-check, # as the parameter name is different in posixpath.join() @overload +def join(__path: LiteralString, *paths: LiteralString) -> LiteralString: ... +@overload def join(__path: StrPath, *paths: StrPath) -> str: ... @overload def join(__path: BytesPath, *paths: BytesPath) -> bytes: ... diff --git a/mypy/typeshed/stdlib/operator.pyi b/mypy/typeshed/stdlib/operator.pyi index 603e15ebc7bec..c3fc4b0a85037 100644 --- a/mypy/typeshed/stdlib/operator.pyi +++ b/mypy/typeshed/stdlib/operator.pyi @@ -2,121 +2,65 @@ import sys from _operator import * +__all__ = [ + "abs", + "add", + "and_", + "attrgetter", + "concat", + "contains", + "countOf", + "delitem", + "eq", + "floordiv", + "ge", + "getitem", + "gt", + "iadd", + "iand", + "iconcat", + "ifloordiv", + "ilshift", + "imatmul", + "imod", + "imul", + "index", + "indexOf", + "inv", + "invert", + "ior", + "ipow", + "irshift", + "is_", + "is_not", + "isub", + "itemgetter", + "itruediv", + "ixor", + "le", + "length_hint", + "lshift", + "lt", + "matmul", + "methodcaller", + "mod", + "mul", + "ne", + "neg", + "not_", + "or_", + "pos", + "pow", + "rshift", + "setitem", + "sub", + "truediv", + "truth", + "xor", +] + if sys.version_info >= (3, 11): - __all__ = [ - "abs", - "add", - "and_", - "attrgetter", - "call", - "concat", - "contains", - "countOf", - "delitem", - "eq", - "floordiv", - "ge", - "getitem", - "gt", - "iadd", - "iand", - "iconcat", - "ifloordiv", - "ilshift", - "imatmul", - "imod", - "imul", - "index", - "indexOf", - "inv", - "invert", - "ior", - "ipow", - "irshift", - "is_", - "is_not", - "isub", - "itemgetter", - "itruediv", - "ixor", - "le", - "length_hint", - "lshift", - "lt", - "matmul", - "methodcaller", - "mod", - "mul", - "ne", - "neg", - "not_", - "or_", - "pos", - "pow", - "rshift", - "setitem", - "sub", - "truediv", - "truth", - "xor", - ] -else: - __all__ = [ - "abs", - "add", - "and_", - "attrgetter", - "concat", - "contains", - "countOf", - "delitem", - "eq", - "floordiv", - "ge", - "getitem", - "gt", - "iadd", - "iand", - "iconcat", - "ifloordiv", - "ilshift", - "imatmul", - "imod", - "imul", - "index", - "indexOf", - "inv", - "invert", - "ior", - "ipow", - "irshift", - "is_", - "is_not", - "isub", - "itemgetter", - "itruediv", - "ixor", - "le", - "length_hint", - "lshift", - "lt", - "matmul", - "methodcaller", - "mod", - "mul", - "ne", - "neg", - "not_", - "or_", - "pos", - "pow", - "rshift", - "setitem", - "sub", - "truediv", - "truth", - "xor", - ] + __all__ += ["call"] __lt__ = lt __le__ = le diff --git a/mypy/typeshed/stdlib/optparse.pyi b/mypy/typeshed/stdlib/optparse.pyi index 1e7428f59a950..b571ff0680b7a 100644 --- a/mypy/typeshed/stdlib/optparse.pyi +++ b/mypy/typeshed/stdlib/optparse.pyi @@ -240,7 +240,10 @@ class OptionParser(OptionContainer): def get_prog_name(self) -> str: ... def get_usage(self) -> str: ... def get_version(self) -> str: ... - def parse_args(self, args: Sequence[AnyStr] | None = ..., values: Values | None = ...) -> tuple[Values, list[AnyStr]]: ... + @overload + def parse_args(self, args: None = ..., values: Values | None = ...) -> tuple[Values, list[str]]: ... + @overload + def parse_args(self, args: Sequence[AnyStr], values: Values | None = ...) -> tuple[Values, list[AnyStr]]: ... def print_usage(self, file: IO[str] | None = ...) -> None: ... def print_help(self, file: IO[str] | None = ...) -> None: ... def print_version(self, file: IO[str] | None = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/os/__init__.pyi b/mypy/typeshed/stdlib/os/__init__.pyi index 2310de701d54b..68ea2948f17e1 100644 --- a/mypy/typeshed/stdlib/os/__init__.pyi +++ b/mypy/typeshed/stdlib/os/__init__.pyi @@ -1,7 +1,9 @@ import sys from _typeshed import ( + AnyStr_co, BytesPath, FileDescriptorLike, + GenericPath, OpenBinaryMode, OpenBinaryModeReading, OpenBinaryModeUpdating, @@ -32,7 +34,6 @@ path = _path _T = TypeVar("_T") _T1 = TypeVar("_T1") _T2 = TypeVar("_T2") -_AnyStr_co = TypeVar("_AnyStr_co", str, bytes, covariant=True) # ----- os variables ----- @@ -356,9 +357,9 @@ class stat_result(structseq[float], tuple[int, int, int, int, int, int, int, flo # See https://github.com/python/typeshed/pull/6560#issuecomment-991253327 @runtime_checkable -class PathLike(Protocol[_AnyStr_co]): +class PathLike(Protocol[AnyStr_co]): @abstractmethod - def __fspath__(self) -> _AnyStr_co: ... + def __fspath__(self) -> AnyStr_co: ... @overload def listdir(path: StrPath | None = ...) -> list[str]: ... @@ -726,7 +727,7 @@ if sys.platform != "win32": def makedev(__major: int, __minor: int) -> int: ... def pathconf(path: _FdOrAnyPath, name: str | int) -> int: ... # Unix only -def readlink(path: AnyStr | PathLike[AnyStr], *, dir_fd: int | None = ...) -> AnyStr: ... +def readlink(path: GenericPath[AnyStr], *, dir_fd: int | None = ...) -> AnyStr: ... def remove(path: StrOrBytesPath, *, dir_fd: int | None = ...) -> None: ... def removedirs(name: StrOrBytesPath) -> None: ... def rename(src: StrOrBytesPath, dst: StrOrBytesPath, *, src_dir_fd: int | None = ..., dst_dir_fd: int | None = ...) -> None: ... @@ -747,7 +748,7 @@ if sys.version_info >= (3, 7): def scandir(path: int) -> _ScandirIterator[str]: ... @overload -def scandir(path: AnyStr | PathLike[AnyStr]) -> _ScandirIterator[AnyStr]: ... +def scandir(path: GenericPath[AnyStr]) -> _ScandirIterator[AnyStr]: ... def stat(path: _FdOrAnyPath, *, dir_fd: int | None = ..., follow_symlinks: bool = ...) -> stat_result: ... if sys.version_info < (3, 7): @@ -778,7 +779,7 @@ def utime( _OnError: TypeAlias = Callable[[OSError], Any] def walk( - top: AnyStr | PathLike[AnyStr], topdown: bool = ..., onerror: _OnError | None = ..., followlinks: bool = ... + top: GenericPath[AnyStr], topdown: bool = ..., onerror: _OnError | None = ..., followlinks: bool = ... ) -> Iterator[tuple[AnyStr, list[AnyStr], list[AnyStr]]]: ... if sys.platform != "win32": diff --git a/mypy/typeshed/stdlib/pdb.pyi b/mypy/typeshed/stdlib/pdb.pyi index e787b4a4c4160..3c2cabe8abe21 100644 --- a/mypy/typeshed/stdlib/pdb.pyi +++ b/mypy/typeshed/stdlib/pdb.pyi @@ -74,7 +74,9 @@ class Pdb(Bdb, Cmd): def print_stack_trace(self) -> None: ... def print_stack_entry(self, frame_lineno: tuple[FrameType, int], prompt_prefix: str = ...) -> None: ... def lookupmodule(self, filename: str) -> str | None: ... - def _runscript(self, filename: str) -> None: ... + if sys.version_info < (3, 11): + def _runscript(self, filename: str) -> None: ... + def do_commands(self, arg: str) -> bool | None: ... def do_break(self, arg: str, temporary: bool = ...) -> bool | None: ... def do_tbreak(self, arg: str) -> bool | None: ... @@ -165,7 +167,7 @@ class Pdb(Bdb, Cmd): complete_whatis = _complete_expression complete_display = _complete_expression - if sys.version_info >= (3, 7): + if sys.version_info >= (3, 7) and sys.version_info < (3, 11): def _runmodule(self, module_name: str) -> None: ... # undocumented diff --git a/mypy/typeshed/stdlib/pickle.pyi b/mypy/typeshed/stdlib/pickle.pyi index d58cf8ed9d504..088adc8196c2d 100644 --- a/mypy/typeshed/stdlib/pickle.pyi +++ b/mypy/typeshed/stdlib/pickle.pyi @@ -4,172 +4,89 @@ from collections.abc import Callable, Iterable, Iterator, Mapping from typing import Any, ClassVar, Protocol, SupportsBytes, Union from typing_extensions import SupportsIndex, TypeAlias, final +__all__ = [ + "PickleError", + "PicklingError", + "UnpicklingError", + "Pickler", + "Unpickler", + "dump", + "dumps", + "load", + "loads", + "ADDITEMS", + "APPEND", + "APPENDS", + "BINBYTES", + "BINBYTES8", + "BINFLOAT", + "BINGET", + "BININT", + "BININT1", + "BININT2", + "BINPERSID", + "BINPUT", + "BINSTRING", + "BINUNICODE", + "BINUNICODE8", + "BUILD", + "DEFAULT_PROTOCOL", + "DICT", + "DUP", + "EMPTY_DICT", + "EMPTY_LIST", + "EMPTY_SET", + "EMPTY_TUPLE", + "EXT1", + "EXT2", + "EXT4", + "FALSE", + "FLOAT", + "FRAME", + "FROZENSET", + "GET", + "GLOBAL", + "HIGHEST_PROTOCOL", + "INST", + "INT", + "LIST", + "LONG", + "LONG1", + "LONG4", + "LONG_BINGET", + "LONG_BINPUT", + "MARK", + "MEMOIZE", + "NEWFALSE", + "NEWOBJ", + "NEWOBJ_EX", + "NEWTRUE", + "NONE", + "OBJ", + "PERSID", + "POP", + "POP_MARK", + "PROTO", + "PUT", + "REDUCE", + "SETITEM", + "SETITEMS", + "SHORT_BINBYTES", + "SHORT_BINSTRING", + "SHORT_BINUNICODE", + "STACK_GLOBAL", + "STOP", + "STRING", + "TRUE", + "TUPLE", + "TUPLE1", + "TUPLE2", + "TUPLE3", + "UNICODE", +] + if sys.version_info >= (3, 8): - __all__ = [ - "PickleError", - "PicklingError", - "UnpicklingError", - "Pickler", - "Unpickler", - "dump", - "dumps", - "load", - "loads", - "PickleBuffer", - "ADDITEMS", - "APPEND", - "APPENDS", - "BINBYTES", - "BINBYTES8", - "BINFLOAT", - "BINGET", - "BININT", - "BININT1", - "BININT2", - "BINPERSID", - "BINPUT", - "BINSTRING", - "BINUNICODE", - "BINUNICODE8", - "BUILD", - "BYTEARRAY8", - "DEFAULT_PROTOCOL", - "DICT", - "DUP", - "EMPTY_DICT", - "EMPTY_LIST", - "EMPTY_SET", - "EMPTY_TUPLE", - "EXT1", - "EXT2", - "EXT4", - "FALSE", - "FLOAT", - "FRAME", - "FROZENSET", - "GET", - "GLOBAL", - "HIGHEST_PROTOCOL", - "INST", - "INT", - "LIST", - "LONG", - "LONG1", - "LONG4", - "LONG_BINGET", - "LONG_BINPUT", - "MARK", - "MEMOIZE", - "NEWFALSE", - "NEWOBJ", - "NEWOBJ_EX", - "NEWTRUE", - "NEXT_BUFFER", - "NONE", - "OBJ", - "PERSID", - "POP", - "POP_MARK", - "PROTO", - "PUT", - "READONLY_BUFFER", - "REDUCE", - "SETITEM", - "SETITEMS", - "SHORT_BINBYTES", - "SHORT_BINSTRING", - "SHORT_BINUNICODE", - "STACK_GLOBAL", - "STOP", - "STRING", - "TRUE", - "TUPLE", - "TUPLE1", - "TUPLE2", - "TUPLE3", - "UNICODE", - ] -else: - __all__ = [ - "PickleError", - "PicklingError", - "UnpicklingError", - "Pickler", - "Unpickler", - "dump", - "dumps", - "load", - "loads", - "ADDITEMS", - "APPEND", - "APPENDS", - "BINBYTES", - "BINBYTES8", - "BINFLOAT", - "BINGET", - "BININT", - "BININT1", - "BININT2", - "BINPERSID", - "BINPUT", - "BINSTRING", - "BINUNICODE", - "BINUNICODE8", - "BUILD", - "DEFAULT_PROTOCOL", - "DICT", - "DUP", - "EMPTY_DICT", - "EMPTY_LIST", - "EMPTY_SET", - "EMPTY_TUPLE", - "EXT1", - "EXT2", - "EXT4", - "FALSE", - "FLOAT", - "FRAME", - "FROZENSET", - "GET", - "GLOBAL", - "HIGHEST_PROTOCOL", - "INST", - "INT", - "LIST", - "LONG", - "LONG1", - "LONG4", - "LONG_BINGET", - "LONG_BINPUT", - "MARK", - "MEMOIZE", - "NEWFALSE", - "NEWOBJ", - "NEWOBJ_EX", - "NEWTRUE", - "NONE", - "OBJ", - "PERSID", - "POP", - "POP_MARK", - "PROTO", - "PUT", - "REDUCE", - "SETITEM", - "SETITEMS", - "SHORT_BINBYTES", - "SHORT_BINSTRING", - "SHORT_BINUNICODE", - "STACK_GLOBAL", - "STOP", - "STRING", - "TRUE", - "TUPLE", - "TUPLE1", - "TUPLE2", - "TUPLE3", - "UNICODE", - ] + __all__ += ["BYTEARRAY8", "NEXT_BUFFER", "PickleBuffer", "READONLY_BUFFER"] HIGHEST_PROTOCOL: int DEFAULT_PROTOCOL: int diff --git a/mypy/typeshed/stdlib/posixpath.pyi b/mypy/typeshed/stdlib/posixpath.pyi index 4cec7c770ea3b..8d880a072dfb6 100644 --- a/mypy/typeshed/stdlib/posixpath.pyi +++ b/mypy/typeshed/stdlib/posixpath.pyi @@ -1,5 +1,5 @@ import sys -from _typeshed import BytesPath, StrOrBytesPath, StrPath +from _typeshed import AnyOrLiteralStr, BytesPath, StrOrBytesPath, StrPath from collections.abc import Sequence from genericpath import ( commonprefix as commonprefix, @@ -16,6 +16,7 @@ from genericpath import ( ) from os import PathLike from typing import AnyStr, overload +from typing_extensions import LiteralString __all__ = [ "normcase", @@ -60,14 +61,14 @@ __all__ = [ supports_unicode_filenames: bool # aliases (also in os) -curdir: str -pardir: str -sep: str -altsep: str | None -extsep: str -pathsep: str -defpath: str -devnull: str +curdir: LiteralString +pardir: LiteralString +sep: LiteralString +altsep: LiteralString | None +extsep: LiteralString +pathsep: LiteralString +defpath: LiteralString +devnull: LiteralString # Overloads are necessary to work around python/mypy#3644. @overload @@ -77,11 +78,11 @@ def abspath(path: AnyStr) -> AnyStr: ... @overload def basename(p: PathLike[AnyStr]) -> AnyStr: ... @overload -def basename(p: AnyStr) -> AnyStr: ... +def basename(p: AnyOrLiteralStr) -> AnyOrLiteralStr: ... @overload def dirname(p: PathLike[AnyStr]) -> AnyStr: ... @overload -def dirname(p: AnyStr) -> AnyStr: ... +def dirname(p: AnyOrLiteralStr) -> AnyOrLiteralStr: ... @overload def expanduser(path: PathLike[AnyStr]) -> AnyStr: ... @overload @@ -93,11 +94,13 @@ def expandvars(path: AnyStr) -> AnyStr: ... @overload def normcase(s: PathLike[AnyStr]) -> AnyStr: ... @overload -def normcase(s: AnyStr) -> AnyStr: ... +def normcase(s: AnyOrLiteralStr) -> AnyOrLiteralStr: ... @overload def normpath(path: PathLike[AnyStr]) -> AnyStr: ... @overload -def normpath(path: AnyStr) -> AnyStr: ... +def normpath(path: AnyOrLiteralStr) -> AnyOrLiteralStr: ... +@overload +def commonpath(paths: Sequence[LiteralString]) -> LiteralString: ... @overload def commonpath(paths: Sequence[StrPath]) -> str: ... @overload @@ -107,6 +110,8 @@ def commonpath(paths: Sequence[BytesPath]) -> bytes: ... # but must be defined as pos-only in the stub or cross-platform code doesn't type-check, # as the parameter name is different in ntpath.join() @overload +def join(__a: LiteralString, *paths: LiteralString) -> LiteralString: ... +@overload def join(__a: StrPath, *paths: StrPath) -> str: ... @overload def join(__a: BytesPath, *paths: BytesPath) -> bytes: ... @@ -123,6 +128,8 @@ else: @overload def realpath(filename: AnyStr) -> AnyStr: ... +@overload +def relpath(path: LiteralString, start: LiteralString | None = ...) -> LiteralString: ... @overload def relpath(path: BytesPath, start: BytesPath | None = ...) -> bytes: ... @overload @@ -130,15 +137,15 @@ def relpath(path: StrPath, start: StrPath | None = ...) -> str: ... @overload def split(p: PathLike[AnyStr]) -> tuple[AnyStr, AnyStr]: ... @overload -def split(p: AnyStr) -> tuple[AnyStr, AnyStr]: ... +def split(p: AnyOrLiteralStr) -> tuple[AnyOrLiteralStr, AnyOrLiteralStr]: ... @overload def splitdrive(p: PathLike[AnyStr]) -> tuple[AnyStr, AnyStr]: ... @overload -def splitdrive(p: AnyStr) -> tuple[AnyStr, AnyStr]: ... +def splitdrive(p: AnyOrLiteralStr) -> tuple[AnyOrLiteralStr, AnyOrLiteralStr]: ... @overload def splitext(p: PathLike[AnyStr]) -> tuple[AnyStr, AnyStr]: ... @overload -def splitext(p: AnyStr) -> tuple[AnyStr, AnyStr]: ... +def splitext(p: AnyOrLiteralStr) -> tuple[AnyOrLiteralStr, AnyOrLiteralStr]: ... def isabs(s: StrOrBytesPath) -> bool: ... def islink(path: StrOrBytesPath | int) -> bool: ... def ismount(path: StrOrBytesPath | int) -> bool: ... diff --git a/mypy/typeshed/stdlib/pydoc.pyi b/mypy/typeshed/stdlib/pydoc.pyi index 6e5d3e818f838..6ea4a74a9d289 100644 --- a/mypy/typeshed/stdlib/pydoc.pyi +++ b/mypy/typeshed/stdlib/pydoc.pyi @@ -1,3 +1,4 @@ +import sys from _typeshed import OptExcInfo, SupportsWrite from abc import abstractmethod from builtins import list as _list # "list" conflicts with method name @@ -78,21 +79,36 @@ class HTMLDoc(Doc): repr = _repr_instance.repr escape = _repr_instance.escape def page(self, title: str, contents: str) -> str: ... - def heading(self, title: str, fgcol: str, bgcol: str, extras: str = ...) -> str: ... - def section( - self, - title: str, - fgcol: str, - bgcol: str, - contents: str, - width: int = ..., - prelude: str = ..., - marginalia: str | None = ..., - gap: str = ..., - ) -> str: ... + if sys.version_info >= (3, 11): + def heading(self, title: str, extras: str = ...) -> str: ... + def section( + self, + title: str, + cls: str, + contents: str, + width: int = ..., + prelude: str = ..., + marginalia: str | None = ..., + gap: str = ..., + ) -> str: ... + def multicolumn(self, list: list[_T], format: Callable[[_T], str]) -> str: ... + else: + def heading(self, title: str, fgcol: str, bgcol: str, extras: str = ...) -> str: ... + def section( + self, + title: str, + fgcol: str, + bgcol: str, + contents: str, + width: int = ..., + prelude: str = ..., + marginalia: str | None = ..., + gap: str = ..., + ) -> str: ... + def multicolumn(self, list: list[_T], format: Callable[[_T], str], cols: int = ...) -> str: ... + def bigsection(self, title: str, *args: Any) -> str: ... def preformat(self, text: str) -> str: ... - def multicolumn(self, list: list[_T], format: Callable[[_T], str], cols: int = ...) -> str: ... def grey(self, text: str) -> str: ... def namelink(self, name: str, *dicts: MutableMapping[str, str]) -> str: ... def classlink(self, object: object, modname: str) -> str: ... diff --git a/mypy/typeshed/stdlib/pyexpat/__init__.pyi b/mypy/typeshed/stdlib/pyexpat/__init__.pyi index 2fe76a3d61b6f..6a4ed891fe104 100644 --- a/mypy/typeshed/stdlib/pyexpat/__init__.pyi +++ b/mypy/typeshed/stdlib/pyexpat/__init__.pyi @@ -33,6 +33,8 @@ class XMLParserType: def ExternalEntityParserCreate(self, __context: str | None, __encoding: str = ...) -> XMLParserType: ... def SetParamEntityParsing(self, __flag: int) -> int: ... def UseForeignDTD(self, __flag: bool = ...) -> None: ... + @property + def intern(self) -> dict[str, str]: ... buffer_size: int buffer_text: bool buffer_used: int @@ -69,6 +71,7 @@ class XMLParserType: DefaultHandlerExpand: Callable[[str], Any] | None NotStandaloneHandler: Callable[[], int] | None ExternalEntityRefHandler: Callable[[str, str | None, str | None, str | None], int] | None + SkippedEntityHandler: Callable[[str, bool], Any] | None def ErrorString(__code: int) -> str: ... diff --git a/mypy/typeshed/stdlib/pyexpat/errors.pyi b/mypy/typeshed/stdlib/pyexpat/errors.pyi index 61826e12da007..2e512eb129891 100644 --- a/mypy/typeshed/stdlib/pyexpat/errors.pyi +++ b/mypy/typeshed/stdlib/pyexpat/errors.pyi @@ -1,3 +1,5 @@ +import sys + codes: dict[str, int] messages: dict[int, str] @@ -38,3 +40,10 @@ XML_ERROR_UNDEFINED_ENTITY: str XML_ERROR_UNEXPECTED_STATE: str XML_ERROR_UNKNOWN_ENCODING: str XML_ERROR_XML_DECL: str +if sys.version_info >= (3, 11): + XML_ERROR_RESERVED_PREFIX_XML: str + XML_ERROR_RESERVED_PREFIX_XMLNS: str + XML_ERROR_RESERVED_NAMESPACE_URI: str + XML_ERROR_INVALID_ARGUMENT: str + XML_ERROR_NO_BUFFER: str + XML_ERROR_AMPLIFICATION_LIMIT_BREACH: str diff --git a/mypy/typeshed/stdlib/random.pyi b/mypy/typeshed/stdlib/random.pyi index 255436dc377d8..3bb999bfaaa66 100644 --- a/mypy/typeshed/stdlib/random.pyi +++ b/mypy/typeshed/stdlib/random.pyi @@ -5,61 +5,35 @@ from collections.abc import Callable, Iterable, MutableSequence, Sequence, Set a from fractions import Fraction from typing import Any, ClassVar, NoReturn, TypeVar +__all__ = [ + "Random", + "seed", + "random", + "uniform", + "randint", + "choice", + "sample", + "randrange", + "shuffle", + "normalvariate", + "lognormvariate", + "expovariate", + "vonmisesvariate", + "gammavariate", + "triangular", + "gauss", + "betavariate", + "paretovariate", + "weibullvariate", + "getstate", + "setstate", + "getrandbits", + "choices", + "SystemRandom", +] + if sys.version_info >= (3, 9): - __all__ = [ - "Random", - "SystemRandom", - "betavariate", - "choice", - "choices", - "expovariate", - "gammavariate", - "gauss", - "getrandbits", - "getstate", - "lognormvariate", - "normalvariate", - "paretovariate", - "randbytes", - "randint", - "random", - "randrange", - "sample", - "seed", - "setstate", - "shuffle", - "triangular", - "uniform", - "vonmisesvariate", - "weibullvariate", - ] -else: - __all__ = [ - "Random", - "seed", - "random", - "uniform", - "randint", - "choice", - "sample", - "randrange", - "shuffle", - "normalvariate", - "lognormvariate", - "expovariate", - "vonmisesvariate", - "gammavariate", - "triangular", - "gauss", - "betavariate", - "paretovariate", - "weibullvariate", - "getstate", - "setstate", - "getrandbits", - "choices", - "SystemRandom", - ] + __all__ += ["randbytes"] _T = TypeVar("_T") @@ -67,8 +41,10 @@ class Random(_random.Random): VERSION: ClassVar[int] def __init__(self, x: Any = ...) -> None: ... # Using other `seed` types is deprecated since 3.9 and removed in 3.11 + # Ignore Y041, since random.seed doesn't treat int like a float subtype. Having an explicit + # int better documents conventional usage of random.seed. if sys.version_info >= (3, 9): - def seed(self, a: int | float | str | bytes | bytearray | None = ..., version: int = ...) -> None: ... # type: ignore[override] + def seed(self, a: int | float | str | bytes | bytearray | None = ..., version: int = ...) -> None: ... # type: ignore[override] # noqa: Y041 else: def seed(self, a: Any = ..., version: int = ...) -> None: ... diff --git a/mypy/typeshed/stdlib/re.pyi b/mypy/typeshed/stdlib/re.pyi index 2f4f3a3a0ed40..bdabf32d895ef 100644 --- a/mypy/typeshed/stdlib/re.pyi +++ b/mypy/typeshed/stdlib/re.pyi @@ -13,102 +13,41 @@ if sys.version_info >= (3, 7): else: from typing import Match, Pattern +__all__ = [ + "match", + "fullmatch", + "search", + "sub", + "subn", + "split", + "findall", + "finditer", + "compile", + "purge", + "template", + "escape", + "error", + "A", + "I", + "L", + "M", + "S", + "X", + "U", + "ASCII", + "IGNORECASE", + "LOCALE", + "MULTILINE", + "DOTALL", + "VERBOSE", + "UNICODE", +] + +if sys.version_info >= (3, 7): + __all__ += ["Match", "Pattern"] + if sys.version_info >= (3, 11): - __all__ = [ - "match", - "fullmatch", - "search", - "sub", - "subn", - "split", - "findall", - "finditer", - "compile", - "purge", - "template", - "escape", - "error", - "Pattern", - "Match", - "A", - "I", - "L", - "M", - "S", - "X", - "U", - "ASCII", - "IGNORECASE", - "LOCALE", - "MULTILINE", - "DOTALL", - "VERBOSE", - "UNICODE", - "RegexFlag", - "NOFLAG", - ] -elif sys.version_info >= (3, 8): - __all__ = [ - "match", - "fullmatch", - "search", - "sub", - "subn", - "split", - "findall", - "finditer", - "compile", - "purge", - "template", - "escape", - "error", - "Pattern", - "Match", - "A", - "I", - "L", - "M", - "S", - "X", - "U", - "ASCII", - "IGNORECASE", - "LOCALE", - "MULTILINE", - "DOTALL", - "VERBOSE", - "UNICODE", - ] -else: - __all__ = [ - "match", - "fullmatch", - "search", - "sub", - "subn", - "split", - "findall", - "finditer", - "compile", - "purge", - "template", - "escape", - "error", - "A", - "I", - "L", - "M", - "S", - "X", - "U", - "ASCII", - "IGNORECASE", - "LOCALE", - "MULTILINE", - "DOTALL", - "VERBOSE", - "UNICODE", - ] + __all__ += ["NOFLAG", "RegexFlag"] class RegexFlag(enum.IntFlag): A = sre_compile.SRE_FLAG_ASCII diff --git a/mypy/typeshed/stdlib/shutil.pyi b/mypy/typeshed/stdlib/shutil.pyi index b367a46fe5722..ae62ea4b658ff 100644 --- a/mypy/typeshed/stdlib/shutil.pyi +++ b/mypy/typeshed/stdlib/shutil.pyi @@ -82,7 +82,17 @@ else: ignore_dangling_symlinks: bool = ..., ) -> _PathReturn: ... -def rmtree(path: StrOrBytesPath, ignore_errors: bool = ..., onerror: Callable[[Any, Any, Any], Any] | None = ...) -> None: ... +if sys.version_info >= (3, 11): + def rmtree( + path: StrOrBytesPath, + ignore_errors: bool = ..., + onerror: Callable[[Any, Any, Any], Any] | None = ..., + *, + dir_fd: int | None = ..., + ) -> None: ... + +else: + def rmtree(path: StrOrBytesPath, ignore_errors: bool = ..., onerror: Callable[[Any, Any, Any], Any] | None = ...) -> None: ... _CopyFn: TypeAlias = Callable[[str, str], None] | Callable[[StrPath, StrPath], None] diff --git a/mypy/typeshed/stdlib/smtplib.pyi b/mypy/typeshed/stdlib/smtplib.pyi index d90c744c504ac..65a85627b6421 100644 --- a/mypy/typeshed/stdlib/smtplib.pyi +++ b/mypy/typeshed/stdlib/smtplib.pyi @@ -8,39 +8,24 @@ from types import TracebackType from typing import Any, Pattern, Protocol, overload from typing_extensions import TypeAlias +__all__ = [ + "SMTPException", + "SMTPServerDisconnected", + "SMTPResponseException", + "SMTPSenderRefused", + "SMTPRecipientsRefused", + "SMTPDataError", + "SMTPConnectError", + "SMTPHeloError", + "SMTPAuthenticationError", + "quoteaddr", + "quotedata", + "SMTP", + "SMTP_SSL", +] + if sys.version_info >= (3, 7): - __all__ = [ - "SMTPException", - "SMTPNotSupportedError", - "SMTPServerDisconnected", - "SMTPResponseException", - "SMTPSenderRefused", - "SMTPRecipientsRefused", - "SMTPDataError", - "SMTPConnectError", - "SMTPHeloError", - "SMTPAuthenticationError", - "quoteaddr", - "quotedata", - "SMTP", - "SMTP_SSL", - ] -else: - __all__ = [ - "SMTPException", - "SMTPServerDisconnected", - "SMTPResponseException", - "SMTPSenderRefused", - "SMTPRecipientsRefused", - "SMTPDataError", - "SMTPConnectError", - "SMTPHeloError", - "SMTPAuthenticationError", - "quoteaddr", - "quotedata", - "SMTP", - "SMTP_SSL", - ] + __all__ += ["SMTPNotSupportedError"] _Reply: TypeAlias = tuple[int, bytes] _SendErrs: TypeAlias = dict[str, _Reply] diff --git a/mypy/typeshed/stdlib/socket.pyi b/mypy/typeshed/stdlib/socket.pyi index 4f8ec07ccc955..d84fd66b87cfd 100644 --- a/mypy/typeshed/stdlib/socket.pyi +++ b/mypy/typeshed/stdlib/socket.pyi @@ -2,8 +2,8 @@ import sys from _typeshed import ReadableBuffer, Self, WriteableBuffer from collections.abc import Iterable from enum import IntEnum, IntFlag -from io import RawIOBase -from typing import Any, BinaryIO, TextIO, overload +from io import BufferedReader, BufferedRWPair, BufferedWriter, IOBase, RawIOBase, TextIOWrapper +from typing import Any, Protocol, overload from typing_extensions import Literal # Ideally, we'd just do "from _socket import *". Unfortunately, socket @@ -538,6 +538,16 @@ AI_V4MAPPED_CFG: AddressInfo if sys.platform == "win32": errorTab: dict[int, str] # undocumented +class _SendableFile(Protocol): + def read(self, __size: int) -> bytes: ... + def seek(self, __offset: int) -> object: ... + + # optional fields: + # + # @property + # def mode(self) -> str: ... + # def fileno(self) -> int: ... + class socket(_socket.socket): def __init__( self, family: AddressFamily | int = ..., type: SocketKind | int = ..., proto: int = ..., fileno: int | None = ... @@ -549,26 +559,66 @@ class socket(_socket.socket): # Note that the makefile's documented windows-specific behavior is not represented # mode strings with duplicates are intentionally excluded @overload + def makefile( # type: ignore[misc] + self, + mode: Literal["b", "rb", "br", "wb", "bw", "rwb", "rbw", "wrb", "wbr", "brw", "bwr"], + buffering: Literal[0], + *, + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., + ) -> SocketIO: ... + @overload def makefile( self, - mode: Literal["r", "w", "rw", "wr", ""] = ..., - buffering: int | None = ..., + mode: Literal["rwb", "rbw", "wrb", "wbr", "brw", "bwr"], + buffering: Literal[-1, 1] | None = ..., *, encoding: str | None = ..., errors: str | None = ..., newline: str | None = ..., - ) -> TextIO: ... + ) -> BufferedRWPair: ... + @overload + def makefile( + self, + mode: Literal["rb", "br"], + buffering: Literal[-1, 1] | None = ..., + *, + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., + ) -> BufferedReader: ... + @overload + def makefile( + self, + mode: Literal["wb", "bw"], + buffering: Literal[-1, 1] | None = ..., + *, + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., + ) -> BufferedWriter: ... @overload def makefile( self, mode: Literal["b", "rb", "br", "wb", "bw", "rwb", "rbw", "wrb", "wbr", "brw", "bwr"], + buffering: int, + *, + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., + ) -> IOBase: ... + @overload + def makefile( + self, + mode: Literal["r", "w", "rw", "wr", ""] = ..., buffering: int | None = ..., *, encoding: str | None = ..., errors: str | None = ..., newline: str | None = ..., - ) -> BinaryIO: ... - def sendfile(self, file: BinaryIO, offset: int = ..., count: int | None = ...) -> int: ... + ) -> TextIOWrapper: ... + def sendfile(self, file: _SendableFile, offset: int = ..., count: int | None = ...) -> int: ... @property def family(self) -> AddressFamily: ... # type: ignore[override] @property diff --git a/mypy/typeshed/stdlib/socketserver.pyi b/mypy/typeshed/stdlib/socketserver.pyi index 20ff5daa718ea..8e2a24e7edfdd 100644 --- a/mypy/typeshed/stdlib/socketserver.pyi +++ b/mypy/typeshed/stdlib/socketserver.pyi @@ -6,36 +6,26 @@ from socket import socket as _socket from typing import Any, BinaryIO, ClassVar, Union from typing_extensions import TypeAlias -if sys.platform == "win32": - __all__ = [ - "BaseServer", - "TCPServer", - "UDPServer", - "ThreadingUDPServer", - "ThreadingTCPServer", - "BaseRequestHandler", - "StreamRequestHandler", - "DatagramRequestHandler", - "ThreadingMixIn", - ] -else: - __all__ = [ - "BaseServer", - "TCPServer", - "UDPServer", - "ThreadingUDPServer", - "ThreadingTCPServer", - "BaseRequestHandler", - "StreamRequestHandler", - "DatagramRequestHandler", - "ThreadingMixIn", - "ForkingUDPServer", - "ForkingTCPServer", +__all__ = [ + "BaseServer", + "TCPServer", + "UDPServer", + "ThreadingUDPServer", + "ThreadingTCPServer", + "BaseRequestHandler", + "StreamRequestHandler", + "DatagramRequestHandler", + "ThreadingMixIn", +] +if sys.platform != "win32": + __all__ += [ "ForkingMixIn", - "UnixStreamServer", - "UnixDatagramServer", - "ThreadingUnixStreamServer", + "ForkingTCPServer", + "ForkingUDPServer", "ThreadingUnixDatagramServer", + "ThreadingUnixStreamServer", + "UnixDatagramServer", + "UnixStreamServer", ] _RequestType: TypeAlias = Union[_socket, tuple[bytes, _socket]] @@ -91,6 +81,8 @@ class TCPServer(BaseServer): def get_request(self) -> tuple[_socket, Any]: ... class UDPServer(BaseServer): + if sys.version_info >= (3, 11): + allow_reuse_port: bool max_packet_size: ClassVar[int] def get_request(self) -> tuple[tuple[bytes, _socket], Any]: ... diff --git a/mypy/typeshed/stdlib/sqlite3/dbapi2.pyi b/mypy/typeshed/stdlib/sqlite3/dbapi2.pyi index dc00a3971b0fd..6db4a9294755d 100644 --- a/mypy/typeshed/stdlib/sqlite3/dbapi2.pyi +++ b/mypy/typeshed/stdlib/sqlite3/dbapi2.pyi @@ -4,11 +4,10 @@ from _typeshed import ReadableBuffer, Self, StrOrBytesPath, SupportsLenAndGetIte from collections.abc import Callable, Generator, Iterable, Iterator, Mapping from datetime import date, datetime, time from types import TracebackType -from typing import Any, Generic, Protocol, TypeVar, overload +from typing import Any, Protocol, TypeVar, overload from typing_extensions import Literal, SupportsIndex, TypeAlias, final _T = TypeVar("_T") -_T_co = TypeVar("_T_co", covariant=True) _CursorT = TypeVar("_CursorT", bound=Cursor) _SqliteData: TypeAlias = str | ReadableBuffer | int | float | None # Data that is passed through adapters can be of any type accepted by an adapter. @@ -379,7 +378,7 @@ class Cursor(Iterator[Any]): def description(self) -> tuple[tuple[str, None, None, None, None, None, None], ...] | Any: ... @property def lastrowid(self) -> int | None: ... - row_factory: Callable[[Cursor, Row[Any]], object] | None + row_factory: Callable[[Cursor, Row], object] | None @property def rowcount(self) -> int: ... def __init__(self, __cursor: Connection) -> None: ... @@ -420,15 +419,15 @@ class PrepareProtocol: class ProgrammingError(DatabaseError): ... -class Row(Generic[_T_co]): - def __init__(self, __cursor: Cursor, __data: tuple[_T_co, ...]) -> None: ... +class Row: + def __init__(self, __cursor: Cursor, __data: tuple[Any, ...]) -> None: ... def keys(self) -> list[str]: ... @overload - def __getitem__(self, __index: int | str) -> _T_co: ... + def __getitem__(self, __index: int | str) -> Any: ... @overload - def __getitem__(self, __index: slice) -> tuple[_T_co, ...]: ... + def __getitem__(self, __index: slice) -> tuple[Any, ...]: ... def __hash__(self) -> int: ... - def __iter__(self) -> Iterator[_T_co]: ... + def __iter__(self) -> Iterator[Any]: ... def __len__(self) -> int: ... # These return NotImplemented for anything that is not a Row. def __eq__(self, __other: object) -> bool: ... @@ -451,13 +450,14 @@ else: class Warning(Exception): ... if sys.version_info >= (3, 11): + @final class Blob: def close(self) -> None: ... def read(self, __length: int = ...) -> bytes: ... def write(self, __data: bytes) -> None: ... def tell(self) -> int: ... # whence must be one of os.SEEK_SET, os.SEEK_CUR, os.SEEK_END - def seek(self, __offset: int, __whence: int = ...) -> None: ... + def seek(self, __offset: int, __origin: int = ...) -> None: ... def __len__(self) -> int: ... def __enter__(self: Self) -> Self: ... def __exit__(self, __typ: object, __val: object, __tb: object) -> Literal[False]: ... diff --git a/mypy/typeshed/stdlib/sre_constants.pyi b/mypy/typeshed/stdlib/sre_constants.pyi index 00644994fe3ef..20a8437ed0073 100644 --- a/mypy/typeshed/stdlib/sre_constants.pyi +++ b/mypy/typeshed/stdlib/sre_constants.pyi @@ -55,7 +55,8 @@ ASSERT: _NamedIntConstant ASSERT_NOT: _NamedIntConstant AT: _NamedIntConstant BRANCH: _NamedIntConstant -CALL: _NamedIntConstant +if sys.version_info < (3, 11): + CALL: _NamedIntConstant CATEGORY: _NamedIntConstant CHARSET: _NamedIntConstant BIGCHARSET: _NamedIntConstant diff --git a/mypy/typeshed/stdlib/sre_parse.pyi b/mypy/typeshed/stdlib/sre_parse.pyi index 0958e73f5176e..1e903028ba7e5 100644 --- a/mypy/typeshed/stdlib/sre_parse.pyi +++ b/mypy/typeshed/stdlib/sre_parse.pyi @@ -19,7 +19,8 @@ if sys.version_info >= (3, 7): TYPE_FLAGS: int GLOBAL_FLAGS: int -class Verbose(Exception): ... +if sys.version_info < (3, 11): + class Verbose(Exception): ... class _State: flags: int @@ -64,7 +65,7 @@ class SubPattern: def __setitem__(self, index: int | slice, code: _CodeType) -> None: ... def insert(self, index: int, code: _CodeType) -> None: ... def append(self, code: _CodeType) -> None: ... - def getwidth(self) -> int: ... + def getwidth(self) -> tuple[int, int]: ... class Tokenizer: istext: bool @@ -87,6 +88,9 @@ class Tokenizer: def seek(self, index: int) -> None: ... def error(self, msg: str, offset: int = ...) -> _Error: ... + if sys.version_info >= (3, 11): + def checkgroupname(self, name: str, offset: int, nested: int) -> None: ... + def fix_flags(src: str | bytes, flags: int) -> int: ... _TemplateType: TypeAlias = tuple[list[tuple[int, int]], list[str | None]] diff --git a/mypy/typeshed/stdlib/ssl.pyi b/mypy/typeshed/stdlib/ssl.pyi index 8445435fa3465..9f0420029258b 100644 --- a/mypy/typeshed/stdlib/ssl.pyi +++ b/mypy/typeshed/stdlib/ssl.pyi @@ -412,7 +412,12 @@ class SSLContext: def load_verify_locations( self, cafile: StrOrBytesPath | None = ..., capath: StrOrBytesPath | None = ..., cadata: str | bytes | None = ... ) -> None: ... - def get_ca_certs(self, binary_form: bool = ...) -> list[_PeerCertRetDictType] | list[bytes]: ... + @overload + def get_ca_certs(self, binary_form: Literal[False] = ...) -> list[_PeerCertRetDictType]: ... + @overload + def get_ca_certs(self, binary_form: Literal[True]) -> list[bytes]: ... + @overload + def get_ca_certs(self, binary_form: bool = ...) -> Any: ... def get_ciphers(self) -> list[_Cipher]: ... def set_default_verify_paths(self) -> None: ... def set_ciphers(self, __cipherlist: str) -> None: ... diff --git a/mypy/typeshed/stdlib/statistics.pyi b/mypy/typeshed/stdlib/statistics.pyi index e6c3d8f35bc63..58e7fd909f1fe 100644 --- a/mypy/typeshed/stdlib/statistics.pyi +++ b/mypy/typeshed/stdlib/statistics.pyi @@ -6,64 +6,26 @@ from fractions import Fraction from typing import Any, NamedTuple, SupportsFloat, TypeVar from typing_extensions import Literal, TypeAlias +__all__ = [ + "StatisticsError", + "pstdev", + "pvariance", + "stdev", + "variance", + "median", + "median_low", + "median_high", + "median_grouped", + "mean", + "mode", + "harmonic_mean", +] + +if sys.version_info >= (3, 8): + __all__ += ["geometric_mean", "multimode", "NormalDist", "fmean", "quantiles"] + if sys.version_info >= (3, 10): - __all__ = [ - "NormalDist", - "StatisticsError", - "correlation", - "covariance", - "fmean", - "geometric_mean", - "harmonic_mean", - "linear_regression", - "mean", - "median", - "median_grouped", - "median_high", - "median_low", - "mode", - "multimode", - "pstdev", - "pvariance", - "quantiles", - "stdev", - "variance", - ] -elif sys.version_info >= (3, 8): - __all__ = [ - "NormalDist", - "StatisticsError", - "fmean", - "geometric_mean", - "harmonic_mean", - "mean", - "median", - "median_grouped", - "median_high", - "median_low", - "mode", - "multimode", - "pstdev", - "pvariance", - "quantiles", - "stdev", - "variance", - ] -else: - __all__ = [ - "StatisticsError", - "pstdev", - "pvariance", - "stdev", - "variance", - "median", - "median_low", - "median_high", - "median_grouped", - "mean", - "mode", - "harmonic_mean", - ] + __all__ += ["covariance", "correlation", "linear_regression"] # Most functions in this module accept homogeneous collections of one of these types _Number: TypeAlias = float | Decimal | Fraction diff --git a/mypy/typeshed/stdlib/string.pyi b/mypy/typeshed/stdlib/string.pyi index 4404bde8bc4f4..525806a740431 100644 --- a/mypy/typeshed/stdlib/string.pyi +++ b/mypy/typeshed/stdlib/string.pyi @@ -45,6 +45,9 @@ class Template: def __init__(self, template: str) -> None: ... def substitute(self, __mapping: Mapping[str, object] = ..., **kwds: object) -> str: ... def safe_substitute(self, __mapping: Mapping[str, object] = ..., **kwds: object) -> str: ... + if sys.version_info >= (3, 11): + def get_identifiers(self) -> list[str]: ... + def is_valid(self) -> bool: ... # TODO(MichalPokorny): This is probably badly and/or loosely typed. class Formatter: diff --git a/mypy/typeshed/stdlib/subprocess.pyi b/mypy/typeshed/stdlib/subprocess.pyi index 83178e15d9e83..6ce1073002b81 100644 --- a/mypy/typeshed/stdlib/subprocess.pyi +++ b/mypy/typeshed/stdlib/subprocess.pyi @@ -8,86 +8,49 @@ from typing_extensions import Literal, TypeAlias if sys.version_info >= (3, 9): from types import GenericAlias +__all__ = [ + "Popen", + "PIPE", + "STDOUT", + "call", + "check_call", + "getstatusoutput", + "getoutput", + "check_output", + "run", + "CalledProcessError", + "DEVNULL", + "SubprocessError", + "TimeoutExpired", + "CompletedProcess", +] + if sys.platform == "win32": + __all__ += [ + "CREATE_NEW_CONSOLE", + "CREATE_NEW_PROCESS_GROUP", + "STARTF_USESHOWWINDOW", + "STARTF_USESTDHANDLES", + "STARTUPINFO", + "STD_ERROR_HANDLE", + "STD_INPUT_HANDLE", + "STD_OUTPUT_HANDLE", + "SW_HIDE", + ] + if sys.version_info >= (3, 7): - __all__ = [ - "Popen", - "PIPE", - "STDOUT", - "call", - "check_call", - "getstatusoutput", - "getoutput", - "check_output", - "run", - "CalledProcessError", - "DEVNULL", - "SubprocessError", - "TimeoutExpired", - "CompletedProcess", - "CREATE_NEW_CONSOLE", - "CREATE_NEW_PROCESS_GROUP", - "STD_INPUT_HANDLE", - "STD_OUTPUT_HANDLE", - "STD_ERROR_HANDLE", - "SW_HIDE", - "STARTF_USESTDHANDLES", - "STARTF_USESHOWWINDOW", - "STARTUPINFO", + __all__ += [ "ABOVE_NORMAL_PRIORITY_CLASS", "BELOW_NORMAL_PRIORITY_CLASS", + "CREATE_BREAKAWAY_FROM_JOB", + "CREATE_DEFAULT_ERROR_MODE", + "CREATE_NO_WINDOW", + "DETACHED_PROCESS", "HIGH_PRIORITY_CLASS", "IDLE_PRIORITY_CLASS", "NORMAL_PRIORITY_CLASS", "REALTIME_PRIORITY_CLASS", - "CREATE_NO_WINDOW", - "DETACHED_PROCESS", - "CREATE_DEFAULT_ERROR_MODE", - "CREATE_BREAKAWAY_FROM_JOB", - ] - else: - __all__ = [ - "Popen", - "PIPE", - "STDOUT", - "call", - "check_call", - "getstatusoutput", - "getoutput", - "check_output", - "run", - "CalledProcessError", - "DEVNULL", - "SubprocessError", - "TimeoutExpired", - "CompletedProcess", - "CREATE_NEW_CONSOLE", - "CREATE_NEW_PROCESS_GROUP", - "STD_INPUT_HANDLE", - "STD_OUTPUT_HANDLE", - "STD_ERROR_HANDLE", - "SW_HIDE", - "STARTF_USESTDHANDLES", - "STARTF_USESHOWWINDOW", - "STARTUPINFO", ] -else: - __all__ = [ - "Popen", - "PIPE", - "STDOUT", - "call", - "check_call", - "getstatusoutput", - "getoutput", - "check_output", - "run", - "CalledProcessError", - "DEVNULL", - "SubprocessError", - "TimeoutExpired", - "CompletedProcess", - ] # We prefer to annotate inputs to methods (eg subprocess.check_call) with these # union types. @@ -444,49 +407,99 @@ else: ) -> CompletedProcess[Any]: ... # Same args as Popen.__init__ -def call( - args: _CMD, - bufsize: int = ..., - executable: StrOrBytesPath | None = ..., - stdin: _FILE = ..., - stdout: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] | None = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: StrOrBytesPath | None = ..., - env: _ENV | None = ..., - universal_newlines: bool = ..., - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - *, - timeout: float | None = ..., -) -> int: ... +if sys.version_info >= (3, 7): + def call( + args: _CMD, + bufsize: int = ..., + executable: StrOrBytesPath | None = ..., + stdin: _FILE = ..., + stdout: _FILE = ..., + stderr: _FILE = ..., + preexec_fn: Callable[[], Any] | None = ..., + close_fds: bool = ..., + shell: bool = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., + universal_newlines: bool = ..., + startupinfo: Any = ..., + creationflags: int = ..., + restore_signals: bool = ..., + start_new_session: bool = ..., + pass_fds: Any = ..., + *, + timeout: float | None = ..., + text: bool | None = ..., + ) -> int: ... + +else: + def call( + args: _CMD, + bufsize: int = ..., + executable: StrOrBytesPath | None = ..., + stdin: _FILE = ..., + stdout: _FILE = ..., + stderr: _FILE = ..., + preexec_fn: Callable[[], Any] | None = ..., + close_fds: bool = ..., + shell: bool = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., + universal_newlines: bool = ..., + startupinfo: Any = ..., + creationflags: int = ..., + restore_signals: bool = ..., + start_new_session: bool = ..., + pass_fds: Any = ..., + *, + timeout: float | None = ..., + ) -> int: ... # Same args as Popen.__init__ -def check_call( - args: _CMD, - bufsize: int = ..., - executable: StrOrBytesPath = ..., - stdin: _FILE = ..., - stdout: _FILE = ..., - stderr: _FILE = ..., - preexec_fn: Callable[[], Any] | None = ..., - close_fds: bool = ..., - shell: bool = ..., - cwd: StrOrBytesPath | None = ..., - env: _ENV | None = ..., - universal_newlines: bool = ..., - startupinfo: Any = ..., - creationflags: int = ..., - restore_signals: bool = ..., - start_new_session: bool = ..., - pass_fds: Any = ..., - timeout: float | None = ..., -) -> int: ... +if sys.version_info >= (3, 7): + def check_call( + args: _CMD, + bufsize: int = ..., + executable: StrOrBytesPath = ..., + stdin: _FILE = ..., + stdout: _FILE = ..., + stderr: _FILE = ..., + preexec_fn: Callable[[], Any] | None = ..., + close_fds: bool = ..., + shell: bool = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., + universal_newlines: bool = ..., + startupinfo: Any = ..., + creationflags: int = ..., + restore_signals: bool = ..., + start_new_session: bool = ..., + pass_fds: Any = ..., + timeout: float | None = ..., + *, + text: bool | None = ..., + ) -> int: ... + +else: + def check_call( + args: _CMD, + bufsize: int = ..., + executable: StrOrBytesPath = ..., + stdin: _FILE = ..., + stdout: _FILE = ..., + stderr: _FILE = ..., + preexec_fn: Callable[[], Any] | None = ..., + close_fds: bool = ..., + shell: bool = ..., + cwd: StrOrBytesPath | None = ..., + env: _ENV | None = ..., + universal_newlines: bool = ..., + startupinfo: Any = ..., + creationflags: int = ..., + restore_signals: bool = ..., + start_new_session: bool = ..., + pass_fds: Any = ..., + timeout: float | None = ..., + ) -> int: ... if sys.version_info >= (3, 7): # 3.7 added text @@ -1652,8 +1665,13 @@ class Popen(Generic[AnyStr]): def __class_getitem__(cls, item: Any) -> GenericAlias: ... # The result really is always a str. -def getstatusoutput(cmd: _TXT) -> tuple[int, str]: ... -def getoutput(cmd: _TXT) -> str: ... +if sys.version_info >= (3, 11): + def getstatusoutput(cmd: _TXT, *, encoding: str | None = ..., errors: str | None = ...) -> tuple[int, str]: ... + def getoutput(cmd: _TXT, *, encoding: str | None = ..., errors: str | None = ...) -> str: ... + +else: + def getstatusoutput(cmd: _TXT) -> tuple[int, str]: ... + def getoutput(cmd: _TXT) -> str: ... if sys.version_info >= (3, 8): def list2cmdline(seq: Iterable[StrOrBytesPath]) -> str: ... # undocumented diff --git a/mypy/typeshed/stdlib/symtable.pyi b/mypy/typeshed/stdlib/symtable.pyi index 7a95fe5e445f0..d44b2d7927b34 100644 --- a/mypy/typeshed/stdlib/symtable.pyi +++ b/mypy/typeshed/stdlib/symtable.pyi @@ -1,4 +1,5 @@ import sys +from _collections_abc import dict_keys from collections.abc import Sequence from typing import Any @@ -15,8 +16,10 @@ class SymbolTable: def is_optimized(self) -> bool: ... def is_nested(self) -> bool: ... def has_children(self) -> bool: ... - def has_exec(self) -> bool: ... - def get_identifiers(self) -> Sequence[str]: ... + if sys.version_info < (3, 9): + def has_exec(self) -> bool: ... + + def get_identifiers(self) -> dict_keys[str, int]: ... def lookup(self, name: str) -> Symbol: ... def get_symbols(self) -> list[Symbol]: ... def get_children(self) -> list[SymbolTable]: ... diff --git a/mypy/typeshed/stdlib/sys.pyi b/mypy/typeshed/stdlib/sys.pyi index 4e24cbd167d93..667b7024fe124 100644 --- a/mypy/typeshed/stdlib/sys.pyi +++ b/mypy/typeshed/stdlib/sys.pyi @@ -221,6 +221,9 @@ def __displayhook__(__value: object) -> None: ... def __excepthook__(__exctype: type[BaseException], __value: BaseException, __traceback: TracebackType | None) -> None: ... def exc_info() -> OptExcInfo: ... +if sys.version_info >= (3, 11): + def exception() -> BaseException | None: ... + # sys.exit() accepts an optional argument of anything printable def exit(__status: object = ...) -> NoReturn: ... def getallocatedblocks() -> int: ... diff --git a/mypy/typeshed/stdlib/tarfile.pyi b/mypy/typeshed/stdlib/tarfile.pyi index 364bcad0683fe..87c57311aa99c 100644 --- a/mypy/typeshed/stdlib/tarfile.pyi +++ b/mypy/typeshed/stdlib/tarfile.pyi @@ -315,7 +315,9 @@ class TarFile: ) -> None: ... def addfile(self, tarinfo: TarInfo, fileobj: IO[bytes] | None = ...) -> None: ... - def gettarinfo(self, name: str | None = ..., arcname: str | None = ..., fileobj: IO[bytes] | None = ...) -> TarInfo: ... + def gettarinfo( + self, name: StrOrBytesPath | None = ..., arcname: str | None = ..., fileobj: IO[bytes] | None = ... + ) -> TarInfo: ... def close(self) -> None: ... if sys.version_info >= (3, 9): diff --git a/mypy/typeshed/stdlib/tempfile.pyi b/mypy/typeshed/stdlib/tempfile.pyi index 4f2b4a545ff7a..2c096f0fb4de8 100644 --- a/mypy/typeshed/stdlib/tempfile.pyi +++ b/mypy/typeshed/stdlib/tempfile.pyi @@ -1,6 +1,6 @@ -import os +import io import sys -from _typeshed import Self +from _typeshed import BytesPath, GenericPath, Self, StrPath, WriteableBuffer from collections.abc import Iterable, Iterator from types import TracebackType from typing import IO, Any, AnyStr, Generic, overload @@ -30,31 +30,32 @@ TMP_MAX: int tempdir: str | None template: str -_DirT: TypeAlias = AnyStr | os.PathLike[AnyStr] +_StrMode: TypeAlias = Literal["r", "w", "a", "x", "r+", "w+", "a+", "x+", "rt", "wt", "at", "xt", "r+t", "w+t", "a+t", "x+t"] +_BytesMode: TypeAlias = Literal["rb", "wb", "ab", "xb", "r+b", "w+b", "a+b", "x+b"] if sys.version_info >= (3, 8): @overload def NamedTemporaryFile( - mode: Literal["r", "w", "a", "x", "r+", "w+", "a+", "x+", "rt", "wt", "at", "xt", "r+t", "w+t", "a+t", "x+t"], + mode: _StrMode, buffering: int = ..., encoding: str | None = ..., newline: str | None = ..., suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., - dir: _DirT[AnyStr] | None = ..., + dir: GenericPath[AnyStr] | None = ..., delete: bool = ..., *, errors: str | None = ..., ) -> _TemporaryFileWrapper[str]: ... @overload def NamedTemporaryFile( - mode: Literal["rb", "wb", "ab", "xb", "r+b", "w+b", "a+b", "x+b"] = ..., + mode: _BytesMode = ..., buffering: int = ..., encoding: str | None = ..., newline: str | None = ..., suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., - dir: _DirT[AnyStr] | None = ..., + dir: GenericPath[AnyStr] | None = ..., delete: bool = ..., *, errors: str | None = ..., @@ -67,7 +68,7 @@ if sys.version_info >= (3, 8): newline: str | None = ..., suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., - dir: _DirT[AnyStr] | None = ..., + dir: GenericPath[AnyStr] | None = ..., delete: bool = ..., *, errors: str | None = ..., @@ -76,24 +77,24 @@ if sys.version_info >= (3, 8): else: @overload def NamedTemporaryFile( - mode: Literal["r", "w", "a", "x", "r+", "w+", "a+", "x+", "rt", "wt", "at", "xt", "r+t", "w+t", "a+t", "x+t"], + mode: _StrMode, buffering: int = ..., encoding: str | None = ..., newline: str | None = ..., suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., - dir: _DirT[AnyStr] | None = ..., + dir: GenericPath[AnyStr] | None = ..., delete: bool = ..., ) -> _TemporaryFileWrapper[str]: ... @overload def NamedTemporaryFile( - mode: Literal["rb", "wb", "ab", "xb", "r+b", "w+b", "a+b", "x+b"] = ..., + mode: _BytesMode = ..., buffering: int = ..., encoding: str | None = ..., newline: str | None = ..., suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., - dir: _DirT[AnyStr] | None = ..., + dir: GenericPath[AnyStr] | None = ..., delete: bool = ..., ) -> _TemporaryFileWrapper[bytes]: ... @overload @@ -104,7 +105,7 @@ else: newline: str | None = ..., suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., - dir: _DirT[AnyStr] | None = ..., + dir: GenericPath[AnyStr] | None = ..., delete: bool = ..., ) -> _TemporaryFileWrapper[Any]: ... @@ -114,25 +115,25 @@ else: if sys.version_info >= (3, 8): @overload def TemporaryFile( - mode: Literal["r", "w", "a", "x", "r+", "w+", "a+", "x+", "rt", "wt", "at", "xt", "r+t", "w+t", "a+t", "x+t"], + mode: _StrMode, buffering: int = ..., encoding: str | None = ..., newline: str | None = ..., suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., - dir: _DirT[AnyStr] | None = ..., + dir: GenericPath[AnyStr] | None = ..., *, errors: str | None = ..., ) -> IO[str]: ... @overload def TemporaryFile( - mode: Literal["rb", "wb", "ab", "xb", "r+b", "w+b", "a+b", "x+b"] = ..., + mode: _BytesMode = ..., buffering: int = ..., encoding: str | None = ..., newline: str | None = ..., suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., - dir: _DirT[AnyStr] | None = ..., + dir: GenericPath[AnyStr] | None = ..., *, errors: str | None = ..., ) -> IO[bytes]: ... @@ -144,30 +145,30 @@ else: newline: str | None = ..., suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., - dir: _DirT[AnyStr] | None = ..., + dir: GenericPath[AnyStr] | None = ..., *, errors: str | None = ..., ) -> IO[Any]: ... else: @overload def TemporaryFile( - mode: Literal["r", "w", "a", "x", "r+", "w+", "a+", "x+", "rt", "wt", "at", "xt", "r+t", "w+t", "a+t", "x+t"], + mode: _StrMode, buffering: int = ..., encoding: str | None = ..., newline: str | None = ..., suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., - dir: _DirT[AnyStr] | None = ..., + dir: GenericPath[AnyStr] | None = ..., ) -> IO[str]: ... @overload def TemporaryFile( - mode: Literal["rb", "wb", "ab", "xb", "r+b", "w+b", "a+b", "x+b"] = ..., + mode: _BytesMode = ..., buffering: int = ..., encoding: str | None = ..., newline: str | None = ..., suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., - dir: _DirT[AnyStr] | None = ..., + dir: GenericPath[AnyStr] | None = ..., ) -> IO[bytes]: ... @overload def TemporaryFile( @@ -177,7 +178,7 @@ else: newline: str | None = ..., suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., - dir: _DirT[AnyStr] | None = ..., + dir: GenericPath[AnyStr] | None = ..., ) -> IO[Any]: ... class _TemporaryFileWrapper(Generic[AnyStr], IO[AnyStr]): @@ -217,9 +218,14 @@ class _TemporaryFileWrapper(Generic[AnyStr], IO[AnyStr]): def write(self, s: AnyStr) -> int: ... def writelines(self, lines: Iterable[AnyStr]) -> None: ... -# It does not actually derive from IO[AnyStr], but it does implement the -# protocol. -class SpooledTemporaryFile(IO[AnyStr]): +if sys.version_info >= (3, 11): + _SpooledTemporaryFileBase = io.IOBase +else: + _SpooledTemporaryFileBase = object + +# It does not actually derive from IO[AnyStr], but it does mostly behave +# like one. +class SpooledTemporaryFile(IO[AnyStr], _SpooledTemporaryFileBase): @property def encoding(self) -> str: ... # undocumented @property @@ -230,7 +236,7 @@ class SpooledTemporaryFile(IO[AnyStr]): def __init__( self: SpooledTemporaryFile[bytes], max_size: int = ..., - mode: Literal["rb", "wb", "ab", "xb", "r+b", "w+b", "a+b", "x+b"] = ..., + mode: _BytesMode = ..., buffering: int = ..., encoding: str | None = ..., newline: str | None = ..., @@ -244,7 +250,7 @@ class SpooledTemporaryFile(IO[AnyStr]): def __init__( self: SpooledTemporaryFile[str], max_size: int = ..., - mode: Literal["r", "w", "a", "x", "r+", "w+", "a+", "x+", "rt", "wt", "at", "xt", "r+t", "w+t", "a+t", "x+t"] = ..., + mode: _StrMode = ..., buffering: int = ..., encoding: str | None = ..., newline: str | None = ..., @@ -275,7 +281,7 @@ class SpooledTemporaryFile(IO[AnyStr]): def __init__( self: SpooledTemporaryFile[bytes], max_size: int = ..., - mode: Literal["rb", "wb", "ab", "xb", "r+b", "w+b", "a+b", "x+b"] = ..., + mode: _BytesMode = ..., buffering: int = ..., encoding: str | None = ..., newline: str | None = ..., @@ -287,7 +293,7 @@ class SpooledTemporaryFile(IO[AnyStr]): def __init__( self: SpooledTemporaryFile[str], max_size: int = ..., - mode: Literal["r", "w", "a", "x", "r+", "w+", "a+", "x+", "rt", "wt", "at", "xt", "r+t", "w+t", "a+t", "x+t"] = ..., + mode: _StrMode = ..., buffering: int = ..., encoding: str | None = ..., newline: str | None = ..., @@ -318,20 +324,28 @@ class SpooledTemporaryFile(IO[AnyStr]): def fileno(self) -> int: ... def flush(self) -> None: ... def isatty(self) -> bool: ... - def read(self, n: int = ...) -> AnyStr: ... - def readline(self, limit: int = ...) -> AnyStr: ... - def readlines(self, hint: int = ...) -> list[AnyStr]: ... + if sys.version_info >= (3, 11): + # These three work only if the SpooledTemporaryFile is opened in binary mode, + # because the underlying object in text mode does not have these methods. + def read1(self, __size: int = ...) -> AnyStr: ... + def readinto(self, b: WriteableBuffer) -> int: ... + def readinto1(self, b: WriteableBuffer) -> int: ... + def detach(self) -> io.RawIOBase: ... + + def read(self, __n: int = ...) -> AnyStr: ... + def readline(self, __limit: int | None = ...) -> AnyStr: ... # type: ignore[override] + def readlines(self, __hint: int = ...) -> list[AnyStr]: ... # type: ignore[override] def seek(self, offset: int, whence: int = ...) -> int: ... def tell(self) -> int: ... def truncate(self, size: int | None = ...) -> None: ... # type: ignore[override] def write(self, s: AnyStr) -> int: ... - def writelines(self, iterable: Iterable[AnyStr]) -> None: ... - def __iter__(self) -> Iterator[AnyStr]: ... - # Other than the following methods, which do not exist on SpooledTemporaryFile + def writelines(self, iterable: Iterable[AnyStr]) -> None: ... # type: ignore[override] + def __iter__(self) -> Iterator[AnyStr]: ... # type: ignore[override] + # These exist at runtime only on 3.11+. def readable(self) -> bool: ... def seekable(self) -> bool: ... def writable(self) -> bool: ... - def __next__(self) -> AnyStr: ... + def __next__(self) -> AnyStr: ... # type: ignore[override] if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... @@ -341,24 +355,28 @@ class TemporaryDirectory(Generic[AnyStr]): @overload def __init__( self: TemporaryDirectory[str], - suffix: None = ..., - prefix: None = ..., - dir: None = ..., + suffix: str | None = ..., + prefix: str | None = ..., + dir: StrPath | None = ..., ignore_cleanup_errors: bool = ..., ) -> None: ... @overload def __init__( - self, - suffix: AnyStr | None = ..., - prefix: AnyStr | None = ..., - dir: _DirT[AnyStr] | None = ..., + self: TemporaryDirectory[bytes], + suffix: bytes | None = ..., + prefix: bytes | None = ..., + dir: BytesPath | None = ..., ignore_cleanup_errors: bool = ..., ) -> None: ... else: @overload - def __init__(self: TemporaryDirectory[str], suffix: None = ..., prefix: None = ..., dir: None = ...) -> None: ... + def __init__( + self: TemporaryDirectory[str], suffix: str | None = ..., prefix: str | None = ..., dir: StrPath | None = ... + ) -> None: ... @overload - def __init__(self, suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., dir: _DirT[AnyStr] | None = ...) -> None: ... + def __init__( + self: TemporaryDirectory[bytes], suffix: bytes | None = ..., prefix: bytes | None = ..., dir: BytesPath | None = ... + ) -> None: ... def cleanup(self) -> None: ... def __enter__(self) -> AnyStr: ... @@ -366,20 +384,22 @@ class TemporaryDirectory(Generic[AnyStr]): if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... +# The overloads overlap, but they should still work fine. @overload -def mkstemp() -> tuple[int, str]: ... +def mkstemp( # type: ignore[misc] + suffix: str | None = ..., prefix: str | None = ..., dir: StrPath | None = ..., text: bool = ... +) -> tuple[int, str]: ... @overload def mkstemp( - suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., dir: _DirT[AnyStr] | None = ..., text: bool = ... -) -> tuple[int, AnyStr]: ... -@overload -def mkdtemp() -> str: ... -@overload -def mkdtemp(suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., dir: _DirT[AnyStr] | None = ...) -> AnyStr: ... + suffix: bytes | None = ..., prefix: bytes | None = ..., dir: BytesPath | None = ..., text: bool = ... +) -> tuple[int, bytes]: ... + +# The overloads overlap, but they should still work fine. @overload -def mktemp() -> str: ... +def mkdtemp(suffix: str | None = ..., prefix: str | None = ..., dir: StrPath | None = ...) -> str: ... # type: ignore[misc] @overload -def mktemp(suffix: AnyStr | None = ..., prefix: AnyStr | None = ..., dir: _DirT[AnyStr] | None = ...) -> AnyStr: ... +def mkdtemp(suffix: bytes | None = ..., prefix: bytes | None = ..., dir: BytesPath | None = ...) -> bytes: ... +def mktemp(suffix: str = ..., prefix: str = ..., dir: StrPath | None = ...) -> str: ... def gettempdirb() -> bytes: ... def gettempprefixb() -> bytes: ... def gettempdir() -> str: ... diff --git a/mypy/typeshed/stdlib/termios.pyi b/mypy/typeshed/stdlib/termios.pyi index b2423304b9302..494162a49b389 100644 --- a/mypy/typeshed/stdlib/termios.pyi +++ b/mypy/typeshed/stdlib/termios.pyi @@ -244,5 +244,8 @@ if sys.platform != "win32": def tcdrain(__fd: FileDescriptorLike) -> None: ... def tcflush(__fd: FileDescriptorLike, __queue: int) -> None: ... def tcflow(__fd: FileDescriptorLike, __action: int) -> None: ... + if sys.version_info >= (3, 11): + def tcgetwinsize(__fd: FileDescriptorLike) -> tuple[int, int]: ... + def tcsetwinsize(__fd: FileDescriptorLike, __winsize: tuple[int, int]) -> None: ... class error(Exception): ... diff --git a/mypy/typeshed/stdlib/threading.pyi b/mypy/typeshed/stdlib/threading.pyi index 231018ca731a1..afc37b771e8c9 100644 --- a/mypy/typeshed/stdlib/threading.pyi +++ b/mypy/typeshed/stdlib/threading.pyi @@ -10,86 +10,35 @@ _TF: TypeAlias = Callable[[FrameType, str, Any], Callable[..., Any] | None] _PF: TypeAlias = Callable[[FrameType, str, Any], None] _T = TypeVar("_T") +__all__ = [ + "get_ident", + "active_count", + "Condition", + "current_thread", + "enumerate", + "main_thread", + "TIMEOUT_MAX", + "Event", + "Lock", + "RLock", + "Semaphore", + "BoundedSemaphore", + "Thread", + "Barrier", + "BrokenBarrierError", + "Timer", + "ThreadError", + "setprofile", + "settrace", + "local", + "stack_size", +] + +if sys.version_info >= (3, 8): + __all__ += ["ExceptHookArgs", "excepthook", "get_native_id"] + if sys.version_info >= (3, 10): - __all__ = [ - "get_ident", - "active_count", - "Condition", - "current_thread", - "enumerate", - "main_thread", - "TIMEOUT_MAX", - "Event", - "Lock", - "RLock", - "Semaphore", - "BoundedSemaphore", - "Thread", - "Barrier", - "BrokenBarrierError", - "Timer", - "ThreadError", - "setprofile", - "settrace", - "local", - "stack_size", - "excepthook", - "ExceptHookArgs", - "gettrace", - "getprofile", - "get_native_id", - ] -elif sys.version_info >= (3, 8): - __all__ = [ - "get_ident", - "active_count", - "Condition", - "current_thread", - "enumerate", - "main_thread", - "TIMEOUT_MAX", - "Event", - "Lock", - "RLock", - "Semaphore", - "BoundedSemaphore", - "Thread", - "Barrier", - "BrokenBarrierError", - "Timer", - "ThreadError", - "setprofile", - "settrace", - "local", - "stack_size", - "excepthook", - "ExceptHookArgs", - "get_native_id", - ] -else: - __all__ = [ - "get_ident", - "active_count", - "Condition", - "current_thread", - "enumerate", - "main_thread", - "TIMEOUT_MAX", - "Event", - "Lock", - "RLock", - "Semaphore", - "BoundedSemaphore", - "Thread", - "Barrier", - "BrokenBarrierError", - "Timer", - "ThreadError", - "setprofile", - "settrace", - "local", - "stack_size", - ] + __all__ += ["getprofile", "gettrace"] _profile_hook: _PF | None @@ -190,6 +139,7 @@ class Condition: def notifyAll(self) -> None: ... # deprecated alias for notify_all() class Semaphore: + _value: int def __init__(self, value: int = ...) -> None: ... def __exit__(self, t: type[BaseException] | None, v: BaseException | None, tb: TracebackType | None) -> None: ... def acquire(self, blocking: bool = ..., timeout: float | None = ...) -> bool: ... @@ -216,6 +166,12 @@ if sys.version_info >= (3, 8): ExceptHookArgs = _ExceptHookArgs class Timer(Thread): + args: Iterable[Any] # undocumented + finished: Event # undocumented + function: Callable[..., Any] # undocumented + interval: float # undocumented + kwargs: Mapping[str, Any] # undocumented + def __init__( self, interval: float, diff --git a/mypy/typeshed/stdlib/tkinter/__init__.pyi b/mypy/typeshed/stdlib/tkinter/__init__.pyi index 582503971e159..0955992d26883 100644 --- a/mypy/typeshed/stdlib/tkinter/__init__.pyi +++ b/mypy/typeshed/stdlib/tkinter/__init__.pyi @@ -2197,31 +2197,29 @@ class Listbox(Widget, XView, YView): @overload def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure - def activate(self, index) -> None: ... - def bbox(self, index) -> tuple[int, int, int, int] | None: ... # type: ignore[override] + def activate(self, index: str | int) -> None: ... + def bbox(self, index: str | int) -> tuple[int, int, int, int] | None: ... # type: ignore[override] def curselection(self): ... - def delete(self, first, last: Any | None = ...) -> None: ... - def get(self, first, last: Any | None = ...): ... - def index(self, index): ... - def insert(self, index, *elements) -> None: ... + def delete(self, first: str | int, last: str | int | None = ...) -> None: ... + def get(self, first: str | int, last: str | int | None = ...): ... + def index(self, index: str | int) -> int: ... + def insert(self, index: str | int, *elements: str | float) -> None: ... def nearest(self, y): ... def scan_mark(self, x, y) -> None: ... def scan_dragto(self, x, y) -> None: ... - def see(self, index) -> None: ... - def selection_anchor(self, index) -> None: ... - select_anchor: Any - def selection_clear(self, first, last: Any | None = ...) -> None: ... # type: ignore[override] - select_clear: Any - def selection_includes(self, index): ... - select_includes: Any - def selection_set(self, first, last: Any | None = ...) -> None: ... - select_set: Any + def see(self, index: str | int) -> None: ... + def selection_anchor(self, index: str | int) -> None: ... + select_anchor = selection_anchor + def selection_clear(self, first: str | int, last: str | int | None = ...) -> None: ... # type: ignore[override] + select_clear = selection_clear + def selection_includes(self, index: str | int): ... + select_includes = selection_includes + def selection_set(self, first: str | int, last: str | int | None = ...) -> None: ... + select_set = selection_set def size(self) -> int: ... # type: ignore[override] - def itemcget(self, index, option): ... - def itemconfigure(self, index, cnf: Any | None = ..., **kw): ... - itemconfig: Any - -_MenuIndex: TypeAlias = str | int + def itemcget(self, index: str | int, option): ... + def itemconfigure(self, index: str | int, cnf: Any | None = ..., **kw): ... + itemconfig = itemconfigure class Menu(Widget): def __init__( @@ -2285,8 +2283,8 @@ class Menu(Widget): @overload def configure(self, cnf: str) -> tuple[str, str, str, Any, Any]: ... config = configure - def tk_popup(self, x: int, y: int, entry: _MenuIndex = ...) -> None: ... - def activate(self, index: _MenuIndex) -> None: ... + def tk_popup(self, x: int, y: int, entry: str | int = ...) -> None: ... + def activate(self, index: str | int) -> None: ... def add(self, itemType, cnf=..., **kw): ... # docstring says "Internal function." def insert(self, index, itemType, cnf=..., **kw): ... # docstring says "Internal function." def add_cascade( @@ -2384,7 +2382,7 @@ class Menu(Widget): def add_separator(self, cnf: dict[str, Any] | None = ..., *, background: _Color = ...) -> None: ... def insert_cascade( self, - index: _MenuIndex, + index: str | int, cnf: dict[str, Any] | None = ..., *, accelerator: str = ..., @@ -2406,7 +2404,7 @@ class Menu(Widget): ) -> None: ... def insert_checkbutton( self, - index: _MenuIndex, + index: str | int, cnf: dict[str, Any] | None = ..., *, accelerator: str = ..., @@ -2433,7 +2431,7 @@ class Menu(Widget): ) -> None: ... def insert_command( self, - index: _MenuIndex, + index: str | int, cnf: dict[str, Any] | None = ..., *, accelerator: str = ..., @@ -2454,7 +2452,7 @@ class Menu(Widget): ) -> None: ... def insert_radiobutton( self, - index: _MenuIndex, + index: str | int, cnf: dict[str, Any] | None = ..., *, accelerator: str = ..., @@ -2478,20 +2476,20 @@ class Menu(Widget): value: Any = ..., variable: Variable = ..., ) -> None: ... - def insert_separator(self, index: _MenuIndex, cnf: dict[str, Any] | None = ..., *, background: _Color = ...) -> None: ... - def delete(self, index1: _MenuIndex, index2: _MenuIndex | None = ...) -> None: ... - def entrycget(self, index: _MenuIndex, option: str) -> Any: ... + def insert_separator(self, index: str | int, cnf: dict[str, Any] | None = ..., *, background: _Color = ...) -> None: ... + def delete(self, index1: str | int, index2: str | int | None = ...) -> None: ... + def entrycget(self, index: str | int, option: str) -> Any: ... def entryconfigure( - self, index: _MenuIndex, cnf: dict[str, Any] | None = ..., **kw: Any + self, index: str | int, cnf: dict[str, Any] | None = ..., **kw: Any ) -> dict[str, tuple[str, str, str, Any, Any]] | None: ... entryconfig = entryconfigure - def index(self, index: _MenuIndex) -> int | None: ... - def invoke(self, index: _MenuIndex) -> Any: ... + def index(self, index: str | int) -> int | None: ... + def invoke(self, index: str | int) -> Any: ... def post(self, x: int, y: int) -> None: ... - def type(self, index: _MenuIndex) -> Literal["cascade", "checkbutton", "command", "radiobutton", "separator"]: ... + def type(self, index: str | int) -> Literal["cascade", "checkbutton", "command", "radiobutton", "separator"]: ... def unpost(self) -> None: ... - def xposition(self, index: _MenuIndex) -> int: ... - def yposition(self, index: _MenuIndex) -> int: ... + def xposition(self, index: str | int) -> int: ... + def yposition(self, index: str | int) -> int: ... class Menubutton(Widget): def __init__( @@ -3578,3 +3576,5 @@ class PanedWindow(Widget): def paneconfigure(self, tagOrId, cnf: Any | None = ..., **kw): ... paneconfig: Any def panes(self): ... + +def _test() -> None: ... diff --git a/mypy/typeshed/stdlib/tkinter/ttk.pyi b/mypy/typeshed/stdlib/tkinter/ttk.pyi index 7ca8f9b800ce6..0fe94ad30ff51 100644 --- a/mypy/typeshed/stdlib/tkinter/ttk.pyi +++ b/mypy/typeshed/stdlib/tkinter/ttk.pyi @@ -6,61 +6,35 @@ from tkinter.font import _FontDescription from typing import Any, overload from typing_extensions import Literal, TypeAlias, TypedDict +__all__ = [ + "Button", + "Checkbutton", + "Combobox", + "Entry", + "Frame", + "Label", + "Labelframe", + "LabelFrame", + "Menubutton", + "Notebook", + "Panedwindow", + "PanedWindow", + "Progressbar", + "Radiobutton", + "Scale", + "Scrollbar", + "Separator", + "Sizegrip", + "Style", + "Treeview", + "LabeledScale", + "OptionMenu", + "tclobjs_to_py", + "setup_master", +] + if sys.version_info >= (3, 7): - __all__ = [ - "Button", - "Checkbutton", - "Combobox", - "Entry", - "Frame", - "Label", - "Labelframe", - "LabelFrame", - "Menubutton", - "Notebook", - "Panedwindow", - "PanedWindow", - "Progressbar", - "Radiobutton", - "Scale", - "Scrollbar", - "Separator", - "Sizegrip", - "Spinbox", - "Style", - "Treeview", - "LabeledScale", - "OptionMenu", - "tclobjs_to_py", - "setup_master", - ] -else: - __all__ = [ - "Button", - "Checkbutton", - "Combobox", - "Entry", - "Frame", - "Label", - "Labelframe", - "LabelFrame", - "Menubutton", - "Notebook", - "Panedwindow", - "PanedWindow", - "Progressbar", - "Radiobutton", - "Scale", - "Scrollbar", - "Separator", - "Sizegrip", - "Style", - "Treeview", - "LabeledScale", - "OptionMenu", - "tclobjs_to_py", - "setup_master", - ] + __all__ += ["Spinbox"] def tclobjs_to_py(adict: dict[Any, Any]) -> dict[Any, Any]: ... def setup_master(master: Any | None = ...): ... diff --git a/mypy/typeshed/stdlib/token.pyi b/mypy/typeshed/stdlib/token.pyi index 49329ec442f02..5fe9db7e230d2 100644 --- a/mypy/typeshed/stdlib/token.pyi +++ b/mypy/typeshed/stdlib/token.pyi @@ -1,283 +1,80 @@ import sys +__all__ = [ + "AMPER", + "AMPEREQUAL", + "AT", + "ATEQUAL", + "CIRCUMFLEX", + "CIRCUMFLEXEQUAL", + "COLON", + "COMMA", + "DEDENT", + "DOT", + "DOUBLESLASH", + "DOUBLESLASHEQUAL", + "DOUBLESTAR", + "DOUBLESTAREQUAL", + "ELLIPSIS", + "ENDMARKER", + "EQEQUAL", + "EQUAL", + "ERRORTOKEN", + "GREATER", + "GREATEREQUAL", + "INDENT", + "ISEOF", + "ISNONTERMINAL", + "ISTERMINAL", + "LBRACE", + "LEFTSHIFT", + "LEFTSHIFTEQUAL", + "LESS", + "LESSEQUAL", + "LPAR", + "LSQB", + "MINEQUAL", + "MINUS", + "NAME", + "NEWLINE", + "NOTEQUAL", + "NT_OFFSET", + "NUMBER", + "N_TOKENS", + "OP", + "PERCENT", + "PERCENTEQUAL", + "PLUS", + "PLUSEQUAL", + "RARROW", + "RBRACE", + "RIGHTSHIFT", + "RIGHTSHIFTEQUAL", + "RPAR", + "RSQB", + "SEMI", + "SLASH", + "SLASHEQUAL", + "STAR", + "STAREQUAL", + "STRING", + "TILDE", + "VBAR", + "VBAREQUAL", + "tok_name", +] + +if sys.version_info < (3, 7) or sys.version_info >= (3, 8): + __all__ += ["ASYNC", "AWAIT"] + +if sys.version_info >= (3, 7): + __all__ += ["ENCODING", "NL", "COMMENT"] + +if sys.version_info >= (3, 8): + __all__ += ["COLONEQUAL", "TYPE_COMMENT", "TYPE_IGNORE"] + if sys.version_info >= (3, 10): - __all__ = [ - "tok_name", - "ISTERMINAL", - "ISNONTERMINAL", - "ISEOF", - "ENDMARKER", - "NAME", - "NUMBER", - "STRING", - "NEWLINE", - "INDENT", - "DEDENT", - "LPAR", - "RPAR", - "LSQB", - "RSQB", - "COLON", - "COMMA", - "SEMI", - "PLUS", - "MINUS", - "STAR", - "SLASH", - "VBAR", - "AMPER", - "LESS", - "GREATER", - "EQUAL", - "DOT", - "PERCENT", - "LBRACE", - "RBRACE", - "EQEQUAL", - "NOTEQUAL", - "LESSEQUAL", - "GREATEREQUAL", - "TILDE", - "CIRCUMFLEX", - "LEFTSHIFT", - "RIGHTSHIFT", - "DOUBLESTAR", - "PLUSEQUAL", - "MINEQUAL", - "STAREQUAL", - "SLASHEQUAL", - "PERCENTEQUAL", - "AMPEREQUAL", - "VBAREQUAL", - "CIRCUMFLEXEQUAL", - "LEFTSHIFTEQUAL", - "RIGHTSHIFTEQUAL", - "DOUBLESTAREQUAL", - "DOUBLESLASH", - "DOUBLESLASHEQUAL", - "AT", - "ATEQUAL", - "RARROW", - "ELLIPSIS", - "COLONEQUAL", - "OP", - "AWAIT", - "ASYNC", - "TYPE_IGNORE", - "TYPE_COMMENT", - "SOFT_KEYWORD", - "ERRORTOKEN", - "COMMENT", - "NL", - "ENCODING", - "N_TOKENS", - "NT_OFFSET", - ] -elif sys.version_info >= (3, 8): - __all__ = [ - "tok_name", - "ISTERMINAL", - "ISNONTERMINAL", - "ISEOF", - "ENDMARKER", - "NAME", - "NUMBER", - "STRING", - "NEWLINE", - "INDENT", - "DEDENT", - "LPAR", - "RPAR", - "LSQB", - "RSQB", - "COLON", - "COMMA", - "SEMI", - "PLUS", - "MINUS", - "STAR", - "SLASH", - "VBAR", - "AMPER", - "LESS", - "GREATER", - "EQUAL", - "DOT", - "PERCENT", - "LBRACE", - "RBRACE", - "EQEQUAL", - "NOTEQUAL", - "LESSEQUAL", - "GREATEREQUAL", - "TILDE", - "CIRCUMFLEX", - "LEFTSHIFT", - "RIGHTSHIFT", - "DOUBLESTAR", - "PLUSEQUAL", - "MINEQUAL", - "STAREQUAL", - "SLASHEQUAL", - "PERCENTEQUAL", - "AMPEREQUAL", - "VBAREQUAL", - "CIRCUMFLEXEQUAL", - "LEFTSHIFTEQUAL", - "RIGHTSHIFTEQUAL", - "DOUBLESTAREQUAL", - "DOUBLESLASH", - "DOUBLESLASHEQUAL", - "AT", - "ATEQUAL", - "RARROW", - "ELLIPSIS", - "COLONEQUAL", - "OP", - "AWAIT", - "ASYNC", - "TYPE_IGNORE", - "TYPE_COMMENT", - "ERRORTOKEN", - "COMMENT", - "NL", - "ENCODING", - "N_TOKENS", - "NT_OFFSET", - ] -elif sys.version_info >= (3, 7): - __all__ = [ - "tok_name", - "ISTERMINAL", - "ISNONTERMINAL", - "ISEOF", - "ENDMARKER", - "NAME", - "NUMBER", - "STRING", - "NEWLINE", - "INDENT", - "DEDENT", - "LPAR", - "RPAR", - "LSQB", - "RSQB", - "COLON", - "COMMA", - "SEMI", - "PLUS", - "MINUS", - "STAR", - "SLASH", - "VBAR", - "AMPER", - "LESS", - "GREATER", - "EQUAL", - "DOT", - "PERCENT", - "LBRACE", - "RBRACE", - "EQEQUAL", - "NOTEQUAL", - "LESSEQUAL", - "GREATEREQUAL", - "TILDE", - "CIRCUMFLEX", - "LEFTSHIFT", - "RIGHTSHIFT", - "DOUBLESTAR", - "PLUSEQUAL", - "MINEQUAL", - "STAREQUAL", - "SLASHEQUAL", - "PERCENTEQUAL", - "AMPEREQUAL", - "VBAREQUAL", - "CIRCUMFLEXEQUAL", - "LEFTSHIFTEQUAL", - "RIGHTSHIFTEQUAL", - "DOUBLESTAREQUAL", - "DOUBLESLASH", - "DOUBLESLASHEQUAL", - "AT", - "ATEQUAL", - "RARROW", - "ELLIPSIS", - "OP", - "ERRORTOKEN", - "COMMENT", - "NL", - "ENCODING", - "N_TOKENS", - "NT_OFFSET", - ] -else: - __all__ = [ - "tok_name", - "ISTERMINAL", - "ISNONTERMINAL", - "ISEOF", - "ENDMARKER", - "NAME", - "NUMBER", - "STRING", - "NEWLINE", - "INDENT", - "DEDENT", - "LPAR", - "RPAR", - "LSQB", - "RSQB", - "COLON", - "COMMA", - "SEMI", - "PLUS", - "MINUS", - "STAR", - "SLASH", - "VBAR", - "AMPER", - "LESS", - "GREATER", - "EQUAL", - "DOT", - "PERCENT", - "LBRACE", - "RBRACE", - "EQEQUAL", - "NOTEQUAL", - "LESSEQUAL", - "GREATEREQUAL", - "TILDE", - "CIRCUMFLEX", - "LEFTSHIFT", - "RIGHTSHIFT", - "DOUBLESTAR", - "PLUSEQUAL", - "MINEQUAL", - "STAREQUAL", - "SLASHEQUAL", - "PERCENTEQUAL", - "AMPEREQUAL", - "VBAREQUAL", - "CIRCUMFLEXEQUAL", - "LEFTSHIFTEQUAL", - "RIGHTSHIFTEQUAL", - "DOUBLESTAREQUAL", - "DOUBLESLASH", - "DOUBLESLASHEQUAL", - "AT", - "ATEQUAL", - "RARROW", - "ELLIPSIS", - "OP", - "AWAIT", - "ASYNC", - "ERRORTOKEN", - "N_TOKENS", - "NT_OFFSET", - ] + __all__ += ["SOFT_KEYWORD"] ENDMARKER: int NAME: int diff --git a/mypy/typeshed/stdlib/tokenize.pyi b/mypy/typeshed/stdlib/tokenize.pyi index dea83263b550a..3ac136150ab5e 100644 --- a/mypy/typeshed/stdlib/tokenize.pyi +++ b/mypy/typeshed/stdlib/tokenize.pyi @@ -6,305 +6,85 @@ from token import * from typing import Any, NamedTuple, Pattern, TextIO from typing_extensions import TypeAlias +__all__ = [ + "AMPER", + "AMPEREQUAL", + "AT", + "ATEQUAL", + "CIRCUMFLEX", + "CIRCUMFLEXEQUAL", + "COLON", + "COMMA", + "COMMENT", + "DEDENT", + "DOT", + "DOUBLESLASH", + "DOUBLESLASHEQUAL", + "DOUBLESTAR", + "DOUBLESTAREQUAL", + "ELLIPSIS", + "ENCODING", + "ENDMARKER", + "EQEQUAL", + "EQUAL", + "ERRORTOKEN", + "GREATER", + "GREATEREQUAL", + "INDENT", + "ISEOF", + "ISNONTERMINAL", + "ISTERMINAL", + "LBRACE", + "LEFTSHIFT", + "LEFTSHIFTEQUAL", + "LESS", + "LESSEQUAL", + "LPAR", + "LSQB", + "MINEQUAL", + "MINUS", + "NAME", + "NEWLINE", + "NL", + "NOTEQUAL", + "NT_OFFSET", + "NUMBER", + "N_TOKENS", + "OP", + "PERCENT", + "PERCENTEQUAL", + "PLUS", + "PLUSEQUAL", + "RARROW", + "RBRACE", + "RIGHTSHIFT", + "RIGHTSHIFTEQUAL", + "RPAR", + "RSQB", + "SEMI", + "SLASH", + "SLASHEQUAL", + "STAR", + "STAREQUAL", + "STRING", + "TILDE", + "TokenInfo", + "VBAR", + "VBAREQUAL", + "detect_encoding", + "tok_name", + "tokenize", + "untokenize", +] + +if sys.version_info < (3, 7) or sys.version_info >= (3, 8): + __all__ += ["ASYNC", "AWAIT"] + +if sys.version_info >= (3, 8): + __all__ += ["COLONEQUAL", "generate_tokens", "TYPE_COMMENT", "TYPE_IGNORE"] + if sys.version_info >= (3, 10): - __all__ = [ - "tok_name", - "ISTERMINAL", - "ISNONTERMINAL", - "ISEOF", - "ENDMARKER", - "NAME", - "NUMBER", - "STRING", - "NEWLINE", - "INDENT", - "DEDENT", - "LPAR", - "RPAR", - "LSQB", - "RSQB", - "COLON", - "COMMA", - "SEMI", - "PLUS", - "MINUS", - "STAR", - "SLASH", - "VBAR", - "AMPER", - "LESS", - "GREATER", - "EQUAL", - "DOT", - "PERCENT", - "LBRACE", - "RBRACE", - "EQEQUAL", - "NOTEQUAL", - "LESSEQUAL", - "GREATEREQUAL", - "TILDE", - "CIRCUMFLEX", - "LEFTSHIFT", - "RIGHTSHIFT", - "DOUBLESTAR", - "PLUSEQUAL", - "MINEQUAL", - "STAREQUAL", - "SLASHEQUAL", - "PERCENTEQUAL", - "AMPEREQUAL", - "VBAREQUAL", - "CIRCUMFLEXEQUAL", - "LEFTSHIFTEQUAL", - "RIGHTSHIFTEQUAL", - "DOUBLESTAREQUAL", - "DOUBLESLASH", - "DOUBLESLASHEQUAL", - "AT", - "ATEQUAL", - "RARROW", - "ELLIPSIS", - "COLONEQUAL", - "OP", - "AWAIT", - "ASYNC", - "TYPE_IGNORE", - "TYPE_COMMENT", - "SOFT_KEYWORD", - "ERRORTOKEN", - "COMMENT", - "NL", - "ENCODING", - "N_TOKENS", - "NT_OFFSET", - "tokenize", - "generate_tokens", - "detect_encoding", - "untokenize", - "TokenInfo", - ] -elif sys.version_info >= (3, 8): - __all__ = [ - "tok_name", - "ISTERMINAL", - "ISNONTERMINAL", - "ISEOF", - "ENDMARKER", - "NAME", - "NUMBER", - "STRING", - "NEWLINE", - "INDENT", - "DEDENT", - "LPAR", - "RPAR", - "LSQB", - "RSQB", - "COLON", - "COMMA", - "SEMI", - "PLUS", - "MINUS", - "STAR", - "SLASH", - "VBAR", - "AMPER", - "LESS", - "GREATER", - "EQUAL", - "DOT", - "PERCENT", - "LBRACE", - "RBRACE", - "EQEQUAL", - "NOTEQUAL", - "LESSEQUAL", - "GREATEREQUAL", - "TILDE", - "CIRCUMFLEX", - "LEFTSHIFT", - "RIGHTSHIFT", - "DOUBLESTAR", - "PLUSEQUAL", - "MINEQUAL", - "STAREQUAL", - "SLASHEQUAL", - "PERCENTEQUAL", - "AMPEREQUAL", - "VBAREQUAL", - "CIRCUMFLEXEQUAL", - "LEFTSHIFTEQUAL", - "RIGHTSHIFTEQUAL", - "DOUBLESTAREQUAL", - "DOUBLESLASH", - "DOUBLESLASHEQUAL", - "AT", - "ATEQUAL", - "RARROW", - "ELLIPSIS", - "COLONEQUAL", - "OP", - "AWAIT", - "ASYNC", - "TYPE_IGNORE", - "TYPE_COMMENT", - "ERRORTOKEN", - "COMMENT", - "NL", - "ENCODING", - "N_TOKENS", - "NT_OFFSET", - "tokenize", - "generate_tokens", - "detect_encoding", - "untokenize", - "TokenInfo", - ] -elif sys.version_info >= (3, 7): - __all__ = [ - "tok_name", - "ISTERMINAL", - "ISNONTERMINAL", - "ISEOF", - "ENDMARKER", - "NAME", - "NUMBER", - "STRING", - "NEWLINE", - "INDENT", - "DEDENT", - "LPAR", - "RPAR", - "LSQB", - "RSQB", - "COLON", - "COMMA", - "SEMI", - "PLUS", - "MINUS", - "STAR", - "SLASH", - "VBAR", - "AMPER", - "LESS", - "GREATER", - "EQUAL", - "DOT", - "PERCENT", - "LBRACE", - "RBRACE", - "EQEQUAL", - "NOTEQUAL", - "LESSEQUAL", - "GREATEREQUAL", - "TILDE", - "CIRCUMFLEX", - "LEFTSHIFT", - "RIGHTSHIFT", - "DOUBLESTAR", - "PLUSEQUAL", - "MINEQUAL", - "STAREQUAL", - "SLASHEQUAL", - "PERCENTEQUAL", - "AMPEREQUAL", - "VBAREQUAL", - "CIRCUMFLEXEQUAL", - "LEFTSHIFTEQUAL", - "RIGHTSHIFTEQUAL", - "DOUBLESTAREQUAL", - "DOUBLESLASH", - "DOUBLESLASHEQUAL", - "AT", - "ATEQUAL", - "RARROW", - "ELLIPSIS", - "OP", - "ERRORTOKEN", - "COMMENT", - "NL", - "ENCODING", - "N_TOKENS", - "NT_OFFSET", - "tokenize", - "detect_encoding", - "untokenize", - "TokenInfo", - ] -else: - __all__ = [ - "tok_name", - "ISTERMINAL", - "ISNONTERMINAL", - "ISEOF", - "ENDMARKER", - "NAME", - "NUMBER", - "STRING", - "NEWLINE", - "INDENT", - "DEDENT", - "LPAR", - "RPAR", - "LSQB", - "RSQB", - "COLON", - "COMMA", - "SEMI", - "PLUS", - "MINUS", - "STAR", - "SLASH", - "VBAR", - "AMPER", - "LESS", - "GREATER", - "EQUAL", - "DOT", - "PERCENT", - "LBRACE", - "RBRACE", - "EQEQUAL", - "NOTEQUAL", - "LESSEQUAL", - "GREATEREQUAL", - "TILDE", - "CIRCUMFLEX", - "LEFTSHIFT", - "RIGHTSHIFT", - "DOUBLESTAR", - "PLUSEQUAL", - "MINEQUAL", - "STAREQUAL", - "SLASHEQUAL", - "PERCENTEQUAL", - "AMPEREQUAL", - "VBAREQUAL", - "CIRCUMFLEXEQUAL", - "LEFTSHIFTEQUAL", - "RIGHTSHIFTEQUAL", - "DOUBLESTAREQUAL", - "DOUBLESLASH", - "DOUBLESLASHEQUAL", - "AT", - "ATEQUAL", - "RARROW", - "ELLIPSIS", - "OP", - "AWAIT", - "ASYNC", - "ERRORTOKEN", - "N_TOKENS", - "NT_OFFSET", - "COMMENT", - "tokenize", - "detect_encoding", - "NL", - "untokenize", - "ENCODING", - "TokenInfo", - ] + __all__ += ["SOFT_KEYWORD"] if sys.version_info >= (3, 8): from token import EXACT_TOKEN_TYPES as EXACT_TOKEN_TYPES diff --git a/mypy/typeshed/stdlib/traceback.pyi b/mypy/typeshed/stdlib/traceback.pyi index 5c4d323a2d9ff..16151f9431eb9 100644 --- a/mypy/typeshed/stdlib/traceback.pyi +++ b/mypy/typeshed/stdlib/traceback.pyi @@ -96,6 +96,12 @@ def clear_frames(tb: TracebackType) -> None: ... def walk_stack(f: FrameType | None) -> Iterator[tuple[FrameType, int]]: ... def walk_tb(tb: TracebackType | None) -> Iterator[tuple[FrameType, int]]: ... +if sys.version_info >= (3, 11): + class _ExceptionPrintContext: + def __init__(self) -> None: ... + def indent(self) -> str: ... + def emit(self, text_gen: str | Iterable[str], margin_char: str | None = ...) -> Generator[str, None, None]: ... + class TracebackException: __cause__: TracebackException __context__: TracebackException @@ -107,7 +113,34 @@ class TracebackException: text: str offset: int msg: str - if sys.version_info >= (3, 10): + if sys.version_info >= (3, 11): + def __init__( + self, + exc_type: type[BaseException], + exc_value: BaseException, + exc_traceback: TracebackType | None, + *, + limit: int | None = ..., + lookup_lines: bool = ..., + capture_locals: bool = ..., + compact: bool = ..., + max_group_width: int = ..., + max_group_depth: int = ..., + _seen: set[int] | None = ..., + ) -> None: ... + @classmethod + def from_exception( + cls: type[Self], + exc: BaseException, + *, + limit: int | None = ..., + lookup_lines: bool = ..., + capture_locals: bool = ..., + compact: bool = ..., + max_group_width: int = ..., + max_group_depth: int = ..., + ) -> Self: ... + elif sys.version_info >= (3, 10): def __init__( self, exc_type: type[BaseException], @@ -148,9 +181,16 @@ class TracebackException: ) -> Self: ... def __eq__(self, other: object) -> bool: ... - def format(self, *, chain: bool = ...) -> Generator[str, None, None]: ... + if sys.version_info >= (3, 11): + def format(self, *, chain: bool = ..., _ctx: _ExceptionPrintContext | None = ...) -> Generator[str, None, None]: ... + else: + def format(self, *, chain: bool = ...) -> Generator[str, None, None]: ... + def format_exception_only(self) -> Generator[str, None, None]: ... + if sys.version_info >= (3, 11): + def print(self, *, file: SupportsWrite[str] | None = ..., chain: bool = ...) -> None: ... + class FrameSummary(Iterable[Any]): if sys.version_info >= (3, 11): def __init__( @@ -213,4 +253,7 @@ class StackSummary(list[FrameSummary]): ) -> StackSummary: ... @classmethod def from_list(cls, a_list: list[_PT]) -> StackSummary: ... + if sys.version_info >= (3, 11): + def format_frame_summary(self, frame_summary: FrameSummary) -> str: ... + def format(self) -> list[str]: ... diff --git a/mypy/typeshed/stdlib/turtle.pyi b/mypy/typeshed/stdlib/turtle.pyi index 3e91a5eb0ebf3..cdacaf63c41f5 100644 --- a/mypy/typeshed/stdlib/turtle.pyi +++ b/mypy/typeshed/stdlib/turtle.pyi @@ -142,9 +142,18 @@ _PenState: TypeAlias = dict[str, Any] _Speed: TypeAlias = str | float _PolygonCoords: TypeAlias = Sequence[tuple[float, float]] -# TODO: Type this more accurately -# Vec2D is actually a custom subclass of 'tuple'. -Vec2D: TypeAlias = tuple[float, float] +class Vec2D(tuple[float, float]): + def __new__(cls: type[Self], x: float, y: float) -> Self: ... + def __add__(self, other: tuple[float, float]) -> Vec2D: ... # type: ignore[override] + @overload # type: ignore[override] + def __mul__(self, other: Vec2D) -> float: ... + @overload + def __mul__(self, other: float) -> Vec2D: ... + def __rmul__(self, other: float) -> Vec2D: ... # type: ignore[override] + def __sub__(self, other: tuple[float, float]) -> Vec2D: ... + def __neg__(self) -> Vec2D: ... + def __abs__(self) -> float: ... + def rotate(self, angle: float) -> Vec2D: ... # Does not actually inherit from Canvas, but dynamically gets all methods of Canvas class ScrolledCanvas(Canvas, Frame): # type: ignore[misc] @@ -410,7 +419,11 @@ class _Screen(TurtleScreen): def __init__(self) -> None: ... # Note int and float are interpreted differently, hence the Union instead of just float def setup( - self, width: int | float = ..., height: int | float = ..., startx: int | None = ..., starty: int | None = ... + self, + width: int | float = ..., # noqa: Y041 + height: int | float = ..., # noqa: Y041 + startx: int | None = ..., + starty: int | None = ..., ) -> None: ... def title(self, titlestring: str) -> None: ... def bye(self) -> None: ... diff --git a/mypy/typeshed/stdlib/types.pyi b/mypy/typeshed/stdlib/types.pyi index ed2476e44a865..de8c8423d47ed 100644 --- a/mypy/typeshed/stdlib/types.pyi +++ b/mypy/typeshed/stdlib/types.pyi @@ -20,150 +20,47 @@ from importlib.machinery import ModuleSpec from typing import Any, ClassVar, Generic, Mapping, TypeVar, overload # noqa: Y027 from typing_extensions import Literal, ParamSpec, final -if sys.version_info >= (3, 10): - __all__ = [ - "FunctionType", - "LambdaType", - "CodeType", - "MappingProxyType", - "SimpleNamespace", - "CellType", - "GeneratorType", - "CoroutineType", - "AsyncGeneratorType", - "MethodType", - "BuiltinFunctionType", - "BuiltinMethodType", - "WrapperDescriptorType", - "MethodWrapperType", - "MethodDescriptorType", +__all__ = [ + "FunctionType", + "LambdaType", + "CodeType", + "MappingProxyType", + "SimpleNamespace", + "GeneratorType", + "CoroutineType", + "AsyncGeneratorType", + "MethodType", + "BuiltinFunctionType", + "ModuleType", + "TracebackType", + "FrameType", + "GetSetDescriptorType", + "MemberDescriptorType", + "new_class", + "prepare_class", + "DynamicClassAttribute", + "coroutine", + "BuiltinMethodType", +] + +if sys.version_info >= (3, 7): + __all__ += [ "ClassMethodDescriptorType", - "ModuleType", - "TracebackType", - "FrameType", - "GetSetDescriptorType", - "MemberDescriptorType", - "new_class", - "resolve_bases", - "prepare_class", - "DynamicClassAttribute", - "coroutine", - "GenericAlias", - "UnionType", - "EllipsisType", - "NoneType", - "NotImplementedType", - ] -elif sys.version_info >= (3, 9): - __all__ = [ - "FunctionType", - "LambdaType", - "CodeType", - "MappingProxyType", - "SimpleNamespace", - "CellType", - "GeneratorType", - "CoroutineType", - "AsyncGeneratorType", - "MethodType", - "BuiltinFunctionType", - "BuiltinMethodType", - "WrapperDescriptorType", - "MethodWrapperType", "MethodDescriptorType", - "ClassMethodDescriptorType", - "ModuleType", - "TracebackType", - "FrameType", - "GetSetDescriptorType", - "MemberDescriptorType", - "new_class", - "resolve_bases", - "prepare_class", - "DynamicClassAttribute", - "coroutine", - "GenericAlias", - ] -elif sys.version_info >= (3, 8): - __all__ = [ - "FunctionType", - "LambdaType", - "CodeType", - "MappingProxyType", - "SimpleNamespace", - "CellType", - "GeneratorType", - "CoroutineType", - "AsyncGeneratorType", - "MethodType", - "BuiltinFunctionType", - "BuiltinMethodType", - "WrapperDescriptorType", "MethodWrapperType", - "MethodDescriptorType", - "ClassMethodDescriptorType", - "ModuleType", - "TracebackType", - "FrameType", - "GetSetDescriptorType", - "MemberDescriptorType", - "new_class", - "resolve_bases", - "prepare_class", - "DynamicClassAttribute", - "coroutine", - ] -elif sys.version_info >= (3, 7): - __all__ = [ - "FunctionType", - "LambdaType", - "CodeType", - "MappingProxyType", - "SimpleNamespace", - "GeneratorType", - "CoroutineType", - "AsyncGeneratorType", - "MethodType", - "BuiltinFunctionType", - "BuiltinMethodType", "WrapperDescriptorType", - "MethodWrapperType", - "MethodDescriptorType", - "ClassMethodDescriptorType", - "ModuleType", - "TracebackType", - "FrameType", - "GetSetDescriptorType", - "MemberDescriptorType", - "new_class", "resolve_bases", - "prepare_class", - "DynamicClassAttribute", - "coroutine", - ] -else: - __all__ = [ - "FunctionType", - "LambdaType", - "CodeType", - "MappingProxyType", - "SimpleNamespace", - "GeneratorType", - "CoroutineType", - "AsyncGeneratorType", - "MethodType", - "BuiltinFunctionType", - "ModuleType", - "TracebackType", - "FrameType", - "GetSetDescriptorType", - "MemberDescriptorType", - "new_class", - "prepare_class", - "DynamicClassAttribute", - "coroutine", ] +if sys.version_info >= (3, 8): + __all__ += ["CellType"] + +if sys.version_info >= (3, 9): + __all__ += ["GenericAlias"] + +if sys.version_info >= (3, 10): + __all__ += ["EllipsisType", "NoneType", "NotImplementedType", "UnionType"] + # Note, all classes "defined" here require special handling. _T1 = TypeVar("_T1") @@ -250,46 +147,99 @@ class CodeType: def co_freevars(self) -> tuple[str, ...]: ... @property def co_cellvars(self) -> tuple[str, ...]: ... - if sys.version_info >= (3, 8): + if sys.version_info >= (3, 10): + @property + def co_linetable(self) -> bytes: ... + def co_lines(self) -> Iterator[tuple[int, int, int | None]]: ... + if sys.version_info >= (3, 11): + @property + def co_exceptiontable(self) -> bytes: ... + @property + def co_qualname(self) -> str: ... + def co_positions(self) -> Iterable[tuple[int | None, int | None, int | None, int | None]]: ... + + if sys.version_info >= (3, 11): + def __init__( + self, + __argcount: int, + __posonlyargcount: int, + __kwonlyargcount: int, + __nlocals: int, + __stacksize: int, + __flags: int, + __codestring: bytes, + __constants: tuple[object, ...], + __names: tuple[str, ...], + __varnames: tuple[str, ...], + __filename: str, + __name: str, + __qualname: str, + __firstlineno: int, + __linetable: bytes, + __exceptiontable: bytes, + __freevars: tuple[str, ...] = ..., + __cellvars: tuple[str, ...] = ..., + ) -> None: ... + elif sys.version_info >= (3, 10): + def __init__( + self, + __argcount: int, + __posonlyargcount: int, + __kwonlyargcount: int, + __nlocals: int, + __stacksize: int, + __flags: int, + __codestring: bytes, + __constants: tuple[object, ...], + __names: tuple[str, ...], + __varnames: tuple[str, ...], + __filename: str, + __name: str, + __firstlineno: int, + __linetable: bytes, + __freevars: tuple[str, ...] = ..., + __cellvars: tuple[str, ...] = ..., + ) -> None: ... + elif sys.version_info >= (3, 8): def __init__( self, - argcount: int, - posonlyargcount: int, - kwonlyargcount: int, - nlocals: int, - stacksize: int, - flags: int, - codestring: bytes, - constants: tuple[Any, ...], - names: tuple[str, ...], - varnames: tuple[str, ...], - filename: str, - name: str, - firstlineno: int, - lnotab: bytes, - freevars: tuple[str, ...] = ..., - cellvars: tuple[str, ...] = ..., + __argcount: int, + __posonlyargcount: int, + __kwonlyargcount: int, + __nlocals: int, + __stacksize: int, + __flags: int, + __codestring: bytes, + __constants: tuple[object, ...], + __names: tuple[str, ...], + __varnames: tuple[str, ...], + __filename: str, + __name: str, + __firstlineno: int, + __lnotab: bytes, + __freevars: tuple[str, ...] = ..., + __cellvars: tuple[str, ...] = ..., ) -> None: ... else: def __init__( self, - argcount: int, - kwonlyargcount: int, - nlocals: int, - stacksize: int, - flags: int, - codestring: bytes, - constants: tuple[Any, ...], - names: tuple[str, ...], - varnames: tuple[str, ...], - filename: str, - name: str, - firstlineno: int, - lnotab: bytes, - freevars: tuple[str, ...] = ..., - cellvars: tuple[str, ...] = ..., + __argcount: int, + __kwonlyargcount: int, + __nlocals: int, + __stacksize: int, + __flags: int, + __codestring: bytes, + __constants: tuple[object, ...], + __names: tuple[str, ...], + __varnames: tuple[str, ...], + __filename: str, + __name: str, + __firstlineno: int, + __lnotab: bytes, + __freevars: tuple[str, ...] = ..., + __cellvars: tuple[str, ...] = ..., ) -> None: ... - if sys.version_info >= (3, 10): + if sys.version_info >= (3, 11): def replace( self, *, @@ -301,18 +251,38 @@ class CodeType: co_flags: int = ..., co_firstlineno: int = ..., co_code: bytes = ..., - co_consts: tuple[Any, ...] = ..., + co_consts: tuple[object, ...] = ..., co_names: tuple[str, ...] = ..., co_varnames: tuple[str, ...] = ..., co_freevars: tuple[str, ...] = ..., co_cellvars: tuple[str, ...] = ..., co_filename: str = ..., co_name: str = ..., - co_linetable: object = ..., + co_qualname: str = ..., + co_linetable: bytes = ..., + co_exceptiontable: bytes = ..., + ) -> CodeType: ... + elif sys.version_info >= (3, 10): + def replace( + self, + *, + co_argcount: int = ..., + co_posonlyargcount: int = ..., + co_kwonlyargcount: int = ..., + co_nlocals: int = ..., + co_stacksize: int = ..., + co_flags: int = ..., + co_firstlineno: int = ..., + co_code: bytes = ..., + co_consts: tuple[object, ...] = ..., + co_names: tuple[str, ...] = ..., + co_varnames: tuple[str, ...] = ..., + co_freevars: tuple[str, ...] = ..., + co_cellvars: tuple[str, ...] = ..., + co_filename: str = ..., + co_name: str = ..., + co_linetable: bytes = ..., ) -> CodeType: ... - def co_lines(self) -> Iterator[tuple[int, int, int | None]]: ... - @property - def co_linetable(self) -> object: ... elif sys.version_info >= (3, 8): def replace( self, @@ -325,7 +295,7 @@ class CodeType: co_flags: int = ..., co_firstlineno: int = ..., co_code: bytes = ..., - co_consts: tuple[Any, ...] = ..., + co_consts: tuple[object, ...] = ..., co_names: tuple[str, ...] = ..., co_varnames: tuple[str, ...] = ..., co_freevars: tuple[str, ...] = ..., @@ -334,8 +304,6 @@ class CodeType: co_name: str = ..., co_lnotab: bytes = ..., ) -> CodeType: ... - if sys.version_info >= (3, 11): - def co_positions(self) -> Iterable[tuple[int | None, int | None, int | None, int | None]]: ... @final class MappingProxyType(Mapping[_KT, _VT_co], Generic[_KT, _VT_co]): @@ -386,6 +354,9 @@ class GeneratorType(Generator[_T_co, _T_contra, _V_co]): def gi_running(self) -> bool: ... @property def gi_yieldfrom(self) -> GeneratorType[_T_co, _T_contra, Any] | None: ... + if sys.version_info >= (3, 11): + @property + def gi_suspended(self) -> bool: ... __name__: str __qualname__: str def __iter__(self) -> GeneratorType[_T_co, _T_contra, _V_co]: ... @@ -439,6 +410,9 @@ class CoroutineType(Coroutine[_T_co, _T_contra, _V_co]): if sys.version_info >= (3, 7): @property def cr_origin(self) -> tuple[tuple[str, int, str], ...] | None: ... + if sys.version_info >= (3, 11): + @property + def cr_suspended(self) -> bool: ... def close(self) -> None: ... def __await__(self) -> Generator[Any, None, _V_co]: ... @@ -654,6 +628,8 @@ if sys.version_info >= (3, 9): if sys.version_info >= (3, 11): @property def __unpacked__(self) -> bool: ... + @property + def __typing_unpacked_tuple_args__(self) -> tuple[Any, ...] | None: ... def __getattr__(self, name: str) -> Any: ... # incomplete diff --git a/mypy/typeshed/stdlib/typing.pyi b/mypy/typeshed/stdlib/typing.pyi index 37ea55c9f2eff..969e61952d5f6 100644 --- a/mypy/typeshed/stdlib/typing.pyi +++ b/mypy/typeshed/stdlib/typing.pyi @@ -1,6 +1,6 @@ import collections # Needed by aliases like DefaultDict, see mypy issue 2986 import sys -from _typeshed import ReadableBuffer, Self as TypeshedSelf, SupportsKeysAndGetItem +from _typeshed import IdentityFunction, ReadableBuffer, Self as TypeshedSelf, SupportsKeysAndGetItem from abc import ABCMeta, abstractmethod from types import BuiltinFunctionType, CodeType, FrameType, FunctionType, MethodType, ModuleType, TracebackType from typing_extensions import Literal as _Literal, ParamSpec as _ParamSpec, final as _final @@ -11,466 +11,108 @@ if sys.version_info >= (3, 7): if sys.version_info >= (3, 9): from types import GenericAlias -if sys.version_info >= (3, 11): - __all__ = [ - "Annotated", - "Any", - "Callable", - "ClassVar", - "Concatenate", +__all__ = [ + "AbstractSet", + "Any", + "AnyStr", + "AsyncContextManager", + "AsyncGenerator", + "AsyncIterable", + "AsyncIterator", + "Awaitable", + "ByteString", + "Callable", + "ChainMap", + "ClassVar", + "Collection", + "Container", + "ContextManager", + "Coroutine", + "Counter", + "DefaultDict", + "Deque", + "Dict", + "FrozenSet", + "Generator", + "Generic", + "Hashable", + "ItemsView", + "Iterable", + "Iterator", + "KeysView", + "List", + "Mapping", + "MappingView", + "MutableMapping", + "MutableSequence", + "MutableSet", + "NamedTuple", + "NewType", + "Optional", + "Reversible", + "Sequence", + "Set", + "Sized", + "SupportsAbs", + "SupportsBytes", + "SupportsComplex", + "SupportsFloat", + "SupportsInt", + "SupportsRound", + "Text", + "Tuple", + "Type", + "TypeVar", + "Union", + "ValuesView", + "TYPE_CHECKING", + "cast", + "get_type_hints", + "no_type_check", + "no_type_check_decorator", + "overload", +] + +if sys.version_info < (3, 7): + __all__ += ["GenericMeta"] + +if sys.version_info >= (3, 7): + __all__ += ["ForwardRef", "NoReturn", "OrderedDict"] + +if sys.version_info >= (3, 8): + __all__ += [ "Final", - "ForwardRef", - "Generic", "Literal", + "Protocol", + "SupportsIndex", + "TypedDict", + "final", + "get_args", + "get_origin", + "runtime_checkable", + ] + +if sys.version_info >= (3, 9): + __all__ += ["Annotated", "BinaryIO", "IO", "Match", "Pattern", "TextIO"] + +if sys.version_info >= (3, 10): + __all__ += ["Concatenate", "ParamSpec", "ParamSpecArgs", "ParamSpecKwargs", "TypeAlias", "TypeGuard", "is_typeddict"] + +if sys.version_info >= (3, 11): + __all__ += [ "LiteralString", + "Never", "NotRequired", - "Optional", - "ParamSpec", - "Protocol", "Required", - "Tuple", - "Type", - "TypeVar", + "Self", "TypeVarTuple", - "Union", "Unpack", - "AbstractSet", - "ByteString", - "Container", - "ContextManager", - "Hashable", - "ItemsView", - "Iterable", - "Iterator", - "KeysView", - "Mapping", - "MappingView", - "MutableMapping", - "MutableSequence", - "MutableSet", - "Sequence", - "Sized", - "ValuesView", - "Awaitable", - "AsyncIterator", - "AsyncIterable", - "Coroutine", - "Collection", - "AsyncGenerator", - "AsyncContextManager", - "Reversible", - "SupportsAbs", - "SupportsBytes", - "SupportsComplex", - "SupportsFloat", - "SupportsIndex", - "SupportsInt", - "SupportsRound", - "ChainMap", - "Counter", - "Deque", - "Dict", - "DefaultDict", - "List", - "OrderedDict", - "Set", - "FrozenSet", - "NamedTuple", - "TypedDict", - "Generator", - "BinaryIO", - "IO", - "Match", - "Pattern", - "TextIO", - "AnyStr", "assert_never", "assert_type", - "cast", "clear_overloads", "dataclass_transform", - "final", - "get_args", - "get_origin", "get_overloads", - "get_type_hints", - "is_typeddict", - "Never", - "NewType", - "no_type_check", - "no_type_check_decorator", - "NoReturn", - "overload", - "ParamSpecArgs", - "ParamSpecKwargs", "reveal_type", - "runtime_checkable", - "Self", - "Text", - "TYPE_CHECKING", - "TypeAlias", - "TypeGuard", - ] -elif sys.version_info >= (3, 10): - __all__ = [ - "Annotated", - "Any", - "Callable", - "ClassVar", - "Concatenate", - "Final", - "ForwardRef", - "Generic", - "Literal", - "Optional", - "ParamSpec", - "Protocol", - "Tuple", - "Type", - "TypeVar", - "Union", - "AbstractSet", - "ByteString", - "Container", - "ContextManager", - "Hashable", - "ItemsView", - "Iterable", - "Iterator", - "KeysView", - "Mapping", - "MappingView", - "MutableMapping", - "MutableSequence", - "MutableSet", - "Sequence", - "Sized", - "ValuesView", - "Awaitable", - "AsyncIterator", - "AsyncIterable", - "Coroutine", - "Collection", - "AsyncGenerator", - "AsyncContextManager", - "Reversible", - "SupportsAbs", - "SupportsBytes", - "SupportsComplex", - "SupportsFloat", - "SupportsIndex", - "SupportsInt", - "SupportsRound", - "ChainMap", - "Counter", - "Deque", - "Dict", - "DefaultDict", - "List", - "OrderedDict", - "Set", - "FrozenSet", - "NamedTuple", - "TypedDict", - "Generator", - "BinaryIO", - "IO", - "Match", - "Pattern", - "TextIO", - "AnyStr", - "cast", - "final", - "get_args", - "get_origin", - "get_type_hints", - "is_typeddict", - "NewType", - "no_type_check", - "no_type_check_decorator", - "NoReturn", - "overload", - "ParamSpecArgs", - "ParamSpecKwargs", - "runtime_checkable", - "Text", - "TYPE_CHECKING", - "TypeAlias", - "TypeGuard", - ] -elif sys.version_info >= (3, 9): - __all__ = [ - "Annotated", - "Any", - "Callable", - "ClassVar", - "Final", - "ForwardRef", - "Generic", - "Literal", - "Optional", - "Protocol", - "Tuple", - "Type", - "TypeVar", - "Union", - "AbstractSet", - "ByteString", - "Container", - "ContextManager", - "Hashable", - "ItemsView", - "Iterable", - "Iterator", - "KeysView", - "Mapping", - "MappingView", - "MutableMapping", - "MutableSequence", - "MutableSet", - "Sequence", - "Sized", - "ValuesView", - "Awaitable", - "AsyncIterator", - "AsyncIterable", - "Coroutine", - "Collection", - "AsyncGenerator", - "AsyncContextManager", - "Reversible", - "SupportsAbs", - "SupportsBytes", - "SupportsComplex", - "SupportsFloat", - "SupportsIndex", - "SupportsInt", - "SupportsRound", - "ChainMap", - "Counter", - "Deque", - "Dict", - "DefaultDict", - "List", - "OrderedDict", - "Set", - "FrozenSet", - "NamedTuple", - "TypedDict", - "Generator", - "BinaryIO", - "IO", - "Match", - "Pattern", - "TextIO", - "AnyStr", - "cast", - "final", - "get_args", - "get_origin", - "get_type_hints", - "NewType", - "no_type_check", - "no_type_check_decorator", - "NoReturn", - "overload", - "runtime_checkable", - "Text", - "TYPE_CHECKING", - ] -elif sys.version_info >= (3, 8): - __all__ = [ - "Any", - "Callable", - "ClassVar", - "Final", - "ForwardRef", - "Generic", - "Literal", - "Optional", - "Protocol", - "Tuple", - "Type", - "TypeVar", - "Union", - "AbstractSet", - "ByteString", - "Container", - "ContextManager", - "Hashable", - "ItemsView", - "Iterable", - "Iterator", - "KeysView", - "Mapping", - "MappingView", - "MutableMapping", - "MutableSequence", - "MutableSet", - "Sequence", - "Sized", - "ValuesView", - "Awaitable", - "AsyncIterator", - "AsyncIterable", - "Coroutine", - "Collection", - "AsyncGenerator", - "AsyncContextManager", - "Reversible", - "SupportsAbs", - "SupportsBytes", - "SupportsComplex", - "SupportsFloat", - "SupportsIndex", - "SupportsInt", - "SupportsRound", - "ChainMap", - "Counter", - "Deque", - "Dict", - "DefaultDict", - "List", - "OrderedDict", - "Set", - "FrozenSet", - "NamedTuple", - "TypedDict", - "Generator", - "AnyStr", - "cast", - "final", - "get_args", - "get_origin", - "get_type_hints", - "NewType", - "no_type_check", - "no_type_check_decorator", - "NoReturn", - "overload", - "runtime_checkable", - "Text", - "TYPE_CHECKING", - ] -elif sys.version_info >= (3, 7): - __all__ = [ - "Any", - "Callable", - "ClassVar", - "ForwardRef", - "Generic", - "Optional", - "Tuple", - "Type", - "TypeVar", - "Union", - "AbstractSet", - "ByteString", - "Container", - "ContextManager", - "Hashable", - "ItemsView", - "Iterable", - "Iterator", - "KeysView", - "Mapping", - "MappingView", - "MutableMapping", - "MutableSequence", - "MutableSet", - "Sequence", - "Sized", - "ValuesView", - "Awaitable", - "AsyncIterator", - "AsyncIterable", - "Coroutine", - "Collection", - "AsyncGenerator", - "AsyncContextManager", - "Reversible", - "SupportsAbs", - "SupportsBytes", - "SupportsComplex", - "SupportsFloat", - "SupportsInt", - "SupportsRound", - "ChainMap", - "Counter", - "Deque", - "Dict", - "DefaultDict", - "List", - "OrderedDict", - "Set", - "FrozenSet", - "NamedTuple", - "Generator", - "AnyStr", - "cast", - "get_type_hints", - "NewType", - "no_type_check", - "no_type_check_decorator", - "NoReturn", - "overload", - "Text", - "TYPE_CHECKING", - ] -else: - __all__ = [ - "Any", - "Callable", - "ClassVar", - "Generic", - "Optional", - "Tuple", - "Type", - "TypeVar", - "Union", - "AbstractSet", - "GenericMeta", - "ByteString", - "Container", - "ContextManager", - "Hashable", - "ItemsView", - "Iterable", - "Iterator", - "KeysView", - "Mapping", - "MappingView", - "MutableMapping", - "MutableSequence", - "MutableSet", - "Sequence", - "Sized", - "ValuesView", - "Reversible", - "SupportsAbs", - "SupportsBytes", - "SupportsComplex", - "SupportsFloat", - "SupportsInt", - "SupportsRound", - "Counter", - "Deque", - "Dict", - "DefaultDict", - "List", - "Set", - "FrozenSet", - "NamedTuple", - "Generator", - "AnyStr", - "cast", - "get_type_hints", - "NewType", - "no_type_check", - "no_type_check_decorator", - "overload", - "Text", - "TYPE_CHECKING", ] Any = object() @@ -1232,7 +874,7 @@ if sys.version_info >= (3, 11): kw_only_default: bool = ..., field_specifiers: tuple[type[Any] | Callable[..., Any], ...] = ..., **kwargs: Any, - ) -> Callable[[_T], _T]: ... + ) -> IdentityFunction: ... # Type constructors diff --git a/mypy/typeshed/stdlib/typing_extensions.pyi b/mypy/typeshed/stdlib/typing_extensions.pyi index b94daaba9f498..38fb9dec19d9b 100644 --- a/mypy/typeshed/stdlib/typing_extensions.pyi +++ b/mypy/typeshed/stdlib/typing_extensions.pyi @@ -1,6 +1,6 @@ import abc import sys -from _typeshed import Self as TypeshedSelf # see #6932 for why the alias cannot have a leading underscore +from _typeshed import IdentityFunction, Self as TypeshedSelf # see #6932 for why the Self alias cannot have a leading underscore from typing import ( # noqa: Y022,Y027,Y039 TYPE_CHECKING as TYPE_CHECKING, Any, @@ -232,4 +232,4 @@ else: kw_only_default: bool = ..., field_specifiers: tuple[type[Any] | Callable[..., Any], ...] = ..., **kwargs: object, - ) -> Callable[[_T], _T]: ... + ) -> IdentityFunction: ... diff --git a/mypy/typeshed/stdlib/unicodedata.pyi b/mypy/typeshed/stdlib/unicodedata.pyi index aec8867df48d9..7337ab8789b23 100644 --- a/mypy/typeshed/stdlib/unicodedata.pyi +++ b/mypy/typeshed/stdlib/unicodedata.pyi @@ -38,6 +38,9 @@ class UCD: def decomposition(self, __chr: str) -> str: ... def digit(self, __chr: str, __default: _T = ...) -> int | _T: ... def east_asian_width(self, __chr: str) -> str: ... + if sys.version_info >= (3, 8): + def is_normalized(self, __form: str, __unistr: str) -> bool: ... + def lookup(self, __name: str | bytes) -> str: ... def mirrored(self, __chr: str) -> int: ... def name(self, __chr: str, __default: _T = ...) -> str | _T: ... diff --git a/mypy/typeshed/stdlib/unittest/__init__.pyi b/mypy/typeshed/stdlib/unittest/__init__.pyi index 4bbf98c992c1a..673597275b33e 100644 --- a/mypy/typeshed/stdlib/unittest/__init__.pyi +++ b/mypy/typeshed/stdlib/unittest/__init__.pyi @@ -32,55 +32,37 @@ if sys.version_info >= (3, 8): from .case import addModuleCleanup as addModuleCleanup - __all__ = [ - "TestResult", - "TestCase", - "IsolatedAsyncioTestCase", - "TestSuite", - "TextTestRunner", - "TestLoader", - "FunctionTestCase", - "main", - "defaultTestLoader", - "SkipTest", - "skip", - "skipIf", - "skipUnless", - "expectedFailure", - "TextTestResult", - "installHandler", - "registerResult", - "removeResult", - "removeHandler", - "addModuleCleanup", - "getTestCaseNames", - "makeSuite", - "findTestCases", - ] +if sys.version_info >= (3, 11): + from .case import doModuleCleanups as doModuleCleanups, enterModuleContext as enterModuleContext -else: - __all__ = [ - "TestResult", - "TestCase", - "TestSuite", - "TextTestRunner", - "TestLoader", - "FunctionTestCase", - "main", - "defaultTestLoader", - "SkipTest", - "skip", - "skipIf", - "skipUnless", - "expectedFailure", - "TextTestResult", - "installHandler", - "registerResult", - "removeResult", - "removeHandler", - "getTestCaseNames", - "makeSuite", - "findTestCases", - ] +__all__ = [ + "TestResult", + "TestCase", + "TestSuite", + "TextTestRunner", + "TestLoader", + "FunctionTestCase", + "main", + "defaultTestLoader", + "SkipTest", + "skip", + "skipIf", + "skipUnless", + "expectedFailure", + "TextTestResult", + "installHandler", + "registerResult", + "removeResult", + "removeHandler", + "getTestCaseNames", + "makeSuite", + "findTestCases", +] + +if sys.version_info >= (3, 8): + __all__ += ["addModuleCleanup", "IsolatedAsyncioTestCase"] + +if sys.version_info >= (3, 11): + __all__ += ["enterModuleContext", "doModuleCleanups"] def load_tests(loader: TestLoader, tests: TestSuite, pattern: str | None) -> TestSuite: ... diff --git a/mypy/typeshed/stdlib/unittest/async_case.pyi b/mypy/typeshed/stdlib/unittest/async_case.pyi index 55407ec3f1c8f..c1de205fbd559 100644 --- a/mypy/typeshed/stdlib/unittest/async_case.pyi +++ b/mypy/typeshed/stdlib/unittest/async_case.pyi @@ -1,11 +1,19 @@ +import sys from collections.abc import Awaitable, Callable +from typing import TypeVar from typing_extensions import ParamSpec from .case import TestCase +if sys.version_info >= (3, 11): + from contextlib import AbstractAsyncContextManager + +_T = TypeVar("_T") _P = ParamSpec("_P") class IsolatedAsyncioTestCase(TestCase): async def asyncSetUp(self) -> None: ... async def asyncTearDown(self) -> None: ... def addAsyncCleanup(self, __func: Callable[_P, Awaitable[object]], *args: _P.args, **kwargs: _P.kwargs) -> None: ... + if sys.version_info >= (3, 11): + async def enterAsyncContext(self, cm: AbstractAsyncContextManager[_T]) -> _T: ... diff --git a/mypy/typeshed/stdlib/unittest/case.pyi b/mypy/typeshed/stdlib/unittest/case.pyi index 578bd6d6f271d..15b573edeebbc 100644 --- a/mypy/typeshed/stdlib/unittest/case.pyi +++ b/mypy/typeshed/stdlib/unittest/case.pyi @@ -1,18 +1,32 @@ -import datetime import logging import sys import unittest.result -from _typeshed import Self +from _typeshed import Self, SupportsDunderGE, SupportsSub from collections.abc import Callable, Container, Iterable, Mapping, Sequence, Set as AbstractSet from contextlib import AbstractContextManager from types import TracebackType -from typing import Any, AnyStr, ClassVar, Generic, NamedTuple, NoReturn, Pattern, TypeVar, overload +from typing import ( + Any, + AnyStr, + ClassVar, + Generic, + NamedTuple, + NoReturn, + Pattern, + Protocol, + SupportsAbs, + SupportsRound, + TypeVar, + overload, +) from typing_extensions import ParamSpec from warnings import WarningMessage if sys.version_info >= (3, 9): from types import GenericAlias +_T = TypeVar("_T") +_S = TypeVar("_S", bound=SupportsSub[Any, Any]) _E = TypeVar("_E", bound=BaseException) _FT = TypeVar("_FT", bound=Callable[..., Any]) _P = ParamSpec("_P") @@ -50,6 +64,9 @@ if sys.version_info >= (3, 8): def addModuleCleanup(__function: Callable[_P, object], *args: _P.args, **kwargs: _P.kwargs) -> None: ... def doModuleCleanups() -> None: ... +if sys.version_info >= (3, 11): + def enterModuleContext(cm: AbstractContextManager[_T]) -> _T: ... + def expectedFailure(test_item: _FT) -> _FT: ... def skip(reason: str) -> Callable[[_FT], _FT]: ... def skipIf(condition: object, reason: str) -> Callable[[_FT], _FT]: ... @@ -58,6 +75,8 @@ def skipUnless(condition: object, reason: str) -> Callable[[_FT], _FT]: ... class SkipTest(Exception): def __init__(self, reason: str) -> None: ... +class _SupportsAbsAndDunderGE(SupportsDunderGE, SupportsAbs[Any], Protocol): ... + class TestCase: failureException: type[BaseException] longMessage: bool @@ -79,7 +98,9 @@ class TestCase: def skipTest(self, reason: Any) -> None: ... def subTest(self, msg: Any = ..., **params: Any) -> AbstractContextManager[None]: ... def debug(self) -> None: ... - def _addSkip(self, result: unittest.result.TestResult, test_case: TestCase, reason: str) -> None: ... + if sys.version_info < (3, 11): + def _addSkip(self, result: unittest.result.TestResult, test_case: TestCase, reason: str) -> None: ... + def assertEqual(self, first: Any, second: Any, msg: Any = ...) -> None: ... def assertNotEqual(self, first: Any, second: Any, msg: Any = ...) -> None: ... def assertTrue(self, expr: Any, msg: Any = ...) -> None: ... @@ -159,33 +180,35 @@ class TestCase: self, logger: str | logging.Logger | None = ..., level: int | str | None = ... ) -> _AssertLogsContext[None]: ... + @overload + def assertAlmostEqual(self, first: _S, second: _S, places: None, msg: Any, delta: _SupportsAbsAndDunderGE) -> None: ... @overload def assertAlmostEqual( - self, first: float, second: float, places: int | None = ..., msg: Any = ..., delta: float | None = ... + self, first: _S, second: _S, places: None = ..., msg: Any = ..., *, delta: _SupportsAbsAndDunderGE ) -> None: ... @overload def assertAlmostEqual( self, - first: datetime.datetime, - second: datetime.datetime, + first: SupportsSub[_T, SupportsAbs[SupportsRound[object]]], + second: _T, places: int | None = ..., msg: Any = ..., - delta: datetime.timedelta | None = ..., + delta: None = ..., ) -> None: ... @overload - def assertNotAlmostEqual(self, first: float, second: float, *, msg: Any = ...) -> None: ... - @overload - def assertNotAlmostEqual(self, first: float, second: float, places: int | None = ..., msg: Any = ...) -> None: ... + def assertNotAlmostEqual(self, first: _S, second: _S, places: None, msg: Any, delta: _SupportsAbsAndDunderGE) -> None: ... @overload - def assertNotAlmostEqual(self, first: float, second: float, *, msg: Any = ..., delta: float | None = ...) -> None: ... + def assertNotAlmostEqual( + self, first: _S, second: _S, places: None = ..., msg: Any = ..., *, delta: _SupportsAbsAndDunderGE + ) -> None: ... @overload def assertNotAlmostEqual( self, - first: datetime.datetime, - second: datetime.datetime, + first: SupportsSub[_T, SupportsAbs[SupportsRound[object]]], + second: _T, places: int | None = ..., msg: Any = ..., - delta: datetime.timedelta | None = ..., + delta: None = ..., ) -> None: ... def assertRegex(self, text: AnyStr, expected_regex: AnyStr | Pattern[AnyStr], msg: Any = ...) -> None: ... def assertNotRegex(self, text: AnyStr, unexpected_regex: AnyStr | Pattern[AnyStr], msg: Any = ...) -> None: ... @@ -209,6 +232,9 @@ class TestCase: else: def addCleanup(self, function: Callable[_P, object], *args: _P.args, **kwargs: _P.kwargs) -> None: ... + if sys.version_info >= (3, 11): + def enterContext(self, cm: AbstractContextManager[_T]) -> _T: ... + def doCleanups(self) -> None: ... if sys.version_info >= (3, 8): @classmethod @@ -216,6 +242,10 @@ class TestCase: @classmethod def doClassCleanups(cls) -> None: ... + if sys.version_info >= (3, 11): + @classmethod + def enterClassContext(cls, cm: AbstractContextManager[_T]) -> _T: ... + def _formatMessage(self, msg: str | None, standardMsg: str) -> str: ... # undocumented def _getAssertEqualityFunc(self, first: Any, second: Any) -> Callable[..., None]: ... # undocumented if sys.version_info < (3, 12): @@ -236,14 +266,10 @@ class TestCase: ) -> None: ... @overload def failUnlessRaises(self, exception: type[_E] | tuple[type[_E], ...], msg: Any = ...) -> _AssertRaisesContext[_E]: ... - def failUnlessAlmostEqual(self, first: float, second: float, places: int = ..., msg: Any = ...) -> None: ... - def assertAlmostEquals( - self, first: float, second: float, places: int = ..., msg: Any = ..., delta: float = ... - ) -> None: ... - def failIfAlmostEqual(self, first: float, second: float, places: int = ..., msg: Any = ...) -> None: ... - def assertNotAlmostEquals( - self, first: float, second: float, places: int = ..., msg: Any = ..., delta: float = ... - ) -> None: ... + failUnlessAlmostEqual = assertAlmostEqual + assertAlmostEquals = assertAlmostEqual + failIfAlmostEqual = assertNotAlmostEqual + assertNotAlmostEquals = assertNotAlmostEqual def assertRegexpMatches(self, text: AnyStr, regex: AnyStr | Pattern[AnyStr], msg: Any = ...) -> None: ... def assertNotRegexpMatches(self, text: AnyStr, regex: AnyStr | Pattern[AnyStr], msg: Any = ...) -> None: ... @overload diff --git a/mypy/typeshed/stdlib/unittest/mock.pyi b/mypy/typeshed/stdlib/unittest/mock.pyi index 400bdaac3b41e..a7111ff2d0904 100644 --- a/mypy/typeshed/stdlib/unittest/mock.pyi +++ b/mypy/typeshed/stdlib/unittest/mock.pyi @@ -440,7 +440,13 @@ class _SpecState: def mock_open(mock: Any | None = ..., read_data: Any = ...) -> Any: ... -PropertyMock = Any +class PropertyMock(Mock): + if sys.version_info >= (3, 8): + def __get__(self: Self, obj: _T, obj_type: type[_T] | None = ...) -> Self: ... + else: + def __get__(self: Self, obj: _T, obj_type: type[_T] | None) -> Self: ... + + def __set__(self, obj: Any, value: Any) -> None: ... if sys.version_info >= (3, 7): def seal(mock: Any) -> None: ... diff --git a/mypy/typeshed/stdlib/urllib/parse.pyi b/mypy/typeshed/stdlib/urllib/parse.pyi index c6a6836e6e958..49f3825e0821e 100644 --- a/mypy/typeshed/stdlib/urllib/parse.pyi +++ b/mypy/typeshed/stdlib/urllib/parse.pyi @@ -39,7 +39,8 @@ non_hierarchical: list[str] uses_query: list[str] uses_fragment: list[str] scheme_chars: str -MAX_CACHE_SIZE: int +if sys.version_info < (3, 11): + MAX_CACHE_SIZE: int class _ResultMixinBase(Generic[AnyStr]): def geturl(self) -> AnyStr: ... diff --git a/mypy/typeshed/stdlib/urllib/request.pyi b/mypy/typeshed/stdlib/urllib/request.pyi index 5e6dde01480ab..02ad1bd300524 100644 --- a/mypy/typeshed/stdlib/urllib/request.pyi +++ b/mypy/typeshed/stdlib/urllib/request.pyi @@ -150,6 +150,10 @@ class HTTPRedirectHandler(BaseHandler): def http_error_302(self, req: Request, fp: IO[bytes], code: int, msg: str, headers: HTTPMessage) -> _UrlopenRet | None: ... def http_error_303(self, req: Request, fp: IO[bytes], code: int, msg: str, headers: HTTPMessage) -> _UrlopenRet | None: ... def http_error_307(self, req: Request, fp: IO[bytes], code: int, msg: str, headers: HTTPMessage) -> _UrlopenRet | None: ... + if sys.version_info >= (3, 11): + def http_error_308( + self, req: Request, fp: IO[bytes], code: int, msg: str, headers: HTTPMessage + ) -> _UrlopenRet | None: ... class HTTPCookieProcessor(BaseHandler): cookiejar: CookieJar @@ -330,6 +334,11 @@ class FancyURLopener(URLopener): def http_error_307( self, url: str, fp: IO[bytes], errcode: int, errmsg: str, headers: HTTPMessage, data: bytes | None = ... ) -> _UrlopenRet | addinfourl | None: ... # undocumented + if sys.version_info >= (3, 11): + def http_error_308( + self, url: str, fp: IO[bytes], errcode: int, errmsg: str, headers: HTTPMessage, data: bytes | None = ... + ) -> _UrlopenRet | addinfourl | None: ... # undocumented + def http_error_401( self, url: str, diff --git a/mypy/typeshed/stdlib/xml/etree/ElementTree.pyi b/mypy/typeshed/stdlib/xml/etree/ElementTree.pyi index dacb6fffcc6be..82cd735bd829a 100644 --- a/mypy/typeshed/stdlib/xml/etree/ElementTree.pyi +++ b/mypy/typeshed/stdlib/xml/etree/ElementTree.pyi @@ -1,92 +1,41 @@ import sys +from _collections_abc import dict_keys from _typeshed import FileDescriptor, StrOrBytesPath, SupportsRead, SupportsWrite -from collections.abc import Callable, Generator, ItemsView, Iterable, Iterator, KeysView, Mapping, MutableSequence, Sequence +from collections.abc import Callable, Generator, ItemsView, Iterable, Iterator, Mapping, Sequence from typing import Any, TypeVar, overload from typing_extensions import Literal, SupportsIndex, TypeAlias, TypeGuard +__all__ = [ + "Comment", + "dump", + "Element", + "ElementTree", + "fromstring", + "fromstringlist", + "iselement", + "iterparse", + "parse", + "ParseError", + "PI", + "ProcessingInstruction", + "QName", + "SubElement", + "tostring", + "tostringlist", + "TreeBuilder", + "VERSION", + "XML", + "XMLID", + "XMLParser", + "XMLPullParser", + "register_namespace", +] + +if sys.version_info >= (3, 8): + __all__ += ["C14NWriterTarget", "canonicalize"] + if sys.version_info >= (3, 9): - __all__ = [ - "Comment", - "dump", - "Element", - "ElementTree", - "fromstring", - "fromstringlist", - "indent", - "iselement", - "iterparse", - "parse", - "ParseError", - "PI", - "ProcessingInstruction", - "QName", - "SubElement", - "tostring", - "tostringlist", - "TreeBuilder", - "VERSION", - "XML", - "XMLID", - "XMLParser", - "XMLPullParser", - "register_namespace", - "canonicalize", - "C14NWriterTarget", - ] -elif sys.version_info >= (3, 8): - __all__ = [ - "Comment", - "dump", - "Element", - "ElementTree", - "fromstring", - "fromstringlist", - "iselement", - "iterparse", - "parse", - "ParseError", - "PI", - "ProcessingInstruction", - "QName", - "SubElement", - "tostring", - "tostringlist", - "TreeBuilder", - "VERSION", - "XML", - "XMLID", - "XMLParser", - "XMLPullParser", - "register_namespace", - "canonicalize", - "C14NWriterTarget", - ] -else: - __all__ = [ - "Comment", - "dump", - "Element", - "ElementTree", - "fromstring", - "fromstringlist", - "iselement", - "iterparse", - "parse", - "ParseError", - "PI", - "ProcessingInstruction", - "QName", - "SubElement", - "tostring", - "tostringlist", - "TreeBuilder", - "VERSION", - "XML", - "XMLID", - "XMLParser", - "XMLPullParser", - "register_namespace", - ] + __all__ += ["indent"] _T = TypeVar("_T") _FileRead: TypeAlias = StrOrBytesPath | FileDescriptor | SupportsRead[bytes] | SupportsRead[str] @@ -132,7 +81,7 @@ if sys.version_info >= (3, 8): exclude_tags: Iterable[str] | None = ..., ) -> None: ... -class Element(MutableSequence[Element]): +class Element: tag: str attrib: dict[str, str] text: str | None @@ -156,7 +105,7 @@ class Element(MutableSequence[Element]): def iter(self, tag: str | None = ...) -> Generator[Element, None, None]: ... def iterfind(self, path: str, namespaces: dict[str, str] | None = ...) -> Generator[Element, None, None]: ... def itertext(self) -> Generator[str, None, None]: ... - def keys(self) -> KeysView[str]: ... + def keys(self) -> dict_keys[str, str]: ... # makeelement returns the type of self in Python impl, but not in C impl def makeelement(self, __tag: str, __attrib: dict[str, str]) -> Element: ... def remove(self, __subelement: Element) -> None: ... @@ -167,8 +116,10 @@ class Element(MutableSequence[Element]): @overload def __getitem__(self, __i: SupportsIndex) -> Element: ... @overload - def __getitem__(self, __s: slice) -> MutableSequence[Element]: ... + def __getitem__(self, __s: slice) -> list[Element]: ... def __len__(self) -> int: ... + # Doesn't actually exist at runtime, but instance of the class are indeed iterable due to __getitem__. + def __iter__(self) -> Iterator[Element]: ... @overload def __setitem__(self, __i: SupportsIndex, __o: Element) -> None: ... @overload @@ -194,7 +145,7 @@ class QName: class ElementTree: def __init__(self, element: Element | None = ..., file: _FileRead | None = ...) -> None: ... - def getroot(self) -> Element: ... + def getroot(self) -> Element | Any: ... def parse(self, source: _FileRead, parser: XMLParser | None = ...) -> Element: ... def iter(self, tag: str | None = ...) -> Generator[Element, None, None]: ... if sys.version_info < (3, 9): @@ -321,7 +272,9 @@ class XMLPullParser: def __init__(self, events: Sequence[str] | None = ..., *, _parser: XMLParser | None = ...) -> None: ... def feed(self, data: str | bytes) -> None: ... def close(self) -> None: ... - def read_events(self) -> Iterator[tuple[str, Element]]: ... + # Second element in the tuple could be `Element`, `tuple[str, str]` or `None`. + # Use `Any` to avoid false-positive errors. + def read_events(self) -> Iterator[tuple[str, Any]]: ... def XML(text: str | bytes, parser: XMLParser | None = ...) -> Element: ... def XMLID(text: str | bytes, parser: XMLParser | None = ...) -> tuple[Element, dict[str, Element]]: ... diff --git a/mypy/typeshed/stdlib/xml/sax/handler.pyi b/mypy/typeshed/stdlib/xml/sax/handler.pyi index 3a51933009816..abf124f836cde 100644 --- a/mypy/typeshed/stdlib/xml/sax/handler.pyi +++ b/mypy/typeshed/stdlib/xml/sax/handler.pyi @@ -1,6 +1,6 @@ -from typing import Any +import sys -version: Any +version: str class ErrorHandler: def error(self, exception): ... @@ -30,17 +30,25 @@ class DTDHandler: class EntityResolver: def resolveEntity(self, publicId, systemId): ... -feature_namespaces: Any -feature_namespace_prefixes: Any -feature_string_interning: Any -feature_validation: Any -feature_external_ges: Any -feature_external_pes: Any -all_features: Any -property_lexical_handler: Any -property_declaration_handler: Any -property_dom_node: Any -property_xml_string: Any -property_encoding: Any -property_interning_dict: Any -all_properties: Any +feature_namespaces: str +feature_namespace_prefixes: str +feature_string_interning: str +feature_validation: str +feature_external_ges: str +feature_external_pes: str +all_features: list[str] +property_lexical_handler: str +property_declaration_handler: str +property_dom_node: str +property_xml_string: str +property_encoding: str +property_interning_dict: str +all_properties: list[str] + +if sys.version_info >= (3, 10): + class LexicalHandler: + def comment(self, content: str) -> object: ... + def startDTD(self, name: str, public_id: str | None, system_id: str | None) -> object: ... + def endDTD(self) -> object: ... + def startCDATA(self) -> object: ... + def endCDATA(self) -> object: ... diff --git a/mypy/typeshed/stdlib/xmlrpc/server.pyi b/mypy/typeshed/stdlib/xmlrpc/server.pyi index 371f1821b29d4..237620f702502 100644 --- a/mypy/typeshed/stdlib/xmlrpc/server.pyi +++ b/mypy/typeshed/stdlib/xmlrpc/server.pyi @@ -4,7 +4,7 @@ import socketserver import sys from collections.abc import Callable, Iterable, Mapping from datetime import datetime -from typing import Any, Pattern, Protocol +from typing import Any, ClassVar, Pattern, Protocol from typing_extensions import TypeAlias from xmlrpc.client import Fault @@ -68,8 +68,7 @@ class SimpleXMLRPCDispatcher: # undocumented def _dispatch(self, method: str, params: Iterable[_Marshallable]) -> _Marshallable: ... # undocumented class SimpleXMLRPCRequestHandler(http.server.BaseHTTPRequestHandler): - - rpc_paths: tuple[str, str] + rpc_paths: ClassVar[tuple[str, ...]] encode_threshold: int # undocumented aepattern: Pattern[str] # undocumented def accept_encodings(self) -> dict[str, float]: ... diff --git a/mypy/typeshed/stdlib/zipfile.pyi b/mypy/typeshed/stdlib/zipfile.pyi index 276f8df82a6de..c799cf9b4e128 100644 --- a/mypy/typeshed/stdlib/zipfile.pyi +++ b/mypy/typeshed/stdlib/zipfile.pyi @@ -7,37 +7,23 @@ from types import TracebackType from typing import IO, Any, Protocol, overload from typing_extensions import Literal, TypeAlias +__all__ = [ + "BadZipFile", + "BadZipfile", + "error", + "ZIP_STORED", + "ZIP_DEFLATED", + "ZIP_BZIP2", + "ZIP_LZMA", + "is_zipfile", + "ZipInfo", + "ZipFile", + "PyZipFile", + "LargeZipFile", +] + if sys.version_info >= (3, 8): - __all__ = [ - "BadZipFile", - "BadZipfile", - "error", - "ZIP_STORED", - "ZIP_DEFLATED", - "ZIP_BZIP2", - "ZIP_LZMA", - "is_zipfile", - "ZipInfo", - "ZipFile", - "PyZipFile", - "LargeZipFile", - "Path", - ] -else: - __all__ = [ - "BadZipFile", - "BadZipfile", - "error", - "ZIP_STORED", - "ZIP_DEFLATED", - "ZIP_BZIP2", - "ZIP_LZMA", - "is_zipfile", - "ZipInfo", - "ZipFile", - "PyZipFile", - "LargeZipFile", - ] + __all__ += ["Path"] _DateTuple: TypeAlias = tuple[int, int, int, int, int, int] _ReadWriteMode: TypeAlias = Literal["r", "w"] @@ -158,7 +144,32 @@ class ZipFile: compresslevel: int | None # undocumented mode: _ZipFileMode # undocumented pwd: str | None # undocumented - if sys.version_info >= (3, 8): + if sys.version_info >= (3, 11): + @overload + def __init__( + self, + file: StrPath | IO[bytes], + mode: Literal["r"] = ..., + compression: int = ..., + allowZip64: bool = ..., + compresslevel: int | None = ..., + *, + strict_timestamps: bool = ..., + metadata_encoding: str | None, + ) -> None: ... + @overload + def __init__( + self, + file: StrPath | IO[bytes], + mode: _ZipFileMode = ..., + compression: int = ..., + allowZip64: bool = ..., + compresslevel: int | None = ..., + *, + strict_timestamps: bool = ..., + metadata_encoding: None = ..., + ) -> None: ... + elif sys.version_info >= (3, 8): def __init__( self, file: StrPath | IO[bytes], @@ -223,7 +234,7 @@ class ZipFile: else: def writestr(self, zinfo_or_arcname: str | ZipInfo, data: bytes | str, compress_type: int | None = ...) -> None: ... if sys.version_info >= (3, 11): - def mkdir(self, zinfo_or_directory: str | ZipInfo, mode: int = ...) -> None: ... + def mkdir(self, zinfo_or_directory_name: str | ZipInfo, mode: int = ...) -> None: ... class PyZipFile(ZipFile): def __init__( @@ -275,6 +286,13 @@ if sys.version_info >= (3, 8): if sys.version_info >= (3, 10): @property def filename(self) -> PathLike[str]: ... # undocumented + if sys.version_info >= (3, 11): + @property + def suffix(self) -> str: ... + @property + def suffixes(self) -> list[str]: ... + @property + def stem(self) -> str: ... def __init__(self, root: ZipFile | StrPath | IO[bytes], at: str = ...) -> None: ... if sys.version_info >= (3, 9): diff --git a/mypy/typeshed/stubs/mypy-extensions/mypy_extensions.pyi b/mypy/typeshed/stubs/mypy-extensions/mypy_extensions.pyi index 412c3cb15142f..bf8d72ba8393d 100644 --- a/mypy/typeshed/stubs/mypy-extensions/mypy_extensions.pyi +++ b/mypy/typeshed/stubs/mypy-extensions/mypy_extensions.pyi @@ -1,7 +1,7 @@ import abc -from _typeshed import Self -from collections.abc import Callable, ItemsView, KeysView, Mapping, ValuesView -from typing import Any, Generic, TypeVar +from _typeshed import IdentityFunction, Self +from collections.abc import ItemsView, KeysView, Mapping, ValuesView +from typing import Any, Generic, TypeVar, overload _T = TypeVar("_T") _U = TypeVar("_U") @@ -21,12 +21,30 @@ class _TypedDict(Mapping[str, object], metaclass=abc.ABCMeta): def __delitem__(self, k: NoReturn) -> None: ... def TypedDict(typename: str, fields: dict[str, type[Any]], total: bool = ...) -> type[dict[str, Any]]: ... -def Arg(type: _T = ..., name: str | None = ...) -> _T: ... -def DefaultArg(type: _T = ..., name: str | None = ...) -> _T: ... -def NamedArg(type: _T = ..., name: str | None = ...) -> _T: ... -def DefaultNamedArg(type: _T = ..., name: str | None = ...) -> _T: ... -def VarArg(type: _T = ...) -> _T: ... -def KwArg(type: _T = ...) -> _T: ... +@overload +def Arg(type: _T, name: str | None = ...) -> _T: ... +@overload +def Arg(*, name: str | None = ...) -> Any: ... +@overload +def DefaultArg(type: _T, name: str | None = ...) -> _T: ... +@overload +def DefaultArg(*, name: str | None = ...) -> Any: ... +@overload +def NamedArg(type: _T, name: str | None = ...) -> _T: ... +@overload +def NamedArg(*, name: str | None = ...) -> Any: ... +@overload +def DefaultNamedArg(type: _T, name: str | None = ...) -> _T: ... +@overload +def DefaultNamedArg(*, name: str | None = ...) -> Any: ... +@overload +def VarArg(type: _T) -> _T: ... +@overload +def VarArg() -> Any: ... +@overload +def KwArg(type: _T) -> _T: ... +@overload +def KwArg() -> Any: ... # Return type that indicates a function does not return. # Deprecated: Use typing.NoReturn instead. @@ -36,6 +54,6 @@ class NoReturn: ... # a class decorator, but mypy does not support type[_T] for abstract # classes until this issue is resolved, https://github.com/python/mypy/issues/4717. def trait(cls: _T) -> _T: ... -def mypyc_attr(*attrs: str, **kwattrs: object) -> Callable[[_T], _T]: ... +def mypyc_attr(*attrs: str, **kwattrs: object) -> IdentityFunction: ... class FlexibleAlias(Generic[_T, _U]): ... diff --git a/test-data/unit/cmdline.test b/test-data/unit/cmdline.test index 016d215027aee..3b3b64c038c14 100644 --- a/test-data/unit/cmdline.test +++ b/test-data/unit/cmdline.test @@ -335,11 +335,11 @@ file.py:6: error: Argument 1 to "foo" has incompatible type "str"; expected "int \[mypy-x] ignore_errors = True [file x.py] -"" + 0 +x: str = 5 [file y.py] -"" + 0 +x: str = 5 [out] -y.py:1: error: Unsupported operand types for + ("str" and "int") +y.py:1: error: Incompatible types in assignment (expression has type "int", variable has type "str") [case testConfigFollowImportsNormal] # cmd: mypy main.py @@ -840,19 +840,19 @@ src/anamespace/foo/bar.py:2: error: Incompatible return value type (got "int", e x = 0 # type: str [file pkg/a1/b/f.py] from pkg.a1.b.c.d.e import x -x + 1 +x() [file pkg/a2/__init__.py] [file pkg/a2/b/c/d/e.py] x = 0 # type: str [file pkg/a2/b/f.py] from pkg.a2.b.c.d.e import x -x + 1 +x() [out] pkg/a2/b/c/d/e.py:1: error: Incompatible types in assignment (expression has type "int", variable has type "str") pkg/a1/b/c/d/e.py:1: error: Incompatible types in assignment (expression has type "int", variable has type "str") -pkg/a2/b/f.py:2: error: Unsupported operand types for + ("str" and "int") -pkg/a1/b/f.py:2: error: Unsupported operand types for + ("str" and "int") +pkg/a2/b/f.py:2: error: "str" not callable +pkg/a1/b/f.py:2: error: "str" not callable [case testFollowImportStubs1] # cmd: mypy main.py From ce891e32d4306df2b9a8bbcb4b88dae9750aa16c Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Fri, 8 Jul 2022 14:15:39 +0100 Subject: [PATCH 365/377] Remove use of LiteralString in builtins (#13093) Fixes #13091 Co-authored-by: Ivan Levkivskyi --- mypy/typeshed/stdlib/builtins.pyi | 154 ++++++------------------------ 1 file changed, 31 insertions(+), 123 deletions(-) diff --git a/mypy/typeshed/stdlib/builtins.pyi b/mypy/typeshed/stdlib/builtins.pyi index 577d5fd99e36c..9d1d1f4b1b106 100644 --- a/mypy/typeshed/stdlib/builtins.pyi +++ b/mypy/typeshed/stdlib/builtins.pyi @@ -54,7 +54,7 @@ from typing import ( # noqa: Y027 TypeVar, overload, ) -from typing_extensions import Literal, LiteralString, SupportsIndex, TypeAlias, TypeGuard, final +from typing_extensions import Literal, SupportsIndex, TypeAlias, TypeGuard, final if sys.version_info >= (3, 9): from types import GenericAlias @@ -400,39 +400,21 @@ class str(Sequence[str]): def __new__(cls: type[Self], object: object = ...) -> Self: ... @overload def __new__(cls: type[Self], object: ReadableBuffer, encoding: str = ..., errors: str = ...) -> Self: ... - @overload - def capitalize(self: LiteralString) -> LiteralString: ... - @overload - def capitalize(self) -> str: ... # type: ignore[misc] - @overload - def casefold(self: LiteralString) -> LiteralString: ... - @overload - def casefold(self) -> str: ... # type: ignore[misc] - @overload - def center(self: LiteralString, __width: SupportsIndex, __fillchar: LiteralString = ...) -> LiteralString: ... - @overload - def center(self, __width: SupportsIndex, __fillchar: str = ...) -> str: ... # type: ignore[misc] + def capitalize(self) -> str: ... + def casefold(self) -> str: ... + def center(self, __width: SupportsIndex, __fillchar: str = ...) -> str: ... def count(self, x: str, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...) -> int: ... def encode(self, encoding: str = ..., errors: str = ...) -> bytes: ... def endswith( self, __suffix: str | tuple[str, ...], __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> bool: ... if sys.version_info >= (3, 8): - @overload - def expandtabs(self: LiteralString, tabsize: SupportsIndex = ...) -> LiteralString: ... - @overload - def expandtabs(self, tabsize: SupportsIndex = ...) -> str: ... # type: ignore[misc] + def expandtabs(self, tabsize: SupportsIndex = ...) -> str: ... else: - @overload - def expandtabs(self: LiteralString, tabsize: int = ...) -> LiteralString: ... - @overload - def expandtabs(self, tabsize: int = ...) -> str: ... # type: ignore[misc] + def expandtabs(self, tabsize: int = ...) -> str: ... def find(self, __sub: str, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...) -> int: ... - @overload - def format(self: LiteralString, *args: LiteralString, **kwargs: LiteralString) -> LiteralString: ... - @overload - def format(self, *args: object, **kwargs: object) -> str: ... # type: ignore[misc] + def format(self, *args: object, **kwargs: object) -> str: ... def format_map(self, map: _FormatMapMapping) -> str: ... def index(self, __sub: str, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...) -> int: ... def isalnum(self) -> bool: ... @@ -449,102 +431,40 @@ class str(Sequence[str]): def isspace(self) -> bool: ... def istitle(self) -> bool: ... def isupper(self) -> bool: ... - @overload - def join(self: LiteralString, __iterable: Iterable[LiteralString]) -> LiteralString: ... - @overload - def join(self, __iterable: Iterable[str]) -> str: ... # type: ignore[misc] - @overload - def ljust(self: LiteralString, __width: SupportsIndex, __fillchar: LiteralString = ...) -> LiteralString: ... - @overload - def ljust(self, __width: SupportsIndex, __fillchar: str = ...) -> str: ... # type: ignore[misc] - @overload - def lower(self: LiteralString) -> LiteralString: ... - @overload - def lower(self) -> str: ... # type: ignore[misc] - @overload - def lstrip(self: LiteralString, __chars: LiteralString | None = ...) -> LiteralString: ... - @overload - def lstrip(self, __chars: str | None = ...) -> str: ... # type: ignore[misc] - @overload - def partition(self: LiteralString, __sep: LiteralString) -> tuple[LiteralString, LiteralString, LiteralString]: ... - @overload - def partition(self, __sep: str) -> tuple[str, str, str]: ... # type: ignore[misc] - @overload - def replace( - self: LiteralString, __old: LiteralString, __new: LiteralString, __count: SupportsIndex = ... - ) -> LiteralString: ... - @overload - def replace(self, __old: str, __new: str, __count: SupportsIndex = ...) -> str: ... # type: ignore[misc] + def join(self, __iterable: Iterable[str]) -> str: ... + def ljust(self, __width: SupportsIndex, __fillchar: str = ...) -> str: ... + def lower(self) -> str: ... + def lstrip(self, __chars: str | None = ...) -> str: ... + def partition(self, __sep: str) -> tuple[str, str, str]: ... + def replace(self, __old: str, __new: str, __count: SupportsIndex = ...) -> str: ... if sys.version_info >= (3, 9): - @overload - def removeprefix(self: LiteralString, __prefix: LiteralString) -> LiteralString: ... - @overload - def removeprefix(self, __prefix: str) -> str: ... # type: ignore[misc] - @overload - def removesuffix(self: LiteralString, __suffix: LiteralString) -> LiteralString: ... - @overload - def removesuffix(self, __suffix: str) -> str: ... # type: ignore[misc] + def removeprefix(self, __prefix: str) -> str: ... + def removesuffix(self, __suffix: str) -> str: ... def rfind(self, __sub: str, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...) -> int: ... def rindex(self, __sub: str, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...) -> int: ... - @overload - def rjust(self: LiteralString, __width: SupportsIndex, __fillchar: LiteralString = ...) -> LiteralString: ... - @overload - def rjust(self, __width: SupportsIndex, __fillchar: str = ...) -> str: ... # type: ignore[misc] - @overload - def rpartition(self: LiteralString, __sep: LiteralString) -> tuple[LiteralString, LiteralString, LiteralString]: ... - @overload - def rpartition(self, __sep: str) -> tuple[str, str, str]: ... # type: ignore[misc] - @overload - def rsplit(self: LiteralString, sep: LiteralString | None = ..., maxsplit: SupportsIndex = ...) -> list[LiteralString]: ... - @overload - def rsplit(self, sep: str | None = ..., maxsplit: SupportsIndex = ...) -> list[str]: ... # type: ignore[misc] - @overload - def rstrip(self: LiteralString, __chars: LiteralString | None = ...) -> LiteralString: ... - @overload - def rstrip(self, __chars: str | None = ...) -> str: ... # type: ignore[misc] - @overload - def split(self: LiteralString, sep: LiteralString | None = ..., maxsplit: SupportsIndex = ...) -> list[LiteralString]: ... - @overload - def split(self, sep: str | None = ..., maxsplit: SupportsIndex = ...) -> list[str]: ... # type: ignore[misc] - @overload - def splitlines(self: LiteralString, keepends: bool = ...) -> list[LiteralString]: ... - @overload - def splitlines(self, keepends: bool = ...) -> list[str]: ... # type: ignore[misc] + def rjust(self, __width: SupportsIndex, __fillchar: str = ...) -> str: ... + def rpartition(self, __sep: str) -> tuple[str, str, str]: ... + def rsplit(self, sep: str | None = ..., maxsplit: SupportsIndex = ...) -> list[str]: ... + def rstrip(self, __chars: str | None = ...) -> str: ... + def split(self, sep: str | None = ..., maxsplit: SupportsIndex = ...) -> list[str]: ... + def splitlines(self, keepends: bool = ...) -> list[str]: ... def startswith( self, __prefix: str | tuple[str, ...], __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ... ) -> bool: ... - @overload - def strip(self: LiteralString, __chars: LiteralString | None = ...) -> LiteralString: ... - @overload - def strip(self, __chars: str | None = ...) -> str: ... # type: ignore[misc] - @overload - def swapcase(self: LiteralString) -> LiteralString: ... - @overload - def swapcase(self) -> str: ... # type: ignore[misc] - @overload - def title(self: LiteralString) -> LiteralString: ... - @overload - def title(self) -> str: ... # type: ignore[misc] + def strip(self, __chars: str | None = ...) -> str: ... + def swapcase(self) -> str: ... + def title(self) -> str: ... def translate(self, __table: Mapping[int, int | str | None] | Sequence[int | str | None]) -> str: ... - @overload - def upper(self: LiteralString) -> LiteralString: ... - @overload - def upper(self) -> str: ... # type: ignore[misc] - @overload - def zfill(self: LiteralString, __width: SupportsIndex) -> LiteralString: ... - @overload - def zfill(self, __width: SupportsIndex) -> str: ... # type: ignore[misc] + def upper(self) -> str: ... + def zfill(self, __width: SupportsIndex) -> str: ... @staticmethod @overload def maketrans(__x: dict[int, _T] | dict[str, _T] | dict[str | int, _T]) -> dict[int, _T]: ... @staticmethod @overload def maketrans(__x: str, __y: str, __z: str | None = ...) -> dict[int, int | None]: ... - @overload - def __add__(self: LiteralString, __s: LiteralString) -> LiteralString: ... - @overload - def __add__(self, __s: str) -> str: ... # type: ignore[misc] + def __add__(self, __s: str) -> str: ... # Incompatible with Sequence.__contains__ def __contains__(self, __o: str) -> bool: ... # type: ignore[override] def __eq__(self, __x: object) -> bool: ... @@ -552,26 +472,14 @@ class str(Sequence[str]): def __getitem__(self, __i: SupportsIndex | slice) -> str: ... def __gt__(self, __x: str) -> bool: ... def __hash__(self) -> int: ... - @overload - def __iter__(self: LiteralString) -> Iterator[LiteralString]: ... - @overload - def __iter__(self) -> Iterator[str]: ... # type: ignore[misc] + def __iter__(self) -> Iterator[str]: ... def __le__(self, __x: str) -> bool: ... def __len__(self) -> int: ... def __lt__(self, __x: str) -> bool: ... - @overload - def __mod__(self: LiteralString, __x: LiteralString | tuple[LiteralString, ...]) -> LiteralString: ... - @overload - def __mod__(self, __x: Any) -> str: ... # type: ignore[misc] - @overload - def __mul__(self: LiteralString, __n: SupportsIndex) -> LiteralString: ... - @overload - def __mul__(self, __n: SupportsIndex) -> str: ... # type: ignore[misc] + def __mod__(self, __x: Any) -> str: ... + def __mul__(self, __n: SupportsIndex) -> str: ... def __ne__(self, __x: object) -> bool: ... - @overload - def __rmul__(self: LiteralString, __n: SupportsIndex) -> LiteralString: ... - @overload - def __rmul__(self, __n: SupportsIndex) -> str: ... # type: ignore[misc] + def __rmul__(self, __n: SupportsIndex) -> str: ... def __getnewargs__(self) -> tuple[str]: ... class bytes(ByteString): From b0c1556c145a8b1fbd613b55d2144b8757baed54 Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Fri, 8 Jul 2022 14:17:36 +0100 Subject: [PATCH 366/377] Fix typeshed regression in unittest (#13092) Fixes #13090 Co-authored-by: Ivan Levkivskyi --- mypy/typeshed/stdlib/_typeshed/__init__.pyi | 3 +++ mypy/typeshed/stdlib/unittest/case.pyi | 20 +++++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/mypy/typeshed/stdlib/_typeshed/__init__.pyi b/mypy/typeshed/stdlib/_typeshed/__init__.pyi index 162c405222245..005849e0fb05e 100644 --- a/mypy/typeshed/stdlib/_typeshed/__init__.pyi +++ b/mypy/typeshed/stdlib/_typeshed/__init__.pyi @@ -78,6 +78,9 @@ class SupportsRAdd(Protocol[_T_contra, _T_co]): class SupportsSub(Protocol[_T_contra, _T_co]): def __sub__(self, __x: _T_contra) -> _T_co: ... +class SupportsRSub(Protocol[_T_contra, _T_co]): + def __rsub__(self, __x: _T_contra) -> _T_co: ... + class SupportsDivMod(Protocol[_T_contra, _T_co]): def __divmod__(self, __other: _T_contra) -> _T_co: ... diff --git a/mypy/typeshed/stdlib/unittest/case.pyi b/mypy/typeshed/stdlib/unittest/case.pyi index 15b573edeebbc..4f69c0a1f3b8b 100644 --- a/mypy/typeshed/stdlib/unittest/case.pyi +++ b/mypy/typeshed/stdlib/unittest/case.pyi @@ -1,7 +1,7 @@ import logging import sys import unittest.result -from _typeshed import Self, SupportsDunderGE, SupportsSub +from _typeshed import Self, SupportsDunderGE, SupportsRSub, SupportsSub from collections.abc import Callable, Container, Iterable, Mapping, Sequence, Set as AbstractSet from contextlib import AbstractContextManager from types import TracebackType @@ -196,6 +196,15 @@ class TestCase: delta: None = ..., ) -> None: ... @overload + def assertAlmostEqual( + self, + first: _T, + second: SupportsRSub[_T, SupportsAbs[SupportsRound[object]]], + places: int | None = ..., + msg: Any = ..., + delta: None = ..., + ) -> None: ... + @overload def assertNotAlmostEqual(self, first: _S, second: _S, places: None, msg: Any, delta: _SupportsAbsAndDunderGE) -> None: ... @overload def assertNotAlmostEqual( @@ -210,6 +219,15 @@ class TestCase: msg: Any = ..., delta: None = ..., ) -> None: ... + @overload + def assertNotAlmostEqual( + self, + first: _T, + second: SupportsRSub[_T, SupportsAbs[SupportsRound[object]]], + places: int | None = ..., + msg: Any = ..., + delta: None = ..., + ) -> None: ... def assertRegex(self, text: AnyStr, expected_regex: AnyStr | Pattern[AnyStr], msg: Any = ...) -> None: ... def assertNotRegex(self, text: AnyStr, unexpected_regex: AnyStr | Pattern[AnyStr], msg: Any = ...) -> None: ... def assertCountEqual(self, first: Iterable[Any], second: Iterable[Any], msg: Any = ...) -> None: ... From 1fedf2c1adfcaccf7c19adbc8dee5cddebdd5d33 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Fri, 8 Jul 2022 14:39:59 +0100 Subject: [PATCH 367/377] Fix false-positive error on multiple enum base classes (#12963) Fixes #12787. Mypy currently emits a false-positive error for this snippet of code, even though it works fine at runtime (and this exact inheritance structure is used in enum.py in the stdlib): ``` from enum import Enum, Flag class ReprEnum(Enum): ... class MyFlag(ReprEnum, Flag): ... ``` This PR fixes that. --- mypy/checker.py | 19 +++++++++++++++++-- test-data/unit/check-enum.test | 34 +++++++++++++++++++++++++++------- 2 files changed, 44 insertions(+), 9 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 62dd15da896ce..60be940a327cf 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -1965,14 +1965,29 @@ def is_final_enum_value(self, sym: SymbolTableNode) -> bool: return False def check_enum_bases(self, defn: ClassDef) -> None: + """ + Non-enum mixins cannot appear after enum bases; this is disallowed at runtime: + + class Foo: ... + class Bar(enum.Enum, Foo): ... + + But any number of enum mixins can appear in a class definition + (even if multiple enum bases define __new__). So this is fine: + + class Foo(enum.Enum): + def __new__(cls, val): ... + class Bar(enum.Enum): + def __new__(cls, val): ... + class Baz(int, Foo, Bar, enum.Flag): ... + """ enum_base: Optional[Instance] = None for base in defn.info.bases: if enum_base is None and base.type.is_enum: enum_base = base continue - elif enum_base is not None: + elif enum_base is not None and not base.type.is_enum: self.fail( - f'No base classes are allowed after "{enum_base}"', + f'No non-enum mixin classes are allowed after "{enum_base}"', defn, ) break diff --git a/test-data/unit/check-enum.test b/test-data/unit/check-enum.test index 84ac3904772a7..4bd04cf673545 100644 --- a/test-data/unit/check-enum.test +++ b/test-data/unit/check-enum.test @@ -1903,6 +1903,14 @@ class Third: class Mixin: pass +class EnumWithCustomNew(enum.Enum): + def __new__(cls, val): + pass + +class SecondEnumWithCustomNew(enum.Enum): + def __new__(cls, val): + pass + # Correct Enums: class Correct0(enum.Enum): @@ -1920,6 +1928,9 @@ class Correct3(Mixin, enum.Enum): class RegularClass(Mixin, First, Second): pass +class Correct5(enum.Enum): + pass + # Correct inheritance: class _InheritingDataAndMixin(Correct1): @@ -1934,25 +1945,34 @@ class _CorrectWithDataAndMixin(Mixin, First, Correct0): class _CorrectWithMixin(Mixin, Correct2): pass +class _CorrectMultipleEnumBases(Correct0, Correct5): + pass + +class _MultipleEnumBasesAndMixin(int, Correct0, enum.Flag): + pass + +class _MultipleEnumBasesWithCustomNew(int, EnumWithCustomNew, SecondEnumWithCustomNew): + pass + # Wrong Enums: class TwoDataTypesViaInheritance(Second, Correct2): # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Correct2" pass -class TwoDataTypesViaInheritanceAndMixin(Second, Correct2, Mixin): # E: No base classes are allowed after "__main__.Correct2" \ +class TwoDataTypesViaInheritanceAndMixin(Second, Correct2, Mixin): # E: No non-enum mixin classes are allowed after "__main__.Correct2" \ # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Correct2" pass -class MixinAfterEnum1(enum.Enum, Mixin): # E: No base classes are allowed after "enum.Enum" +class MixinAfterEnum1(enum.Enum, Mixin): # E: No non-enum mixin classes are allowed after "enum.Enum" pass -class MixinAfterEnum2(First, enum.Enum, Mixin): # E: No base classes are allowed after "enum.Enum" +class MixinAfterEnum2(First, enum.Enum, Mixin): # E: No non-enum mixin classes are allowed after "enum.Enum" pass class TwoDataTypes(First, Second, enum.Enum): # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second" pass -class TwoDataTypesAndIntEnumMixin(First, Second, enum.IntEnum, Mixin): # E: No base classes are allowed after "enum.IntEnum" \ +class TwoDataTypesAndIntEnumMixin(First, Second, enum.IntEnum, Mixin): # E: No non-enum mixin classes are allowed after "enum.IntEnum" \ # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second" pass @@ -1960,16 +1980,16 @@ class ThreeDataTypes(First, Second, Third, enum.Enum): # E: Only a single data # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Third" pass -class ThreeDataTypesAndMixin(First, Second, Third, enum.Enum, Mixin): # E: No base classes are allowed after "enum.Enum" \ +class ThreeDataTypesAndMixin(First, Second, Third, enum.Enum, Mixin): # E: No non-enum mixin classes are allowed after "enum.Enum" \ # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second" \ # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Third" pass -class FromEnumAndOther1(Correct2, Second, enum.Enum): # E: No base classes are allowed after "__main__.Correct2" \ +class FromEnumAndOther1(Correct2, Second, enum.Enum): # E: No non-enum mixin classes are allowed after "__main__.Correct2" \ # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second" pass -class FromEnumAndOther2(Correct2, Second): # E: No base classes are allowed after "__main__.Correct2" \ +class FromEnumAndOther2(Correct2, Second): # E: No non-enum mixin classes are allowed after "__main__.Correct2" \ # E: Only a single data type mixin is allowed for Enum subtypes, found extra "__main__.Second" pass [builtins fixtures/tuple.pyi] From 49b4b3da336cefb2aceb13ee721b5aa7b15bf8e0 Mon Sep 17 00:00:00 2001 From: Stanislav K <44553725+stkrizh@users.noreply.github.com> Date: Fri, 8 Jul 2022 15:43:27 +0200 Subject: [PATCH 368/377] Don't add __match_args__ for dataclasses and named tuples with --python-version < 3.10 (#12503) Fixes #12489 --- mypy/plugins/dataclasses.py | 3 +- mypy/semanal_namedtuple.py | 3 +- mypy/test/testmerge.py | 2 - test-data/unit/check-dataclasses.test | 45 ++++++++++++++++++++ test-data/unit/check-namedtuple.test | 23 ++++++++++ test-data/unit/deps.test | 32 +++++++++++++- test-data/unit/merge.test | 61 ++++++++++++++++++++++++++- 7 files changed, 163 insertions(+), 6 deletions(-) diff --git a/mypy/plugins/dataclasses.py b/mypy/plugins/dataclasses.py index 00c46e1417c53..87b42a499a1c0 100644 --- a/mypy/plugins/dataclasses.py +++ b/mypy/plugins/dataclasses.py @@ -230,7 +230,8 @@ def transform(self) -> bool: if (decorator_arguments['match_args'] and ('__match_args__' not in info.names or info.names['__match_args__'].plugin_generated) and - attributes): + attributes and + py_version >= (3, 10)): str_type = ctx.api.named_type("builtins.str") literals: List[Type] = [LiteralType(attr.name, str_type) for attr in attributes if attr.is_in_init] diff --git a/mypy/semanal_namedtuple.py b/mypy/semanal_namedtuple.py index 109ec17cbc899..ef0a38d222775 100644 --- a/mypy/semanal_namedtuple.py +++ b/mypy/semanal_namedtuple.py @@ -447,7 +447,8 @@ def add_field(var: Var, is_initialized_in_class: bool = False, add_field(Var('_source', strtype), is_initialized_in_class=True) add_field(Var('__annotations__', ordereddictype), is_initialized_in_class=True) add_field(Var('__doc__', strtype), is_initialized_in_class=True) - add_field(Var('__match_args__', match_args_type), is_initialized_in_class=True) + if self.options.python_version >= (3, 10): + add_field(Var('__match_args__', match_args_type), is_initialized_in_class=True) tvd = TypeVarType(SELF_TVAR_NAME, info.fullname + '.' + SELF_TVAR_NAME, -1, [], info.tuple_type) diff --git a/mypy/test/testmerge.py b/mypy/test/testmerge.py index fe0de2a7fe2d4..3f07c39f856db 100644 --- a/mypy/test/testmerge.py +++ b/mypy/test/testmerge.py @@ -7,7 +7,6 @@ from mypy import build from mypy.build import BuildResult from mypy.modulefinder import BuildSource -from mypy.defaults import PYTHON3_VERSION from mypy.errors import CompileError from mypy.nodes import ( Node, MypyFile, SymbolTable, SymbolTableNode, TypeInfo, Expression, Var, TypeVarExpr, @@ -107,7 +106,6 @@ def build(self, source: str, testcase: DataDrivenTestCase) -> Optional[BuildResu options.use_builtins_fixtures = True options.export_types = True options.show_traceback = True - options.python_version = PYTHON3_VERSION main_path = os.path.join(test_temp_dir, 'main') with open(main_path, 'w', encoding='utf8') as f: f.write(source) diff --git a/test-data/unit/check-dataclasses.test b/test-data/unit/check-dataclasses.test index fb1b4a1e8b464..40c6b66d5c390 100644 --- a/test-data/unit/check-dataclasses.test +++ b/test-data/unit/check-dataclasses.test @@ -1790,3 +1790,48 @@ class MyDataclass: class MyGeneric(Generic[T]): ... class MyClass(MyGeneric[MyDataclass]): ... [builtins fixtures/dataclasses.pyi] + +[case testDataclassWithMatchArgs] +# flags: --python-version 3.10 +from dataclasses import dataclass +@dataclass +class One: + bar: int + baz: str +o: One +reveal_type(o.__match_args__) # N: Revealed type is "Tuple[Literal['bar'], Literal['baz']]" +@dataclass(match_args=True) +class Two: + bar: int +t: Two +reveal_type(t.__match_args__) # N: Revealed type is "Tuple[Literal['bar']]" +[builtins fixtures/dataclasses.pyi] + +[case testDataclassWithoutMatchArgs] +# flags: --python-version 3.10 +from dataclasses import dataclass +@dataclass(match_args=False) +class One: + bar: int + baz: str +o: One +reveal_type(o.__match_args__) # E: "One" has no attribute "__match_args__" \ + # N: Revealed type is "Any" +[builtins fixtures/dataclasses.pyi] + +[case testDataclassWithMatchArgsOldVersion] +# flags: --python-version 3.9 +from dataclasses import dataclass +@dataclass(match_args=True) +class One: + bar: int +o: One +reveal_type(o.__match_args__) # E: "One" has no attribute "__match_args__" \ + # N: Revealed type is "Any" +@dataclass +class Two: + bar: int +t: Two +reveal_type(t.__match_args__) # E: "Two" has no attribute "__match_args__" \ + # N: Revealed type is "Any" +[builtins fixtures/dataclasses.pyi] diff --git a/test-data/unit/check-namedtuple.test b/test-data/unit/check-namedtuple.test index c6f1fe3b1d04a..034889878c371 100644 --- a/test-data/unit/check-namedtuple.test +++ b/test-data/unit/check-namedtuple.test @@ -1134,3 +1134,26 @@ def f(fields) -> None: NT2 = namedtuple("bad", "x") # E: First argument to namedtuple() should be "NT2", not "bad" nt2: NT2 = NT2(x=1) [builtins fixtures/tuple.pyi] + +[case testNamedTupleHasMatchArgs] +# flags: --python-version 3.10 +from typing import NamedTuple +class One(NamedTuple): + bar: int + baz: str +o: One +reveal_type(o.__match_args__) # N: Revealed type is "Tuple[Literal['bar'], Literal['baz']]" +[builtins fixtures/tuple.pyi] +[typing fixtures/typing-namedtuple.pyi] + +[case testNamedTupleHasNoMatchArgsOldVersion] +# flags: --python-version 3.9 +from typing import NamedTuple +class One(NamedTuple): + bar: int + baz: str +o: One +reveal_type(o.__match_args__) # E: "One" has no attribute "__match_args__" \ + # N: Revealed type is "Any" +[builtins fixtures/tuple.pyi] +[typing fixtures/typing-namedtuple.pyi] diff --git a/test-data/unit/deps.test b/test-data/unit/deps.test index 53156b6f4f48b..884b10f166b0a 100644 --- a/test-data/unit/deps.test +++ b/test-data/unit/deps.test @@ -1420,7 +1420,7 @@ class D(C): -> m, m.C, m.D -> m.D -[case testDataclassDeps] +[case testDataclassDepsOldVersion] # flags: --python-version 3.7 from dataclasses import dataclass @@ -1435,6 +1435,36 @@ class B(A): y: int [builtins fixtures/dataclasses.pyi] +[out] + -> , m + -> + -> , m.B.__init__ + -> + -> + -> + -> m, m.A, m.B + -> m + -> m + -> m.B + -> m + -> m + -> m + +[case testDataclassDeps] +# flags: --python-version 3.10 +from dataclasses import dataclass + +Z = int + +@dataclass +class A: + x: Z + +@dataclass +class B(A): + y: int +[builtins fixtures/dataclasses.pyi] + [out] -> , m -> diff --git a/test-data/unit/merge.test b/test-data/unit/merge.test index 881e21bb1a929..a593a064cbb25 100644 --- a/test-data/unit/merge.test +++ b/test-data/unit/merge.test @@ -646,7 +646,7 @@ TypeInfo<2>( f<3>)) [case testNamedTuple_typeinfo] - +# flags: --python-version 3.10 import target [file target.py] from typing import NamedTuple @@ -707,6 +707,65 @@ TypeInfo<2>( x<19> (target.A<0>) y<20> (target.A<0>))) +[case testNamedTupleOldVersion_typeinfo] +import target +[file target.py] +from typing import NamedTuple +class A: pass +N = NamedTuple('N', [('x', A)]) +[file target.py.next] +from typing import NamedTuple +class A: pass +N = NamedTuple('N', [('x', A), ('y', A)]) +[builtins fixtures/tuple.pyi] +[out] +TypeInfo<0>( + Name(target.A) + Bases(builtins.object<1>) + Mro(target.A<0>, builtins.object<1>) + Names()) +TypeInfo<2>( + Name(target.N) + Bases(builtins.tuple[target.A<0>, ...]<3>) + Mro(target.N<2>, builtins.tuple<3>, typing.Sequence<4>, typing.Iterable<5>, builtins.object<1>) + Names( + _NT<6> + __annotations__<7> (builtins.object<1>) + __doc__<8> (builtins.str<9>) + __new__<10> + _asdict<11> + _field_defaults<12> (builtins.object<1>) + _field_types<13> (builtins.object<1>) + _fields<14> (Tuple[builtins.str<9>]) + _make<15> + _replace<16> + _source<17> (builtins.str<9>) + x<18> (target.A<0>))) +==> +TypeInfo<0>( + Name(target.A) + Bases(builtins.object<1>) + Mro(target.A<0>, builtins.object<1>) + Names()) +TypeInfo<2>( + Name(target.N) + Bases(builtins.tuple[target.A<0>, ...]<3>) + Mro(target.N<2>, builtins.tuple<3>, typing.Sequence<4>, typing.Iterable<5>, builtins.object<1>) + Names( + _NT<6> + __annotations__<7> (builtins.object<1>) + __doc__<8> (builtins.str<9>) + __new__<10> + _asdict<11> + _field_defaults<12> (builtins.object<1>) + _field_types<13> (builtins.object<1>) + _fields<14> (Tuple[builtins.str<9>, builtins.str<9>]) + _make<15> + _replace<16> + _source<17> (builtins.str<9>) + x<18> (target.A<0>) + y<19> (target.A<0>))) + [case testUnionType_types] import target [file target.py] From 9f99400b748a4550813c54fb3f7a00268affdd6d Mon Sep 17 00:00:00 2001 From: Jake Lishman Date: Fri, 8 Jul 2022 15:07:15 +0100 Subject: [PATCH 369/377] Fix crash overriding partial-type attribute with method (#12943) Attributes can still be partially typed (e.g. ``) after a parent-class definition if the block they are declared in is deferred. The first pass for child classes might then encounter this type when considering method overrides, which could cause a crash when attempting to determine subtype compatibility. Fixes #11686 Fixes #11981 --- mypy/checker.py | 4 +++- test-data/unit/check-classes.test | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/mypy/checker.py b/mypy/checker.py index 60be940a327cf..d17871039332b 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -1579,7 +1579,9 @@ def check_method_override_for_base_with_name( # it can be checked for compatibility. original_type = get_proper_type(base_attr.type) original_node = base_attr.node - if original_type is None: + # `original_type` can be partial if (e.g.) it is originally an + # instance variable from an `__init__` block that becomes deferred. + if original_type is None or isinstance(original_type, PartialType): if self.pass_num < self.last_pass: # If there are passes left, defer this node until next pass, # otherwise try reconstructing the method type from available information. diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index ee560de892084..e326e24df0e6d 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -151,6 +151,24 @@ class Derived(Base): __hash__ = 1 # E: Incompatible types in assignment (expression has type "int", base class "Base" defined the type as "Callable[[Base], int]") +[case testOverridePartialAttributeWithMethod] +# This was crashing: https://github.com/python/mypy/issues/11686. +class Base: + def __init__(self, arg: int): + self.partial_type = [] # E: Need type annotation for "partial_type" (hint: "partial_type: List[] = ...") + self.force_deferral = [] + + # Force inference of the `force_deferral` attribute in `__init__` to be + # deferred to a later pass by providing a definition in another context, + # which means `partial_type` remains only partially inferred. + force_deferral = [] # E: Need type annotation for "force_deferral" (hint: "force_deferral: List[] = ...") + + +class Derived(Base): + def partial_type(self) -> int: # E: Signature of "partial_type" incompatible with supertype "Base" + ... + + -- Attributes -- ---------- From d06dcf0c0383a95492aef8fe46eafcff10be63c0 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sat, 16 Jul 2022 09:23:20 -0700 Subject: [PATCH 370/377] [0.970 backport] add typing_extensions.NamedTuple (#13149) https://github.com/python/typeshed/pull/8295 --- mypy/typeshed/stdlib/typing_extensions.pyi | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/mypy/typeshed/stdlib/typing_extensions.pyi b/mypy/typeshed/stdlib/typing_extensions.pyi index 38fb9dec19d9b..358853549bed7 100644 --- a/mypy/typeshed/stdlib/typing_extensions.pyi +++ b/mypy/typeshed/stdlib/typing_extensions.pyi @@ -1,6 +1,8 @@ import abc +import collections import sys from _typeshed import IdentityFunction, Self as TypeshedSelf # see #6932 for why the Self alias cannot have a leading underscore +from collections.abc import Iterable from typing import ( # noqa: Y022,Y027,Y039 TYPE_CHECKING as TYPE_CHECKING, Any, @@ -52,6 +54,7 @@ __all__ = [ "Counter", "Deque", "DefaultDict", + "NamedTuple", "OrderedDict", "TypedDict", "SupportsIndex", @@ -189,9 +192,11 @@ else: def is_typeddict(tp: object) -> bool: ... # New things in 3.11 +# NamedTuples are not new, but the ability to create generic NamedTuples is new in 3.11 if sys.version_info >= (3, 11): from typing import ( LiteralString as LiteralString, + NamedTuple as NamedTuple, Never as Never, NotRequired as NotRequired, Required as Required, @@ -233,3 +238,24 @@ else: field_specifiers: tuple[type[Any] | Callable[..., Any], ...] = ..., **kwargs: object, ) -> IdentityFunction: ... + + class NamedTuple(tuple[Any, ...]): + if sys.version_info < (3, 8): + _field_types: collections.OrderedDict[str, type] + elif sys.version_info < (3, 9): + _field_types: dict[str, type] + _field_defaults: dict[str, Any] + _fields: tuple[str, ...] + _source: str + @overload + def __init__(self, typename: str, fields: Iterable[tuple[str, Any]] = ...) -> None: ... + @overload + def __init__(self, typename: str, fields: None = ..., **kwargs: Any) -> None: ... + @classmethod + def _make(cls: type[TypeshedSelf], iterable: Iterable[Any]) -> TypeshedSelf: ... + if sys.version_info >= (3, 8): + def _asdict(self) -> dict[str, Any]: ... + else: + def _asdict(self) -> collections.OrderedDict[str, Any]: ... + + def _replace(self: TypeshedSelf, **kwargs: Any) -> TypeshedSelf: ... From 88c1b85c7ca5bb7ac2d7ad36d7dcdfb222412a75 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sat, 16 Jul 2022 09:24:44 -0700 Subject: [PATCH 371/377] [mypyc] Add LoadAddress op for PyFloat_Type & PyTuple_Type (#13078) (#13150) - Fixes https://github.com/mypyc/mypyc/issues/924 - Fixes https://github.com/mypyc/mypyc/issues/926 - Fixes https://github.com/mypyc/mypyc/issues/935 This is a follow-up of commit 7811f085d0081d48302237faa20254c0fc3eb43a. Co-authored-by: Richard Si <63936253+ichard26@users.noreply.github.com> --- mypyc/primitives/float_ops.py | 10 +++++-- mypyc/primitives/tuple_ops.py | 7 ++++- mypyc/test-data/irbuild-dunders.test | 11 +++---- mypyc/test-data/run-python37.test | 4 ++- mypyc/test-data/run-tuples.test | 43 ++++++++++++++++++++++++++++ 5 files changed, 64 insertions(+), 11 deletions(-) diff --git a/mypyc/primitives/float_ops.py b/mypyc/primitives/float_ops.py index ad028a9012229..3359cf6fe122f 100644 --- a/mypyc/primitives/float_ops.py +++ b/mypyc/primitives/float_ops.py @@ -2,12 +2,18 @@ from mypyc.ir.ops import ERR_MAGIC from mypyc.ir.rtypes import ( - str_rprimitive, float_rprimitive + str_rprimitive, float_rprimitive, object_rprimitive ) from mypyc.primitives.registry import ( - function_op + load_address_op, function_op ) +# Get the 'builtins.float' type object. +load_address_op( + name='builtins.float', + type=object_rprimitive, + src='PyFloat_Type') + # float(str) function_op( name='builtins.float', diff --git a/mypyc/primitives/tuple_ops.py b/mypyc/primitives/tuple_ops.py index ce88a4ee0f4d9..33f8e331b56dc 100644 --- a/mypyc/primitives/tuple_ops.py +++ b/mypyc/primitives/tuple_ops.py @@ -9,8 +9,13 @@ tuple_rprimitive, int_rprimitive, list_rprimitive, object_rprimitive, c_pyssize_t_rprimitive, bit_rprimitive ) -from mypyc.primitives.registry import method_op, function_op, custom_op +from mypyc.primitives.registry import load_address_op, method_op, function_op, custom_op +# Get the 'builtins.tuple' type object. +load_address_op( + name='builtins.tuple', + type=object_rprimitive, + src='PyTuple_Type') # tuple[index] (for an int index) tuple_get_item_op = method_op( diff --git a/mypyc/test-data/irbuild-dunders.test b/mypyc/test-data/irbuild-dunders.test index 808617e438894..d06a570aa7b0a 100644 --- a/mypyc/test-data/irbuild-dunders.test +++ b/mypyc/test-data/irbuild-dunders.test @@ -175,16 +175,13 @@ L0: def f(c): c :: __main__.C r0, r1 :: int - r2, r3, r4 :: object - r5 :: str - r6, r7 :: object + r2, r3, r4, r5 :: object L0: r0 = c.__neg__() r1 = c.__invert__() r2 = load_address PyLong_Type r3 = PyObject_CallFunctionObjArgs(r2, c, 0) - r4 = builtins :: module - r5 = 'float' - r6 = CPyObject_GetAttr(r4, r5) - r7 = PyObject_CallFunctionObjArgs(r6, c, 0) + r4 = load_address PyFloat_Type + r5 = PyObject_CallFunctionObjArgs(r4, c, 0) return 1 + diff --git a/mypyc/test-data/run-python37.test b/mypyc/test-data/run-python37.test index 5bf2c29263e1d..61d428c17a441 100644 --- a/mypyc/test-data/run-python37.test +++ b/mypyc/test-data/run-python37.test @@ -70,6 +70,7 @@ class Person4: @dataclass class Person5: + weight: float friends: Set[str] = field(default_factory=set) parents: FrozenSet[str] = frozenset() @@ -122,7 +123,8 @@ assert i8 > i9 assert Person1.__annotations__ == {'age': int, 'name': str} assert Person2.__annotations__ == {'age': int, 'name': str} -assert Person5.__annotations__ == {'friends': set, 'parents': frozenset} +assert Person5.__annotations__ == {'weight': float, 'friends': set, + 'parents': frozenset} [file driver.py] import sys diff --git a/mypyc/test-data/run-tuples.test b/mypyc/test-data/run-tuples.test index 759177342fa93..26b0393208443 100644 --- a/mypyc/test-data/run-tuples.test +++ b/mypyc/test-data/run-tuples.test @@ -95,6 +95,49 @@ class Sub(NT): pass assert f(Sub(3, 2)) == 3 +-- Ref: https://github.com/mypyc/mypyc/issues/924 +[case testNamedTupleClassSyntax] +from typing import Dict, List, NamedTuple, Optional, Tuple, Union + +class ClassIR: pass + +class FuncIR: pass + +StealsDescription = Union[bool, List[bool]] + +class Record(NamedTuple): + st_mtime: float + st_size: int + is_borrowed: bool + hash: str + python_path: Tuple[str, ...] + type: 'ClassIR' + method: FuncIR + shadow_method: Optional[FuncIR] + classes: Dict[str, 'ClassIR'] + steals: StealsDescription + ordering: Optional[List[int]] + extra_int_constants: List[Tuple[int]] + +[file driver.py] +from typing import Optional +from native import ClassIR, FuncIR, Record + +assert Record.__annotations__ == { + 'st_mtime': float, + 'st_size': int, + 'is_borrowed': bool, + 'hash': str, + 'python_path': tuple, + 'type': ClassIR, + 'method': FuncIR, + 'shadow_method': type, + 'classes': dict, + 'steals': type, + 'ordering': type, + 'extra_int_constants': list, +}, Record.__annotations__ + [case testTupleOps] from typing import Tuple, List, Any, Optional from typing_extensions import Final From ee10d29a0eeded05ad4fa281c90341412f843d0b Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sat, 16 Jul 2022 09:25:38 -0700 Subject: [PATCH 372/377] flush keepalives on operator assignment statements (#13144) (#13151) This PR makes mypyc flush keepalives on operator assignment statements, to prevent accessing undefined variables in the generated C code. Fixes mypyc/mypyc#941. Co-authored-by: Zsolt Dollenstein --- mypyc/irbuild/statement.py | 1 + mypyc/test-data/run-generators.test | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/mypyc/irbuild/statement.py b/mypyc/irbuild/statement.py index 93dc5f24158fd..c1d9666a34ec1 100644 --- a/mypyc/irbuild/statement.py +++ b/mypyc/irbuild/statement.py @@ -136,6 +136,7 @@ def transform_operator_assignment_stmt(builder: IRBuilder, stmt: OperatorAssignm # usually operator assignments are done in-place # but when target doesn't support that we need to manually assign builder.assign(target, res, res.line) + builder.flush_keep_alives() def transform_import(builder: IRBuilder, node: Import) -> None: diff --git a/mypyc/test-data/run-generators.test b/mypyc/test-data/run-generators.test index 8aecce6564c89..8feabd21258b8 100644 --- a/mypyc/test-data/run-generators.test +++ b/mypyc/test-data/run-generators.test @@ -595,3 +595,15 @@ class C: self.foo.flag = True yield self.foo.flag = False + +[case testGeneratorEarlyReturnWithBorrows] +from typing import Iterator +class Bar: + bar = 0 +class Foo: + bar = Bar() + def f(self) -> Iterator[int]: + if self: + self.bar.bar += 1 + return + yield 0 \ No newline at end of file From 2132036a019ed26d77389c0a9af9b928911a5846 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sun, 17 Jul 2022 02:22:04 -0700 Subject: [PATCH 373/377] Handle cwd correctly in pyinfo (#13161) (#13162) This fixes a recent regression introduced by the change to use sys.path Fixes #12956 --- mypy/pyinfo.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/mypy/pyinfo.py b/mypy/pyinfo.py index c129063a01a47..b8a1b234e67a0 100644 --- a/mypy/pyinfo.py +++ b/mypy/pyinfo.py @@ -10,9 +10,6 @@ import sys import sysconfig -if __name__ == '__main__': - sys.path = sys.path[1:] # we don't want to pick up mypy.types - MYPY = False if MYPY: from typing import List @@ -29,10 +26,17 @@ def getsearchdirs(): ) stdlib = sysconfig.get_path("stdlib") stdlib_ext = os.path.join(stdlib, "lib-dynload") - cwd = os.path.abspath(os.getcwd()) - excludes = set([cwd, stdlib_zip, stdlib, stdlib_ext]) - - abs_sys_path = (os.path.abspath(p) for p in sys.path) + excludes = set([stdlib_zip, stdlib, stdlib_ext]) + + # Drop the first entry of sys.path + # - If pyinfo.py is executed as a script (in a subprocess), this is the directory + # containing pyinfo.py + # - Otherwise, if mypy launched via console script, this is the directory of the script + # - Otherwise, if mypy launched via python -m mypy, this is the current directory + # In all cases, this is safe to drop + # Note that mypy adds the cwd to SearchPaths.python_path, so we still find things on the + # cwd consistently (the return value here sets SearchPaths.package_path) + abs_sys_path = (os.path.abspath(p) for p in sys.path[1:]) return [p for p in abs_sys_path if p not in excludes] From 72fa32526bff25d0738c39835b2ac309976961f8 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Mon, 18 Jul 2022 14:22:56 +0100 Subject: [PATCH 374/377] Update version to 0.970 --- mypy/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/version.py b/mypy/version.py index b46cd5b82a663..543def4a3dea1 100644 --- a/mypy/version.py +++ b/mypy/version.py @@ -5,7 +5,7 @@ # - Release versions have the form "0.NNN". # - Dev versions have the form "0.NNN+dev" (PLUS sign to conform to PEP 440). # - For 1.0 we'll switch back to 1.2.3 form. -__version__ = '0.970+dev' +__version__ = '0.970' base_version = __version__ mypy_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) From d8d900c4b8a178d8416ea831864234a21204dadb Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Mon, 18 Jul 2022 17:36:10 +0100 Subject: [PATCH 375/377] Update version to 0.971+dev --- mypy/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/version.py b/mypy/version.py index 543def4a3dea1..e080326d8cf16 100644 --- a/mypy/version.py +++ b/mypy/version.py @@ -5,7 +5,7 @@ # - Release versions have the form "0.NNN". # - Dev versions have the form "0.NNN+dev" (PLUS sign to conform to PEP 440). # - For 1.0 we'll switch back to 1.2.3 form. -__version__ = '0.970' +__version__ = '0.971+dev' base_version = __version__ mypy_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) From 61c0064fc4eb0a97ce1b69c05124fa6c2a4f3670 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Mon, 18 Jul 2022 17:23:55 +0100 Subject: [PATCH 376/377] Add back workaround to avoid confusing mypy.types and types in pyinfo (#13176) We run mypy/pyinfo.py as a script, and this means that mypy/types.py could be picked up instead of the stdlib `types` module, which clearly doesn't work. This seems to happen at least on macOS, and it broke PEP 561 tests. The workaround was accidentally removed as part of #13161. This should fix #13174 and help with the wheel builds. --- mypy/pyinfo.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/mypy/pyinfo.py b/mypy/pyinfo.py index b8a1b234e67a0..c874530a1799e 100644 --- a/mypy/pyinfo.py +++ b/mypy/pyinfo.py @@ -14,6 +14,15 @@ if MYPY: from typing import List +if __name__ == '__main__': + # HACK: We don't want to pick up mypy.types as the top-level types + # module. This could happen if this file is run as a script. + # This workaround fixes it. + old_sys_path = sys.path + sys.path = sys.path[1:] + import types # noqa + sys.path = old_sys_path + def getsearchdirs(): # type: () -> List[str] From 1f08cf44c7ec3dc4111aaf817958f7a51018ba38 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Tue, 19 Jul 2022 13:32:01 +0100 Subject: [PATCH 377/377] Update version to 0.971 --- mypy/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/version.py b/mypy/version.py index e080326d8cf16..66c5bb8077983 100644 --- a/mypy/version.py +++ b/mypy/version.py @@ -5,7 +5,7 @@ # - Release versions have the form "0.NNN". # - Dev versions have the form "0.NNN+dev" (PLUS sign to conform to PEP 440). # - For 1.0 we'll switch back to 1.2.3 form. -__version__ = '0.971+dev' +__version__ = '0.971' base_version = __version__ mypy_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))