run-dunders.test 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945
  1. # Test cases for (some) dunder methods (compile and run)
  2. [case testDundersMisc]
  3. # Legacy test case for dunders (don't add more here)
  4. from typing import Any
  5. class Item:
  6. def __init__(self, value: str) -> None:
  7. self.value = value
  8. def __hash__(self) -> int:
  9. return hash(self.value)
  10. def __eq__(self, rhs: object) -> bool:
  11. return isinstance(rhs, Item) and self.value == rhs.value
  12. def __lt__(self, x: 'Item') -> bool:
  13. return self.value < x.value
  14. class Subclass1(Item):
  15. def __bool__(self) -> bool:
  16. return bool(self.value)
  17. class NonBoxedThing:
  18. def __getitem__(self, index: Item) -> Item:
  19. return Item("2 * " + index.value + " + 1")
  20. class BoxedThing:
  21. def __getitem__(self, index: int) -> int:
  22. return 2 * index + 1
  23. class Subclass2(BoxedThing):
  24. pass
  25. class UsesNotImplemented:
  26. def __eq__(self, b: object) -> bool:
  27. return NotImplemented
  28. def index_into(x : Any, y : Any) -> Any:
  29. return x[y]
  30. def internal_index_into() -> None:
  31. x = BoxedThing()
  32. print (x[3])
  33. y = NonBoxedThing()
  34. z = Item("3")
  35. print(y[z].value)
  36. def is_truthy(x: Item) -> bool:
  37. return True if x else False
  38. [file driver.py]
  39. from native import *
  40. x = BoxedThing()
  41. y = 3
  42. print(x[y], index_into(x, y))
  43. x = Subclass2()
  44. y = 3
  45. print(x[y], index_into(x, y))
  46. z = NonBoxedThing()
  47. w = Item("3")
  48. print(z[w].value, index_into(z, w).value)
  49. i1 = Item('lolol')
  50. i2 = Item('lol' + 'ol')
  51. i3 = Item('xyzzy')
  52. assert hash(i1) == hash(i2)
  53. assert i1 == i2
  54. assert not i1 != i2
  55. assert not i1 == i3
  56. assert i1 != i3
  57. assert i2 < i3
  58. assert not i1 < i2
  59. assert i1 == Subclass1('lolol')
  60. assert is_truthy(Item(''))
  61. assert is_truthy(Item('a'))
  62. assert not is_truthy(Subclass1(''))
  63. assert is_truthy(Subclass1('a'))
  64. assert UsesNotImplemented() != object()
  65. internal_index_into()
  66. [out]
  67. 7 7
  68. 7 7
  69. 2 * 3 + 1 2 * 3 + 1
  70. 7
  71. 2 * 3 + 1
  72. [case testDundersContainer]
  73. # Sequence/mapping dunder methods
  74. from typing import Any
  75. class Seq:
  76. def __init__(self) -> None:
  77. self.key = 0
  78. self.value = 0
  79. def __len__(self) -> int:
  80. return 5
  81. def __setitem__(self, key: int, value: int) -> None:
  82. self.key = key
  83. self.value = value
  84. def __contains__(self, x: int) -> bool:
  85. return x == 3
  86. def __delitem__(self, key: int) -> None:
  87. self.key = key
  88. class Plain: pass
  89. def any_seq() -> Any:
  90. """Return Any-typed Seq."""
  91. return Seq()
  92. def any_plain() -> Any:
  93. """Return Any-typed Seq."""
  94. return Plain()
  95. def test_len() -> None:
  96. assert len(any_seq()) == 5
  97. assert len(Seq()) == 5
  98. def test_len_error() -> None:
  99. try:
  100. len(any_plain())
  101. except TypeError:
  102. pass
  103. else:
  104. assert False
  105. def test_set_item() -> None:
  106. s = any_seq()
  107. s[44] = 66
  108. assert s.key == 44 and s.value == 66
  109. ss = Seq()
  110. ss[33] = 55
  111. assert ss.key == 33 and ss.value == 55
  112. def test_contains() -> None:
  113. assert 3 in any_seq()
  114. assert 4 not in any_seq()
  115. assert 2 not in any_seq()
  116. assert 3 in Seq()
  117. assert 4 not in Seq()
  118. assert 2 not in Seq()
  119. def test_delitem() -> None:
  120. s = any_seq()
  121. del s[55]
  122. assert s.key == 55
  123. class SeqAny:
  124. def __contains__(self, x: Any) -> Any:
  125. return x == 3
  126. def __setitem__(self, x: Any, y: Any) -> Any:
  127. self.x = x
  128. return 'x'
  129. def test_contains_any() -> None:
  130. assert (3 in SeqAny()) is True
  131. assert (2 in SeqAny()) is False
  132. assert (3 not in SeqAny()) is False
  133. assert (2 not in SeqAny()) is True
  134. s = SeqAny() # type: Any
  135. assert (3 in s) is True
  136. assert (2 in s) is False
  137. assert (3 not in s) is False
  138. assert (2 not in s) is True
  139. def test_set_item_any() -> None:
  140. s = SeqAny()
  141. s[4] = 6
  142. assert s.x == 4
  143. ss = SeqAny() # type: Any
  144. ss[5] = 7
  145. assert ss.x == 5
  146. class SeqError:
  147. def __setitem__(self, key: int, value: int) -> None:
  148. raise RuntimeError()
  149. def __contains__(self, x: int) -> bool:
  150. raise RuntimeError()
  151. def __len__(self):
  152. return -5
  153. def any_seq_error() -> Any:
  154. return SeqError()
  155. def test_set_item_error_propagate() -> None:
  156. s = any_seq_error()
  157. try:
  158. s[44] = 66
  159. except RuntimeError:
  160. pass
  161. else:
  162. assert False
  163. def test_contains_error_propagate() -> None:
  164. s = any_seq_error()
  165. try:
  166. 3 in s
  167. except RuntimeError:
  168. pass
  169. else:
  170. assert False
  171. def test_negative_len() -> None:
  172. try:
  173. len(SeqError())
  174. except ValueError:
  175. pass
  176. else:
  177. assert False
  178. class DelItemNoSetItem:
  179. def __delitem__(self, x: int) -> None:
  180. self.key = x
  181. def test_del_item_with_no_set_item() -> None:
  182. o = DelItemNoSetItem()
  183. del o[22]
  184. assert o.key == 22
  185. a = o # type: Any
  186. del a[12]
  187. assert a.key == 12
  188. try:
  189. a[1] = 2
  190. except TypeError as e:
  191. assert str(e) == "'DelItemNoSetItem' object does not support item assignment"
  192. else:
  193. assert False
  194. class SetItemOverride(dict):
  195. # Only override __setitem__, __delitem__ comes from dict
  196. def __setitem__(self, x: int, y: int) -> None:
  197. self.key = x
  198. self.value = y
  199. def test_set_item_override() -> None:
  200. o = SetItemOverride({'x': 12, 'y': 13})
  201. o[2] = 3
  202. assert o.key == 2 and o.value == 3
  203. a = o # type: Any
  204. o[4] = 5
  205. assert o.key == 4 and o.value == 5
  206. assert o['x'] == 12
  207. assert o['y'] == 13
  208. del o['x']
  209. assert 'x' not in o and 'y' in o
  210. del a['y']
  211. assert 'y' not in a and 'x' not in a
  212. class DelItemOverride(dict):
  213. # Only override __delitem__, __setitem__ comes from dict
  214. def __delitem__(self, x: int) -> None:
  215. self.key = x
  216. def test_del_item_override() -> None:
  217. o = DelItemOverride()
  218. del o[2]
  219. assert o.key == 2
  220. a = o # type: Any
  221. del o[5]
  222. assert o.key == 5
  223. o['x'] = 12
  224. assert o['x'] == 12
  225. a['y'] = 13
  226. assert a['y'] == 13
  227. class SetItemOverrideNative(Seq):
  228. def __setitem__(self, key: int, value: int) -> None:
  229. self.key = key + 1
  230. self.value = value + 1
  231. def test_native_set_item_override() -> None:
  232. o = SetItemOverrideNative()
  233. o[1] = 4
  234. assert o.key == 2 and o.value == 5
  235. del o[6]
  236. assert o.key == 6
  237. a = o # type: Any
  238. a[10] = 12
  239. assert a.key == 11 and a.value == 13
  240. del a[16]
  241. assert a.key == 16
  242. class DelItemOverrideNative(Seq):
  243. def __delitem__(self, key: int) -> None:
  244. self.key = key + 2
  245. def test_native_del_item_override() -> None:
  246. o = DelItemOverrideNative()
  247. o[1] = 4
  248. assert o.key == 1 and o.value == 4
  249. del o[6]
  250. assert o.key == 8
  251. a = o # type: Any
  252. a[10] = 12
  253. assert a.key == 10 and a.value == 12
  254. del a[16]
  255. assert a.key == 18
  256. [case testDundersNumber]
  257. from typing import Any
  258. class C:
  259. def __init__(self, x: int) -> None:
  260. self.x = x
  261. def __neg__(self) -> int:
  262. return self.x + 1
  263. def __invert__(self) -> int:
  264. return self.x + 2
  265. def __int__(self) -> int:
  266. return self.x + 3
  267. def __float__(self) -> float:
  268. return float(self.x + 4)
  269. def __pos__(self) -> int:
  270. return self.x + 5
  271. def __abs__(self) -> int:
  272. return abs(self.x) + 6
  273. def test_unary_dunders_generic() -> None:
  274. a: Any = C(10)
  275. assert -a == 11
  276. assert ~a == 12
  277. assert int(a) == 13
  278. assert float(a) == 14.0
  279. assert +a == 15
  280. assert abs(a) == 16
  281. def test_unary_dunders_native() -> None:
  282. c = C(10)
  283. assert -c == 11
  284. assert ~c == 12
  285. assert int(c) == 13
  286. assert float(c) == 14.0
  287. assert +c == 15
  288. assert abs(c) == 16
  289. [case testDundersBinarySimple]
  290. from typing import Any
  291. class C:
  292. def __init__(self) -> None:
  293. self.x = 5
  294. def __add__(self, y: int) -> int:
  295. return self.x + y
  296. def __sub__(self, y: int) -> int:
  297. return self.x - y
  298. def __mul__(self, y: int) -> int:
  299. return self.x * y
  300. def __mod__(self, y: int) -> int:
  301. return self.x % y
  302. def __lshift__(self, y: int) -> int:
  303. return self.x << y
  304. def __rshift__(self, y: int) -> int:
  305. return self.x >> y
  306. def __and__(self, y: int) -> int:
  307. return self.x & y
  308. def __or__(self, y: int) -> int:
  309. return self.x | y
  310. def __xor__(self, y: int) -> int:
  311. return self.x ^ y
  312. def __matmul__(self, y: int) -> int:
  313. return self.x + y + 10
  314. def __truediv__(self, y: int) -> int:
  315. return self.x + y + 20
  316. def __floordiv__(self, y: int) -> int:
  317. return self.x + y + 30
  318. def __divmod__(self, y: int) -> int:
  319. return self.x + y + 40
  320. def __pow__(self, y: int) -> int:
  321. return self.x + y + 50
  322. def test_generic() -> None:
  323. a: Any = C()
  324. assert a + 3 == 8
  325. assert a - 3 == 2
  326. assert a * 5 == 25
  327. assert a % 2 == 1
  328. assert a << 4 == 80
  329. assert a >> 0 == 5
  330. assert a >> 1 == 2
  331. assert a & 1 == 1
  332. assert a | 3 == 7
  333. assert a ^ 3 == 6
  334. assert a @ 3 == 18
  335. assert a / 2 == 27
  336. assert a // 2 == 37
  337. assert divmod(a, 2) == 47
  338. assert a ** 2 == 57
  339. def test_native() -> None:
  340. c = C()
  341. assert c + 3 == 8
  342. assert c - 3 == 2
  343. assert divmod(c, 3) == 48
  344. assert c ** 3 == 58
  345. def test_error() -> None:
  346. a: Any = C()
  347. try:
  348. a + 'x'
  349. except TypeError as e:
  350. assert str(e) == "unsupported operand type(s) for +: 'C' and 'str'"
  351. else:
  352. assert False
  353. try:
  354. a - 'x'
  355. except TypeError as e:
  356. assert str(e) == "unsupported operand type(s) for -: 'C' and 'str'"
  357. else:
  358. assert False
  359. try:
  360. a ** 'x'
  361. except TypeError as e:
  362. assert str(e) == "unsupported operand type(s) for **: 'C' and 'str'"
  363. else:
  364. assert False
  365. [case testDundersBinaryReverse]
  366. from typing import Any
  367. class C:
  368. def __init__(self) -> None:
  369. self.x = 5
  370. def __add__(self, y: int) -> int:
  371. return self.x + y
  372. def __radd__(self, y: int) -> int:
  373. return self.x + y + 1
  374. def __sub__(self, y: int) -> int:
  375. return self.x - y
  376. def __rsub__(self, y: int) -> int:
  377. return self.x - y - 1
  378. def __pow__(self, y: int) -> int:
  379. return self.x**y
  380. def __rpow__(self, y: int) -> int:
  381. return self.x**y + 1
  382. def test_generic() -> None:
  383. a: Any = C()
  384. assert a + 3 == 8
  385. assert 4 + a == 10
  386. assert a - 3 == 2
  387. assert 4 - a == 0
  388. assert a**3 == 125
  389. assert 4**a == 626
  390. def test_native() -> None:
  391. c = C()
  392. assert c + 3 == 8
  393. assert 4 + c == 10
  394. assert c - 3 == 2
  395. assert 4 - c == 0
  396. assert c**3 == 125
  397. assert 4**c == 626
  398. def test_errors() -> None:
  399. a: Any = C()
  400. try:
  401. a + 'x'
  402. except TypeError as e:
  403. assert str(e) == "unsupported operand type(s) for +: 'C' and 'str'"
  404. else:
  405. assert False
  406. try:
  407. a - 'x'
  408. except TypeError as e:
  409. assert str(e) == "unsupported operand type(s) for -: 'C' and 'str'"
  410. else:
  411. assert False
  412. try:
  413. 'x' + a
  414. except TypeError as e:
  415. assert str(e) in ('can only concatenate str (not "C") to str',
  416. 'must be str, not C')
  417. else:
  418. assert False
  419. try:
  420. 'x' ** a
  421. except TypeError as e:
  422. assert str(e) == "unsupported operand type(s) for ** or pow(): 'str' and 'C'"
  423. else:
  424. assert False
  425. class F:
  426. def __add__(self, x: int) -> int:
  427. return 5
  428. def __pow__(self, x: int) -> int:
  429. return -5
  430. class G:
  431. def __add__(self, x: int) -> int:
  432. return 33
  433. def __pow__(self, x: int) -> int:
  434. return -33
  435. def __radd__(self, x: F) -> int:
  436. return 6
  437. def __rpow__(self, x: F) -> int:
  438. return -6
  439. def test_type_mismatch_fall_back_to_reverse() -> None:
  440. assert F() + G() == 6
  441. assert F()**G() == -6
  442. [case testDundersBinaryNotImplemented]
  443. from typing import Any, Union
  444. from testutil import assertRaises
  445. class C:
  446. def __init__(self, v: int) -> None:
  447. self.v = v
  448. def __add__(self, y: int) -> Union[int, Any]:
  449. if y == 1:
  450. return self.v
  451. return NotImplemented
  452. def test_any_add() -> None:
  453. a: Any = C(4)
  454. assert a + 1 == 4
  455. try:
  456. a + 2
  457. except TypeError:
  458. pass
  459. else:
  460. assert False
  461. class D:
  462. def __init__(self, x: int) -> None:
  463. self.x = x
  464. def __add__(self, e: E) -> Union[int, Any]:
  465. if e.x == 1:
  466. return 2
  467. return NotImplemented
  468. class E:
  469. def __init__(self, x: int) -> None:
  470. self.x = x
  471. def __radd__(self, d: D) -> Union[int, Any]:
  472. if d.x == 3:
  473. return 4
  474. return NotImplemented
  475. def test_any_radd() -> None:
  476. d1: Any = D(1)
  477. d3: Any = D(3)
  478. e1: Any = E(1)
  479. e3: Any = E(3)
  480. assert d1 + e1 == 2
  481. assert d3 + e1 == 2
  482. assert d3 + e3 == 4
  483. class F:
  484. def __init__(self, v):
  485. self.v = v
  486. def __add__(self, x):
  487. if isinstance(x, int):
  488. return self.v + x
  489. return NotImplemented
  490. class G:
  491. def __radd__(self, x):
  492. if isinstance(x, F):
  493. return x.v + 1
  494. if isinstance(x, str):
  495. return 'a'
  496. return NotImplemented
  497. def test_unannotated_add() -> None:
  498. o = F(4)
  499. assert o + 5 == 9
  500. with assertRaises(TypeError, "unsupported operand type(s) for +: 'F' and 'str'"):
  501. o + 'x'
  502. def test_unannotated_add_and_radd_1() -> None:
  503. o = F(4)
  504. assert o + G() == 5
  505. def test_unannotated_radd() -> None:
  506. assert 'x' + G() == 'a'
  507. with assertRaises(TypeError, "unsupported operand type(s) for +: 'int' and 'G'"):
  508. 1 + G()
  509. class H:
  510. def __add__(self, x):
  511. if isinstance(x, int):
  512. return x + 1
  513. return NotImplemented
  514. def __radd__(self, x):
  515. if isinstance(x, str):
  516. return 22
  517. return NotImplemented
  518. def test_unannotated_add_and_radd_2() -> None:
  519. h = H()
  520. assert h + 5 == 6
  521. assert 'x' + h == 22
  522. with assertRaises(TypeError, "unsupported operand type(s) for +: 'int' and 'H'"):
  523. 1 + h
  524. # TODO: Inheritance
  525. [case testDifferentReverseDunders]
  526. class C:
  527. # __radd__ and __rsub__ are tested elsewhere
  528. def __rmul__(self, x):
  529. return 1
  530. def __rtruediv__(self, x):
  531. return 2
  532. def __rmod__(self, x):
  533. return 3
  534. def __rfloordiv__(self, x):
  535. return 4
  536. def __rlshift__(self, x):
  537. return 5
  538. def __rrshift__(self, x):
  539. return 6
  540. def __rand__(self, x):
  541. return 7
  542. def __ror__(self, x):
  543. return 8
  544. def __rxor__(self, x):
  545. return 9
  546. def __rmatmul__(self, x):
  547. return 10
  548. def test_reverse_dunders() -> None:
  549. x = 0
  550. c = C()
  551. assert x * c == 1
  552. assert x / c == 2
  553. assert x % c == 3
  554. assert x // c == 4
  555. assert x << c == 5
  556. assert x >> c == 6
  557. assert x & c == 7
  558. assert x | c == 8
  559. assert x ^ c == 9
  560. assert x @ c == 10
  561. [case testDundersInplace]
  562. from typing import Any
  563. from testutil import assertRaises
  564. class C:
  565. def __init__(self) -> None:
  566. self.x = 5
  567. def __iadd__(self, y: int) -> C:
  568. self.x += y
  569. return self
  570. def __isub__(self, y: int) -> C:
  571. self.x -= y
  572. return self
  573. def __imul__(self, y: int) -> C:
  574. self.x *= y
  575. return self
  576. def __imod__(self, y: int) -> C:
  577. self.x %= y
  578. return self
  579. def __itruediv__(self, y: int) -> C:
  580. self.x += y + 10
  581. return self
  582. def __ifloordiv__(self, y: int) -> C:
  583. self.x += y + 20
  584. return self
  585. def __ilshift__(self, y: int) -> C:
  586. self.x <<= y
  587. return self
  588. def __irshift__(self, y: int) -> C:
  589. self.x >>= y
  590. return self
  591. def __iand__(self, y: int) -> C:
  592. self.x &= y
  593. return self
  594. def __ior__(self, y: int) -> C:
  595. self.x |= y
  596. return self
  597. def __ixor__(self, y: int) -> C:
  598. self.x ^= y
  599. return self
  600. def __imatmul__(self, y: int) -> C:
  601. self.x += y + 5
  602. return self
  603. def __ipow__(self, y: int, __mod_throwaway: None = None) -> C:
  604. self.x **= y
  605. return self
  606. def test_generic_1() -> None:
  607. c: Any = C()
  608. c += 3
  609. assert c.x == 8
  610. c -= 5
  611. assert c.x == 3
  612. c *= 3
  613. assert c.x == 9
  614. c %= 4
  615. assert c.x == 1
  616. c /= 5
  617. assert c.x == 16
  618. c //= 4
  619. assert c.x == 40
  620. c **= 2
  621. assert c.x == 1600
  622. def test_generic_2() -> None:
  623. c: Any = C()
  624. c <<= 4
  625. assert c.x == 80
  626. c >>= 3
  627. assert c.x == 10
  628. c &= 3
  629. assert c.x == 2
  630. c |= 6
  631. assert c.x == 6
  632. c ^= 12
  633. assert c.x == 10
  634. c @= 3
  635. assert c.x == 18
  636. def test_native() -> None:
  637. c = C()
  638. c += 3
  639. assert c.x == 8
  640. c -= 5
  641. assert c.x == 3
  642. c *= 3
  643. assert c.x == 9
  644. c **= 2
  645. assert c.x == 81
  646. def test_error() -> None:
  647. c: Any = C()
  648. with assertRaises(TypeError, "int object expected; got str"):
  649. c += 'x'
  650. class BadInplaceAdd:
  651. def __init__(self):
  652. self.x = 0
  653. def __iadd__(self, x):
  654. self.x += x
  655. def test_in_place_operator_returns_none() -> None:
  656. o = BadInplaceAdd()
  657. with assertRaises(TypeError, "native.BadInplaceAdd object expected; got None"):
  658. o += 5
  659. [case testDunderMinMax]
  660. class SomeItem:
  661. def __init__(self, val: int) -> None:
  662. self.val = val
  663. def __lt__(self, x: 'SomeItem') -> bool:
  664. return self.val < x.val
  665. def __gt__(self, x: 'SomeItem') -> bool:
  666. return self.val > x.val
  667. class AnotherItem:
  668. def __init__(self, val: str) -> None:
  669. self.val = val
  670. def __lt__(self, x: 'AnotherItem') -> bool:
  671. return True
  672. def __gt__(self, x: 'AnotherItem') -> bool:
  673. return True
  674. def test_dunder_min() -> None:
  675. x = SomeItem(5)
  676. y = SomeItem(10)
  677. z = SomeItem(15)
  678. assert min(x, y).val == 5
  679. assert min(y, z).val == 10
  680. assert max(x, y).val == 10
  681. assert max(y, z).val == 15
  682. x2 = AnotherItem('xxx')
  683. y2 = AnotherItem('yyy')
  684. z2 = AnotherItem('zzz')
  685. assert min(x2, y2).val == 'yyy'
  686. assert min(y2, x2).val == 'xxx'
  687. assert max(x2, y2).val == 'yyy'
  688. assert max(y2, x2).val == 'xxx'
  689. assert min(y2, z2).val == 'zzz'
  690. assert max(x2, z2).val == 'zzz'
  691. [case testDundersPowerSpecial]
  692. import sys
  693. from typing import Any, Optional
  694. from testutil import assertRaises
  695. class Forward:
  696. def __pow__(self, exp: int, mod: Optional[int] = None) -> int:
  697. if mod is None:
  698. return 2**exp
  699. else:
  700. return 2**exp % mod
  701. class ForwardModRequired:
  702. def __pow__(self, exp: int, mod: int) -> int:
  703. return 2**exp % mod
  704. class ForwardNotImplemented:
  705. def __pow__(self, exp: int, mod: Optional[object] = None) -> Any:
  706. return NotImplemented
  707. class Reverse:
  708. def __rpow__(self, exp: int) -> int:
  709. return 2**exp + 1
  710. class Both:
  711. def __pow__(self, exp: int, mod: Optional[int] = None) -> int:
  712. if mod is None:
  713. return 2**exp
  714. else:
  715. return 2**exp % mod
  716. def __rpow__(self, exp: int) -> int:
  717. return 2**exp + 1
  718. class Child(ForwardNotImplemented):
  719. def __rpow__(self, exp: object) -> int:
  720. return 50
  721. class Inplace:
  722. value = 2
  723. def __ipow__(self, exp: int, mod: Optional[int] = None) -> "Inplace":
  724. self.value **= exp - (mod or 0)
  725. return self
  726. def test_native() -> None:
  727. f = Forward()
  728. assert f**3 == 8
  729. assert pow(f, 3) == 8
  730. assert pow(f, 3, 3) == 2
  731. assert pow(ForwardModRequired(), 3, 3) == 2
  732. b = Both()
  733. assert b**3 == 8
  734. assert 3**b == 9
  735. assert pow(b, 3) == 8
  736. assert pow(b, 3, 3) == 2
  737. i = Inplace()
  738. i **= 2
  739. assert i.value == 4
  740. def test_errors() -> None:
  741. if sys.version_info[0] >= 3 and sys.version_info[1] >= 10:
  742. op = "** or pow()"
  743. else:
  744. op = "pow()"
  745. f = Forward()
  746. with assertRaises(TypeError, f"unsupported operand type(s) for {op}: 'Forward', 'int', 'str'"):
  747. pow(f, 3, "x") # type: ignore
  748. with assertRaises(TypeError, "unsupported operand type(s) for **: 'Forward' and 'str'"):
  749. f**"x" # type: ignore
  750. r = Reverse()
  751. with assertRaises(TypeError, "unsupported operand type(s) for ** or pow(): 'str' and 'Reverse'"):
  752. "x"**r # type: ignore
  753. with assertRaises(TypeError, f"unsupported operand type(s) for {op}: 'int', 'Reverse', 'int'"):
  754. # Ternary pow() does not fallback to __rpow__ if LHS's __pow__ returns NotImplemented.
  755. pow(3, r, 3) # type: ignore
  756. with assertRaises(TypeError, f"unsupported operand type(s) for {op}: 'ForwardNotImplemented', 'Child', 'int'"):
  757. # Ternary pow() does not try RHS's __rpow__ first when it's a subclass and redefines
  758. # __rpow__ unlike other ops.
  759. pow(ForwardNotImplemented(), Child(), 3) # type: ignore
  760. with assertRaises(TypeError, "unsupported operand type(s) for ** or pow(): 'ForwardModRequired' and 'int'"):
  761. ForwardModRequired()**3 # type: ignore