diff --git a/django/contrib/gis/db/models/sql/aggregates.py b/django/contrib/gis/db/models/sql/aggregates.py deleted file mode 100644 index e3fb049cf5..0000000000 --- a/django/contrib/gis/db/models/sql/aggregates.py +++ /dev/null @@ -1,10 +0,0 @@ -from django.db.models.sql import aggregates -from django.db.models.sql.aggregates import * # NOQA - -__all__ = ['Collect', 'Extent', 'Extent3D', 'MakeLine', 'Union'] + aggregates.__all__ - - -warnings.warn( - "django.contrib.gis.db.models.sql.aggregates is deprecated. Use " - "django.contrib.gis.db.models.aggregates instead.", - RemovedInDjango110Warning, stacklevel=2) diff --git a/django/db/models/sql/aggregates.py b/django/db/models/sql/aggregates.py deleted file mode 100644 index 4f74a3b0c0..0000000000 --- a/django/db/models/sql/aggregates.py +++ /dev/null @@ -1,155 +0,0 @@ -""" -Classes to represent the default SQL aggregate functions -""" -import copy -import warnings - -from django.db.models.fields import FloatField, IntegerField -from django.db.models.query_utils import RegisterLookupMixin -from django.utils.deprecation import RemovedInDjango110Warning -from django.utils.functional import cached_property - -__all__ = ['Aggregate', 'Avg', 'Count', 'Max', 'Min', 'StdDev', 'Sum', 'Variance'] - - -warnings.warn( - "django.db.models.sql.aggregates is deprecated. Use " - "django.db.models.aggregates instead.", - RemovedInDjango110Warning, stacklevel=2) - - -class Aggregate(RegisterLookupMixin): - """ - Default SQL Aggregate. - """ - is_ordinal = False - is_computed = False - sql_template = '%(function)s(%(field)s)' - - def __init__(self, col, source=None, is_summary=False, **extra): - """Instantiate an SQL aggregate - - * col is a column reference describing the subject field - of the aggregate. It can be an alias, or a tuple describing - a table and column name. - * source is the underlying field or aggregate definition for - the column reference. If the aggregate is not an ordinal or - computed type, this reference is used to determine the coerced - output type of the aggregate. - * extra is a dictionary of additional data to provide for the - aggregate definition - - Also utilizes the class variables: - * sql_function, the name of the SQL function that implements the - aggregate. - * sql_template, a template string that is used to render the - aggregate into SQL. - * is_ordinal, a boolean indicating if the output of this aggregate - is an integer (e.g., a count) - * is_computed, a boolean indicating if this output of this aggregate - is a computed float (e.g., an average), regardless of the input - type. - """ - self.col = col - self.source = source - self.is_summary = is_summary - self.extra = extra - - # Follow the chain of aggregate sources back until you find an - # actual field, or an aggregate that forces a particular output - # type. This type of this field will be used to coerce values - # retrieved from the database. - tmp = self - - while tmp and isinstance(tmp, Aggregate): - if getattr(tmp, 'is_ordinal', False): - tmp = self._ordinal_aggregate_field - elif getattr(tmp, 'is_computed', False): - tmp = self._computed_aggregate_field - else: - tmp = tmp.source - - self.field = tmp - - # Two fake fields used to identify aggregate types in data-conversion operations. - @cached_property - def _ordinal_aggregate_field(self): - return IntegerField() - - @cached_property - def _computed_aggregate_field(self): - return FloatField() - - def relabeled_clone(self, change_map): - clone = copy.copy(self) - if isinstance(self.col, (list, tuple)): - clone.col = (change_map.get(self.col[0], self.col[0]), self.col[1]) - return clone - - def as_sql(self, compiler, connection): - "Return the aggregate, rendered as SQL with parameters." - params = [] - - if hasattr(self.col, 'as_sql'): - field_name, params = self.col.as_sql(compiler, connection) - elif isinstance(self.col, (list, tuple)): - field_name = '.'.join(compiler(c) for c in self.col) - else: - field_name = compiler(self.col) - - substitutions = { - 'function': self.sql_function, - 'field': field_name - } - substitutions.update(self.extra) - - return self.sql_template % substitutions, params - - def get_group_by_cols(self): - return [] - - @property - def output_field(self): - return self.field - - -class Avg(Aggregate): - is_computed = True - sql_function = 'AVG' - - -class Count(Aggregate): - is_ordinal = True - sql_function = 'COUNT' - sql_template = '%(function)s(%(distinct)s%(field)s)' - - def __init__(self, col, distinct=False, **extra): - super(Count, self).__init__(col, distinct='DISTINCT ' if distinct else '', **extra) - - -class Max(Aggregate): - sql_function = 'MAX' - - -class Min(Aggregate): - sql_function = 'MIN' - - -class StdDev(Aggregate): - is_computed = True - - def __init__(self, col, sample=False, **extra): - super(StdDev, self).__init__(col, **extra) - self.sql_function = 'STDDEV_SAMP' if sample else 'STDDEV_POP' - - -class Sum(Aggregate): - sql_function = 'SUM' - - -class Variance(Aggregate): - is_computed = True - - def __init__(self, col, sample=False, **extra): - super(Variance, self).__init__(col, **extra) - self.sql_function = 'VAR_SAMP' if sample else 'VAR_POP' diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index 9dd666040f..cb1696dd62 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -7,7 +7,6 @@ databases). The abstraction barrier only works one way: this module has to know all about the internals of models in order to get the information it needs. """ import copy -import warnings from collections import Counter, Iterator, Mapping, OrderedDict from itertools import chain, count, product from string import ascii_uppercase @@ -31,7 +30,6 @@ from django.db.models.sql.where import ( AND, OR, ExtraWhere, NothingNode, WhereNode, ) from django.utils import six -from django.utils.deprecation import RemovedInDjango110Warning from django.utils.encoding import force_text from django.utils.tree import Node @@ -214,13 +212,6 @@ class Query(object): self._annotations = OrderedDict() return self._annotations - @property - def aggregates(self): - warnings.warn( - "The aggregates property is deprecated. Use annotations instead.", - RemovedInDjango110Warning, stacklevel=2) - return self.annotations - def __str__(self): """ Returns the query as a string of SQL with the parameter values @@ -973,12 +964,6 @@ class Query(object): alias = seen[int_model] = joins[-1] return alias or seen[None] - def add_aggregate(self, aggregate, model, alias, is_summary): - warnings.warn( - "add_aggregate() is deprecated. Use add_annotation() instead.", - RemovedInDjango110Warning, stacklevel=2) - self.add_annotation(aggregate, alias, is_summary) - def add_annotation(self, annotation, alias, is_summary=False): """ Adds a single annotation expression to the Query @@ -1818,12 +1803,6 @@ class Query(object): """ target[model] = {f.attname for f in fields} - def set_aggregate_mask(self, names): - warnings.warn( - "set_aggregate_mask() is deprecated. Use set_annotation_mask() instead.", - RemovedInDjango110Warning, stacklevel=2) - self.set_annotation_mask(names) - def set_annotation_mask(self, names): "Set the mask of annotations that will actually be returned by the SELECT" if names is None: @@ -1832,12 +1811,6 @@ class Query(object): self.annotation_select_mask = set(names) self._annotation_select_cache = None - def append_aggregate_mask(self, names): - warnings.warn( - "append_aggregate_mask() is deprecated. Use append_annotation_mask() instead.", - RemovedInDjango110Warning, stacklevel=2) - self.append_annotation_mask(names) - def append_annotation_mask(self, names): if self.annotation_select_mask is not None: self.set_annotation_mask(set(names).union(self.annotation_select_mask)) @@ -1874,13 +1847,6 @@ class Query(object): else: return self.annotations - @property - def aggregate_select(self): - warnings.warn( - "aggregate_select() is deprecated. Use annotation_select() instead.", - RemovedInDjango110Warning, stacklevel=2) - return self.annotation_select - @property def extra_select(self): if self._extra_select_cache is not None: diff --git a/tests/aggregation/tests.py b/tests/aggregation/tests.py index a1d12e363e..3fa36bbcb5 100644 --- a/tests/aggregation/tests.py +++ b/tests/aggregation/tests.py @@ -7,13 +7,12 @@ from decimal import Decimal from django.core.exceptions import FieldError from django.db import connection from django.db.models import ( - F, Aggregate, Avg, Count, DecimalField, DurationField, FloatField, Func, - IntegerField, Max, Min, Sum, Value, + F, Avg, Count, DecimalField, DurationField, FloatField, Func, IntegerField, + Max, Min, Sum, Value, ) -from django.test import TestCase, ignore_warnings +from django.test import TestCase from django.test.utils import Approximate, CaptureQueriesContext from django.utils import six, timezone -from django.utils.deprecation import RemovedInDjango110Warning from .models import Author, Book, Publisher, Store @@ -1184,23 +1183,3 @@ class AggregateTestCase(TestCase): ).filter(rating_or_num_awards__gt=F('num_awards')).order_by('num_awards') self.assertQuerysetEqual( qs2, [1, 3], lambda v: v.num_awards) - - @ignore_warnings(category=RemovedInDjango110Warning) - def test_backwards_compatibility(self): - from django.db.models.sql import aggregates as sql_aggregates - - class SqlNewSum(sql_aggregates.Aggregate): - sql_function = 'SUM' - - class NewSum(Aggregate): - name = 'Sum' - - def add_to_query(self, query, alias, col, source, is_summary): - klass = SqlNewSum - aggregate = klass( - col, source=source, is_summary=is_summary, **self.extra) - query.annotations[alias] = aggregate - - qs = Author.objects.values('name').annotate(another_age=NewSum('age') + F('age')) - a = qs.get(name="Adrian Holovaty") - self.assertEqual(a['another_age'], 68)