Skip to content
This repository has been archived by the owner on Feb 7, 2019. It is now read-only.

Commit

Permalink
test_models tests passing; Major clean-up required yet
Browse files Browse the repository at this point in the history
  • Loading branch information
maennel committed Dec 28, 2016
1 parent e732deb commit c09ab57
Show file tree
Hide file tree
Showing 8 changed files with 175 additions and 295 deletions.
8 changes: 2 additions & 6 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,10 @@ language: python
python: "2.7"

env:
- TOX_ENV=py27-django18-pg
- TOX_ENV=py27-django18-sqlite
- TOX_ENV=py27-django19-pg
- TOX_ENV=py27-django19-sqlite
- TOX_ENV=py34-django18-pg
- TOX_ENV=py34-django18-sqlite
- TOX_ENV=py34-django19-pg
- TOX_ENV=py34-django19-sqlite
- TOX_ENV=py36-django19-pg
- TOX_ENV=py36-django19-sqlite

# Enable PostgreSQL usage
addons:
Expand Down
3 changes: 1 addition & 2 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@

[tox]
envlist =
py{27,34}-django{18,19}-{sqlite,pg}
py{27,36}-django{19}-{sqlite,pg}

[testenv]
deps =
coverage
django18: django>=1.8,<1.9
django19: django>=1.9,<2.0
pg: psycopg2
commands =
Expand Down
9 changes: 4 additions & 5 deletions versions/deletion.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,12 +135,11 @@ def related_objects(self, related, objs):
Gets a QuerySet of current objects related to ``objs`` via the relation ``related``.
"""
if VERSION >= (1, 8):
related_model = related.related_model
else:
related_model = related.model
from versions.models import Versionable

related_model = related.related_model
manager = related_model._base_manager
if issubclass(related_model, versions.models.Versionable):
if issubclass(related_model, Versionable):
manager = manager.current
return manager.using(self.using).filter(
**{"%s__in" % related.field.name: objs}
Expand Down
350 changes: 122 additions & 228 deletions versions/descriptors.py

Large diffs are not rendered by default.

32 changes: 11 additions & 21 deletions versions/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,17 @@
from django.db.models.sql.datastructures import Join
from django.db.models.sql.where import ExtraWhere, WhereNode

if VERSION[:2] >= (1, 9):
# With Django 1.9 related descriptor classes have been renamed:
# ReverseSingleRelatedObjectDescriptor => ForwardManyToOneDescriptor
# ForeignRelatedObjectsDescriptor => ReverseManyToOneDescriptor
# ReverseManyRelatedObjectsDescriptor => ManyToManyDescriptor
# ManyRelatedObjectsDescriptor => ManyToManyDescriptor
# (new) => ReverseOneToOneDescriptor
# from django.db.models.fields.related import (ForwardManyToOneDescriptor, ReverseManyToOneDescriptor,
# ManyToManyDescriptor, ReverseOneToOneDescriptor)
from descriptors import (VersionedForwardManyToOneDescriptor,
VersionedReverseManyToOneDescriptor,
VersionedManyToManyDescriptor)
else:
from descriptors import (VersionedReverseSingleRelatedObjectDescriptor,
VersionedForeignRelatedObjectsDescriptor,
VersionedReverseManyRelatedObjectsDescriptor,
VersionedManyRelatedObjectsDescriptor)
# from django.db.models.fields.related import (ReverseSingleRelatedObjectDescriptor,
# ReverseManyRelatedObjectsDescriptor, ManyToManyField,
# ManyRelatedObjectsDescriptor, create_many_related_manager,
# ForeignRelatedObjectsDescriptor, RECURSIVE_RELATIONSHIP_CONSTANT)
# With Django 1.9 related descriptor classes have been renamed:
# ReverseSingleRelatedObjectDescriptor => ForwardManyToOneDescriptor
# ForeignRelatedObjectsDescriptor => ReverseManyToOneDescriptor
# ReverseManyRelatedObjectsDescriptor => ManyToManyDescriptor
# ManyRelatedObjectsDescriptor => ManyToManyDescriptor
# (new) => ReverseOneToOneDescriptor
# from django.db.models.fields.related import (ForwardManyToOneDescriptor, ReverseManyToOneDescriptor,
# ManyToManyDescriptor, ReverseOneToOneDescriptor)
from descriptors import (VersionedForwardManyToOneDescriptor,
VersionedReverseManyToOneDescriptor,
VersionedManyToManyDescriptor)
from models import Versionable


Expand Down
59 changes: 31 additions & 28 deletions versions/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,25 @@
from collections import namedtuple

from django import VERSION
from django.db.models.fields.related_descriptors import ForwardManyToOneDescriptor, ReverseManyToOneDescriptor, \
ManyToManyDescriptor, create_forward_many_to_many_manager
from django.utils.functional import cached_property

from versions.descriptors import VersionedForwardManyToOneDescriptor, VersionedReverseManyToOneDescriptor, \
VersionedManyToManyDescriptor
from versions.util import get_utc_now

from django.db.models.sql.datastructures import Join
from django.apps.registry import apps
from django.core.exceptions import SuspiciousOperation, ObjectDoesNotExist
from django.core.exceptions import SuspiciousOperation, ObjectDoesNotExist, FieldDoesNotExist
from django.db import models, router, transaction
from django.db.models.base import Model
from django.db.models import Q
from django.db.models.constants import LOOKUP_SEP
from django.db.models.fields.related import ForeignKey, ManyToManyField, RECURSIVE_RELATIONSHIP_CONSTANT

from django.db.models.query import QuerySet
if VERSION[:2] >= (1, 9):
from django.db.models.query import ModelIterable
else:
from django.db.models.query import ValuesListQuerySet, ValuesQuerySet
from django.db.models.query import ModelIterable
from django.db.models.sql import Query
from django.db.models.sql.where import ExtraWhere, WhereNode
from django.utils.timezone import utc
Expand Down Expand Up @@ -503,15 +505,10 @@ def _fetch_all(self):
"""
if self._result_cache is None:
self._result_cache = list(self.iterator())
if VERSION[:2] >= (1, 9):
# TODO: Do we have to test for ValuesListIterable, ValuesIterable, and FlatValuesListIterable here?
if self._iterable_class == ModelIterable:
for x in self._result_cache:
self._set_item_querytime(x)
else:
if not isinstance(self, ValuesListQuerySet):
for x in self._result_cache:
self._set_item_querytime(x)
# TODO: Do we have to test for ValuesListIterable, ValuesIterable, and FlatValuesListIterable here?
if self._iterable_class == ModelIterable:
for x in self._result_cache:
self._set_item_querytime(x)
if self._prefetch_related_lookups and not self._prefetch_done:
self._prefetch_related_objects()

Expand Down Expand Up @@ -601,7 +598,7 @@ def __init__(self, *args, **kwargs):

def contribute_to_class(self, cls, name, virtual_only=False):
super(VersionedForeignKey, self).contribute_to_class(cls, name, virtual_only)
setattr(cls, self.name, VersionedReverseSingleRelatedObjectDescriptor(self))
setattr(cls, self.name, VersionedForwardManyToOneDescriptor(self))

def contribute_to_related_class(self, cls, related):
"""
Expand All @@ -612,7 +609,7 @@ def contribute_to_related_class(self, cls, related):
super(VersionedForeignKey, self).contribute_to_related_class(cls, related)
accessor_name = related.get_accessor_name()
if hasattr(cls, accessor_name):
setattr(cls, accessor_name, VersionedForeignRelatedObjectsDescriptor(related))
setattr(cls, accessor_name, VersionedReverseManyToOneDescriptor(related))

def get_extra_restriction(self, where_class, alias, remote_alias):
"""
Expand Down Expand Up @@ -677,7 +674,7 @@ def contribute_to_class(self, cls, name):

# Overwrite the descriptor
if hasattr(cls, self.name):
setattr(cls, self.name, VersionedReverseManyRelatedObjectsDescriptor(self))
setattr(cls, self.name, VersionedManyToManyDescriptor(self))

def contribute_to_related_class(self, cls, related):
"""
Expand All @@ -686,7 +683,7 @@ def contribute_to_related_class(self, cls, related):
super(VersionedManyToManyField, self).contribute_to_related_class(cls, related)
accessor_name = related.get_accessor_name()
if accessor_name and hasattr(cls, accessor_name):
descriptor = VersionedManyRelatedObjectsDescriptor(related, accessor_name)
descriptor = VersionedManyToManyDescriptor(related, accessor_name)
setattr(cls, accessor_name, descriptor)
if hasattr(cls._meta, 'many_to_many_related') and isinstance(cls._meta.many_to_many_related, list):
cls._meta.many_to_many_related.append(descriptor)
Expand Down Expand Up @@ -740,8 +737,10 @@ def create_versioned_many_to_many_intermediary_model(field, cls, field_name):
})


class VersionedReverseSingleRelatedObjectDescriptor(ReverseSingleRelatedObjectDescriptor):
class VersionedReverseSingleRelatedObjectDescriptor(ForwardManyToOneDescriptor):
"""
Django1.9 compatibility note: ReverseSingleRelatedObjectDescriptor becomes ForwardManyToOneDescriptor
A ReverseSingleRelatedObjectDescriptor-typed object gets inserted, when a ForeignKey
is defined in a Django model. This is one part of the analogue for versioned items.
Expand Down Expand Up @@ -782,8 +781,10 @@ def __get__(self, instance, instance_type=None):
return current_elt.__class__.objects.current.get(identity=current_elt.identity)


class VersionedForeignRelatedObjectsDescriptor(ForeignRelatedObjectsDescriptor):
class VersionedForeignRelatedObjectsDescriptor(ReverseManyToOneDescriptor):
"""
Django 1.9 compatibility note: ForeignRelatedObjectsDescriptor becomes ReverseManyToOneDescriptor
This descriptor generates the manager class that is used on the related object of a ForeignKey relation
(i.e. the reverse-ForeignKey field manager).
"""
Expand Down Expand Up @@ -815,7 +816,7 @@ def get_queryset(self):
def get_prefetch_queryset(self, instances, queryset=None):
"""
Overrides RelatedManager's implementation of get_prefetch_queryset so that it works
nicely with VersionedQuerySets. It ensures that identities and time-limited where
nicely with VersionedQuerySets. It ensures that identities and time-limited where
clauses are used when selecting related reverse foreign key objects.
"""
if queryset is None:
Expand Down Expand Up @@ -893,7 +894,8 @@ def create_versioned_many_related_manager(superclass, rel):
:param rel: Contains the ManyToMany relation
:return: A subclass of ManyRelatedManager and Versionable
"""
many_related_manager_klass = create_many_related_manager(superclass, rel)
# Django 1.9 compatibility note: create_many_related_manager becomes create_forward_many_to_many_manager
many_related_manager_klass = create_forward_many_to_many_manager(superclass, rel)

class VersionedManyRelatedManager(many_related_manager_klass):
def __init__(self, *args, **kwargs):
Expand Down Expand Up @@ -1016,8 +1018,10 @@ def remove_at(self, timestamp, *objs):
return VersionedManyRelatedManager


class VersionedReverseManyRelatedObjectsDescriptor(ReverseManyRelatedObjectsDescriptor):
class VersionedReverseManyRelatedObjectsDescriptor(ManyToManyDescriptor):
"""
Django 1.9 compatibility note: ReverseManyRelatedObjectsDescriptor becomes ManyToManyDescriptor (as well)
Beside having a very long name, this class is useful when it comes to versioning the
ReverseManyRelatedObjectsDescriptor (huhu!!). The main part is the exposure of the
'related_manager_cls' property
Expand Down Expand Up @@ -1103,8 +1107,10 @@ def related_manager_cls(self):
)


class VersionedManyRelatedObjectsDescriptor(ManyRelatedObjectsDescriptor):
class VersionedManyRelatedObjectsDescriptor(ManyToManyDescriptor):
"""
Django 1.9 compatibility note: ManyRelatedObjectsDescriptor becomes ManyToManyDescriptor
Beside having a very long name, this class is useful when it comes to versioning the
ManyRelatedObjectsDescriptor (huhu!!). The main part is the exposure of the
'related_manager_cls' property
Expand Down Expand Up @@ -1475,10 +1481,7 @@ def get_all_m2m_field_names(self):
opts = self._meta
rel_field_names = [field.attname for field in opts.many_to_many]
if hasattr(opts, 'many_to_many_related'):
if VERSION[:2] >= (1, 9):
rel_field_names += [rel.reverse for rel in opts.many_to_many_related]
else:
rel_field_names += [rel.via_field_name for rel in opts.many_to_many_related]
rel_field_names += [rel.reverse for rel in opts.many_to_many_related]

return rel_field_names

Expand Down
7 changes: 3 additions & 4 deletions versions_tests/tests/test_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

APP_NAME = 'versions_tests'

if django.VERSION[:2] >= (1, 7):
class TestMigrations(TestCase):
def test_makemigrations_command(self):
call_command('makemigrations', APP_NAME, dry_run=True, verbosity=0)
class TestMigrations(TestCase):
def test_makemigrations_command(self):
call_command('makemigrations', APP_NAME, dry_run=True, verbosity=0)
2 changes: 1 addition & 1 deletion versions_tests/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1959,7 +1959,7 @@ def setUp(self):
self.c1.team_set = []

self.team10 = Team.objects.current.get(identity=self.team10.identity).clone()
self.c10.team_set = []
self.c10.team_set.clear()
self.t3 = get_utc_now()

def test_t1_relations_for_cloned_referenced_object(self):
Expand Down

0 comments on commit c09ab57

Please sign in to comment.