summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRan Benita <ran234@gmail.com>2019-05-03 13:24:43 +0300
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2023-06-12 05:33:02 +0200
commitb214845f0f8d973e527e41730ca5770fad51ec5d (patch)
tree0bccce475a629832d4a529a0ed025b232dd04bf7
parente0e0204477e47a9f8c3302236a31a42514b94c25 (diff)
Improved order of methods in proxy class in lazy().
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>
-rw-r--r--django/utils/functional.py26
1 files changed, 16 insertions, 10 deletions
diff --git a/django/utils/functional.py b/django/utils/functional.py
index 6ee630c021..e3be672282 100644
--- a/django/utils/functional.py
+++ b/django/utils/functional.py
@@ -104,8 +104,12 @@ def lazy(func, *resultclasses):
(func, self.__args, self.__kw) + resultclasses,
)
- def __repr__(self):
- return repr(self.__cast())
+ def __deepcopy__(self, memo):
+ # Instances of this class are effectively immutable. It's just a
+ # collection of functions. So we don't need to do anything
+ # complicated for copying.
+ memo[id(self)] = self
+ return self
@classmethod
def __prepare_class__(cls):
@@ -133,6 +137,12 @@ def lazy(func, *resultclasses):
def __cast(self):
return func(*self.__args, **self.__kw)
+ # Explicitly wrap methods which are defined on object and hence would
+ # not have been overloaded by the loop over resultclasses below.
+
+ def __repr__(self):
+ return repr(self.__cast())
+
def __str__(self):
# object defines __str__(), so __prepare_class__() won't overload
# a __str__() method from the proxied class.
@@ -171,8 +181,8 @@ def lazy(func, *resultclasses):
def __hash__(self):
return hash(self.__cast())
- def __mod__(self, rhs):
- return self.__cast() % rhs
+ # Explicitly wrap methods which are required for certain operations on
+ # int/str objects to function correctly.
def __add__(self, other):
return self.__cast() + other
@@ -180,12 +190,8 @@ def lazy(func, *resultclasses):
def __radd__(self, other):
return other + self.__cast()
- def __deepcopy__(self, memo):
- # Instances of this class are effectively immutable. It's just a
- # collection of functions. So we don't need to do anything
- # complicated for copying.
- memo[id(self)] = self
- return self
+ def __mod__(self, other):
+ return self.__cast() % other
@wraps(func)
def __wrapper__(*args, **kw):