Configuration reference#
Configuration and the OAuth client registry.
All client construction is explicit: a Config carries
credentials location, output policy, quality, network policy, and the
OAuth client (Tidal’s API-key/device pair) to authenticate as. There
is no global state anywhere in the package.
Config is a pydantic model: every field is validated at
construction (a bad value fails fast with
ConfigError, not at first request), the
camelCase aliases used by Config.as_dict() and Django’s
JSONField are handled declaratively, and instances are immutable —
Config.with_updates() returns a fresh, re-validated copy.
The client registry mirrors what the proven reference clients ship:
each entry is a public device-OAuth client_id/client_secret pair
with the quality tiers it is known to unlock. A Bearer token is only
valid for the client that issued it, so the active client is part of
the saved session (see tidalpy.session).
- class tidalpy.config.Config(*, tokenPath=None, clientId=None, output=None, trackFormat='{number} {artist} - {title}{explicit}', albumFormat='{artist} - {album} {year}', playlistFormat='Playlist - {title}', includeEp=True, quality=Quality.LOSSLESS, apiBase=None, legacyApiBase=None, openapiBase=None, authBase=None, proxies=None, verifyTls=None, timeoutConnect=10.0, timeoutRead=60.0, maxRetries=3, retryBackoff=1.0, rateLimitMaxWait=90.0, rateLimitMaxPause=21600, assetNotReadyMaxWaits=6, userAgent=None, downloadWorkers=8, partSize=1048576, pacingBps=None, validateMediaUrls=True, writeTags=True, writeLyrics=False, lyricFile=False, downloadCover=True, saveAsFlac=True, verifyMedia=True, saveReceipts=False, skipBroken=True)[source]#
Bases:
BaseModelValidated, immutable configuration for a
tidalpy.client.TidalClient.Both
snake_casefield names and the camelCase aliases used byas_dict()are accepted by the constructor andfrom_dict(). Invalid values raiseConfigErrorimmediately.- Parameters:
tokenPath (Path | None)
clientId (str | None)
output (Path | None)
trackFormat (str)
albumFormat (str)
playlistFormat (str)
includeEp (bool)
quality (Quality)
apiBase (str | None)
legacyApiBase (str | None)
openapiBase (str | None)
authBase (str | None)
userAgent (str | None)
validateMediaUrls (bool)
writeTags (bool)
writeLyrics (bool)
lyricFile (bool)
downloadCover (bool)
saveAsFlac (bool)
verifyMedia (bool)
saveReceipts (bool)
skipBroken (bool)
- classmethod from_dict(data)[source]#
Build a
Configfrom a plain dict (JSON-safe).Accepts both
snake_caseand the camelCase keys used byas_dict()and Django’s JSONField settings. Unknown keys raiseConfigError(a typo should fail fast, not silently pick a default). Explicitnullvalues are treated as “unspecified” and keep the model default (Django form/JSON round-trips serialize unset values asNone; the reference client applies the same rule — a naiveNonewould clobber a working default).
- __init__(**data)[source]#
Construction is validated; invalid values raise
ConfigError(not a rawValidationError).- Parameters:
data (object)
- Return type:
None
- user_agent_for(client)[source]#
- Parameters:
client (OAuthClient)
- Return type:
- with_updates(**kwargs)[source]#
A copy of this config with the given fields replaced.
Runs the same validation as the constructor; an invalid value raises
ConfigErrorand leaves this object untouched.
- model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'frozen': True, 'populate_by_name': True}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- property oauth_client: OAuthClient#
- class tidalpy.config.OAuthClient(client_id, client_secret, platform, qualities=(), user_agent='TIDAL/3.34.0 (Android TV; Linux; U)', note='')[source]#
Bases:
objectA public device-OAuth client (Tidal “API key”).
- Parameters:
- __init__(client_id, client_secret, platform, qualities=(), user_agent='TIDAL/3.34.0 (Android TV; Linux; U)', note='')#
- tidalpy.config.clients_for(quality=None)[source]#
Registered clients that can serve
quality, best first.The registry documents per-client quality support, but nothing used it: a host that needs “a client that can actually deliver this quality” (a login that should target the right client from the start) had to walk
list_clients()andOAuthClient.supports()itself.qualitytakes the same labels as the rest of the library (aliases included, e.g."24/192");None/unknown resolve to the default profile.The default client comes first when it claims the quality (its login is usually the one a host already has), then the other claiming clients in registry order (the stable id order). Raises
ConfigErrorwhen no registered client claims the quality — a registry gap, not a host error.- Parameters:
- Return type:
- tidalpy.config.config_from_env(env=None)[source]#
Build a
ConfigwithTIDALPY_-prefixed environment overrides.Every configurable field has a
TIDALPY_variable (the full table is_ENV_OVERRIDES):TIDALPY_TOKEN_PATH,TIDALPY_OUTPUT,TIDALPY_QUALITY,TIDALPY_PROXY,TIDALPY_WRITE_TAGS,TIDALPY_WRITE_LYRICS,TIDALPY_INCLUDE_EP,TIDALPY_DOWNLOAD_WORKERS,TIDALPY_PART_SIZE,TIDALPY_MAX_RETRIES,TIDALPY_TIMEOUT_CONNECT,TIDALPY_TIMEOUT_READ, and so on. Handy for the Django side to inject per-deployment settings without code changes.Values are parsed with the same strictness as constructor arguments: an unparseable value raises
ConfigError(TIDALPY_WRITE_TAGS=tureis a deploy bug, not a silentFalse). Unset or empty variables keep the default.envdefaults toos.environ; tests pass a plain dict.
- tidalpy.config.get_client(client_id=None)[source]#
Look up a registered client by id (default client when
None).- Parameters:
client_id (str | None)
- Return type: