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

импорт  копия 
импорта  itertools 
импорта  оператор 
из  functools  импортируют  total_ordering ,  обручи


[docs] class cached_property : "" " Декоратор, который преобразует метод с одним аргументом self в свойство, кэшированное в экземпляре. Кешированное свойство может быть создано из существующего метода: (например, `` url = cached_property (get_absolute_url) ''). Необязательный аргумент name устарел в Python 3.6 и станет устаревшим в Django 4.0 (# 30127). "" " name = Нет @staticmethod def func ( instance ): raise TypeError ( 'Невозможно использовать экземпляр cached_property без вызова' '__set_name __ () на нем.' ) def __init__ ( self , func , name = None ): self . real_func = FUNC самостоятельно . __doc__ = GetAttr ( FUNC , '__doc__' ) def __set_name__ ( я , владелец , имя ): если self . Имя является None : самостоятельно . name = name self . func = self . real_func elif имя ! = себя . name : raise TypeError ( "Невозможно назначить одно и то же cached_property двум разным именам" "( % r и % r )." % ( self . name, имя ) ) def __get__ ( self , instance , cls = None ): "" " Вызовите функцию и поместите возвращаемое значение в instance .__ dict__, чтобы последующий доступ к атрибутам в экземпляре возвращал кешированное значение вместо вызова cached_property .__ get __ (). " " " если instance is None : return self res = instance . __dict__ [ сам . имя ] = себя . func ( экземпляр ) вернуть res
[docs] class classproperty : "" " Декоратор, преобразующий метод с одним аргументом cls в свойство, к которому можно получить доступ напрямую из класса. " "" def __init__ ( self , method = None ): self . fget = метод def __get__ ( self , instance , cls = None ): вернуть self . fget ( cls ) def getter ( self , method ): self . fget = метод return self
class Promise : "" " Базовый класс для прокси-класса, созданный при закрытии ленивой функции. Он используется для распознавания обещаний в коде. " "" pass def lazy ( func , * resultclasses ): "" " Превратите любой вызываемый объект в вызываемый объект с отложенной оценкой. Требуются классы или типы результатов - по крайней мере, один необходим, чтобы запускалось автоматическое принудительное выполнение кода отложенного вычисления. Результаты не мемоизованный; функция оценивается при каждом доступе. "" " @total_ordering class __proxy__ ( Promise ): "" " Инкапсулирует вызов функции и действует как прокси для методов, которые вызываются в результате этой функции. Функция не оценивается, пока не будет вызван один из методов для результата. " " " __prepared = Ложь def __init__ ( self , args , kw ): себя . __args = args self . __kw = kw, если не сам . __prepared : самостоятельно . __prepare_class__ () себя . __class__ . __prepared = Верно def __reduce__ ( self ): return ( _lazy_proxy_unpickle , ( func , self . __args , self . __kw ) + resultclasses ) def __repr__ ( self ): вернуть repr ( self . __cast ()) @classmethod def __prepare_class__ ( cls ): для класса результатов в классах результатов : для типа_ в классе результатов . mro (): для method_name в type_ . __dict__ : # Все __promise__ возвращают один и тот же метод оболочки, они # ищут правильную реализацию при вызове. если hasattr ( cls , имя_метода ): продолжить meth = cls . __promise__ ( имя_метода ) setattr ( cls , имя_метода , meth ) cls . _delegate_bytes = байт в resultclasses ЦБС . _delegate_text = str в результирующих классах assert not ( cls . _delegate_bytes и cls . _delegate_text ), ( «Невозможно вызвать lazy () с возвращаемыми типами как байтов, так и текста.» ) if cls . _delegate_text : cls . __str__ = cls, __text_cast elif cls . _delegate_bytes : cls . __bytes__ = cls . __bytes_cast @classmethod def __promise__ ( cls , method_name ): # Создает оболочку вокруг некоторого магического метода def __wrapper__ ( self , * args , ** kw ): # Автоматически запускает вычисление ленивого значения и # применяет указанный магический метод результата тип. res = func ( * self . __args , ** self . __kw ) return getattr ( res , method_name ) (* args , ** kw ) return __wrapper__ def __text_cast ( self ): return func ( * self . __args , ** self . __kw ) def __bytes_cast ( self ): вернуть байты ( func ( * self . __args , ** self . __kw )) def __bytes_cast_encoded ( self ): return func ( * self . __args , ** self . __kw ) . кодировать () def __cast ( self ): если self . _delegate_bytes : вернуть себя . __bytes_cast () elif self . _delegate_text : вернуть себя . __text_cast () else : return func ( * self . __args , ** self . __kw ) def __str__ ( self ): # объект определяет __str __ (), поэтому __prepare_class __ () не будет перегружать # метод __str __ () проксируемого класса. return str ( self . __cast ()) def __eq__ ( self , other ): if isinstance ( other , Promise ): other = other . __cast () вернуть себя . __cast () == другое def __lt__ ( self , other ): if isinstance ( other , Promise ): other = other . __cast () вернуть себя . __cast () < другое def __hash__ ( self ): вернуть хэш ( self . __cast ()) def __mod__ ( self , rhs ): если self . _delegate_text : return str ( self ) % rhs return self . __cast () % rhs def __deepcopy__ ( self , memo ): # Экземпляры этого класса фактически неизменяемы. Это просто # набор функций. Так что нам не нужно # делать ничего сложного для копирования. памятка [ идентификатор ( само )] = само возвращение самообслуживания @wraps ( func ) def __wrapper__ ( * args , ** kw ): # Создает прокси-объект вместо фактического значения. вернуть __proxy__ ( аргументы , кВт ) вернуть __wrapper__ def _lazy_proxy_unpickle ( func , args , kwargs , * resultclasses ): return lazy ( func , * resultclasses ) ( * args , ** kwargs ) def lazystr ( text ): "" " Ярлык для общего случая ленивого вызываемого объекта, который возвращает str. " "" return lazy ( str , str ) ( text )
[docs] def keep_lazy ( * resultclasses ): "" " Декоратор, который позволяет вызывать функцию с одним или несколькими ленивыми аргументами. Если ни один из аргументов не является ленивым, функция оценивается немедленно, в противном случае возвращается __proxy__, который будет при необходимости оцените функцию. "" " если не resultclasses : raise TypeError ( " Вы должны передать хотя бы один аргумент keep_lazy (). " ) декоратор def ( func ): lazy_func = lazy ( func , * resultclasses ) @wraps ( func ) def wrapper ( * args , ** kwargs ): если есть ( isinstance ( arg , Promise ) для arg в itertools . chain ( args , kwargs . values ())): return lazy_func ( * args , ** kwargs ) return func ( * args , ** kwargs) декоратор возврата обертки возврата
[docs] def keep_lazy_text ( func ): "" " Декоратор для функций, которые принимают ленивые аргументы и возвращают текст. " "" return keep_lazy ( str ) ( func )
пустой = объект () def new_method_proxy ( func ): def inner ( self , * args ): если self . _wrapped является пустым : самостоятельно . _setup () return func ( self . _wrapped , * args ) return inner class LazyObject : "" " Обертка для другого класса, которая может использоваться для задержки создания экземпляра обернутого класса. Создавая подклассы, у вас есть возможность перехватить и изменить экземпляр. Если вам это не нужно, используйте SimpleLazyObject. «»» # Избегайте бесконечной рекурсии при трассировке __init__ (# 19456). _wrapped = Нет def __init__ ( self ): # Примечание: если подкласс переопределяет __init __ (), ему, вероятно, также потребуется # переопределить __copy __ () и __deepcopy __ (). я . _wrapped = пусто __getattr__ = новый_метод_прокси ( getattr ) def __setattr__ ( self , name , value ): if name == "_wrapped" : # Назначьте __dict__, чтобы избежать бесконечных циклов __setattr__. я . __dict__ [ "_wrapped" ] = значение иначе : если self . _wrapped является пустым : самостоятельно . _setup () setattr ( сам . _wrapped , имя , значение ) def __delattr__ ( self , name ): if name == "_wrapped" : поднять TypeError ( "невозможно удалить _wrapped." ) if self . _wrapped является пустым : самостоятельно . _setup () delattr ( сам . _wrapped , имя ) def _setup ( self ): "" " Должен быть реализован подклассами для инициализации обернутого объекта. " "" raise NotImplementedError ( 'подклассы LazyObject должны предоставлять метод _setup ()' ) # Поскольку мы испортили __class__ ниже, мы путаем pickle с тем, какой # класс мы обрабатываем. Нам нужно будет инициализировать обернутый объект #, чтобы успешно его засолить, поэтому мы можем просто засолить обернутый # объект, поскольку они должны действовать одинаково. # # К сожалению, если мы попытаемся просто действовать как обернутый объект, уловка # сломается, когда pickle получит наш id (). Таким образом, мы заканчиваем тем, что рассуждаем # думаем, по сути, что мы отдельный объект от обернутого # объекта, но с тем же __dict__. Это может вызвать проблемы (см. # 25389). # # Вместо этого мы определяем наш собственный метод __reduce__ и настраиваемый распаковщик. Мы # рассолить обернутый объект в качестве аргумента unpickler, чтобы pickle # обработал его как обычно, а затем unpickler просто возвращает свой # аргумент. def __reduce__ ( self ): если self . _wrapped является пустым : самостоятельно . _setup () return ( unpickle_lazyobject , ( self . _wrapped ,)) def __copy__ ( self ): если self . _wrapped является пустым : # Если инициализирован, скопируйте обертку. Используйте тип (self), а не # self .__ class__, потому что последний проксируется. return type ( self ) () else : # Если инициализировано, вернуть копию обернутого объекта. вернуть копию . копия ( self . _wrapped ) def __deepcopy__ ( self , memo ): если self . _wrapped является пустым : # Мы должны типа использования (само), а не само .__ class__, поскольку # последний проксируется. result = type ( self ) () memo [ id ( self )] = результат return result return copy . deepcopy ( self . _wrapped , memo ) __bytes__ = new_method_proxy ( байты ) __str__ = new_method_proxy ( str ) __bool__ = new_method_proxy ( bool ) # Поддержка интроспекции __dir__ = new_method_proxy ( dir ) # Нужно притвориться обернутый класс, ради объектов, # забота об этом (особенно в тестах равенства) __class__ = свойство ( new_method_proxy ( оператор . Attrgetter ( «__class__» ))) __eq__ = new_method_proxy ( оператор . Экв ) __lt__ = new_method_proxy ( operator . lt ) __gt__ = new_method_proxy ( operator . gt ) __ne__ = new_method_proxy( оператор . ne ) __hash__ = new_method_proxy ( хэш ) # Список / Кортеж / Словарь методы поддержки __getitem__ = new_method_proxy ( оператор . GetItem ) __setitem__ = new_method_proxy ( оператор . SetItem ) __delitem__ = new_method_proxy ( оператор . Delitem ) __iter__ = new_method_proxy ( ИТЭР ) __len__ = new_method_proxy ( Len ) __contains__ = new_method_proxy ( оператор . содержит) def unpickle_lazyobject ( wrapped ): "" " Используется для извлечения ленивых объектов. Просто верните его аргумент, которым будет завернутый объект. " "" return wrapped class SimpleLazyObject ( LazyObject ): "" " Ленивый объект, инициализируемый любой функцией. Предназначен для составных объектов неизвестного типа. Для встроенных функций или объектов известного типа используйте django.utils.functional.lazy. "" " def __init__ ( self , func ): " "" Передайте вызываемый объект, который возвращает объект, который нужно обернуть. Если создаются копии результирующего объекта SimpleLazyObject, что может происходить в Django при различных обстоятельствах, тогда вы должны убедиться, что вызываемый объект может безопасно запускаться более одного раза и возвращать то же значение. "" " self . __dict__ [ '_setupfunc' ] = func super () . __init__ () def _setup ( self ): себя . _wrapped = self . _setupfunc () # Возвращает осмысленное представление ленивого объекта для отладки # без оценки обернутого объекта. def __repr__ ( self ): если self . _wrapped является пустым : repr_attr = сам . _setupfunc else : repr_attr = self . _wrapped return '< % s : % r >' % ( тип ( сам ) . __name__ , repr_attr ) def __copy__ ( self ): если self . _wrapped является пустым : # Если инициализирован, скопируйте обертку. Используйте SimpleLazyObject, а не # self .__ class__, потому что последний проксируется. return SimpleLazyObject ( self . _setupfunc ) else : # Если инициализирован, вернуть копию обернутого объекта. вернуть копию . копия ( self . _wrapped ) def __deepcopy__ ( self , memo ): если self . _wrapped является пустым : # Мы должны использовать SimpleLazyObject, а не само .__ class__, поскольку # последний проксируется. result = SimpleLazyObject ( self . _setupfunc ) memo [ id ( self )] = результат вернуть результат вернуть копию . deepcopy ( self . _wrapped , memo ) def partition ( предикат , значения ): "" " Разделите значения на два набора на основе возвращаемого значения функции (True / False). например: >>> partition (lambda x: x> 3, range (5)) [0, 1, 2, 3], [4] "" " results = ([], []) для элемента в значениях : results [ предикат ( item )] . append ( item ) возвращает результаты

Copyright ©2020 All rights reserved