From 24b969d28eef143f350815ace68d8e5a1a2e7775 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Sun, 7 Mar 2010 07:18:46 +0000 Subject: [PATCH] [1.1.X] Fixed #12876 -- Corrected a problem with recursive relations under deepcopy. Thanks to elachuni for the patch. Backport of r12700 from trunk. git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.1.X@12702 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/db/models/sql/query.py | 12 ++++++------ tests/modeltests/many_to_one/models.py | 7 +++++++ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index dc16a4f442..36a83036a9 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -111,7 +111,7 @@ class BaseQuery(object): return sql % params def __deepcopy__(self, memo): - result= self.clone() + result = self.clone(memo=memo) memo[id(self)] = result return result @@ -173,7 +173,7 @@ class BaseQuery(object): self.quote_cache[name] = r return r - def clone(self, klass=None, **kwargs): + def clone(self, klass=None, memo=None, **kwargs): """ Creates a copy of the current instance. The 'kwargs' parameter can be used by clients to update attributes after copying has taken place. @@ -198,19 +198,19 @@ class BaseQuery(object): obj.dupe_avoidance = self.dupe_avoidance.copy() obj.select = self.select[:] obj.tables = self.tables[:] - obj.where = deepcopy(self.where) + obj.where = deepcopy(self.where, memo=memo) obj.where_class = self.where_class if self.group_by is None: obj.group_by = None else: obj.group_by = self.group_by[:] - obj.having = deepcopy(self.having) + obj.having = deepcopy(self.having, memo=memo) obj.order_by = self.order_by[:] obj.low_mark, obj.high_mark = self.low_mark, self.high_mark obj.distinct = self.distinct obj.select_related = self.select_related obj.related_select_cols = [] - obj.aggregates = deepcopy(self.aggregates) + obj.aggregates = deepcopy(self.aggregates, memo=memo) if self.aggregate_select_mask is None: obj.aggregate_select_mask = None else: @@ -231,7 +231,7 @@ class BaseQuery(object): obj._extra_select_cache = self._extra_select_cache.copy() obj.extra_tables = self.extra_tables obj.extra_order_by = self.extra_order_by - obj.deferred_loading = deepcopy(self.deferred_loading) + obj.deferred_loading = deepcopy(self.deferred_loading, memo=memo) if self.filter_is_sticky and self.used_aliases: obj.used_aliases = self.used_aliases.copy() else: diff --git a/tests/modeltests/many_to_one/models.py b/tests/modeltests/many_to_one/models.py index 8093e73013..21b5bf91b4 100644 --- a/tests/modeltests/many_to_one/models.py +++ b/tests/modeltests/many_to_one/models.py @@ -263,6 +263,13 @@ FieldError: Cannot resolve keyword 'reporter_id' into field. Choices are: headli >>> Reporter.objects.filter(article__reporter__exact=r).distinct() [] +# Regression for #12876 -- Model methods that include queries that +# recursive don't cause recursion depth problems under deepcopy. +>>> r.cached_query = Article.objects.filter(reporter=r) +>>> from copy import deepcopy +>>> deepcopy(r) + + # Check that implied __exact also works. >>> Reporter.objects.filter(article__reporter=r).distinct() []