Skip to content

Commit 1e241dc

Browse files
committed
Address review comments pt.2
1 parent 94cf8dd commit 1e241dc

File tree

4 files changed

+84
-17
lines changed

4 files changed

+84
-17
lines changed

mypyc/irbuild/specialize.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
NameExpr,
3131
RefExpr,
3232
StrExpr,
33+
SuperExpr,
3334
TupleExpr,
3435
Var,
3536
)
@@ -1012,11 +1013,20 @@ def translate_object_new(builder: IRBuilder, expr: CallExpr, callee: RefExpr) ->
10121013
if fn.name != "__new__":
10131014
return None
10141015

1016+
is_super_new = isinstance(expr.callee, SuperExpr)
1017+
is_object_new = (
1018+
isinstance(callee, MemberExpr)
1019+
and isinstance(callee.expr, NameExpr)
1020+
and callee.expr.fullname == "builtins.object"
1021+
)
1022+
if not (is_super_new or is_object_new):
1023+
return None
1024+
10151025
ir = builder.get_current_class_ir()
10161026
if ir is None:
10171027
return None
10181028

1019-
call = "object.__new__()"
1029+
call = '"object.__new__()"'
10201030
if not ir.is_ext_class:
10211031
builder.error(f"{call} not supported for non-extension classes", expr.line)
10221032
return None

mypyc/irbuild/statement.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -182,19 +182,24 @@ def check_unsupported_cls_assignment(builder: IRBuilder, stmt: AssignmentStmt) -
182182
return
183183

184184
cls_arg = method_args[0]
185-
lvalues: list[Expression] = []
186-
for lvalue in stmt.lvalues:
187-
if isinstance(lvalue, (TupleExpr, ListExpr)):
188-
lvalues += lvalue.items
189-
else:
190-
lvalues.append(lvalue)
185+
186+
def flatten(lvalues: list[Expression]) -> list[Expression]:
187+
flat = []
188+
for lvalue in lvalues:
189+
if isinstance(lvalue, (TupleExpr, ListExpr)):
190+
flat += flatten(lvalue.items)
191+
else:
192+
flat.append(lvalue)
193+
return flat
194+
195+
lvalues = flatten(stmt.lvalues)
191196

192197
for lvalue in lvalues:
193198
if isinstance(lvalue, NameExpr) and lvalue.name == cls_arg:
194199
# Disallowed because it could break the transformation of object.__new__ calls
195200
# inside __new__ methods.
196201
builder.error(
197-
f"Assignment to argument {cls_arg} in __new__ method unsupported", stmt.line
202+
f'Assignment to argument "{cls_arg}" in "__new__" method unsupported', stmt.line
198203
)
199204

200205

mypyc/test-data/irbuild-classes.test

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2022,43 +2022,48 @@ from typing import Any
20222022
@mypyc_attr(native_class=False)
20232023
class NonNative:
20242024
def __new__(cls) -> NonNative:
2025-
return super().__new__(cls) # E: object.__new__() not supported for non-extension classes
2025+
return super().__new__(cls) # E: "object.__new__()" not supported for non-extension classes
20262026

20272027
class InheritsPython(dict):
20282028
def __new__(cls) -> InheritsPython:
2029-
return super().__new__(cls) # E: object.__new__() not supported for classes inheriting from non-native classes
2029+
return super().__new__(cls) # E: "object.__new__()" not supported for classes inheriting from non-native classes
20302030

20312031
@mypyc_attr(native_class=False)
20322032
class NonNativeObjectNew:
20332033
def __new__(cls) -> NonNativeObjectNew:
2034-
return object.__new__(cls) # E: object.__new__() not supported for non-extension classes
2034+
return object.__new__(cls) # E: "object.__new__()" not supported for non-extension classes
20352035

20362036
class InheritsPythonObjectNew(dict):
20372037
def __new__(cls) -> InheritsPythonObjectNew:
2038-
return object.__new__(cls) # E: object.__new__() not supported for classes inheriting from non-native classes
2038+
return object.__new__(cls) # E: "object.__new__()" not supported for classes inheriting from non-native classes
20392039

20402040
class ClsAssignment:
20412041
def __new__(cls: Any) -> Any:
2042-
cls = str # E: Assignment to argument cls in __new__ method unsupported
2042+
cls = str # E: Assignment to argument "cls" in "__new__" method unsupported
20432043
return super().__new__(cls)
20442044

20452045
class ClsTupleAssignment:
20462046
def __new__(class_i_want: Any, val: int) -> Any:
2047-
class_i_want, val = dict, 1 # E: Assignment to argument class_i_want in __new__ method unsupported
2047+
class_i_want, val = dict, 1 # E: Assignment to argument "class_i_want" in "__new__" method unsupported
20482048
return object.__new__(class_i_want)
20492049

20502050
class ClsListAssignment:
20512051
def __new__(cls: Any, val: str) -> Any:
2052-
[cls, val] = [object, "object"] # E: Assignment to argument cls in __new__ method unsupported
2052+
[cls, val] = [object, "object"] # E: Assignment to argument "cls" in "__new__" method unsupported
2053+
return object.__new__(cls)
2054+
2055+
class ClsNestedAssignment:
2056+
def __new__(cls: Any, val1: str, val2: int) -> Any:
2057+
[val1, [val2, cls]] = ["val1", [2, int]] # E: Assignment to argument "cls" in "__new__" method unsupported
20532058
return object.__new__(cls)
20542059

20552060
class WrongNumberOfArgs:
20562061
def __new__(cls):
2057-
return super().__new__() # E: object.__new__() supported only with 1 argument, got 0
2062+
return super().__new__() # E: "object.__new__()" supported only with 1 argument, got 0
20582063

20592064
class WrongNumberOfArgsObjectNew:
20602065
def __new__(cls):
2061-
return object.__new__(cls, 1) # E: object.__new__() supported only with 1 argument, got 2
2066+
return object.__new__(cls, 1) # E: "object.__new__()" supported only with 1 argument, got 2
20622067

20632068
[case testClassWithFreeList]
20642069
from mypy_extensions import mypyc_attr, trait

mypyc/test-data/run-classes.test

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3945,6 +3945,53 @@ assert t.generic == "{}"
39453945
assert t.bitfield == 0x0C
39463946
assert t.default == 10
39473947

3948+
[case testUntransformedDunderNewCalls]
3949+
from testutil import assertRaises
3950+
from typing import Any
3951+
3952+
class TestStrCls:
3953+
def __new__(cls):
3954+
return str.__new__(cls)
3955+
3956+
@classmethod
3957+
def factory(cls):
3958+
return str.__new__(cls)
3959+
3960+
class TestStrStr:
3961+
def __new__(cls):
3962+
return str.__new__(str)
3963+
3964+
@classmethod
3965+
def factory(cls):
3966+
return str.__new__(str)
3967+
3968+
class TestStrInt:
3969+
def __new__(cls):
3970+
return str.__new__(int)
3971+
3972+
@classmethod
3973+
def factory(cls):
3974+
return str.__new__(int)
3975+
3976+
def test_untransformed_dunder_new() -> None:
3977+
with assertRaises(TypeError, "str.__new__(TestStrCls): TestStrCls is not a subtype of str"):
3978+
i = TestStrCls()
3979+
3980+
j: Any = TestStrStr()
3981+
assert j == ""
3982+
3983+
with assertRaises(TypeError, "str.__new__(int): int is not a subtype of str"):
3984+
k = TestStrInt()
3985+
3986+
with assertRaises(TypeError, "str.__new__(TestStrCls): TestStrCls is not a subtype of str"):
3987+
i = TestStrCls.factory()
3988+
3989+
j = TestStrStr.factory()
3990+
assert j == ""
3991+
3992+
with assertRaises(TypeError, "str.__new__(int): int is not a subtype of str"):
3993+
k = TestStrInt.factory()
3994+
39483995
[case testPerTypeFreeList]
39493996
from __future__ import annotations
39503997

0 commit comments

Comments
 (0)