typeddjango / django-stubs

PEP-484 stubs for Django
MIT License
1.54k stars 430 forks source link

Incompatible typing between `BaseModelAdmin.get_fieldsets` and its `fieldsets` #757

Open blueyed opened 2 years ago

blueyed commented 2 years ago

When adding type hints to a get_fieldsets method as defined in the stubs ([1]) it fails when returning self.fieldsets there (like the default implementation does):

t_fieldsets.py:

from typing import Any, Dict, List, Optional, Tuple

from django.contrib import admin

class MyAdmin(admin.ModelAdmin):
    def get_fieldsets(
        self, request, obj=None
    ) -> List[Tuple[Optional[str], Dict[str, Any]]]:
        if self.fieldsets:
            return self.fieldsets
        return [(None, {'fields': self.get_fields(request, obj)})]

t_fieldsets.py:11: error: Incompatible return value type (got "Union[Tuple[Tuple[Optional[str], _FieldOpts], ...], List[Tuple[Optional[str], _FieldOpts]]]", expected "List[Tuple[Optional[str], Dict[str, Any]]]")

I think the default implementation [2] should cause no type errors.

1: https://github.com/typeddjango/django-stubs/blob/a57ae4fc76c791774b9a953cc2b3244a226f23a1/django-stubs/contrib/admin/options.pyi#L115-L117 2: https://github.com/django/django/blob/31539a63f2e769cae795e3645d8daf8455ef92e7/django/contrib/admin/options.py#L331-L337

System information

ysmolski commented 10 months ago

I have got somewhat related issue when working with fields sets. This code

class MyUserAdmin(UserAdmin):
    fieldsets = UserAdmin.fieldsets + (("user activity", {"fields": ("f1",)}),)

Produces following error:

code.py:679: error: No overload variant of "__add__" of "list" matches argument type "tuple[tuple[str, dict[str, tuple[str]]]]"  [operator]
code.py:679: note: Possible overload variants:
code.py:679: note:     def __add__(self, list[tuple[str | _StrPromise | None, _FieldOpts]], /) -> list[tuple[str | _StrPromise | None, _FieldOpts]]
code.py:679: note:     def [_S] __add__(self, list[_S], /) -> list[_S | tuple[str | _StrPromise | None, _FieldOpts]]
code.py:679: error: Unsupported left operand type for + ("None")  [operator]
code.py:679: note: Left operand is of type "list[tuple[str | _StrPromise | None, _FieldOpts]] | tuple[tuple[str | _StrPromise | None, _FieldOpts], ...] | None"