Removed a bunch of deprecated code.

This commit is contained in:
Carl Meyer 2013-01-27 13:30:31 -08:00
parent a9ac3685fb
commit 6ae66e0153
7 changed files with 9 additions and 277 deletions

View file

@ -11,7 +11,8 @@ tip (unreleased)
.. _BitBucket: https://bitbucket.org/carljm/django-model-utils/overview
.. _GitHub: https://github.com/carljm/django-model-utils/
- Removed deprecated ``ChoiceEnum`` class.
- Removed deprecated ``ChoiceEnum``, ``InheritanceCastModel``,
``InheritanceCastManager``, and ``manager_from``.
- Added ``UpdateOrCreateMixin`` for custom queryset subclasses. Thanks Antti
Kaihola.

View file

@ -305,14 +305,6 @@ it's safe to use as your default manager for the model.
internally. Due to `Django bug #16855`_, this currently means that it
will override any previous ``select_related`` calls on the ``QuerySet``.
.. note::
``InheritanceManager`` requires Django 1.2 or later. Previous versions of
django-model-utils included ``InheritanceCastModel``, an alternative (and
inferior) approach to this problem that is Django 1.1
compatible. ``InheritanceCastModel`` will remain in django-model-utils
until support for Django 1.1 is removed, but it is no longer documented and
its use in new code is discouraged.
.. _contributed by Jeff Elmore: http://jeffelmore.org/2010/11/11/automatic-downcasting-of-inherited-models-in-django/
.. _Django bug #16855: https://code.djangoproject.com/ticket/16855
@ -396,13 +388,6 @@ directly on the manager::
Post.objects.published()
Post.objects.by_author(user=request.user).unpublished()
.. note::
Previous versions of django-model-utils included ``manager_from``, a
function that solved the same problem as ``PassThroughManager``. The
``manager_from`` approach created dynamic ``QuerySet`` subclasses on the
fly, which broke pickling of those querysets. For this reason,
``PassThroughManager`` is recommended instead.
UpdateOrCreateMixin

View file

@ -3,8 +3,6 @@ from datetime import datetime
from django.db import models
from django.conf import settings
from model_utils import Choices
try:
from django.utils.timezone import now as now

View file

@ -1,11 +1,7 @@
from types import ClassType
import sys
import warnings
from django.contrib.contenttypes.models import ContentType
from django.db import IntegrityError, models, transaction
from django.db.models.fields.related import OneToOneField
from django.db.models.manager import Manager
from django.db.models.query import QuerySet
from django.core.exceptions import ObjectDoesNotExist
@ -67,26 +63,6 @@ class InheritanceManager(models.Manager):
return self.get_query_set().select_subclasses().get(*args, **kwargs)
class InheritanceCastMixin(object):
def cast(self):
results = tuple(self.values_list('pk', 'real_type'))
type_to_pks = {}
for pk, real_type_id in results:
type_to_pks.setdefault(real_type_id, []).append(pk)
content_types = ContentType.objects.in_bulk(type_to_pks.keys())
pk_to_child = {}
for real_type_id, pks in type_to_pks.iteritems():
content_type = content_types[real_type_id]
child_type = content_type.model_class()
children = child_type._default_manager.in_bulk(pks)
for pk, child in children.iteritems():
pk_to_child[pk] = child
children = []
# sort children into same order as parents where returned
for pk, real_type_id in results:
children.append(pk_to_child[pk])
return children
class QueryManager(models.Manager):
use_for_related_fields = True
@ -180,62 +156,6 @@ def unpickle_pass_through_manager_for_queryset_class(base, queryset_cls):
return cls.__new__(cls)
def manager_from(*mixins, **kwds):
"""
Returns a Manager instance with extra methods, also available and
chainable on generated querysets.
(By George Sakkis, originally posted at
http://djangosnippets.org/snippets/2117/)
:param mixins: Each ``mixin`` can be either a class or a function. The
generated manager and associated queryset subclasses extend the mixin
classes and include the mixin functions (as methods).
:keyword queryset_cls: The base queryset class to extend from
(``django.db.models.query.QuerySet`` by default).
:keyword manager_cls: The base manager class to extend from
(``django.db.models.manager.Manager`` by default).
"""
warnings.warn(
"manager_from is pending deprecation; use PassThroughManager instead.",
PendingDeprecationWarning,
stacklevel=2)
# collect separately the mixin classes and methods
bases = [kwds.get('queryset_cls', QuerySet)]
methods = {}
for mixin in mixins:
if isinstance(mixin, (ClassType, type)):
bases.append(mixin)
else:
try: methods[mixin.__name__] = mixin
except AttributeError:
raise TypeError('Mixin must be class or function, not %s' %
mixin.__class__)
# create the QuerySet subclass
id = hash(mixins + tuple(kwds.iteritems()))
new_queryset_cls = type('Queryset_%d' % id, tuple(bases), methods)
# create the Manager subclass
bases[0] = manager_cls = kwds.get('manager_cls', Manager)
new_manager_cls = type('Manager_%d' % id, tuple(bases), methods)
# and finally override new manager's get_query_set
super_get_query_set = manager_cls.get_query_set
def get_query_set(self):
# first honor the super manager's get_query_set
qs = super_get_query_set(self)
# and then try to bless the returned queryset by reassigning it to the
# newly created Queryset class, though this may not be feasible
if not issubclass(new_queryset_cls, qs.__class__):
raise TypeError('QuerySet subclass conflict: cannot determine a '
'unique class for queryset instance')
qs.__class__ = new_queryset_cls
return qs
new_manager_cls.get_query_set = get_query_set
return new_manager_cls()
class UpdateOrCreateMixin(object):
def update_or_create(self, **kwargs):
"""

View file

@ -1,15 +1,11 @@
import warnings
from datetime import datetime
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.utils.translation import ugettext_lazy as _
from django.db.models.fields import FieldDoesNotExist
from django.core.exceptions import ImproperlyConfigured
from model_utils.managers import manager_from, InheritanceCastMixin, \
QueryManager
from model_utils.managers import QueryManager
from model_utils.fields import AutoCreatedField, AutoLastModifiedField, \
StatusField, MonitorField
@ -19,42 +15,6 @@ except ImportError:
now = datetime.now
class InheritanceCastModel(models.Model):
"""
An abstract base class that provides a ``real_type`` FK to ContentType.
For use in trees of inherited models, to be able to downcast
parent instances to their child types.
Pending deprecation; use InheritanceManager instead.
"""
real_type = models.ForeignKey(ContentType, editable=False, null=True)
objects = manager_from(InheritanceCastMixin)
def __init__(self, *args, **kwargs):
warnings.warn(
"InheritanceCastModel is pending deprecation. "
"Use InheritanceManager instead.",
PendingDeprecationWarning,
stacklevel=2)
super(InheritanceCastModel, self).__init__(*args, **kwargs)
def save(self, *args, **kwargs):
if not self.id:
self.real_type = self._get_real_type()
super(InheritanceCastModel, self).save(*args, **kwargs)
def _get_real_type(self):
return ContentType.objects.get_for_model(type(self))
def cast(self):
return self.real_type.get_object_for_this_type(pk=self.pk)
class Meta:
abstract = True
class TimeStampedModel(models.Model):
"""

View file

@ -1,34 +1,13 @@
from django.db import models
from django.utils.translation import ugettext_lazy as _
from model_utils.models import InheritanceCastModel, TimeStampedModel, StatusModel, TimeFramedModel
from model_utils.managers import QueryManager, manager_from, InheritanceManager, PassThroughManager, UpdateOrCreateMixin
from model_utils.models import TimeStampedModel, StatusModel, TimeFramedModel
from model_utils.managers import QueryManager, InheritanceManager, PassThroughManager, UpdateOrCreateMixin
from model_utils.fields import SplitField, MonitorField
from model_utils import Choices
class InheritParent(InheritanceCastModel):
non_related_field_using_descriptor = models.FileField(upload_to="test")
normal_field = models.TextField()
pass
class InheritChild(InheritParent):
non_related_field_using_descriptor_2 = models.FileField(upload_to="test")
normal_field_2 = models.TextField()
pass
class InheritChild2(InheritParent):
non_related_field_using_descriptor_3 = models.FileField(upload_to="test")
normal_field_3 = models.TextField()
pass
class InheritanceManagerTestRelated(models.Model):
pass
@ -178,19 +157,6 @@ class FeaturedManager(models.Manager):
class Entry(models.Model):
author = models.CharField(max_length=20)
published = models.BooleanField()
feature = models.BooleanField(default=False)
objects = manager_from(AuthorMixin, PublishedMixin, unpublished)
broken = manager_from(PublishedMixin, manager_cls=FeaturedManager)
featured = manager_from(PublishedMixin,
manager_cls=FeaturedManager,
queryset_cls=ByAuthorQuerySet)
class DudeQuerySet(models.query.QuerySet):
def abiding(self):
return self.filter(abides=True)

View file

@ -1,6 +1,6 @@
from __future__ import with_statement
import pickle, warnings
import pickle
from datetime import date, datetime, timedelta
@ -9,18 +9,16 @@ from django.db.models.fields import FieldDoesNotExist
from django.core.exceptions import ImproperlyConfigured
from django.test import TestCase
from django.contrib.contenttypes.models import ContentType
from model_utils import Choices
from model_utils.fields import get_excerpt, MonitorField
from model_utils.managers import QueryManager, manager_from
from model_utils.managers import QueryManager
from model_utils.models import StatusModel, TimeFramedModel
from model_utils.tests.models import (
InheritParent, InheritChild, InheritChild2, InheritanceManagerTestRelated,
InheritanceManagerTestRelated,
InheritanceManagerTestParent, InheritanceManagerTestChild1,
InheritanceManagerTestChild2, TimeStamp, Post, Article, Status,
StatusPlainTuple, TimeFrame, Monitored, StatusManagerAdded,
TimeFrameManagerAdded, Entry, Dude, SplitFieldAbstractParent, Car, Spot,
TimeFrameManagerAdded, Dude, SplitFieldAbstractParent, Car, Spot,
Person)
@ -277,57 +275,6 @@ class IdentifierChoicesTests(ChoicesTests):
"(2, 'DELETED', 'is deleted'))")
class InheritanceCastModelTests(TestCase):
def setUp(self):
self.parent = InheritParent.objects.create()
self.child = InheritChild.objects.create()
def test_parent_real_type(self):
self.assertEquals(self.parent.real_type,
ContentType.objects.get_for_model(InheritParent))
def test_child_real_type(self):
self.assertEquals(self.child.real_type,
ContentType.objects.get_for_model(InheritChild))
def test_cast(self):
obj = InheritParent.objects.get(pk=self.child.pk).cast()
self.assertEquals(obj.__class__, InheritChild)
def test_pending_deprecation(self):
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always")
InheritParent()
self.assertEqual(len(w), 1)
assert issubclass(w[-1].category, PendingDeprecationWarning)
class InheritanceCastQuerysetTests(TestCase):
def setUp(self):
self.child = InheritChild.objects.create()
self.child2 = InheritChild2.objects.create()
def test_cast_manager(self):
self.assertEquals(set(InheritParent.objects.cast()),
set([self.child, self.child2]))
def test_cast(self):
parent = InheritParent.objects.create()
obj = InheritParent.objects.filter(pk=self.child.pk).cast()[0]
self.assertEquals(obj.__class__, InheritChild)
self.assertEquals(set(InheritChild2.objects.all().cast()),
set([self.child2]))
self.assertEquals(set(InheritParent.objects.all().cast()),
set([parent, self.child, self.child2]))
class InheritanceManagerTests(TestCase):
def setUp(self):
@ -579,51 +526,6 @@ if introspector:
class ManagerFromTests(TestCase):
def setUp(self):
Entry.objects.create(author='George', published=True)
Entry.objects.create(author='George', published=False)
Entry.objects.create(author='Paul', published=True, feature=True)
def test_chaining(self):
self.assertEqual(Entry.objects.by_author('George').published().count(),
1)
def test_function(self):
self.assertEqual(Entry.objects.unpublished().count(), 1)
def test_typecheck(self):
self.assertRaises(TypeError, manager_from, 'somestring')
def test_custom_get_query_set(self):
self.assertEqual(Entry.featured.published().count(), 1)
def test_cant_reconcile_qs_class(self):
self.assertRaises(TypeError, Entry.broken.all)
def test_queryset_pickling_fails(self):
qs = Entry.objects.all()
def dump_load():
pqs = pickle.dumps(qs)
pickle.loads(pqs)
self.assertRaises(pickle.PicklingError, dump_load)
def test_pending_deprecation(self):
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always")
manager_from()
self.assertEqual(len(w), 1)
assert issubclass(w[-1].category, PendingDeprecationWarning)
class PassThroughManagerTests(TestCase):
def setUp(self):
Dude.objects.create(name='The Dude', abides=True, has_rug=False)