<feed xmlns='http://www.w3.org/2005/Atom'>
<title>django.git/django/utils/functional.py, branch main</title>
<subtitle>django
</subtitle>
<id>http://cgit.adnoto.dev/django.git/atom?h=main</id>
<link rel='self' href='http://cgit.adnoto.dev/django.git/atom?h=main'/>
<link rel='alternate' type='text/html' href='http://cgit.adnoto.dev/django.git/'/>
<updated>2025-12-24T17:46:41Z</updated>
<entry>
<title>Fixed #36810 -- Avoided infinite recursion in SimpleLazyObject.__repr__().</title>
<updated>2025-12-24T17:46:41Z</updated>
<author>
<name>Sean</name>
<email>sean@pop-os.home</email>
</author>
<published>2025-12-18T23:37:07Z</published>
<link rel='alternate' type='text/html' href='http://cgit.adnoto.dev/django.git/commit/?id=8e4b531111ddd3256c45eee601947e475651e8e7'/>
<id>urn:sha1:8e4b531111ddd3256c45eee601947e475651e8e7</id>
<content type='text'>
Detect when `SimpleLazyObject._setupfunc` is a bound method of the same
instance to use a safe representation and avoid infinite recursion.
</content>
</entry>
<entry>
<title>Refs #28909 -- Simplified code using unpacking generalizations.</title>
<updated>2025-04-01T01:43:13Z</updated>
<author>
<name>Aarni Koskela</name>
<email>akx@iki.fi</email>
</author>
<published>2025-03-05T16:45:10Z</published>
<link rel='alternate' type='text/html' href='http://cgit.adnoto.dev/django.git/commit/?id=c972af69e2021b75b89d8bc47e214ef875bbdc06'/>
<id>urn:sha1:c972af69e2021b75b89d8bc47e214ef875bbdc06</id>
<content type='text'>
</content>
</entry>
<entry>
<title>Allowed custom formatting of lazy() objects.</title>
<updated>2023-06-12T04:09:20Z</updated>
<author>
<name>Nick Pope</name>
<email>nick@nickpope.me.uk</email>
</author>
<published>2023-06-07T11:34:35Z</published>
<link rel='alternate' type='text/html' href='http://cgit.adnoto.dev/django.git/commit/?id=e042024b28fcef43606557554714352781fc1d13'/>
<id>urn:sha1:e042024b28fcef43606557554714352781fc1d13</id>
<content type='text'>
This allows for formatting of lazy objects which have a custom formatter
defined by overriding the default implementation from `object`.
</content>
</entry>
<entry>
<title>Allowed multiplication of lazy() objects with int return type.</title>
<updated>2023-06-12T03:59:40Z</updated>
<author>
<name>Nick Pope</name>
<email>nick@nickpope.me.uk</email>
</author>
<published>2023-06-07T11:13:34Z</published>
<link rel='alternate' type='text/html' href='http://cgit.adnoto.dev/django.git/commit/?id=fd97b0471b19cb45c4346e4947dfa7e69ff06158'/>
<id>urn:sha1:fd97b0471b19cb45c4346e4947dfa7e69ff06158</id>
<content type='text'>
</content>
</entry>
<entry>
<title>Removed function call overhead when preparing proxy class for lazy().</title>
<updated>2023-06-12T03:53:30Z</updated>
<author>
<name>Nick Pope</name>
<email>nick@nickpope.me.uk</email>
</author>
<published>2023-04-19T20:07:59Z</published>
<link rel='alternate' type='text/html' href='http://cgit.adnoto.dev/django.git/commit/?id=45466f11f200914cde2a4b5533441b93015ea14e'/>
<id>urn:sha1:45466f11f200914cde2a4b5533441b93015ea14e</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>Made proxy class in lazy() prepare eagerly.</title>
<updated>2023-06-12T03:45:44Z</updated>
<author>
<name>Ran Benita</name>
<email>ran@unusedvar.com</email>
</author>
<published>2020-04-26T18:42:07Z</published>
<link rel='alternate' type='text/html' href='http://cgit.adnoto.dev/django.git/commit/?id=ae94077e7d884c26fc92b4b0d248a3b4a541ee44'/>
<id>urn:sha1:ae94077e7d884c26fc92b4b0d248a3b4a541ee44</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>Improved order of methods in proxy class in lazy().</title>
<updated>2023-06-12T03:33:02Z</updated>
<author>
<name>Ran Benita</name>
<email>ran234@gmail.com</email>
</author>
<published>2019-05-03T10:24:43Z</published>
<link rel='alternate' type='text/html' href='http://cgit.adnoto.dev/django.git/commit/?id=b214845f0f8d973e527e41730ca5770fad51ec5d'/>
<id>urn:sha1:b214845f0f8d973e527e41730ca5770fad51ec5d</id>
<content type='text'>
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 &lt;nick@nickpope.me.uk&gt;
</content>
</entry>
<entry>
<title>Optimized lazy() by removing use of @total_ordering.</title>
<updated>2023-06-08T07:17:50Z</updated>
<author>
<name>Ran Benita</name>
<email>ran234@gmail.com</email>
</author>
<published>2019-05-03T10:34:05Z</published>
<link rel='alternate' type='text/html' href='http://cgit.adnoto.dev/django.git/commit/?id=ee36e101e8f8c0acde4bb148b738ab7034e902a0'/>
<id>urn:sha1:ee36e101e8f8c0acde4bb148b738ab7034e902a0</id>
<content type='text'>
@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 &lt;string&gt;:1(&lt;module&gt;)
     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(&lt;setcomp&gt;)
     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 &lt;string&gt;:1(&lt;module&gt;)
     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}
</content>
</entry>
<entry>
<title>Made bytes and str return types no longer mutually exclusive in lazy().</title>
<updated>2023-06-08T07:15:40Z</updated>
<author>
<name>Ran Benita</name>
<email>ran234@gmail.com</email>
</author>
<published>2019-05-03T10:03:14Z</published>
<link rel='alternate' type='text/html' href='http://cgit.adnoto.dev/django.git/commit/?id=a57d5d9bbc27a7c3f18e14f68cfc74477b50eda0'/>
<id>urn:sha1:a57d5d9bbc27a7c3f18e14f68cfc74477b50eda0</id>
<content type='text'>
They are no longer special cased.
</content>
</entry>
<entry>
<title>Removed unnecessary wrapping of __bytes__ in proxy class in lazy().</title>
<updated>2023-06-08T07:15:40Z</updated>
<author>
<name>Ran Benita</name>
<email>ran234@gmail.com</email>
</author>
<published>2019-05-03T10:15:52Z</published>
<link rel='alternate' type='text/html' href='http://cgit.adnoto.dev/django.git/commit/?id=459f30f73e489356cf128abb3e9f357a7bffed0a'/>
<id>urn:sha1:459f30f73e489356cf128abb3e9f357a7bffed0a</id>
<content type='text'>
</content>
</entry>
</feed>
