1from __future__ import with_statement 2 3import sys 4 5def typename(t): 6 name = type(t).__name__ 7 if sys.version_info < (2,5): 8 if name == 'classobj' and issubclass(t, MyException): 9 name = 'type' 10 elif name == 'instance' and isinstance(t, MyException): 11 name = 'MyException' 12 return u"<type '%s'>" % name 13 14class MyException(Exception): 15 pass 16 17class ContextManager(object): 18 def __init__(self, value, exit_ret = None): 19 self.value = value 20 self.exit_ret = exit_ret 21 22 def __exit__(self, a, b, tb): 23 print u"exit", typename(a), typename(b), typename(tb) 24 return self.exit_ret 25 26 def __enter__(self): 27 print u"enter" 28 return self.value 29 30def no_as(): 31 """ 32 >>> no_as() 33 enter 34 hello 35 exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'> 36 """ 37 with ContextManager(u"value"): 38 print u"hello" 39 40def basic(): 41 """ 42 >>> basic() 43 enter 44 value 45 exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'> 46 """ 47 with ContextManager(u"value") as x: 48 print x 49 50def with_pass(): 51 """ 52 >>> with_pass() 53 enter 54 exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'> 55 """ 56 with ContextManager(u"value") as x: 57 pass 58 59def with_exception(exit_ret): 60 """ 61 >>> with_exception(None) 62 enter 63 value 64 exit <type 'type'> <type 'MyException'> <type 'traceback'> 65 outer except 66 >>> with_exception(True) 67 enter 68 value 69 exit <type 'type'> <type 'MyException'> <type 'traceback'> 70 """ 71 try: 72 with ContextManager(u"value", exit_ret=exit_ret) as value: 73 print value 74 raise MyException() 75 except: 76 print u"outer except" 77 78def multitarget(): 79 """ 80 >>> multitarget() 81 enter 82 1 2 3 4 5 83 exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'> 84 """ 85 with ContextManager((1, 2, (3, (4, 5)))) as (a, b, (c, (d, e))): 86 print a, b, c, d, e 87 88def tupletarget(): 89 """ 90 >>> tupletarget() 91 enter 92 (1, 2, (3, (4, 5))) 93 exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'> 94 """ 95 with ContextManager((1, 2, (3, (4, 5)))) as t: 96 print t 97 98def typed(): 99 """ 100 >>> typed() 101 enter 102 10 103 exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'> 104 """ 105 cdef unsigned char i 106 c = ContextManager(255) 107 with c as i: 108 i += 11 109 print i 110 111def multimanager(): 112 """ 113 >>> multimanager() 114 enter 115 enter 116 enter 117 enter 118 enter 119 enter 120 2 121 value 122 1 2 3 4 5 123 nested 124 exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'> 125 exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'> 126 exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'> 127 exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'> 128 exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'> 129 exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'> 130 """ 131 with ContextManager(1), ContextManager(2) as x, ContextManager(u'value') as y,\ 132 ContextManager(3), ContextManager((1, 2, (3, (4, 5)))) as (a, b, (c, (d, e))): 133 with ContextManager(u'nested') as nested: 134 print x 135 print y 136 print a, b, c, d, e 137 print nested 138 139# Tests borrowed from pyregr test_with.py, 140# modified to follow the constraints of Cython. 141import unittest 142 143class Dummy(object): 144 def __init__(self, value=None, gobble=False): 145 if value is None: 146 value = self 147 self.value = value 148 self.gobble = gobble 149 self.enter_called = False 150 self.exit_called = False 151 152 def __enter__(self): 153 self.enter_called = True 154 return self.value 155 156 def __exit__(self, *exc_info): 157 self.exit_called = True 158 self.exc_info = exc_info 159 if self.gobble: 160 return True 161 162class InitRaises(object): 163 def __init__(self): raise RuntimeError() 164 165class EnterRaises(object): 166 def __enter__(self): raise RuntimeError() 167 def __exit__(self, *exc_info): pass 168 169class ExitRaises(object): 170 def __enter__(self): pass 171 def __exit__(self, *exc_info): raise RuntimeError() 172 173class NestedWith(unittest.TestCase): 174 """ 175 >>> NestedWith().runTest() 176 """ 177 178 def runTest(self): 179 self.testNoExceptions() 180 self.testExceptionInExprList() 181 self.testExceptionInEnter() 182 self.testExceptionInExit() 183 self.testEnterReturnsTuple() 184 185 def testNoExceptions(self): 186 with Dummy() as a, Dummy() as b: 187 self.assertTrue(a.enter_called) 188 self.assertTrue(b.enter_called) 189 self.assertTrue(a.exit_called) 190 self.assertTrue(b.exit_called) 191 192 def testExceptionInExprList(self): 193 try: 194 with Dummy() as a, InitRaises(): 195 pass 196 except: 197 pass 198 self.assertTrue(a.enter_called) 199 self.assertTrue(a.exit_called) 200 201 def testExceptionInEnter(self): 202 try: 203 with Dummy() as a, EnterRaises(): 204 self.fail('body of bad with executed') 205 except RuntimeError: 206 pass 207 else: 208 self.fail('RuntimeError not reraised') 209 self.assertTrue(a.enter_called) 210 self.assertTrue(a.exit_called) 211 212 def testExceptionInExit(self): 213 body_executed = False 214 with Dummy(gobble=True) as a, ExitRaises(): 215 body_executed = True 216 self.assertTrue(a.enter_called) 217 self.assertTrue(a.exit_called) 218 self.assertTrue(body_executed) 219 self.assertNotEqual(a.exc_info[0], None) 220 221 def testEnterReturnsTuple(self): 222 with Dummy(value=(1,2)) as (a1, a2), \ 223 Dummy(value=(10, 20)) as (b1, b2): 224 self.assertEqual(1, a1) 225 self.assertEqual(2, a2) 226 self.assertEqual(10, b1) 227 self.assertEqual(20, b2) 228