diff --git a/.gitignore b/.gitignore index e63dffc..8699683 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ *.egg-info/ *.egg/ .coverage +coverage.xml .project .idea/ .pydevproject diff --git a/.travis.yml b/.travis.yml index 175a66b..5601d0a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,98 +10,98 @@ python: - "3.5" - "3.6" env: - - DJANGO="Django>=1.4,<1.5" - - DJANGO="Django>=1.5,<1.6" - - DJANGO="Django>=1.6,<1.7" - - DJANGO="Django>=1.7,<1.8" - - DJANGO="Django>=1.8,<1.9" - - DJANGO="Django>=1.9,<1.10" - - DJANGO="Django>=1.10,<1.11" - - DJANGO="Django>=1.11,<1.12" - - DJANGO="https://github.com/django/django/tarball/master" + - TOXENV="django14" + - TOXENV="django15" + - TOXENV="django16" + - TOXENV="django17" + - TOXENV="django18" + - TOXENV="django19" + - TOXENV="django110" + - TOXENV="django111" + - TOXENV="djangodev" matrix: + fast_finish: true exclude: - - python: "3.6" - env: DJANGO="Django>=1.4,<1.5" - - python: "3.6" - env: DJANGO="Django>=1.5,<1.6" - - python: "3.6" - env: DJANGO="Django>=1.6,<1.7" - - python: "3.6" - env: DJANGO="Django>=1.7,<1.8" - - python: "3.6" - env: DJANGO="Django>=1.8,<1.9" - - python: "3.6" - env: DJANGO="Django>=1.9,<1.10" - - python: "3.6" - env: DJANGO="Django>=1.10,<1.11" + - python: "3.6" + env: TOXENV="django14" + - python: "3.6" + env: TOXENV="django15" + - python: "3.6" + env: TOXENV="django16" + - python: "3.6" + env: TOXENV="django17" + - python: "3.6" + env: TOXENV="django18" + - python: "3.6" + env: TOXENV="django19" + - python: "3.6" + env: TOXENV="django110" - - python: "3.5" - env: DJANGO="Django>=1.4,<1.5" - - python: "3.5" - env: DJANGO="Django>=1.5,<1.6" - - python: "3.5" - env: DJANGO="Django>=1.6,<1.7" - - python: "3.5" - env: DJANGO="Django>=1.7,<1.8" + - python: "3.5" + env: TOXENV="django14" + - python: "3.5" + env: TOXENV="django15" + - python: "3.5" + env: TOXENV="django16" + - python: "3.5" + env: TOXENV="django17" - - python: "3.4" - env: DJANGO="Django>=1.4,<1.5" - - python: "3.4" - env: DJANGO="Django>=1.9,<1.10" - - python: "3.4" - env: DJANGO="Django>=1.10,<1.11" - - python: "3.4" - env: DJANGO="Django>=1.11,<1.12" + - python: "3.4" + env: TOXENV="django14" + - python: "3.4" + env: TOXENV="django19" + - python: "3.4" + env: TOXENV="django110" + - python: "3.4" + env: TOXENV="django111" - - python: "3.3" - env: DJANGO="Django>=1.4,<1.5" - - python: "3.3" - env: DJANGO="Django>=1.9,<1.10" - - python: "3.3" - env: DJANGO="Django>=1.10,<1.11" - - python: "3.3" - env: DJANGO="Django>=1.11,<1.12" - - python: "3.3" - env: DJANGO="https://github.com/django/django/tarball/master" + - python: "3.3" + env: TOXENV="django14" + - python: "3.3" + env: TOXENV="django19" + - python: "3.3" + env: TOXENV="django110" + - python: "3.3" + env: TOXENV="django111" + - python: "3.3" + env: TOXENV="djangodev" - - python: "3.2" - env: DJANGO="Django>=1.4,<1.5" - - python: "3.2" - env: DJANGO="Django>=1.9,<1.10" - - python: "3.2" - env: DJANGO="Django>=1.10,<1.11" - - python: "3.2" - env: DJANGO="Django>=1.11,<1.12" - - python: "3.2" - env: DJANGO="https://github.com/django/django/tarball/master" + - python: "3.2" + env: TOXENV="django14" + - python: "3.2" + env: TOXENV="django19" + - python: "3.2" + env: TOXENV="django110" + - python: "3.2" + env: TOXENV="django111" + - python: "3.2" + env: TOXENV="djangodev" + + - python: "2.6" + env: TOXENV="django17" + - python: "2.6" + env: TOXENV="django18" + - python: "2.6" + env: TOXENV="django19" + - python: "2.6" + env: TOXENV="django110" + - python: "2.6" + env: TOXENV="django111" + - python: "2.6" + env: TOXENV="djangodev" - - python: "2.6" - env: DJANGO="Django>=1.7,<1.8" - - python: "2.6" - env: DJANGO="Django>=1.8,<1.9" - - python: "2.6" - env: DJANGO="Django>=1.9,<1.10" - - python: "2.6" - env: DJANGO="Django>=1.10,<1.11" - - python: "2.6" - env: DJANGO="Django>=1.11,<1.12" - - python: "2.6" - env: DJANGO="https://github.com/django/django/tarball/master" allow_failures: - - env: DJANGO="https://github.com/django/django/tarball/master" + - env: TOXENV="djangodev" before_install: -- pip install codecov - -install: - - pip install -q $DJANGO coverage==3.6 +- pip install codecov coverage==3.6 tox script: - - coverage run --source=polymorphic runtests.py + - tox after_success: +- coverage xml -i - codecov branches: diff --git a/README.rst b/README.rst index 4c769cf..f72b011 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,4 @@ -.. image:: https://travis-ci.org/django-polymorphic/django-polymorphic.png?branch=master +.. image:: https://travis-ci.org/django-polymorphic/django-polymorphic.svg?branch=master :target: http://travis-ci.org/django-polymorphic/django-polymorphic .. image:: https://img.shields.io/pypi/v/django-polymorphic.svg :target: https://pypi.python.org/pypi/django-polymorphic/ diff --git a/polymorphic/query.py b/polymorphic/query.py index 0d716ff..209d7a2 100644 --- a/polymorphic/query.py +++ b/polymorphic/query.py @@ -39,6 +39,8 @@ def _polymorhic_iterator(queryset, base_iter): base_result_objects = [] reached_end = False + # Make sure the base iterator is read in chunks instead of + # reading it completely, in case our caller read only a few objects. for i in range(Polymorphic_QuerySet_objects_per_request): try: o = next(base_iter) @@ -47,17 +49,17 @@ def _polymorhic_iterator(queryset, base_iter): reached_end = True break - real_results = queryset._get_real_instances(base_result_objects) + real_results = queryset._get_real_instances(base_result_objects) - for o in real_results: - yield o + for o in real_results: + yield o - if reached_end: - return + if reached_end: + return if django.VERSION >= (1, 9): - + # We ignore this on django < 1.9, as ModelIterable didn't yet exist. from django.db.models.query import ModelIterable class PolymorphicModelIterable(ModelIterable): @@ -115,8 +117,9 @@ class PolymorphicQuerySet(QuerySet): def __init__(self, *args, **kwargs): super(PolymorphicQuerySet, self).__init__(*args, **kwargs) if django.VERSION >= (1, 9): + # On django < 1.9 we override the iterator() method instead self._iterable_class = PolymorphicModelIterable - # init our queryset object member variables + self.polymorphic_disabled = False # A parallel structure to django.db.models.query.Query.deferred_loading, # which we maintain with the untranslated field names passed to @@ -460,8 +463,22 @@ class PolymorphicQuerySet(QuerySet): return resultlist if django.VERSION < (1, 9): - # Before Django 1.9 ModelIterable functionality was implemented in `iterator` method + # On django 1.9+, we can define self._iterator_class instead of iterator() def iterator(self): + """ + This function is used by Django 1.8 and earlier for all object retrieval. + By overriding it, we modify the objects that this queryset returns + when it is evaluated (or its get method or other object-returning methods are called). + + Here we do the same as:: + + base_result_objects = list(super(PolymorphicQuerySet, self).iterator()) + real_results = self._get_real_instances(base_result_objects) + for o in real_results: yield o + + but it requests the objects in chunks from the database, + with Polymorphic_QuerySet_objects_per_request per chunk + """ base_iter = super(PolymorphicQuerySet, self).iterator() # disabled => work just like a normal queryset diff --git a/tox.ini b/tox.ini index ee02b1b..cff1ea7 100644 --- a/tox.ini +++ b/tox.ini @@ -5,14 +5,13 @@ envlist= py32-django{15,16,17,18}, py33-django{15,16,17,18}, py34-django{15,16,17,18,19,110,111}, - py35-django{18,19,110,111} - py35-django{18,19,110,111}, - py36-django{111}, - # py33-django-dev, + py35-django{18,19,110,111,dev}, + py36-django{111,dev}, docs, [testenv] deps = + coverage == 3.6 django14: Django >= 1.4, < 1.5 django15: Django >= 1.5, < 1.6 django16: Django >= 1.6, < 1.7 @@ -21,9 +20,9 @@ deps = django19: Django >= 1.9, < 1.10 django110: Django >= 1.10, < 1.11 django111: Django >= 1.11, < 1.12 - django-dev: https://github.com/django/django/tarball/master + djangodev: https://github.com/django/django/tarball/master commands= - python runtests.py + coverage run --source polymorphic runtests.py [testenv:docs] deps=Sphinx