Исходный код для django.utils.decorators

«Функции, помогающие динамически создавать декораторы для представлений».

из  functools  import  partial ,  update_wrapper ,  wraps


class  classonlymethod ( classmethod ): 
    def  __get__ ( self ,  instance ,  cls = None ): 
        if  instance  is  not  None : 
            raise  AttributeError ( «Этот метод доступен только для класса, а не для экземпляров.» ) 
        return  super () . __get__ ( экземпляр ,  cls )


def  _update_method_wrapper ( _wrapper ,  decorator ): 
    метод bound_method _multi_decorate () недоступен в этой области. Обманите 
    # используя его в фиктивной функции. 
    @decorator 
    def  dummy ( * args ,  ** kwargs ): 
        передать 
    update_wrapper ( _wrapper ,  dummy )


def  _multi_decorate ( decorators ,  method ): 
    "" " 
    Украсить` method` одним или несколькими декораторами функций. `decorators` могут быть 
    одним или несколькими декораторами. 
    " "" 
    if  hasattr ( decorators ,  '__iter__' ): 
        # Примените список / кортеж декораторов, если 'декораторы' один. 
        Функции 
        Decorator # применяются таким образом, что порядок вызова совпадает с порядком #, в котором они появляются в итеративном элементе. 
        декораторы  =  декораторы [:: - 1 ] 
    else : 
        декораторы  = [ декораторы ]

    def  _wrapper ( self ,  * args ,  ** kwargs ): 
        # bound_method имеет подпись, которую ожидает 'декоратор', т.е. нет 
        аргумента # 'self', но это закрытие над self, поэтому он может вызывать 
        # 'func'. Кроме того, оберните метод .__ get __ () в функцию, потому что новые 
        # атрибуты не могут быть установлены для связанных объектов метода, только для функций. 
        bound_method  =  partial ( method . __get__ ( self ,  type ( self ))) 
        для  dec  в  декораторах : 
            bound_method  = dec ( bound_method ) 
        return  bound_method ( * аргументы ,  ** kwargs )

    # Скопируйте любые атрибуты, которые декоратор добавляет к функции, которую он украшает. 
    для  dec  в  декораторах : 
        _update_method_wrapper ( _wrapper ,  dec ) 
    # Сохранить все существующие атрибуты 'метода', включая имя. 
    update_wrapper ( _wrapper ,  метод ) 
    return  _wrapper


[docs] def method_decorator ( decorator , name = '' ): "" " Преобразование декоратора функции в декоратор метода " "" # 'obj' может быть классом или функцией. Если 'obj' является функцией в момент передачи # в _dec, в конечном итоге это будет метод класса, # для которого он определен. Если «obj» - это класс, «name» должно быть именем # метода, который будет украшен. def _dec ( obj ): если не isinstance ( obj , type ): декоратор , obj ) если нет ( name и hasattr ( obj , name )): raise ValueError ( "Аргумент ключевого слова` name` должен быть именем метода " " декорированного класса: % s . Вместо этого получено ' % s ' . " % ( obj , name ) ) method = getattr ( obj , name ) if not callable ( method ): raise TypeError( "Не может украсить ' % s ' , как это не вызываемым атрибут" " % S ( % s )." % ( Имя , OBJ , метод ) ) _wrapper = _multi_decorate ( декоратор , метод ) SetAttr ( OBJ , имя , _wrapper ) return obj # Не беспокойтесь о том, чтобы _dec выглядел как список / кортеж, потому что это # бессмысленно. if not hasattr ( decorator , '__iter__' ): update_wrapper ( _dec , decorator ) # Измените имя, чтобы облегчить отладку. obj = декоратор if hasattr ( декоратор , '__name__' ) else декоратор . __class__ _dec . __name__ = 'method_decorator ( % s )' % obj . __название__ вернуть _dec
[docs] def decorator_from_middleware_with_args ( middleware_class ): "" " Как decorator_from_middleware, но возвращает функцию, которая принимает аргументы, передаваемые в middleware_class. Используйте как :: cache_page = decorator_from_middleware_with_args (CacheMiddleware) # ... @cache_page (3600) def my_view (request): # ... "" " return make_middleware_decorator ( middleware_class )
[docs] def decorator_from_middleware ( middleware_class ): "" " Учитывая класс промежуточного программного обеспечения (не экземпляр), вернуть декоратор представления. Это позволяет использовать функциональность промежуточного программного обеспечения для каждого представления. Промежуточное программное обеспечение создается без переданных параметров. " "" return make_middleware_decorator ( middleware_class ) ()
def make_middleware_decorator ( middleware_class ): def _make_decorator ( * m_args , ** m_kwargs ): def _decorator ( view_func ): middleware = middleware_class ( view_func , * m_args , ** m_kwargs ) @wraps ( view_func ) def _wrapped_view ( request , * args , ** kwargs ): if hasattr ( middleware , 'process_request' ): result = middleware . process_request ( запрос ), если результат не равен None : вернуть результат, если hasattr ( промежуточное ПО , 'process_view' ): result = middleware , process_view ( request , view_func , args , kwargs ), если результат не равен None : вернуть результат try : response = view_func ( request , * args , ** kwargs ), кроме Exception как e : if hasattr ( middleware , 'process_exception' ): result = промежуточное ПО . process_exception ( request , e ), если результат не равен None : вернуть результат поднять, если hasattr ( response , 'render' ) и callable ( response . render ): if hasattr ( middleware , 'process_template_response' ): response = middleware . process_template_response ( запрос , ответ ) # Отложить выполнение process_response до тех пор, пока шаблон # не будет отрисован: if hasattr ( middleware , 'process_response' ): def callback ( response ): return middleware . process_response ( запрос , ответ ) ответ . add_post_render_callback ( обратный вызов ) else : if hasattr ( middleware , 'process_response' ): вернуть промежуточное ПО .process_response ( запрос , ответ ) return response return _wrapped_view return _decorator return _make_decorator
[docs] def sync_and_async_middleware ( func ): "" " Отметить фабрику промежуточного программного обеспечения как возвращающую гибридное промежуточное программное обеспечение, поддерживающее оба типа запросов. " "" func . sync_capable = Истинный функ . async_capable = True return func
[docs] def sync_only_middleware ( func ): "" " Отметить фабрику промежуточного программного обеспечения как возвращающую промежуточное программное обеспечение синхронизации. Это значение по умолчанию. " "" func . sync_capable = Истинный функ . async_capable = Ложные возвращение функ
[docs] def async_only_middleware ( func ): "" "Отметить фабрику промежуточного программного обеспечения как возвращающую асинхронное промежуточное ПО." "" func . sync_capable = Ложный функ . async_capable = True return func

Copyright ©2020 All rights reserved