Source code for asyncspotify.mixins

import logging

from .http import Route
from .image import Image
from .object import SpotifyObject
from .pager import Pager

log = logging.getLogger(__name__)


class ArtistMixin:
	def __init__(self, data):
		from .artist import SimpleArtist

		artists = data.pop('artists')
		self.artists = []

		for art in artists:
			self.artists.append(SimpleArtist(self._client, art))


class ImageMixin:
	def __init__(self, data):
		images = data.pop('images', None)
		self.images = []

		if images is not None:
			for img in images:
				self.images.append(Image(img))


class ExternalIDMixin:
	def __init__(self, data):
		external_ids = data.pop('external_ids')
		self.external_ids = {}

		for key, value in external_ids.items():
			self.external_ids[key] = value


class ExternalURLMixin:
	def __init__(self, data):
		external_urls = data.pop('external_urls')
		self.external_urls = {}

		self.link = external_urls.get('spotify', None)
		for site, url in external_urls.items():
			self.external_urls[site] = url


def valid_item(item):
	if item is None:
		return False
	# maybe explicitly check for self._track_class?
	if 'track' in item and item['track'] is None:
		return False
	return True


class TrackMixin:
	def __init__(self, data):
		tracks = data.pop('tracks', None)
		if tracks is None:
			return

		items = tracks.pop('items', None)
		if items is None:
			return

		self.tracks = []

		for item in items:
			if valid_item(item):
				self._add_track(item)

		self.__total = tracks.get('total')
		self.__limit = tracks.get('limit')

		self.track_count = self.__total

	async def __aiter__(self):
		'''Create a pager and iterate all tracks in this object. Also updates the ``tracks`` cache.'''

		self.tracks = []

		# get new pager
		r = Route('GET', '{0}s/{1}/tracks'.format(self._type, self.id), offset=0, limit=self.__limit)
		pager_data = await self._client.http.request(r)

		self.__total = pager_data.get('total')
		self.track_count = self.__total

		async for item in Pager(self._client.http, pager_data):
			if valid_item(item):
				yield self._add_track(item)
			else:
				# if it's not a valid item it shouldn't count towards the total track count goal
				self.__total -= 1

	async def fill(self):
		'''Update this objects ``tracks`` cache.'''

		async for track in self:
			pass

	def is_filled(self):
		'''Whether this object contains as many tracks as advertised by the previous pager.'''

		return len(self.tracks) >= self.__total

	def has_track(self, track):
		'''Check if this object has a track.'''

		if isinstance(track, SpotifyObject):
			track = track.id
		return any(track == t.id for t in self.tracks)

	def _add_track(self, track_data):
		track = self._track_class(self._client.http, track_data)
		self.tracks.append(track)
		return track