#34608: Migrations generates code that it can't execute
-----------------------------------------+---------------------------------
               Reporter:  Michael        |          Owner:  nobody
                   Type:  Uncategorized  |         Status:  new
              Component:  Migrations     |        Version:  4.0
               Severity:  Normal         |       Keywords:  make migrations
           Triage Stage:  Unreviewed     |      Has patch:  0
    Needs documentation:  0              |    Needs tests:  0
Patch needs improvement:  0              |  Easy pickings:  0
                  UI/UX:  0              |
-----------------------------------------+---------------------------------
 Migrations have been fine, until I rebuilt them to squash them down.

 When I run `makemigrations` it generates this line of code:
 {{{
 bases=(core.djpp.permpp.PermissionsMixin_factory.<locals>.PermissionsMixin,
 models.Model, djpp.modelpp.NiceNameMixin),
 }}}

 Which when it tries to run falls over:
 {{{
   File
 "/home/user/project/src/dist/app/plug/migrations/accounts/0001_initial.py",
 line 92
 bases=(core.djpp.permpp.PermissionsMixin_factory.<locals>.PermissionsMixin,
 models.Model, djpp.modelpp.NiceNameMixin),
     ^
 SyntaxError: expression cannot contain assignment, perhaps you meant "=="?
 }}}

 Here is most of the migration, I left out some other operations:
 {{{
 # Generated by Django 4.0.1 on 2023-05-30 16:17

 import accounts.models
 import core.djpp.permpp
 import django.contrib.auth.models
 from django.db import migrations, models
 import django.utils.timezone
 import djpp.modelpp
 import lib.timelib.ttb


 class Migration(migrations.Migration):

     initial = True

     dependencies = [
         ('auth', '0012_alter_user_first_name_max_length'),
     ]

     operations = [
        ...,
         migrations.CreateModel(
             name='User',
             fields=[
                 ('id', models.SmallAutoField(auto_created=True,
 primary_key=True, serialize=False, verbose_name='ID')),
                 ('password', models.CharField(max_length=128,
 verbose_name='password')),
                 ('last_login', models.DateTimeField(blank=True, null=True,
 verbose_name='last login')),
                 ('is_superuser', models.BooleanField(default=False,
 help_text='Designates that this user has all permissions without
 explicitly assigning them.', verbose_name='superuser status')),
                 ('first_name', models.CharField(blank=True,
 max_length=150, verbose_name='first name')),
                 ('last_name', models.CharField(blank=True, max_length=150,
 verbose_name='last name')),
                 ('is_active', models.BooleanField(default=True,
 help_text='Designates whether this user should be treated as active.
 Unselect this instead of deleting accounts.', verbose_name='active')),
                 ('date_joined',
 models.DateTimeField(default=django.utils.timezone.now, verbose_name='date
 joined')),
                 ('email', models.EmailField(max_length=254, unique=True,
 verbose_name='email address')),
                 ('is_staff', models.BooleanField(default=False,
 help_text='Designates whether the user can log into this admin site.',
 verbose_name='admin access')),
                 ('groups', models.ManyToManyField(blank=True,
 help_text='The groups this user belongs to. A user will get all
 permissions granted to each of their groups.', related_name='user_set',
 related_query_name='user', to='auth.Group', verbose_name='groups')),
                 ('user_permissions', models.ManyToManyField(blank=True,
 help_text='Specific permissions for this user.', related_name='user_set',
 related_query_name='user', to='auth.Permission', verbose_name='user
 permissions')),
             ],
             options={
                 'db_table': 'auth_user',
             },
 bases=(core.djpp.permpp.PermissionsMixin_factory.<locals>.PermissionsMixin,
 models.Model, djpp.modelpp.NiceNameMixin),
             managers=[
                 ('objects', accounts.models.UserManager()),
             ],
         ),
     ]
 }}}

 In Django's defense it is quite a convoluted iheritance chain for the user
 model, that looks like this:

 {{{
 #permpp.py - permission mixin factory which the user model inherits from
 def PermissionsMixin_factory(group_roles: GroupRoles, user_perms:
 UserPerms) -> type:
     class PermissionsMixin:
         def __init__(self, *args, **kwargs):
             super().__init__(*args, **kwargs)
             # user.has_perm is built into Django, call ours
 user.permissions
             setattr(self, GETTER_ATTR, PermissionGetter(self, group_roles,
 user_perms))

         @property
         def cached_groups(self):
               print('cached_group things')

     return PermissionsMixin

 PermissionsMixin = permpp.PermissionsMixin_factory(grs, ups)
 }}}

 {{{
 #perm.py - Constructs the permission mixin
 from core.djpp import permpp
 ...

 PermissionsMixin = permpp.PermissionsMixin_factory(...)
 }}}


 {{{
 #app/plug/user.py - mixin for customising user model for this project
 from django.db import models
 from .perm import PermissionsMixin

 class UserMixin(PermissionsMixin, models.Model):
     class Meta:
         abstract = True

     @property
     def foo(self):
         return 'foo'
 }}}

 {{{
 #accounts/user.py - define the user model
 class User(UserMixin, AbstractUser, modelpp.NiceNameMixin):
     """
     Requirements:
     - Must be defined in models.py, due to the way
 settings.AUTH_USER_MODEL is defined
     """

     objects = UserManager()

     username = None
     email = models.EmailField('email address', unique=True)
     is_staff = models.BooleanField(
         'admin access',
         default=False,
         help_text='Designates whether the user can log into this admin
 site.',
     )

     USERNAME_FIELD = 'email'
     REQUIRED_FIELDS = ('first_name',)

     def __str__(self):
         return self.get_full_name()

     class Meta:
         db_table = 'auth_user'

     #Other of custom methods ...
 }}}

-- 
Ticket URL: <https://code.djangoproject.com/ticket/34608>
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 view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/010701886d95d37d-08aa1765-23fc-4dc8-bb2e-61f774fffcd2-000000%40eu-central-1.amazonses.com.

Reply via email to