Skip to content

Commit 89090c5

Browse files
committed
tmp
1 parent 6d1bcc1 commit 89090c5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+198
-1540
lines changed

docs/source/error_code_list2.rst

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -82,25 +82,6 @@ Example:
8282
# Error: Redundant cast to "int" [redundant-cast]
8383
return cast(int, x)
8484
85-
Check that methods do not have redundant Self annotations [redundant-self]
86-
--------------------------------------------------------------------------
87-
88-
Such annotations are allowed by :pep:`673` but are redundant, so if you want
89-
warnings about them, enable this error code.
90-
91-
Example:
92-
93-
.. code-block:: python
94-
95-
# mypy: enable-error-code="redundant-self"
96-
97-
from typing import Self
98-
99-
class C:
100-
# Error: Redundant Self annotation on method first argument
101-
def copy(self: Self) -> Self:
102-
return type(self)()
103-
10485
Check that comparisons are overlapping [comparison-overlap]
10586
-----------------------------------------------------------
10687

docs/source/generics.rst

Lines changed: 10 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -264,8 +264,15 @@ Generic methods and generic self
264264
You can also define generic methods — just use a type variable in the
265265
method signature that is different from class type variables. In particular,
266266
``self`` may also be generic, allowing a method to return the most precise
267-
type known at the point of access. In this way, for example, you can typecheck
268-
chaining of setter methods:
267+
type known at the point of access.
268+
269+
.. note::
270+
271+
This feature is experimental. Checking code with type annotations for self
272+
arguments is still not fully implemented. Mypy may disallow valid code or
273+
allow unsafe code.
274+
275+
In this way, for example, you can typecheck chaining of setter methods:
269276

270277
.. code-block:: python
271278
@@ -326,69 +333,8 @@ or a deserialization method returns the actual type of self. Therefore
326333
you may need to silence mypy inside these methods (but not at the call site),
327334
possibly by making use of the ``Any`` type.
328335

329-
Note that this feature may accept some unsafe code for the purpose of
330-
*practicality*. For example:
331-
332-
.. code-block:: python
333-
334-
from typing import TypeVar
335-
336-
T = TypeVar("T")
337-
class Base:
338-
def compare(self: T, other: T) -> bool:
339-
return False
340-
341-
class Sub(Base):
342-
def __init__(self, x: int) -> None:
343-
self.x = x
344-
345-
# This is unsafe (see below), but allowed because it is
346-
# a common pattern, and rarely causes issues in practice.
347-
def compare(self, other: Sub) -> bool:
348-
return self.x > other.x
349-
350-
b: Base = Sub(42)
351-
b.compare(Base()) # Runtime error here: 'Base' object has no attribute 'x'
352-
353336
For some advanced uses of self-types see :ref:`additional examples <advanced_self>`.
354337

355-
Automatic self types using typing.Self
356-
**************************************
357-
358-
The patterns described above are quite common, so there is a syntactic sugar
359-
for them introduced in :pep:`673`. Instead of defining a type variable and
360-
using an explicit ``self`` annotation, you can import a magic type ``typing.Self``
361-
that is automatically transformed into a type variable with an upper bound of
362-
current class, and you don't need an annotation for ``self`` (or ``cls`` for
363-
class methods). The above example can thus be rewritten as:
364-
365-
.. code-block:: python
366-
367-
from typing import Self
368-
369-
class Friend:
370-
other: Self | None = None
371-
372-
@classmethod
373-
def make_pair(cls) -> tuple[Self, Self]:
374-
a, b = cls(), cls()
375-
a.other = b
376-
b.other = a
377-
return a, b
378-
379-
class SuperFriend(Friend):
380-
pass
381-
382-
a, b = SuperFriend.make_pair()
383-
384-
This is more compact than using explicit type variables, plus additionally
385-
you can use ``Self`` in attribute annotations, not just in methods.
386-
387-
.. note::
388-
389-
To use this feature on versions of Python before 3.11, you will need to
390-
import ``Self`` from ``typing_extensions`` version 4.0 or newer.
391-
392338
.. _variance-of-generics:
393339

394340
Variance of generic types
@@ -602,7 +548,7 @@ Note that class decorators are handled differently than function decorators in
602548
mypy: decorating a class does not erase its type, even if the decorator has
603549
incomplete type annotations.
604550

605-
Suppose we have the following decorator, not type annotated yet,
551+
Suppose we have the following decorator, not type annotated yet,
606552
that preserves the original function's signature and merely prints the decorated function's name:
607553

608554
.. code-block:: python

docs/source/more_types.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -804,10 +804,9 @@ classes are generic, self-type allows giving them precise signatures:
804804
.. code-block:: python
805805
806806
T = TypeVar('T')
807+
Q = TypeVar('Q', bound='Base[Any]')
807808
808809
class Base(Generic[T]):
809-
Q = TypeVar('Q', bound='Base[T]')
810-
811810
def __init__(self, item: T) -> None:
812811
self.item = item
813812

mypy/applytype.py

Lines changed: 28 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,13 @@
44

55
import mypy.subtypes
66
from mypy.expandtype import expand_type, expand_unpack_with_variables
7-
from mypy.nodes import ARG_STAR, Context
7+
from mypy.nodes import ARG_POS, ARG_STAR, Context
88
from mypy.types import (
99
AnyType,
1010
CallableType,
1111
Parameters,
1212
ParamSpecType,
1313
PartialType,
14-
TupleType,
1514
Type,
1615
TypeVarId,
1716
TypeVarLikeType,
@@ -20,7 +19,6 @@
2019
UnpackType,
2120
get_proper_type,
2221
)
23-
from mypy.typevartuples import find_unpack_in_list, replace_starargs
2422

2523

2624
def get_target_type(
@@ -75,7 +73,6 @@ def apply_generic_arguments(
7573
report_incompatible_typevar_value: Callable[[CallableType, Type, str, Context], None],
7674
context: Context,
7775
skip_unsatisfied: bool = False,
78-
allow_erased_callables: bool = False,
7976
) -> CallableType:
8077
"""Apply generic type arguments to a callable type.
8178
@@ -116,69 +113,46 @@ def apply_generic_arguments(
116113
# Apply arguments to argument types.
117114
var_arg = callable.var_arg()
118115
if var_arg is not None and isinstance(var_arg.typ, UnpackType):
116+
expanded = expand_unpack_with_variables(var_arg.typ, id_to_type)
117+
assert isinstance(expanded, list)
118+
# Handle other cases later.
119+
for t in expanded:
120+
assert not isinstance(t, UnpackType)
119121
star_index = callable.arg_kinds.index(ARG_STAR)
120-
callable = callable.copy_modified(
121-
arg_types=(
122-
[
123-
expand_type(at, id_to_type, allow_erased_callables)
124-
for at in callable.arg_types[:star_index]
125-
]
126-
+ [callable.arg_types[star_index]]
127-
+ [
128-
expand_type(at, id_to_type, allow_erased_callables)
129-
for at in callable.arg_types[star_index + 1 :]
130-
]
131-
)
122+
arg_kinds = (
123+
callable.arg_kinds[:star_index]
124+
+ [ARG_POS] * len(expanded)
125+
+ callable.arg_kinds[star_index + 1 :]
132126
)
133-
134-
unpacked_type = get_proper_type(var_arg.typ.type)
135-
if isinstance(unpacked_type, TupleType):
136-
# Assuming for now that because we convert prefixes to positional arguments,
137-
# the first argument is always an unpack.
138-
expanded_tuple = expand_type(unpacked_type, id_to_type)
139-
if isinstance(expanded_tuple, TupleType):
140-
# TODO: handle the case where the tuple has an unpack. This will
141-
# hit an assert below.
142-
expanded_unpack = find_unpack_in_list(expanded_tuple.items)
143-
if expanded_unpack is not None:
144-
callable = callable.copy_modified(
145-
arg_types=(
146-
callable.arg_types[:star_index]
147-
+ [expanded_tuple]
148-
+ callable.arg_types[star_index + 1 :]
149-
)
150-
)
151-
else:
152-
callable = replace_starargs(callable, expanded_tuple.items)
153-
else:
154-
# TODO: handle the case for if we get a variable length tuple.
155-
assert False, f"mypy bug: unimplemented case, {expanded_tuple}"
156-
elif isinstance(unpacked_type, TypeVarTupleType):
157-
expanded_tvt = expand_unpack_with_variables(var_arg.typ, id_to_type)
158-
assert isinstance(expanded_tvt, list)
159-
for t in expanded_tvt:
160-
assert not isinstance(t, UnpackType)
161-
callable = replace_starargs(callable, expanded_tvt)
162-
else:
163-
assert False, "mypy bug: unhandled case applying unpack"
164-
else:
165-
callable = callable.copy_modified(
166-
arg_types=[
167-
expand_type(at, id_to_type, allow_erased_callables) for at in callable.arg_types
168-
]
127+
arg_names = (
128+
callable.arg_names[:star_index]
129+
+ [None] * len(expanded)
130+
+ callable.arg_names[star_index + 1 :]
169131
)
132+
arg_types = (
133+
[expand_type(at, id_to_type) for at in callable.arg_types[:star_index]]
134+
+ expanded
135+
+ [expand_type(at, id_to_type) for at in callable.arg_types[star_index + 1 :]]
136+
)
137+
else:
138+
arg_types = [expand_type(at, id_to_type) for at in callable.arg_types]
139+
arg_kinds = callable.arg_kinds
140+
arg_names = callable.arg_names
170141

171142
# Apply arguments to TypeGuard if any.
172143
if callable.type_guard is not None:
173-
type_guard = expand_type(callable.type_guard, id_to_type, allow_erased_callables)
144+
type_guard = expand_type(callable.type_guard, id_to_type)
174145
else:
175146
type_guard = None
176147

177148
# The callable may retain some type vars if only some were applied.
178149
remaining_tvars = [tv for tv in tvars if tv.id not in id_to_type]
179150

180151
return callable.copy_modified(
181-
ret_type=expand_type(callable.ret_type, id_to_type, allow_erased_callables),
152+
arg_types=arg_types,
153+
ret_type=expand_type(callable.ret_type, id_to_type),
182154
variables=remaining_tvars,
183155
type_guard=type_guard,
156+
arg_kinds=arg_kinds,
157+
arg_names=arg_names,
184158
)

mypy/checker.py

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
from mypy.erasetype import erase_type, erase_typevars, remove_instance_last_known_values
4040
from mypy.errorcodes import TYPE_VAR, UNUSED_AWAITABLE, UNUSED_COROUTINE, ErrorCode
4141
from mypy.errors import Errors, ErrorWatcher, report_internal_error
42-
from mypy.expandtype import expand_self_type, expand_type, expand_type_by_instance
42+
from mypy.expandtype import expand_type, expand_type_by_instance
4343
from mypy.join import join_types
4444
from mypy.literals import Key, literal, literal_hash
4545
from mypy.maptype import map_instance_to_supertype
@@ -1178,17 +1178,12 @@ def check_func_def(
11781178
if isinstance(arg_type, ParamSpecType):
11791179
pass
11801180
elif isinstance(arg_type, UnpackType):
1181-
if isinstance(get_proper_type(arg_type.type), TupleType):
1182-
# Instead of using Tuple[Unpack[Tuple[...]]], just use
1183-
# Tuple[...]
1184-
arg_type = arg_type.type
1185-
else:
1186-
arg_type = TupleType(
1187-
[arg_type],
1188-
fallback=self.named_generic_type(
1189-
"builtins.tuple", [self.named_type("builtins.object")]
1190-
),
1191-
)
1181+
arg_type = TupleType(
1182+
[arg_type],
1183+
fallback=self.named_generic_type(
1184+
"builtins.tuple", [self.named_type("builtins.object")]
1185+
),
1186+
)
11921187
else:
11931188
# builtins.tuple[T] is typing.Tuple[T, ...]
11941189
arg_type = self.named_generic_type("builtins.tuple", [arg_type])
@@ -2493,10 +2488,6 @@ class C(B, A[int]): ... # this is unsafe because...
24932488
second_sig = self.bind_and_map_method(second, second_type, ctx, base2)
24942489
ok = is_subtype(first_sig, second_sig, ignore_pos_arg_names=True)
24952490
elif first_type and second_type:
2496-
if isinstance(first.node, Var):
2497-
first_type = expand_self_type(first.node, first_type, fill_typevars(ctx))
2498-
if isinstance(second.node, Var):
2499-
second_type = expand_self_type(second.node, second_type, fill_typevars(ctx))
25002491
ok = is_equivalent(first_type, second_type)
25012492
if not ok:
25022493
second_node = base2[name].node
@@ -3077,8 +3068,6 @@ def lvalue_type_from_base(
30773068
if base_var:
30783069
base_node = base_var.node
30793070
base_type = base_var.type
3080-
if isinstance(base_node, Var) and base_type is not None:
3081-
base_type = expand_self_type(base_node, base_type, fill_typevars(expr_node.info))
30823071
if isinstance(base_node, Decorator):
30833072
base_node = base_node.func
30843073
base_type = base_node.type

0 commit comments

Comments
 (0)