Skip to content

Commit 75c949c

Browse files
committed
Add more test cases
1 parent 30370d9 commit 75c949c

File tree

3 files changed

+215
-20
lines changed

3 files changed

+215
-20
lines changed

mypyc/test-data/fixtures/typing-full.pyi

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ Final = 0
3232
TypedDict = 0
3333
NoReturn = 0
3434
NewType = 0
35+
Self = 0
3536
Callable: _SpecialForm
3637
Union: _SpecialForm
3738
Literal: _SpecialForm
@@ -175,6 +176,3 @@ class _TypedDict(Mapping[str, object]):
175176

176177
class TypeAliasType:
177178
pass
178-
179-
def Self(self, parameters):
180-
raise TypeError(f"{self} is not subscriptable")

mypyc/test-data/irbuild-classes.test

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1608,6 +1608,29 @@ L0:
16081608
r0 = CPy_TYPE(x)
16091609
return r0
16101610

1611+
[case testDunderNew]
1612+
from __future__ import annotations
1613+
1614+
class Test:
1615+
val: int
1616+
1617+
def __new__(cls, val: int) -> Test:
1618+
obj = super().__new__(cls)
1619+
obj.val = val
1620+
return obj
1621+
1622+
[out]
1623+
def Test.__new__(cls, val):
1624+
cls :: object
1625+
val :: int
1626+
r0, obj :: __main__.Test
1627+
r1 :: bool
1628+
L0:
1629+
r0 = __mypyc__Test_setup(cls)
1630+
obj = r0
1631+
obj.val = val; r1 = is_error
1632+
return obj
1633+
16111634
[case testUnsupportedDunderNew]
16121635
from __future__ import annotations
16131636
from mypy_extensions import mypyc_attr

mypyc/test-data/run-classes.test

Lines changed: 191 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3280,13 +3280,68 @@ class Dyn: pass
32803280

32813281
[case testDunderNew]
32823282
from __future__ import annotations
3283-
from typing import Union
3283+
from typing import Any, Union
3284+
3285+
from testutil import assertRaises
32843286

32853287
class 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-
33083360
IntLike = 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

33133376
print(f'{Add(1, 5)=}')
33143377
print(f'{Add(0, 5)=}')
33153378
print(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]
33183387
running __new__ with 1 and 5
33193388
Add(1, 5)=(1 + 5)
@@ -3325,45 +3394,126 @@ Add(1, 0)=1
33253394
[case testInheritedDunderNew]
33263395
from __future__ import annotations
33273396
from mypy_extensions import mypyc_attr
3397+
from typing import Self
33283398

33293399
from m import interpreted_subclass
33303400

33313401
@mypyc_attr(allow_interpreted_subclasses=True)
33323402
class 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

33433413
class 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

33503450
def 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

33543482
def test_interpreted_subclass() -> None:
33553483
interpreted_subclass(Base)
33563484

33573485
[file m.py]
33583486
from __future__ import annotations
3487+
from typing import Self
33593488

33603489
def 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]
33693519
from __future__ import annotations
@@ -3463,56 +3613,80 @@ with assertRaises(AttributeError, "attribute 'val' of 'Test2' undefined"):
34633613

34643614
[case testDunderNewAttributeAccess]
34653615
from __future__ import annotations
3616+
3617+
from mypy_extensions import u8
34663618
from testutil import assertRaises
34673619

34683620
class 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

34863646
def 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]
34923654
from __future__ import annotations
3655+
3656+
from mypy_extensions import u8
34933657
from testutil import assertRaises
34943658

34953659
class 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]
35143686
from native import Test
35153687

3516-
t = Test(42, {})
3688+
t = Test(42, {}, 0xCC)
35173689
assert t.native == 43
35183690
assert t.generic == "{}"
3691+
assert t.bitfield == 0x0C
3692+
assert t.default == 10

0 commit comments

Comments
 (0)