Skip to content

Instantly share code, notes, and snippets.

@voldmar
Created January 11, 2012 20:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save voldmar/1596545 to your computer and use it in GitHub Desktop.
Save voldmar/1596545 to your computer and use it in GitHub Desktop.
nested_getattr — getattr for inner functions in decorators
# coding: utf-8
from functools import wraps
def decorator_wraps(f):
@wraps(f)
def inner(*args, **kwargs):
return f(*args, **kwargs)
inner.test = 'ok'
return inner
def outer_decorator_wraps(f):
@wraps(f)
def inner(*args, **kwargs):
return f(*args, **kwargs)
return inner
def decorator_non_wraps(f):
def inner(*args, **kwargs):
return f(*args, **kwargs)
inner.test = 'ok'
return inner
def outer_decorator_non_wraps(f):
def inner(*args, **kwargs):
return f(*args, **kwargs)
return inner
@outer_decorator_wraps
@outer_decorator_wraps
@decorator_wraps
def func_wraps(*args, **kwargs):
pass
@outer_decorator_non_wraps
@outer_decorator_non_wraps
@decorator_non_wraps
def func_non_wraps(*args, **kwargs):
pass
def nested_getattr(func, name, *args):
'''Get attr for nested functions'''
if len(args) > 1:
raise TypeError('nested_getattr expected at most 3 arguments, got {0}'.format(2 + len(args)))
nested = func
while 1:
if hasattr(nested, name):
return getattr(nested, name)
if getattr(nested, 'func_closure', None) is None:
if args:
return args[0]
raise AttributeError(name)
nested = nested.func_closure[0].cell_contents
def test_not_fail_wraps():
assert getattr(func_wraps, 'test') == 'ok'
def test_ok_wraps():
assert nested_getattr(func_wraps, 'test') == 'ok'
def test_fail_non_wraps():
assert not hasattr(func_non_wraps, 'test')
def test_ok_non_wraps():
assert nested_getattr(func_non_wraps, 'test') == 'ok'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment