flet-dev / flet

Flet enables developers to easily build realtime web, mobile and desktop apps in Python. No frontend experience required.
https://flet.dev
Apache License 2.0
10.76k stars 416 forks source link

Covariance in Python: Using Sequence[T] instead of list[T] #3660

Closed zrr1999 closed 1 month ago

zrr1999 commented 1 month ago

Duplicate Check

Describe the requested feature

In the current version of Python, list[T] is not covariant, and you need to use Sequence[T] to achieve covariance. If a developer passes a list like [b, c], where b and c are objects of different subclasses of T, the type hint for list will raise an error.

ref: https://peps.python.org/pep-0484/

Note: Dict, DefaultDict, List, Set and FrozenSet are mainly useful for annotating return values. For arguments, prefer the abstract collection types defined below, e.g. Mapping, Sequence or AbstractSet.

Suggest a solution

Replace controls: Optional[List[Control]] = None with controls: Optional[Sequence[Control]] = None everywhere, and then change self.controls = controls to self.controls = list(controls).

Screenshots

image

Additional details

No response

ndonkoHenri commented 1 month ago

In the current version of Python

Which one?

Can you please provide the code to reproduce the typing issue? (instead of the screenshot)

zrr1999 commented 1 month ago

All versions of Python have this issue, but it is not ruled out that this part may be modified in the future because this behavior does not seem very reasonable.

import flet as ft

controls = [
    ft.Control(),
    ft.Control(),
]

another_controls = [
    ft.Text("Hello, World!"),
    ft.Text("Hello, World!"),
]

# normal
a = ft.Row(controls)
# error
b = ft.Row(another_controls)

You can reproduce it using Pyright or by enabling the standard mode of type checking in VS Code.

zrr1999 commented 1 month ago

All versions of Python have this issue, but it is not ruled out that this part may be modified in the future because this behavior does not seem very reasonable.

import flet as ft

controls = [
    ft.Control(),
    ft.Control(),
]

another_controls = [
    ft.Text("Hello, World!"),
    ft.Text("Hello, World!"),
]

# normal
a = ft.Row(controls)
# error
b = ft.Row(another_controls)

You can reproduce it using Pyright or by enabling the standard mode of type checking in VS Code.

I apologize for the earlier screenshot I provided, which had some issues (possibly due to my incorrect specification of the interpreter). The error should occur in the situation described above, with the error message as follows:

/home/zrr/workspace/work-projects/monitor/demo.py:67:12 - error: Argument of type "list[Text]" cannot be assigned to parameter "controls" of type "List[Control] | None" in function "__init__"
    Type "list[Text]" is incompatible with type "List[Control] | None"
      "list[Text]" is incompatible with "List[Control]"
        Type parameter "_T@list" is invariant, but "Text" is not the same as "Control"
        Consider switching from "list" to "Sequence" which is covariant
      "list[Text]" is incompatible with "None" (reportArgumentType)
1 error, 0 warnings, 0 informations