<commit_before>import logging
import os
import urllib
from xml.etree.ElementTree import fromstring
try:  # XML Exception class import dance
    from xml.etree.ElementTree import ParseError
except ImportError:  # python 2.6
    from xml.parsers.expat import ExpatError as ParseError

import requests

from .import errors


class BaseLibrary(object):
    def __init__(self, show, season, episode, cache):
        self.cache = cache
        self.show = show
        self.season = season
        self.episode = episode

        self.log.info('Searching: {0}'.format(self.show))
        self.set_show_id()

        self.set_episode_title(self.build_episode_url())

    def build_episode_url(self):
        raise NotImplementedError

    def build_id_url(self, quoted_show):
        raise NotImplementedError

    def get_cache_dir(self, show):
        show = show.lower().replace(' ', '_')  # sanitise show name
        module = self.__class__.__name__.lower()
        config_dir = os.path.expanduser('~/.tvrenamr')
        cache_dir = os.path.join(config_dir, 'cache', module, show)
        if not os.path.exists(cache_dir):
            os.makedirs(cache_dir)
        return cache_dir

    def get_episode_title_from_xml(self, xml):
        raise NotImplementedError

    def get_show_id_from_xml(self, xml):
        raise NotImplementedError

    def request_show_id(self, show, cache):
        try:
            quoted_show = urllib.parse.quote(self.show)
        except AttributeError:  # python 2
            quoted_show = urllib.quote(self.show)

        url = self.build_id_url(quoted_show)
        self.log.debug('Series url: {0}'.format(url))

        req = requests.get(url)
        if not req.ok:
            raise errors.NoNetworkConnectionException('thetvdb.com')
        if self.cache:
            with open(cache, 'w') as f:
                f.write(req.text)
        return req.text

    def set_episode_title(self, url):
        self.log.debug('Episode URL: {0}'.format(url))

        self.log.debug('Attempting to retrieve episode title')
        req = requests.get(url)
        if not req.ok:
            args = (self.log.name, self.show, self.season, self.episode)
            raise errors.EpisodeNotFoundException(*args)
        self.log.debug('XML: Retreived')

        self.log.debug('XML: Attempting to parse')
        try:
            tree = fromstring(req.content)
        except ParseError:
            raise errors.InvalidXMLException(self.log.name, self.show)
        if tree is None:
            raise errors.InvalidXMLException(self.log.name, self.show)
        args = (self.show, self.season, self.episode.zfill(2))
        self.log.debug('XML: Episode document retrived for {0} - {1}{2}'.format(*args))

        self.log.debug('XML: Attempting to find the episode title')
        self.title = self.get_episode_title_from_xml(tree)

        self.log.debug('Retrieved episode title: {0}'.format(self.title))

    def set_show_id(self):
        self.log.debug('Retrieving series id for {0}'.format(self.show))

        cache = os.path.join(self.get_cache_dir(self.show), 'show_id')
        try:
            if not self.cache:
                raise IOError
            with open(cache, 'r') as f:
                xml = f.read()
        except IOError:
            xml = self.request_show_id(self.show, cache)

        try:
            xml = xml.encode('utf-8')  # deal with py2 faff
        except UnicodeEncodeError:
            pass

        self.log.debug('XML: Attempting to parse')
        try:
            tree = fromstring(xml)
        except ParseError:
            raise errors.InvalidXMLException(self.log.name, self.show)
        if tree is None or len(tree) is 0:
            raise errors.InvalidXMLException(self.log.name, self.show)
        self.log.debug('XML: Parsed')

        self.show_id, self.show = self.get_show_id_from_xml(tree)
        self.log.debug('Retrieved show id: {0}'.format(self.show_id))
        self.log.debug('Retrieved canonical show name: {0}'.format(self.show))


class TheTvDb(BaseLibrary):
    log = logging.getLogger('The Tv DB')
    url_base = 'http://www.thetvdb.com/api/'

    def build_episode_url(self):
        apikey = '<KEY>'
        episode = str(int(self.episode))
        season = str(int(self.season))
        args = (self.url_base, apikey, self.show_id, season, episode)
        return '{0}{1}/series/{2}/default/{3}/{4}/en.xml'.format(*args)

    def build_id_url(self, quoted_show):
        url_series = 'GetSeries.php?seriesname='<commit_msg>Rely on string formatting to deal with ints in the api url<commit_after>import logging
import os
import urllib
from xml.etree.ElementTree import fromstring
try:  # XML Exception class import dance
    from xml.etree.ElementTree import ParseError
except ImportError:  # python 2.6
    from xml.parsers.expat import ExpatError as ParseError

import requests

from .import errors


class BaseLibrary(object):
    def __init__(self, show, season, episode, cache):
        self.cache = cache
        self.show = show
        self.season = season
        self.episode = episode

        self.log.info('Searching: {0}'.format(self.show))
        self.set_show_id()

        self.set_episode_title(self.build_episode_url())

    def build_episode_url(self):
        raise NotImplementedError

    def build_id_url(self, quoted_show):
        raise NotImplementedError

    def get_cache_dir(self, show):
        show = show.lower().replace(' ', '_')  # sanitise show name
        module = self.__class__.__name__.lower()
        config_dir = os.path.expanduser('~/.tvrenamr')
        cache_dir = os.path.join(config_dir, 'cache', module, show)
        if not os.path.exists(cache_dir):
            os.makedirs(cache_dir)
        return cache_dir

    def get_episode_title_from_xml(self, xml):
        raise NotImplementedError

    def get_show_id_from_xml(self, xml):
        raise NotImplementedError

    def request_show_id(self, show, cache):
        try:
            quoted_show = urllib.parse.quote(self.show)
        except AttributeError:  # python 2
            quoted_show = urllib.quote(self.show)

        url = self.build_id_url(quoted_show)
        self.log.debug('Series url: {0}'.format(url))

        req = requests.get(url)
        if not req.ok:
            raise errors.NoNetworkConnectionException('thetvdb.com')
        if self.cache:
            with open(cache, 'w') as f:
                f.write(req.text)
        return req.text

    def set_episode_title(self, url):
        self.log.debug('Episode URL: {0}'.format(url))

        self.log.debug('Attempting to retrieve episode title')
        req = requests.get(url)
        if not req.ok:
            args = (self.log.name, self.show, self.season, self.episode)
            raise errors.EpisodeNotFoundException(*args)
        self.log.debug('XML: Retreived')

        self.log.debug('XML: Attempting to parse')
        try:
            tree = fromstring(req.content)
        except ParseError:
            raise errors.InvalidXMLException(self.log.name, self.show)
        if tree is None:
            raise errors.InvalidXMLException(self.log.name, self.show)
        args = (self.show, self.season, self.episode.zfill(2))
        self.log.debug('XML: Episode document retrived for {0} - {1}{2}'.format(*args))

        self.log.debug('XML: Attempting to find the episode title')
        self.title = self.get_episode_title_from_xml(tree)

        self.log.debug('Retrieved episode title: {0}'.format(self.title))

    def set_show_id(self):
        self.log.debug('Retrieving series id for {0}'.format(self.show))

        cache = os.path.join(self.get_cache_dir(self.show), 'show_id')
        try:
            if not self.cache:
                raise IOError
            with open(cache, 'r') as f:
                xml = f.read()
        except IOError:
            xml = self.request_show_id(self.show, cache)

        try:
            xml = xml.encode('utf-8')  # deal with py2 faff
        except UnicodeEncodeError:
            pass

        self.log.debug('XML: Attempting to parse')
        try:
            tree = fromstring(xml)
        except ParseError:
            raise errors.InvalidXMLException(self.log.name, self.show)
        if tree is None or len(tree) is 0:
            raise errors.InvalidXMLException(self.log.name, self.show)
        self.log.debug('XML: Parsed')

        self.show_id, self.show = self.get_show_id_from_xml(tree)
        self.log.debug('Retrieved show id: {0}'.format(self.show_id))
        self.log.debug('Retrieved canonical show name: {0}'.format(self.show))


class TheTvDb(BaseLibrary):
    log = logging.getLogger('The Tv DB')
    url_base = 'http://www.thetvdb.com/api/'

    def build_episode_url(self):
        apikey = '<KEY>'
        args = (self.url_base, apikey, self.show_id, self.season, self.episode)
        return '{0}{1}/series/{2}/default/{3}/{4}/en.xml'.format(*args)

    def build_id_url(self, quoted_show):
        url_series = 'GetSeries.php?seriesname='
{'fraction_non_alphanumeric': 0.11420334848652844, 'fraction_numerical': 0.00487858964408471, 'mean_word_length': 2.432267884322679, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 30}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5410464', 'n_tokens_mistral': 2871, 'n_tokens_neox': 2774, 'n_words': 614}