Skip to content

Commit 1eb673f

Browse files
Merge branch 'master' into patch-4
2 parents 4441489 + 61cbe0c commit 1eb673f

File tree

9 files changed

+76
-10
lines changed

9 files changed

+76
-10
lines changed

mypy/checker.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7190,7 +7190,7 @@ def check_subtype(
71907190
if (
71917191
isinstance(supertype, Instance)
71927192
and supertype.type.is_protocol
7193-
and isinstance(subtype, (CallableType, Instance, TupleType, TypedDictType))
7193+
and isinstance(subtype, (CallableType, Instance, TupleType, TypedDictType, TypeType))
71947194
):
71957195
self.msg.report_protocol_problems(subtype, supertype, context, parent_error=error)
71967196
if isinstance(supertype, CallableType) and isinstance(subtype, Instance):

mypy/messages.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3090,9 +3090,14 @@ def get_bad_protocol_flags(
30903090
assert right.type.is_protocol
30913091
all_flags: list[tuple[str, set[int], set[int]]] = []
30923092
for member in right.type.protocol_members:
3093-
if find_member(member, left, left):
3094-
item = (member, get_member_flags(member, left), get_member_flags(member, right))
3095-
all_flags.append(item)
3093+
if find_member(member, left, left, class_obj=class_obj):
3094+
all_flags.append(
3095+
(
3096+
member,
3097+
get_member_flags(member, left, class_obj=class_obj),
3098+
get_member_flags(member, right),
3099+
)
3100+
)
30963101
bad_flags = []
30973102
for name, subflags, superflags in all_flags:
30983103
if (

mypy/subtypes.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1319,8 +1319,8 @@ def find_member(
13191319
is_lvalue=is_lvalue,
13201320
is_super=False,
13211321
is_operator=is_operator,
1322-
original_type=itype,
1323-
self_type=subtype,
1322+
original_type=TypeType.make_normalized(itype) if class_obj else itype,
1323+
self_type=TypeType.make_normalized(subtype) if class_obj else subtype,
13241324
context=Context(), # all errors are filtered, but this is a required argument
13251325
chk=type_checker,
13261326
suppress_errors=True,

mypy/util.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ def is_dunder(name: str, exclude_special: bool = False) -> bool:
6666

6767

6868
def is_sunder(name: str) -> bool:
69-
return not is_dunder(name) and name.startswith("_") and name.endswith("_")
69+
return not is_dunder(name) and name.startswith("_") and name.endswith("_") and name != "_"
7070

7171

7272
def split_module_names(mod_name: str) -> list[str]:

mypyc/build.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@ def construct_groups(
357357
sources: list[BuildSource],
358358
separate: bool | list[tuple[list[str], str | None]],
359359
use_shared_lib: bool,
360+
group_name_override: str | None,
360361
) -> emitmodule.Groups:
361362
"""Compute Groups given the input source list and separate configs.
362363
@@ -386,7 +387,10 @@ def construct_groups(
386387
# Generate missing names
387388
for i, (group, name) in enumerate(groups):
388389
if use_shared_lib and not name:
389-
name = group_name([source.module for source in group])
390+
if group_name_override is not None:
391+
name = group_name_override
392+
else:
393+
name = group_name([source.module for source in group])
390394
groups[i] = (group, name)
391395

392396
return groups
@@ -432,7 +436,10 @@ def mypyc_build(
432436
or always_use_shared_lib
433437
)
434438

435-
groups = construct_groups(mypyc_sources, separate, use_shared_lib)
439+
groups = construct_groups(mypyc_sources, separate, use_shared_lib, compiler_options.group_name)
440+
441+
if compiler_options.group_name is not None:
442+
assert len(groups) == 1, "If using custom group_name, only one group is expected"
436443

437444
# We let the test harness just pass in the c file contents instead
438445
# so that it can do a corner-cutting version without full stubs.
@@ -477,6 +484,7 @@ def mypycify(
477484
target_dir: str | None = None,
478485
include_runtime_files: bool | None = None,
479486
strict_dunder_typing: bool = False,
487+
group_name: str | None = None,
480488
) -> list[Extension]:
481489
"""Main entry point to building using mypyc.
482490
@@ -519,6 +527,10 @@ def mypycify(
519527
strict_dunder_typing: If True, force dunder methods to have the return type
520528
of the method strictly, which can lead to more
521529
optimization opportunities. Defaults to False.
530+
group_name: If set, override the default group name derived from
531+
the hash of module names. This is used for the names of the
532+
output C files and the shared library. This is only supported
533+
if there is a single group. [Experimental]
522534
"""
523535

524536
# Figure out our configuration
@@ -530,6 +542,7 @@ def mypycify(
530542
target_dir=target_dir,
531543
include_runtime_files=include_runtime_files,
532544
strict_dunder_typing=strict_dunder_typing,
545+
group_name=group_name,
533546
)
534547

535548
# Generate all the actual important C code

mypyc/options.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ def __init__(
1515
capi_version: tuple[int, int] | None = None,
1616
python_version: tuple[int, int] | None = None,
1717
strict_dunder_typing: bool = False,
18+
group_name: str | None = None,
1819
) -> None:
1920
self.strip_asserts = strip_asserts
2021
self.multi_file = multi_file
@@ -38,3 +39,9 @@ def __init__(
3839
# will assume the return type of the method strictly, which can lead to
3940
# more optimization opportunities.
4041
self.strict_dunders_typing = strict_dunder_typing
42+
# Override the automatic group name derived from the hash of module names.
43+
# This affects the names of generated .c, .h and shared library files.
44+
# This is only supported when compiling exactly one group, and a shared
45+
# library is generated (with shims). This can be used to make the output
46+
# file names more predictable.
47+
self.group_name = group_name

mypyc/test/test_run.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ def run_case_step(self, testcase: DataDrivenTestCase, incremental_step: int) ->
235235
else False
236236
)
237237

238-
groups = construct_groups(sources, separate, len(module_names) > 1)
238+
groups = construct_groups(sources, separate, len(module_names) > 1, None)
239239

240240
try:
241241
compiler_options = CompilerOptions(

test-data/unit/check-enum.test

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2524,3 +2524,18 @@ class Base:
25242524
self.o = Enum("o", names) # E: Enum type as attribute is not supported \
25252525
# E: Second argument of Enum() must be string, tuple, list or dict literal for mypy to determine Enum members
25262526
[builtins fixtures/tuple.pyi]
2527+
2528+
[case testSingleUnderscoreNameEnumMember]
2529+
# flags: --warn-unreachable
2530+
2531+
# https://github.com/python/mypy/issues/19271
2532+
from enum import Enum
2533+
2534+
class Things(Enum):
2535+
_ = "under score"
2536+
2537+
def check(thing: Things) -> None:
2538+
if thing is Things._:
2539+
return None
2540+
return None # E: Statement is unreachable
2541+
[builtins fixtures/enum.pyi]

test-data/unit/check-protocols.test

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4552,6 +4552,32 @@ t = Test(Mock())
45524552
reveal_type(t) # N: Revealed type is "__main__.Test[Any]"
45534553
[builtins fixtures/dict.pyi]
45544554

4555+
[case testProtocolClassObjectDescriptor]
4556+
from typing import Any, Protocol, overload
4557+
4558+
class Desc:
4559+
@overload
4560+
def __get__(self, instance: None, owner: Any) -> Desc: ...
4561+
@overload
4562+
def __get__(self, instance: object, owner: Any) -> int: ...
4563+
def __get__(self, instance, owner):
4564+
pass
4565+
4566+
class HasDesc(Protocol):
4567+
attr: Desc
4568+
4569+
class HasInt(Protocol):
4570+
attr: int
4571+
4572+
class C:
4573+
attr = Desc()
4574+
4575+
x: HasInt = C()
4576+
y: HasDesc = C
4577+
z: HasInt = C # E: Incompatible types in assignment (expression has type "type[C]", variable has type "HasInt") \
4578+
# N: Following member(s) of "C" have conflicts: \
4579+
# N: attr: expected "int", got "Desc"
4580+
45554581
[case testProtocolErrorReportingNoDuplicates]
45564582
from typing import Callable, Protocol, TypeVar
45574583

0 commit comments

Comments
 (0)