[Python-modules-commits] [django-model-utils] 01/03: Import django-model-utils_2.5.2.orig.tar.gz

Brian May bam at moszumanska.debian.org
Fri Aug 12 04:52:22 UTC 2016


This is an automated email from the git hooks/post-receive script.

bam pushed a commit to branch master
in repository django-model-utils.

commit 3896a3775fa50d001bf7fe4104550e3055fb2cc0
Author: Brian May <bam at debian.org>
Date:   Fri Aug 12 14:48:49 2016 +1000

    Import django-model-utils_2.5.2.orig.tar.gz
---
 .travis.yml                 | 18 ++++++++-------
 AUTHORS.rst                 |  2 ++
 CHANGES.rst                 | 35 +++++++++++++++++++++++++++--
 CONTRIBUTING.rst            | 15 +++++++------
 MANIFEST.in                 |  3 ++-
 README.rst                  | 26 +++++++++------------
 TODO.rst                    |  4 ----
 docs/managers.rst           | 47 +++-----------------------------------
 docs/utilities.rst          |  2 +-
 model_utils/__init__.py     |  2 +-
 model_utils/managers.py     | 28 ++++++++++++++++++-----
 model_utils/tests/models.py |  5 +++++
 model_utils/tests/tests.py  | 55 ++++++++++++++++++++++++++++++++++++++++++++-
 model_utils/tracker.py      |  6 ++---
 requirements.txt            |  3 +++
 setup.py                    | 24 +++++++++++++-------
 tox.ini                     | 23 ++++++++++---------
 17 files changed, 186 insertions(+), 112 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index b23f12e..6ea0c92 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,6 +6,7 @@ env:
   - TOXENV=py26-django14
   - TOXENV=py26-django15
   - TOXENV=py26-django16
+  - TOXENV=py27-django110
   - TOXENV=py27-django14
   - TOXENV=py27-django15
   - TOXENV=py27-django15_nosouth
@@ -14,20 +15,19 @@ env:
   - TOXENV=py27-django18
   - TOXENV=py27-django19
   - TOXENV=py27-django_trunk
-  - TOXENV=py32-django15
-  - TOXENV=py32-django16
-  - TOXENV=py32-django17
-  - TOXENV=py32-django18
-  - TOXENV=py32-django_trunk
   - TOXENV=py33-django15
   - TOXENV=py33-django16
   - TOXENV=py33-django17
   - TOXENV=py33-django18
-  - TOXENV=py33-django_trunk
+  - TOXENV=py34-django110
   - TOXENV=py34-django17
   - TOXENV=py34-django18
   - TOXENV=py34-django19
   - TOXENV=py34-django_trunk
+  - TOXENV=py35-django110
+  - TOXENV=py35-django18
+  - TOXENV=py35-django19
+  - TOXENV=py35-django_trunk
 
 install:
   - pip install --upgrade pip setuptools tox virtualenv coveralls
@@ -37,9 +37,11 @@ script:
 
 matrix:
   allow_failures:
+    - env: TOXENV=py27-django110
+    - env: TOXENV=py34-django110
+    - env: TOXENV=py35-django110
     - env: TOXENV=py27-django_trunk
-    - env: TOXENV=py32-django_trunk
-    - env: TOXENV=py33-django_trunk
     - env: TOXENV=py34-django_trunk
+    - env: TOXENV=py35-django_trunk
 
 after_success: coveralls
diff --git a/AUTHORS.rst b/AUTHORS.rst
index 1776b2b..668453e 100644
--- a/AUTHORS.rst
+++ b/AUTHORS.rst
@@ -2,6 +2,7 @@ ad-m <github.com/ad-m>
 Alejandro Varas <alej0varas at gmail.com>
 Alex Orange <crazycasta at gmail.com>
 Andy Freeland <andy at andyfreeland.net>
+Artis Avotins <artis.avotins at gmail.com>
 Bram Boogaard <b.boogaard at auto-interactive.nl>
 Carl Meyer <carl at dirtcircle.com>
 Curtis Maloney <curtis at tinbrain.net>
@@ -22,6 +23,7 @@ Jeff Elmore <jeffelmore.org>
 Keryn Knight <kerynknight.com>
 Matthew Schinckel <matt at schinckel.net>
 Michael van Tellingen <michaelvantellingen at gmail.com>
+Mike Bryant <mike at mikebryant.me.uk>
 Mikhail Silonov <silonov.pro>
 Patryk Zawadzki <patrys at room-303.com>
 Paul McLanahan <paul at mclanahan.net>
diff --git a/CHANGES.rst b/CHANGES.rst
index 0c450d7..fa0bd0e 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -1,10 +1,41 @@
 CHANGES
 =======
 
-2.4 (2015-12-03)
+2.5.2 (2016.08.09)
+------------------
+
+* Include `runtests.py` in sdist.
+
+
+2.5.1 (2016.08.03)
+------------------
+
+* Fix `InheritanceQuerySet` raising an `AttributeError` exception
+  under Django 1.9.
+
+* Django 1.10 support regressed with changes between pre-alpha and final
+  release; 1.10 currently not supported.
+
+
+2.5 (2016.04.18)
 ----------------
 
-* Add support for Django 1.9. Drop support for Django 1.6 and earlier.
+* Drop support for Python 3.2.
+
+* Add support for Django 1.10 pre-alpha.
+
+* Track foreign keys on parent models properly when a tracker
+  is defined on a child model. Fixes GH-214.
+
+
+2.4 (2015.12.03)
+----------------
+
+* Remove `PassThroughManager`. Use Django's built-in `QuerySet.as_manager()`
+  and/or `Manager.from_queryset()` utilities instead.
+
+* Add support for Django 1.9.
+
 
 2.3.1 (2015-07-20)
 ------------------
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index 6b2b848..10fbcca 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -1,26 +1,26 @@
 Contributing
 ============
 
-Below is a list of tips for submitting issues and pull requests.  These are
-suggestions and not requirements.
+Below is a list of tips for submitting issues and pull requests.
 
 Submitting Issues
 -----------------
 
-Issues are often easier to reproduce/resolve when they have:
+Issues are easier to reproduce/resolve when they have:
 
 - A pull request with a failing test demonstrating the issue
 - A code example that produces the issue consistently
 - A traceback (when applicable)
 
+
 Pull Requests
 -------------
 
-When creating a pull request, try to:
+When creating a pull request:
 
-- Write tests if applicable
-- Note important changes in the `CHANGES`_ file
-- Update the documentation if needed
+- Write tests
+- Note user-facing changes in the `CHANGES`_ file
+- Update the documentation
 - Add yourself to the `AUTHORS`_ file
 - If you have added or changed translated strings, run ``make messages`` to
   update the ``.po`` translation files, and update translations for any
@@ -47,6 +47,7 @@ After you finished editing add yourself to the list of translators.
 If you have created a new translation, make sure to copy the header from one
 of the existing translation files.
 
+
 Testing
 -------
 
diff --git a/MANIFEST.in b/MANIFEST.in
index 48f0ac9..351a82c 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -4,4 +4,5 @@ include LICENSE.txt
 include MANIFEST.in
 include README.rst
 include TODO.rst
-locale/*/LC_MESSAGES/django.po
\ No newline at end of file
+recursive-include locale django.po
+include runtests.py
diff --git a/README.rst b/README.rst
index b7ddd73..001712f 100644
--- a/README.rst
+++ b/README.rst
@@ -11,35 +11,29 @@ django-model-utils
 
 Django model mixins and utilities.
 
-``django-model-utils`` supports `Django`_ 1.4.10 and later on Python 2.6, 2.7,
-3.2, 3.3 and 3.4.
+``django-model-utils`` supports `Django`_ 1.4 through 1.9 (latest bugfix
+release in each series only) on Python 2.6 (through Django 1.6 only), 2.7, 3.3
+(through Django 1.8 only), 3.4 and 3.5.
 
 .. _Django: http://www.djangoproject.com/
 
+This app is available on `PyPI`_.
 
-Getting Help
-============
+.. _PyPI: https://pypi.python.org/pypi/django-model-utils/
 
-Documentation for django-model-utils is available at https://django-model-utils.readthedocs.org/
 
-This app is available on `PyPI`_.
+Getting Help
+============
 
-.. _PyPI: https://pypi.python.org/pypi/django-model-utils/
+Documentation for django-model-utils is available at https://django-model-utils.readthedocs.io/
 
 
 Contributing
 ============
 
 Please file bugs and send pull requests to the `GitHub repository`_ and `issue
-tracker`_.
+tracker`_. See `CONTRIBUTING.rst`_ for details.
 
 .. _GitHub repository: https://github.com/carljm/django-model-utils/
 .. _issue tracker: https://github.com/carljm/django-model-utils/issues
-
-(Until January 2013 django-model-utils primary development was hosted at
-`BitBucket`_; the issue tracker there will remain open until all issues and
-pull requests tracked in it are closed, but all new issues should be filed at
-GitHub.)
-
-.. _BitBucket: https://bitbucket.org/carljm/django-model-utils/overview
-
+.. _CONTRIBUTING.rst: https://github.com/carljm/django-model-utils/blob/master/CONTRIBUTING.rst
diff --git a/TODO.rst b/TODO.rst
deleted file mode 100644
index 4218c78..0000000
--- a/TODO.rst
+++ /dev/null
@@ -1,4 +0,0 @@
-TODO
-====
-
-* Switch to proper test skips once Django 1.3 is minimum supported.
diff --git a/docs/managers.rst b/docs/managers.rst
index 0fb3144..2669a1c 100644
--- a/docs/managers.rst
+++ b/docs/managers.rst
@@ -128,50 +128,9 @@ not required).
 PassThroughManager
 ------------------
 
-A common "gotcha" when defining methods on a custom manager class is that those
-same methods are not automatically also available on the QuerySets returned by
-that manager, so are not "chainable". This can be counterintuitive, as most of
-the public QuerySet API is mirrored on managers. It is possible to create a
-custom Manager that returns QuerySets that have the same additional methods,
-but this requires boilerplate code. The ``PassThroughManager`` class
-(`contributed by Paul McLanahan`_) removes this boilerplate.
-
-.. _contributed by Paul McLanahan: http://paulm.us/post/3717466639/passthroughmanager-for-django
-
-To use ``PassThroughManager``, rather than defining a custom manager with
-additional methods, define a custom ``QuerySet`` subclass with the additional
-methods you want, and pass that ``QuerySet`` subclass to the
-``PassThroughManager.for_queryset_class()`` class method. The returned
-``PassThroughManager`` subclass will always return instances of your custom
-``QuerySet``, and you can also call methods of your custom ``QuerySet``
-directly on the manager:
-
-.. code-block:: python
-
-    from datetime import datetime
-    from django.db import models
-    from django.db.models.query import QuerySet
-    from model_utils.managers import PassThroughManager
-
-    class PostQuerySet(QuerySet):
-        def by_author(self, user):
-            return self.filter(user=user)
-
-        def published(self):
-            return self.filter(published__lte=datetime.now())
-
-        def unpublished(self):
-            return self.filter(published__gte=datetime.now())
-
-
-    class Post(models.Model):
-        user = models.ForeignKey(User)
-        published = models.DateTimeField()
-
-        objects = PassThroughManager.for_queryset_class(PostQuerySet)()
-
-    Post.objects.published()
-    Post.objects.by_author(user=request.user).unpublished()
+`PassThroughManager` was removed in django-model-utils 2.4. Use Django's
+built-in `QuerySet.as_manager()` and/or `Manager.from_queryset()` utilities
+instead.
 
 Mixins
 ------
diff --git a/docs/utilities.rst b/docs/utilities.rst
index e8d22d2..44824f5 100644
--- a/docs/utilities.rst
+++ b/docs/utilities.rst
@@ -153,7 +153,7 @@ Returns ``None`` when the model instance isn't saved yet.
 
 has_changed
 ~~~~~~~~~~~
-Returns ``True`` if the given field has changed since the last save:
+Returns ``True`` if the given field has changed since the last save. The ``has_changed`` method expects a single field:
 
 .. code-block:: pycon
 
diff --git a/model_utils/__init__.py b/model_utils/__init__.py
index 782fa33..e42aa57 100644
--- a/model_utils/__init__.py
+++ b/model_utils/__init__.py
@@ -1,4 +1,4 @@
 from .choices import Choices
 from .tracker import FieldTracker, ModelTracker
 
-__version__ = '2.4'
+__version__ = '2.5.2'
diff --git a/model_utils/managers.py b/model_utils/managers.py
index 9392e69..4f06d2e 100644
--- a/model_utils/managers.py
+++ b/model_utils/managers.py
@@ -1,7 +1,7 @@
 from __future__ import unicode_literals
 import django
 from django.db import models
-from django.db.models.fields.related import OneToOneField
+from django.db.models.fields.related import OneToOneField, OneToOneRel
 from django.db.models.query import QuerySet
 from django.core.exceptions import ObjectDoesNotExist
 
@@ -101,12 +101,20 @@ class InheritanceQuerySetMixin(object):
         recursively, returning a `list` of strings representing the
         relations for select_related
         """
+        if django.VERSION < (1, 8):
+            related_objects = model._meta.get_all_related_objects()
+        else:
+            related_objects = [
+                f for f in model._meta.get_fields()
+                if isinstance(f, OneToOneRel)]
+
         rels = [
-            rel for rel in model._meta.get_all_related_objects()
+            rel for rel in related_objects
             if isinstance(rel.field, OneToOneField)
             and issubclass(rel.field.model, model)
             and model is not rel.field.model
             ]
+
         subclasses = []
         if levels:
             levels -= 1
@@ -135,12 +143,16 @@ class InheritanceQuerySetMixin(object):
         if levels:
             levels -= 1
         while parent_link is not None:
-            ancestry.insert(0, parent_link.related.get_accessor_name())
+            if django.VERSION < (1, 8):
+                related = parent_link.related
+            else:
+                related = parent_link.rel
+            ancestry.insert(0, related.get_accessor_name())
             if levels or levels is None:
                 if django.VERSION < (1, 8):
-                    parent_model = parent_link.related.parent_model
+                    parent_model = related.parent_model
                 else:
-                    parent_model = parent_link.related.model
+                    parent_model = related.model
                 parent_link = parent_model._meta.get_ancestor_link(
                     self.model)
             else:
@@ -149,6 +161,12 @@ class InheritanceQuerySetMixin(object):
 
     def _get_sub_obj_recurse(self, obj, s):
         rel, _, s = s.partition(LOOKUP_SEP)
+
+        # Django 1.9: If a primitive type gets passed to this recursive function,
+        # return None as non-models are not part of inheritance.
+        if not isinstance(obj, models.Model):
+            return None
+
         try:
             node = getattr(obj, rel)
         except ObjectDoesNotExist:
diff --git a/model_utils/tests/models.py b/model_utils/tests/models.py
index 6b82541..c77c034 100644
--- a/model_utils/tests/models.py
+++ b/model_utils/tests/models.py
@@ -246,6 +246,11 @@ class InheritedTracked(Tracked):
     name2 = models.CharField(max_length=20)
 
 
+class InheritedTrackedFK(TrackedFK):
+    custom_tracker = FieldTracker(fields=['fk_id'])
+    custom_tracker_without_id = FieldTracker(fields=['fk'])
+
+
 class ModelTracked(models.Model):
     name = models.CharField(max_length=20)
     number = models.IntegerField()
diff --git a/model_utils/tests/tests.py b/model_utils/tests/tests.py
index d32bf86..14b6329 100644
--- a/model_utils/tests/tests.py
+++ b/model_utils/tests/tests.py
@@ -26,7 +26,7 @@ from model_utils.tests.models import (
     StatusPlainTuple, TimeFrame, Monitored, MonitorWhen, MonitorWhenEmpty, StatusManagerAdded,
     TimeFrameManagerAdded, SplitFieldAbstractParent,
     ModelTracked, ModelTrackedFK, ModelTrackedNotDefault, ModelTrackedMultiple, InheritedModelTracked,
-    Tracked, TrackedFK, TrackedNotDefault, TrackedNonFieldAttr, TrackedMultiple,
+    Tracked, TrackedFK, InheritedTrackedFK, TrackedNotDefault, TrackedNonFieldAttr, TrackedMultiple,
     InheritedTracked, StatusFieldDefaultFilled, StatusFieldDefaultNotFilled,
     InheritanceManagerTestChild3, StatusFieldChoicesName)
 
@@ -768,6 +768,54 @@ class InheritanceManagerTests(TestCase):
         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):
@@ -1682,6 +1730,11 @@ class InheritedFieldTrackerTests(FieldTrackerTests):
         self.assertRaises(FieldError, self.tracker.has_changed, 'name2')
 
 
+class FieldTrackerInheritedForeignKeyTests(FieldTrackerForeignKeyTests):
+
+    tracked_class = InheritedTrackedFK
+
+
 class ModelTrackerTests(FieldTrackerTests):
 
     tracked_class = ModelTracked
diff --git a/model_utils/tracker.py b/model_utils/tracker.py
index be5a7ff..a9c7f70 100644
--- a/model_utils/tracker.py
+++ b/model_utils/tracker.py
@@ -63,7 +63,7 @@ class FieldInstanceTracker(object):
 
     def init_deferred_fields(self):
         self.instance._deferred_fields = []
-        if not self.instance._deferred:
+        if hasattr(self.instance, '_deferred') and not self.instance._deferred:
             return
 
         class DeferredAttributeTracker(DeferredAttribute):
@@ -101,7 +101,7 @@ class FieldTracker(object):
     def get_field_map(self, cls):
         """Returns dict mapping fields names to model attribute names"""
         field_map = dict((field, field) for field in self.fields)
-        all_fields = dict((f.name, f.attname) for f in cls._meta.local_fields)
+        all_fields = dict((f.name, f.attname) for f in cls._meta.fields)
         field_map.update(**dict((k, v) for (k, v) in all_fields.items()
                                 if k in field_map))
         return field_map
@@ -113,7 +113,7 @@ class FieldTracker(object):
 
     def finalize_class(self, sender, **kwargs):
         if self.fields is None:
-            self.fields = (field.attname for field in sender._meta.local_fields)
+            self.fields = (field.attname for field in sender._meta.fields)
         self.fields = set(self.fields)
         self.field_map = self.get_field_map(sender)
         models.signals.post_init.connect(self.initialize_tracker)
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..082f7fb
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,3 @@
+tox
+sphinx
+twine
diff --git a/setup.py b/setup.py
index feb5ffc..d894b58 100644
--- a/setup.py
+++ b/setup.py
@@ -1,21 +1,29 @@
-from os.path import join
+import os
 from setuptools import setup, find_packages
 
 
-long_description = (open('README.rst').read() +
-                    open('CHANGES.rst').read() +
-                    open('TODO.rst').read())
+def long_desc(root_path):
+    FILES = ['README.rst', 'CHANGES.rst']
+    for filename in FILES:
+        filepath = os.path.realpath(os.path.join(root_path, filename))
+        if os.path.isfile(filepath):
+            with open(filepath, mode='r') as f:
+                yield f.read()
 
 
-def get_version():
-    with open(join('model_utils', '__init__.py')) as f:
+HERE = os.path.abspath(os.path.dirname(__file__))
+long_description = "\n\n".join(long_desc(HERE))
+
+
+def get_version(root_path):
+    with open(os.path.join(root_path, 'model_utils', '__init__.py')) as f:
         for line in f:
             if line.startswith('__version__ ='):
                 return line.split('=')[1].strip().strip('"\'')
 
 setup(
     name='django-model-utils',
-    version=get_version(),
+    version=get_version(HERE),
     description='Django model mixins and utilities',
     long_description=long_description,
     author='Carl Meyer',
@@ -33,9 +41,9 @@ setup(
         'Programming Language :: Python :: 2.6',
         'Programming Language :: Python :: 2.7',
         'Programming Language :: Python :: 3',
-        'Programming Language :: Python :: 3.2',
         'Programming Language :: Python :: 3.3',
         'Programming Language :: Python :: 3.4',
+        'Programming Language :: Python :: 3.5',
         'Framework :: Django',
     ],
     zip_safe=False,
diff --git a/tox.ini b/tox.ini
index 40aa033..b096f7a 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,27 +1,28 @@
 [tox]
 envlist =
     py26-django{14,15,16},
-    py27-django14, py27-django15_nosouth,
-    py{27,32,33}-django{15,16,17,18,_trunk},
-    py27-django19,
-    py34-django{17,18,19,_trunk},
+    py27-django{14,19,110,_trunk}, py27-django15_nosouth,
+    py{27,33}-django{15,16,17,18},
+    py34-django{17,18,19,110,_trunk},
+    py35-django{18,19,110,_trunk},
 
 [testenv]
 basepython =
     py26: python2.6
     py27: python2.7
-    py32: python3.2
     py33: python3.3
     py34: python3.4
+    py35: python3.5
 
 deps =
     coverage == 3.6
-    django14: Django==1.4.18
-    django15{,_nosouth}: Django==1.5.12
-    django16: Django==1.6.10
-    django17: Django==1.7.7
-    django18: Django==1.8.5
-    django19: Django==1.9
+    django14: Django>=1.4,<1.5
+    django15{,_nosouth}: Django>=1.5,<1.6
+    django16: Django>=1.6,<1.7
+    django17: Django>=1.7,<1.8
+    django18: Django>=1.8,<1.9
+    django19: Django>=1.9,<1.10
+    django110: Django>=1.10,<1.11
     django_trunk: https://github.com/django/django/tarball/master
     django{14,15,16}: South==1.0.2
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/django-model-utils.git



More information about the Python-modules-commits mailing list