From 282a19d95251ecb033d30300b2e21ad6c57fbd77 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sat, 21 Dec 2013 19:51:25 -0500 Subject: - alter the decorator function, and the newer public_factory function, 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 | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'lib/sqlalchemy/util/langhelpers.py') diff --git a/lib/sqlalchemy/util/langhelpers.py b/lib/sqlalchemy/util/langhelpers.py index 1a66426d0..7e261e38f 100644 --- a/lib/sqlalchemy/util/langhelpers.py +++ b/lib/sqlalchemy/util/langhelpers.py @@ -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 -- cgit v1.2.1