summaryrefslogtreecommitdiff
path: root/django/utils/functional.py
AgeCommit message (Collapse)Author
2025-12-24Fixed #36810 -- Avoided infinite recursion in SimpleLazyObject.__repr__().Sean
Detect when `SimpleLazyObject._setupfunc` is a bound method of the same instance to use a safe representation and avoid infinite recursion.
2025-03-31Refs #28909 -- Simplified code using unpacking generalizations.Aarni Koskela
2023-06-12Allowed custom formatting of lazy() objects.Nick Pope
This allows for formatting of lazy objects which have a custom formatter defined by overriding the default implementation from `object`.
2023-06-12Allowed multiplication of lazy() objects with int return type.Nick Pope
2023-06-12Removed function call overhead when preparing proxy class for lazy().Nick Pope
We can avoid the function call and assignment overhead which could be significant when instantiating many lazy objects. It's still easy enough to read too.
2023-06-12Made proxy class in lazy() prepare eagerly.Ran Benita
Previously, the proxy class was prepared lazily: lazy_identity = lazy(identity, int) lazy_identity(10) # prepared here lazy_identity(10) This has a slight advantage that if the lazy doesn't end up getting used, the preparation work is skipped, however that's not very likely. Besides this laziness, it is also inconsistent in that the methods which are wrapped directly (__str__ etc.) are prepared already when __proxy__ is defined, and there is a weird half-initialized state. This change it so that everything is prepared already on the first line of the example above.
2023-06-12Improved order of methods in proxy class in lazy().Ran Benita
This order reads more naturally and puts methods into three groups: 1. The methods required to support the implementation of __proxy__, e.g. __deepcopy__ doesn't come from `object` and __reduce__ is overridden to support behavior required explicitly for pickling of lazy objects. 2. Methods that are specifically overridden from `object` which we don't want to inherit from the provided resultclasses. These will be skipped later when we add methods from the resultclasses. 3. Additional methods - that is _add__, __radd__, and __mod__ - don't come from `object`, but typically from `str` and `int` which are the most common use cases. Co-authored-by: Nick Pope <nick@nickpope.me.uk>
2023-06-08Optimized lazy() by removing use of @total_ordering.Ran Benita
@total_ordering is slow. Using the following micro-benchmark (resultclasses intentionally omitted to narrow the scope): import cProfile from django.utils.functional import lazy def identity(x): return x cProfile.run("for i in range(10000): str(lazy(identity)(1))") Before: 380003 function calls in 0.304 seconds ncalls tottime percall cumtime percall filename:lineno(function) 1 0.016 0.016 0.304 0.304 <string>:1(<module>) 10000 0.002 0.000 0.002 0.000 bench.py:5(double) 10000 0.005 0.000 0.006 0.000 functional.py:100(__cast) 10000 0.007 0.000 0.013 0.000 functional.py:106(__str__) 10000 0.005 0.000 0.017 0.000 functional.py:140(__wrapper__) 10000 0.020 0.000 0.258 0.000 functional.py:60(lazy) 10000 0.039 0.000 0.039 0.000 functional.py:68(__proxy__) 10000 0.010 0.000 0.012 0.000 functional.py:77(__init__) 10000 0.002 0.000 0.002 0.000 functional.py:84(__prepare_class__) 10000 0.025 0.000 0.075 0.000 functools.py:186(total_ordering) 10000 0.015 0.000 0.028 0.000 functools.py:189(<setcomp>) 10000 0.024 0.000 0.044 0.000 functools.py:37(update_wrapper) 10000 0.005 0.000 0.005 0.000 functools.py:67(wraps) 10000 0.074 0.000 0.114 0.000 {built-in method builtins.__build_class__} 1 0.000 0.000 0.304 0.304 {built-in method builtins.exec} 150000 0.023 0.000 0.023 0.000 {built-in method builtins.getattr} 10000 0.004 0.000 0.004 0.000 {built-in method builtins.max} 80000 0.025 0.000 0.025 0.000 {built-in method builtins.setattr} 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 10000 0.003 0.000 0.003 0.000 {method 'update' of 'dict' objects} After: 240003 function calls in 0.231 seconds ncalls tottime percall cumtime percall filename:lineno(function) 1 0.016 0.016 0.231 0.231 <string>:1(<module>) 10000 0.002 0.000 0.002 0.000 bench.py:5(double) 10000 0.006 0.000 0.012 0.000 functional.py:105(__str__) 10000 0.005 0.000 0.017 0.000 functional.py:159(__wrapper__) 10000 0.015 0.000 0.186 0.000 functional.py:60(lazy) 10000 0.022 0.000 0.022 0.000 functional.py:68(__proxy__) 10000 0.010 0.000 0.012 0.000 functional.py:76(__init__) 10000 0.002 0.000 0.002 0.000 functional.py:83(__prepare_class__) 10000 0.004 0.000 0.006 0.000 functional.py:99(__cast) 10000 0.023 0.000 0.043 0.000 functools.py:37(update_wrapper) 10000 0.004 0.000 0.004 0.000 functools.py:67(wraps) 10000 0.102 0.000 0.124 0.000 {built-in method builtins.__build_class__} 1 0.000 0.000 0.231 0.231 {built-in method builtins.exec} 70000 0.011 0.000 0.011 0.000 {built-in method builtins.getattr} 50000 0.007 0.000 0.007 0.000 {built-in method builtins.setattr} 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 10000 0.003 0.000 0.003 0.000 {method 'update' of 'dict' objects}
2023-06-08Made bytes and str return types no longer mutually exclusive in lazy().Ran Benita
They are no longer special cased.
2023-06-08Removed unnecessary wrapping of __bytes__ in proxy class in lazy().Ran Benita
2023-06-08Removed unnecessary branch in __mod__() from proxy class in lazy().Ran Benita
Unnecessary since c716fe87821df00f9f03ecc761c914d1682591a2 and 7b2f2e74adb36a4334e83130f6abc2f79d395235.
2023-06-08Refs #34445 -- Fixed string-casting of non-string lazy objects when value ↵Ran Benita
may be bytes. If the result type is bytes, then calling bytes() on it does nothing. If the result type is not bytes, we should not cast to bytes, just because the return value may be bytes.
2023-03-30Fixed #34445 -- Fixed string-casting of non-string lazy objects.Ran Benita
This removes __text_cast() as it's the same as __cast(). _delegate_bytes and __delegate_text are mutually exclusive so the `if self._delegate_bytes` branch in __cast() is unreachable. Co-Authored-By: David Sanders <shang.xiao.sanders@gmail.com>
2023-03-30Removed unused __bytes_cast_encoded() from proxy class in lazy().Ran Benita
Unused since c716fe87821df00f9f03ecc761c914d1682591a2.
2023-01-17Refs #30127 -- Removed name argument for ↵Mariusz Felisiak
django.utils.functional.cached_property(). Per deprecation timeline.
2022-03-03Optimized lazy wrappers a bit.Collin Anderson
This avoids an extra __getattribute__() call for self._wrapped.
2022-02-17Refs #28358 -- Fixed infinite recursion in LazyObject.__getattribute__().Matthias Kestenholz
Regression in 97d7990abde3fe4b525ae83958fd0b52d6a1d13f. Co-authored-by: Mariusz Felisiak <felisiak.mariusz@gmail.com> Co-authored-by: Theo Alexiou <theofilosalexiou@gmail.com>
2022-02-16Fixed #28358 -- Prevented LazyObject from mimicking nonexistent attributes.Theo Alexiou
Thanks Sergey Fedoseev for the initial patch.
2022-02-10Fixed #26287 -- Added support for addition operations to SimpleLazyObject.Theo Alexiou
2022-02-07Refs #33476 -- Reformatted code with Black.django-bot
2021-12-16Fixed #30127 -- Deprecated name argument of cached_property().mgaligniana
2021-03-15Refs #32508 -- Raised ValueError instead of using "assert" in lazy().Hasan Ramezani
2020-12-21Fixed #32208 -- Allowed adding lazy() objects.Hasan Ramezani
Co-authored-by: Claude Paroz <claude@2xlibre.net>
2020-03-31Fixed #30864 -- Doc'd classproperty decorator.Deep Sukhwani
2019-10-21Fixed #30876 -- Moved classproperty() decorator to the django.utils.functional.André Ericson
2019-05-22Fixed #30498 -- Fixed proxy class caching in lazy().Ran Benita
lazy() should prepare the proxy class only once (the first time it's used) not on every call. Regression in b4e76f30d12bfa8a53cc297c60055c6f4629cc4c.
2019-02-05Refs #27753 -- Removed django.utils.functional.curry().Tim Graham
2019-01-30Fixed #30116 -- Dropped support for Python 3.5.Tim Graham
2018-11-19Fixed #29478 -- Added support for mangled names to cached_property.Thomas Grainger
Co-Authored-By: Sergey Fedoseev <fedoseev.sergey@gmail.com>
2018-09-19Fixed #29772 -- Made LazyObject proxy __lt__() and __gt__().Javier Buzzi
2017-12-26Fixed #28930 -- Simplified code with any() and all().Дилян Палаузов
2017-12-21Refs #28909 -- Simplifed code using unpacking generalizations.Nick Pope
2017-12-11Fixed #28909 -- Simplified code using tuple/list/set/dict unpacking.Nick Pope
2017-10-13Improved performance of utils.html.escape().Tom
2017-07-12Refs #23919 -- Removed LazyObject.__getstate__() needed only on Python 2.Sergey Fedoseev
2017-05-27Fixed #28249 -- Removed unnecessary dict.keys() calls.Jon Dufresne
iter(dict) is equivalent to iter(dict.keys()).
2017-05-15Corrected cached_property.__get__() docstring.Simon Charette
2017-05-15Added a docstring to cached_property.__get__().Adam Alton
2017-03-04Refs #27795 -- Removed unneeded force_text callsClaude Paroz
Thanks Tim Graham for the review.
2017-02-11Refs #27656 -- Updated django.utils docstring verbs according to PEP 257.Anton Samarchyan
2017-02-09Refs #23919 -- Removed default 'utf-8' argument for str.encode()/decode().Tim Graham
2017-01-25Refs #23919 -- Replaced super(ClassName, self) with super().chillaranand
2017-01-19Refs #23919 -- Stopped inheriting from object to define new style classes.Simon Charette
2017-01-18Refs #23919 -- Removed obsolete __ne__() methods.Aymeric Augustin
__ne__() defaults to the opposite of __eq__() on Python 3 when it doesn't return NotImplemented.
2017-01-18Refs #23919 -- Removed most of remaining six usageClaude Paroz
Thanks Tim Graham for the review.
2017-01-18Refs #23919 -- Removed six.<various>_types usageClaude Paroz
Thanks Tim Graham and Simon Charette for the reviews.
2017-01-18Refs #23919 -- Removed six.PY2/PY3 usageClaude Paroz
Thanks Tim Graham for the review.
2017-01-17Refs #20223 -- Removed deprecated django.utils.functional.allow_lazy().Tim Graham
2016-11-29Fixed #27555 -- Removed django.utils.functional.lazy_property.Adam Chainz
2016-11-23Cleaned up some __getstate__() docstrings.Tim Graham