summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Charette <charette.s@gmail.com>2024-01-13 14:21:36 -0500
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2024-01-15 05:56:33 +0100
commitd074c7530b812a7b78c9a201c8a70f281ed3a36e (patch)
tree518955c30ed741af8df3a9c6a9978670ea7b76be
parent92d6cff6a2fee7a3f9244081b84fd82c50cc71aa (diff)
Refs #35102 -- Optimized Expression.identity used for equality and hashing.
inspect.signature() is quite slow and produces the same object for each instance of the same class as they share their __init__ method which makes it a prime candidate for caching. Thanks Anthony Shaw for the report.
-rw-r--r--django/db/models/expressions.py13
1 files changed, 9 insertions, 4 deletions
diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py
index c20de5995a..9ee2d65c8a 100644
--- a/django/db/models/expressions.py
+++ b/django/db/models/expressions.py
@@ -14,7 +14,7 @@ from django.db.models import fields
from django.db.models.constants import LOOKUP_SEP
from django.db.models.query_utils import Q
from django.utils.deconstruct import deconstructible
-from django.utils.functional import cached_property
+from django.utils.functional import cached_property, classproperty
from django.utils.hashable import make_hashable
@@ -485,13 +485,18 @@ class BaseExpression:
class Expression(BaseExpression, Combinable):
"""An expression that can be combined with other expressions."""
+ @classproperty
+ @functools.lru_cache(maxsize=128)
+ def _constructor_signature(cls):
+ return inspect.signature(cls.__init__)
+
@cached_property
def identity(self):
- constructor_signature = inspect.signature(self.__init__)
args, kwargs = self._constructor_args
- signature = constructor_signature.bind_partial(*args, **kwargs)
+ signature = self._constructor_signature.bind_partial(self, *args, **kwargs)
signature.apply_defaults()
- arguments = signature.arguments.items()
+ arguments = iter(signature.arguments.items())
+ next(arguments)
identity = [self.__class__]
for arg, value in arguments:
if isinstance(value, fields.Field):