@@ -3280,13 +3280,68 @@ class Dyn: pass
32803280
32813281[case testDunderNew]
32823282from __future__ import annotations
3283- from typing import Union
3283+ from typing import Any, Union
3284+
3285+ from testutil import assertRaises
32843286
32853287class Add:
32863288 l: IntLike
32873289 r: IntLike
32883290
3289- def __new__(cls, l: IntLike, r: IntLike) -> IntLike: # type: ignore[misc]
3291+ def __new__(cls, l: IntLike, r: IntLike) -> Any:
3292+ return (
3293+ l if r == 0 else
3294+ r if l == 0 else
3295+ super().__new__(cls)
3296+ )
3297+
3298+ def __init__(self, l: IntLike, r: IntLike):
3299+ self.l = l
3300+ self.r = r
3301+
3302+ IntLike = Union[int, Add]
3303+
3304+ class RaisesException:
3305+ def __new__(cls, val: int) -> RaisesException:
3306+ if val == 0:
3307+ raise RuntimeError("Invalid value!")
3308+ return super().__new__(cls)
3309+
3310+ def __init__(self, val: int) -> None:
3311+ self.val = val
3312+
3313+ def test_dunder_new() -> None:
3314+ add_instance: Any = Add(1, 5)
3315+ assert type(add_instance) == Add
3316+ assert add_instance.l == 1
3317+ assert add_instance.r == 5
3318+
3319+ # TODO: explicit types should not be needed but mypy does not use
3320+ # the return type of __new__ which makes mypyc add casts to Add.
3321+ right_int: Any = Add(0, 5)
3322+ assert type(right_int) == int
3323+ assert right_int == 5
3324+
3325+ left_int: Any = Add(1, 0)
3326+ assert type(left_int) == int
3327+ assert left_int == 1
3328+
3329+ with assertRaises(RuntimeError, "Invalid value!"):
3330+ raised = RaisesException(0)
3331+
3332+ not_raised = RaisesException(1)
3333+ assert not_raised.val == 1
3334+
3335+
3336+ [case testDunderNewInInterpreted]
3337+ from __future__ import annotations
3338+ from typing import Any, Union
3339+
3340+ class Add:
3341+ l: IntLike
3342+ r: IntLike
3343+
3344+ def __new__(cls, l: IntLike, r: IntLike) -> Any:
32903345 print(f'running __new__ with {l} and {r}')
32913346
32923347 return (
@@ -3302,18 +3357,32 @@ class Add:
33023357 def __repr__(self) -> str:
33033358 return f'({self.l} + {self.r})'
33043359
3305- def __add__(self, other: IntLike) -> IntLike:
3306- return Add(self, other)
3307-
33083360IntLike = Union[int, Add]
33093361
3362+ class RaisesException:
3363+ def __new__(cls, val: int) -> RaisesException:
3364+ if val == 0:
3365+ raise RuntimeError("Invalid value!")
3366+ return super().__new__(cls)
3367+
3368+ def __init__(self, val: int) -> None:
3369+ self.val = val
3370+
33103371[file driver.py]
3311- from native import Add
3372+ from native import Add, RaisesException
3373+
3374+ from testutil import assertRaises
33123375
33133376print(f'{Add(1, 5)=}')
33143377print(f'{Add(0, 5)=}')
33153378print(f'{Add(1, 0)=}')
33163379
3380+ with assertRaises(RuntimeError, "Invalid value!"):
3381+ raised = RaisesException(0)
3382+
3383+ not_raised = RaisesException(1)
3384+ assert not_raised.val == 1
3385+
33173386[out]
33183387running __new__ with 1 and 5
33193388Add(1, 5)=(1 + 5)
@@ -3325,45 +3394,126 @@ Add(1, 0)=1
33253394[case testInheritedDunderNew]
33263395from __future__ import annotations
33273396from mypy_extensions import mypyc_attr
3397+ from typing import Self
33283398
33293399from m import interpreted_subclass
33303400
33313401@mypyc_attr(allow_interpreted_subclasses=True)
33323402class Base:
33333403 val: int
33343404
3335- def __new__(cls, val: int) -> Base :
3405+ def __new__(cls, val: int) -> Self :
33363406 obj = super().__new__(cls)
33373407 obj.val = val + 1
33383408 return obj
33393409
3340- def __init__(self, val: int):
3341- pass
3410+ def __init__(self, val: int) -> None :
3411+ self.init_val = val
33423412
33433413class Sub(Base):
3344- def __new__(cls, val: int) -> Base: # type: ignore[misc]
3414+ def __new__(cls, val: int) -> Self:
33453415 return super().__new__(cls, val + 1)
33463416
3347- def __init__(self, val: int):
3348- pass
3417+ def __init__(self, val: int) -> None:
3418+ super().__init__(val)
3419+ self.init_val = self.init_val * 2
3420+
3421+ class SubWithoutNew(Base):
3422+ def __init__(self, val: int) -> None:
3423+ super().__init__(val)
3424+ self.init_val = self.init_val * 2
3425+
3426+ class BaseWithoutInterpretedSubclasses:
3427+ val: int
3428+
3429+ def __new__(cls, val: int) -> Self:
3430+ obj = super().__new__(cls)
3431+ obj.val = val + 1
3432+ return obj
3433+
3434+ def __init__(self, val: int) -> None:
3435+ self.init_val = val
3436+
3437+ class SubNoInterpreted(BaseWithoutInterpretedSubclasses):
3438+ def __new__(cls, val: int) -> Self:
3439+ return super().__new__(cls, val + 1)
3440+
3441+ def __init__(self, val: int) -> None:
3442+ super().__init__(val)
3443+ self.init_val = self.init_val * 2
3444+
3445+ class SubNoInterpretedWithoutNew(BaseWithoutInterpretedSubclasses):
3446+ def __init__(self, val: int) -> None:
3447+ super().__init__(val)
3448+ self.init_val = self.init_val * 2
33493449
33503450def test_inherited_dunder_new() -> None:
3451+ b = Base(42)
3452+ assert type(b) == Base
3453+ assert b.val == 43
3454+ assert b.init_val == 42
3455+
33513456 s = Sub(42)
3457+ assert type(s) == Sub
3458+ assert s.val == 44
3459+ assert s.init_val == 84
3460+
3461+ s2 = SubWithoutNew(42)
3462+ assert type(s2) == SubWithoutNew
3463+ assert s2.val == 43
3464+ assert s2.init_val == 84
3465+
3466+ def test_inherited_dunder_new_without_interpreted_subclasses() -> None:
3467+ b = BaseWithoutInterpretedSubclasses(42)
3468+ assert type(b) == BaseWithoutInterpretedSubclasses
3469+ assert b.val == 43
3470+ assert b.init_val == 42
3471+
3472+ s = SubNoInterpreted(42)
3473+ assert type(s) == SubNoInterpreted
33523474 assert s.val == 44
3475+ assert s.init_val == 84
3476+
3477+ s2 = SubNoInterpretedWithoutNew(42)
3478+ assert type(s2) == SubNoInterpretedWithoutNew
3479+ assert s2.val == 43
3480+ assert s2.init_val == 84
33533481
33543482def test_interpreted_subclass() -> None:
33553483 interpreted_subclass(Base)
33563484
33573485[file m.py]
33583486from __future__ import annotations
3487+ from typing import Self
33593488
33603489def interpreted_subclass(base) -> None:
3490+ b = base(42)
3491+ assert type(b) == base
3492+ assert b.val == 43
3493+ assert b.init_val == 42
3494+
33613495 class InterpretedSub(base):
3362- def __new__(cls, val: int) -> base :
3496+ def __new__(cls, val: int) -> Self :
33633497 return super().__new__(cls, val + 1)
3498+
3499+ def __init__(self, val: int) -> None:
3500+ super().__init__(val)
3501+ self.init_val : int = self.init_val * 2
33643502
33653503 s = InterpretedSub(42)
3504+ assert type(s) == InterpretedSub
33663505 assert s.val == 44
3506+ assert s.init_val == 84
3507+
3508+ class InterpretedSubWithoutNew(base):
3509+ def __init__(self, val: int) -> None:
3510+ super().__init__(val)
3511+ self.init_val : int = self.init_val * 2
3512+
3513+ s2 = InterpretedSubWithoutNew(42)
3514+ assert type(s2) == InterpretedSubWithoutNew
3515+ assert s2.val == 43
3516+ assert s2.init_val == 84
33673517
33683518[case testDunderNewInitArgMismatch]
33693519from __future__ import annotations
@@ -3463,56 +3613,80 @@ with assertRaises(AttributeError, "attribute 'val' of 'Test2' undefined"):
34633613
34643614[case testDunderNewAttributeAccess]
34653615from __future__ import annotations
3616+
3617+ from mypy_extensions import u8
34663618from testutil import assertRaises
34673619
34683620class Test:
34693621 native: int
34703622 generic: object
3471- def __new__(cls, native: int, generic: object) -> Test:
3623+ bitfield: u8
3624+ default: int = 5
3625+
3626+ def __new__(cls, native: int, generic: object, bitfield: u8) -> Test:
34723627 obj = super().__new__(cls)
34733628
34743629 with assertRaises(AttributeError, "attribute 'native' of 'Test' undefined"):
34753630 print(obj.native)
34763631 with assertRaises(AttributeError, "attribute 'generic' of 'Test' undefined"):
34773632 print(obj.generic)
3633+ with assertRaises(AttributeError, "attribute 'bitfield' of 'Test' undefined"):
3634+ print(obj.bitfield)
34783635
34793636 obj.native = native
34803637 obj.generic = generic
3638+ obj.bitfield = bitfield
34813639
34823640 obj.native = obj.native + 1
34833641 obj.generic = obj.generic.__str__()
3642+ obj.bitfield = obj.bitfield & 0x0F
3643+ obj.default = obj.default * 2
34843644 return obj
34853645
34863646def test_attribute_access() -> None:
3487- t = Test(42, {})
3647+ t = Test(42, {}, 0xCC )
34883648 assert t.native == 43
34893649 assert t.generic == "{}"
3650+ assert t.bitfield == 0x0C
3651+ assert t.default == 10
34903652
34913653[case testDunderNewAttributeAccessInInterpreted]
34923654from __future__ import annotations
3655+
3656+ from mypy_extensions import u8
34933657from testutil import assertRaises
34943658
34953659class Test:
34963660 native: int
34973661 generic: object
3498- def __new__(cls, native: int, generic: object) -> Test:
3662+ bitfield: u8
3663+ default: int = 5
3664+
3665+ def __new__(cls, native: int, generic: object, bitfield: u8) -> Test:
34993666 obj = super().__new__(cls)
35003667
35013668 with assertRaises(AttributeError, "attribute 'native' of 'Test' undefined"):
35023669 print(obj.native)
35033670 with assertRaises(AttributeError, "attribute 'generic' of 'Test' undefined"):
35043671 print(obj.generic)
3672+ with assertRaises(AttributeError, "attribute 'bitfield' of 'Test' undefined"):
3673+ print(obj.bitfield)
35053674
35063675 obj.native = native
35073676 obj.generic = generic
3677+ obj.bitfield = bitfield
35083678
35093679 obj.native = obj.native + 1
35103680 obj.generic = obj.generic.__str__()
3681+ obj.bitfield = obj.bitfield & 0x0F
3682+ obj.default = obj.default * 2
35113683 return obj
35123684
35133685[file driver.py]
35143686from native import Test
35153687
3516- t = Test(42, {})
3688+ t = Test(42, {}, 0xCC )
35173689assert t.native == 43
35183690assert t.generic == "{}"
3691+ assert t.bitfield == 0x0C
3692+ assert t.default == 10
0 commit comments