Skip to content

feat(models): response models for the upload-library methods - #1008

Open
atirna wants to merge 1 commit into
sigma67:ytmusicapi-2from
atirna:feat/987-upload-response-models
Open

feat(models): response models for the upload-library methods#1008
atirna wants to merge 1 commit into
sigma67:ytmusicapi-2from
atirna:feat/987-upload-response-models

Conversation

@atirna

@atirna atirna commented Sep 5, 2026

Copy link
Copy Markdown

Summary

  • get_library_upload_songs, get_library_upload_artist and get_library_upload_album now return pydantic response models (UploadSong, UploadAlbum) deriving from the YTMusicModel base landed in feat(models): add pydantic and the YTMusicModel dict-compatible base #1004
  • parsing lives in ytmusicapi/parsers/uploads.py: parse_uploaded_items constructs UploadSong directly, and a new parse_upload_album assembles the album header plus tracks
  • docstrings point at the models instead of repeating the JSON shape
  • get_continuations / get_continuation_contents take a TypeVar so a parse func returning models typechecks; the dict parse funcs everywhere else are unchanged

Closes #987

Why

uploaded items are similar to but not the same as regular songs: they carry an entityId and lack several fields YTM-hosted songs have (isAvailable, videoType, setVideoId). since the song model from #983 and the shared leaf models from #981 are not merged yet, these are upload-specific models for now. the leaf shapes (Thumbnail, ArtistRef, AlbumRef) deliberately match what #981 plans, so re-homing them onto the shared models later is mostly a rename.

one behavioural note for 2.0 consumers: with the #307 key-presence semantics, a field the API did not return is present with value None instead of being absent. "album" in song is True even when the song has no album column, and song["album"] returns None instead of raising. dict-style access (song["title"], song.get("entityId")) keeps working through the mapping protocol, so code like the existing tests/mixins/test_uploads.py flows is unaffected.

Verification

  • pytest -o addopts='' tests/parsers tests/models -q: 103 passed. new tests in tests/parsers/test_uploads.py cover: full song parse, missing fixedColumns / album column / thumbnails staying present as None, unknown likeStatus falling back to INDIFFERENT, menu-less items skipped, a continuation page parsed through the model parse func, and album duration_seconds summed over tracks (4:15 => 255, two tracks => 510)
  • mypy (strict, repo config), clean
  • ruff check . and ruff format --check .: clean
  • the live tests in tests/mixins/test_uploads.py are unchanged and run in CI with the repo credentials

get_library_upload_songs, get_library_upload_artist and
get_library_upload_album now return UploadSong and UploadAlbum
models deriving from YTMusicModel, per sigma67#987. Parsers construct the
models directly; docstrings point at them instead of repeating the
JSON shape.

Uploaded items are similar to but not the same as regular songs
(entityId, several absent fields), so the models are upload-specific
until sigma67#983/sigma67#981 land; the leaf shapes match sigma67#981 so they can be
re-homed later.

get_continuations and get_continuation_contents take a TypeVar so a
parse func returning models typechecks; dict parse funcs are
unaffected.

Part of sigma67#307.
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