@@ -151,21 +151,18 @@ def double(x):
151
151
self .assertEqual (counts ['double' ], 4 )
152
152
153
153
def test_errors (self ):
154
- # Test syntax restrictions - these are all compile-time errors:
155
- #
156
- for expr in [ "1+2" , "x[3]" , "(1, 2)" ]:
157
- # Sanity check: is expr is a valid expression by itself?
158
- compile (expr , "testexpr" , "exec" )
159
-
160
- codestr = "@%s\n def f(): pass" % expr
161
- self .assertRaises (SyntaxError , compile , codestr , "test" , "exec" )
162
154
163
- # You can't put multiple decorators on a single line:
164
- #
165
- self .assertRaises (SyntaxError , compile ,
166
- "@f1 @f2\n def f(): pass" , "test" , "exec" )
155
+ # Test SyntaxErrors:
156
+ for stmt in ("x," , "x, y" , "x = y" , "pass" , "import sys" ):
157
+ compile (stmt , "test" , "exec" ) # Sanity check.
158
+ with self .assertRaises (SyntaxError ):
159
+ compile (f"@{ stmt } \n def f(): pass" , "test" , "exec" )
167
160
168
- # Test runtime errors
161
+ # Test TypeErrors that used to be SyntaxErrors:
162
+ for expr in ("1.+2j" , "[1, 2][-1]" , "(1, 2)" , "True" , "..." , "None" ):
163
+ compile (expr , "test" , "eval" ) # Sanity check.
164
+ with self .assertRaises (TypeError ):
165
+ exec (f"@{ expr } \n def f(): pass" )
169
166
170
167
def unimp (func ):
171
168
raise NotImplementedError
@@ -179,6 +176,18 @@ def unimp(func):
179
176
code = compile (codestr , "test" , "exec" )
180
177
self .assertRaises (exc , eval , code , context )
181
178
179
+ def test_expressions (self ):
180
+ for expr in (
181
+ ## original tests
182
+ # "(x,)", "(x, y)", "x := y", "(x := y)", "x @y", "(x @ y)", "x[0]",
183
+ # "w[x].y.z", "w + x - (y + z)", "x(y)()(z)", "[w, x, y][z]", "x.y",
184
+
185
+ ##same without :=
186
+ "(x,)" , "(x, y)" , "x @y" , "(x @ y)" , "x[0]" ,
187
+ "w[x].y.z" , "w + x - (y + z)" , "x(y)()(z)" , "[w, x, y][z]" , "x.y" ,
188
+ ):
189
+ compile (f"@{ expr } \n def f(): pass" , "test" , "exec" )
190
+
182
191
def test_double (self ):
183
192
class C (object ):
184
193
@funcattrs (abc = 1 , xyz = "haha" )
@@ -265,6 +274,45 @@ def bar(): return 42
265
274
self .assertEqual (bar (), 42 )
266
275
self .assertEqual (actions , expected_actions )
267
276
277
+ def test_wrapped_descriptor_inside_classmethod (self ):
278
+ class BoundWrapper :
279
+ def __init__ (self , wrapped ):
280
+ self .__wrapped__ = wrapped
281
+
282
+ def __call__ (self , * args , ** kwargs ):
283
+ return self .__wrapped__ (* args , ** kwargs )
284
+
285
+ class Wrapper :
286
+ def __init__ (self , wrapped ):
287
+ self .__wrapped__ = wrapped
288
+
289
+ def __get__ (self , instance , owner ):
290
+ bound_function = self .__wrapped__ .__get__ (instance , owner )
291
+ return BoundWrapper (bound_function )
292
+
293
+ def decorator (wrapped ):
294
+ return Wrapper (wrapped )
295
+
296
+ class Class :
297
+ @decorator
298
+ @classmethod
299
+ def inner (cls ):
300
+ # This should already work.
301
+ return 'spam'
302
+
303
+ @classmethod
304
+ @decorator
305
+ def outer (cls ):
306
+ # Raised TypeError with a message saying that the 'Wrapper'
307
+ # object is not callable.
308
+ return 'eggs'
309
+
310
+ self .assertEqual (Class .inner (), 'spam' )
311
+ #self.assertEqual(Class.outer(), 'eggs') # TODO RustPython
312
+ self .assertEqual (Class ().inner (), 'spam' )
313
+ #self.assertEqual(Class().outer(), 'eggs') # TODO RustPython
314
+
315
+
268
316
class TestClassDecorators (unittest .TestCase ):
269
317
270
318
def test_simple (self ):
@@ -301,4 +349,4 @@ class C(object): pass
301
349
self .assertEqual (C .extra , 'second' )
302
350
303
351
if __name__ == "__main__" :
304
- unittest .main ()
352
+ unittest .main ()
0 commit comments