Ticket #17681: emptyqs_removal.diff

File emptyqs_removal.diff, 12.8 KB (added by akaariai, 3 years ago)
  • django/contrib/auth/models.py

    diff --git a/django/contrib/auth/models.py b/django/contrib/auth/models.py
    index eb39868..fb5ad10 100644
    a b class AnonymousUser(object): 
    408408    is_staff = False
    409409    is_active = False
    410410    is_superuser = False
    411     _groups = EmptyManager()
    412     _user_permissions = EmptyManager()
     411    _groups = EmptyManager(model=User)
     412    _user_permissions = EmptyManager(model=User)
    413413
    414414    def __init__(self):
    415415        pass
  • django/db/models/manager.py

    diff --git a/django/db/models/manager.py b/django/db/models/manager.py
    index e1bbf6e..28a320a 100644
    a b  
    11import copy
    22from django.db import router
    3 from django.db.models.query import QuerySet, EmptyQuerySet, insert_query, RawQuerySet
     3from django.db.models.query import QuerySet, insert_query, RawQuerySet
    44from django.db.models import signals
    55from django.db.models.fields import FieldDoesNotExist
    66
    class Manager(object): 
    4646    # Tracks each time a Manager instance is created. Used to retain order.
    4747    creation_counter = 0
    4848
    49     def __init__(self):
     49    def __init__(self, model=None):
    5050        super(Manager, self).__init__()
    5151        self._set_creation_counter()
    52         self.model = None
     52        self.model = model
    5353        self._inherited = False
    5454        self._db = None
    5555
    class Manager(object): 
    101101    #######################
    102102
    103103    def get_empty_query_set(self):
    104         return EmptyQuerySet(self.model, using=self._db)
     104        return QuerySet(self.model, using=self.db).none()
    105105
    106106    def get_query_set(self):
    107107        """Returns a new QuerySet object.  Subclasses can override this method
  • django/db/models/query.py

    diff --git a/django/db/models/query.py b/django/db/models/query.py
    index 41c24c7..0d91ce9 100644
    a b class QuerySet(object): 
    3131    """
    3232    def __init__(self, model=None, query=None, using=None):
    3333        self.model = model
    34         # EmptyQuerySet instantiates QuerySet with model as None
    3534        self._db = using
    3635        self.query = query or sql.Query(self.model)
    3736        self._result_cache = None
    class QuerySet(object): 
    210209
    211210    def __and__(self, other):
    212211        self._merge_sanity_check(other)
    213         if isinstance(other, EmptyQuerySet):
    214             return other._clone()
    215212        combined = self._clone()
    216213        combined.query.combine(other.query, sql.AND)
    217214        return combined
    class QuerySet(object): 
    219216    def __or__(self, other):
    220217        self._merge_sanity_check(other)
    221218        combined = self._clone()
    222         if isinstance(other, EmptyQuerySet):
    223             return combined
    224219        combined.query.combine(other.query, sql.OR)
    225220        return combined
    226221
    class QuerySet(object): 
    600595        """
    601596        Returns an empty QuerySet.
    602597        """
    603         return self._clone(klass=EmptyQuerySet)
     598        c = self._clone()
     599        c.query.set_empty()
     600        return c
    604601
    605602    ##################################################################
    606603    # PUBLIC METHODS THAT ALTER ATTRIBUTES AND RETURN A NEW QUERYSET #
    class DateQuerySet(QuerySet): 
    11161113            c._setup_query()
    11171114        return c
    11181115
    1119 
    1120 class EmptyQuerySet(QuerySet):
    1121     def __init__(self, model=None, query=None, using=None):
    1122         super(EmptyQuerySet, self).__init__(model, query, using)
    1123         self._result_cache = []
    1124 
    1125     def __and__(self, other):
    1126         return self._clone()
    1127 
    1128     def __or__(self, other):
    1129         return other._clone()
    1130 
    1131     def count(self):
    1132         return 0
    1133 
    1134     def delete(self):
    1135         pass
    1136 
    1137     def _clone(self, klass=None, setup=False, **kwargs):
    1138         c = super(EmptyQuerySet, self)._clone(klass, setup=setup, **kwargs)
    1139         c._result_cache = []
    1140         return c
    1141 
    1142     def iterator(self):
    1143         # This slightly odd construction is because we need an empty generator
    1144         # (it raises StopIteration immediately).
    1145         yield iter([]).next()
    1146 
    1147     def all(self):
    1148         """
    1149         Always returns EmptyQuerySet.
    1150         """
    1151         return self
    1152 
    1153     def filter(self, *args, **kwargs):
    1154         """
    1155         Always returns EmptyQuerySet.
    1156         """
    1157         return self
    1158 
    1159     def exclude(self, *args, **kwargs):
    1160         """
    1161         Always returns EmptyQuerySet.
    1162         """
    1163         return self
    1164 
    1165     def complex_filter(self, filter_obj):
    1166         """
    1167         Always returns EmptyQuerySet.
    1168         """
    1169         return self
    1170 
    1171     def select_related(self, *fields, **kwargs):
    1172         """
    1173         Always returns EmptyQuerySet.
    1174         """
    1175         return self
    1176 
    1177     def annotate(self, *args, **kwargs):
    1178         """
    1179         Always returns EmptyQuerySet.
    1180         """
    1181         return self
    1182 
    1183     def order_by(self, *field_names):
    1184         """
    1185         Always returns EmptyQuerySet.
    1186         """
    1187         return self
    1188 
    1189     def distinct(self, fields=None):
    1190         """
    1191         Always returns EmptyQuerySet.
    1192         """
    1193         return self
    1194 
    1195     def extra(self, select=None, where=None, params=None, tables=None,
    1196               order_by=None, select_params=None):
    1197         """
    1198         Always returns EmptyQuerySet.
    1199         """
    1200         assert self.query.can_filter(), \
    1201                 "Cannot change a query once a slice has been taken"
    1202         return self
    1203 
    1204     def reverse(self):
    1205         """
    1206         Always returns EmptyQuerySet.
    1207         """
    1208         return self
    1209 
    1210     def defer(self, *fields):
    1211         """
    1212         Always returns EmptyQuerySet.
    1213         """
    1214         return self
    1215 
    1216     def only(self, *fields):
    1217         """
    1218         Always returns EmptyQuerySet.
    1219         """
    1220         return self
    1221 
    1222     def update(self, **kwargs):
    1223         """
    1224         Don't update anything.
    1225         """
    1226         return 0
    1227 
    1228     def aggregate(self, *args, **kwargs):
    1229         """
    1230         Return a dict mapping the aggregate names to None
    1231         """
    1232         for arg in args:
    1233             kwargs[arg.default_alias] = arg
    1234         return dict([(key, None) for key in kwargs])
    1235 
    1236     # EmptyQuerySet is always an empty result in where-clauses (and similar
    1237     # situations).
    1238     value_annotation = False
    1239 
    12401116def get_klass_info(klass, max_depth=0, cur_depth=0, requested=None,
    12411117                   only_load=None, local_only=False):
    12421118    """
  • django/db/models/sql/compiler.py

    diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py
    index 72948f9..6808b34 100644
    a b class SQLCompiler(object): 
    6060        """
    6161        if with_limits and self.query.low_mark == self.query.high_mark:
    6262            return '', ()
    63 
    6463        self.pre_sql_setup()
    6564        # After executing the query, we must get rid of any joins the query
    6665        # setup created. So, take note of alias counts before the query ran.
  • django/db/models/sql/query.py

    diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
    index a78df34..825647d 100644
    a b from django.db.models.sql.constants import * 
    2222from django.db.models.sql.datastructures import EmptyResultSet, Empty, MultiJoin
    2323from django.db.models.sql.expressions import SQLEvaluator
    2424from django.db.models.sql.where import (WhereNode, Constraint, EverythingNode,
    25     ExtraWhere, AND, OR)
     25    ExtraWhere, AND, OR, NothingNode)
    2626from django.core.exceptions import FieldError
    2727
    2828__all__ = ['Query', 'RawQuery']
    class Query(object): 
    426426
    427427        return number
    428428
     429    def set_empty(self):
     430        """
     431        Turn this queryset into one which will return nothing when evaluated.
     432        """
     433        self.where = self.where_class()
     434        self.where.add(NothingNode(), AND)
     435
    429436    def has_results(self, using):
    430437        q = self.clone()
    431438        q.add_extra({'a': 1}, None, None, None, None, None)
  • django/db/models/sql/where.py

    diff --git a/django/db/models/sql/where.py b/django/db/models/sql/where.py
    index 1455ba6..36cf82d 100644
    a b class WhereNode(tree.Node): 
    3636    """
    3737    default = AND
    3838
     39    def __init__(self, *args, **kwargs):
     40        super(WhereNode, self).__init__(*args, **kwargs)
     41
    3942    def add(self, data, connector):
    4043        """
    4144        Add a node to the where-tree. If the data is a list or tuple, it is
    class WhereNode(tree.Node): 
    252255                if hasattr(child[3], 'relabel_aliases'):
    253256                    child[3].relabel_aliases(change_map)
    254257
     258
    255259class EverythingNode(object):
    256260    """
    257261    A node that matches everything.
  • docs/ref/models/querysets.txt

    diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt
    index 103cae1..886cbf6 100644
    a b none 
    601601
    602602.. method:: none()
    603603
    604 Returns an ``EmptyQuerySet`` — a ``QuerySet`` subclass that always evaluates to
    605 an empty list. This can be used in cases where you know that you should return
     604Returns a ``QuerySet`` that always evaluates to an empty list. No query should
     605be executed. This can be used in cases where you know that you should return
    606606an empty result set and your caller is expecting a ``QuerySet`` object (instead
    607607of returning an empty list, for example.)
    608608
  • tests/modeltests/get_object_or_404/tests.py

    diff --git a/tests/modeltests/get_object_or_404/tests.py b/tests/modeltests/get_object_or_404/tests.py
    index 280720f..992a2f3 100644
    a b class GetObjectOr404Tests(TestCase): 
    5353            get_object_or_404, Author.objects.all()
    5454        )
    5555
    56         # Using an EmptyQuerySet raises a Http404 error.
     56        # Using a empty queryset raises a Http404 error.
    5757        self.assertRaises(Http404,
    5858            get_object_or_404, Article.objects.none(), title__contains="Run"
    5959        )
  • tests/modeltests/lookup/tests.py

    diff --git a/tests/modeltests/lookup/tests.py b/tests/modeltests/lookup/tests.py
    index 3571e21..5333402 100644
    a b class LookupTests(TestCase): 
    436436            ])
    437437
    438438    def test_none(self):
    439        # none() returns an EmptyQuerySet that behaves like any other QuerySet object
     439       # none() returns an empty queryset that behaves like any other QuerySet object
    440440        self.assertQuerysetEqual(Article.objects.none(), [])
    441441        self.assertQuerysetEqual(
    442442            Article.objects.none().filter(headline__startswith='Article'), [])
  • tests/regressiontests/queries/tests.py

    diff --git a/tests/regressiontests/queries/tests.py b/tests/regressiontests/queries/tests.py
    index ded3e8f..a706c82 100644
    a b from django.conf import settings 
    88from django.core.exceptions import FieldError
    99from django.db import DatabaseError, connection, connections, DEFAULT_DB_ALIAS
    1010from django.db.models import Count
    11 from django.db.models.query import Q, ITER_CHUNK_SIZE, EmptyQuerySet
     11from django.db.models.query import Q, ITER_CHUNK_SIZE
    1212from django.test import TestCase, skipUnlessDBFeature
    1313from django.utils import unittest
    1414from django.utils.datastructures import SortedDict
    class Queries1Tests(BaseQuerysetTest): 
    655655            ['<Item: one>', '<Item: two>']
    656656        )
    657657
    658     def test_ticket7235(self):
    659         # An EmptyQuerySet should not raise exceptions if it is filtered.
    660         q = EmptyQuerySet()
    661         self.assertQuerysetEqual(q.all(), [])
    662         self.assertQuerysetEqual(q.filter(x=10), [])
    663         self.assertQuerysetEqual(q.exclude(y=3), [])
    664         self.assertQuerysetEqual(q.complex_filter({'pk': 1}), [])
    665         self.assertQuerysetEqual(q.select_related('spam', 'eggs'), [])
    666         self.assertQuerysetEqual(q.annotate(Count('eggs')), [])
    667         self.assertQuerysetEqual(q.order_by('-pub_date', 'headline'), [])
    668         self.assertQuerysetEqual(q.distinct(), [])
    669         self.assertQuerysetEqual(
    670             q.extra(select={'is_recent': "pub_date > '2006-01-01'"}),
    671             []
    672         )
    673         q.query.low_mark = 1
    674         self.assertRaisesMessage(
    675             AssertionError,
    676             'Cannot change a query once a slice has been taken',
    677             q.extra, select={'is_recent': "pub_date > '2006-01-01'"}
    678         )
    679         self.assertQuerysetEqual(q.reverse(), [])
    680         self.assertQuerysetEqual(q.defer('spam', 'eggs'), [])
    681         self.assertQuerysetEqual(q.only('spam', 'eggs'), [])
    682 
    683658    def test_ticket7791(self):
    684659        # There were "issues" when ordering and distinct-ing on fields related
    685660        # via ForeignKeys.
    class CloneTests(TestCase): 
    16131588
    16141589class EmptyQuerySetTests(TestCase):
    16151590    def test_emptyqueryset_values(self):
    1616         # #14366 -- Calling .values() on an EmptyQuerySet and then cloning that
     1591        # #14366 -- Calling .values() on an empty queryset and then cloning that
    16171592        # should not cause an error"
    16181593        self.assertQuerysetEqual(
    16191594            Number.objects.none().values('num').order_by('num'), []
Back to Top