diff --git a/sickbeard/clients/__init__.py b/sickbeard/clients/__init__.py index ddc11114af7adfac01cef01991ef12ae81616aa5..f1e67523c4484d193c3389757158f6dd91d8fd3f 100644 --- a/sickbeard/clients/__init__.py +++ b/sickbeard/clients/__init__.py @@ -28,82 +28,6 @@ __all__ = [ 'mlnet' ] -# Mapping error status codes to official W3C names -http_error_code = { - # todo: Handle error codes with duplicates (e.g. 451, 499) - 300: 'Multiple Choices', - 301: 'Moved Permanently', - 302: 'Found', - 303: 'See Other', - 304: 'Not Modified', - 305: 'Use Proxy', - 306: 'Switch Proxy', - 307: 'Temporary Redirect', - 308: 'Permanent Redirect', - 400: 'Bad Request', - 401: 'Unauthorized', - 402: 'Payment Required', - 403: 'Forbidden', - 404: 'Not Found', - 405: 'Method Not Allowed', - 406: 'Not Acceptable', - 407: 'Proxy Authentication Required', - 408: 'Request Timeout', - 409: 'Conflict', - 410: 'Gone', - 411: 'Length Required', - 412: 'Precondition Failed', - 413: 'Request Entity Too Large', - 414: 'Request-URI Too Long', - 415: 'Unsupported Media Type', - 416: 'Requested Range Not Satisfiable', - 417: 'Expectation Failed', - 418: 'Im a teapot', - 419: 'Authentication Timeout', - 420: 'Enhance Your Calm', - 422: 'Unprocessable Entity', - 423: 'Locked', - 424: 'Failed Dependency', - 426: 'Upgrade Required', - 428: 'Precondition Required', - 429: 'Too Many Requests', - 431: 'Request Header Fields Too Large', - 440: 'Login Timeout', - 444: 'No Response', - 449: 'Retry With', - 450: 'Blocked by Windows Parental Controls', - 451: 'Redirect', - 451: 'Unavailable For Legal Reasons', - 494: 'Request Header Too Large', - 495: 'Cert Error', - 496: 'No Cert', - 497: 'HTTP to HTTPS', - 498: 'Token expired/invalid', - 499: 'Client Closed Request', - 499: 'Token required', - 500: 'Internal Server Error', - 501: 'Not Implemented', - 502: 'Bad Gateway', - 503: 'Service Unavailable', - 504: 'Gateway Timeout', - 505: 'HTTP Version Not Supported', - 506: 'Variant Also Negotiates', - 507: 'Insufficient Storage', - 508: 'Loop Detected', - 509: 'Bandwidth Limit Exceeded', - 510: 'Not Extended', - 511: 'Network Authentication Required', - 520: 'Cloudfare - Web server is returning an unknown error', - 521: 'Cloudfare - Web server is down', - 522: 'Cloudfare - Connection timed out', - 523: 'Cloudfare - Origin is unreachable', - 524: 'Cloudfare - A timeout occurred', - 525: 'Cloudfare - SSL handshake failed', - 526: 'Cloudfare - Invalid SSL certificate', - 598: 'Network read timeout error', - 599: 'Network connect timeout error ' -} - default_host = { 'utorrent': 'http://localhost:8000', 'transmission': 'http://localhost:9091', diff --git a/sickbeard/clients/generic.py b/sickbeard/clients/generic.py index 945554403af1025bdf6606f78c9b2f0a8946c00d..2109da630a568984ea4cb3c5c78d92541ee165b3 100644 --- a/sickbeard/clients/generic.py +++ b/sickbeard/clients/generic.py @@ -7,10 +7,10 @@ from base64 import b16encode, b32decode import sickbeard from sickbeard import logger -from sickbeard.clients import http_error_code from bencode import bencode, bdecode import requests from bencode.BTL import BTFailure +from sickrage.helper.common import http_code_description class GenericClient(object): @@ -66,8 +66,10 @@ class GenericClient(object): logger.log(self.name + u': Invalid Username or Password, check your config', logger.ERROR) return False - if self.response.status_code in http_error_code.keys(): - logger.log(self.name + u': ' + http_error_code[self.response.status_code], logger.DEBUG) + code_description = http_code_description(self.response.status_code) + + if code_description is not None: + logger.log(self.name + u': ' + code_description, logger.DEBUG) return False logger.log(self.name + u': Response to ' + method.upper() + ' request is ' + self.response.text, logger.DEBUG) diff --git a/sickbeard/helpers.py b/sickbeard/helpers.py index e35c57295f5028a9bced3c5056d08bb414e96859..fee409f69e41018b74e8e7d3b832574bca80a0af 100644 --- a/sickbeard/helpers.py +++ b/sickbeard/helpers.py @@ -52,8 +52,7 @@ from sickbeard import logger, classes from sickbeard.common import USER_AGENT from sickbeard import db from sickbeard.notifiers.synoindex import notifier as synoindex_notifier -from sickbeard import clients -from sickrage.helper.common import media_extensions, pretty_file_size, subtitle_extensions +from sickrage.helper.common import http_code_description, media_extensions, pretty_file_size, subtitle_extensions from sickrage.helper.encoding import ek from sickrage.helper.exceptions import ex from sickrage.show.Show import Show @@ -955,22 +954,6 @@ def restoreVersionedFile(backup_file, version): return True -# try to convert to int, if it fails the default will be returned -def tryInt(s, s_default=0): - """ - Try to convert to int, if it fails, the default will be returned - - :param s: Value to attempt to convert to int - :param s_default: Default value to return on failure (defaults to 0) - :return: integer, or default value on failure - """ - - try: - return int(s) - except Exception: - return s_default - - # generates a md5 hash of a file def md5_for_file(filename, block_size=2 ** 16): """ @@ -1420,17 +1403,6 @@ def _getTempDir(): return ek(os.path.join, tempfile.gettempdir(), "sickrage-%s" % uid) -def codeDescription(status_code): - """ - Returns the description of the URL error code - """ - if status_code in clients.http_error_code: - return clients.http_error_code[status_code] - else: - logger.log(u"Unknown error code: %s. Please submit an issue" % status_code, logger.ERROR) - return 'unknown' - - def _setUpSession(session, headers): """ Returns a session initialized with default cache and parameter settings @@ -1504,7 +1476,7 @@ def getURL(url, post_data=None, params=None, headers=None, timeout=30, session=N if not resp.ok: logger.log(u"Requested getURL %s returned status code is %s: %s" - % (url, resp.status_code, codeDescription(resp.status_code)), logger.DEBUG) + % (url, resp.status_code, http_code_description(resp.status_code)), logger.DEBUG) return None except (SocketTimeout, TypeError) as e: @@ -1549,7 +1521,7 @@ def download_file(url, filename, session=None, headers=None): with closing(session.get(url, allow_redirects=True, verify=session.verify)) as resp: if not resp.ok: logger.log(u"Requested download url %s returned status code is %s: %s" - % (url, resp.status_code, codeDescription(resp.status_code)), logger.DEBUG) + % (url, resp.status_code, http_code_description(resp.status_code)), logger.DEBUG) return False try: diff --git a/sickbeard/network_timezones.py b/sickbeard/network_timezones.py index 15f09d15b2df9a4e9e2ec56596c2cbcd42e28da4..ae1b2eafeaee808dc8886f6f7457b30abad172fc 100644 --- a/sickbeard/network_timezones.py +++ b/sickbeard/network_timezones.py @@ -25,6 +25,7 @@ from dateutil import tz from sickbeard import db from sickbeard import helpers from sickbeard import logger +from sickrage.helper.common import try_int # regex to parse time (12/24 hour format) time_regex = re.compile(r'(\d{1,2})(([:.](\d{2,2}))? ?([PA][. ]? ?M)|[:.](\d{2,2}))\b', flags=re.IGNORECASE) @@ -136,8 +137,8 @@ def parse_date_time(d, t, network): if mo is not None and len(mo.groups()) >= 5: if mo.group(5) is not None: try: - hr = helpers.tryInt(mo.group(1)) - m = helpers.tryInt(mo.group(4)) + hr = try_int(mo.group(1)) + m = try_int(mo.group(4)) ap = mo.group(5) # convert am/pm to 24 hour clock if ap is not None: @@ -150,8 +151,8 @@ def parse_date_time(d, t, network): m = 0 else: try: - hr = helpers.tryInt(mo.group(1)) - m = helpers.tryInt(mo.group(6)) + hr = try_int(mo.group(1)) + m = try_int(mo.group(6)) except Exception: hr = 0 m = 0 @@ -162,7 +163,7 @@ def parse_date_time(d, t, network): hr = 0 m = 0 - te = datetime.datetime.fromordinal(helpers.tryInt(d) or 1) + te = datetime.datetime.fromordinal(try_int(d) or 1) try: foreign_timezone = get_network_timezone(network, network_dict) return datetime.datetime(te.year, te.month, te.day, hr, m, tzinfo=foreign_timezone) diff --git a/sickbeard/nzbget.py b/sickbeard/nzbget.py index 5e12b521aac631e9e36b8b9290dd5dbaf6860891..d5ea16b16663353cbf76284df0966f9d94e473f1 100644 --- a/sickbeard/nzbget.py +++ b/sickbeard/nzbget.py @@ -17,7 +17,6 @@ # You should have received a copy of the GNU General Public License # along with SickRage. If not, see <http://www.gnu.org/licenses/>. - import httplib import datetime from base64 import standard_b64encode @@ -25,8 +24,9 @@ import xmlrpclib import sickbeard from sickbeard.providers.generic import GenericProvider -from sickbeard import logger, helpers +from sickbeard import logger from sickbeard.common import Quality +from sickrage.helper.common import try_int def sendNZB(nzb, proper=False): @@ -108,7 +108,7 @@ def sendNZB(nzb, proper=False): try: # Find out if nzbget supports priority (Version 9.0+), old versions beginning with a 0.x will use the old command nzbget_version_str = nzbGetRPC.version() - nzbget_version = helpers.tryInt(nzbget_version_str[:nzbget_version_str.find(".")]) + nzbget_version = try_int(nzbget_version_str[:nzbget_version_str.find(".")]) if nzbget_version == 0: if nzbcontent64 is not None: nzbget_result = nzbGetRPC.append(nzb.name + ".nzb", category, addToTop, nzbcontent64) diff --git a/sickbeard/providers/bitsnoop.py b/sickbeard/providers/bitsnoop.py index 8ae8d316b4ad860371f8a7c35b4752f692d1abf7..1a9b5857fe4c5b7297cd3027f6620732c9196a36 100644 --- a/sickbeard/providers/bitsnoop.py +++ b/sickbeard/providers/bitsnoop.py @@ -22,8 +22,8 @@ from bs4 import BeautifulSoup import sickbeard from sickbeard import logger from sickbeard import tvcache -from sickbeard.helpers import tryInt from sickbeard.providers import generic +from sickrage.helper.common import try_int class BitSnoopProvider(generic.TorrentProvider): # pylint: disable=R0902,R0913 @@ -90,9 +90,9 @@ class BitSnoopProvider(generic.TorrentProvider): # pylint: disable=R0902,R0913 if not (title and download_url): continue - seeders = tryInt(item.find('numseeders').text, 0) - leechers = tryInt(item.find('numleechers').text, 0) - size = tryInt(item.find('size').text, -1) + seeders = try_int(item.find('numseeders').text, 0) + leechers = try_int(item.find('numleechers').text, 0) + size = try_int(item.find('size').text, -1) info_hash = item.find('infohash').text diff --git a/sickbeard/providers/extratorrent.py b/sickbeard/providers/extratorrent.py index b0ab586fcc31f68b333ef4b0c5b8e193a09e3896..e760fbbb4526351cf5867a08b72b867c0f1ec864 100644 --- a/sickbeard/providers/extratorrent.py +++ b/sickbeard/providers/extratorrent.py @@ -23,9 +23,9 @@ from xml.parsers.expat import ExpatError from sickbeard import logger from sickbeard import tvcache -from sickbeard import helpers from sickbeard.common import USER_AGENT from sickbeard.providers import generic +from sickrage.helper.common import try_int class ExtraTorrentProvider(generic.TorrentProvider): @@ -89,8 +89,8 @@ class ExtraTorrentProvider(generic.TorrentProvider): title = item['title'].decode('utf-8') # info_hash = item['info_hash'] size = int(item['size']) - seeders = helpers.tryInt(item['seeders'], 0) - leechers = helpers.tryInt(item['leechers'], 0) + seeders = try_int(item['seeders'], 0) + leechers = try_int(item['leechers'], 0) download_url = item['enclosure']['@url'] if 'enclosure' in item else self._magnet_from_details(item['link']) if not all([title, download_url]): diff --git a/sickbeard/providers/freshontv.py b/sickbeard/providers/freshontv.py index 71ac0b448a15b89ca904143beb4f209efcd3089a..c875e022d2fd4e7c8ee2ae2dffb60e69108e65e8 100644 --- a/sickbeard/providers/freshontv.py +++ b/sickbeard/providers/freshontv.py @@ -23,12 +23,12 @@ import traceback from sickbeard import logger from sickbeard import tvcache -from sickbeard.helpers import tryInt from sickbeard.providers import generic from sickbeard.bs4_parser import BS4Parser +from sickrage.helper.common import try_int -class FreshOnTVProvider(generic.TorrentProvider): +class FreshOnTVProvider(generic.TorrentProvider): def __init__(self): generic.TorrentProvider.__init__(self, "FreshOnTV") @@ -202,8 +202,8 @@ class FreshOnTVProvider(generic.TorrentProvider): details_url = individual_torrent.find('a', {'class': 'torrent_name_link'})['href'] torrent_id = int((re.match('.*?([0-9]+)$', details_url).group(1)).strip()) download_url = self.urls['download'] % (str(torrent_id)) - seeders = tryInt(individual_torrent.find('td', {'class': 'table_seeders'}).find('span').text.strip(), 1) - leechers = tryInt(individual_torrent.find('td', {'class': 'table_leechers'}).find('a').text.strip(), 0) + seeders = try_int(individual_torrent.find('td', {'class': 'table_seeders'}).find('span').text.strip(), 1) + leechers = try_int(individual_torrent.find('td', {'class': 'table_leechers'}).find('a').text.strip(), 0) # FIXME size = -1 except Exception: diff --git a/sickbeard/providers/kat.py b/sickbeard/providers/kat.py index ad8a8d57397f6339c3a8dd3d009c3a64b5e95e39..0c580a7ad7120454fd7fbac45c2817581382bd06 100755 --- a/sickbeard/providers/kat.py +++ b/sickbeard/providers/kat.py @@ -28,7 +28,8 @@ from sickbeard import logger from sickbeard import tvcache from sickbeard.common import USER_AGENT from sickbeard.providers import generic -from sickbeard.helpers import tryInt +from sickrage.helper.common import try_int + class KATProvider(generic.TorrentProvider): def __init__(self): @@ -114,10 +115,10 @@ class KATProvider(generic.TorrentProvider): if not (title and download_url): continue - seeders = tryInt(item.find('torrent:seeds').text, 0) - leechers = tryInt(item.find('torrent:peers').text, 0) - verified = bool(tryInt(item.find('torrent:verified').text, 0)) - size = tryInt(item.find('torrent:contentlength').text) + seeders = try_int(item.find('torrent:seeds').text, 0) + leechers = try_int(item.find('torrent:peers').text, 0) + verified = bool(try_int(item.find('torrent:verified').text, 0)) + size = try_int(item.find('torrent:contentlength').text) info_hash = item.find('torrent:infohash').text # link = item['link'] diff --git a/sickbeard/providers/newznab.py b/sickbeard/providers/newznab.py index 14cc97e69aed09aab5bd5615662fb4c328db183f..a250100f4ac03d750b0d67d5fb1a097d02fea98d 100644 --- a/sickbeard/providers/newznab.py +++ b/sickbeard/providers/newznab.py @@ -38,6 +38,7 @@ from sickbeard.common import Quality from sickbeard.providers import generic from sickrage.helper.encoding import ek from sickrage.show.Show import Show +from sickrage.helper.common import try_int from sickbeard.common import USER_AGENT @@ -286,11 +287,11 @@ class NewznabProvider(generic.NZBProvider): continue seeders = leechers = None - size = helpers.tryInt(item.size, -1) + size = try_int(item.size, -1) for attr in item.findAll('newznab:attr') + item.findAll('torznab:attr'): - size = helpers.tryInt(attr['value'], -1) if attr['name'] == 'size' else size - seeders = helpers.tryInt(attr['value'], 1) if attr['name'] == 'seeders' else seeders - leechers = helpers.tryInt(attr['value'], 0) if attr['name'] == 'peers' else leechers + size = try_int(attr['value'], -1) if attr['name'] == 'size' else size + seeders = try_int(attr['value'], 1) if attr['name'] == 'seeders' else seeders + leechers = try_int(attr['value'], 0) if attr['name'] == 'peers' else leechers if not size or (torznab and (seeders is None or leechers is None)): continue @@ -305,14 +306,12 @@ class NewznabProvider(generic.NZBProvider): return results - def _get_size(self, item): """ Gets size info from a result item Returns int size or -1 """ - return helpers.tryInt(item.get('size', -1), -1) - + return try_int(item.get('size', -1), -1) def findPropers(self, search_date=datetime.datetime.today()): """ diff --git a/sickbeard/providers/torrentproject.py b/sickbeard/providers/torrentproject.py index f0134ceb6f8b906886b4295e1dfd53aab542c925..b7df83d7e62b533561d7f71044ba2e62584b50d1 100644 --- a/sickbeard/providers/torrentproject.py +++ b/sickbeard/providers/torrentproject.py @@ -20,13 +20,12 @@ from urllib import quote_plus from sickbeard import logger from sickbeard import tvcache -from sickbeard import helpers from sickbeard.providers import generic from sickbeard.common import USER_AGENT +from sickrage.helper.common import try_int class TORRENTPROJECTProvider(generic.TorrentProvider): - def __init__(self): generic.TorrentProvider.__init__(self, "TorrentProject") @@ -64,8 +63,8 @@ class TORRENTPROJECTProvider(generic.TorrentProvider): results = [] for i in torrents: title = torrents[i]["title"] - seeders = helpers.tryInt(torrents[i]["seeds"], 1) - leechers = helpers.tryInt(torrents[i]["leechs"], 0) + seeders = try_int(torrents[i]["seeds"], 1) + leechers = try_int(torrents[i]["leechs"], 0) if seeders < self.minseed or leechers < self.minleech: if mode != 'RSS': logger.log(u"Torrent doesn't meet minimum seeds & leechers not selecting : %s" % title, logger.DEBUG) diff --git a/sickbeard/tv.py b/sickbeard/tv.py index a6fef33e2f81c3d978fb6543368ec3209da002b0..16c28ec76d0c33d647f26cd9d355e5564750f7aa 100644 --- a/sickbeard/tv.py +++ b/sickbeard/tv.py @@ -47,7 +47,7 @@ from sickbeard.blackandwhitelist import BlackAndWhiteList from sickbeard import network_timezones from sickbeard.indexers.indexer_config import INDEXER_TVRAGE from sickbeard.name_parser.parser import NameParser, InvalidNameException, InvalidShowException -from sickrage.helper.common import dateTimeFormat, remove_extension, replace_extension, sanitize_filename +from sickrage.helper.common import dateTimeFormat, remove_extension, replace_extension, sanitize_filename, try_int from sickrage.helper.encoding import ek from sickrage.helper.exceptions import EpisodeDeletedException, EpisodeNotFoundException, ex from sickrage.helper.exceptions import MultipleEpisodesInDatabaseException, MultipleShowsInDatabaseException @@ -1551,9 +1551,9 @@ class TVEpisode(object): sickbeard.scene_numbering.xem_refresh(self.show.indexerid, self.show.indexer) - self.scene_season = helpers.tryInt(sqlResults[0]["scene_season"], 0) - self.scene_episode = helpers.tryInt(sqlResults[0]["scene_episode"], 0) - self.scene_absolute_number = helpers.tryInt(sqlResults[0]["scene_absolute_number"], 0) + self.scene_season = try_int(sqlResults[0]["scene_season"], 0) + self.scene_episode = try_int(sqlResults[0]["scene_episode"], 0) + self.scene_absolute_number = try_int(sqlResults[0]["scene_absolute_number"], 0) if self.scene_absolute_number == 0: self.scene_absolute_number = sickbeard.scene_numbering.get_scene_absolute_numbering( diff --git a/sickbeard/webapi.py b/sickbeard/webapi.py index 199fec6f6c4a38969c7d08da985f187d0facf98f..ad07a1c54f75525f27978bd6549e22fe250ec1e7 100644 --- a/sickbeard/webapi.py +++ b/sickbeard/webapi.py @@ -31,7 +31,7 @@ import datetime import traceback import sickbeard -from sickrage.helper.common import dateFormat, dateTimeFormat, pretty_file_size, sanitize_filename, timeFormat +from sickrage.helper.common import dateFormat, dateTimeFormat, pretty_file_size, sanitize_filename, timeFormat, try_int from sickrage.helper.encoding import ek from sickrage.helper.exceptions import CantUpdateShowException, ex, ShowDirectoryNotFoundException from sickrage.helper.quality import get_quality_string @@ -746,7 +746,7 @@ class CMD_Episode(ApiCall): episode["location"] = episode["location"][show_path_length:] # convert stuff to human form - if helpers.tryInt(episode['airdate'], 1) > 693595: # 1900 + if try_int(episode['airdate'], 1) > 693595: # 1900 episode['airdate'] = sbdatetime.sbdatetime.sbfdate(sbdatetime.sbdatetime.convert_to_setting( network_timezones.parse_date_time(int(episode['airdate']), show_obj.airs, show_obj.network)), d_preset=dateFormat) else: @@ -1913,7 +1913,7 @@ class CMD_Show(ApiCall): show_dict["network"] = "" show_dict["status"] = show_obj.status - if helpers.tryInt(show_obj.nextaired, 1) > 693595: + if try_int(show_obj.nextaired, 1) > 693595: dt_episode_airs = sbdatetime.sbdatetime.convert_to_setting( network_timezones.parse_date_time(show_obj.nextaired, show_dict['airs'], show_dict['network'])) show_dict['airs'] = sbdatetime.sbdatetime.sbftime(dt_episode_airs, t_preset=timeFormat).lstrip('0').replace( @@ -2533,7 +2533,7 @@ class CMD_ShowSeasons(ApiCall): status, quality = Quality.splitCompositeStatus(int(row["status"])) row["status"] = _get_status_strings(status) row["quality"] = get_quality_string(quality) - if helpers.tryInt(row['airdate'], 1) > 693595: # 1900 + if try_int(row['airdate'], 1) > 693595: # 1900 dt_episode_airs = sbdatetime.sbdatetime.convert_to_setting( network_timezones.parse_date_time(row['airdate'], sho_obj.airs, sho_obj.network)) row['airdate'] = sbdatetime.sbdatetime.sbfdate(dt_episode_airs, d_preset=dateFormat) @@ -2560,7 +2560,7 @@ class CMD_ShowSeasons(ApiCall): status, quality = Quality.splitCompositeStatus(int(row["status"])) row["status"] = _get_status_strings(status) row["quality"] = get_quality_string(quality) - if helpers.tryInt(row['airdate'], 1) > 693595: # 1900 + if try_int(row['airdate'], 1) > 693595: # 1900 dt_episode_airs = sbdatetime.sbdatetime.convert_to_setting( network_timezones.parse_date_time(row['airdate'], sho_obj.airs, sho_obj.network)) row['airdate'] = sbdatetime.sbdatetime.sbfdate(dt_episode_airs, d_preset=dateFormat) @@ -2818,7 +2818,7 @@ class CMD_Shows(ApiCall): "subtitles": (0, 1)[curShow.subtitles], } - if helpers.tryInt(curShow.nextaired, 1) > 693595: # 1900 + if try_int(curShow.nextaired, 1) > 693595: # 1900 dt_episode_airs = sbdatetime.sbdatetime.convert_to_setting( network_timezones.parse_date_time(curShow.nextaired, curShow.airs, show_dict['network'])) show_dict['next_ep_airdate'] = sbdatetime.sbdatetime.sbfdate(dt_episode_airs, d_preset=dateFormat) diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py index c67bffbe2117ab131e57379587c84f6e35c6f3a8..ee89f8ad8d061af5a73fc46f0da2fe8e6022648c 100644 --- a/sickbeard/webserve.py +++ b/sickbeard/webserve.py @@ -53,7 +53,7 @@ from unrar2 import RarFile import adba from libtrakt import TraktAPI from libtrakt.exceptions import traktException -from sickrage.helper.common import sanitize_filename +from sickrage.helper.common import sanitize_filename, try_int from sickrage.helper.encoding import ek, ss from sickrage.helper.exceptions import CantRefreshShowException, CantUpdateShowException, ex from sickrage.helper.exceptions import MultipleShowObjectsException, NoNFOException, ShowDirectoryNotFoundException @@ -557,7 +557,7 @@ class CalendarHandler(BaseHandler): air_date_time = network_timezones.parse_date_time(episode['airdate'], show["airs"], show['network']).astimezone(utc) air_date_time_end = air_date_time + datetime.timedelta( - minutes=helpers.tryInt(show["runtime"], 60)) + minutes=try_int(show["runtime"], 60)) # Create event for episode ical += 'BEGIN:VEVENT\r\n' @@ -1370,7 +1370,7 @@ class Home(WebRoot): showObj.exceptions = sickbeard.scene_exceptions.get_scene_exceptions(showObj.indexerid) - if helpers.tryInt(quality_preset, None): + if try_int(quality_preset, None): bestQualities = [] if not location and not anyQualities and not bestQualities and not flatten_folders: @@ -2726,7 +2726,7 @@ class HomeAddShows(Home): if not anyQualities: anyQualities = [] - if not bestQualities or helpers.tryInt(quality_preset, None): + if not bestQualities or try_int(quality_preset, None): bestQualities = [] if not isinstance(anyQualities, list): anyQualities = [anyQualities] @@ -3304,7 +3304,7 @@ class Manage(Home, WebRoot): if quality_preset == 'keep': anyQualities, bestQualities = Quality.splitQuality(showObj.quality) - elif helpers.tryInt(quality_preset, None): + elif try_int(quality_preset, None): bestQualities = [] exceptions_list = [] diff --git a/sickrage/helper/common.py b/sickrage/helper/common.py index 7126687d1f40f82c4fd8e1f071fe83ce33aaa1b6..34e0f5a107321a11dbdca0fd3748ad6fde85f481 100644 --- a/sickrage/helper/common.py +++ b/sickrage/helper/common.py @@ -21,6 +21,84 @@ import sickbeard dateFormat = '%Y-%m-%d' dateTimeFormat = '%Y-%m-%d %H:%M:%S' +# Mapping HTTP status codes to official W3C names +http_status_code = { + 300: 'Multiple Choices', + 301: 'Moved Permanently', + 302: 'Found', + 303: 'See Other', + 304: 'Not Modified', + 305: 'Use Proxy', + 306: 'Switch Proxy', + 307: 'Temporary Redirect', + 308: 'Permanent Redirect', + 400: 'Bad Request', + 401: 'Unauthorized', + 402: 'Payment Required', + 403: 'Forbidden', + 404: 'Not Found', + 405: 'Method Not Allowed', + 406: 'Not Acceptable', + 407: 'Proxy Authentication Required', + 408: 'Request Timeout', + 409: 'Conflict', + 410: 'Gone', + 411: 'Length Required', + 412: 'Precondition Failed', + 413: 'Request Entity Too Large', + 414: 'Request-URI Too Long', + 415: 'Unsupported Media Type', + 416: 'Requested Range Not Satisfiable', + 417: 'Expectation Failed', + 418: 'Im a teapot', + 419: 'Authentication Timeout', + 420: 'Enhance Your Calm', + 422: 'Unprocessable Entity', + 423: 'Locked', + 424: 'Failed Dependency', + 426: 'Upgrade Required', + 428: 'Precondition Required', + 429: 'Too Many Requests', + 431: 'Request Header Fields Too Large', + 440: 'Login Timeout', + 444: 'No Response', + 449: 'Retry With', + 450: 'Blocked by Windows Parental Controls', + 451: [ + 'Redirect', + 'Unavailable For Legal Reasons', + ], + 494: 'Request Header Too Large', + 495: 'Cert Error', + 496: 'No Cert', + 497: 'HTTP to HTTPS', + 498: 'Token expired/invalid', + 499: [ + 'Client Closed Request', + 'Token required', + ], + 500: 'Internal Server Error', + 501: 'Not Implemented', + 502: 'Bad Gateway', + 503: 'Service Unavailable', + 504: 'Gateway Timeout', + 505: 'HTTP Version Not Supported', + 506: 'Variant Also Negotiates', + 507: 'Insufficient Storage', + 508: 'Loop Detected', + 509: 'Bandwidth Limit Exceeded', + 510: 'Not Extended', + 511: 'Network Authentication Required', + 520: 'Cloudfare - Web server is returning an unknown error', + 521: 'Cloudfare - Web server is down', + 522: 'Cloudfare - Connection timed out', + 523: 'Cloudfare - Origin is unreachable', + 524: 'Cloudfare - A timeout occurred', + 525: 'Cloudfare - SSL handshake failed', + 526: 'Cloudfare - Invalid SSL certificate', + 598: 'Network read timeout error', + 599: 'Network connect timeout error', +} media_extensions = [ '3gp', 'avi', 'divx', 'dvr-ms', 'f4v', 'flv', 'img', 'iso', 'm2ts', 'm4v', 'mkv', 'mov', 'mp4', 'mpeg', 'mpg', 'ogm', 'ogv', 'rmvb', 'tp', 'ts', 'vob', 'webm', 'wmv', 'wtv', @@ -29,6 +107,27 @@ subtitle_extensions = ['ass', 'idx', 'srt', 'ssa', 'sub'] timeFormat = '%A %I:%M %p' +def http_code_description(http_code): + """ + Get the description of the provided HTTP status code. + :param http_code: The HTTP status code + :return: The description of the provided ``http_code`` + """ + + if http_code in http_status_code: + description = http_status_code[http_code] + + if isinstance(description, list): + return '(%s)' % ', '.join(description) + + return description + + # TODO Restore logger import + # logger.log(u'Unknown HTTP status code %s. Please submit an issue' % http_code, logger.ERROR) + + return None + + def is_sync_file(filename): """ Check if the provided ``filename`` is a sync file, based on its name. @@ -131,3 +230,17 @@ def sanitize_filename(filename): return filename return '' + + +def try_int(candidate, default_value=0): + """ + Try to convert ``candidate`` to int, or return the ``default_value``. + :param candidate: The value to convert to int + :param default_value: The value to return if the conversion fails + :return: ``candidate`` as int, or ``default_value`` if the conversion fails + """ + + try: + return int(candidate) + except Exception: + return default_value diff --git a/tests/helpers_tests.py b/tests/helpers_tests.py index 3eef330dd8504cfdfacfd7bf0c6a678b981177ee..b605837d48c8903fdfb6f1c426a95b96c9d3b2f3 100755 --- a/tests/helpers_tests.py +++ b/tests/helpers_tests.py @@ -54,7 +54,6 @@ Methods: create_https_certificates backupVersionedFile restoreVersionedFile - tryInt md5_for_file get_lan_ip check_url @@ -75,7 +74,6 @@ Methods: mapIndexersToShow touchFile _getTempDir - codeDescription _setUpSession getURL download_file @@ -629,13 +627,6 @@ class HelpersMiscTests(unittest.TestCase): """ pass - @unittest.skip('Not yet implemented') - def test_try_int(self): - """ - Test tryInt - """ - pass - @unittest.skip('Not yet implemented') def test_full_sanitize_scene_name(self): """ @@ -643,13 +634,6 @@ class HelpersMiscTests(unittest.TestCase): """ pass - @unittest.skip('Not yet implemented') - def test_code_description(self): - """ - Test codeDescription - """ - pass - @unittest.skip('Not yet implemented') def test_remove_article(self): """ diff --git a/tests/sickrage_tests/helper/common_tests.py b/tests/sickrage_tests/helper/common_tests.py index 1747055cdd6a552a61135103f05b0bb7846b2686..d46d0547fd98be9fd679e37eaeb0dfad229152d8 100644 --- a/tests/sickrage_tests/helper/common_tests.py +++ b/tests/sickrage_tests/helper/common_tests.py @@ -33,14 +33,41 @@ sys.path.insert(1, os.path.abspath(os.path.join(os.path.dirname(__file__), '../. sys.path.insert(1, os.path.abspath(os.path.join(os.path.dirname(__file__), '../../..'))) import sickbeard -from sickrage.helper.common import is_sync_file, is_torrent_or_nzb_file, pretty_file_size, remove_extension -from sickrage.helper.common import replace_extension, sanitize_filename +from sickrage.helper.common import http_code_description, is_sync_file, is_torrent_or_nzb_file, pretty_file_size +from sickrage.helper.common import remove_extension, replace_extension, sanitize_filename, try_int class CommonTests(unittest.TestCase): """ Test common """ + + def test_http_code_description(self): + test_cases = { + None: None, + '': None, + '300': None, + 0: None, + 123: None, + 12.3: None, + -123: None, + -12.3: None, + 300: 'Multiple Choices', + 451: '(Redirect, Unavailable For Legal Reasons)', + 497: 'HTTP to HTTPS', + 499: '(Client Closed Request, Token required)', + 600: None, + } + + unicode_test_cases = { + u'': None, + u'300': None, + } + + for test in test_cases, unicode_test_cases: + for (http_code, result) in test.iteritems(): + self.assertEqual(http_code_description(http_code), result) + def test_is_sync_file(self): """ Test is sync file @@ -301,6 +328,67 @@ class CommonTests(unittest.TestCase): for (filename, result) in tests.iteritems(): self.assertEqual(sanitize_filename(filename), result) + def test_try_int(self): + """ + Test try int + """ + test_cases = { + None: 0, + '': 0, + '123': 123, + '-123': -123, + '12.3': 0, + '-12.3': 0, + 0: 0, + 123: 123, + -123: -123, + 12.3: 12, + -12.3: -12, + } + + unicode_test_cases = { + u'': 0, + u'123': 123, + u'-123': -123, + u'12.3': 0, + u'-12.3': 0, + } + + for test in test_cases, unicode_test_cases: + for (candidate, result) in test.iteritems(): + self.assertEqual(try_int(candidate), result) + + def test_try_int_with_default(self): + """ + Test try int + """ + default_value = 42 + test_cases = { + None: default_value, + '': default_value, + '123': 123, + '-123': -123, + '12.3': default_value, + '-12.3': default_value, + 0: 0, + 123: 123, + -123: -123, + 12.3: 12, + -12.3: -12, + } + + unicode_test_cases = { + u'': default_value, + u'123': 123, + u'-123': -123, + u'12.3': default_value, + u'-12.3': default_value, + } + + for test in test_cases, unicode_test_cases: + for (candidate, result) in test.iteritems(): + self.assertEqual(try_int(candidate, default_value), result) + if __name__ == '__main__': print('=====> Testing %s' % __file__)