Skip to content

Commit b077063

Browse files
committed
Merge remote-tracking branch 'upstream/master' into bugfix/st-paramspec-with-functools-partial
2 parents 4d55122 + 9323b88 commit b077063

File tree

10 files changed

+112
-13
lines changed

10 files changed

+112
-13
lines changed

docs/source/type_narrowing.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -400,11 +400,11 @@ Mypy supports TypeIs (:pep:`742`).
400400

401401
A `TypeIs narrowing function <https://typing.readthedocs.io/en/latest/spec/narrowing.html#typeis>`_
402402
allows you to define custom type checks that can narrow the type of a variable
403-
in `both the if and else <https://docs.python.org/3.13/library/typing.html#typing.TypeIs>_`
403+
in `both the if and else <https://docs.python.org/3.13/library/typing.html#typing.TypeIs>`_
404404
branches of a conditional, similar to how the built-in isinstance() function works.
405405

406406
TypeIs is new in Python 3.13 — for use in older Python versions, use the backport
407-
from `typing_extensions <https://typing-extensions.readthedocs.io/en/latest/>_`
407+
from `typing_extensions <https://typing-extensions.readthedocs.io/en/latest/>`_
408408

409409
Consider the following example using TypeIs:
410410

mypy/checkexpr.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2785,7 +2785,7 @@ def plausible_overload_call_targets(
27852785
) -> list[CallableType]:
27862786
"""Returns all overload call targets that having matching argument counts.
27872787
2788-
If the given args contains a star-arg (*arg or **kwarg argument, including
2788+
If the given args contains a star-arg (*arg or **kwarg argument, except for
27892789
ParamSpec), this method will ensure all star-arg overloads appear at the start
27902790
of the list, instead of their usual location.
27912791
@@ -2820,7 +2820,9 @@ def has_shape(typ: Type) -> bool:
28202820
# ParamSpec can be expanded in a lot of different ways. We may try
28212821
# to expand it here instead, but picking an impossible overload
28222822
# is safe: it will be filtered out later.
2823-
star_matches.append(typ)
2823+
# Unlike other var-args signatures, ParamSpec produces essentially
2824+
# a fixed signature, so there's no need to push them to the top.
2825+
matches.append(typ)
28242826
elif self.check_argument_count(
28252827
typ, arg_types, arg_kinds, arg_names, formal_to_actual, None
28262828
):

mypy/meet.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,11 @@ def get_possible_variants(typ: Type) -> list[Type]:
223223
else:
224224
return [typ.upper_bound]
225225
elif isinstance(typ, ParamSpecType):
226-
return [typ.upper_bound]
226+
# Extract 'object' from the final mro item
227+
upper_bound = get_proper_type(typ.upper_bound)
228+
if isinstance(upper_bound, Instance):
229+
return [Instance(upper_bound.type.mro[-1], [])]
230+
return [AnyType(TypeOfAny.implementation_artifact)]
227231
elif isinstance(typ, TypeVarTupleType):
228232
return [typ.upper_bound]
229233
elif isinstance(typ, UnionType):

mypy/stubtest.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1893,6 +1893,8 @@ class _Arguments:
18931893
custom_typeshed_dir: str | None
18941894
check_typeshed: bool
18951895
version: str
1896+
show_traceback: bool
1897+
pdb: bool
18961898

18971899

18981900
# typeshed added a stub for __main__, but that causes stubtest to check itself
@@ -1938,6 +1940,8 @@ def test_stubs(args: _Arguments, use_builtins_fixtures: bool = False) -> int:
19381940
options.abs_custom_typeshed_dir = os.path.abspath(options.custom_typeshed_dir)
19391941
options.config_file = args.mypy_config_file
19401942
options.use_builtins_fixtures = use_builtins_fixtures
1943+
options.show_traceback = args.show_traceback
1944+
options.pdb = args.pdb
19411945

19421946
if options.config_file:
19431947

@@ -2091,6 +2095,10 @@ def parse_options(args: list[str]) -> _Arguments:
20912095
parser.add_argument(
20922096
"--version", action="version", version="%(prog)s " + mypy.version.__version__
20932097
)
2098+
parser.add_argument("--pdb", action="store_true", help="Invoke pdb on fatal error")
2099+
parser.add_argument(
2100+
"--show-traceback", "--tb", action="store_true", help="Show traceback on fatal error"
2101+
)
20942102

20952103
return parser.parse_args(args, namespace=_Arguments())
20962104

mypyc/irbuild/builder.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -979,17 +979,13 @@ def _analyze_iterable_item_type(self, expr: Expression) -> Type:
979979

980980
def is_native_module(self, module: str) -> bool:
981981
"""Is the given module one compiled by mypyc?"""
982-
return module in self.mapper.group_map
982+
return self.mapper.is_native_module(module)
983983

984984
def is_native_ref_expr(self, expr: RefExpr) -> bool:
985-
if expr.node is None:
986-
return False
987-
if "." in expr.node.fullname:
988-
return self.is_native_module(expr.node.fullname.rpartition(".")[0])
989-
return True
985+
return self.mapper.is_native_ref_expr(expr)
990986

991987
def is_native_module_ref_expr(self, expr: RefExpr) -> bool:
992-
return self.is_native_ref_expr(expr) and expr.kind == GDEF
988+
return self.mapper.is_native_module_ref_expr(expr)
993989

994990
def is_synthetic_type(self, typ: TypeInfo) -> bool:
995991
"""Is a type something other than just a class we've created?"""

mypyc/irbuild/mapper.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ def __init__(self, group_map: dict[str, str | None]) -> None:
6262
self.group_map = group_map
6363
self.type_to_ir: dict[TypeInfo, ClassIR] = {}
6464
self.func_to_decl: dict[SymbolNode, FuncDecl] = {}
65+
self.symbol_fullnames: set[str] = set()
6566

6667
def type_to_rtype(self, typ: Type | None) -> RType:
6768
if typ is None:
@@ -217,7 +218,8 @@ def is_native_ref_expr(self, expr: RefExpr) -> bool:
217218
if expr.node is None:
218219
return False
219220
if "." in expr.node.fullname:
220-
return self.is_native_module(expr.node.fullname.rpartition(".")[0])
221+
name = expr.node.fullname.rpartition(".")[0]
222+
return self.is_native_module(name) or name in self.symbol_fullnames
221223
return True
222224

223225
def is_native_module_ref_expr(self, expr: RefExpr) -> bool:

mypyc/irbuild/prepare.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ def build_type_map(
9494
if not options.global_opts:
9595
class_ir.children = None
9696
mapper.type_to_ir[cdef.info] = class_ir
97+
mapper.symbol_fullnames.add(class_ir.fullname)
9798

9899
# Populate structural information in class IR for extension classes.
99100
for module, cdef in classes:
@@ -149,6 +150,7 @@ def load_type_map(mapper: Mapper, modules: list[MypyFile], deser_ctx: DeserMaps)
149150
if isinstance(node.node, TypeInfo) and is_from_module(node.node, module):
150151
ir = deser_ctx.classes[node.node.fullname]
151152
mapper.type_to_ir[node.node] = ir
153+
mapper.symbol_fullnames.add(node.node.fullname)
152154
mapper.func_to_decl[node.node] = ir.ctor
153155

154156
for module in modules:

mypyc/test-data/run-classes.test

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2594,3 +2594,15 @@ def test_class_final_attribute_inherited() -> None:
25942594
assert C().b == 2
25952595
assert B().c == 3
25962596
assert C().c == 3
2597+
2598+
[case testClassWithFinalAttributeAccess]
2599+
from typing import Final
2600+
2601+
class C:
2602+
a: Final = {'x': 'y'}
2603+
b: Final = C.a
2604+
2605+
def test_final_attribute() -> None:
2606+
assert C.a['x'] == 'y'
2607+
assert C.b['x'] == 'y'
2608+
assert C.a is C.b

test-data/unit/check-parameter-specification.test

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2304,6 +2304,41 @@ reveal_type(capture(err)) # N: Revealed type is "builtins.int"
23042304

23052305
[builtins fixtures/paramspec.pyi]
23062306

2307+
[case testRunParamSpecOverlappingOverloadsOrder]
2308+
from typing import Any, Callable, overload
2309+
from typing_extensions import ParamSpec
2310+
2311+
P = ParamSpec("P")
2312+
2313+
class Base:
2314+
pass
2315+
class Child(Base):
2316+
def __call__(self) -> str: ...
2317+
class NotChild:
2318+
def __call__(self) -> str: ...
2319+
2320+
@overload
2321+
def handle(func: Base) -> int: ...
2322+
@overload
2323+
def handle(func: Callable[P, str], *args: P.args, **kwargs: P.kwargs) -> str: ...
2324+
def handle(func: Any, *args: Any, **kwargs: Any) -> Any:
2325+
return func(*args, **kwargs)
2326+
2327+
@overload
2328+
def handle_reversed(func: Callable[P, str], *args: P.args, **kwargs: P.kwargs) -> str: ...
2329+
@overload
2330+
def handle_reversed(func: Base) -> int: ...
2331+
def handle_reversed(func: Any, *args: Any, **kwargs: Any) -> Any:
2332+
return func(*args, **kwargs)
2333+
2334+
reveal_type(handle(Child())) # N: Revealed type is "builtins.int"
2335+
reveal_type(handle(NotChild())) # N: Revealed type is "builtins.str"
2336+
2337+
reveal_type(handle_reversed(Child())) # N: Revealed type is "builtins.str"
2338+
reveal_type(handle_reversed(NotChild())) # N: Revealed type is "builtins.str"
2339+
2340+
[builtins fixtures/paramspec.pyi]
2341+
23072342
[case testBindPartial]
23082343
from functools import partial
23092344
from typing_extensions import ParamSpec

test-data/unit/check-selftype.test

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2176,3 +2176,41 @@ class count:
21762176
def foo(x: Union[range[int], count]) -> None:
21772177
for item in x:
21782178
reveal_type(item) # N: Revealed type is "builtins.int"
2179+
2180+
[case testGenericDescriptorWithSelfTypeAnnotationsAndOverloads]
2181+
from __future__ import annotations
2182+
from typing import Any, overload, Callable, TypeVar, Generic, ParamSpec
2183+
from typing_extensions import Concatenate
2184+
2185+
C = TypeVar("C", bound=Callable[..., Any])
2186+
S = TypeVar("S")
2187+
P = ParamSpec("P")
2188+
R = TypeVar("R")
2189+
2190+
class Descriptor(Generic[C]):
2191+
def __init__(self, impl: C) -> None: ...
2192+
2193+
@overload
2194+
def __get__(
2195+
self: Descriptor[C], instance: None, owner: type | None
2196+
) -> Descriptor[C]: ...
2197+
2198+
@overload
2199+
def __get__(
2200+
self: Descriptor[Callable[Concatenate[S, P], R]], instance: S, owner: type | None,
2201+
) -> Callable[P, R]: ...
2202+
2203+
def __get__(self, *args, **kwargs): ...
2204+
2205+
class Test:
2206+
@Descriptor
2207+
def method(self, foo: int, bar: str) -> bytes: ...
2208+
2209+
reveal_type(Test().method) # N: Revealed type is "def (foo: builtins.int, bar: builtins.str) -> builtins.bytes"
2210+
2211+
class Test2:
2212+
@Descriptor
2213+
def method(self, foo: int, *, bar: str) -> bytes: ...
2214+
2215+
reveal_type(Test2().method) # N: Revealed type is "def (foo: builtins.int, *, bar: builtins.str) -> builtins.bytes"
2216+
[builtins fixtures/tuple.pyi]

0 commit comments

Comments
 (0)