[Django] #27337: Convoluted MTI with abstract model mixin fails on PY2, works on PY3

4 views
Skip to first unread message

Django

unread,
Oct 12, 2016, 6:59:45 PM10/12/16
to django-...@googlegroups.com
#27337: Convoluted MTI with abstract model mixin fails on PY2, works on PY3
----------------------------------------------+--------------------------
Reporter: Tim Heap | Owner: nobody
Type: Bug | Status: new
Component: Database layer (models, ORM) | Version: 1.10
Severity: Normal | Keywords: python2, mti
Triage Stage: Unreviewed | Has patch: 0
Easy pickings: 0 | UI/UX: 0
----------------------------------------------+--------------------------
This is a rather convoluted situation, but with the set up below, PY2
fails but PY3 works. For context, this is roughly the same model set up
used in Wagtail:

* A Page class with custom Metaclass,
* Developers extend Page using MTI to make custom page types
* Mixins can be used for adding common functionality from e.g. plugins.

{{{#!python
from django.db import models
from django.utils import six
from django.test import TestCase

class ConvolutedMTIWithAbtractMixinTests(TestCase):
def test_convoluted_mti(self):

class PageBase(type(models.Model)):
"""
Wagtail's metaclass does some things, but nothing related.
This empty metaclass still spoils things for some reason?
"""

class Page(six.with_metaclass(PageBase, models.Model)):
"""The base page model. Every page should inherit from
this."""
url = models.CharField(max_length=255)

class Meta:
app_label = 'tests'

class FancyMixin(models.Model):
"""A model mixin with extra functionality, including extra
model fields."""
fancy_field = models.CharField(max_length=10)

class Meta:
abstract = True

class MyPage(FancyMixin, Page):
"""My custom page type. Extends Page using MTI, and mixes in
FancyMixin"""
content = models.CharField(max_length=255)

class Meta:
app_label = 'tests'

# The page_ptr from MyPage to Page is created.
self.assertTrue(hasattr(MyPage, 'page_ptr'))

# The other fields are all there
self.assertTrue(MyPage._meta.get_field('url'))
self.assertTrue(MyPage._meta.get_field('fancy_field'))
self.assertTrue(MyPage._meta.get_field('content'))

# The page_ptr field exists as a parent pointer to page.
self.assertIn(Page, MyPage._meta.parents)
self.assertIsInstance(MyPage._meta.parents[Page],
models.OneToOneField)

# But Django on py27 gets confused, and 'page_ptr' is not
'registered'
# (There is no nice _meta.has_field, so try: catch will do.)
try:
MyPage._meta.get_field('page_ptr')
except FieldDoesNotExist:
self.fail("MyPage.page_ptr field is missing!")
}}}

I stuck this test in `tests/model_inheritance/tests.py` when testing this
out, but the tests can probably go anywhere. For some tests failing in the
wild, this Travis CI build (https://travis-
ci.org/takeflight/wagtail/builds/167013485) of some patches to Wagtail
shows this happening on Django 1.8, 1.9 and 1.10 at least, but only on
Python 2.7.

I've poked around a little bit to see if I could work out what is going
on, but I am not familiar enough with the model internals to make much
headway.

--
Ticket URL: <https://code.djangoproject.com/ticket/27337>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Oct 12, 2016, 7:11:41 PM10/12/16
to django-...@googlegroups.com
#27337: Convoluted MTI with abstract model mixin fails on PY2, works on PY3
-------------------------------------+-------------------------------------

Reporter: Tim Heap | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 1.10
(models, ORM) |
Severity: Normal | Resolution:
Keywords: python2, mti py2 | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Graham):

* keywords: python2, mti => python2, mti py2
* needs_docs: => 0
* needs_better_patch: => 0
* needs_tests: => 0
* stage: Unreviewed => Accepted


Comment:

I'm not going to spend any time investigating the issue, but I'll assume
the report is valid and accept the ticket. We're accepting Python
2-specific bug fixes until mid-January 2017 (1.11 alpha), at which point
we'll close any unresolved issues that only affect Python 2 as wontfix as
master will become Python 3 only.

--
Ticket URL: <https://code.djangoproject.com/ticket/27337#comment:1>

Django

unread,
Oct 12, 2016, 7:16:23 PM10/12/16
to django-...@googlegroups.com
#27337: Convoluted MTI with abstract model mixin fails on PY2, works on PY3
-------------------------------------+-------------------------------------

Reporter: Tim Heap | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 1.10
(models, ORM) |
Severity: Normal | Resolution:
Keywords: python2, mti py2 | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Tim Heap):

I will eagerly look forward to the day we can all drop Python 2 support.

--
Ticket URL: <https://code.djangoproject.com/ticket/27337#comment:2>

Django

unread,
Oct 13, 2016, 4:00:08 AM10/13/16
to django-...@googlegroups.com
#27337: Convoluted MTI with abstract model mixin fails on PY2, works on PY3
-------------------------------------+-------------------------------------

Reporter: Tim Heap | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 1.10
(models, ORM) |
Severity: Normal | Resolution:
Keywords: python2, mti py2 | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Aymeric Augustin):

Thanks for the bug report anyway! :-)

--
Ticket URL: <https://code.djangoproject.com/ticket/27337#comment:3>

Django

unread,
Oct 19, 2016, 10:52:51 AM10/19/16
to django-...@googlegroups.com
#27337: Convoluted MTI with abstract model mixin fails on PY2, works on PY3
-------------------------------------+-------------------------------------

Reporter: Tim Heap | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 1.10
(models, ORM) |
Severity: Normal | Resolution:
Keywords: python2, mti py2 | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Andrew Nester):

Hi guys!

I was able to reproduce this behavior just in plain Python 2.7
You can check my question on Stack Overflow for more details.
http://stackoverflow.com/questions/40134852/metaclass-inheritance-in-
python-2-and-python-3

--
Ticket URL: <https://code.djangoproject.com/ticket/27337#comment:4>

Django

unread,
Oct 19, 2016, 11:17:23 AM10/19/16
to django-...@googlegroups.com
#27337: Convoluted MTI with abstract model mixin fails on PY2, works on PY3
-------------------------------------+-------------------------------------

Reporter: Tim Heap | Owner: nobody
Type: Bug | Status: closed

Component: Database layer | Version: 1.10
(models, ORM) |
Severity: Normal | Resolution: invalid

Keywords: python2, mti py2 | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Aymeric Augustin):

* status: new => closed
* resolution: => invalid


Comment:

Closing as Django doesn't seem to be at fault here.

--
Ticket URL: <https://code.djangoproject.com/ticket/27337#comment:5>

Reply all
Reply to author
Forward
0 new messages