summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Graham <timograham@gmail.com>2015-09-02 19:55:55 -0400
committerTim Graham <timograham@gmail.com>2015-09-23 19:31:10 -0400
commit5d383549eee498e4903fe290613d726a68615aca (patch)
tree593b9b4d1d5145af9ef6e47f7c4f73a0f391e2ab
parentb6ea1961eb6816dee4370fb0ebd49dba29478db1 (diff)
Refs #24152 -- Removed deprecated GeoQuerySet aggregate methods.
Per deprecation timeline.
-rw-r--r--django/contrib/gis/db/models/query.py98
-rw-r--r--docs/ref/contrib/gis/geoquerysets.txt66
-rw-r--r--docs/releases/1.2.txt3
-rw-r--r--tests/gis_tests/geo3d/tests.py12
-rw-r--r--tests/gis_tests/geoapp/feeds.py4
-rw-r--r--tests/gis_tests/geoapp/tests.py49
-rw-r--r--tests/gis_tests/relatedapp/tests.py36
7 files changed, 35 insertions, 233 deletions
diff --git a/django/contrib/gis/db/models/query.py b/django/contrib/gis/db/models/query.py
index 66c45aa2be..07d593de02 100644
--- a/django/contrib/gis/db/models/query.py
+++ b/django/contrib/gis/db/models/query.py
@@ -1,6 +1,5 @@
import warnings
-from django.contrib.gis.db.models import aggregates
from django.contrib.gis.db.models.fields import (
GeometryField, LineStringField, PointField, get_srid_info,
)
@@ -15,9 +14,7 @@ from django.db.models.expressions import RawSQL
from django.db.models.fields import Field
from django.db.models.query import QuerySet
from django.utils import six
-from django.utils.deprecation import (
- RemovedInDjango20Warning, RemovedInDjango110Warning,
-)
+from django.utils.deprecation import RemovedInDjango20Warning
class GeoQuerySet(QuerySet):
@@ -62,19 +59,6 @@ class GeoQuerySet(QuerySet):
"""
return self._geom_attribute('centroid', **kwargs)
- def collect(self, **kwargs):
- """
- Performs an aggregate collect operation on the given geometry field.
- This is analogous to a union operation, but much faster because
- boundaries are not dissolved.
- """
- warnings.warn(
- "The collect GeoQuerySet method is deprecated. Use the Collect() "
- "aggregate in an aggregate() or annotate() method.",
- RemovedInDjango110Warning, stacklevel=2
- )
- return self._spatial_aggregate(aggregates.Collect, **kwargs)
-
def difference(self, geom, **kwargs):
"""
Returns the spatial difference of the geographic field in a `difference`
@@ -108,31 +92,6 @@ class GeoQuerySet(QuerySet):
"""
return self._geom_attribute('envelope', **kwargs)
- def extent(self, **kwargs):
- """
- Returns the extent (aggregate) of the features in the GeoQuerySet. The
- extent will be returned as a 4-tuple, consisting of (xmin, ymin, xmax, ymax).
- """
- warnings.warn(
- "The extent GeoQuerySet method is deprecated. Use the Extent() "
- "aggregate in an aggregate() or annotate() method.",
- RemovedInDjango110Warning, stacklevel=2
- )
- return self._spatial_aggregate(aggregates.Extent, **kwargs)
-
- def extent3d(self, **kwargs):
- """
- Returns the aggregate extent, in 3D, of the features in the
- GeoQuerySet. It is returned as a 6-tuple, comprising:
- (xmin, ymin, zmin, xmax, ymax, zmax).
- """
- warnings.warn(
- "The extent3d GeoQuerySet method is deprecated. Use the Extent3D() "
- "aggregate in an aggregate() or annotate() method.",
- RemovedInDjango110Warning, stacklevel=2
- )
- return self._spatial_aggregate(aggregates.Extent3D, **kwargs)
-
def force_rhr(self, **kwargs):
"""
Returns a modified version of the Polygon/MultiPolygon in which
@@ -227,19 +186,6 @@ class GeoQuerySet(QuerySet):
"""
return self._distance_attribute('length', None, **kwargs)
- def make_line(self, **kwargs):
- """
- Creates a linestring from all of the PointField geometries in the
- this GeoQuerySet and returns it. This is a spatial aggregate
- method, and thus returns a geometry rather than a GeoQuerySet.
- """
- warnings.warn(
- "The make_line GeoQuerySet method is deprecated. Use the MakeLine() "
- "aggregate in an aggregate() or annotate() method.",
- RemovedInDjango110Warning, stacklevel=2
- )
- return self._spatial_aggregate(aggregates.MakeLine, geo_field_type=PointField, **kwargs)
-
def mem_size(self, **kwargs):
"""
Returns the memory size (number of bytes) that the geometry field takes
@@ -415,19 +361,6 @@ class GeoQuerySet(QuerySet):
"""
return self._geomset_attribute('union', geom, **kwargs)
- def unionagg(self, **kwargs):
- """
- Performs an aggregate union on the given geometry field. Returns
- None if the GeoQuerySet is empty. The `tolerance` keyword is for
- Oracle backends only.
- """
- warnings.warn(
- "The unionagg GeoQuerySet method is deprecated. Use the Union() "
- "aggregate in an aggregate() or annotate() method.",
- RemovedInDjango110Warning, stacklevel=2
- )
- return self._spatial_aggregate(aggregates.Union, **kwargs)
-
# ### Private API -- Abstracted DRY routines. ###
def _spatial_setup(self, att, desc=None, field_name=None, geo_field_type=None):
"""
@@ -462,35 +395,6 @@ class GeoQuerySet(QuerySet):
return procedure_args, geo_field
- def _spatial_aggregate(self, aggregate, field_name=None,
- geo_field_type=None, tolerance=0.05):
- """
- DRY routine for calling aggregate spatial stored procedures and
- returning their result to the caller of the function.
- """
- # Getting the field the geographic aggregate will be called on.
- geo_field = self._geo_field(field_name)
- if not geo_field:
- raise TypeError('%s aggregate only available on GeometryFields.' % aggregate.name)
-
- # Checking if there are any geo field type limitations on this
- # aggregate (e.g. ST_Makeline only operates on PointFields).
- if geo_field_type is not None and not isinstance(geo_field, geo_field_type):
- raise TypeError('%s aggregate may only be called on %ss.' % (aggregate.name, geo_field_type.__name__))
-
- # Getting the string expression of the field name, as this is the
- # argument taken by `Aggregate` objects.
- agg_col = field_name or geo_field.name
-
- # Adding any keyword parameters for the Aggregate object. Oracle backends
- # in particular need an additional `tolerance` parameter.
- agg_kwargs = {}
- if connections[self.db].ops.oracle:
- agg_kwargs['tolerance'] = tolerance
-
- # Calling the QuerySet.aggregate, and returning only the value of the aggregate.
- return self.aggregate(geoagg=aggregate(agg_col, **agg_kwargs))['geoagg']
-
def _spatial_attribute(self, att, settings, field_name=None, model_att=None):
"""
DRY routine for calling a spatial stored procedure on a geometry column
diff --git a/docs/ref/contrib/gis/geoquerysets.txt b/docs/ref/contrib/gis/geoquerysets.txt
index d4b83e86c8..9a42bd7a15 100644
--- a/docs/ref/contrib/gis/geoquerysets.txt
+++ b/docs/ref/contrib/gis/geoquerysets.txt
@@ -1216,72 +1216,6 @@ Returns the number of points in the first linestring in the
geometry field in a ``num_points`` attribute on each element of
the ``GeoQuerySet``; otherwise sets with ``None``.
-Spatial Aggregates
-==================
-
-Aggregate Methods
------------------
-
-.. deprecated:: 1.8
-
- Aggregate methods are now deprecated. Prefer using their function-based
- equivalents.
-
-``collect``
-~~~~~~~~~~~
-
-.. method:: GeoQuerySet.collect(**kwargs)
-
-.. deprecated:: 1.8
-
- Use the :class:`Collect` aggregate instead.
-
-Shortcut for ``aggregate(Collect(<field>))``.
-
-``extent``
-~~~~~~~~~~
-
-.. method:: GeoQuerySet.extent(**kwargs)
-
-.. deprecated:: 1.8
-
- Use the :class:`Extent` aggregate instead.
-
-Shortcut for ``aggregate(Extent(<field>))``.
-
-``extent3d``
-~~~~~~~~~~~~
-
-.. method:: GeoQuerySet.extent3d(**kwargs)
-
-.. deprecated:: 1.8
-
- Use the :class:`Extent` aggregate instead.
-
-Shortcut for ``aggregate(Extent3D(<field>))``.
-
-``make_line``
-~~~~~~~~~~~~~
-
-.. method:: GeoQuerySet.make_line(**kwargs)
-
-.. deprecated:: 1.8
-
- Use the :class:`MakeLine` aggregate instead.
-
-Shortcut for ``aggregate(MakeLine(<field>))``.
-
-``unionagg``
-~~~~~~~~~~~~
-
-.. method:: GeoQuerySet.unionagg(**kwargs)
-
-.. deprecated:: 1.8
-
- Use the :class:`Union` aggregate instead.
-
-Shortcut for ``aggregate(Union(<field>))``.
-
Aggregate Functions
-------------------
diff --git a/docs/releases/1.2.txt b/docs/releases/1.2.txt
index 368c436b39..1e36d4888b 100644
--- a/docs/releases/1.2.txt
+++ b/docs/releases/1.2.txt
@@ -358,8 +358,7 @@ Support for 3D geometry fields was added, and may be enabled
by setting the :attr:`~django.contrib.gis.db.models.GeometryField.dim`
keyword to 3 in your :class:`~django.contrib.gis.db.models.GeometryField`.
The :class:`~django.contrib.gis.db.models.Extent3D` aggregate
-and :meth:`~django.contrib.gis.db.models.GeoQuerySet.extent3d` ``GeoQuerySet``
-method were added as a part of this feature.
+and ``extent3d()`` ``GeoQuerySet`` method were added as a part of this feature.
The following :class:`~django.contrib.gis.db.models.GeoQuerySet`
methods are new in 1.2:
diff --git a/tests/gis_tests/geo3d/tests.py b/tests/gis_tests/geo3d/tests.py
index 31b440be4a..156b59da09 100644
--- a/tests/gis_tests/geo3d/tests.py
+++ b/tests/gis_tests/geo3d/tests.py
@@ -12,9 +12,7 @@ from django.contrib.gis.gdal import HAS_GDAL
from django.contrib.gis.geos import GEOSGeometry, LineString, Point, Polygon
from django.test import TestCase, ignore_warnings, skipUnlessDBFeature
from django.utils._os import upath
-from django.utils.deprecation import (
- RemovedInDjango20Warning, RemovedInDjango110Warning,
-)
+from django.utils.deprecation import RemovedInDjango20Warning
from .models import (
City3D, Interstate2D, Interstate3D, InterstateProj2D, InterstateProj3D,
@@ -217,7 +215,6 @@ class Geo3DTest(Geo3DLoadingHelper, TestCase):
self.assertSetEqual({p.ewkt for p in ref_union}, {p.ewkt for p in union})
@skipUnlessDBFeature("supports_3d_functions")
- @ignore_warnings(category=RemovedInDjango110Warning)
def test_extent(self):
"""
Testing the Extent3D aggregate for 3D models.
@@ -225,16 +222,13 @@ class Geo3DTest(Geo3DLoadingHelper, TestCase):
self._load_city_data()
# `SELECT ST_Extent3D(point) FROM geo3d_city3d;`
ref_extent3d = (-123.305196, -41.315268, 14, 174.783117, 48.462611, 1433)
- extent1 = City3D.objects.aggregate(Extent3D('point'))['point__extent3d']
- extent2 = City3D.objects.extent3d()
+ extent = City3D.objects.aggregate(Extent3D('point'))['point__extent3d']
def check_extent3d(extent3d, tol=6):
for ref_val, ext_val in zip(ref_extent3d, extent3d):
self.assertAlmostEqual(ref_val, ext_val, tol)
- for e3d in [extent1, extent2]:
- check_extent3d(e3d)
- self.assertIsNone(City3D.objects.none().extent3d())
+ check_extent3d(extent)
self.assertIsNone(City3D.objects.none().aggregate(Extent3D('point'))['point__extent3d'])
@ignore_warnings(category=RemovedInDjango20Warning)
diff --git a/tests/gis_tests/geoapp/feeds.py b/tests/gis_tests/geoapp/feeds.py
index f2ebc46109..57d2d74866 100644
--- a/tests/gis_tests/geoapp/feeds.py
+++ b/tests/gis_tests/geoapp/feeds.py
@@ -23,8 +23,8 @@ class TestGeoRSS2(TestGeoRSS1):
def geometry(self, obj):
# This should attach a <georss:box> element for the extent of
# of the cities in the database. This tuple came from
- # calling `City.objects.extent()` -- we can't do that call here
- # because `extent` is not implemented for MySQL/Oracle.
+ # calling `City.objects.aggregate(Extent())` -- we can't do that call
+ # here because `Extent` is not implemented for MySQL/Oracle.
return (-123.30, -41.32, 174.78, 48.46)
def item_geometry(self, item):
diff --git a/tests/gis_tests/geoapp/tests.py b/tests/gis_tests/geoapp/tests.py
index 0d6ee0362f..0dbf3fa5c5 100644
--- a/tests/gis_tests/geoapp/tests.py
+++ b/tests/gis_tests/geoapp/tests.py
@@ -13,9 +13,7 @@ from django.core.management import call_command
from django.db import connection
from django.test import TestCase, ignore_warnings, skipUnlessDBFeature
from django.utils import six
-from django.utils.deprecation import (
- RemovedInDjango20Warning, RemovedInDjango110Warning,
-)
+from django.utils.deprecation import RemovedInDjango20Warning
from ..utils import no_oracle, oracle, postgis, spatialite
from .models import (
@@ -493,11 +491,9 @@ class GeoQuerySetTest(TestCase):
self.assertIsInstance(country.envelope, Polygon)
@skipUnlessDBFeature("supports_extent_aggr")
- @ignore_warnings(category=RemovedInDjango110Warning)
def test_extent(self):
"""
- Testing the (deprecated) `extent` GeoQuerySet method and the Extent
- aggregate.
+ Testing the `Extent` aggregate.
"""
# Reference query:
# `SELECT ST_extent(point) FROM geoapp_city WHERE (name='Houston' or name='Dallas');`
@@ -505,13 +501,9 @@ class GeoQuerySetTest(TestCase):
expected = (-96.8016128540039, 29.7633724212646, -95.3631439208984, 32.782058715820)
qs = City.objects.filter(name__in=('Houston', 'Dallas'))
- extent1 = qs.extent()
- extent2 = qs.aggregate(Extent('point'))['point__extent']
-
- for extent in (extent1, extent2):
- for val, exp in zip(extent, expected):
- self.assertAlmostEqual(exp, val, 4)
- self.assertIsNone(City.objects.filter(name=('Smalltown')).extent())
+ extent = qs.aggregate(Extent('point'))['point__extent']
+ for val, exp in zip(extent, expected):
+ self.assertAlmostEqual(exp, val, 4)
self.assertIsNone(City.objects.filter(name=('Smalltown')).aggregate(Extent('point'))['point__extent'])
@skipUnlessDBFeature("supports_extent_aggr")
@@ -651,11 +643,9 @@ class GeoQuerySetTest(TestCase):
for ptown in [ptown1, ptown2]:
self.assertEqual('<Point><coordinates>-104.609252,38.255001</coordinates></Point>', ptown.kml)
- @ignore_warnings(category=RemovedInDjango110Warning)
def test_make_line(self):
"""
- Testing the (deprecated) `make_line` GeoQuerySet method and the MakeLine
- aggregate.
+ Testing the `MakeLine` aggregate.
"""
if not connection.features.supports_make_line_aggr:
# Only PostGIS has support for the MakeLine aggregate. For other
@@ -666,9 +656,6 @@ class GeoQuerySetTest(TestCase):
)
return
- # Ensuring that a `TypeError` is raised on models without PointFields.
- self.assertRaises(TypeError, State.objects.make_line)
- self.assertRaises(TypeError, Country.objects.make_line)
# MakeLine on an inappropriate field returns simply None
self.assertIsNone(State.objects.aggregate(MakeLine('poly'))['poly__makeline'])
# Reference query:
@@ -681,11 +668,11 @@ class GeoQuerySetTest(TestCase):
)
# We check for equality with a tolerance of 10e-5 which is a lower bound
# of the precisions of ref_line coordinates
- line1 = City.objects.make_line()
- line2 = City.objects.aggregate(MakeLine('point'))['point__makeline']
- for line in (line1, line2):
- self.assertTrue(ref_line.equals_exact(line, tolerance=10e-5),
- "%s != %s" % (ref_line, line))
+ line = City.objects.aggregate(MakeLine('point'))['point__makeline']
+ self.assertTrue(
+ ref_line.equals_exact(line, tolerance=10e-5),
+ "%s != %s" % (ref_line, line)
+ )
@skipUnlessDBFeature("has_num_geom_method")
def test_num_geom(self):
@@ -863,33 +850,25 @@ class GeoQuerySetTest(TestCase):
# but this seems unexpected and should be investigated to determine the cause.
@skipUnlessDBFeature("has_unionagg_method")
@no_oracle
- @ignore_warnings(category=RemovedInDjango110Warning)
def test_unionagg(self):
"""
- Testing the (deprecated) `unionagg` (aggregate union) GeoQuerySet method
- and the Union aggregate.
+ Testing the `Union` aggregate.
"""
tx = Country.objects.get(name='Texas').mpoly
# Houston, Dallas -- Ordering may differ depending on backend or GEOS version.
union1 = fromstr('MULTIPOINT(-96.801611 32.782057,-95.363151 29.763374)')
union2 = fromstr('MULTIPOINT(-95.363151 29.763374,-96.801611 32.782057)')
qs = City.objects.filter(point__within=tx)
- self.assertRaises(TypeError, qs.unionagg, 'name')
self.assertRaises(ValueError, qs.aggregate, Union('name'))
# Using `field_name` keyword argument in one query and specifying an
# order in the other (which should not be used because this is
# an aggregate method on a spatial column)
- u1 = qs.unionagg(field_name='point')
- u2 = qs.order_by('name').unionagg()
- u3 = qs.aggregate(Union('point'))['point__union']
- u4 = qs.order_by('name').aggregate(Union('point'))['point__union']
+ u1 = qs.aggregate(Union('point'))['point__union']
+ u2 = qs.order_by('name').aggregate(Union('point'))['point__union']
tol = 0.00001
self.assertTrue(union1.equals_exact(u1, tol) or union2.equals_exact(u1, tol))
self.assertTrue(union1.equals_exact(u2, tol) or union2.equals_exact(u2, tol))
- self.assertTrue(union1.equals_exact(u3, tol) or union2.equals_exact(u3, tol))
- self.assertTrue(union1.equals_exact(u4, tol) or union2.equals_exact(u4, tol))
qs = City.objects.filter(name='NotACity')
- self.assertIsNone(qs.unionagg(field_name='point'))
self.assertIsNone(qs.aggregate(Union('point'))['point__union'])
def test_within_subquery(self):
diff --git a/tests/gis_tests/relatedapp/tests.py b/tests/gis_tests/relatedapp/tests.py
index 19b0f89eab..14828455fb 100644
--- a/tests/gis_tests/relatedapp/tests.py
+++ b/tests/gis_tests/relatedapp/tests.py
@@ -4,10 +4,9 @@ from django.contrib.gis.db.models import F, Collect, Count, Extent, Union
from django.contrib.gis.geometry.backend import Geometry
from django.contrib.gis.geos import GEOSGeometry, MultiPoint, Point
from django.db import connection
-from django.test import TestCase, ignore_warnings, skipUnlessDBFeature
+from django.test import TestCase, skipUnlessDBFeature
from django.test.utils import override_settings
from django.utils import timezone
-from django.utils.deprecation import RemovedInDjango110Warning
from ..utils import no_oracle
from .models import (
@@ -64,17 +63,16 @@ class RelatedGeoModelTest(TestCase):
check_pnt(GEOSGeometry(wkt, srid), qs[0].location.point)
@skipUnlessDBFeature("supports_extent_aggr")
- @ignore_warnings(category=RemovedInDjango110Warning)
def test_related_extent_aggregate(self):
- "Testing the `extent` GeoQuerySet aggregates on related geographic models."
+ "Testing the `Extent` aggregate on related geographic models."
# This combines the Extent and Union aggregates into one query
aggs = City.objects.aggregate(Extent('location__point'))
# One for all locations, one that excludes New Mexico (Roswell).
all_extent = (-104.528056, 29.763374, -79.460734, 40.18476)
txpa_extent = (-97.516111, 29.763374, -79.460734, 40.18476)
- e1 = City.objects.extent(field_name='location__point')
- e2 = City.objects.exclude(state='NM').extent(field_name='location__point')
+ e1 = City.objects.aggregate(Extent('location__point'))['location__point__extent']
+ e2 = City.objects.exclude(state='NM').aggregate(Extent('location__point'))['location__point__extent']
e3 = aggs['location__point__extent']
# The tolerance value is to four decimal places because of differences
@@ -98,9 +96,8 @@ class RelatedGeoModelTest(TestCase):
)
@skipUnlessDBFeature("has_unionagg_method")
- @ignore_warnings(category=RemovedInDjango110Warning)
def test_related_union_aggregate(self):
- "Testing the `unionagg` GeoQuerySet aggregates on related geographic models."
+ "Testing the `Union` aggregate on related geographic models."
# This combines the Extent and Union aggregates into one query
aggs = City.objects.aggregate(Union('location__point'))
@@ -114,14 +111,14 @@ class RelatedGeoModelTest(TestCase):
# The second union aggregate is for a union
# query that includes limiting information in the WHERE clause (in other
- # words a `.filter()` precedes the call to `.unionagg()`).
+ # words a `.filter()` precedes the call to `.aggregate(Union()`).
ref_u1 = MultiPoint(p1, p2, p4, p5, p3, srid=4326)
ref_u2 = MultiPoint(p2, p3, srid=4326)
- u1 = City.objects.unionagg(field_name='location__point')
+ u1 = City.objects.aggregate(Union('location__point'))['location__point__union']
u2 = City.objects.exclude(
name__in=('Roswell', 'Houston', 'Dallas', 'Fort Worth'),
- ).unionagg(field_name='location__point')
+ ).aggregate(Union('location__point'))['location__point__union']
u3 = aggs['location__point__union']
self.assertEqual(type(u1), MultiPoint)
self.assertEqual(type(u3), MultiPoint)
@@ -291,11 +288,9 @@ class RelatedGeoModelTest(TestCase):
self.assertIsNone(b.author)
@skipUnlessDBFeature("supports_collect_aggr")
- @ignore_warnings(category=RemovedInDjango110Warning)
def test_collect(self):
"""
- Testing the (deprecated) `collect` GeoQuerySet method and `Collect`
- aggregate.
+ Testing the `Collect` aggregate.
"""
# Reference query:
# SELECT AsText(ST_Collect("relatedapp_location"."point")) FROM "relatedapp_city" LEFT OUTER JOIN
@@ -306,14 +301,11 @@ class RelatedGeoModelTest(TestCase):
'-95.363151 29.763374,-96.801611 32.782057)'
)
- c1 = City.objects.filter(state='TX').collect(field_name='location__point')
- c2 = City.objects.filter(state='TX').aggregate(Collect('location__point'))['location__point__collect']
-
- for coll in (c1, c2):
- # Even though Dallas and Ft. Worth share same point, Collect doesn't
- # consolidate -- that's why 4 points in MultiPoint.
- self.assertEqual(4, len(coll))
- self.assertTrue(ref_geom.equals(coll))
+ coll = City.objects.filter(state='TX').aggregate(Collect('location__point'))['location__point__collect']
+ # Even though Dallas and Ft. Worth share same point, Collect doesn't
+ # consolidate -- that's why 4 points in MultiPoint.
+ self.assertEqual(4, len(coll))
+ self.assertTrue(ref_geom.equals(coll))
def test15_invalid_select_related(self):
"Testing doing select_related on the related name manager of a unique FK. See #13934."