Source code for soco.music_services.token_store

"""This module implements token stores for the music services

A user can provide their own token store depending on how that person
wishes to save the tokens, or use the builtin token store (the default)
which saves the tokens in a config file.

"""

from os import path, makedirs
import json
import appdirs


[docs]class TokenStoreBase: """Token store base class""" def __init__(self, token_collection="default"): """Instantiate instance variables Args: token_collection (str): The name of the token collection to use. This may be used to store different token collections for different client programs. """ self.token_collection = token_collection
[docs] def save_token_pair(self, music_service_id, household_id, token_pair): """Save a token value pair (token, key) which is a 2 item sequence""" raise NotImplementedError
[docs] def load_token_pair(self, music_service_id, household_id): """Load a token pair (token, key) which is a 2 item sequence""" raise NotImplementedError
[docs] def has_token(self, music_service_id, household_id): """Return True if a token is stored for the music service and household ID""" raise NotImplementedError
[docs]class JsonFileTokenStore(TokenStoreBase): """Implementation of a token store around a JSON file""" def __init__(self, filepath, token_collection="default"): """Instantiate instance variables Args: token_collection (str): The name of the token collection to use. This may be used to store different token collections for different client programs. """ super().__init__(token_collection=token_collection) self.filepath = filepath try: with open(self.filepath, encoding="UTF-8") as file_: self._token_store = json.load(file_) except FileNotFoundError: self._token_store = {}
[docs] @classmethod def from_config_file(cls, token_collection="default"): """Load from file in config directory location Args: token_collection (str): The name of the token collection to use. This may be used to store different token collections for different client programs. """ config_dir = appdirs.user_config_dir("SoCo", "SoCoGroup") config_file = path.join(config_dir, "token_store.json") return cls(config_file, token_collection=token_collection)
[docs] def save_collection(self): """Save the collection to a config file""" folder = path.dirname(self.filepath) if not path.exists(folder): makedirs(folder) with open(self.filepath, "w", encoding="UTF-8") as file_: json.dump(self._token_store, file_, indent=4)
[docs] def save_token_pair(self, music_service_id, household_id, token_pair): """Save a token value pair (token, key) which is a 2 item sequence""" if self.token_collection not in self._token_store: self._token_store[self.token_collection] = {} self._token_store[self.token_collection][ self._create_jsonable_key(music_service_id, household_id) ] = list(token_pair) self.save_collection()
[docs] def load_token_pair(self, music_service_id, household_id): """Load a token pair (token, key) which is a 2 item sequence""" return self._token_store.get(self.token_collection, {})[ self._create_jsonable_key(music_service_id, household_id) ]
[docs] def has_token(self, music_service_id, household_id): """Return True if a token is stored for the music service""" return self._create_jsonable_key( music_service_id, household_id ) in self._token_store.get(self.token_collection, {})
@staticmethod def _create_jsonable_key(music_service_id, household_id): """Return a JSON-able dictionary key created from music_service_id and household_id""" return str(music_service_id) + "#" + str(household_id)
if __name__ == "__main__": ts = JsonFileTokenStore.from_config_file() print(ts)