Models and reports#
Typed data models for tidalpy.
Plain dataclasses with to_dict() for JSON serialisation. The
catalog-facing dicts intentionally mirror the camelCase key names of
the Tidal v1 JSON API (title, numberOfTracks, releaseDate,
…) because downstream consumers — in particular tidal_transfer’s
TidalTask.info JSONField and its admin UI — were written against
that shape. Resource.to_dict() emits {"type": ..., "data": ...}
exactly like the legacy CLI’s --json mode.
- class tidalpy.models.Album(id: 'int | str | None' = None, title: 'str | None' = None, version: 'str | None' = None, release_date: 'str | None' = None, copyright_label: 'str | None' = None, number_of_tracks: 'int' = 0, number_of_volumes: 'int' = 0, album_type: 'str | None' = None, explicit: 'bool' = False, audio_quality: 'str | None' = None, artwork_id: 'str | None' = None, artists: 'list[Artist]' = <factory>, popularity: 'float' = 0.0, upc: 'str | None' = None, vibrant_color: 'str | None' = None, duration: 'int' = 0, pay_to_stream: 'bool' = False, stream_start_date: 'str | None' = None)[source]#
Bases:
object- Parameters:
title (str | None)
version (str | None)
release_date (str | None)
copyright_label (str | None)
number_of_tracks (int)
number_of_volumes (int)
album_type (str | None)
explicit (bool)
audio_quality (str | None)
artwork_id (str | None)
popularity (float)
upc (str | None)
vibrant_color (str | None)
duration (int)
pay_to_stream (bool)
stream_start_date (str | None)
- __init__(id=None, title=None, version=None, release_date=None, copyright_label=None, number_of_tracks=0, number_of_volumes=0, album_type=None, explicit=False, audio_quality=None, artwork_id=None, artists=<factory>, popularity=0.0, upc=None, vibrant_color=None, duration=0, pay_to_stream=False, stream_start_date=None)#
- Parameters:
title (str | None)
version (str | None)
release_date (str | None)
copyright_label (str | None)
number_of_tracks (int)
number_of_volumes (int)
album_type (str | None)
explicit (bool)
audio_quality (str | None)
artwork_id (str | None)
popularity (float)
upc (str | None)
vibrant_color (str | None)
duration (int)
pay_to_stream (bool)
stream_start_date (str | None)
- Return type:
None
- class tidalpy.models.Artist(id: 'int | str | None' = None, name: 'str | None' = None, picture: 'str | None' = None, popularity: 'float' = 0.0, handle: 'str | None' = None, follower_count: 'int' = 0, mixes: 'dict[str, str]' = <factory>)[source]#
Bases:
object- Parameters:
- __init__(id=None, name=None, picture=None, popularity=0.0, handle=None, follower_count=0, mixes=<factory>)#
- property link: str | None#
https://tidal.com/artist/<id>(Nonewithout an id).The id form, not the handle form:
tidalpy.api.parse_tidal_url()validates artist ids as numeric, so this is the form that round-trips through the library.
- class tidalpy.models.DownloadReport(kind, title=None, requested_quality='', items=<factory>, cancelled=False)[source]#
Bases:
objectStructured outcome of a whole download run.
- Parameters:
- __init__(kind, title=None, requested_quality='', items=<factory>, cancelled=False)#
- summary()[source]#
A compact, JSON-safe status line for the whole run.
Hosts that display run state (a Django admin column, a batch UI, a log line) get the counts and the failed items’ identity without walking
items; useto_dict()for the full per-item detail.failuresrows are compact: id, title, the machinecode, and the humanreason.Keys (camelCase, as in
to_dict()):kind,title,requestedQuality,ok,cancelled,total,okCount,skippedCount,failedCount,totalBytes,failures.
- to_dict()[source]#
JSON-safe dict of the whole run. Top-level keys are camelCase (same convention as the catalog
metadata()output); theitemsrows are snake_case (the legacy diagnose row shape).
- property failures: list[ItemReport]#
- items: list[ItemReport]#
- class tidalpy.models.ItemReport(index, kind, id=None, title=None, status='pending', reason='', path=None, delivered_quality=None, codec=None, code=None, retryable=False, size=0)[source]#
Bases:
objectOutcome of one item (track) inside a download run.
- Parameters:
- __init__(index, kind, id=None, title=None, status='pending', reason='', path=None, delivered_quality=None, codec=None, code=None, retryable=False, size=0)#
- to_dict()[source]#
JSON-safe row for this item (snake_case keys, matching the legacy client’s per-item diagnose rows). All fields are present; unset optional fields are
null.
- class tidalpy.models.Playlist(id=None, title=None, description=None, number_of_tracks=0, explicit=False, artwork_id=None, is_mix=False, creator=None, creation_time=None, last_modified=None, duration=0, playlist_type=None, follower_count=0, popularity=0.0, is_public=None, promoted_artists=<factory>, last_item_added=None, items=<factory>)[source]#
Bases:
objectA playlist or mix (
is_mixdistinguishes the two).- Parameters:
title (str | None)
description (str | None)
number_of_tracks (int)
explicit (bool)
artwork_id (str | None)
is_mix (bool)
creator (str | None)
creation_time (str | None)
last_modified (str | None)
duration (int)
playlist_type (str | None)
follower_count (int)
popularity (float)
is_public (bool | None)
last_item_added (str | None)
- __init__(id=None, title=None, description=None, number_of_tracks=0, explicit=False, artwork_id=None, is_mix=False, creator=None, creation_time=None, last_modified=None, duration=0, playlist_type=None, follower_count=0, popularity=0.0, is_public=None, promoted_artists=<factory>, last_item_added=None, items=<factory>)#
- Parameters:
title (str | None)
description (str | None)
number_of_tracks (int)
explicit (bool)
artwork_id (str | None)
is_mix (bool)
creator (str | None)
creation_time (str | None)
last_modified (str | None)
duration (int)
playlist_type (str | None)
follower_count (int)
popularity (float)
is_public (bool | None)
last_item_added (str | None)
- Return type:
None
- property link: str | None#
The linkable URL (
Nonewithout an id).Mixes use the player host (
https://play.tidal.com/mc/<id>), everything elsehttps://tidal.com/playlist/<id>(the id is the uuid for user playlists, the numeric id for editorial ones). Both forms round-trip throughtidalpy.api.parse_tidal_url().
- class tidalpy.models.Resource(kind, data)[source]#
Bases:
objectA resolved catalog entry:
album/track/playlist/mix/artist.- __init__(kind, data)#
- to_dict()[source]#
{"type": ..., "data": {...}}— the legacy--jsonshape.typeis the reference client’sTypeenum name (capitalised:"Track","Album","Playlist","Mix","Artist") — the same value its CLI--json, wrapper json-mode, and RPCmetadataall emit, which the host contract reads. (The reports use the lowercasekindinstead — different convention, different consumer, seeDownloadReport.)
- class tidalpy.models.SessionInfo(user_id=None, country_code=None, access_token='', refresh_token=None, expires_in=None, client_id=None, token_type='device', subscription=None)[source]#
Bases:
objectA live login session (device OAuth or pasted web token).
- Parameters:
- __init__(user_id=None, country_code=None, access_token='', refresh_token=None, expires_in=None, client_id=None, token_type='device', subscription=None)#
- class tidalpy.models.StreamInfo(track_id, urls, codec, delivered_quality, requested_quality, manifest_mime, encryption_key=None, bandwidth=None, sample_rate=None, bit_depth=None, channels=None, representation_id=None, manifest_hash=None, replaygain=<factory>, preview=False)[source]#
Bases:
objectA resolved stream: where to fetch the media bytes from and what it is.
urlshas one entry for bento (single file) streams and several for DASH (initialization + segments, concatenated in order).encryption_keyis the base64 security token from a bento manifest (keyId);Nonemeans the bytes are plain.- Parameters:
- __init__(track_id, urls, codec, delivered_quality, requested_quality, manifest_mime, encryption_key=None, bandwidth=None, sample_rate=None, bit_depth=None, channels=None, representation_id=None, manifest_hash=None, replaygain=<factory>, preview=False)#
- Parameters:
- Return type:
None
- class tidalpy.models.Track(id: 'int | str | None' = None, title: 'str | None' = None, version: 'str | None' = None, duration: 'int' = 0, track_number: 'int' = 0, volume_number: 'int' = 0, position: 'int' = 0, explicit: 'bool' = False, isrc: 'str | None' = None, copyright_text: 'str | None' = None, audio_quality: 'str | None' = None, media_tags: 'list[str]' = <factory>, artists: 'list[Artist]' = <factory>, album: 'Album | None' = None, replaygain: 'dict[str, str]' = <factory>, bpm: 'int | float | None' = None, key: 'str | None' = None, key_scale: 'str | None' = None, pay_to_stream: 'bool' = False, audio_modes: 'tuple[str, ...]' = (), stream_start_date: 'str | None' = None, mixes: 'dict[str, str]' = <factory>)[source]#
Bases:
object- Parameters:
title (str | None)
version (str | None)
duration (int)
track_number (int)
volume_number (int)
position (int)
explicit (bool)
isrc (str | None)
copyright_text (str | None)
audio_quality (str | None)
album (Album | None)
key (str | None)
key_scale (str | None)
pay_to_stream (bool)
stream_start_date (str | None)
- __init__(id=None, title=None, version=None, duration=0, track_number=0, volume_number=0, position=0, explicit=False, isrc=None, copyright_text=None, audio_quality=None, media_tags=<factory>, artists=<factory>, album=None, replaygain=<factory>, bpm=None, key=None, key_scale=None, pay_to_stream=False, audio_modes=(), stream_start_date=None, mixes=<factory>)#
- Parameters:
title (str | None)
version (str | None)
duration (int)
track_number (int)
volume_number (int)
position (int)
explicit (bool)
isrc (str | None)
copyright_text (str | None)
audio_quality (str | None)
album (Album | None)
key (str | None)
key_scale (str | None)
pay_to_stream (bool)
stream_start_date (str | None)
- Return type:
None
- property duration_label: str#
The track length in
M:SSdisplay form ("3:38") — the duration column of a player/search UI.""when the catalog has no duration (search rows); the rare hour-plus track formats asH:MM:SS.
- property key_label: str#
the pitch class in display form (
Sharp→#,Flat→b) with the"m"scale suffix when minor;""when the catalog has no key facts (search rows).- Type:
A short pitch label (
"F#m") for players/DJ tools
- property number_label: str#
the volume is never part of the filename — multi-disc albums use
CD{n}subfolders, seetidalpy.naming.cd_folder()).The reference client numbers a track by its position in the playlist when the track is playlist-bound, and by its album track number otherwise — hence
positiontakes precedence here (it is only set for playlist items).- Type:
Zero-padded track number (TMD parity