test_with.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748
  1. """Unit tests for the with statement specified in PEP 343."""
  2. __author__ = "Mike Bland"
  3. __email__ = "mbland at acm dot org"
  4. import sys
  5. import unittest
  6. from collections import deque
  7. from contextlib import GeneratorContextManager, contextmanager
  8. from test.test_support import run_unittest
  9. class MockContextManager(GeneratorContextManager):
  10. def __init__(self, gen):
  11. GeneratorContextManager.__init__(self, gen)
  12. self.enter_called = False
  13. self.exit_called = False
  14. self.exit_args = None
  15. def __enter__(self):
  16. self.enter_called = True
  17. return GeneratorContextManager.__enter__(self)
  18. def __exit__(self, type, value, traceback):
  19. self.exit_called = True
  20. self.exit_args = (type, value, traceback)
  21. return GeneratorContextManager.__exit__(self, type,
  22. value, traceback)
  23. def mock_contextmanager(func):
  24. def helper(*args, **kwds):
  25. return MockContextManager(func(*args, **kwds))
  26. return helper
  27. class MockResource(object):
  28. def __init__(self):
  29. self.yielded = False
  30. self.stopped = False
  31. @mock_contextmanager
  32. def mock_contextmanager_generator():
  33. mock = MockResource()
  34. try:
  35. mock.yielded = True
  36. yield mock
  37. finally:
  38. mock.stopped = True
  39. class Nested(object):
  40. def __init__(self, *managers):
  41. self.managers = managers
  42. self.entered = None
  43. def __enter__(self):
  44. if self.entered is not None:
  45. raise RuntimeError("Context is not reentrant")
  46. self.entered = deque()
  47. vars = []
  48. try:
  49. for mgr in self.managers:
  50. vars.append(mgr.__enter__())
  51. self.entered.appendleft(mgr)
  52. except:
  53. if not self.__exit__(*sys.exc_info()):
  54. raise
  55. return vars
  56. def __exit__(self, *exc_info):
  57. # Behave like nested with statements
  58. # first in, last out
  59. # New exceptions override old ones
  60. ex = exc_info
  61. for mgr in self.entered:
  62. try:
  63. if mgr.__exit__(*ex):
  64. ex = (None, None, None)
  65. except:
  66. ex = sys.exc_info()
  67. self.entered = None
  68. if ex is not exc_info:
  69. raise ex[0], ex[1], ex[2]
  70. class MockNested(Nested):
  71. def __init__(self, *managers):
  72. Nested.__init__(self, *managers)
  73. self.enter_called = False
  74. self.exit_called = False
  75. self.exit_args = None
  76. def __enter__(self):
  77. self.enter_called = True
  78. return Nested.__enter__(self)
  79. def __exit__(self, *exc_info):
  80. self.exit_called = True
  81. self.exit_args = exc_info
  82. return Nested.__exit__(self, *exc_info)
  83. class FailureTestCase(unittest.TestCase):
  84. def testNameError(self):
  85. def fooNotDeclared():
  86. with foo: pass
  87. self.assertRaises(NameError, fooNotDeclared)
  88. def testEnterAttributeError(self):
  89. class LacksEnter(object):
  90. def __exit__(self, type, value, traceback):
  91. pass
  92. def fooLacksEnter():
  93. foo = LacksEnter()
  94. with foo: pass
  95. self.assertRaises(AttributeError, fooLacksEnter)
  96. def testExitAttributeError(self):
  97. class LacksExit(object):
  98. def __enter__(self):
  99. pass
  100. def fooLacksExit():
  101. foo = LacksExit()
  102. with foo: pass
  103. self.assertRaises(AttributeError, fooLacksExit)
  104. def assertRaisesSyntaxError(self, codestr):
  105. def shouldRaiseSyntaxError(s):
  106. compile(s, '', 'single')
  107. self.assertRaises(SyntaxError, shouldRaiseSyntaxError, codestr)
  108. def testAssignmentToNoneError(self):
  109. self.assertRaisesSyntaxError('with mock as None:\n pass')
  110. self.assertRaisesSyntaxError(
  111. 'with mock as (None):\n'
  112. ' pass')
  113. def testAssignmentToEmptyTupleError(self):
  114. self.assertRaisesSyntaxError(
  115. 'with mock as ():\n'
  116. ' pass')
  117. def testAssignmentToTupleOnlyContainingNoneError(self):
  118. self.assertRaisesSyntaxError('with mock as None,:\n pass')
  119. self.assertRaisesSyntaxError(
  120. 'with mock as (None,):\n'
  121. ' pass')
  122. def testAssignmentToTupleContainingNoneError(self):
  123. self.assertRaisesSyntaxError(
  124. 'with mock as (foo, None, bar):\n'
  125. ' pass')
  126. def testEnterThrows(self):
  127. class EnterThrows(object):
  128. def __enter__(self):
  129. raise RuntimeError("Enter threw")
  130. def __exit__(self, *args):
  131. pass
  132. def shouldThrow():
  133. ct = EnterThrows()
  134. self.foo = None
  135. with ct as self.foo:
  136. pass
  137. self.assertRaises(RuntimeError, shouldThrow)
  138. self.assertEqual(self.foo, None)
  139. def testExitThrows(self):
  140. class ExitThrows(object):
  141. def __enter__(self):
  142. return
  143. def __exit__(self, *args):
  144. raise RuntimeError(42)
  145. def shouldThrow():
  146. with ExitThrows():
  147. pass
  148. self.assertRaises(RuntimeError, shouldThrow)
  149. class ContextmanagerAssertionMixin(object):
  150. TEST_EXCEPTION = RuntimeError("test exception")
  151. def assertInWithManagerInvariants(self, mock_manager):
  152. self.assertTrue(mock_manager.enter_called)
  153. self.assertFalse(mock_manager.exit_called)
  154. self.assertEqual(mock_manager.exit_args, None)
  155. def assertAfterWithManagerInvariants(self, mock_manager, exit_args):
  156. self.assertTrue(mock_manager.enter_called)
  157. self.assertTrue(mock_manager.exit_called)
  158. self.assertEqual(mock_manager.exit_args, exit_args)
  159. def assertAfterWithManagerInvariantsNoError(self, mock_manager):
  160. self.assertAfterWithManagerInvariants(mock_manager,
  161. (None, None, None))
  162. def assertInWithGeneratorInvariants(self, mock_generator):
  163. self.assertTrue(mock_generator.yielded)
  164. self.assertFalse(mock_generator.stopped)
  165. def assertAfterWithGeneratorInvariantsNoError(self, mock_generator):
  166. self.assertTrue(mock_generator.yielded)
  167. self.assertTrue(mock_generator.stopped)
  168. def raiseTestException(self):
  169. raise self.TEST_EXCEPTION
  170. def assertAfterWithManagerInvariantsWithError(self, mock_manager,
  171. exc_type=None):
  172. self.assertTrue(mock_manager.enter_called)
  173. self.assertTrue(mock_manager.exit_called)
  174. if exc_type is None:
  175. self.assertEqual(mock_manager.exit_args[1], self.TEST_EXCEPTION)
  176. exc_type = type(self.TEST_EXCEPTION)
  177. self.assertEqual(mock_manager.exit_args[0], exc_type)
  178. # Test the __exit__ arguments. Issue #7853
  179. self.assertIsInstance(mock_manager.exit_args[1], exc_type)
  180. self.assertIsNot(mock_manager.exit_args[2], None)
  181. def assertAfterWithGeneratorInvariantsWithError(self, mock_generator):
  182. self.assertTrue(mock_generator.yielded)
  183. self.assertTrue(mock_generator.stopped)
  184. class NonexceptionalTestCase(unittest.TestCase, ContextmanagerAssertionMixin):
  185. def testInlineGeneratorSyntax(self):
  186. with mock_contextmanager_generator():
  187. pass
  188. def testUnboundGenerator(self):
  189. mock = mock_contextmanager_generator()
  190. with mock:
  191. pass
  192. self.assertAfterWithManagerInvariantsNoError(mock)
  193. def testInlineGeneratorBoundSyntax(self):
  194. with mock_contextmanager_generator() as foo:
  195. self.assertInWithGeneratorInvariants(foo)
  196. # FIXME: In the future, we'll try to keep the bound names from leaking
  197. self.assertAfterWithGeneratorInvariantsNoError(foo)
  198. def testInlineGeneratorBoundToExistingVariable(self):
  199. foo = None
  200. with mock_contextmanager_generator() as foo:
  201. self.assertInWithGeneratorInvariants(foo)
  202. self.assertAfterWithGeneratorInvariantsNoError(foo)
  203. def testInlineGeneratorBoundToDottedVariable(self):
  204. with mock_contextmanager_generator() as self.foo:
  205. self.assertInWithGeneratorInvariants(self.foo)
  206. self.assertAfterWithGeneratorInvariantsNoError(self.foo)
  207. def testBoundGenerator(self):
  208. mock = mock_contextmanager_generator()
  209. with mock as foo:
  210. self.assertInWithGeneratorInvariants(foo)
  211. self.assertInWithManagerInvariants(mock)
  212. self.assertAfterWithGeneratorInvariantsNoError(foo)
  213. self.assertAfterWithManagerInvariantsNoError(mock)
  214. def testNestedSingleStatements(self):
  215. mock_a = mock_contextmanager_generator()
  216. with mock_a as foo:
  217. mock_b = mock_contextmanager_generator()
  218. with mock_b as bar:
  219. self.assertInWithManagerInvariants(mock_a)
  220. self.assertInWithManagerInvariants(mock_b)
  221. self.assertInWithGeneratorInvariants(foo)
  222. self.assertInWithGeneratorInvariants(bar)
  223. self.assertAfterWithManagerInvariantsNoError(mock_b)
  224. self.assertAfterWithGeneratorInvariantsNoError(bar)
  225. self.assertInWithManagerInvariants(mock_a)
  226. self.assertInWithGeneratorInvariants(foo)
  227. self.assertAfterWithManagerInvariantsNoError(mock_a)
  228. self.assertAfterWithGeneratorInvariantsNoError(foo)
  229. class NestedNonexceptionalTestCase(unittest.TestCase,
  230. ContextmanagerAssertionMixin):
  231. def testSingleArgInlineGeneratorSyntax(self):
  232. with Nested(mock_contextmanager_generator()):
  233. pass
  234. def testSingleArgBoundToNonTuple(self):
  235. m = mock_contextmanager_generator()
  236. # This will bind all the arguments to nested() into a single list
  237. # assigned to foo.
  238. with Nested(m) as foo:
  239. self.assertInWithManagerInvariants(m)
  240. self.assertAfterWithManagerInvariantsNoError(m)
  241. def testSingleArgBoundToSingleElementParenthesizedList(self):
  242. m = mock_contextmanager_generator()
  243. # This will bind all the arguments to nested() into a single list
  244. # assigned to foo.
  245. with Nested(m) as (foo):
  246. self.assertInWithManagerInvariants(m)
  247. self.assertAfterWithManagerInvariantsNoError(m)
  248. def testSingleArgBoundToMultipleElementTupleError(self):
  249. def shouldThrowValueError():
  250. with Nested(mock_contextmanager_generator()) as (foo, bar):
  251. pass
  252. self.assertRaises(ValueError, shouldThrowValueError)
  253. def testSingleArgUnbound(self):
  254. mock_contextmanager = mock_contextmanager_generator()
  255. mock_nested = MockNested(mock_contextmanager)
  256. with mock_nested:
  257. self.assertInWithManagerInvariants(mock_contextmanager)
  258. self.assertInWithManagerInvariants(mock_nested)
  259. self.assertAfterWithManagerInvariantsNoError(mock_contextmanager)
  260. self.assertAfterWithManagerInvariantsNoError(mock_nested)
  261. def testMultipleArgUnbound(self):
  262. m = mock_contextmanager_generator()
  263. n = mock_contextmanager_generator()
  264. o = mock_contextmanager_generator()
  265. mock_nested = MockNested(m, n, o)
  266. with mock_nested:
  267. self.assertInWithManagerInvariants(m)
  268. self.assertInWithManagerInvariants(n)
  269. self.assertInWithManagerInvariants(o)
  270. self.assertInWithManagerInvariants(mock_nested)
  271. self.assertAfterWithManagerInvariantsNoError(m)
  272. self.assertAfterWithManagerInvariantsNoError(n)
  273. self.assertAfterWithManagerInvariantsNoError(o)
  274. self.assertAfterWithManagerInvariantsNoError(mock_nested)
  275. def testMultipleArgBound(self):
  276. mock_nested = MockNested(mock_contextmanager_generator(),
  277. mock_contextmanager_generator(), mock_contextmanager_generator())
  278. with mock_nested as (m, n, o):
  279. self.assertInWithGeneratorInvariants(m)
  280. self.assertInWithGeneratorInvariants(n)
  281. self.assertInWithGeneratorInvariants(o)
  282. self.assertInWithManagerInvariants(mock_nested)
  283. self.assertAfterWithGeneratorInvariantsNoError(m)
  284. self.assertAfterWithGeneratorInvariantsNoError(n)
  285. self.assertAfterWithGeneratorInvariantsNoError(o)
  286. self.assertAfterWithManagerInvariantsNoError(mock_nested)
  287. class ExceptionalTestCase(unittest.TestCase, ContextmanagerAssertionMixin):
  288. def testSingleResource(self):
  289. cm = mock_contextmanager_generator()
  290. def shouldThrow():
  291. with cm as self.resource:
  292. self.assertInWithManagerInvariants(cm)
  293. self.assertInWithGeneratorInvariants(self.resource)
  294. self.raiseTestException()
  295. self.assertRaises(RuntimeError, shouldThrow)
  296. self.assertAfterWithManagerInvariantsWithError(cm)
  297. self.assertAfterWithGeneratorInvariantsWithError(self.resource)
  298. def testExceptionNormalized(self):
  299. cm = mock_contextmanager_generator()
  300. def shouldThrow():
  301. with cm as self.resource:
  302. # Note this relies on the fact that 1 // 0 produces an exception
  303. # that is not normalized immediately.
  304. 1 // 0
  305. self.assertRaises(ZeroDivisionError, shouldThrow)
  306. self.assertAfterWithManagerInvariantsWithError(cm, ZeroDivisionError)
  307. def testNestedSingleStatements(self):
  308. mock_a = mock_contextmanager_generator()
  309. mock_b = mock_contextmanager_generator()
  310. def shouldThrow():
  311. with mock_a as self.foo:
  312. with mock_b as self.bar:
  313. self.assertInWithManagerInvariants(mock_a)
  314. self.assertInWithManagerInvariants(mock_b)
  315. self.assertInWithGeneratorInvariants(self.foo)
  316. self.assertInWithGeneratorInvariants(self.bar)
  317. self.raiseTestException()
  318. self.assertRaises(RuntimeError, shouldThrow)
  319. self.assertAfterWithManagerInvariantsWithError(mock_a)
  320. self.assertAfterWithManagerInvariantsWithError(mock_b)
  321. self.assertAfterWithGeneratorInvariantsWithError(self.foo)
  322. self.assertAfterWithGeneratorInvariantsWithError(self.bar)
  323. def testMultipleResourcesInSingleStatement(self):
  324. cm_a = mock_contextmanager_generator()
  325. cm_b = mock_contextmanager_generator()
  326. mock_nested = MockNested(cm_a, cm_b)
  327. def shouldThrow():
  328. with mock_nested as (self.resource_a, self.resource_b):
  329. self.assertInWithManagerInvariants(cm_a)
  330. self.assertInWithManagerInvariants(cm_b)
  331. self.assertInWithManagerInvariants(mock_nested)
  332. self.assertInWithGeneratorInvariants(self.resource_a)
  333. self.assertInWithGeneratorInvariants(self.resource_b)
  334. self.raiseTestException()
  335. self.assertRaises(RuntimeError, shouldThrow)
  336. self.assertAfterWithManagerInvariantsWithError(cm_a)
  337. self.assertAfterWithManagerInvariantsWithError(cm_b)
  338. self.assertAfterWithManagerInvariantsWithError(mock_nested)
  339. self.assertAfterWithGeneratorInvariantsWithError(self.resource_a)
  340. self.assertAfterWithGeneratorInvariantsWithError(self.resource_b)
  341. def testNestedExceptionBeforeInnerStatement(self):
  342. mock_a = mock_contextmanager_generator()
  343. mock_b = mock_contextmanager_generator()
  344. self.bar = None
  345. def shouldThrow():
  346. with mock_a as self.foo:
  347. self.assertInWithManagerInvariants(mock_a)
  348. self.assertInWithGeneratorInvariants(self.foo)
  349. self.raiseTestException()
  350. with mock_b as self.bar:
  351. pass
  352. self.assertRaises(RuntimeError, shouldThrow)
  353. self.assertAfterWithManagerInvariantsWithError(mock_a)
  354. self.assertAfterWithGeneratorInvariantsWithError(self.foo)
  355. # The inner statement stuff should never have been touched
  356. self.assertEqual(self.bar, None)
  357. self.assertFalse(mock_b.enter_called)
  358. self.assertFalse(mock_b.exit_called)
  359. self.assertEqual(mock_b.exit_args, None)
  360. def testNestedExceptionAfterInnerStatement(self):
  361. mock_a = mock_contextmanager_generator()
  362. mock_b = mock_contextmanager_generator()
  363. def shouldThrow():
  364. with mock_a as self.foo:
  365. with mock_b as self.bar:
  366. self.assertInWithManagerInvariants(mock_a)
  367. self.assertInWithManagerInvariants(mock_b)
  368. self.assertInWithGeneratorInvariants(self.foo)
  369. self.assertInWithGeneratorInvariants(self.bar)
  370. self.raiseTestException()
  371. self.assertRaises(RuntimeError, shouldThrow)
  372. self.assertAfterWithManagerInvariantsWithError(mock_a)
  373. self.assertAfterWithManagerInvariantsNoError(mock_b)
  374. self.assertAfterWithGeneratorInvariantsWithError(self.foo)
  375. self.assertAfterWithGeneratorInvariantsNoError(self.bar)
  376. def testRaisedStopIteration1(self):
  377. # From bug 1462485
  378. @contextmanager
  379. def cm():
  380. yield
  381. def shouldThrow():
  382. with cm():
  383. raise StopIteration("from with")
  384. self.assertRaises(StopIteration, shouldThrow)
  385. def testRaisedStopIteration2(self):
  386. # From bug 1462485
  387. class cm(object):
  388. def __enter__(self):
  389. pass
  390. def __exit__(self, type, value, traceback):
  391. pass
  392. def shouldThrow():
  393. with cm():
  394. raise StopIteration("from with")
  395. self.assertRaises(StopIteration, shouldThrow)
  396. def testRaisedStopIteration3(self):
  397. # Another variant where the exception hasn't been instantiated
  398. # From bug 1705170
  399. @contextmanager
  400. def cm():
  401. yield
  402. def shouldThrow():
  403. with cm():
  404. raise iter([]).next()
  405. self.assertRaises(StopIteration, shouldThrow)
  406. def testRaisedGeneratorExit1(self):
  407. # From bug 1462485
  408. @contextmanager
  409. def cm():
  410. yield
  411. def shouldThrow():
  412. with cm():
  413. raise GeneratorExit("from with")
  414. self.assertRaises(GeneratorExit, shouldThrow)
  415. def testRaisedGeneratorExit2(self):
  416. # From bug 1462485
  417. class cm (object):
  418. def __enter__(self):
  419. pass
  420. def __exit__(self, type, value, traceback):
  421. pass
  422. def shouldThrow():
  423. with cm():
  424. raise GeneratorExit("from with")
  425. self.assertRaises(GeneratorExit, shouldThrow)
  426. def testErrorsInBool(self):
  427. # issue4589: __exit__ return code may raise an exception
  428. # when looking at its truth value.
  429. class cm(object):
  430. def __init__(self, bool_conversion):
  431. class Bool:
  432. def __nonzero__(self):
  433. return bool_conversion()
  434. self.exit_result = Bool()
  435. def __enter__(self):
  436. return 3
  437. def __exit__(self, a, b, c):
  438. return self.exit_result
  439. def trueAsBool():
  440. with cm(lambda: True):
  441. self.fail("Should NOT see this")
  442. trueAsBool()
  443. def falseAsBool():
  444. with cm(lambda: False):
  445. self.fail("Should raise")
  446. self.assertRaises(AssertionError, falseAsBool)
  447. def failAsBool():
  448. with cm(lambda: 1 // 0):
  449. self.fail("Should NOT see this")
  450. self.assertRaises(ZeroDivisionError, failAsBool)
  451. class NonLocalFlowControlTestCase(unittest.TestCase):
  452. def testWithBreak(self):
  453. counter = 0
  454. while True:
  455. counter += 1
  456. with mock_contextmanager_generator():
  457. counter += 10
  458. break
  459. counter += 100 # Not reached
  460. self.assertEqual(counter, 11)
  461. def testWithContinue(self):
  462. counter = 0
  463. while True:
  464. counter += 1
  465. if counter > 2:
  466. break
  467. with mock_contextmanager_generator():
  468. counter += 10
  469. continue
  470. counter += 100 # Not reached
  471. self.assertEqual(counter, 12)
  472. def testWithReturn(self):
  473. def foo():
  474. counter = 0
  475. while True:
  476. counter += 1
  477. with mock_contextmanager_generator():
  478. counter += 10
  479. return counter
  480. counter += 100 # Not reached
  481. self.assertEqual(foo(), 11)
  482. def testWithYield(self):
  483. def gen():
  484. with mock_contextmanager_generator():
  485. yield 12
  486. yield 13
  487. x = list(gen())
  488. self.assertEqual(x, [12, 13])
  489. def testWithRaise(self):
  490. counter = 0
  491. try:
  492. counter += 1
  493. with mock_contextmanager_generator():
  494. counter += 10
  495. raise RuntimeError
  496. counter += 100 # Not reached
  497. except RuntimeError:
  498. self.assertEqual(counter, 11)
  499. else:
  500. self.fail("Didn't raise RuntimeError")
  501. class AssignmentTargetTestCase(unittest.TestCase):
  502. def testSingleComplexTarget(self):
  503. targets = {1: [0, 1, 2]}
  504. with mock_contextmanager_generator() as targets[1][0]:
  505. self.assertEqual(targets.keys(), [1])
  506. self.assertEqual(targets[1][0].__class__, MockResource)
  507. with mock_contextmanager_generator() as targets.values()[0][1]:
  508. self.assertEqual(targets.keys(), [1])
  509. self.assertEqual(targets[1][1].__class__, MockResource)
  510. with mock_contextmanager_generator() as targets[2]:
  511. keys = targets.keys()
  512. keys.sort()
  513. self.assertEqual(keys, [1, 2])
  514. class C: pass
  515. blah = C()
  516. with mock_contextmanager_generator() as blah.foo:
  517. self.assertEqual(hasattr(blah, "foo"), True)
  518. def testMultipleComplexTargets(self):
  519. class C:
  520. def __enter__(self): return 1, 2, 3
  521. def __exit__(self, t, v, tb): pass
  522. targets = {1: [0, 1, 2]}
  523. with C() as (targets[1][0], targets[1][1], targets[1][2]):
  524. self.assertEqual(targets, {1: [1, 2, 3]})
  525. with C() as (targets.values()[0][2], targets.values()[0][1], targets.values()[0][0]):
  526. self.assertEqual(targets, {1: [3, 2, 1]})
  527. with C() as (targets[1], targets[2], targets[3]):
  528. self.assertEqual(targets, {1: 1, 2: 2, 3: 3})
  529. class B: pass
  530. blah = B()
  531. with C() as (blah.one, blah.two, blah.three):
  532. self.assertEqual(blah.one, 1)
  533. self.assertEqual(blah.two, 2)
  534. self.assertEqual(blah.three, 3)
  535. class ExitSwallowsExceptionTestCase(unittest.TestCase):
  536. def testExitTrueSwallowsException(self):
  537. class AfricanSwallow:
  538. def __enter__(self): pass
  539. def __exit__(self, t, v, tb): return True
  540. try:
  541. with AfricanSwallow():
  542. 1 // 0
  543. except ZeroDivisionError:
  544. self.fail("ZeroDivisionError should have been swallowed")
  545. def testExitFalseDoesntSwallowException(self):
  546. class EuropeanSwallow:
  547. def __enter__(self): pass
  548. def __exit__(self, t, v, tb): return False
  549. try:
  550. with EuropeanSwallow():
  551. 1 // 0
  552. except ZeroDivisionError:
  553. pass
  554. else:
  555. self.fail("ZeroDivisionError should have been raised")
  556. class NestedWith(unittest.TestCase):
  557. class Dummy(object):
  558. def __init__(self, value=None, gobble=False):
  559. if value is None:
  560. value = self
  561. self.value = value
  562. self.gobble = gobble
  563. self.enter_called = False
  564. self.exit_called = False
  565. def __enter__(self):
  566. self.enter_called = True
  567. return self.value
  568. def __exit__(self, *exc_info):
  569. self.exit_called = True
  570. self.exc_info = exc_info
  571. if self.gobble:
  572. return True
  573. class InitRaises(object):
  574. def __init__(self): raise RuntimeError()
  575. class EnterRaises(object):
  576. def __enter__(self): raise RuntimeError()
  577. def __exit__(self, *exc_info): pass
  578. class ExitRaises(object):
  579. def __enter__(self): pass
  580. def __exit__(self, *exc_info): raise RuntimeError()
  581. def testNoExceptions(self):
  582. with self.Dummy() as a, self.Dummy() as b:
  583. self.assertTrue(a.enter_called)
  584. self.assertTrue(b.enter_called)
  585. self.assertTrue(a.exit_called)
  586. self.assertTrue(b.exit_called)
  587. def testExceptionInExprList(self):
  588. try:
  589. with self.Dummy() as a, self.InitRaises():
  590. pass
  591. except:
  592. pass
  593. self.assertTrue(a.enter_called)
  594. self.assertTrue(a.exit_called)
  595. def testExceptionInEnter(self):
  596. try:
  597. with self.Dummy() as a, self.EnterRaises():
  598. self.fail('body of bad with executed')
  599. except RuntimeError:
  600. pass
  601. else:
  602. self.fail('RuntimeError not reraised')
  603. self.assertTrue(a.enter_called)
  604. self.assertTrue(a.exit_called)
  605. def testExceptionInExit(self):
  606. body_executed = False
  607. with self.Dummy(gobble=True) as a, self.ExitRaises():
  608. body_executed = True
  609. self.assertTrue(a.enter_called)
  610. self.assertTrue(a.exit_called)
  611. self.assertTrue(body_executed)
  612. self.assertNotEqual(a.exc_info[0], None)
  613. def testEnterReturnsTuple(self):
  614. with self.Dummy(value=(1,2)) as (a1, a2), \
  615. self.Dummy(value=(10, 20)) as (b1, b2):
  616. self.assertEqual(1, a1)
  617. self.assertEqual(2, a2)
  618. self.assertEqual(10, b1)
  619. self.assertEqual(20, b2)
  620. def test_main():
  621. run_unittest(FailureTestCase, NonexceptionalTestCase,
  622. NestedNonexceptionalTestCase, ExceptionalTestCase,
  623. NonLocalFlowControlTestCase,
  624. AssignmentTargetTestCase,
  625. ExitSwallowsExceptionTestCase,
  626. NestedWith)
  627. if __name__ == '__main__':
  628. test_main()