pythonpython-typing

How to declare the type of the attribute of an undeclared variable


I want to declare the type of a variable which I do not declare myself, but which I know exists.

Motivation

I am currently working with the kivy library, which does a poor job indicating to static type checkers what types its fields have. I would like to indicate the types myself so I can get autocompletions. In the example below, self.ids will be a DictProperty (I believe this is a subclass of a dict) and I want to declare the type of self.ids.task_list_area.

Problem statement

How do I declare the type of self.ids.task_list_area in the following code?

class MyScreenManager(ScreenManager):
    task_list = ["Do Homework", "Take out Trash"]

class DetailsScreen(Screen):

    manager: MyScreenManager # this works

    # ids: dict
    # ids.task_list_area: BoxLayout # this does not work because ids does not exist

    def display_tasks(self):
        print(self.manager.task_list) # this is correctly infered as list[str]

        # this works at runtime, but the type checker has no clue what is happening
        print(self.ids.task_list_area) 

    def display_tasks_with_annotation(self):
        self.ids.task_list_area: BoxLayout # this does not error, but does not work either

        print(self.ids.task_list_area) # type checker still knows nothing

Solution

  • You should annotate ids with a type for which it is known that it has an attribute task_list_area of type BoxLayout.

    If kivy doesn't provide such a type, you can create one using typing.Protocol:

    from typing import Protocol
    
    class HasTaskListArea(Protocol):
        task_list_area: BoxLayout
    
    class DetailsScreen(Screen):
        ids: HasTaskListArea
        # ...