From f54a6e25b258151ab00c1b724069166665f2bf44 Mon Sep 17 00:00:00 2001 From: echel0n Date: Tue, 22 Apr 2014 12:15:15 -0700 Subject: [PATCH] Fixes issues with tvdb and tvrage api content attribute not found --- lib/tvdb_api/tvdb_api.py | 83 ++++++++++++++++++++--------------- lib/tvrage_api/tvrage_api.py | 79 +++++++++++++++++++++------------ sickbeard/databases/mainDB.py | 6 +-- 3 files changed, 100 insertions(+), 68 deletions(-) diff --git a/lib/tvdb_api/tvdb_api.py b/lib/tvdb_api/tvdb_api.py index 14c74412..0ca2a2f9 100644 --- a/lib/tvdb_api/tvdb_api.py +++ b/lib/tvdb_api/tvdb_api.py @@ -5,15 +5,8 @@ #repository:http://github.com/dbr/tvdb_api #license:unlicense (http://unlicense.org/) -"""Simple-to-use Python interface to The TVDB's API (thetvdb.com) +from functools import wraps -Example usage: - ->>> from tvdb_api import Tvdb ->>> t = Tvdb() ->>> t['Lost'][4][11]['episodename'] -u'Cabin Fever' -""" __author__ = "dbr/Ben" __version__ = "1.9" @@ -25,6 +18,8 @@ import tempfile import warnings import logging import zipfile +import requests +import cachecontrol try: import xml.etree.cElementTree as ElementTree @@ -36,10 +31,7 @@ try: except ImportError: gzip = None -from lib import requests -from lib.requests import exceptions -from lib import cachecontrol -from lib.cachecontrol import caches +from cachecontrol import caches from tvdb_ui import BaseUI, ConsoleUI from tvdb_exceptions import (tvdb_error, tvdb_userabort, tvdb_shownotfound, @@ -48,6 +40,48 @@ from tvdb_exceptions import (tvdb_error, tvdb_userabort, tvdb_shownotfound, def log(): return logging.getLogger("tvdb_api") +def retry(ExceptionToCheck, tries=4, delay=3, backoff=2, logger=None): + """Retry calling the decorated function using an exponential backoff. + + http://www.saltycrane.com/blog/2009/11/trying-out-retry-decorator-python/ + original from: http://wiki.python.org/moin/PythonDecoratorLibrary#Retry + + :param ExceptionToCheck: the exception to check. may be a tuple of + exceptions to check + :type ExceptionToCheck: Exception or tuple + :param tries: number of times to try (not retry) before giving up + :type tries: int + :param delay: initial delay between retries in seconds + :type delay: int + :param backoff: backoff multiplier e.g. value of 2 will double the delay + each retry + :type backoff: int + :param logger: logger to use. If None, print + :type logger: logging.Logger instance + """ + + def deco_retry(f): + + @wraps(f) + def f_retry(*args, **kwargs): + mtries, mdelay = tries, delay + while mtries > 1: + try: + return f(*args, **kwargs) + except ExceptionToCheck, e: + msg = "%s, Retrying in %d seconds..." % (str(e), mdelay) + if logger: + logger.warning(msg) + else: + print msg + time.sleep(mdelay) + mtries -= 1 + mdelay *= backoff + return f(*args, **kwargs) + + return f_retry # true decorator + + return deco_retry class ShowContainer(dict): """Simple dict that holds a series of Show instances @@ -509,27 +543,7 @@ class Tvdb: return os.path.join(tempfile.gettempdir(), "tvdb_api-%s" % (uid)) - - def retry(ExceptionToCheck, tries=4, delay=3, backoff=2): - def deco_retry(f): - def f_retry(*args, **kwargs): - mtries, mdelay = tries, delay - while mtries > 0: - try: - return f(*args, **kwargs) - except ExceptionToCheck, e: - print "%s, Retrying in %d seconds..." % (str(e), mdelay) - time.sleep(mdelay) - mtries -= 1 - mdelay *= backoff - lastException = e - raise lastException - - return f_retry # true decorator - - return deco_retry - - @retry(tvdb_error, tries=4) + @retry(tvdb_error) def _loadUrl(self, url, params=None, language=None): try: log().debug("Retrieving URL %s" % url) @@ -549,9 +563,6 @@ class Tvdb: except requests.Timeout, e: raise tvdb_error("Connection timed out " + str(e.message) + " while loading URL " + str(url)) - except Exception, e: - raise tvdb_error("Unknown exception occured: " + str(e.message) + " while loading URL " + str(url)) - if 'application/zip' in resp.headers.get("Content-Type", '') and resp.ok: try: # TODO: The zip contains actors.xml and banners.xml, which are currently ignored [GH-20] diff --git a/lib/tvrage_api/tvrage_api.py b/lib/tvrage_api/tvrage_api.py index 9506ad5d..7c26ab62 100644 --- a/lib/tvrage_api/tvrage_api.py +++ b/lib/tvrage_api/tvrage_api.py @@ -9,32 +9,29 @@ Modified from http://github.com/dbr/tvrage_api Simple-to-use Python interface to The TVRage's API (tvrage.com) """ +from functools import wraps + __author__ = "echel0n" __version__ = "1.0" import os import re import time -import urllib import getpass import tempfile import warnings import logging -import StringIO -import zipfile import datetime as dt +import requests +import cachecontrol try: import xml.etree.cElementTree as ElementTree except ImportError: import xml.etree.ElementTree as ElementTree -from lib.dateutil.parser import parse - -from lib import requests -from lib.requests import exceptions -from lib import cachecontrol -from lib.cachecontrol import caches +from dateutil.parser import parse +from cachecontrol import caches from tvrage_ui import BaseUI from tvrage_exceptions import (tvrage_error, tvrage_userabort, tvrage_shownotfound, @@ -43,6 +40,49 @@ from tvrage_exceptions import (tvrage_error, tvrage_userabort, tvrage_shownotfou def log(): return logging.getLogger("tvrage_api") +def retry(ExceptionToCheck, tries=4, delay=3, backoff=2, logger=None): + """Retry calling the decorated function using an exponential backoff. + + http://www.saltycrane.com/blog/2009/11/trying-out-retry-decorator-python/ + original from: http://wiki.python.org/moin/PythonDecoratorLibrary#Retry + + :param ExceptionToCheck: the exception to check. may be a tuple of + exceptions to check + :type ExceptionToCheck: Exception or tuple + :param tries: number of times to try (not retry) before giving up + :type tries: int + :param delay: initial delay between retries in seconds + :type delay: int + :param backoff: backoff multiplier e.g. value of 2 will double the delay + each retry + :type backoff: int + :param logger: logger to use. If None, print + :type logger: logging.Logger instance + """ + + def deco_retry(f): + + @wraps(f) + def f_retry(*args, **kwargs): + mtries, mdelay = tries, delay + while mtries > 1: + try: + return f(*args, **kwargs) + except ExceptionToCheck, e: + msg = "%s, Retrying in %d seconds..." % (str(e), mdelay) + if logger: + logger.warning(msg) + else: + print msg + time.sleep(mdelay) + mtries -= 1 + mdelay *= backoff + return f(*args, **kwargs) + + return f_retry # true decorator + + return deco_retry + class ShowContainer(dict): """Simple dict that holds a series of Show instances """ @@ -343,26 +383,7 @@ class TVRage: return os.path.join(tempfile.gettempdir(), "tvrage_api-%s" % (uid)) - def retry(ExceptionToCheck, tries=4, delay=3, backoff=2): - def deco_retry(f): - def f_retry(*args, **kwargs): - mtries, mdelay = tries, delay - while mtries > 0: - try: - return f(*args, **kwargs) - except ExceptionToCheck, e: - print "%s, Retrying in %d seconds..." % (str(e), mdelay) - time.sleep(mdelay) - mtries -= 1 - mdelay *= backoff - lastException = e - raise lastException - - return f_retry # true decorator - - return deco_retry - - @retry(tvrage_error, tries=4) + @retry(tvrage_error) def _loadUrl(self, url, params=None): try: log().debug("Retrieving URL %s" % url) diff --git a/sickbeard/databases/mainDB.py b/sickbeard/databases/mainDB.py index 232d8280..36da6d78 100644 --- a/sickbeard/databases/mainDB.py +++ b/sickbeard/databases/mainDB.py @@ -102,17 +102,17 @@ class MainSanityCheck(db.DBSanityCheck): def fix_missing_table_indexes(self): try: - self.connection.action("CREATE UNIQUE INDEX idx_indexer_id ON tv_shows (indexer_id);") + sqlResults = self.connection.action("CREATE UNIQUE INDEX idx_indexer_id ON tv_shows (indexer_id);") logger.log(u"Missing idx_indexer_id for TV Shows table added!") except:pass try: - self.connection.action("CREATE INDEX idx_tv_episodes_showid_airdate ON tv_episodes(showid,airdate);") + sqlResults = self.connection.action("CREATE INDEX idx_tv_episodes_showid_airdate ON tv_episodes(showid,airdate);") logger.log(u"Missing idx_tv_episodes_showid_airdate for TV Episodes table added!") except:pass try: - self.connection.action("CREATE INDEX idx_showid ON tv_episodes (showid);") + sqlResults = self.connection.action("CREATE INDEX idx_showid ON tv_episodes (showid);") logger.log(u"Missing idx_showid for TV Episodes table added!") except:pass