импорт копия
импорта 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 ):
self . __args = args
self . __kw = kw,
если не сам . __подготовлено :
сам . __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 __add__ ( self , other ):
вернуть себя . __cast () + другое
def __radd__ ( self , other ):
вернуть другой + self . __cast ()
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" ] = значение
иначе :
если сам . _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 (). Таким образом, мы в конечном итоге
думаем, что #
pickle , по сути, являемся отдельным объектом от обернутого # объекта, но с тем же __dict__. Это может вызвать проблемы (см. # 25389).
#
# Вместо этого мы определяем наш собственный метод __reduce__ и настраиваемый 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 )] = результат
вернуть результат
вернуть копию . deepcopy ( self . _wrapped , памятка )
__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 ( сам ):
себя . _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 , памятка )
def partition ( предикат , значения ):
"" "
Разделите значения на два набора на основе возвращаемого значения функции
(Истина / Ложь). Например:
>>> partition (lambda x: x> 3, range (5))
[0, 1, 2, 3], [4]
"" "
results = ([], [])
для элемента в значениях :
results [ предикат ( item )] . append ( item )
возвращает результаты