text: from __future__ import unicode_literals
  
  from unittest import skipUnless
  
  import django
  from django.db import models
  from django.test import TestCase
  
  from tests.models import (
      InheritanceManagerTestRelated, InheritanceManagerTestGrandChild1,
      InheritanceManagerTestGrandChild1_2, InheritanceManagerTestParent,
      InheritanceManagerTestChild1,
      InheritanceManagerTestChild2, TimeFrame, InheritanceManagerTestChild3
  )
  
  
  class InheritanceManagerTests(TestCase):
      def setUp(self):
          self.child1 = InheritanceManagerTestChild1.objects.create()
          self.child2 = InheritanceManagerTestChild2.objects.create()
          self.grandchild1 = InheritanceManagerTestGrandChild1.objects.create()
          self.grandchild1_2 = \
              InheritanceManagerTestGrandChild1_2.objects.create()
  
      def get_manager(self):
          return InheritanceManagerTestParent.objects
  
      def test_normal(self):
          children = set([
              InheritanceManagerTestParent(pk=self.child1.pk),
              InheritanceManagerTestParent(pk=self.child2.pk),
              InheritanceManagerTestParent(pk=self.grandchild1.pk),
              InheritanceManagerTestParent(pk=self.grandchild1_2.pk),
          ])
          self.assertEqual(set(self.get_manager().all()), children)
  
      def test_select_all_subclasses(self):
          children = set([self.child1, self.child2])
          children.add(self.grandchild1)
          children.add(self.grandchild1_2)
          self.assertEqual(
              set(self.get_manager().select_subclasses()), children)
  
      def test_select_subclasses_invalid_relation(self):
          """
          If an invalid relation string is provided, we can provide the user
          with a list which is valid, rather than just have the select_related()
          raise an AttributeError further in.
          """
          regex = '^.+? is not in the discovered subclasses, tried:.+$'
          with self.assertRaisesRegexp(ValueError, regex):
              self.get_manager().select_subclasses('user')
  
      def test_select_specific_subclasses(self):
          children = set([
              self.child1,
              InheritanceManagerTestParent(pk=self.child2.pk),
              InheritanceManagerTestChild1(pk=self.grandchild1.pk),
              InheritanceManagerTestChild1(pk=self.grandchild1_2.pk),
          ])
          self.assertEqual(
              set(
                  self.get_manager().select_subclasses(
                      "inheritancemanagertestchild1")
              ),
              children,
          )
  
      def test_select_specific_grandchildren(self):
          children = set([
              InheritanceManagerTestParent(pk=self.child1.pk),
              InheritanceManagerTestParent(pk=self.child2.pk),
              self.grandchild1,
              InheritanceManagerTestParent(pk=self.grandchild1_2.pk),
          ])
          self.assertEqual(
              set(
                  self.get_manager().select_subclasses(
                      "inheritancemanagertestchild1__inheritancemanagertestgrandchild1"
                  )
              ),
              children,
          )
  
      def test_children_and_grandchildren(self):
          children = set([
              self.child1,
              InheritanceManagerTestParent(pk=self.child2.pk),
              self.grandchild1,
              InheritanceManagerTestChild1(pk=self.grandchild1_2.pk),
          ])
          self.assertEqual(
              set(
                  self.get_manager().select_subclasses(
                      "inheritancemanagertestchild1",
                      "inheritancemanagertestchild1__inheritancemanagertestgrandchild1"
                  )
              ),
              children,
          )
  
      def test_get_subclass(self):
          self.assertEqual(
              self.get_manager().get_subclass(pk=self.child1.pk),
              self.child1)
  
      def test_get_subclass_on_queryset(self):
          self.assertEqual(
              self.get_manager().all().get_subclass(pk=self.child1.pk),
              self.child1)
  
      def test_prior_select_related(self):
          with self.assertNumQueries(1):
              obj = self.get_manager().select_related(
                  "inheritancemanagertestchild1").select_subclasses(
                  "inheritancemanagertestchild2").get(pk=self.child1.pk)
              obj.inheritancemanagertestchild1
  
      def test_manually_specifying_parent_fk_including_grandchildren(self):
          """
          given a Model which inherits from another Model, but also declares
          the OneToOne link manually using `related_name` and `parent_link`,
          ensure that the relation names and subclasses are obtained correctly.
          """
          child3 = InheritanceManagerTestChild3.objects.create()
          qs = InheritanceManagerTestParent.objects.all()
          results = qs.select_subclasses().order_by('pk')
  
          expected_objs = [
              self.child1,
              self.child2,
              self.grandchild1,
              self.grandchild1_2,
              child3
          ]
          self.assertEqual(list(results), expected_objs)
  
          expected_related_names = [
              'inheritancemanagertestchild1__inheritancemanagertestgrandchild1',
              'inheritancemanagertestchild1__inheritancemanagertestgrandchild1_2',
              'inheritancemanagertestchild1',
              'inheritancemanagertestchild2',
              'manual_onetoone',  # this was set via parent_link & related_name
          ]
          self.assertEqual(set(results.subclasses),
                           set(expected_related_names))
  
      def test_manually_specifying_parent_fk_single_subclass(self):
          """
          Using a string related_name when the relation is manually defined
          instead of implicit should still work in the same way.
          """
          related_name = 'manual_onetoone'
          child3 = InheritanceManagerTestChild3.objects.create()
          qs = InheritanceManagerTestParent.objects.all()
          results = qs.select_subclasses(related_name).order_by('pk')
  
          expected_objs = [InheritanceManagerTestParent(pk=self.child1.pk),
                           InheritanceManagerTestParent(pk=self.child2.pk),
                           InheritanceManagerTestParent(pk=self.grandchild1.pk),
                           InheritanceManagerTestParent(pk=self.grandchild1_2.pk),
                           child3]
          self.assertEqual(list(results), expected_objs)
          expected_related_names = [related_name]
          self.assertEqual(set(results.subclasses),
                           set(expected_related_names))
  
      def test_filter_on_values_queryset(self):
          queryset = InheritanceManagerTestChild1.objects.values('id').filter(pk=self.child1.pk)
          self.assertEqual(list(queryset), [{'id': self.child1.pk}])
  
      @skipUnless(django.VERSION >= (1, 9, 0), "test only applies to Django 1.9+")
      def test_dj19_values_list_on_select_subclasses(self):
          """
          Using `select_subclasses` in conjunction with `values_list()` raised an
          exception in `_get_sub_obj_recurse()` because the result of `values_list()`
          is either a `tuple` or primitive objects if `flat=True` is specified,
          because no type checking was done prior to fetching child nodes.
  
          Django versions below 1.9 are not affected by this bug.
          """
  
          # Querysets are cast to lists to force immediate evaluation.
          # No exceptions must be thrown.
  
          # No argument to select_subclasses
          objs_1 = list(
              self.get_manager()
                  .select_subclasses()
                  .values_list('id')
          )
  
          # String argument to select_subclasses
          objs_2 = list(
              self.get_manager()
              .select_subclasses(
                  "inheritancemanagertestchild2"
              )
              .values_list('id')
          )
  
          # String argument to select_subclasses
          objs_3 = list(
              self.get_manager()
              .select_subclasses(
                  InheritanceManagerTestChild2
              ).values_list('id')
          )
  
          assert all((
              isinstance(objs_1, list),
              isinstance(objs_2, list),
              isinstance(objs_3, list),
          ))
  
          assert objs_1 == objs_2 == objs_3
  
  
  class InheritanceManagerUsingModelsTests(TestCase):
      def setUp(self):
          self.parent1 = InheritanceManagerTestParent.objects.create()
          self.child1 = InheritanceManagerTestChild1.objects.create()
          self.child2 = InheritanceManagerTestChild2.objects.create()
          self.grandchild1 = InheritanceManagerTestGrandChild1.objects.create()
          self.grandchild1_2 = InheritanceManagerTestGrandChild1_2.objects.create()
  
      def test_select_subclass_by_child_model(self):
          """
          Confirm that passing a child model works the same as passing the
          select_related manually
          """
          objs = InheritanceManagerTestParent.objects.select_subclasses(
              "inheritancemanagertestchild1").order_by('pk')
          objsmodels = InheritanceManagerTestParent.objects.select_subclasses(
              InheritanceManagerTestChild1).order_by('pk')
          self.assertEqual(objs.subclasses, objsmodels.subclasses)
          self.assertEqual(list(objs), list(objsmodels))
  
      def test_select_subclass_by_grandchild_model(self):
          """
          Confirm that passing a grandchild model works the same as passing the
          select_related manually
          """
          objs = InheritanceManagerTestParent.objects.select_subclasses(
              "inheritancemanagertestchild1__inheritancemanagertestgrandchild1") \
              .order_by('pk')
          objsmodels = InheritanceManagerTestParent.objects.select_subclasses(
              InheritanceManagerTestGrandChild1).order_by('pk')
          self.assertEqual(objs.subclasses, objsmodels.subclasses)
          self.assertEqual(list(objs), list(objsmodels))
  
      def test_selecting_all_subclasses_specifically_grandchildren(self):
          """
          A bare select_subclasses() should achieve the same results as doing
          select_subclasses and specifying all possible subclasses.
          This test checks grandchildren, so only works on 1.6>=
          """
          objs = InheritanceManagerTestParent.objects.select_subclasses().order_by('pk')
          objsmodels = InheritanceManagerTestParent.objects.select_subclasses(
              InheritanceManagerTestChild1, InheritanceManagerTestChild2,
              InheritanceManagerTestChild3,
              InheritanceManagerTestGrandChild1,
              InheritanceManagerTestGrandChild1_2).order_by('pk')
          self.assertEqual(set(objs.subclasses), set(objsmodels.subclasses))
          self.assertEqual(list(objs), list(objsmodels))
  
      def test_selecting_all_subclasses_specifically_children(self):
          """
          A bare select_subclasses() should achieve the same results as doing
          select_subclasses and specifying all possible subclasses.
  
          Note: This is sort of the same test as
          `test_selecting_all_subclasses_specifically_grandchildren` but it
          specifically switches what models are used because that happens
          behind the scenes in a bare select_subclasses(), so we need to
          emulate it.
          """
          objs = InheritanceManagerTestParent.objects.select_subclasses().order_by('pk')
  
          models = (InheritanceManagerTestChild1,
                    InheritanceManagerTestChild2,
                    InheritanceManagerTestChild3,
                    InheritanceManagerTestGrandChild1,
                    InheritanceManagerTestGrandChild1_2)
  
          objsmodels = InheritanceManagerTestParent.objects.select_subclasses(
              *models).order_by('pk')
          # order shouldn't matter, I don't think, as long as the resulting
          # queryset (when cast to a list) is the same.
          self.assertEqual(set(objs.subclasses), set(objsmodels.subclasses))
          self.assertEqual(list(objs), list(objsmodels))
  
      def test_select_subclass_just_self(self):
          """
          Passing in the same model as the manager/queryset is bound against
          (ie: the root parent) should have no effect on the result set.
          """
          objsmodels = InheritanceManagerTestParent.objects.select_subclasses(
              InheritanceManagerTestParent).order_by('pk')
          self.assertEqual([], objsmodels.subclasses)
          self.assertEqual(list(objsmodels), [
              InheritanceManagerTestParent(pk=self.parent1.pk),
              InheritanceManagerTestParent(pk=self.child1.pk),
              InheritanceManagerTestParent(pk=self.child2.pk),
              InheritanceManagerTestParent(pk=self.grandchild1.pk),
              InheritanceManagerTestParent(pk=self.grandchild1_2.pk),
          ])
  
      def test_select_subclass_invalid_related_model(self):
          """
          Confirming that giving a stupid model doesn't work.
          """
          regex = '^.+? is not a subclass of .+$'
          with self.assertRaisesRegexp(ValueError, regex):
              InheritanceManagerTestParent.objects.select_subclasses(
                  TimeFrame).order_by('pk')
  
      def test_mixing_strings_and_classes_with_grandchildren(self):
          """
          Given arguments consisting of both strings and model classes,
          ensure the right resolutions take place, accounting for the extra
          depth (grandchildren etc) 1.6> allows.
          """
          objs = InheritanceManagerTestParent.objects.select_subclasses(
              "inheritancemanagertestchild2",
              InheritanceManagerTestGrandChild1_2).order_by('pk')
          expecting = ['inheritancemanagertestchild1__inheritancemanagertestgrandchild1_2',
                       'inheritancemanagertestchild2']
          self.assertEqual(set(objs.subclasses), set(expecting))
          expecting2 = [
              InheritanceManagerTestParent(pk=self.parent1.pk),
              InheritanceManagerTestParent(pk=self.child1.pk),
              InheritanceManagerTestChild2(pk=self.child2.pk),
              InheritanceManagerTestParent(pk=self.grandchild1.pk),
              InheritanceManagerTestGrandChild1_2(pk=self.grandchild1_2.pk),
          ]
          self.assertEqual(list(objs), expecting2)
  
      def test_mixing_strings_and_classes_with_children(self):
          """
          Given arguments consisting of both strings and model classes,
          ensure the right resolutions take place, walking down as far as
          children.
          """
          objs = InheritanceManagerTestParent.objects.select_subclasses(
              "inheritancemanagertestchild2",
              InheritanceManagerTestChild1).order_by('pk')
          expecting = ['inheritancemanagertestchild1',
                       'inheritancemanagertestchild2']
  
          self.assertEqual(set(objs.subclasses), set(expecting))
          expecting2 = [
              InheritanceManagerTestParent(pk=self.parent1.pk),
              InheritanceManagerTestChild1(pk=self.child1.pk),
              InheritanceManagerTestChild2(pk=self.child2.pk),
              InheritanceManagerTestChild1(pk=self.grandchild1.pk),
              InheritanceManagerTestChild1(pk=self.grandchild1_2.pk),
          ]
          self.assertEqual(list(objs), expecting2)
  
      def test_duplications(self):
          """
          Check that even if the same thing is provided as a string and a model
          that the right results are retrieved.
          """
          # mixing strings and models which evaluate to the same thing is fine.
          objs = InheritanceManagerTestParent.objects.select_subclasses(
              "inheritancemanagertestchild2",
              InheritanceManagerTestChild2).order_by('pk')
          self.assertEqual(list(objs), [
              InheritanceManagerTestParent(pk=self.parent1.pk),
              InheritanceManagerTestParent(pk=self.child1.pk),
              InheritanceManagerTestChild2(pk=self.child2.pk),
              InheritanceManagerTestParent(pk=self.grandchild1.pk),
              InheritanceManagerTestParent(pk=self.grandchild1_2.pk),
          ])
  
      def test_child_doesnt_accidentally_get_parent(self):
          """
          Given a Child model which also has an InheritanceManager,
          none of the returned objects should be Parent objects.
          """
          objs = InheritanceManagerTestChild1.objects.select_subclasses(
              InheritanceManagerTestGrandChild1).order_by('pk')
          self.assertEqual([
              InheritanceManagerTestChild1(pk=self.child1.pk),
              InheritanceManagerTestGrandChild1(pk=self.grandchild1.pk),
              InheritanceManagerTestChild1(pk=self.grandchild1_2.pk),
          ], list(objs))
  
      def test_manually_specifying_parent_fk_only_specific_child(self):
          """
          given a Model which inherits from another Model, but also declares
          the OneToOne link manually using `related_name` and `parent_link`,
          ensure that the relation names and subclasses are obtained correctly.
          """
          child3 = InheritanceManagerTestChild3.objects.create()
          results = InheritanceManagerTestParent.objects.all().select_subclasses(
              InheritanceManagerTestChild3).order_by('pk')
  
          expected_objs = [
              InheritanceManagerTestParent(pk=self.parent1.pk),
              InheritanceManagerTestParent(pk=self.child1.pk),
              InheritanceManagerTestParent(pk=self.child2.pk),
              InheritanceManagerTestParent(pk=self.grandchild1.pk),
              InheritanceManagerTestParent(pk=self.grandchild1_2.pk),
              child3
          ]
          self.assertEqual(list(results), expected_objs)
  
          expected_related_names = ['manual_onetoone']
          self.assertEqual(set(results.subclasses),
                           set(expected_related_names))
  
      def test_extras_descend(self):
          """
          Ensure that extra(select=) values are copied onto sub-classes.
          """
          results = InheritanceManagerTestParent.objects.select_subclasses().extra(
              select={'foo': 'id + 1'}
          )
          self.assertTrue(all(result.foo == (result.id + 1) for result in results))
  
  
  class InheritanceManagerRelatedTests(InheritanceManagerTests):
      def setUp(self):
          self.related = InheritanceManagerTestRelated.objects.create()
          self.child1 = InheritanceManagerTestChild1.objects.create(
              related=self.related)
          self.child2 = InheritanceManagerTestChild2.objects.create(
              related=self.related)
          self.grandchild1 = InheritanceManagerTestGrandChild1.objects.create(related=self.related)
          self.grandchild1_2 = InheritanceManagerTestGrandChild1_2.objects.create(related=self.related)
  
      def get_manager(self):
          return self.related.imtests
  
      def test_get_method_with_select_subclasses(self):
          self.assertEqual(
              InheritanceManagerTestParent.objects.select_subclasses().get(
                  id=self.child1.id),
              self.child1)
  
      def test_annotate_with_select_subclasses(self):
          qs = InheritanceManagerTestParent.objects.select_subclasses().annotate(
              models.Count('id'))
          self.assertEqual(qs.get(id=self.child1.id).id__count, 1)
  
      def test_annotate_with_named_arguments_with_select_subclasses(self):
          qs = InheritanceManagerTestParent.objects.select_subclasses().annotate(
              test_count=models.Count('id'))
          self.assertEqual(qs.get(id=self.child1.id).test_count, 1)
  
      def test_annotate_before_select_subclasses(self):
          qs = InheritanceManagerTestParent.objects.annotate(
              models.Count('id')).select_subclasses()
          self.assertEqual(qs.get(id=self.child1.id).id__count, 1)
  
      def test_annotate_with_named_arguments_before_select_subclasses(self):
          qs = InheritanceManagerTestParent.objects.annotate(
              test_count=models.Count('id')).select_subclasses()
          self.assertEqual(qs.get(id=self.child1.id).test_count, 1)
  
      def test_clone_when_inheritance_queryset_selects_subclasses_should_clone_them_too(self):
          qs = InheritanceManagerTestParent.objects.select_subclasses()
          self.assertEqual(qs.subclasses, qs._clone().subclasses)
  