Получение локальных переменных функции - PullRequest
3 голосов
/ 17 октября 2010

Я пытаюсь получить локальную переменную от декоратора.Пример:

def needs_privilege(privilege, project=None):
    """Check whether the logged-in user is authorised based on the
    given privilege

    @type privilege: Privilege object, id, or str
    @param privilege: The requested privilege"""

    def validate(func, self, *args, **kwargs):
        """Validator of needs_privillige"""
        try: check(self.user, privilege, project)
        except AccessDenied:
            return abort(status_code=401)
        else: 
            return func(self, *args, **kwargs)

    return decorator(validate)

После оформления функции, например:

 @needs_privilege("some_privilege")
 def some_function():
     pass

Я хотел бы получить переменную 'privilige' (которую использует validate ()) из some_function.После поисков более часа я чувствую себя довольно растерянным.Возможно ли это?

Редактировать : Позвольте мне более подробно описать мою проблему: могу ли я получить строку "some_prvilege" без выполнения Some_function?Что-то вроде:

a = getattr(module, 'somefunction')
print a.decorator_arguments

?Спасибо за помощь мне до сих пор!

Ответы [ 4 ]

3 голосов
/ 17 октября 2010

Ваш декоратор в основном проверяет, есть ли у пользователя разрешение на выполнение данной функции, на самом деле я не понимаю, почему вы хотите получить (присоединить) привилегию к функции, которая была упакована, но вы можете сделать это без добавленияеще один аргумент для всех ваших функций.

def needs_privilege(privilege, project=None):
    """Check whether the logged-in user is authorised based on the
    given privilege

    @type privilege: Privilege object, id, or str
    @param privilege: The requested privilege"""

    def validate(func, self, *args, **kwargs):
        """Validator of needs_privillige"""
        try: check(self.user, privilege, project)
        except AccessDenied:
            return abort(status_code=401)
        else:
            return func(self, *args, **kwargs)
    validate.privelege = privelege
    return decorator(validate)

кстати, ваш декоратор должен быть таким:

def needs_privilege(privilege, project=None):
    def validate(func):
        def new_func(self, *args, **kwargs):
            try: 
                check(self.user, privilege, project)
            except AccessDenied:
                return abort(status_code=401)
            else:
                return func(self, *args, **kwargs)
        new_func.privilege = privilege
        return new_func
    return validate
2 голосов
/ 17 октября 2010

Вы можете передать его в качестве параметра:

def needs_privilege(privilege, project=None):
    """Check whether the logged-in user is authorised based on the
    given privilege

    @type privilege: Privilege object, id, or str
    @param privilege: The requested privilege"""

    def validate(func, self, *args, **kwargs):
        """Validator of needs_privillige"""
        try: check(self.user, privilege, project)
        except AccessDenied:
            return abort(status_code=401)
        else: 
            return func(self, privilege, *args, **kwargs)

    return decorator(validate)

@needs_privilege("some_privilege")
def some_function(privilege):
    pass
1 голос
/ 17 октября 2010

Ваша проблема была бы намного проще, если бы вам не нужен модуль decorator. Если вам не нужен модуль decorator, вы можете написать декоратор так:

def needs_privilege(privilege, project=None):
    def validate(func):
        def _validate(self, *args, **kwargs):
            return func(self, *args, **kwargs)
        _validate.decorator_args=(privilege,project)
        return _validate
    return validate

@needs_privilege("some_privilege")
def some_function(self):
    pass

a = some_function
print(a.decorator_args)
# ('some_privilege', None)
0 голосов
/ 17 октября 2010

Функции - это объекты, которые тоже могут иметь атрибуты. Вы можете установить атрибуты в декораторе. Вот пример:

class TestClass(object):
    def needs_privilege(privilege, project=None):
        def wrapper(func):
            def validate(self, *args, **kwargs):
                """Validator of needs_privillige"""
                print 'validator check for %s' % privilege
                return func(*args, **kwargs)
            validate.privilege = privilege
            return validate

        return wrapper

    @needs_privilege("foo")
    def bar():
        print "called"

>>> test.TestClass().bar()
validator check for foo
called
>>> test.TestClass.bar.privilege
'foo'
>>> test.TestClass().bar.privilege
'foo'
...