mirror of
https://github.com/django/django.git
synced 2025-08-04 10:59:45 +00:00
Fixed #28353 -- Fixed some GIS functions when queryset is evaluated more than once.
Reverted test for refs #27603 in favor of using FuncTestMixin.
This commit is contained in:
parent
99e65d6488
commit
3905cfa1a5
12 changed files with 176 additions and 86 deletions
|
@ -1,8 +1,11 @@
|
|||
import copy
|
||||
import unittest
|
||||
from functools import wraps
|
||||
from unittest import mock
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import DEFAULT_DB_ALIAS, connection
|
||||
from django.db.models.expressions import Func
|
||||
|
||||
|
||||
def skipUnlessGISLookup(*gis_lookups):
|
||||
|
@ -56,3 +59,39 @@ elif spatialite:
|
|||
from django.contrib.gis.db.backends.spatialite.models import SpatialiteSpatialRefSys as SpatialRefSys
|
||||
else:
|
||||
SpatialRefSys = None
|
||||
|
||||
|
||||
class FuncTestMixin:
|
||||
"""Assert that Func expressions aren't mutated during their as_sql()."""
|
||||
def setUp(self):
|
||||
def as_sql_wrapper(original_as_sql):
|
||||
def inner(*args, **kwargs):
|
||||
func = original_as_sql.__self__
|
||||
# Resolve output_field before as_sql() so touching it in
|
||||
# as_sql() won't change __dict__.
|
||||
func.output_field
|
||||
__dict__original = copy.deepcopy(func.__dict__)
|
||||
result = original_as_sql(*args, **kwargs)
|
||||
msg = '%s Func was mutated during compilation.' % func.__class__.__name__
|
||||
self.assertEqual(func.__dict__, __dict__original, msg)
|
||||
return result
|
||||
return inner
|
||||
|
||||
def __getattribute__(self, name):
|
||||
if name != vendor_impl:
|
||||
return __getattribute__original(self, name)
|
||||
try:
|
||||
as_sql = __getattribute__original(self, vendor_impl)
|
||||
except AttributeError:
|
||||
as_sql = __getattribute__original(self, 'as_sql')
|
||||
return as_sql_wrapper(as_sql)
|
||||
|
||||
vendor_impl = 'as_' + connection.vendor
|
||||
__getattribute__original = Func.__getattribute__
|
||||
self.func_patcher = mock.patch.object(Func, '__getattribute__', __getattribute__)
|
||||
self.func_patcher.start()
|
||||
super().setUp()
|
||||
|
||||
def tearDown(self):
|
||||
super().tearDown()
|
||||
self.func_patcher.stop()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue