Curses screens, windows and pads are typed as curses.window, and the
widgets that may get no parent window take curses.window | None.
- EventHandler is generic over a ParamSpec, so each handler declares
the arguments it passes, and MenuView is generic over the item its
on_confirm hands out. Choice callbacks take no arguments.
- Scrollable is generic over its items, which DataTable and ListBox
fix to tuple[str, str] and str.
- random.choice() and choice_low() are generic over the sequence, so
the casts at their call sites are gone. BasicUserInterface.menu()
and util.first() are generic too.
- Signal callbacks and their payloads are Callable[..., object] and
object, since emit() only forwards them.
- JSON values in game_data are object and narrowed by isinstance,
and data files are Traversable.
- Signal handlers take an int and a FrameType | None, and
list_players() takes a TextIO.
- The focus_standout() context managers return
Generator[None, None, None].
Any remains in three places: Player.__setstate__, whose pickled
__dict__ holds values of every type; Focusable.__init__, a mixin that
passes *args and **kwargs through to the next class; and the values
load_game_data() collects, whose element type depends on the field
each one fills.
Python 3.10 is the minimum, so annotations use `X | None`, `list[X]`
and friends, enforced by ruff's pyupgrade rules. The remaining typing
names are imported directly, with abstract types coming from
collections.abc. first() is now generic over the item and default.