alwaysdefined.test 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732
  1. -- Test cases for always defined attributes.
  2. --
  3. -- If class C has attributes x and y that are always defined, the output will
  4. -- have a line like this:
  5. --
  6. -- C: [x, y]
  7. [case testAlwaysDefinedSimple]
  8. class C:
  9. def __init__(self, x: int) -> None:
  10. self.x = x
  11. [out]
  12. C: [x]
  13. [case testAlwaysDefinedFail]
  14. class MethodCall:
  15. def __init__(self, x: int) -> None:
  16. self.f()
  17. self.x = x
  18. def f(self) -> None:
  19. pass
  20. class FuncCall:
  21. def __init__(self, x: int) -> None:
  22. f(x)
  23. self.x = x
  24. f(self)
  25. self.y = x
  26. class GetAttr:
  27. x: int
  28. def __init__(self, x: int) -> None:
  29. a = self.x
  30. self.x = x
  31. class _Base:
  32. def __init__(self) -> None:
  33. f(self)
  34. class CallSuper(_Base):
  35. def __init__(self, x: int) -> None:
  36. super().__init__()
  37. self.x = x
  38. class Lambda:
  39. def __init__(self, x: int) -> None:
  40. f = lambda x: x + 1
  41. self.x = x
  42. g = lambda x: self
  43. self.y = x
  44. class If:
  45. def __init__(self, x: int) -> None:
  46. self.a = 1
  47. if x:
  48. self.x = x
  49. else:
  50. self.y = 1
  51. class Deletable:
  52. __deletable__ = ('x', 'y')
  53. def __init__(self) -> None:
  54. self.x = 0
  55. self.y = 1
  56. self.z = 2
  57. class PrimitiveWithSelf:
  58. def __init__(self, s: str) -> None:
  59. self.x = getattr(self, s)
  60. def f(a) -> None: pass
  61. [out]
  62. MethodCall: []
  63. FuncCall: [x]
  64. GetAttr: []
  65. CallSuper: []
  66. Lambda: []
  67. If: [a]
  68. Deletable: [z]
  69. PrimitiveWithSelf: []
  70. [case testAlwaysDefinedConditional]
  71. class IfAlways:
  72. def __init__(self, x: int, y: int) -> None:
  73. if x:
  74. self.x = x
  75. self.y = y
  76. elif y:
  77. self.x = y
  78. self.y = x
  79. else:
  80. self.x = 0
  81. self.y = 0
  82. self.z = 0
  83. class IfSometimes1:
  84. def __init__(self, x: int, y: int) -> None:
  85. if x:
  86. self.x = x
  87. self.y = y
  88. elif y:
  89. self.z = y
  90. self.y = x
  91. else:
  92. self.y = 0
  93. self.a = 0
  94. class IfSometimes2:
  95. def __init__(self, x: int, y: int) -> None:
  96. if x:
  97. self.x = x
  98. self.y = y
  99. class IfStopAnalysis1:
  100. def __init__(self, x: int, y: int) -> None:
  101. if x:
  102. self.x = x
  103. f(self)
  104. else:
  105. self.x = x
  106. self.y = y
  107. class IfStopAnalysis2:
  108. def __init__(self, x: int, y: int) -> None:
  109. if x:
  110. self.x = x
  111. else:
  112. self.x = x
  113. f(self)
  114. self.y = y
  115. class IfStopAnalysis3:
  116. def __init__(self, x: int, y: int) -> None:
  117. if x:
  118. self.x = x
  119. else:
  120. f(self)
  121. self.x = x
  122. self.y = y
  123. class IfConditionalAndNonConditional1:
  124. def __init__(self, x: int) -> None:
  125. self.x = 0
  126. if x:
  127. self.x = x
  128. class IfConditionalAndNonConditional2:
  129. def __init__(self, x: int) -> None:
  130. # x is not considered always defined, since the second assignment may
  131. # either initialize or update.
  132. if x:
  133. self.x = x
  134. self.x = 0
  135. def f(a) -> None: pass
  136. [out]
  137. IfAlways: [x, y, z]
  138. IfSometimes1: [y]
  139. IfSometimes2: [y]
  140. IfStopAnalysis1: [x]
  141. IfStopAnalysis2: [x]
  142. IfStopAnalysis3: []
  143. IfConditionalAndNonConditional1: [x]
  144. IfConditionalAndNonConditional2: []
  145. [case testAlwaysDefinedExpressions]
  146. from typing import Dict, List, Set, Optional, cast
  147. from typing_extensions import Final
  148. import other
  149. class C: pass
  150. class Collections:
  151. def __init__(self, x: int) -> None:
  152. self.l = [x]
  153. self.d: Dict[str, str] = {}
  154. self.s: Set[int] = set()
  155. self.d2 = {'x': x}
  156. self.s2 = {x}
  157. self.l2 = [f(), None] * x
  158. self.t = tuple(self.l2)
  159. class Comparisons:
  160. def __init__(self, y: int, c: C, s: str, o: Optional[str]) -> None:
  161. self.n1 = y < 5
  162. self.n2 = y == 5
  163. self.c1 = y is c
  164. self.c2 = y is not c
  165. self.o1 = o is None
  166. self.o2 = o is not None
  167. self.s = s < 'x'
  168. class BinaryOps:
  169. def __init__(self, x: int, s: str) -> None:
  170. self.a = x + 2
  171. self.b = x & 2
  172. self.c = x * 2
  173. self.d = -x
  174. self.e = 'x' + s
  175. self.f = x << x
  176. g = 2
  177. class LocalsAndGlobals:
  178. def __init__(self, x: int) -> None:
  179. t = x + 1
  180. self.a = t - t
  181. self.g = g
  182. class Booleans:
  183. def __init__(self, x: int, b: bool) -> None:
  184. self.a = True
  185. self.b = False
  186. self.c = not b
  187. self.d = b or b
  188. self.e = b and b
  189. F: Final = 3
  190. class ModuleFinal:
  191. def __init__(self) -> None:
  192. self.a = F
  193. self.b = other.Y
  194. class ClassFinal:
  195. F: Final = 3
  196. def __init__(self) -> None:
  197. self.a = ClassFinal.F
  198. class Literals:
  199. def __init__(self) -> None:
  200. self.a = 'x'
  201. self.b = b'x'
  202. self.c = 2.2
  203. class ListComprehension:
  204. def __init__(self, x: List[int]) -> None:
  205. self.a = [i + 1 for i in x]
  206. class Helper:
  207. def __init__(self, arg) -> None:
  208. self.x = 0
  209. def foo(self, arg) -> int:
  210. return 1
  211. class AttrAccess:
  212. def __init__(self, o: Helper) -> None:
  213. self.x = o.x
  214. o.x = o.x + 1
  215. self.y = o.foo(self.x)
  216. o.foo(self)
  217. self.z = 1
  218. class Construct:
  219. def __init__(self) -> None:
  220. self.x = Helper(1)
  221. self.y = Helper(self)
  222. class IsInstance:
  223. def __init__(self, x: object) -> None:
  224. if isinstance(x, str):
  225. self.x = 0
  226. elif isinstance(x, Helper):
  227. self.x = 1
  228. elif isinstance(x, (list, tuple)):
  229. self.x = 2
  230. else:
  231. self.x = 3
  232. class Cast:
  233. def __init__(self, x: object) -> None:
  234. self.x = cast(int, x)
  235. self.s = cast(str, x)
  236. self.c = cast(Cast, x)
  237. class PropertyAccessGetter:
  238. def __init__(self, other: PropertyAccessGetter) -> None:
  239. self.x = other.p
  240. self.y = 1
  241. self.z = self.p
  242. @property
  243. def p(self) -> int:
  244. return 0
  245. class PropertyAccessSetter:
  246. def __init__(self, other: PropertyAccessSetter) -> None:
  247. other.p = 1
  248. self.y = 1
  249. self.z = self.p
  250. @property
  251. def p(self) -> int:
  252. return 0
  253. @p.setter
  254. def p(self, x: int) -> None:
  255. pass
  256. def f() -> int:
  257. return 0
  258. [file other.py]
  259. # Not compiled
  260. from typing_extensions import Final
  261. Y: Final = 3
  262. [out]
  263. C: []
  264. Collections: [d, d2, l, l2, s, s2, t]
  265. Comparisons: [c1, c2, n1, n2, o1, o2, s]
  266. BinaryOps: [a, b, c, d, e, f]
  267. LocalsAndGlobals: [a, g]
  268. Booleans: [a, b, c, d, e]
  269. ModuleFinal: [a, b]
  270. ClassFinal: [F, a]
  271. Literals: [a, b, c]
  272. ListComprehension: [a]
  273. Helper: [x]
  274. AttrAccess: [x, y]
  275. Construct: [x]
  276. IsInstance: [x]
  277. Cast: [c, s, x]
  278. PropertyAccessGetter: [x, y]
  279. PropertyAccessSetter: [y]
  280. [case testAlwaysDefinedExpressions2]
  281. from typing import List, Tuple
  282. class C:
  283. def __init__(self) -> None:
  284. self.x = 0
  285. class AttributeRef:
  286. def __init__(self, c: C) -> None:
  287. self.aa = c.x
  288. self.bb = self.aa
  289. if c is not None:
  290. self.z = 0
  291. self.cc = 0
  292. self.dd = self.z
  293. class ListOps:
  294. def __init__(self, x: List[int], n: int) -> None:
  295. self.a = len(x)
  296. self.b = x[n]
  297. self.c = [y + 1 for y in x]
  298. class TupleOps:
  299. def __init__(self, t: Tuple[int, str]) -> None:
  300. x, y = t
  301. self.x = x
  302. self.y = t[0]
  303. s = x, y
  304. self.z = s
  305. class IfExpr:
  306. def __init__(self, x: int) -> None:
  307. self.a = 1 if x < 5 else 2
  308. class Base:
  309. def __init__(self, x: int) -> None:
  310. self.x = x
  311. class Derived1(Base):
  312. def __init__(self, y: int) -> None:
  313. self.aa = y
  314. super().__init__(y)
  315. self.bb = y
  316. class Derived2(Base):
  317. pass
  318. class Conditionals:
  319. def __init__(self, b: bool, n: int) -> None:
  320. if not (n == 5 or n >= n + 1):
  321. self.a = b
  322. else:
  323. self.a = not b
  324. if b:
  325. self.b = 2
  326. else:
  327. self.b = 4
  328. [out]
  329. C: [x]
  330. AttributeRef: [aa, bb, cc, dd]
  331. ListOps: [a, b, c]
  332. TupleOps: [x, y, z]
  333. IfExpr: [a]
  334. Base: [x]
  335. Derived1: [aa, bb, x]
  336. Derived2: [x]
  337. Conditionals: [a, b]
  338. [case testAlwaysDefinedStatements]
  339. from typing import Any, List, Optional, Iterable
  340. class Return:
  341. def __init__(self, x: int) -> None:
  342. self.x = x
  343. if x > 5:
  344. self.y = 1
  345. return
  346. self.y = 2
  347. self.z = x
  348. class While:
  349. def __init__(self, x: int) -> None:
  350. n = 2
  351. while x > 0:
  352. n *=2
  353. x -= 1
  354. self.a = n
  355. while x < 5:
  356. self.b = 1
  357. self.b += 1
  358. class Try:
  359. def __init__(self, x: List[int]) -> None:
  360. self.a = 0
  361. try:
  362. self.b = x[0]
  363. except:
  364. self.c = x
  365. self.d = 0
  366. try:
  367. self.e = x[0]
  368. except:
  369. self.e = 1
  370. class TryFinally:
  371. def __init__(self, x: List[int]) -> None:
  372. self.a = 0
  373. try:
  374. self.b = x[0]
  375. finally:
  376. self.c = x
  377. self.d = 0
  378. try:
  379. self.e = x[0]
  380. finally:
  381. self.e = 1
  382. class Assert:
  383. def __init__(self, x: Optional[str], y: int) -> None:
  384. assert x is not None
  385. assert y < 5
  386. self.a = x
  387. class For:
  388. def __init__(self, it: Iterable[int]) -> None:
  389. self.x = 0
  390. for x in it:
  391. self.x += x
  392. for x in it:
  393. self.y = x
  394. class Assignment1:
  395. def __init__(self, other: Assignment1) -> None:
  396. self.x = 0
  397. self = other # Give up after assignment to self
  398. self.y = 1
  399. class Assignment2:
  400. def __init__(self) -> None:
  401. self.x = 0
  402. other = self # Give up after self is aliased
  403. self.y = other.x
  404. class With:
  405. def __init__(self, x: Any) -> None:
  406. self.a = 0
  407. with x:
  408. self.b = 1
  409. self.c = 2
  410. def f() -> None:
  411. pass
  412. [out]
  413. Return: [x, y]
  414. While: [a]
  415. -- We could infer 'e' as always defined, but this is tricky, since always defined attribute
  416. -- analysis must be performed earlier than exception handling transform. This would be
  417. -- easy to infer *after* exception handling transform.
  418. Try: [a, d]
  419. -- Again, 'e' could be always defined, but it would be a bit tricky to do it.
  420. TryFinally: [a, c, d]
  421. Assert: [a]
  422. For: [x]
  423. Assignment1: [x]
  424. Assignment2: [x]
  425. -- TODO: Why is not 'b' included?
  426. With: [a, c]
  427. [case testAlwaysDefinedAttributeDefaults]
  428. class Basic:
  429. x = 0
  430. class ClassBodyAndInit:
  431. x = 0
  432. s = 'x'
  433. def __init__(self, n: int) -> None:
  434. self.n = 0
  435. class AttrWithDefaultAndInit:
  436. x = 0
  437. def __init__(self, x: int) -> None:
  438. self.x = x
  439. class Base:
  440. x = 0
  441. y = 1
  442. class Derived(Base):
  443. y = 2
  444. z = 3
  445. [out]
  446. Basic: [x]
  447. ClassBodyAndInit: [n, s, x]
  448. AttrWithDefaultAndInit: [x]
  449. Base: [x, y]
  450. Derived: [x, y, z]
  451. [case testAlwaysDefinedWithInheritance]
  452. class Base:
  453. def __init__(self, x: int) -> None:
  454. self.x = x
  455. class Deriv1(Base):
  456. def __init__(self, x: int, y: str) -> None:
  457. super().__init__(x)
  458. self.y = y
  459. class Deriv2(Base):
  460. def __init__(self, x: int, y: str) -> None:
  461. self.y = y
  462. super().__init__(x)
  463. class Deriv22(Deriv2):
  464. def __init__(self, x: int, y: str, z: bool) -> None:
  465. super().__init__(x, y)
  466. self.z = False
  467. class Deriv3(Base):
  468. def __init__(self) -> None:
  469. super().__init__(1)
  470. class Deriv4(Base):
  471. def __init__(self) -> None:
  472. self.y = 1
  473. self.x = 2
  474. def f(a): pass
  475. class BaseUnsafe:
  476. def __init__(self, x: int, y: int) -> None:
  477. self.x = x
  478. f(self) # Unknown function
  479. self.y = y
  480. class DerivUnsafe(BaseUnsafe):
  481. def __init__(self, z: int, zz: int) -> None:
  482. self.z = z
  483. super().__init__(1, 2) # Calls unknown function
  484. self.zz = zz
  485. class BaseWithDefault:
  486. x = 1
  487. def __init__(self) -> None:
  488. self.y = 1
  489. class DerivedWithDefault(BaseWithDefault):
  490. def __init__(self) -> None:
  491. super().__init__()
  492. self.z = 1
  493. class AlwaysDefinedInBase:
  494. def __init__(self) -> None:
  495. self.x = 1
  496. self.y = 1
  497. class UndefinedInDerived(AlwaysDefinedInBase):
  498. def __init__(self, x: bool) -> None:
  499. self.x = 1
  500. if x:
  501. self.y = 2
  502. class UndefinedInDerived2(UndefinedInDerived):
  503. def __init__(self, x: bool):
  504. if x:
  505. self.y = 2
  506. [out]
  507. Base: [x]
  508. Deriv1: [x, y]
  509. Deriv2: [x, y]
  510. Deriv22: [x, y, z]
  511. Deriv3: [x]
  512. Deriv4: [x, y]
  513. BaseUnsafe: [x]
  514. DerivUnsafe: [x, z]
  515. BaseWithDefault: [x, y]
  516. DerivedWithDefault: [x, y, z]
  517. AlwaysDefinedInBase: []
  518. UndefinedInDerived: []
  519. UndefinedInDerived2: []
  520. [case testAlwaysDefinedWithInheritance2]
  521. from mypy_extensions import trait, mypyc_attr
  522. from interpreted import PythonBase
  523. class BasePartiallyDefined:
  524. def __init__(self, x: int) -> None:
  525. self.a = 0
  526. if x:
  527. self.x = x
  528. class Derived1(BasePartiallyDefined):
  529. def __init__(self, x: int) -> None:
  530. super().__init__(x)
  531. self.y = x
  532. class BaseUndefined:
  533. x: int
  534. class DerivedAlwaysDefined(BaseUndefined):
  535. def __init__(self) -> None:
  536. super().__init__()
  537. self.z = 0
  538. self.x = 2
  539. @trait
  540. class MyTrait:
  541. def f(self) -> None: pass
  542. class SimpleTraitImpl(MyTrait):
  543. def __init__(self) -> None:
  544. super().__init__()
  545. self.x = 0
  546. @trait
  547. class TraitWithAttr:
  548. x: int
  549. y: str
  550. class TraitWithAttrImpl(TraitWithAttr):
  551. def __init__(self) -> None:
  552. self.y = 'x'
  553. @trait
  554. class TraitWithAttr2:
  555. z: int
  556. class TraitWithAttrImpl2(TraitWithAttr, TraitWithAttr2):
  557. def __init__(self) -> None:
  558. self.y = 'x'
  559. self.z = 2
  560. @mypyc_attr(allow_interpreted_subclasses=True)
  561. class BaseWithGeneralSubclassing:
  562. x = 0
  563. y: int
  564. def __init__(self, s: str) -> None:
  565. self.s = s
  566. class Derived2(BaseWithGeneralSubclassing):
  567. def __init__(self) -> None:
  568. super().__init__('x')
  569. self.z = 0
  570. class SubclassPythonclass(PythonBase):
  571. def __init__(self) -> None:
  572. self.y = 1
  573. class BaseWithSometimesDefined:
  574. def __init__(self, b: bool) -> None:
  575. if b:
  576. self.x = 0
  577. class Derived3(BaseWithSometimesDefined):
  578. def __init__(self, b: bool) -> None:
  579. super().__init__(b)
  580. self.x = 1
  581. [file interpreted.py]
  582. class PythonBase:
  583. def __init__(self) -> None:
  584. self.x = 0
  585. [out]
  586. BasePartiallyDefined: [a]
  587. Derived1: [a, y]
  588. BaseUndefined: []
  589. DerivedAlwaysDefined: [x, z]
  590. MyTrait: []
  591. SimpleTraitImpl: [x]
  592. TraitWithAttr: []
  593. TraitWithAttrImpl: [y]
  594. TraitWithAttr2: []
  595. TraitWithAttrImpl2: [y, z]
  596. BaseWithGeneralSubclassing: []
  597. -- TODO: 's' could also be always defined
  598. Derived2: [x, z]
  599. -- Always defined attribute analysis is turned off when inheriting a non-native class.
  600. SubclassPythonclass: []
  601. BaseWithSometimesDefined: []
  602. -- TODO: 'x' could also be always defined, but it is a bit tricky to support
  603. Derived3: []
  604. [case testAlwaysDefinedWithNesting]
  605. class NestedFunc:
  606. def __init__(self) -> None:
  607. self.x = 0
  608. def f() -> None:
  609. self.y = 0
  610. f()
  611. self.z = 1
  612. [out]
  613. -- TODO: Support nested functions.
  614. NestedFunc: []
  615. f___init___NestedFunc_obj: []