From a6eedd3c75d889d675fb04aff0a650037d09c394 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 25 Jul 2015 17:19:46 +0800 Subject: [PATCH 1/2] Bump release version --- CHANGES.md | 9 -- SickBeard.py | 4 + contributing.md | 125 ---------------- readme.md | 6 +- sickbeard/logger.py | 16 ++- sickbeard/nzbSplitter.py | 2 +- sickbeard/scene_exceptions.py | 197 +++++++++++++++---------- sickbeard/scene_numbering.py | 262 +++++++++++++++++----------------- sickbeard/showUpdater.py | 3 + sickbeard/show_queue.py | 10 +- sickbeard/webserve.py | 4 +- tests/scene_helpers_tests.py | 41 ++++-- 12 files changed, 310 insertions(+), 369 deletions(-) delete mode 100644 contributing.md diff --git a/CHANGES.md b/CHANGES.md index 163f1d91..4644528d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -109,15 +109,6 @@ * Change accept SD titles that contain audio quality * Change readme.md -[develop changelog] -* Update Requests library 2.7.0 (ab1f493) to 2.7.0 (8b5e457) -* Update Tornado webserver from 4.2.dev1 (609dbb9) to 4.2b1 (61a16c9) -* Change reload_module call to explicit import lib/six.moves -* Change queue, httplib, cookielib and xmlrpclib to use explicit import lib/six.moves -* Change zoneinfo update/loader to be compatible with dateutil 2.4.2 -* Change use metadata for zoneinfo files and remove hack of dateutil lib -* Change param item "features" passed to Beautiful Soup to prevent false +ve warning in r353 - ### 0.9.1 (2015-05-25 03:03:00 UTC) diff --git a/SickBeard.py b/SickBeard.py index 8bf57a26..932886fa 100755 --- a/SickBeard.py +++ b/SickBeard.py @@ -363,6 +363,10 @@ class SickGear(object): # refresh network timezones network_timezones.update_network_dict() + # load all ids from xem + startup_background_tasks = threading.Thread(name='FETCH-XEMDATA', target=sickbeard.scene_exceptions.get_xem_ids) + startup_background_tasks.start() + # sure, why not? if sickbeard.USE_FAILED_DOWNLOADS: failed_history.trimHistory() diff --git a/contributing.md b/contributing.md deleted file mode 100644 index 51be9155..00000000 --- a/contributing.md +++ /dev/null @@ -1,125 +0,0 @@ -### Questions about SickGear? - -To get your questions answered, please ask in the [SickGear Forum], on IRC \#SickGear pn freenode.net, or webchat. - -# Contributing to SickGear - -1. [Getting Involved](#getting-involved) -2. [How To Report Bugs](#how-to-report-bugs) -3. [Tips For Submitting Code](#tips-for-submitting-code) - - -## Getting Involved - -There are a number of ways to get involved with the development of SickGear. Even if you've never contributed code to an Open Source project before, we're always looking for help identifying bugs, cleaning up code, writing documentation and testing. - -The goal of this guide is to provide the best way to contribute to the official SickGear repository. Please read through the full guide detailing [How to Report Bugs](#how-to-report-bugs). - -## Discussion - -### Issues and IRC - -If you think you've found a bug please [file it in the bug tracker](#how-to-report-bugs). - -Additionally most of the SickGear development team can be found in the [#SickGear](http://webchat.freenode.net/?channels=SickGear) IRC channel on irc.freenode.net. - - -## How to Report Bugs - -### Make sure it is a SickGear bug - -Many bugs reported are actually issues with the user mis-understanding of how something works (there are a bit of moving parts to an ideal setup) and most of the time can be fixed by just changing some settings to fit the users needs. - -If you are new to SickGear, it is usually a much better idea to ask for help first in the [SickGear IRC channel](http://webchat.freenode.net/?channels=SickGear). You will get much quicker support, and you will help avoid tying up the SickGear team with invalid bug reports. - -### Try the latest version of SickGear - -Bugs in old versions of SickGear may have already been fixed. In order to avoid reporting known issues, make sure you are always testing against the latest build/source. Also, we put new code in the `dev` branch first before pushing down to the `master` branch (which is what the binary builds are built off of). - - -## Tips For Submitting Code - - -### Code - -**NEVER write your patches to the master branch** - it gets messy (I say this from experience!) - -**ALWAYS USE A "TOPIC" BRANCH!** Personally I like the `branch-feature_name` format that way its easy to identify the branch and feature at a glance. Also please make note of any forum post / issue number in the pull commit so we know what you are solving (it helps with cleaning up the related items later). - - -Please follow these guidelines before reporting a bug: - -1. **Update to the latest version** — Check if you can reproduce the issue with the latest version from the `dev` branch. - -2. **Use the SickGear Forums search** — check if the issue has already been reported. If it has been, please comment on the existing issue. - -3. **Provide a means to reproduce the problem** — Please provide as much details as possible, e.g. SickGear log files (obfuscate apikey/passwords), browser and operating system versions, how you started SickGear, and of course the steps to reproduce the problem. Bugs are always reported in the forums. - - -### Feature requests - -Please follow the bug guidelines above for feature requests, i.e. update to the latest version and search for existing issues before posting a new request. You can submit Feature Requests in the [SickGear Forum] as well. - -### Pull requests - -[Pull requests](https://help.github.com/articles/using-pull-requests) are welcome and the preferred way of accepting code contributions. - -Please follow these guidelines before sending a pull request: - -1. Update your fork to the latest upstream version. - -2. Use the `dev` branch to base your code off of. Create a topic-branch for your work. We will not merge your 'dev' branch, or your 'master' branch, only topic branches, coming from dev are merged. - -3. Follow the coding conventions of the original repository. Do not change line endings of the existing file, as this will rewrite the file and loses history. - -4. Keep your commits as autonomous as possible, i.e. create a new commit for every single bug fix or feature added. - -5. Always add meaningful commit messages. We should not have to guess at what your code is supposed to do. - -6. One pull request per feature. If you want multiple features, send multiple PR's - -Please follow this process; it's the best way to get your work included in the project: - -- [Fork](http://help.github.com/fork-a-repo/) the project, clone your fork, - and configure the remotes: - -```bash - # clone your fork of the repo into the current directory in terminal - git clone git@github.com:/SickGear.git - # navigate to the newly cloned directory - cd SickGear - # assign the original repo to a remote called "upstream" - git remote add upstream https://github.com/SickGear/SickGear.git - ``` - -- If you cloned a while ago, get the latest changes from upstream: - - ```bash - # fetch upstream changes - git fetch upstream - # make sure you are on your 'master' branch - git checkout master - # merge upstream changes - git merge upstream/master - ``` - -- Create a new topic branch to contain your feature, change, or fix: - - ```bash - git checkout -b dev - ``` - -- Commit your changes in logical chunks. or your pull request is unlikely - be merged into the main project. Use git's - [interactive rebase](https://help.github.com/articles/interactive-rebase) - feature to tidy up your commits before making them public. - -- Push your topic branch up to your fork: - - ```bash - git push origin - ``` - -- [Open a Pull Request](https://help.github.com/articles/using-pull-requests) with a - clear title and description. - diff --git a/readme.md b/readme.md index f2157151..ed6c09ae 100644 --- a/readme.md +++ b/readme.md @@ -18,7 +18,7 @@ SickGear provides management of TV shows and/or Anime, can detect wanted or epis * Uses well known established index sites to gather show information * Searches for known alternatively named shows with a fallback to user edited names * Searches for known alternatively numbered episodes with a fallback to user edited numbers - * Forward search results to a downloader program (e.g. SABNZBd, NZBGet, uTorrent, and others) + * Forward search results to a downloader (e.g. SABNZBd, NZBGet, uTorrent, and others) * Save search results to a "blackhole" folder that can be periodically scanned for taking action * Post-process downloaded episodes into customisable layouts, with or without extra metadata * Advanced Failed Download Handling (FDH) @@ -105,9 +105,9 @@ Finally, a massive thanks to all those that remain in the shadows, the quiet one Show List: Simple
Theme: Dark, Light Show List: Banner
Theme: Dark, Light - Show List: Poster
Theme: Dark 1, Dark 2 + Show List: Poster
Theme: Dark, Dark 2 Episode View: Day by Day
Theme: Dark, Light - Episode View: List
Theme: Dark 1, Dark 2, Light + Episode View: List
Theme: Dark, Dark 2, Light Display Show
Theme: Dark, Light diff --git a/sickbeard/logger.py b/sickbeard/logger.py index 43253f47..c0c7a159 100644 --- a/sickbeard/logger.py +++ b/sickbeard/logger.py @@ -31,6 +31,7 @@ from logging.handlers import TimedRotatingFileHandler import sickbeard from sickbeard import classes +import sickbeard.helpers try: from lib.send2trash import send2trash @@ -268,15 +269,18 @@ class TimedCompressedRotatingFileHandler(TimedRotatingFileHandler): file_name = self.baseFilename.rpartition('.')[0] dfn = '%s_%s.log' % (file_name, time.strftime(self.suffix, timeTuple)) if os.path.exists(dfn): - os.remove(dfn) - os.rename(self.baseFilename, dfn) + sickbeard.helpers._remove_file_failed(dfn) + try: + os.rename(self.baseFilename, dfn) + except: + pass if self.backupCount > 0: # find the oldest log file and delete it s = glob.glob(file_name + '_*') if len(s) > self.backupCount: s.sort() - os.remove(s[0]) - #print "%s -> %s" % (self.baseFilename, dfn) + sickbeard.helpers._remove_file_failed(s[0]) + # print "%s -> %s" % (self.baseFilename, dfn) if self.encoding: self.stream = codecs.open(self.baseFilename, 'w', self.encoding) else: @@ -284,11 +288,11 @@ class TimedCompressedRotatingFileHandler(TimedRotatingFileHandler): self.rolloverAt = self.rolloverAt + self.interval zip_name = dfn.rpartition('.')[0] + '.zip' if os.path.exists(zip_name): - os.remove(zip_name) + sickbeard.helpers._remove_file_failed(zip_name) file = zipfile.ZipFile(zip_name, 'w') file.write(dfn, os.path.basename(dfn), zipfile.ZIP_DEFLATED) file.close() - os.remove(dfn) + sickbeard.helpers._remove_file_failed(dfn) sb_log_instance = SBRotatingLogHandler('sickbeard.log') diff --git a/sickbeard/nzbSplitter.py b/sickbeard/nzbSplitter.py index 950a0473..4a64f7f8 100644 --- a/sickbeard/nzbSplitter.py +++ b/sickbeard/nzbSplitter.py @@ -48,7 +48,7 @@ def getSeasonNZBs(name, urlData, season): if sceneNameMatch: showName, qualitySection, groupName = sceneNameMatch.groups() # @UnusedVariable else: - logger.log(u"Unable to parse " + name + " into a scene name. If it's a valid one log a bug.", logger.ERROR) + logger.log(u"Unable to parse " + name + " into a scene name. If it's a valid one, log a bug.", logger.ERROR) return ({}, '') regex = '(' + re.escape(showName) + '\.S%02d(?:[E0-9]+)\.[\w\._]+\-\w+' % season + ')' diff --git a/sickbeard/scene_exceptions.py b/sickbeard/scene_exceptions.py index 84fecac1..47f752c9 100644 --- a/sickbeard/scene_exceptions.py +++ b/sickbeard/scene_exceptions.py @@ -31,68 +31,73 @@ from sickbeard import db exception_dict = {} anidb_exception_dict = {} xem_exception_dict = {} +xem_tvdb_ids_list = [] +xem_rage_ids_list = [] exceptionsCache = {} exceptionsSeasonCache = {} exceptionLock = threading.Lock() -def shouldRefresh(list): - MAX_REFRESH_AGE_SECS = 86400 # 1 day - myDB = db.DBConnection('cache.db') - rows = myDB.select("SELECT last_refreshed FROM scene_exceptions_refresh WHERE list = ?", [list]) +def shouldRefresh(list): + max_refresh_age_secs = 86400 # 1 day + + my_db = db.DBConnection('cache.db') + rows = my_db.select('SELECT last_refreshed FROM scene_exceptions_refresh WHERE list = ?', [list]) if rows: - lastRefresh = int(rows[0]['last_refreshed']) - return int(time.mktime(datetime.datetime.today().timetuple())) > lastRefresh + MAX_REFRESH_AGE_SECS + last_refresh = int(rows[0]['last_refreshed']) + return int(time.mktime(datetime.datetime.today().timetuple())) > last_refresh + max_refresh_age_secs else: return True + def setLastRefresh(list): - myDB = db.DBConnection('cache.db') - myDB.upsert("scene_exceptions_refresh", - {'last_refreshed': int(time.mktime(datetime.datetime.today().timetuple()))}, - {'list': list}) + my_db = db.DBConnection('cache.db') + my_db.upsert('scene_exceptions_refresh', + {'last_refreshed': int(time.mktime(datetime.datetime.today().timetuple()))}, + {'list': list}) + def get_scene_exceptions(indexer_id, season=-1): """ Given a indexer_id, return a list of all the scene exceptions. """ global exceptionsCache - exceptionsList = [] + exceptions_list = [] if indexer_id not in exceptionsCache or season not in exceptionsCache[indexer_id]: - myDB = db.DBConnection('cache.db') - exceptions = myDB.select("SELECT show_name FROM scene_exceptions WHERE indexer_id = ? and season = ?", - [indexer_id, season]) + my_db = db.DBConnection('cache.db') + exceptions = my_db.select('SELECT show_name FROM scene_exceptions WHERE indexer_id = ? and season = ?', + [indexer_id, season]) if exceptions: - exceptionsList = list(set([cur_exception["show_name"] for cur_exception in exceptions])) + exceptions_list = list(set([cur_exception['show_name'] for cur_exception in exceptions])) - if not indexer_id in exceptionsCache: + if indexer_id not in exceptionsCache: exceptionsCache[indexer_id] = {} - exceptionsCache[indexer_id][season] = exceptionsList + exceptionsCache[indexer_id][season] = exceptions_list else: - exceptionsList = exceptionsCache[indexer_id][season] + exceptions_list = exceptionsCache[indexer_id][season] - if season == 1: # if we where looking for season 1 we can add generic names - exceptionsList += get_scene_exceptions(indexer_id, season=-1) + if 1 == season: # if we where looking for season 1 we can add generic names + exceptions_list += get_scene_exceptions(indexer_id, season=-1) - return exceptionsList + return exceptions_list def get_all_scene_exceptions(indexer_id): - exceptionsDict = {} + exceptions_dict = {} - myDB = db.DBConnection('cache.db') - exceptions = myDB.select("SELECT show_name,season FROM scene_exceptions WHERE indexer_id = ?", [indexer_id]) + my_db = db.DBConnection('cache.db') + exceptions = my_db.select('SELECT show_name,season FROM scene_exceptions WHERE indexer_id = ?', [indexer_id]) if exceptions: for cur_exception in exceptions: - if not cur_exception["season"] in exceptionsDict: - exceptionsDict[cur_exception["season"]] = [] - exceptionsDict[cur_exception["season"]].append(cur_exception["show_name"]) + if not cur_exception['season'] in exceptions_dict: + exceptions_dict[cur_exception['season']] = [] + exceptions_dict[cur_exception['season']].append(cur_exception['show_name']) - return exceptionsDict + return exceptions_dict def get_scene_seasons(indexer_id): @@ -100,23 +105,23 @@ def get_scene_seasons(indexer_id): return a list of season numbers that have scene exceptions """ global exceptionsSeasonCache - exceptionsSeasonList = [] + exception_sseason_list = [] if indexer_id not in exceptionsSeasonCache: - myDB = db.DBConnection('cache.db') - sqlResults = myDB.select("SELECT DISTINCT(season) as season FROM scene_exceptions WHERE indexer_id = ?", - [indexer_id]) - if sqlResults: - exceptionsSeasonList = list(set([int(x["season"]) for x in sqlResults])) + my_db = db.DBConnection('cache.db') + sql_results = my_db.select('SELECT DISTINCT(season) as season FROM scene_exceptions WHERE indexer_id = ?', + [indexer_id]) + if sql_results: + exception_sseason_list = list(set([int(x['season']) for x in sql_results])) - if not indexer_id in exceptionsSeasonCache: + if indexer_id not in exceptionsSeasonCache: exceptionsSeasonCache[indexer_id] = {} - exceptionsSeasonCache[indexer_id] = exceptionsSeasonList + exceptionsSeasonCache[indexer_id] = exception_sseason_list else: - exceptionsSeasonList = exceptionsSeasonCache[indexer_id] + exception_sseason_list = exceptionsSeasonCache[indexer_id] - return exceptionsSeasonList + return exception_sseason_list def get_scene_exception_by_name(show_name): @@ -145,14 +150,14 @@ def retrieve_exceptions(): # exceptions are stored on github pages for indexer in sickbeard.indexerApi().indexers: if shouldRefresh(sickbeard.indexerApi(indexer).name): - logger.log(u"Checking for scene exception updates for " + sickbeard.indexerApi(indexer).name + "") + logger.log(u'Checking for scene exception updates for %s' % sickbeard.indexerApi(indexer).name) url = sickbeard.indexerApi(indexer).config['scene_url'] url_data = helpers.getURL(url) - if url_data is None: - # When urlData is None, trouble connecting to github - logger.log(u"Check scene exceptions update failed. Unable to get URL: " + url, logger.ERROR) + if None is url_data: + # When None is urlData, trouble connecting to github + logger.log(u'Check scene exceptions update failed. Unable to get URL: %s' % url, logger.ERROR) continue else: @@ -194,19 +199,19 @@ def retrieve_exceptions(): changed_exceptions = False # write all the exceptions we got off the net into the database - myDB = db.DBConnection('cache.db') + my_db = db.DBConnection('cache.db') cl = [] for cur_indexer_id in exception_dict: # get a list of the existing exceptions for this ID - existing_exceptions = [x["show_name"] for x in - myDB.select("SELECT * FROM scene_exceptions WHERE indexer_id = ?", [cur_indexer_id])] + existing_exceptions = [x['show_name'] for x in + my_db.select('SELECT * FROM scene_exceptions WHERE indexer_id = ?', [cur_indexer_id])] - if not cur_indexer_id in exception_dict: + if cur_indexer_id not in exception_dict: continue for cur_exception_dict in exception_dict[cur_indexer_id]: - cur_exception, curSeason = cur_exception_dict.items()[0] + cur_exception, cur_season = cur_exception_dict.items()[0] # if this exception isn't already in the DB then add it if cur_exception not in existing_exceptions: @@ -214,33 +219,33 @@ def retrieve_exceptions(): if not isinstance(cur_exception, unicode): cur_exception = unicode(cur_exception, 'utf-8', 'replace') - cl.append(["INSERT INTO scene_exceptions (indexer_id, show_name, season) VALUES (?,?,?)", - [cur_indexer_id, cur_exception, curSeason]]) + cl.append(['INSERT INTO scene_exceptions (indexer_id, show_name, season) VALUES (?,?,?)', + [cur_indexer_id, cur_exception, cur_season]]) changed_exceptions = True - myDB.mass_action(cl) + my_db.mass_action(cl) # since this could invalidate the results of the cache we clear it out after updating if changed_exceptions: - logger.log(u"Updated scene exceptions") + logger.log(u'Updated scene exceptions') else: - logger.log(u"No scene exceptions update needed") - + logger.log(u'No scene exceptions update needed') # cleanup exception_dict.clear() anidb_exception_dict.clear() xem_exception_dict.clear() + def update_scene_exceptions(indexer_id, scene_exceptions, season=-1): """ Given a indexer_id, and a list of all show scene exceptions, update the db. """ global exceptionsCache - myDB = db.DBConnection('cache.db') - myDB.action('DELETE FROM scene_exceptions WHERE indexer_id=? and season=?', [indexer_id, season]) + my_db = db.DBConnection('cache.db') + my_db.action('DELETE FROM scene_exceptions WHERE indexer_id=? and season=?', [indexer_id, season]) - logger.log(u"Updating scene exceptions", logger.MESSAGE) + logger.log(u'Updating scene exceptions', logger.MESSAGE) # A change has been made to the scene exception list. Let's clear the cache, to make this visible if indexer_id in exceptionsCache: @@ -252,16 +257,17 @@ def update_scene_exceptions(indexer_id, scene_exceptions, season=-1): if not isinstance(cur_exception, unicode): cur_exception = unicode(cur_exception, 'utf-8', 'replace') - myDB.action("INSERT INTO scene_exceptions (indexer_id, show_name, season) VALUES (?,?,?)", - [indexer_id, cur_exception, season]) + my_db.action('INSERT INTO scene_exceptions (indexer_id, show_name, season) VALUES (?,?,?)', + [indexer_id, cur_exception, season]) + def _anidb_exceptions_fetcher(): global anidb_exception_dict if shouldRefresh('anidb'): - logger.log(u"Checking for scene exception updates for AniDB") + logger.log(u'Checking for scene exception updates for AniDB') for show in sickbeard.showList: - if show.is_anime and show.indexer == 1: + if show.is_anime and 1 == show.indexer: try: anime = adba.Anime(None, name=show.name, tvdbid=show.indexerid, autoCorrectName=True) except: @@ -277,28 +283,75 @@ def _anidb_exceptions_fetcher(): def _xem_exceptions_fetcher(): global xem_exception_dict - if shouldRefresh('xem'): + xem_list = 'xem_us' + for show in sickbeard.showList: + if show.is_anime and not show.paused: + xem_list = 'xem' + break + + if shouldRefresh(xem_list): for indexer in sickbeard.indexerApi().indexers: - logger.log(u"Checking for XEM scene exception updates for " + sickbeard.indexerApi(indexer).name) + logger.log(u'Checking for XEM scene exception updates for %s' % sickbeard.indexerApi(indexer).name) - url = "http://thexem.de/map/allNames?origin=%s&seasonNumbers=1" % sickbeard.indexerApi(indexer).config[ - 'xem_origin'] + url = 'http://thexem.de/map/allNames?origin=%s%s&seasonNumbers=1'\ + % (sickbeard.indexerApi(indexer).config['xem_origin'], ('&language=us', '')['xem' == xem_list]) - parsedJSON = helpers.getURL(url, json=True) - if not parsedJSON: - logger.log(u"Check scene exceptions update failed for " + sickbeard.indexerApi( - indexer).name + ", Unable to get URL: " + url, logger.ERROR) + parsed_json = helpers.getURL(url, json=True, timeout=90) + if not parsed_json: + logger.log(u'Check scene exceptions update failed for %s, Unable to get URL: %s' + % (sickbeard.indexerApi(indexer).name, url), logger.ERROR) continue - if parsedJSON['result'] == 'failure': + if 'failure' == parsed_json['result']: continue - for indexerid, names in parsedJSON['data'].items(): + for indexerid, names in parsed_json['data'].items(): try: xem_exception_dict[int(indexerid)] = names except: continue - setLastRefresh('xem') + setLastRefresh(xem_list) - return xem_exception_dict \ No newline at end of file + return xem_exception_dict + + +def _xem_get_ids(indexer_name, xem_origin): + xem_ids = [] + + url = 'http://thexem.de/map/havemap?origin=%s' % xem_origin + + task = 'Fetching show ids with%s xem scene mapping%s for origin' + logger.log(u'%s %s' % (task % ('', 's'), indexer_name)) + parsed_json = helpers.getURL(url, json=True, timeout=90) + if not parsed_json: + logger.log(u'Failed %s %s, Unable to get URL: %s' + % (task.lower() % ('', 's'), indexer_name, url), logger.ERROR) + else: + if 'result' in parsed_json and 'success' == parsed_json['result'] and 'data' in parsed_json: + try: + for indexerid in parsed_json['data']: + xem_id = helpers.tryInt(indexerid) + if xem_id and xem_id not in xem_ids: + xem_ids.append(xem_id) + except: + pass + if 0 == len(xem_ids): + logger.log(u'Failed %s %s, no data items parsed from URL: %s' + % (task.lower() % ('', 's'), indexer_name, url), logger.WARNING) + + logger.log(u'Finished %s %s' % (task.lower() % (' %s' % len(xem_ids), helpers.maybe_plural(len(xem_ids))), + indexer_name)) + return xem_ids + + +def get_xem_ids(): + global xem_tvdb_ids_list + global xem_rage_ids_list + + xem_ids = _xem_get_ids('TheTVDB', 'tvdb') + if len(xem_ids): + xem_tvdb_ids_list = xem_ids + xem_ids = _xem_get_ids('TVRage', 'rage') + if len(xem_ids): + xem_rage_ids_list = xem_ids diff --git a/sickbeard/scene_numbering.py b/sickbeard/scene_numbering.py index 4ee45dd5..c516309c 100644 --- a/sickbeard/scene_numbering.py +++ b/sickbeard/scene_numbering.py @@ -27,15 +27,11 @@ import datetime import traceback import sickbeard -try: - import json -except ImportError: - from lib import simplejson as json - from sickbeard import logger from sickbeard import db from sickbeard.exceptions import ex + def get_scene_numbering(indexer_id, indexer, season, episode, fallback_to_xem=True): """ Returns a tuple, (season, episode), with the scene numbering (if there is one), @@ -49,12 +45,12 @@ def get_scene_numbering(indexer_id, indexer, season, episode, fallback_to_xem=Tr @param fallback_to_xem: bool If set (the default), check xem for matches if there is no local scene numbering @return: (int, int) a tuple with (season, episode) """ - if indexer_id is None or season is None or episode is None: - return (season, episode) + if None is indexer_id or None is season or None is episode: + return season, episode - showObj = sickbeard.helpers.findCertainShow(sickbeard.showList, int(indexer_id)) - if showObj and not showObj.is_scene: - return (season, episode) + show_obj = sickbeard.helpers.findCertainShow(sickbeard.showList, int(indexer_id)) + if show_obj and not show_obj.is_scene: + return season, episode result = find_scene_numbering(int(indexer_id), int(indexer), season, episode) if result: @@ -64,26 +60,26 @@ def get_scene_numbering(indexer_id, indexer, season, episode, fallback_to_xem=Tr xem_result = find_xem_numbering(int(indexer_id), int(indexer), season, episode) if xem_result: return xem_result - return (season, episode) + return season, episode def find_scene_numbering(indexer_id, indexer, season, episode): """ Same as get_scene_numbering(), but returns None if scene numbering is not set """ - if indexer_id is None or season is None or episode is None: - return (season, episode) + if None is indexer_id or None is season or None is episode: + return season, episode indexer_id = int(indexer_id) indexer = int(indexer) - myDB = db.DBConnection() - rows = myDB.select( - "SELECT scene_season, scene_episode FROM scene_numbering WHERE indexer = ? and indexer_id = ? and season = ? and episode = ? and (scene_season or scene_episode) != 0", + my_db = db.DBConnection() + rows = my_db.select( + 'SELECT scene_season, scene_episode FROM scene_numbering WHERE indexer = ? and indexer_id = ? and season = ? and episode = ? and (scene_season or scene_episode) != 0', [indexer, indexer_id, season, episode]) if rows: - return (int(rows[0]["scene_season"]), int(rows[0]["scene_episode"])) + return int(rows[0]['scene_season']), int(rows[0]['scene_episode']) def get_scene_absolute_numbering(indexer_id, indexer, absolute_number, fallback_to_xem=True): @@ -98,14 +94,14 @@ def get_scene_absolute_numbering(indexer_id, indexer, absolute_number, fallback_ @param fallback_to_xem: bool If set (the default), check xem for matches if there is no local scene numbering @return: (int, int) a tuple with (season, episode) """ - if indexer_id is None or absolute_number is None: + if None is indexer_id or None is absolute_number: return absolute_number indexer_id = int(indexer_id) indexer = int(indexer) - showObj = sickbeard.helpers.findCertainShow(sickbeard.showList, indexer_id) - if showObj and not showObj.is_scene: + show_obj = sickbeard.helpers.findCertainShow(sickbeard.showList, indexer_id) + if show_obj and not show_obj.is_scene: return absolute_number result = find_scene_absolute_numbering(indexer_id, indexer, absolute_number) @@ -123,19 +119,19 @@ def find_scene_absolute_numbering(indexer_id, indexer, absolute_number): """ Same as get_scene_numbering(), but returns None if scene numbering is not set """ - if indexer_id is None or absolute_number is None: + if None is indexer_id or None is absolute_number: return absolute_number indexer_id = int(indexer_id) indexer = int(indexer) - myDB = db.DBConnection() - rows = myDB.select( - "SELECT scene_absolute_number FROM scene_numbering WHERE indexer = ? and indexer_id = ? and absolute_number = ? and scene_absolute_number != 0", + my_db = db.DBConnection() + rows = my_db.select( + 'SELECT scene_absolute_number FROM scene_numbering WHERE indexer = ? and indexer_id = ? and absolute_number = ? and scene_absolute_number != 0', [indexer, indexer_id, absolute_number]) if rows: - return int(rows[0]["scene_absolute_number"]) + return int(rows[0]['scene_absolute_number']) def get_indexer_numbering(indexer_id, indexer, sceneSeason, sceneEpisode, fallback_to_xem=True): @@ -143,23 +139,23 @@ def get_indexer_numbering(indexer_id, indexer, sceneSeason, sceneEpisode, fallba Returns a tuple, (season, episode) with the TVDB and TVRAGE numbering for (sceneSeason, sceneEpisode) (this works like the reverse of get_scene_numbering) """ - if indexer_id is None or sceneSeason is None or sceneEpisode is None: - return (sceneSeason, sceneEpisode) + if None is indexer_id or None is sceneSeason or None is sceneEpisode: + return sceneSeason, sceneEpisode indexer_id = int(indexer_id) indexer = int(indexer) - myDB = db.DBConnection() - rows = myDB.select( - "SELECT season, episode FROM scene_numbering WHERE indexer = ? and indexer_id = ? and scene_season = ? and scene_episode = ?", + my_db = db.DBConnection() + rows = my_db.select( + 'SELECT season, episode FROM scene_numbering WHERE indexer = ? and indexer_id = ? and scene_season = ? and scene_episode = ?', [indexer, indexer_id, sceneSeason, sceneEpisode]) if rows: - return (int(rows[0]["season"]), int(rows[0]["episode"])) + return int(rows[0]['season']), int(rows[0]['episode']) else: if fallback_to_xem: return get_indexer_numbering_for_xem(indexer_id, indexer, sceneSeason, sceneEpisode) - return (sceneSeason, sceneEpisode) + return sceneSeason, sceneEpisode def get_indexer_absolute_numbering(indexer_id, indexer, sceneAbsoluteNumber, fallback_to_xem=True, scene_season=None): @@ -167,24 +163,24 @@ def get_indexer_absolute_numbering(indexer_id, indexer, sceneAbsoluteNumber, fal Returns a tuple, (season, episode, absolute_number) with the TVDB and TVRAGE numbering for (sceneAbsoluteNumber) (this works like the reverse of get_absolute_numbering) """ - if indexer_id is None or sceneAbsoluteNumber is None: + if None is indexer_id or None is sceneAbsoluteNumber: return sceneAbsoluteNumber indexer_id = int(indexer_id) indexer = int(indexer) - myDB = db.DBConnection() - if scene_season is None: - rows = myDB.select( - "SELECT absolute_number FROM scene_numbering WHERE indexer = ? and indexer_id = ? and scene_absolute_number = ?", + my_db = db.DBConnection() + if None is scene_season: + rows = my_db.select( + 'SELECT absolute_number FROM scene_numbering WHERE indexer = ? and indexer_id = ? and scene_absolute_number = ?', [indexer, indexer_id, sceneAbsoluteNumber]) else: - rows = myDB.select( - "SELECT absolute_number FROM scene_numbering WHERE indexer = ? and indexer_id = ? and scene_absolute_number = ? and scene_season = ?", + rows = my_db.select( + 'SELECT absolute_number FROM scene_numbering WHERE indexer = ? and indexer_id = ? and scene_absolute_number = ? and scene_season = ?', [indexer, indexer_id, sceneAbsoluteNumber, scene_season]) if rows: - return int(rows[0]["absolute_number"]) + return int(rows[0]['absolute_number']) else: if fallback_to_xem: return get_indexer_absolute_numbering_for_xem(indexer_id, indexer, sceneAbsoluteNumber, scene_season) @@ -198,28 +194,28 @@ def set_scene_numbering(indexer_id, indexer, season=None, episode=None, absolute To clear the scene numbering, leave both sceneSeason and sceneEpisode as None. """ - if indexer_id is None: + if None is indexer_id: return indexer_id = int(indexer_id) indexer = int(indexer) - myDB = db.DBConnection() + my_db = db.DBConnection() if season and episode: - myDB.action( - "INSERT OR IGNORE INTO scene_numbering (indexer, indexer_id, season, episode) VALUES (?,?,?,?)", + my_db.action( + 'INSERT OR IGNORE INTO scene_numbering (indexer, indexer_id, season, episode) VALUES (?,?,?,?)', [indexer, indexer_id, season, episode]) - myDB.action( - "UPDATE scene_numbering SET scene_season = ?, scene_episode = ? WHERE indexer = ? and indexer_id = ? and season = ? and episode = ?", + my_db.action( + 'UPDATE scene_numbering SET scene_season = ?, scene_episode = ? WHERE indexer = ? and indexer_id = ? and season = ? and episode = ?', [sceneSeason, sceneEpisode, indexer, indexer_id, season, episode]) elif absolute_number: - myDB.action( - "INSERT OR IGNORE INTO scene_numbering (indexer, indexer_id, absolute_number) VALUES (?,?,?)", + my_db.action( + 'INSERT OR IGNORE INTO scene_numbering (indexer, indexer_id, absolute_number) VALUES (?,?,?)', [indexer, indexer_id, absolute_number]) - myDB.action( - "UPDATE scene_numbering SET scene_absolute_number = ? WHERE indexer = ? and indexer_id = ? and absolute_number = ?", + my_db.action( + 'UPDATE scene_numbering SET scene_absolute_number = ? WHERE indexer = ? and indexer_id = ? and absolute_number = ?', [sceneAbsolute, indexer, indexer_id, absolute_number]) @@ -233,21 +229,21 @@ def find_xem_numbering(indexer_id, indexer, season, episode): @param episode: int @return: (int, int) a tuple of scene_season, scene_episode, or None if there is no special mapping. """ - if indexer_id is None or season is None or episode is None: - return (season, episode) + if None is indexer_id or None is season or None is episode: + return season, episode indexer_id = int(indexer_id) indexer = int(indexer) xem_refresh(indexer_id, indexer) - myDB = db.DBConnection() - rows = myDB.select( - "SELECT scene_season, scene_episode FROM tv_episodes WHERE indexer = ? and showid = ? and season = ? and episode = ? and (scene_season or scene_episode) != 0", + my_db = db.DBConnection() + rows = my_db.select( + 'SELECT scene_season, scene_episode FROM tv_episodes WHERE indexer = ? and showid = ? and season = ? and episode = ? and (scene_season or scene_episode) != 0', [indexer, indexer_id, season, episode]) if rows: - return (int(rows[0]["scene_season"]), int(rows[0]["scene_episode"])) + return int(rows[0]['scene_season']), int(rows[0]['scene_episode']) def find_xem_absolute_numbering(indexer_id, indexer, absolute_number): @@ -259,7 +255,7 @@ def find_xem_absolute_numbering(indexer_id, indexer, absolute_number): @param absolute_number: int @return: int """ - if indexer_id is None or absolute_number is None: + if None is indexer_id or None is absolute_number: return absolute_number indexer_id = int(indexer_id) @@ -267,13 +263,13 @@ def find_xem_absolute_numbering(indexer_id, indexer, absolute_number): xem_refresh(indexer_id, indexer) - myDB = db.DBConnection() - rows = myDB.select( - "SELECT scene_absolute_number FROM tv_episodes WHERE indexer = ? and showid = ? and absolute_number = ? and scene_absolute_number != 0", + my_db = db.DBConnection() + rows = my_db.select( + 'SELECT scene_absolute_number FROM tv_episodes WHERE indexer = ? and showid = ? and absolute_number = ? and scene_absolute_number != 0', [indexer, indexer_id, absolute_number]) if rows: - return int(rows[0]["scene_absolute_number"]) + return int(rows[0]['scene_absolute_number']) def get_indexer_numbering_for_xem(indexer_id, indexer, sceneSeason, sceneEpisode): @@ -285,23 +281,23 @@ def get_indexer_numbering_for_xem(indexer_id, indexer, sceneSeason, sceneEpisode @param sceneEpisode: int @return: (int, int) a tuple of (season, episode) """ - if indexer_id is None or sceneSeason is None or sceneEpisode is None: - return (sceneSeason, sceneEpisode) + if None is indexer_id or None is sceneSeason or None is sceneEpisode: + return sceneSeason, sceneEpisode indexer_id = int(indexer_id) indexer = int(indexer) xem_refresh(indexer_id, indexer) - myDB = db.DBConnection() - rows = myDB.select( - "SELECT season, episode FROM tv_episodes WHERE indexer = ? and showid = ? and scene_season = ? and scene_episode = ?", + my_db = db.DBConnection() + rows = my_db.select( + 'SELECT season, episode FROM tv_episodes WHERE indexer = ? and showid = ? and scene_season = ? and scene_episode = ?', [indexer, indexer_id, sceneSeason, sceneEpisode]) if rows: - return (int(rows[0]["season"]), int(rows[0]["episode"])) + return int(rows[0]['season']), int(rows[0]['episode']) - return (sceneSeason, sceneEpisode) + return sceneSeason, sceneEpisode def get_indexer_absolute_numbering_for_xem(indexer_id, indexer, sceneAbsoluteNumber, scene_season=None): @@ -312,7 +308,7 @@ def get_indexer_absolute_numbering_for_xem(indexer_id, indexer, sceneAbsoluteNum @param sceneAbsoluteNumber: int @return: int """ - if indexer_id is None or sceneAbsoluteNumber is None: + if None is indexer_id or None is sceneAbsoluteNumber: return sceneAbsoluteNumber indexer_id = int(indexer_id) @@ -320,18 +316,18 @@ def get_indexer_absolute_numbering_for_xem(indexer_id, indexer, sceneAbsoluteNum xem_refresh(indexer_id, indexer) - myDB = db.DBConnection() - if scene_season is None: - rows = myDB.select( - "SELECT absolute_number FROM tv_episodes WHERE indexer = ? and showid = ? and scene_absolute_number = ?", + my_db = db.DBConnection() + if None is scene_season: + rows = my_db.select( + 'SELECT absolute_number FROM tv_episodes WHERE indexer = ? and showid = ? and scene_absolute_number = ?', [indexer, indexer_id, sceneAbsoluteNumber]) else: - rows = myDB.select( - "SELECT absolute_number FROM tv_episodes WHERE indexer = ? and showid = ? and scene_absolute_number = ? and scene_season = ?", + rows = my_db.select( + 'SELECT absolute_number FROM tv_episodes WHERE indexer = ? and showid = ? and scene_absolute_number = ? and scene_season = ?', [indexer, indexer_id, sceneAbsoluteNumber, scene_season]) if rows: - return int(rows[0]["absolute_number"]) + return int(rows[0]['absolute_number']) return sceneAbsoluteNumber @@ -342,14 +338,14 @@ def get_scene_numbering_for_show(indexer_id, indexer): for an entire show. Both the keys and values of the dict are tuples. Will be empty if there are no scene numbers set """ - if indexer_id is None: + if None is indexer_id: return {} indexer_id = int(indexer_id) indexer = int(indexer) - myDB = db.DBConnection() - rows = myDB.select( + my_db = db.DBConnection() + rows = my_db.select( 'SELECT season, episode, scene_season, scene_episode FROM scene_numbering WHERE indexer = ? and indexer_id = ? and (scene_season or scene_episode) != 0 ORDER BY season, episode', [indexer, indexer_id]) @@ -371,7 +367,7 @@ def get_xem_numbering_for_show(indexer_id, indexer): for an entire show. Both the keys and values of the dict are tuples. Will be empty if there are no scene numbers set in xem """ - if indexer_id is None: + if None is indexer_id: return {} indexer_id = int(indexer_id) @@ -379,8 +375,8 @@ def get_xem_numbering_for_show(indexer_id, indexer): xem_refresh(indexer_id, indexer) - myDB = db.DBConnection() - rows = myDB.select( + my_db = db.DBConnection() + rows = my_db.select( 'SELECT season, episode, scene_season, scene_episode FROM tv_episodes WHERE indexer = ? and showid = ? and (scene_season or scene_episode) != 0 ORDER BY season, episode', [indexer, indexer_id]) @@ -402,14 +398,14 @@ def get_scene_absolute_numbering_for_show(indexer_id, indexer): for an entire show. Both the keys and values of the dict are tuples. Will be empty if there are no scene numbers set """ - if indexer_id is None: + if None is indexer_id: return {} indexer_id = int(indexer_id) indexer = int(indexer) - myDB = db.DBConnection() - rows = myDB.select( + my_db = db.DBConnection() + rows = my_db.select( 'SELECT absolute_number, scene_absolute_number FROM scene_numbering WHERE indexer = ? and indexer_id = ? and scene_absolute_number != 0 ORDER BY absolute_number', [indexer, indexer_id]) @@ -429,7 +425,7 @@ def get_xem_absolute_numbering_for_show(indexer_id, indexer): for an entire show. Both the keys and values of the dict are tuples. Will be empty if there are no scene numbers set in xem """ - if indexer_id is None: + if None is indexer_id: return {} indexer_id = int(indexer_id) @@ -438,8 +434,8 @@ def get_xem_absolute_numbering_for_show(indexer_id, indexer): xem_refresh(indexer_id, indexer) result = {} - myDB = db.DBConnection() - rows = myDB.select( + my_db = db.DBConnection() + rows = my_db.select( 'SELECT absolute_number, scene_absolute_number FROM tv_episodes WHERE indexer = ? and showid = ? and scene_absolute_number != 0 ORDER BY absolute_number', [indexer, indexer_id]) @@ -458,87 +454,87 @@ def xem_refresh(indexer_id, indexer, force=False): @param indexer_id: int """ - if indexer_id is None: + if None is indexer_id: return indexer_id = int(indexer_id) indexer = int(indexer) # XEM API URL - url = "http://thexem.de/map/all?id=%s&origin=%s&destination=scene" % ( - indexer_id, sickbeard.indexerApi(indexer).config['xem_origin']) + url = 'http://thexem.de/map/all?id=%s&origin=%s&destination=scene' % ( + indexer_id, sickbeard.indexerApi(indexer).config['xem_origin']) - MAX_REFRESH_AGE_SECS = 86400 # 1 day + max_refresh_age_secs = 86400 # 1 day - myDB = db.DBConnection() - rows = myDB.select("SELECT last_refreshed FROM xem_refresh WHERE indexer = ? and indexer_id = ?", - [indexer, indexer_id]) + my_db = db.DBConnection() + rows = my_db.select('SELECT last_refreshed FROM xem_refresh WHERE indexer = ? and indexer_id = ?', + [indexer, indexer_id]) if rows: - lastRefresh = int(rows[0]['last_refreshed']) - refresh = int(time.mktime(datetime.datetime.today().timetuple())) > lastRefresh + MAX_REFRESH_AGE_SECS + last_refresh = int(rows[0]['last_refreshed']) + refresh = int(time.mktime(datetime.datetime.today().timetuple())) > last_refresh + max_refresh_age_secs else: refresh = True if refresh or force: logger.log( - u'Looking up XEM scene mapping for show %s on %s' % (indexer_id, sickbeard.indexerApi(indexer).name,), + u'Looking up XEM scene mapping for show %s on %s' % (indexer_id, sickbeard.indexerApi(indexer).name), logger.DEBUG) # mark refreshed - myDB.upsert("xem_refresh", - {'indexer': indexer, - 'last_refreshed': int(time.mktime(datetime.datetime.today().timetuple()))}, - {'indexer_id': indexer_id}) + my_db.upsert('xem_refresh', + {'indexer': indexer, 'last_refreshed': int(time.mktime(datetime.datetime.today().timetuple()))}, + {'indexer_id': indexer_id}) try: - parsedJSON = sickbeard.helpers.getURL(url, json=True) - if not parsedJSON or parsedJSON == '': - logger.log(u'No XEM data for show "%s on %s"' % (indexer_id, sickbeard.indexerApi(indexer).name,), logger.MESSAGE) + parsed_json = sickbeard.helpers.getURL(url, json=True, timeout=90) + if not parsed_json or '' == parsed_json: + logger.log(u'No XEM data for show %s on %s' % (indexer_id, sickbeard.indexerApi(indexer).name), logger.MESSAGE) return - if 'success' in parsedJSON['result']: + if 'success' in parsed_json['result']: cl = [] - for entry in parsedJSON['data']: + for entry in parsed_json['data']: if 'scene' in entry: cl.append([ - "UPDATE tv_episodes SET scene_season = ?, scene_episode = ?, scene_absolute_number = ? WHERE showid = ? AND season = ? AND episode = ?", + 'UPDATE tv_episodes SET scene_season = ?, scene_episode = ?, scene_absolute_number = ? WHERE showid = ? AND season = ? AND episode = ?', [entry['scene']['season'], entry['scene']['episode'], entry['scene']['absolute'], indexer_id, entry[sickbeard.indexerApi(indexer).config['xem_origin']]['season'], entry[sickbeard.indexerApi(indexer).config['xem_origin']]['episode'] - ]]) + ]]) if 'scene_2' in entry: # for doubles cl.append([ - "UPDATE tv_episodes SET scene_season = ?, scene_episode = ?, scene_absolute_number = ? WHERE showid = ? AND season = ? AND episode = ?", + 'UPDATE tv_episodes SET scene_season = ?, scene_episode = ?, scene_absolute_number = ? WHERE showid = ? AND season = ? AND episode = ?', [entry['scene_2']['season'], entry['scene_2']['episode'], entry['scene_2']['absolute'], indexer_id, entry[sickbeard.indexerApi(indexer).config['xem_origin']]['season'], entry[sickbeard.indexerApi(indexer).config['xem_origin']]['episode'] - ]]) + ]]) - if len(cl) > 0: - myDB = db.DBConnection() - myDB.mass_action(cl) + if 0 < len(cl): + my_db = db.DBConnection() + my_db.mass_action(cl) else: - logger.log(u"Empty lookup result - no XEM data for show %s on %s" % ( - indexer_id, sickbeard.indexerApi(indexer).name,), logger.DEBUG) + logger.log(u'Empty lookup result - no XEM data for show %s on %s' % ( + indexer_id, sickbeard.indexerApi(indexer).name), logger.DEBUG) except Exception as e: logger.log( - u"Exception while refreshing XEM data for show " + str(indexer_id) + " on " + sickbeard.indexerApi( - indexer).name + ": " + ex(e), logger.WARNING) + u'Exception while refreshing XEM data for show ' + str(indexer_id) + ' on ' + sickbeard.indexerApi( + indexer).name + ': ' + ex(e), logger.WARNING) logger.log(traceback.format_exc(), logger.DEBUG) + def fix_xem_numbering(indexer_id, indexer): """ Returns a dict of (season, episode) : (sceneSeason, sceneEpisode) mappings for an entire show. Both the keys and values of the dict are tuples. Will be empty if there are no scene numbers set in xem """ - if indexer_id is None: + if None is indexer_id: return {} indexer_id = int(indexer_id) @@ -584,8 +580,8 @@ def fix_xem_numbering(indexer_id, indexer): # # Get query results # tmp = get_from_api(url, params=params)['result'] - myDB = db.DBConnection() - rows = myDB.select( + my_db = db.DBConnection() + rows = my_db.select( 'SELECT season, episode, absolute_number, scene_season, scene_episode, scene_absolute_number FROM tv_episodes WHERE indexer = ? and showid = ?', [indexer, indexer_id]) @@ -600,7 +596,7 @@ def fix_xem_numbering(indexer_id, indexer): update_scene_absolute_number = False logger.log( - u'Fixing any XEM scene mapping issues for show %s on %s' % (indexer_id, sickbeard.indexerApi(indexer).name,), + u'Fixing any XEM scene mapping issues for show %s on %s' % (indexer_id, sickbeard.indexerApi(indexer).name), logger.DEBUG) cl = [] @@ -653,44 +649,44 @@ def fix_xem_numbering(indexer_id, indexer): if update_absolute_number: cl.append([ - "UPDATE tv_episodes SET absolute_number = ? WHERE showid = ? AND season = ? AND episode = ?", + 'UPDATE tv_episodes SET absolute_number = ? WHERE showid = ? AND season = ? AND episode = ?', [absolute_number, indexer_id, season, episode - ]]) + ]]) update_absolute_number = False if update_scene_season: cl.append([ - "UPDATE tv_episodes SET scene_season = ? WHERE showid = ? AND season = ? AND episode = ?", + 'UPDATE tv_episodes SET scene_season = ? WHERE showid = ? AND season = ? AND episode = ?', [scene_season, indexer_id, season, episode - ]]) + ]]) update_scene_season = False if update_scene_episode: cl.append([ - "UPDATE tv_episodes SET scene_episode = ? WHERE showid = ? AND season = ? AND episode = ?", + 'UPDATE tv_episodes SET scene_episode = ? WHERE showid = ? AND season = ? AND episode = ?', [scene_episode, indexer_id, season, episode - ]]) + ]]) update_scene_episode = False if update_scene_absolute_number: cl.append([ - "UPDATE tv_episodes SET scene_absolute_number = ? WHERE showid = ? AND season = ? AND episode = ?", + 'UPDATE tv_episodes SET scene_absolute_number = ? WHERE showid = ? AND season = ? AND episode = ?', [scene_absolute_number, indexer_id, season, episode - ]]) + ]]) update_scene_absolute_number = False - if len(cl) > 0: - myDB = db.DBConnection() - myDB.mass_action(cl) + if 0 < len(cl): + my_db = db.DBConnection() + my_db.mass_action(cl) diff --git a/sickbeard/showUpdater.py b/sickbeard/showUpdater.py index b42e2101..7b3faa3a 100644 --- a/sickbeard/showUpdater.py +++ b/sickbeard/showUpdater.py @@ -45,6 +45,9 @@ class ShowUpdater(): # refresh network timezones network_timezones.update_network_dict() + # update xem id lists + sickbeard.scene_exceptions.get_xem_ids() + # update scene exceptions sickbeard.scene_exceptions.retrieve_exceptions() diff --git a/sickbeard/show_queue.py b/sickbeard/show_queue.py index 5784cdd5..502cb57c 100644 --- a/sickbeard/show_queue.py +++ b/sickbeard/show_queue.py @@ -29,6 +29,7 @@ from sickbeard import generic_queue from sickbeard import name_cache from sickbeard.exceptions import ex from sickbeard.blackandwhitelist import BlackAndWhiteList +from sickbeard.indexers.indexer_config import INDEXER_TVDB class ShowQueue(generic_queue.GenericQueue): @@ -131,12 +132,12 @@ class ShowQueue(generic_queue.GenericQueue): return queueItemObj - def refreshShow(self, show, force=False, scheduled_update=False): + def refreshShow(self, show, force=False, scheduled_update=False, after_update=False): if self.isBeingRefreshed(show) and not force: raise exceptions.CantRefreshException('This show is already being refreshed, not refreshing again.') - if (self.isBeingUpdated(show) or self.isInUpdateQueue(show)) and not force: + if ((not after_update and self.isBeingUpdated(show)) or self.isInUpdateQueue(show)) and not force: logger.log( u'A refresh was attempted but there is already an update queued or in progress. Since updates do a refresh at the end anyway I\'m skipping this request.', logger.DEBUG) @@ -510,7 +511,8 @@ class QueueItemRefresh(ShowQueueItem): self.show.populateCache() # Load XEM data to DB for show - sickbeard.scene_numbering.xem_refresh(self.show.indexerid, self.show.indexer) + if self.show.indexerid in sickbeard.scene_exceptions.xem_tvdb_ids_list if INDEXER_TVDB == self.show.indexer else sickbeard.scene_exceptions.xem_rage_ids_list: + sickbeard.scene_numbering.xem_refresh(self.show.indexerid, self.show.indexer) self.inProgress = False @@ -641,7 +643,7 @@ class QueueItemUpdate(ShowQueueItem): except exceptions.EpisodeDeletedException: pass - sickbeard.showQueueScheduler.action.refreshShow(self.show, self.force) + sickbeard.showQueueScheduler.action.refreshShow(self.show, self.force, self.scheduled_update, after_update=True) class QueueItemForceUpdate(QueueItemUpdate): diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py index f003940d..5212f034 100644 --- a/sickbeard/webserve.py +++ b/sickbeard/webserve.py @@ -2040,7 +2040,7 @@ class NewHomeAddShows(Home): if not lang or lang == 'null': lang = 'en' - search_term = search_term.encode('utf-8') + search_term = search_term.strip().encode('utf-8') results = {} final_results = [] @@ -3294,7 +3294,7 @@ class showQueueOverview(Manage): t = PageTemplate(headers=self.request.headers, file='manage_showQueueOverview.tmpl') t.queueLength = sickbeard.showQueueScheduler.action.queue_length() t.showList = sickbeard.showList - t.ShowUpdateRunning = sickbeard.showQueueScheduler.action.isShowUpdateRunning() + t.ShowUpdateRunning = sickbeard.showQueueScheduler.action.isShowUpdateRunning() or sickbeard.showUpdateScheduler.action.amActive t.submenu = self.ManageMenu() diff --git a/tests/scene_helpers_tests.py b/tests/scene_helpers_tests.py index bfb55f37..ce9cb586 100644 --- a/tests/scene_helpers_tests.py +++ b/tests/scene_helpers_tests.py @@ -1,14 +1,16 @@ +# coding=utf-8 + import unittest import test_lib as test -import sys, os.path +import sys +import os.path sys.path.insert(1, os.path.abspath('..')) from sickbeard import show_name_helpers, scene_exceptions, common, name_cache import sickbeard from sickbeard import db -from sickbeard.databases import cache_db from sickbeard.tv import TVShow as Show @@ -26,9 +28,9 @@ class SceneTests(test.SickbeardTestDBCase): self.assertEqual(result, expected) def test_allPossibleShowNames(self): - #common.sceneExceptions[-1] = ['Exception Test'] - myDB = db.DBConnection("cache.db") - myDB.action("INSERT INTO scene_exceptions (indexer_id, show_name, season) VALUES (?,?,?)", [-1, 'Exception Test', -1]) + # common.sceneExceptions[-1] = ['Exception Test'] + my_db = db.DBConnection('cache.db') + my_db.action('INSERT INTO scene_exceptions (indexer_id, show_name, season) VALUES (?,?,?)', [-1, 'Exception Test', -1]) common.countryList['Full Country Name'] = 'FCN' self._test_allPossibleShowNames('Show Name', expected=['Show Name']) @@ -42,7 +44,7 @@ class SceneTests(test.SickbeardTestDBCase): self._test_filterBadReleases('Show.S02.German.Stuff-Grp', False) self._test_filterBadReleases('Show.S02.Some.Stuff-Core2HD', False) self._test_filterBadReleases('Show.S02.Some.German.Stuff-Grp', False) - #self._test_filterBadReleases('German.Show.S02.Some.Stuff-Grp', True) + # self._test_filterBadReleases('German.Show.S02.Some.Stuff-Grp', True) self._test_filterBadReleases('Show.S02.This.Is.German', False) @@ -51,28 +53,39 @@ class SceneExceptionTestCase(test.SickbeardTestDBCase): def setUp(self): super(SceneExceptionTestCase, self).setUp() - sickbeard.showList = [Show(1, 70726), Show(1, 164451)] + sickbeard.showList = [Show(1, 79604), Show(1, 251085)] scene_exceptions.retrieve_exceptions() name_cache.buildNameCache() def test_sceneExceptionsEmpty(self): self.assertEqual(scene_exceptions.get_scene_exceptions(0), []) - def test_sceneExceptionsBabylon5(self): - self.assertEqual(sorted(scene_exceptions.get_scene_exceptions(70726)), ['Babylon 5', 'Babylon5']) + def test_sceneExceptionsBlack_Lagoon(self): + self.assertEqual(sorted(scene_exceptions.get_scene_exceptions(79604)), ['Black-Lagoon']) def test_sceneExceptionByName(self): - self.assertEqual(scene_exceptions.get_scene_exception_by_name('Babylon5'), [70726, -1]) - self.assertEqual(scene_exceptions.get_scene_exception_by_name('babylon 5'), [70726, -1]) - self.assertEqual(scene_exceptions.get_scene_exception_by_name('Carlos 2010'), [164451, -1]) + self.assertEqual(scene_exceptions.get_scene_exception_by_name('Black-Lagoon'), [79604, -1]) + self.assertEqual(scene_exceptions.get_scene_exception_by_name('Black Lagoon: The Second Barrage'), [79604, 2]) + self.assertEqual(scene_exceptions.get_scene_exception_by_name('Rokka no Yuusha'), [None, None]) + + def test_sceneExceptionByNameAnime(self): + sickbeard.showList = None + sickbeard.showList = [Show(1, 79604), Show(1, 295243)] + sickbeard.showList[0].anime = 1 + sickbeard.showList[1].anime = 1 + scene_exceptions.retrieve_exceptions() + name_cache.buildNameCache() + self.assertEqual(scene_exceptions.get_scene_exception_by_name(u'ブラック・ラグーン'), [79604, -1]) + self.assertEqual(scene_exceptions.get_scene_exception_by_name(u'Burakku Ragūn'), [79604, -1]) + self.assertEqual(scene_exceptions.get_scene_exception_by_name('Rokka no Yuusha'), [295243, -1]) def test_sceneExceptionByNameEmpty(self): self.assertEqual(scene_exceptions.get_scene_exception_by_name('nothing useful'), [None, None]) def test_sceneExceptionsResetNameCache(self): # clear the exceptions - myDB = db.DBConnection("cache.db") - myDB.action("DELETE FROM scene_exceptions") + my_db = db.DBConnection('cache.db') + my_db.action('DELETE FROM scene_exceptions') # put something in the cache name_cache.addNameToCache('Cached Name', 0) From a64f0e0390584193f9c7677c22683c9fefc5165a Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 6 Aug 2015 19:05:26 +0800 Subject: [PATCH 2/2] Bump release date --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 4644528d..4c49edc5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,4 +1,4 @@ -### 0.10.0 (2015-xx-xx xx:xx:xx UTC) +### 0.10.0 (2015-08-06 11:05:00 UTC) * Remove EZRSS provider * Update Tornado webserver to 4.2 (fdfaf3d)