Skip to content

Fix more type stub mismatches - #2467

Merged
WyattBlue merged 1 commit into
masterfrom
stub-fixes-3
Oct 24, 2026
Merged

WyattBlue merged 1 commit into
masterfrom
stub-fixes-3

Conversation

@WyattBlue

Copy link
Copy Markdown
Member

More stub fixes, found by type-checking examples/, comparing each class's runtime dunders against its stub, and comparing stream attributes with the codec-context attributes they forward to.

Things that work at runtime but failed type-checking

  • SubtitleSet items (rects, __iter__, __getitem__) were typed as the base Subtitle, but at runtime they are only ever AssSubtitle or BitmapSubtitle, so sub.ass could never type-check (examples/subtitles/remux.py failed). Now AssSubtitle | BitmapSubtitle, which also lets a sub.type check narrow the type.
  • BitmapSubtitle has __len__, __iter__, and __getitem__ over its planes at runtime; they're now in the stub.
  • BitmapSubtitlePlane supports the buffer protocol; added __buffer__, so memoryview(plane) and bytes(plane) type-check.
  • VideoFormat has __int__ (used by Graph.add_buffer); added to the stub.

Annotation fixes

  • CodecContext.encode, encode_lazy, and decode had no return types. decode returns Sequence[Frame | AssSubtitle | BitmapSubtitle]; I used Sequence because list is invariant, and the list[VideoFrame] that VideoCodecContext.decode returns wouldn't fit a list[Frame] base.
  • SubtitleCodecContext.decode(None) raises RuntimeError: packet cannot be None, so its stub now requires a Packet. This uses # type: ignore[override], like the existing encode overrides in the audio and video contexts. SubtitleStream.decode(None) still accepts None, since it substitutes an empty packet.
  • VideoStream.format is now VideoFormat | None, matching the VideoCodecContext.format it forwards to.
  • Audio, video, and subtitle streams declare name: str, since they forward it to the codec context.
  • VideoFrame.to_image returns PIL.Image.Image, and set_image/from_image take one. Pillow is in the test and lint dependency groups.

Notes

  • Possible break for type-checked code: stream.format.name on a VideoStream now needs a None check. Four test blocks gained assert stream.format is not None.
  • examples/subtitles/remux.py now checks isinstance(sub, AssSubtitle) before using sub.ass.
  • Not changed: AudioStream.format/AudioCodecContext.format can also be None at runtime but are typed as always AudioFormat.

- Type `SubtitleSet` items as `AssSubtitle | BitmapSubtitle`
- Add `BitmapSubtitle` sequence methods, `BitmapSubtitlePlane.__buffer__`, and `VideoFormat.__int__`
- Add return types to `CodecContext.encode`, `encode_lazy`, and `decode`; `SubtitleCodecContext.decode` requires a packet
- `VideoStream.format` may be `None`, like `VideoCodecContext.format`
- Forwarded stream `name` is a `str`
- Use `PIL.Image.Image` in `VideoFrame` image methods
@WyattBlue
WyattBlue merged commit 9af38b1 into master Oct 24, 2026
1 check passed
@WyattBlue
WyattBlue deleted the stub-fixes-3 branch October 24, 2026 17:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant