#32156: Add __class_getitem__ to support runtime type parameters for more 
classes
-------------------------------------+-------------------------------------
     Reporter:  Brady Kieffer        |                    Owner:  Brady
                                     |  Kieffer
         Type:  New feature          |                   Status:  new
    Component:  Utilities            |                  Version:  2.2
     Severity:  Normal               |               Resolution:
     Keywords:  types, mypy,         |             Triage Stage:
  django-stubs                       |  Unreviewed
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  1                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
Changes (by Brady Kieffer):

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


Comment:

 Hi Carlton,

 I didn't think you were criticizing, I actually agree with your worry
 about the boilerplate :)

 As for the `from __future__ import annotations` suggestion - that won't
 actually fix the issue in this case. The problem is that we're
 encountering a type error for the following snippet of code:

 {{{
 from django.contrb import admin
 from myapp import models as db

 class MyModelAdmin(admin.ModelAdmin):
     pass

 admin.site.register(db.MyModel, MyModelAdmin)
 }}}

 In `django-stubs 1.7.0` `BaseModelAdmin` was made generic to allow
 properly typing model admin methods that expect a model class of a certain
 type, [https://github.com/typeddjango/django-stubs/pull/504 link to this
 patch]. Due to this change, when running mypy in strict mode, the above
 snippet won't work because `admin.ModelAdmin` needs a type parameter. So,
 we'd need to write the following code:

 {{{
 from django.contrb import admin
 from myapp import models as db

 class MyModelAdmin(admin.ModelAdmin[db.MyModel]):
     pass

 admin.site.register(db.MyModel, MyModelAdmin)
 }}}

 which breaks because `admin.ModelAdmin` does not have the
 `__class_getitem__` attribute. So, to fix this issue I ''think'' the paths
 forward would be one of the following:

 1. Have `BaseModelAdmin` inherit directly from `Generic`, I ''think'' this
 is the most correct approach but I'm not 100% certain (getting input from
 the `mypy` devs here would be a good idea). This would be the least
 boilerplate-y and `Generic` was added in Python 3.5, so this should be
 fine for all supported versions of Django. The only downside I can think
 of with this approach is if there would be some weirdness with having
 `Generic` for all of these classes? I don't really know
 2. Directly bolt on a no-op for `__class_getitem__` to the
 `BaseModelAdmin` class (as I did in the proposed patch), which would allow
 me to write `class MyModelAdmin(admin.ModelAdmin[db.MyModel]): ...` . This
 directly solves the issue at hand but is boilerplate-y and doesn't address
 the underlying problem going forward.
 3. Revert the changes in `django-stubs` to account for the fact that this
 functionality isn't yet supported in Django (I'm not a fan of this one).
 Would stop typechecking from breaking for us but we'd lose out on a lot of
 powerful typing functionality, something I think django-stubs has done
 very well.
 4. Monkey-patch `BaseModelAdmin` directly. I'm not a fan of this approach
 either because it feels like we'd just be kicking the can down the road.
 Also, it'll be more work for my team to maintain divergent behavior.
 Although, the implementation really isn't difficult, it could just be done
 like so:
 {{{
 from django.contrib.admin import options

 options.BaseModelAdmin.__class_getitem__ = lambda cls, *args, **kwargs:
 cls # type: ignore
 }}}

 I'm personally a fan of (1) because it avoids the issue of boilerplate
 entirely + leverages builtin types.

 Refs:
 django stubs: https://github.com/typeddjango/django-stubs
 mypy generics:
 https://mypy.readthedocs.io/en/stable/generics.html#generics
 django stubs issue related to this: https://github.com/typeddjango/django-
 stubs/issues/507

-- 
Ticket URL: <https://code.djangoproject.com/ticket/32156#comment:6>
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/070.5d995933f6724a9c9c27895920e41a10%40djangoproject.com.

Reply via email to