<commit_before># -*- coding: utf-8 -*-

import xml
from urllib.parse import quote_plus

from plexapi import log, settings, utils
from plexapi.base import PlexObject
from plexapi.exceptions import BadRequest


@utils.registerPlexObject
class Media(PlexObject):
    """ Container object for all MediaPart objects. Provides useful data about the
        video or audio this media belong to such as video framerate, resolution, etc.

        Attributes:
            TAG (str): 'Media'
            aspectRatio (float): The aspect ratio of the media (ex: 2.35).
            audioChannels (int): The number of audio channels of the media (ex: 6).
            audioCodec (str): The audio codec of the media (ex: ac3).
            audioProfile (str): The audio profile of the media (ex: dts).
            bitrate (int): The bitrate of the media (ex: 1624).
            container (str): The container of the media (ex: avi).
            duration (int): The duration of the media in milliseconds (ex: 6990483).
            height (int): The height of the media in pixels (ex: 256).
            id (int): The unique ID for this media on the server.
            has64bitOffsets (bool): True if video has 64 bit offsets.
            optimizedForStreaming (bool): True if video is optimized for streaming.
            parts (List<:class:`~plexapi.media.MediaPart`>): List of media part objects.
            proxyType (int): Equals 42 for optimized versions.
            target (str): The media version target name.
            title (str): The title of the media.
            videoCodec (str): The video codec of the media (ex: ac3).
            videoFrameRate (str): The video frame rate of the media (ex: 24p).
            videoProfile (str): The video profile of the media (ex: high).
            videoResolution (str): The video resolution of the media (ex: sd).
            width (int): The width of the video in pixels (ex: 608).

            <Photo_only_attributes>: The following attributes are only available for photos.

                * aperture (str): The apeture used to take the photo.
                * exposure (str): The exposure used to take the photo.
                * iso (int): The iso used to take the photo.
                * lens (str): The lens used to take the photo.
                * make (str): The make of the camera used to take the photo.
                * model (str): The model of the camera used to take the photo.
    """
    TAG = 'Media'

    def _loadData(self, data):
        """ Load attribute values from Plex XML response. """
        self._data = data
        self.aspectRatio = utils.cast(float, data.attrib.get('aspectRatio'))
        self.audioChannels = utils.cast(int, data.attrib.get('audioChannels'))
        self.audioCodec = data.attrib.get('audioCodec')
        self.audioProfile = data.attrib.get('audioProfile')
        self.bitrate = utils.cast(int, data.attrib.get('bitrate'))
        self.container = data.attrib.get('container')
        self.duration = utils.cast(int, data.attrib.get('duration'))
        self.height = utils.cast(int, data.attrib.get('height'))
        self.id = utils.cast(int, data.attrib.get('id'))
        self.has64bitOffsets = utils.cast(bool, data.attrib.get('has64bitOffsets'))
        self.optimizedForStreaming = utils.cast(bool, data.attrib.get('optimizedForStreaming'))
        self.parts = self.findItems(data, MediaPart)
        self.proxyType = utils.cast(int, data.attrib.get('proxyType'))
        self.target = data.attrib.get('target')
        self.title = data.attrib.get('title')
        self.videoCodec = data.attrib.get('videoCodec')
        self.videoFrameRate = data.attrib.get('videoFrameRate')
        self.videoProfile = data.attrib.get('videoProfile')
        self.videoResolution = data.attrib.get('videoResolution')
        self.width = utils.cast(int, data.attrib.get('width'))

        if self._isChildOf(etag='Photo'):
            self.aperture = data.attrib.get('aperture')
            self.exposure = data.attrib.get('exposure')
            self.iso = utils.cast(int, data.attrib.get('iso'))
            self.lens = data.attrib.get('lens')
            self.make = data.attrib.get('make')
            self.model = data.attrib.get('model')

    @property
    def isOptimizedVersion(self):
        """ Returns True if the media is a Plex optimized version. """
        return self.proxyType == utils.SEARCHTYPES['optimizedVersion']

    def delete(self):
        part = self._initpath + '/media/%s' % self.id
        try:
            return self._server.query(part, method=self._server._session.delete)
        except BadRequest:
            log.error("Failed to delete %s. This could be because you havn't allowed "
                      "items to be deleted" % part)
            raise


@utils.registerPlexObject
class MediaPart(PlexObject):
    """ Represents a single media part (often a single file) for the media this belongs to.

        Attributes:
            TAG (str): 'Part'
            accessible (bool): True if the file is accessible.
            audioProfile (str): The audio profile of the file.
            container (str): The container type of the file (ex: avi).
            decision (str): Unknown.
            deepAnalysisVersion (int): The Plex deep analysis version for the file.
            duration (int): The duration of the file in milliseconds.
            exists (bool): True if the file exists.
            file (str): The path to this file on disk (ex: /media/Movies/Cars (2006)/Cars (2006).mkv)
            has64bitOffsets (bool): True if the file has 64 bit offsets.
            hasThumbnail (bool): True if the file (track) has an embedded thumbnail.
            id (int): The unique ID for this media part on the server.
            indexes (str, None): sd if the file has generated preview (BIF) thumbnails.
            key (str): API URL (ex: /library/parts/46618/1389985872/file.mkv).
            optimizedForStreaming (bool): True if the file is optimized for streaming.
            packetLength (int): The packet length of the file.
            requiredBandwidths (str): The required bandwidths to stream the file.
            size (int): The size of the file in bytes (ex: 733884416).
            streams (List<:class:`~plexapi.media.MediaPartStream`>): List of stream objects.
            syncItemId (int): The unique ID for this media part if it is synced.
            syncState (str): The sync state for this media part.
            videoProfile (str): The video profile of the file.
    """
    TAG = 'Part'

    def _loadData(self, data):
        """ Load attribute values from Plex XML response. """
        self._data = data
        self.accessible = utils.cast(bool, data.attrib.get('accessible'))
        self.audioProfile = data.attrib.get('audioProfile')
        self.container = data.attrib.get('container')
        self.decision = data.attrib.get('decision')
        self.deepAnalysisVersion = utils.cast(int, data.attrib.get('deepAnalysisVersion'))
        self.duration = utils.cast(int, data.attrib.get('duration'))
        self.exists = utils.cast(bool, data.attrib.get('exists'))
        self.file = data.attrib.get('file')
        self.has64bitOffsets = utils.cast(bool, data.attrib.get('has64bitOffsets'))
        self.hasThumbnail = utils.cast(bool, data.attrib.get('hasThumbnail'))
        self.id = utils.cast(int, data.attrib.get('id'))
        self.indexes = data.attrib.get('indexes')
        self.key = data.attrib.get('key')
        self.optimizedForStreaming = utils.cast(bool, data.attrib.get('optimizedForStreaming'))
        self.packetLength = utils.cast(int, data.attrib.get('packetLength'))
        self.requiredBandwidths = data.attrib.get('requiredBandwidths')
        self.size = utils.cast(int, data.attrib.get('size'))
        self.streams = self._buildStreams(data)
        self.syncItemId = utils.cast(int, data.attrib.get('syncItemId'))
        self.syncState = data.attrib.get('syncState')
        self.videoProfile = data.attrib.get('videoProfile')

    def _buildStreams(self, data):
        streams = []
        for cls in (VideoStream, AudioStream, SubtitleStream, LyricStream):
            items = self.findItems(data, cls, streamType=cls.STREAMTYPE)
            streams.extend(items)
        return streams

    @property
    def hasPreviewThumbnails(self):
        """ Returns True if the media part has generated preview (BIF) thumbnails. """
        return self.indexes == 'sd'

    def videoStreams(self):
        """ Returns a list of :class:`~plexapi.media.VideoStream` objects in this MediaPart. """
        return [stream for stream in self.streams if isinstance(stream, VideoStream)]

    def audioStreams(self):
        """ Returns a list of :class:`~plexapi.media.AudioStream` objects in this MediaPart. """
        return [stream for stream in self.streams if isinstance(stream, AudioStream)]

    def subtitleStreams(self):
        """ Returns a list of :class:`~plexapi.media.SubtitleStream` objects in this MediaPart. """
        return [stream for stream in self.streams if isinstance(stream, SubtitleStream)]

    def lyricStreams(self):
        """ Returns a list of :class:`~plexapi.media.SubtitleStream` objects in this MediaPart. """
        return [stream for stream in self.streams if isinstance(stream, LyricStream)]

    def setDefaultAudioStream(self, stream):
        """ Set the default :class:`~plexapi.media.AudioStream` for this MediaPart.

            Parameters:
                stream (:class:`~plexapi.media.AudioStream`): AudioStream to set as default
        """<commit_msg>Fix typo in lyric streams doc string<commit_after># -*- coding: utf-8 -*-

import xml
from urllib.parse import quote_plus

from plexapi import log, settings, utils
from plexapi.base import PlexObject
from plexapi.exceptions import BadRequest


@utils.registerPlexObject
class Media(PlexObject):
    """ Container object for all MediaPart objects. Provides useful data about the
        video or audio this media belong to such as video framerate, resolution, etc.

        Attributes:
            TAG (str): 'Media'
            aspectRatio (float): The aspect ratio of the media (ex: 2.35).
            audioChannels (int): The number of audio channels of the media (ex: 6).
            audioCodec (str): The audio codec of the media (ex: ac3).
            audioProfile (str): The audio profile of the media (ex: dts).
            bitrate (int): The bitrate of the media (ex: 1624).
            container (str): The container of the media (ex: avi).
            duration (int): The duration of the media in milliseconds (ex: 6990483).
            height (int): The height of the media in pixels (ex: 256).
            id (int): The unique ID for this media on the server.
            has64bitOffsets (bool): True if video has 64 bit offsets.
            optimizedForStreaming (bool): True if video is optimized for streaming.
            parts (List<:class:`~plexapi.media.MediaPart`>): List of media part objects.
            proxyType (int): Equals 42 for optimized versions.
            target (str): The media version target name.
            title (str): The title of the media.
            videoCodec (str): The video codec of the media (ex: ac3).
            videoFrameRate (str): The video frame rate of the media (ex: 24p).
            videoProfile (str): The video profile of the media (ex: high).
            videoResolution (str): The video resolution of the media (ex: sd).
            width (int): The width of the video in pixels (ex: 608).

            <Photo_only_attributes>: The following attributes are only available for photos.

                * aperture (str): The apeture used to take the photo.
                * exposure (str): The exposure used to take the photo.
                * iso (int): The iso used to take the photo.
                * lens (str): The lens used to take the photo.
                * make (str): The make of the camera used to take the photo.
                * model (str): The model of the camera used to take the photo.
    """
    TAG = 'Media'

    def _loadData(self, data):
        """ Load attribute values from Plex XML response. """
        self._data = data
        self.aspectRatio = utils.cast(float, data.attrib.get('aspectRatio'))
        self.audioChannels = utils.cast(int, data.attrib.get('audioChannels'))
        self.audioCodec = data.attrib.get('audioCodec')
        self.audioProfile = data.attrib.get('audioProfile')
        self.bitrate = utils.cast(int, data.attrib.get('bitrate'))
        self.container = data.attrib.get('container')
        self.duration = utils.cast(int, data.attrib.get('duration'))
        self.height = utils.cast(int, data.attrib.get('height'))
        self.id = utils.cast(int, data.attrib.get('id'))
        self.has64bitOffsets = utils.cast(bool, data.attrib.get('has64bitOffsets'))
        self.optimizedForStreaming = utils.cast(bool, data.attrib.get('optimizedForStreaming'))
        self.parts = self.findItems(data, MediaPart)
        self.proxyType = utils.cast(int, data.attrib.get('proxyType'))
        self.target = data.attrib.get('target')
        self.title = data.attrib.get('title')
        self.videoCodec = data.attrib.get('videoCodec')
        self.videoFrameRate = data.attrib.get('videoFrameRate')
        self.videoProfile = data.attrib.get('videoProfile')
        self.videoResolution = data.attrib.get('videoResolution')
        self.width = utils.cast(int, data.attrib.get('width'))

        if self._isChildOf(etag='Photo'):
            self.aperture = data.attrib.get('aperture')
            self.exposure = data.attrib.get('exposure')
            self.iso = utils.cast(int, data.attrib.get('iso'))
            self.lens = data.attrib.get('lens')
            self.make = data.attrib.get('make')
            self.model = data.attrib.get('model')

    @property
    def isOptimizedVersion(self):
        """ Returns True if the media is a Plex optimized version. """
        return self.proxyType == utils.SEARCHTYPES['optimizedVersion']

    def delete(self):
        part = self._initpath + '/media/%s' % self.id
        try:
            return self._server.query(part, method=self._server._session.delete)
        except BadRequest:
            log.error("Failed to delete %s. This could be because you havn't allowed "
                      "items to be deleted" % part)
            raise


@utils.registerPlexObject
class MediaPart(PlexObject):
    """ Represents a single media part (often a single file) for the media this belongs to.

        Attributes:
            TAG (str): 'Part'
            accessible (bool): True if the file is accessible.
            audioProfile (str): The audio profile of the file.
            container (str): The container type of the file (ex: avi).
            decision (str): Unknown.
            deepAnalysisVersion (int): The Plex deep analysis version for the file.
            duration (int): The duration of the file in milliseconds.
            exists (bool): True if the file exists.
            file (str): The path to this file on disk (ex: /media/Movies/Cars (2006)/Cars (2006).mkv)
            has64bitOffsets (bool): True if the file has 64 bit offsets.
            hasThumbnail (bool): True if the file (track) has an embedded thumbnail.
            id (int): The unique ID for this media part on the server.
            indexes (str, None): sd if the file has generated preview (BIF) thumbnails.
            key (str): API URL (ex: /library/parts/46618/1389985872/file.mkv).
            optimizedForStreaming (bool): True if the file is optimized for streaming.
            packetLength (int): The packet length of the file.
            requiredBandwidths (str): The required bandwidths to stream the file.
            size (int): The size of the file in bytes (ex: 733884416).
            streams (List<:class:`~plexapi.media.MediaPartStream`>): List of stream objects.
            syncItemId (int): The unique ID for this media part if it is synced.
            syncState (str): The sync state for this media part.
            videoProfile (str): The video profile of the file.
    """
    TAG = 'Part'

    def _loadData(self, data):
        """ Load attribute values from Plex XML response. """
        self._data = data
        self.accessible = utils.cast(bool, data.attrib.get('accessible'))
        self.audioProfile = data.attrib.get('audioProfile')
        self.container = data.attrib.get('container')
        self.decision = data.attrib.get('decision')
        self.deepAnalysisVersion = utils.cast(int, data.attrib.get('deepAnalysisVersion'))
        self.duration = utils.cast(int, data.attrib.get('duration'))
        self.exists = utils.cast(bool, data.attrib.get('exists'))
        self.file = data.attrib.get('file')
        self.has64bitOffsets = utils.cast(bool, data.attrib.get('has64bitOffsets'))
        self.hasThumbnail = utils.cast(bool, data.attrib.get('hasThumbnail'))
        self.id = utils.cast(int, data.attrib.get('id'))
        self.indexes = data.attrib.get('indexes')
        self.key = data.attrib.get('key')
        self.optimizedForStreaming = utils.cast(bool, data.attrib.get('optimizedForStreaming'))
        self.packetLength = utils.cast(int, data.attrib.get('packetLength'))
        self.requiredBandwidths = data.attrib.get('requiredBandwidths')
        self.size = utils.cast(int, data.attrib.get('size'))
        self.streams = self._buildStreams(data)
        self.syncItemId = utils.cast(int, data.attrib.get('syncItemId'))
        self.syncState = data.attrib.get('syncState')
        self.videoProfile = data.attrib.get('videoProfile')

    def _buildStreams(self, data):
        streams = []
        for cls in (VideoStream, AudioStream, SubtitleStream, LyricStream):
            items = self.findItems(data, cls, streamType=cls.STREAMTYPE)
            streams.extend(items)
        return streams

    @property
    def hasPreviewThumbnails(self):
        """ Returns True if the media part has generated preview (BIF) thumbnails. """
        return self.indexes == 'sd'

    def videoStreams(self):
        """ Returns a list of :class:`~plexapi.media.VideoStream` objects in this MediaPart. """
        return [stream for stream in self.streams if isinstance(stream, VideoStream)]

    def audioStreams(self):
        """ Returns a list of :class:`~plexapi.media.AudioStream` objects in this MediaPart. """
        return [stream for stream in self.streams if isinstance(stream, AudioStream)]

    def subtitleStreams(self):
        """ Returns a list of :class:`~plexapi.media.SubtitleStream` objects in this MediaPart. """
        return [stream for stream in self.streams if isinstance(stream, SubtitleStream)]

    def lyricStreams(self):
        """ Returns a list of :class:`~plexapi.media.LyricStream` objects in this MediaPart. """
        return [stream for stream in self.streams if isinstance(stream, LyricStream)]

    def setDefaultAudioStream(self, stream):
        """ Set the default :class:`~plexapi.media.AudioStream` for this MediaPart.

            Parameters:
                stream (:class:`~plexapi.media.AudioStream`): AudioStream to set as default
        """
{'fraction_non_alphanumeric': 0.11029029237332223, 'fraction_numerical': 0.007907605868275934, 'mean_word_length': 2.5777033314721756, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, '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': '6564626', 'n_tokens_mistral': 5508, 'n_tokens_neox': 5346, 'n_words': 1714}