@@ -151,21 +151,18 @@ def double(x):
151151 self .assertEqual (counts ['double' ], 4 )
152152
153153 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" )
162154
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" )
167160
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" )
169166
170167 def unimp (func ):
171168 raise NotImplementedError
@@ -179,6 +176,18 @@ def unimp(func):
179176 code = compile (codestr , "test" , "exec" )
180177 self .assertRaises (exc , eval , code , context )
181178
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+
182191 def test_double (self ):
183192 class C (object ):
184193 @funcattrs (abc = 1 , xyz = "haha" )
@@ -265,6 +274,47 @@ def bar(): return 42
265274 self .assertEqual (bar (), 42 )
266275 self .assertEqual (actions , expected_actions )
267276
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+
268318class TestClassDecorators (unittest .TestCase ):
269319
270320 def test_simple (self ):
@@ -301,4 +351,4 @@ class C(object): pass
301351 self .assertEqual (C .extra , 'second' )
302352
303353if __name__ == "__main__" :
304- unittest .main ()
354+ unittest .main ()
0 commit comments