Skip to content

feat(notebook): harden exception boundaries and metadata nullability handling in notebook subsystem #196

Description

@allenporter

Summary

As identified during the notebook subsystem test coverage audit (PR #134), the core processing logic is solid, but there are a few edge cases where exception handling and nullability contracts could be hardened to prevent unhandled runtime errors when processing corrupted files or new device formats.

Proposed Improvements

1. Harden Base64 & JSON Layer Metadata Decoding (converter.py)

  • Current Behavior: ImageConverter._get_layer_visibility() attempts raw json.loads(info). On json.JSONDecodeError, it calls base64.b64decode(info).decode().
  • Issue: If info is malformed base64 or non-UTF-8 bytes, binascii.Error or UnicodeDecodeError can be raised unhandled.
  • Fix: Catch (json.JSONDecodeError, binascii.Error, UnicodeDecodeError, ValueError) and fall back to default layer visibility or raise a typed SupernoteError.

2. Add Explicit Nullability Guards for Metadata & Pages (fileformat.py / manipulator.py)

  • Current Behavior: notebook.get_metadata() returns SupernoteMetadata | None, and metadata.pages is list[...] | None.
  • Issue: Manipulator functions (merge(), reconstruct(), page addition/deletion/reordering) assume non-null metadata properties. Corrupted files could raise unhandled AttributeError or TypeError.
  • Fix: Provide a safe getter/assertion helper (e.g. get_required_metadata()) that raises a typed SupernoteFormatError if metadata or pages structure is missing.

3. Strict BPP Validation in Decoder Image Creation (converter.py)

  • Current Behavior: ImageConverter._create_image_from_decoder() matches bpp of 32, 24, or 16, and silently falls back to grayscale ("L") for any other value.
  • Issue: If a new firmware revision or device introduces an unhandled color depth, rendering fails silently as distorted grayscale.
  • Fix: Raise an explicit ValueError or UnsupportedFormatError when encountering an unexpected bpp.

Subsystem Impact

  • supernote/notebook/converter.py
  • supernote/notebook/manipulator.py
  • supernote/notebook/fileformat.py

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions