<commit_before>from __future__ import absolute_import, unicode_literals

from mopidy.models import fields
from mopidy.models.immutable import ImmutableObject, ValidatedImmutableObject
from mopidy.models.serialize import ModelJSONEncoder, model_json_decoder

__all__ = [
    'ImmutableObject', 'Ref', 'Image', 'Artist', 'Album', 'track', 'TlTrack',
    'Playlist', 'SearchResult', 'model_json_decoder', 'ModelJSONEncoder',
    'ValidatedImmutableObject']


class Ref(ValidatedImmutableObject):

    """
    Model to represent URI references with a human friendly name and type
    attached. This is intended for use a lightweight object "free" of metadata
    that can be passed around instead of using full blown models.

    :param uri: object URI
    :type uri: string
    :param name: object name
    :type name: string
    :param type: object type
    :type type: string
    """

    #: The object URI. Read-only.
    uri = fields.URI()

    #: The object name. Read-only.
    name = fields.String()

    #: The object type, e.g. "artist", "album", "track", "playlist",
    #: "directory". Read-only.
    type = fields.Identifier()  # TODO: consider locking this down.
    # type = fields.Field(choices=(ALBUM, ARTIST, DIRECTORY, PLAYLIST, TRACK))

    #: Constant used for comparison with the :attr:`type` field.
    ALBUM = 'album'

    #: Constant used for comparison with the :attr:`type` field.
    ARTIST = 'artist'

    #: Constant used for comparison with the :attr:`type` field.
    DIRECTORY = 'directory'

    #: Constant used for comparison with the :attr:`type` field.
    PLAYLIST = 'playlist'

    #: Constant used for comparison with the :attr:`type` field.
    TRACK = 'track'

    @classmethod
    def album(cls, **kwargs):
        """Create a :class:`Ref` with ``type`` :attr:`ALBUM`."""
        kwargs['type'] = Ref.ALBUM
        return cls(**kwargs)

    @classmethod
    def artist(cls, **kwargs):
        """Create a :class:`Ref` with ``type`` :attr:`ARTIST`."""
        kwargs['type'] = Ref.ARTIST
        return cls(**kwargs)

    @classmethod
    def directory(cls, **kwargs):
        """Create a :class:`Ref` with ``type`` :attr:`DIRECTORY`."""
        kwargs['type'] = Ref.DIRECTORY
        return cls(**kwargs)

    @classmethod
    def playlist(cls, **kwargs):
        """Create a :class:`Ref` with ``type`` :attr:`PLAYLIST`."""
        kwargs['type'] = Ref.PLAYLIST
        return cls(**kwargs)

    @classmethod
    def track(cls, **kwargs):
        """Create a :class:`Ref` with ``type`` :attr:`TRACK`."""
        kwargs['type'] = Ref.TRACK
        return cls(**kwargs)


class Image(ValidatedImmutableObject):

    """
    :param string uri: URI of the image
    :param int width: Optional width of image or :class:`None`
    :param int height: Optional height of image or :class:`None`
    """

    #: The image URI. Read-only.
    uri = fields.URI()

    #: Optional width of the image or :class:`None`. Read-only.
    width = fields.Integer(min=0)

    #: Optional height of the image or :class:`None`. Read-only.
    height = fields.Integer(min=0)


class Artist(ValidatedImmutableObject):

    """
    :param uri: artist URI
    :type uri: string
    :param name: artist name
    :type name: string
    :param musicbrainz_id: MusicBrainz ID
    :type musicbrainz_id: string
    """

    #: The artist URI. Read-only.
    uri = fields.URI()

    #: The artist name. Read-only.
    name = fields.String()

    #: Artist name for better sorting, e.g. with articles stripped
    sortname = fields.String()

    #: The MusicBrainz ID of the artist. Read-only.
    musicbrainz_id = fields.Identifier()


class Album(ValidatedImmutableObject):

    """
    :param uri: album URI
    :type uri: string<commit_msg>models: Add Artist.sortname to init docstring<commit_after>from __future__ import absolute_import, unicode_literals

from mopidy.models import fields
from mopidy.models.immutable import ImmutableObject, ValidatedImmutableObject
from mopidy.models.serialize import ModelJSONEncoder, model_json_decoder

__all__ = [
    'ImmutableObject', 'Ref', 'Image', 'Artist', 'Album', 'track', 'TlTrack',
    'Playlist', 'SearchResult', 'model_json_decoder', 'ModelJSONEncoder',
    'ValidatedImmutableObject']


class Ref(ValidatedImmutableObject):

    """
    Model to represent URI references with a human friendly name and type
    attached. This is intended for use a lightweight object "free" of metadata
    that can be passed around instead of using full blown models.

    :param uri: object URI
    :type uri: string
    :param name: object name
    :type name: string
    :param type: object type
    :type type: string
    """

    #: The object URI. Read-only.
    uri = fields.URI()

    #: The object name. Read-only.
    name = fields.String()

    #: The object type, e.g. "artist", "album", "track", "playlist",
    #: "directory". Read-only.
    type = fields.Identifier()  # TODO: consider locking this down.
    # type = fields.Field(choices=(ALBUM, ARTIST, DIRECTORY, PLAYLIST, TRACK))

    #: Constant used for comparison with the :attr:`type` field.
    ALBUM = 'album'

    #: Constant used for comparison with the :attr:`type` field.
    ARTIST = 'artist'

    #: Constant used for comparison with the :attr:`type` field.
    DIRECTORY = 'directory'

    #: Constant used for comparison with the :attr:`type` field.
    PLAYLIST = 'playlist'

    #: Constant used for comparison with the :attr:`type` field.
    TRACK = 'track'

    @classmethod
    def album(cls, **kwargs):
        """Create a :class:`Ref` with ``type`` :attr:`ALBUM`."""
        kwargs['type'] = Ref.ALBUM
        return cls(**kwargs)

    @classmethod
    def artist(cls, **kwargs):
        """Create a :class:`Ref` with ``type`` :attr:`ARTIST`."""
        kwargs['type'] = Ref.ARTIST
        return cls(**kwargs)

    @classmethod
    def directory(cls, **kwargs):
        """Create a :class:`Ref` with ``type`` :attr:`DIRECTORY`."""
        kwargs['type'] = Ref.DIRECTORY
        return cls(**kwargs)

    @classmethod
    def playlist(cls, **kwargs):
        """Create a :class:`Ref` with ``type`` :attr:`PLAYLIST`."""
        kwargs['type'] = Ref.PLAYLIST
        return cls(**kwargs)

    @classmethod
    def track(cls, **kwargs):
        """Create a :class:`Ref` with ``type`` :attr:`TRACK`."""
        kwargs['type'] = Ref.TRACK
        return cls(**kwargs)


class Image(ValidatedImmutableObject):

    """
    :param string uri: URI of the image
    :param int width: Optional width of image or :class:`None`
    :param int height: Optional height of image or :class:`None`
    """

    #: The image URI. Read-only.
    uri = fields.URI()

    #: Optional width of the image or :class:`None`. Read-only.
    width = fields.Integer(min=0)

    #: Optional height of the image or :class:`None`. Read-only.
    height = fields.Integer(min=0)


class Artist(ValidatedImmutableObject):

    """
    :param uri: artist URI
    :type uri: string
    :param name: artist name
    :type name: string
    :param sortname: artist name for sorting
    :type sortname: string
    :param musicbrainz_id: MusicBrainz ID
    :type musicbrainz_id: string
    """

    #: The artist URI. Read-only.
    uri = fields.URI()

    #: The artist name. Read-only.
    name = fields.String()

    #: Artist name for better sorting, e.g. with articles stripped
    sortname = fields.String()

    #: The MusicBrainz ID of the artist. Read-only.
    musicbrainz_id = fields.Identifier()


class Album(ValidatedImmutableObject):

    """
    :param uri: album URI
    :type uri: string
{'fraction_non_alphanumeric': 0.13026315789473683, 'fraction_numerical': 0.0005263157894736842, 'mean_word_length': 3.086559139784946, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5799375', 'n_tokens_mistral': 2351, 'n_tokens_neox': 2227, 'n_words': 737}