#25068: Metaclass conflict when doing createmigrations in ModelState.render
-------------------------+-------------------------------------------------
     Reporter:  kosz85   |      Owner:  nobody
         Type:           |     Status:  new
  Uncategorized          |
    Component:           |    Version:  1.8
  Migrations             |
     Severity:  Release  |   Keywords:  metaclass conflict createmigrations
  blocker                |
 Triage Stage:           |  Has patch:  0
  Unreviewed             |
Easy pickings:  0        |      UI/UX:  0
-------------------------+-------------------------------------------------
 I'm migrating my project from Django 1.6.x to 1.8.2, I found this bug and
 fix for it.
 In my project I'm using few ModelMixins with custom {{{__metadata__}}},
 problem is that render is trying do a class using {{{type}}} but this code
 forgot about python class metadata multi inheritance.

 Traceback looks like this, for each model with more complex metadata:
 {{{
 $ /manage.py makemigrations
 (...)
 Traceback (most recent call last):
   File "/home/vagrant/***/manage.py", line 10, in <module>
     execute_from_command_line(sys.argv)
   File "/home/vagrant/env/local/lib/python2.7/site-
 packages/django/core/management/__init__.py", line 338, in
 execute_from_command_line
     utility.execute()
   File "/home/vagrant/env/local/lib/python2.7/site-
 packages/django/core/management/__init__.py", line 330, in execute
     self.fetch_command(subcommand).run_from_argv(self.argv)
   File "/home/vagrant/env/local/lib/python2.7/site-
 packages/django/core/management/base.py", line 390, in run_from_argv
     self.execute(*args, **cmd_options)
   File "/home/vagrant/env/local/lib/python2.7/site-
 packages/django/core/management/base.py", line 441, in execute
     output = self.handle(*args, **options)
   File "/home/vagrant/env/local/lib/python2.7/site-
 packages/django/core/management/commands/makemigrations.py", line 125, in
 handle
     migration_name=self.migration_name,
   File "/home/vagrant/env/local/lib/python2.7/site-
 packages/django/db/migrations/autodetector.py", line 43, in changes
     changes = self._detect_changes(convert_apps, graph)
   File "/home/vagrant/env/local/lib/python2.7/site-
 packages/django/db/migrations/autodetector.py", line 110, in
 _detect_changes
     self.old_apps = self.from_state.concrete_apps
   File "/home/vagrant/env/local/lib/python2.7/site-
 packages/django/db/migrations/state.py", line 170, in concrete_apps
     self.apps = StateApps(self.real_apps, self.models,
 ignore_swappable=True)
   File "/home/vagrant/env/local/lib/python2.7/site-
 packages/django/db/migrations/state.py", line 232, in __init__
     self.render_multiple(list(models.values()) + self.real_models)
   File "/home/vagrant/env/local/lib/python2.7/site-
 packages/django/db/migrations/state.py", line 262, in render_multiple
     model.render(self)
   File "/home/vagrant/env/local/lib/python2.7/site-
 packages/django/db/migrations/state.py", line 548, in render
     body,
 TypeError: metaclass conflict: the metaclass of a derived class must be a
 (non-strict) subclass of the metaclasses of all its bases
 }}}

 Fix is simple. I used classmaker from here
 http://code.activestate.com/recipes/204197-solving-the-metaclass-conflict/
 And replaced line 543 of db/migrations/state.py from this:
 {{{
         # Then, make a Model object (apps.register_model is called in
 __new__)
         return type(
             str(self.name),
             bases,
             body,
         )
 }}}
 to this:
 {{{
         # Then, make a Model object (apps.register_model is called in
 __new__)
         from lib.utils.meta_maker import classmaker
         return classmaker()(str(self.name), bases, body)
 }}}

 My lib.utils.meta_maker is code from link I provided, with little changes.
 This way it works without a problems as metaclases are handled properly.
 Classmaker in most cases will return type, but for my more complex models
 will do the magic.

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

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/049.802bbc215097db8cce7b65e647434b7e%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to