@@ -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,47 @@ def bar(): return 42
265
274
self .assertEqual (bar (), 42 )
266
275
self .assertEqual (actions , expected_actions )
267
276
277
+ # this test was already not working before adding the Py39 decorator extension
278
+ @unittest .expectedFailure ('TODO RustPython' )
279
+ def test_wrapped_descriptor_inside_classmethod (self ):
280
+ class BoundWrapper :
281
+ def __init__ (self , wrapped ):
282
+ self .__wrapped__ = wrapped
283
+
284
+ def __call__ (self , * args , ** kwargs ):
285
+ return self .__wrapped__ (* args , ** kwargs )
286
+
287
+ class Wrapper :
288
+ def __init__ (self , wrapped ):
289
+ self .__wrapped__ = wrapped
290
+
291
+ def __get__ (self , instance , owner ):
292
+ bound_function = self .__wrapped__ .__get__ (instance , owner )
293
+ return BoundWrapper (bound_function )
294
+
295
+ def decorator (wrapped ):
296
+ return Wrapper (wrapped )
297
+
298
+ class Class :
299
+ @decorator
300
+ @classmethod
301
+ def inner (cls ):
302
+ # This should already work.
303
+ return 'spam'
304
+
305
+ @classmethod
306
+ @decorator
307
+ def outer (cls ):
308
+ # Raised TypeError with a message saying that the 'Wrapper'
309
+ # object is not callable.
310
+ return 'eggs'
311
+
312
+ self .assertEqual (Class .inner (), 'spam' )
313
+ #self.assertEqual(Class.outer(), 'eggs') # TODO RustPython
314
+ self .assertEqual (Class ().inner (), 'spam' )
315
+ #self.assertEqual(Class().outer(), 'eggs') # TODO RustPython
316
+
317
+
268
318
class TestClassDecorators (unittest .TestCase ):
269
319
270
320
def test_simple (self ):
@@ -301,4 +351,4 @@ class C(object): pass
301
351
self .assertEqual (C .extra , 'second' )
302
352
303
353
if __name__ == "__main__" :
304
- unittest .main ()
354
+ unittest .main ()
0 commit comments