Repository: matplotlib/matplotlib
File: lib/matplotlib/animation.pyi (Python)

Code before:
        bitrate: int | None = ...,
        extra_args: list[str] | None = ...,
        metadata: dict[str, str] | None = ...,
        embed_frames: bool = ...,
        default_mode: str = ...,
        embed_limit: float | None = ...,
    ) -> None: ...
    def setup(
        self,
        fig: Figure,
        outfile: str | Path,
        dpi: float | None = ...,
        frame_dir: str | Path | None = ...,
    ) -> None: ...
    def grab_frame(self, **savefig_kwargs): ...
    def finish(self) -> None: ...

class EventSourceProtocol(Protocol):
    def add_callback(self, func: Callable): ...
    def remove_callback(self, func: Callable): ...
    def start(self): ...
    def stop(self): ...

class Animation:
    frame_seq: Iterable[Artist]
    event_source: EventSourceProtocol
    def __init__(
        self, fig: Figure, event_source: EventSourceProtocol, blit: bool = ...
    ) -> None: ...
    def __del__(self) -> None: ...
    def save(
        self,
        filename: str | Path,
        writer: AbstractMovieWriter | str | None = ...,
        fps: int | None = ...,
        dpi: float | None = ...,
        codec: str | None = ...,
        bitrate: int | None = ...,
        extra_args: list[str] | None = ...,
        metadata: dict[str, str] | None = ...,
        extra_anim: list[Animation] | None = ...,
        savefig_kwargs: dict[str, Any] | None = ...,
        *,
        progress_callback: Callable[[int, int], Any] | None = ...
    ) -> None: ...
    def new_frame_seq(self) -> Iterable[Artist]: ...
    def new_saved_frame_seq(self) -> Iterable[Artist]: ...
    def to_html5_video(self, embed_limit: float | None = ...) -> str: ...
    def to_jshtml(
        self,
        fps: int | None = ...,

Review comment (suggestion):
`Animation._stop` sets this attribute to `None`, so this annotation should still have `| None`, though I don't know if that could be replaced by a plain call to `.stop`.

Code after:
        bitrate: int | None = ...,
        extra_args: list[str] | None = ...,
        metadata: dict[str, str] | None = ...,
        embed_frames: bool = ...,
        default_mode: str = ...,
        embed_limit: float | None = ...,
    ) -> None: ...
    def setup(
        self,
        fig: Figure,
        outfile: str | Path,
        dpi: float | None = ...,
        frame_dir: str | Path | None = ...,
    ) -> None: ...
    def grab_frame(self, **savefig_kwargs): ...
    def finish(self) -> None: ...

class EventSourceProtocol(Protocol):
    def add_callback(self, func: Callable): ...
    def remove_callback(self, func: Callable): ...
    def start(self): ...
    def stop(self): ...

class Animation:
    frame_seq: Iterable[Artist]
    event_source: EventSourceProtocol | None  # TODO: We should remove None
    def __init__(
        self, fig: Figure, event_source: EventSourceProtocol, blit: bool = ...
    ) -> None: ...
    def __del__(self) -> None: ...
    def save(
        self,
        filename: str | Path,
        writer: AbstractMovieWriter | str | None = ...,
        fps: int | None = ...,
        dpi: float | None = ...,
        codec: str | None = ...,
        bitrate: int | None = ...,
        extra_args: list[str] | None = ...,
        metadata: dict[str, str] | None = ...,
        extra_anim: list[Animation] | None = ...,
        savefig_kwargs: dict[str, Any] | None = ...,
        *,
        progress_callback: Callable[[int, int], Any] | None = ...
    ) -> None: ...
    def new_frame_seq(self) -> Iterable[Artist]: ...
    def new_saved_frame_seq(self) -> Iterable[Artist]: ...
    def to_html5_video(self, embed_limit: float | None = ...) -> str: ...
    def to_jshtml(
        self,
        fps: int | None = ...,