test_scope.py revision 5941d191deaf2a0c8eab5ce75316067ed16dfb1a
1from __future__ import nested_scopes 2 3from test.test_support import verify, TestFailed, check_syntax 4 5print "1. simple nesting" 6 7def make_adder(x): 8 def adder(y): 9 return x + y 10 return adder 11 12inc = make_adder(1) 13plus10 = make_adder(10) 14 15verify(inc(1) == 2) 16verify(plus10(-2) == 8) 17 18print "2. extra nesting" 19 20def make_adder2(x): 21 def extra(): # check freevars passing through non-use scopes 22 def adder(y): 23 return x + y 24 return adder 25 return extra() 26 27inc = make_adder2(1) 28plus10 = make_adder2(10) 29 30verify(inc(1) == 2) 31verify(plus10(-2) == 8) 32 33print "3. simple nesting + rebinding" 34 35def make_adder3(x): 36 def adder(y): 37 return x + y 38 x = x + 1 # check tracking of assignment to x in defining scope 39 return adder 40 41inc = make_adder3(0) 42plus10 = make_adder3(9) 43 44verify(inc(1) == 2) 45verify(plus10(-2) == 8) 46 47print "4. nesting with global but no free" 48 49def make_adder4(): # XXX add exta level of indirection 50 def nest(): 51 def nest(): 52 def adder(y): 53 return global_x + y # check that plain old globals work 54 return adder 55 return nest() 56 return nest() 57 58global_x = 1 59adder = make_adder4() 60verify(adder(1) == 2) 61 62global_x = 10 63verify(adder(-2) == 8) 64 65print "5. nesting through class" 66 67def make_adder5(x): 68 class Adder: 69 def __call__(self, y): 70 return x + y 71 return Adder() 72 73inc = make_adder5(1) 74plus10 = make_adder5(10) 75 76verify(inc(1) == 2) 77verify(plus10(-2) == 8) 78 79print "6. nesting plus free ref to global" 80 81def make_adder6(x): 82 global global_nest_x 83 def adder(y): 84 return global_nest_x + y 85 global_nest_x = x 86 return adder 87 88inc = make_adder6(1) 89plus10 = make_adder6(10) 90 91verify(inc(1) == 11) # there's only one global 92verify(plus10(-2) == 8) 93 94print "7. nearest enclosing scope" 95 96def f(x): 97 def g(y): 98 x = 42 # check that this masks binding in f() 99 def h(z): 100 return x + z 101 return h 102 return g(2) 103 104test_func = f(10) 105verify(test_func(5) == 47) 106 107print "8. mixed freevars and cellvars" 108 109def identity(x): 110 return x 111 112def f(x, y, z): 113 def g(a, b, c): 114 a = a + x # 3 115 def h(): 116 # z * (4 + 9) 117 # 3 * 13 118 return identity(z * (b + y)) 119 y = c + z # 9 120 return h 121 return g 122 123g = f(1, 2, 3) 124h = g(2, 4, 6) 125verify(h() == 39) 126 127print "9. free variable in method" 128 129def test(): 130 method_and_var = "var" 131 class Test: 132 def method_and_var(self): 133 return "method" 134 def test(self): 135 return method_and_var 136 def actual_global(self): 137 return str("global") 138 def str(self): 139 return str(self) 140 return Test() 141 142t = test() 143verify(t.test() == "var") 144verify(t.method_and_var() == "method") 145verify(t.actual_global() == "global") 146 147method_and_var = "var" 148class Test: 149 # this class is not nested, so the rules are different 150 def method_and_var(self): 151 return "method" 152 def test(self): 153 return method_and_var 154 def actual_global(self): 155 return str("global") 156 def str(self): 157 return str(self) 158 159t = Test() 160verify(t.test() == "var") 161verify(t.method_and_var() == "method") 162verify(t.actual_global() == "global") 163 164print "10. recursion" 165 166def f(x): 167 def fact(n): 168 if n == 0: 169 return 1 170 else: 171 return n * fact(n - 1) 172 if x >= 0: 173 return fact(x) 174 else: 175 raise ValueError, "x must be >= 0" 176 177verify(f(6) == 720) 178 179 180print "11. unoptimized namespaces" 181 182check_syntax("""from __future__ import nested_scopes 183def unoptimized_clash1(strip): 184 def f(s): 185 from string import * 186 return strip(s) # ambiguity: free or local 187 return f 188""") 189 190check_syntax("""from __future__ import nested_scopes 191def unoptimized_clash2(): 192 from string import * 193 def f(s): 194 return strip(s) # ambiguity: global or local 195 return f 196""") 197 198check_syntax("""from __future__ import nested_scopes 199def unoptimized_clash2(): 200 from string import * 201 def g(): 202 def f(s): 203 return strip(s) # ambiguity: global or local 204 return f 205""") 206 207# XXX could allow this for exec with const argument, but what's the point 208check_syntax("""from __future__ import nested_scopes 209def error(y): 210 exec "a = 1" 211 def f(x): 212 return x + y 213 return f 214""") 215 216check_syntax("""from __future__ import nested_scopes 217def f(x): 218 def g(): 219 return x 220 del x # can't del name 221""") 222 223check_syntax("""from __future__ import nested_scopes 224def f(): 225 def g(): 226 from string import * 227 return strip # global or local? 228""") 229 230# and verify a few cases that should work 231 232def noproblem1(): 233 from string import * 234 f = lambda x:x 235 236def noproblem2(): 237 from string import * 238 def f(x): 239 return x + 1 240 241def noproblem3(): 242 from string import * 243 def f(x): 244 global y 245 y = x 246 247print "12. lambdas" 248 249f1 = lambda x: lambda y: x + y 250inc = f1(1) 251plus10 = f1(10) 252verify(inc(1) == 2) 253verify(plus10(5) == 15) 254 255f2 = lambda x: (lambda : lambda y: x + y)() 256inc = f2(1) 257plus10 = f2(10) 258verify(inc(1) == 2) 259verify(plus10(5) == 15) 260 261f3 = lambda x: lambda y: global_x + y 262global_x = 1 263inc = f3(None) 264verify(inc(2) == 3) 265 266f8 = lambda x, y, z: lambda a, b, c: lambda : z * (b + y) 267g = f8(1, 2, 3) 268h = g(2, 4, 6) 269verify(h() == 18) 270 271print "13. UnboundLocal" 272 273def errorInOuter(): 274 print y 275 def inner(): 276 return y 277 y = 1 278 279def errorInInner(): 280 def inner(): 281 return y 282 inner() 283 y = 1 284 285try: 286 errorInOuter() 287except UnboundLocalError: 288 pass 289else: 290 raise TestFailed 291 292try: 293 errorInInner() 294except UnboundLocalError: 295 pass 296else: 297 raise TestFailed 298 299print "14. complex definitions" 300 301def makeReturner(*lst): 302 def returner(): 303 return lst 304 return returner 305 306verify(makeReturner(1,2,3)() == (1,2,3)) 307 308def makeReturner2(**kwargs): 309 def returner(): 310 return kwargs 311 return returner 312 313verify(makeReturner2(a=11)()['a'] == 11) 314 315def makeAddPair((a, b)): 316 def addPair((c, d)): 317 return (a + c, b + d) 318 return addPair 319 320verify(makeAddPair((1, 2))((100, 200)) == (101,202)) 321