]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- alter the decorator function, and the newer public_factory function,
authorMike Bayer <mike_mp@zzzcomputing.com>
Sun, 22 Dec 2013 00:51:25 +0000 (19:51 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sun, 22 Dec 2013 00:51:25 +0000 (19:51 -0500)
to use a named def instead of a lambda.  this so that TypeError on wrong
arguments are more legible.  [ticket:2884]

lib/sqlalchemy/util/langhelpers.py

index 1a66426d06f9203c8eca446c480c401848bd5514..7e261e38fe47f9d65d47cc3223f0e9f0f761ca55 100644 (file)
@@ -99,14 +99,21 @@ def decorator(target):
 
         metadata = dict(target=targ_name, fn=fn_name)
         metadata.update(format_argspec_plus(spec, grouped=False))
-
-        code = 'lambda %(args)s: %(target)s(%(fn)s, %(apply_kw)s)' % (
-                metadata)
-        decorated = eval(code, {targ_name: target, fn_name: fn})
+        metadata['name'] = fn.__name__
+        code = """\
+def %(name)s(%(args)s):
+    return %(target)s(%(fn)s, %(apply_kw)s)
+""" % metadata
+        decorated = _exec_code_in_env(code,
+                            {targ_name: target, fn_name: fn},
+                            fn.__name__)
         decorated.__defaults__ = getattr(fn, 'im_func', fn).__defaults__
         return update_wrapper(decorated, fn)
     return update_wrapper(decorate, target)
 
+def _exec_code_in_env(code, env, fn_name):
+    exec(code, env)
+    return env[fn_name]
 
 def public_factory(target, location):
     """Produce a wrapping function for the given cls or classmethod.
@@ -127,11 +134,18 @@ def public_factory(target, location):
         doc = "This function is mirrored; see :func:`~%s` "\
                 "for a description of arguments." % location
 
+    location_name = location.split(".")[-1]
     spec = compat.inspect_getfullargspec(fn)
     del spec[0][0]
     metadata = format_argspec_plus(spec, grouped=False)
-    code = 'lambda %(args)s: cls(%(apply_kw)s)' % metadata
-    decorated = eval(code, {'cls': callable_, 'symbol': symbol})
+    metadata['name'] = location_name
+    code = """\
+def %(name)s(%(args)s):
+    return cls(%(apply_kw)s)
+""" % metadata
+    env = {'cls': callable_, 'symbol': symbol}
+    exec(code, env)
+    decorated = env[location_name]
     decorated.__doc__ = fn.__doc__
     if compat.py2k or hasattr(fn, '__func__'):
         fn.__func__.__doc__ = doc