pythondjangopython-typingpyright

error: "get" is not a known attribute of "None" (reportOptionalMemberAccess)


I use PyRight to check my Django code. It complains about that


class FooForm(ModelForm):

    def clean(self):
        cleaned_data = super().clean()
        start = cleaned_data.get("start_date")  # <------- here

error: "get" is not a known attribute of "None" (reportOptionalMemberAccess)

I installed django-stubs.

The Django ORM magic gets detected. Example:

foo = Foo.objects.get(id=123)
foo. --> Autocomplete works. I see the attributes of a foo instance.

Both (vscode and PyRight cli-tool) understand the above snippet. It works in most cases, but not for cleaned_data.

PyRight complains about start = cleaned_data.get("start_date") but vscode does not.

How to make PyRight aware that cleaned_data is a dictionary?


Solution

  • The django-stub annotates it with an optional, as we can see in the source code [GitHub]:

    class BaseForm(RenderableFormMixin):
        # ...
        def clean(self) -> dict[str, Any] | None: ...
    

    The issue is discussed in issue #1403 [GitHub]:

    Form subclasses are allowed to skip returning the dictionary, so the type in form needs to allow none. See previous issue #954. Please search the issue tracker before opening issues.

    So you are allowed to override def clean() and return None, in fact a FormSet does that. Perhaps the programmer then should annotate it, but probably from a type-check point of view, it makes sense to make it optional.