/mopidy/models/__init__.py

https://github.com/adamcik/mopidy · Python · 361 lines · 155 code · 73 blank · 133 comment · 0 complexity · 58cf5510566ba8b6535fc3cdbe212ac4 MD5 · raw file

  1. from mopidy.models import fields
  2. from mopidy.models.immutable import ImmutableObject, ValidatedImmutableObject
  3. from mopidy.models.serialize import ModelJSONEncoder, model_json_decoder
  4. __all__ = [
  5. "ImmutableObject",
  6. "Ref",
  7. "Image",
  8. "Artist",
  9. "Album",
  10. "Track",
  11. "TlTrack",
  12. "Playlist",
  13. "SearchResult",
  14. "model_json_decoder",
  15. "ModelJSONEncoder",
  16. "ValidatedImmutableObject",
  17. ]
  18. class Ref(ValidatedImmutableObject):
  19. """
  20. Model to represent URI references with a human friendly name and type
  21. attached. This is intended for use a lightweight object "free" of metadata
  22. that can be passed around instead of using full blown models.
  23. :param uri: object URI
  24. :type uri: string
  25. :param name: object name
  26. :type name: string
  27. :param type: object type
  28. :type type: string
  29. """
  30. #: The object URI. Read-only.
  31. uri = fields.URI()
  32. #: The object name. Read-only.
  33. name = fields.String()
  34. #: The object type, e.g. "artist", "album", "track", "playlist",
  35. #: "directory". Read-only.
  36. type = fields.Identifier() # TODO: consider locking this down.
  37. # type = fields.Field(choices=(ALBUM, ARTIST, DIRECTORY, PLAYLIST, TRACK))
  38. #: Constant used for comparison with the :attr:`type` field.
  39. ALBUM = "album"
  40. #: Constant used for comparison with the :attr:`type` field.
  41. ARTIST = "artist"
  42. #: Constant used for comparison with the :attr:`type` field.
  43. DIRECTORY = "directory"
  44. #: Constant used for comparison with the :attr:`type` field.
  45. PLAYLIST = "playlist"
  46. #: Constant used for comparison with the :attr:`type` field.
  47. TRACK = "track"
  48. @classmethod
  49. def album(cls, **kwargs):
  50. """Create a :class:`Ref` with ``type`` :attr:`ALBUM`."""
  51. kwargs["type"] = Ref.ALBUM
  52. return cls(**kwargs)
  53. @classmethod
  54. def artist(cls, **kwargs):
  55. """Create a :class:`Ref` with ``type`` :attr:`ARTIST`."""
  56. kwargs["type"] = Ref.ARTIST
  57. return cls(**kwargs)
  58. @classmethod
  59. def directory(cls, **kwargs):
  60. """Create a :class:`Ref` with ``type`` :attr:`DIRECTORY`."""
  61. kwargs["type"] = Ref.DIRECTORY
  62. return cls(**kwargs)
  63. @classmethod
  64. def playlist(cls, **kwargs):
  65. """Create a :class:`Ref` with ``type`` :attr:`PLAYLIST`."""
  66. kwargs["type"] = Ref.PLAYLIST
  67. return cls(**kwargs)
  68. @classmethod
  69. def track(cls, **kwargs):
  70. """Create a :class:`Ref` with ``type`` :attr:`TRACK`."""
  71. kwargs["type"] = Ref.TRACK
  72. return cls(**kwargs)
  73. class Image(ValidatedImmutableObject):
  74. """
  75. :param string uri: URI of the image
  76. :param int width: Optional width of image or :class:`None`
  77. :param int height: Optional height of image or :class:`None`
  78. """
  79. #: The image URI. Read-only.
  80. uri = fields.URI()
  81. #: Optional width of the image or :class:`None`. Read-only.
  82. width = fields.Integer(min=0)
  83. #: Optional height of the image or :class:`None`. Read-only.
  84. height = fields.Integer(min=0)
  85. class Artist(ValidatedImmutableObject):
  86. """
  87. :param uri: artist URI
  88. :type uri: string
  89. :param name: artist name
  90. :type name: string
  91. :param sortname: artist name for sorting
  92. :type sortname: string
  93. :param musicbrainz_id: MusicBrainz ID
  94. :type musicbrainz_id: string
  95. """
  96. #: The artist URI. Read-only.
  97. uri = fields.URI()
  98. #: The artist name. Read-only.
  99. name = fields.String()
  100. #: Artist name for better sorting, e.g. with articles stripped
  101. sortname = fields.String()
  102. #: The MusicBrainz ID of the artist. Read-only.
  103. musicbrainz_id = fields.Identifier()
  104. class Album(ValidatedImmutableObject):
  105. """
  106. :param uri: album URI
  107. :type uri: string
  108. :param name: album name
  109. :type name: string
  110. :param artists: album artists
  111. :type artists: list of :class:`Artist`
  112. :param num_tracks: number of tracks in album
  113. :type num_tracks: integer or :class:`None` if unknown
  114. :param num_discs: number of discs in album
  115. :type num_discs: integer or :class:`None` if unknown
  116. :param date: album release date (YYYY or YYYY-MM-DD)
  117. :type date: string
  118. :param musicbrainz_id: MusicBrainz ID
  119. :type musicbrainz_id: string
  120. """
  121. #: The album URI. Read-only.
  122. uri = fields.URI()
  123. #: The album name. Read-only.
  124. name = fields.String()
  125. #: A set of album artists. Read-only.
  126. artists = fields.Collection(type=Artist, container=frozenset)
  127. #: The number of tracks in the album. Read-only.
  128. num_tracks = fields.Integer(min=0)
  129. #: The number of discs in the album. Read-only.
  130. num_discs = fields.Integer(min=0)
  131. #: The album release date. Read-only.
  132. date = fields.Date()
  133. #: The MusicBrainz ID of the album. Read-only.
  134. musicbrainz_id = fields.Identifier()
  135. class Track(ValidatedImmutableObject):
  136. """
  137. :param uri: track URI
  138. :type uri: string
  139. :param name: track name
  140. :type name: string
  141. :param artists: track artists
  142. :type artists: list of :class:`Artist`
  143. :param album: track album
  144. :type album: :class:`Album`
  145. :param composers: track composers
  146. :type composers: list of :class:`Artist`
  147. :param performers: track performers
  148. :type performers: list of :class:`Artist`
  149. :param genre: track genre
  150. :type genre: string
  151. :param track_no: track number in album
  152. :type track_no: integer or :class:`None` if unknown
  153. :param disc_no: disc number in album
  154. :type disc_no: integer or :class:`None` if unknown
  155. :param date: track release date (YYYY or YYYY-MM-DD)
  156. :type date: string
  157. :param length: track length in milliseconds
  158. :type length: integer or :class:`None` if there is no duration
  159. :param bitrate: bitrate in kbit/s
  160. :type bitrate: integer
  161. :param comment: track comment
  162. :type comment: string
  163. :param musicbrainz_id: MusicBrainz ID
  164. :type musicbrainz_id: string
  165. :param last_modified: Represents last modification time
  166. :type last_modified: integer or :class:`None` if unknown
  167. """
  168. #: The track URI. Read-only.
  169. uri = fields.URI()
  170. #: The track name. Read-only.
  171. name = fields.String()
  172. #: A set of track artists. Read-only.
  173. artists = fields.Collection(type=Artist, container=frozenset)
  174. #: The track :class:`Album`. Read-only.
  175. album = fields.Field(type=Album)
  176. #: A set of track composers. Read-only.
  177. composers = fields.Collection(type=Artist, container=frozenset)
  178. #: A set of track performers`. Read-only.
  179. performers = fields.Collection(type=Artist, container=frozenset)
  180. #: The track genre. Read-only.
  181. genre = fields.String()
  182. #: The track number in the album. Read-only.
  183. track_no = fields.Integer(min=0)
  184. #: The disc number in the album. Read-only.
  185. disc_no = fields.Integer(min=0)
  186. #: The track release date. Read-only.
  187. date = fields.Date()
  188. #: The track length in milliseconds. Read-only.
  189. length = fields.Integer(min=0)
  190. #: The track's bitrate in kbit/s. Read-only.
  191. bitrate = fields.Integer(min=0)
  192. #: The track comment. Read-only.
  193. comment = fields.String()
  194. #: The MusicBrainz ID of the track. Read-only.
  195. musicbrainz_id = fields.Identifier()
  196. #: Integer representing when the track was last modified. Exact meaning
  197. #: depends on source of track. For local files this is the modification
  198. #: time in milliseconds since Unix epoch. For other backends it could be an
  199. #: equivalent timestamp or simply a version counter.
  200. last_modified = fields.Integer(min=0)
  201. class TlTrack(ValidatedImmutableObject):
  202. """
  203. A tracklist track. Wraps a regular track and it's tracklist ID.
  204. The use of :class:`TlTrack` allows the same track to appear multiple times
  205. in the tracklist.
  206. This class also accepts it's parameters as positional arguments. Both
  207. arguments must be provided, and they must appear in the order they are
  208. listed here.
  209. This class also supports iteration, so your extract its values like this::
  210. (tlid, track) = tl_track
  211. :param tlid: tracklist ID
  212. :type tlid: int
  213. :param track: the track
  214. :type track: :class:`Track`
  215. """
  216. #: The tracklist ID. Read-only.
  217. tlid = fields.Integer(min=0)
  218. #: The track. Read-only.
  219. track = fields.Field(type=Track)
  220. def __init__(self, *args, **kwargs):
  221. if len(args) == 2 and len(kwargs) == 0:
  222. kwargs["tlid"] = args[0]
  223. kwargs["track"] = args[1]
  224. args = []
  225. super().__init__(*args, **kwargs)
  226. def __iter__(self):
  227. return iter([self.tlid, self.track])
  228. class Playlist(ValidatedImmutableObject):
  229. """
  230. :param uri: playlist URI
  231. :type uri: string
  232. :param name: playlist name
  233. :type name: string
  234. :param tracks: playlist's tracks
  235. :type tracks: list of :class:`Track` elements
  236. :param last_modified:
  237. playlist's modification time in milliseconds since Unix epoch
  238. :type last_modified: int
  239. """
  240. #: The playlist URI. Read-only.
  241. uri = fields.URI()
  242. #: The playlist name. Read-only.
  243. name = fields.String()
  244. #: The playlist's tracks. Read-only.
  245. tracks = fields.Collection(type=Track, container=tuple)
  246. #: The playlist modification time in milliseconds since Unix epoch.
  247. #: Read-only.
  248. #:
  249. #: Integer, or :class:`None` if unknown.
  250. last_modified = fields.Integer(min=0)
  251. # TODO: def insert(self, pos, track): ... ?
  252. @property
  253. def length(self):
  254. """The number of tracks in the playlist. Read-only."""
  255. return len(self.tracks)
  256. class SearchResult(ValidatedImmutableObject):
  257. """
  258. :param uri: search result URI
  259. :type uri: string
  260. :param tracks: matching tracks
  261. :type tracks: list of :class:`Track` elements
  262. :param artists: matching artists
  263. :type artists: list of :class:`Artist` elements
  264. :param albums: matching albums
  265. :type albums: list of :class:`Album` elements
  266. """
  267. #: The search result URI. Read-only.
  268. uri = fields.URI()
  269. #: The tracks matching the search query. Read-only.
  270. tracks = fields.Collection(type=Track, container=tuple)
  271. #: The artists matching the search query. Read-only.
  272. artists = fields.Collection(type=Artist, container=tuple)
  273. #: The albums matching the search query. Read-only.
  274. albums = fields.Collection(type=Album, container=tuple)