diff --git a/CHANGES.md b/CHANGES.md index b9e865ea..cdf25cc3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -35,6 +35,7 @@ * Change py2 exception clauses to py2/3 compatible clauses * Change py2 print statements to py2/3 compatible functions * Change Kodi notifier to use requests as opposed to urllib +* Change to consolidate scene exceptions and name cache code [develop changelog] * Update Requests library 2.7.0 (ab1f493) to 2.7.0 (8b5e457) diff --git a/sickbeard/__init__.py b/sickbeard/__init__.py index 703f88fd..f09be6eb 100755 --- a/sickbeard/__init__.py +++ b/sickbeard/__init__.py @@ -135,7 +135,7 @@ PROXY_INDEXERS = True LOCALHOST_IP = None -CPU_PRESET = None +CPU_PRESET = 'NORMAL' ANON_REDIRECT = None diff --git a/sickbeard/name_cache.py b/sickbeard/name_cache.py index 845505b8..40dfc338 100644 --- a/sickbeard/name_cache.py +++ b/sickbeard/name_cache.py @@ -23,18 +23,19 @@ nameCache = {} nameCacheLock = threading.Lock() -def addNameToCache(name, indexer_id=0): +def addNameToCache(name, indexer_id=0, season=-1): """Adds the show & tvdb id to the namecache :param name: the show name to cache :param indexer_id: the TVDB and TVRAGE id that this show should be cached with (can be None/0 for unknown) + :param season: the season the the name exception belongs to. -1 for generic exception """ global nameCache # standardize the name we're using to account for small differences in providers name = sickbeard.helpers.full_sanitizeSceneName(name) if name not in nameCache: - nameCache[name] = int(indexer_id) + nameCache[name] = [int(indexer_id), season] def retrieveNameFromCache(name): @@ -47,7 +48,7 @@ def retrieveNameFromCache(name): name = sickbeard.helpers.full_sanitizeSceneName(name) if name in nameCache: - return int(nameCache[name]) + return int(nameCache[name][0]) def buildNameCache(show=None): @@ -64,26 +65,27 @@ def buildNameCache(show=None): nameCache = dict((k, v) for k, v in nameCache.items() if v != show.indexerid) # add standard indexer name to namecache - nameCache[show.name] = show.indexerid + nameCache[sickbeard.helpers.full_sanitizeSceneName(show.name)] = [show.indexerid, -1] else: # generate list of indexer ids to look up in cache.db indexer_ids = [x.indexerid for x in sickbeard.showList if x] # add all standard show indexer names to namecache nameCache = dict( - (sickbeard.helpers.full_sanitizeSceneName(x.name), x.indexerid) for x in sickbeard.showList if x) + (sickbeard.helpers.full_sanitizeSceneName(x.name), [x.indexerid, -1]) for x in sickbeard.showList if x) cacheDB = db.DBConnection('cache.db') cache_results = cacheDB.select( - 'SELECT show_name, indexer_id FROM scene_exceptions WHERE indexer_id IN (%s)' % ','.join( + 'SELECT show_name, indexer_id, season FROM scene_exceptions WHERE indexer_id IN (%s)' % ','.join( ['?'] * len(indexer_ids)), indexer_ids) if cache_results: for cache_result in cache_results: indexer_id = int(cache_result['indexer_id']) + season = int(cache_result['season']) name = sickbeard.helpers.full_sanitizeSceneName(cache_result['show_name']) - nameCache[name] = indexer_id + nameCache[name] = [indexer_id, season] def remove_from_namecache(indexer_id): diff --git a/sickbeard/name_parser/parser.py b/sickbeard/name_parser/parser.py index e638fa41..07494c8f 100644 --- a/sickbeard/name_parser/parser.py +++ b/sickbeard/name_parser/parser.py @@ -29,6 +29,7 @@ import sickbeard from sickbeard import logger, helpers, scene_numbering, common, scene_exceptions, encodingKludge as ek, db from dateutil import parser from sickbeard.exceptions import ex +from sickbeard.common import cpu_presets class NameParser(object): @@ -215,7 +216,7 @@ class NameParser(object): if bestResult.show and bestResult.show.is_anime and len(self.compiled_regexes[1]) > 1 and regex != 1: continue - # if this is a naming pattern test or result doesn't have a show object then return best result + # if this is a naming pattern test then return best result if not bestResult.show or self.naming_pattern: return bestResult @@ -340,9 +341,9 @@ class NameParser(object): logger.DEBUG) # CPU sleep - time.sleep(0.02) + time.sleep(cpu_presets[sickbeard.CPU_PRESET]) - return bestResult + return bestResult def _combine_results(self, first, second, attr): # if the first doesn't exist then return the second or nothing diff --git a/sickbeard/name_parser/regexes.py b/sickbeard/name_parser/regexes.py index ef1c89b2..bc4fa3b8 100644 --- a/sickbeard/name_parser/regexes.py +++ b/sickbeard/name_parser/regexes.py @@ -220,7 +220,7 @@ anime_regexes = [ (?P\d{1,3}) # E01 (-(?P\d{1,3}))? # E02 (v(?P[0-9]))? # version - [ ._-]+\[(?P\d{3,4}[xp]?\d{0,4}[\.\w\s-]*)\] # Source_Quality_Etc- + [ ._-]+\[(?P\d{3,4}[xp]?\d{0,4}.+?)\] # Source_Quality_Etc- (\[(?P\w{8})\])? # CRC .*? # Separator and EOL '''), diff --git a/sickbeard/scene_exceptions.py b/sickbeard/scene_exceptions.py index 386dece2..84fecac1 100644 --- a/sickbeard/scene_exceptions.py +++ b/sickbeard/scene_exceptions.py @@ -128,34 +128,11 @@ def get_scene_exception_by_name_multiple(show_name): Given a show name, return the indexerid of the exception, None if no exception is present. """ - - # try the obvious case first - myDB = db.DBConnection('cache.db') - exception_result = myDB.select( - "SELECT indexer_id, season FROM scene_exceptions WHERE LOWER(show_name) = ? ORDER BY season ASC", - [show_name.lower()]) - if exception_result: - return [(int(x["indexer_id"]), int(x["season"])) for x in exception_result] - - out = [] - all_exception_results = myDB.select("SELECT show_name, indexer_id, season FROM scene_exceptions") - - for cur_exception in all_exception_results: - - cur_exception_name = cur_exception["show_name"] - cur_indexer_id = int(cur_exception["indexer_id"]) - cur_season = int(cur_exception["season"]) - - if show_name.lower() in ( - cur_exception_name.lower(), - sickbeard.helpers.sanitizeSceneName(cur_exception_name).lower().replace('.', ' ')): - logger.log(u"Scene exception lookup got indexer id " + str(cur_indexer_id) + u", using that", logger.DEBUG) - out.append((cur_indexer_id, cur_season)) - - if out: - return out - else: - return [(None, None)] + try: + exception_result = name_cache.nameCache[helpers.full_sanitizeSceneName(show_name)] + return [exception_result] + except: + return [[None, None]] def retrieve_exceptions(): diff --git a/tests/name_parser_tests.py b/tests/name_parser_tests.py index 9e519ce8..81498d47 100644 --- a/tests/name_parser_tests.py +++ b/tests/name_parser_tests.py @@ -132,7 +132,12 @@ simple_test_cases = { '[UTW]_Fractal_-_01_[h264-720p][96D3F1BF]': parser.ParseResult(None, 'Fractal', None, [], 'h264-720p', 'UTW', None, [1]), '[a-s]_inuyasha_-_028_rs2_[BFDDF9F2]': parser.ParseResult(None, 'inuyasha', None, [], 'BFDDF9F2', 'a-s', None, [28]), '[HorribleSubs] Fairy Tail S2 - 37 [1080p]': parser.ParseResult(None,'Fairy Tail S2', None, [], '1080p', 'HorribleSubs', None, [37]), - '[HorribleSubs] Sword Art Online II - 23 [720p]': parser.ParseResult(None, 'Sword Art Online II', None, [], '720p', 'HorribleSubs', None, [23]) + '[HorribleSubs] Sword Art Online II - 23 [720p]': parser.ParseResult(None, 'Sword Art Online II', None, [], '720p', 'HorribleSubs', None, [23]), + }, + + 'anime_standard': { + '[Cthuko] Shirobako - 05v2 [720p H264 AAC][80C9B09B]': parser.ParseResult(None, 'Shirobako', None, [], '720p H264 AAC', 'Cthuko', None, [5]), + '[Ayako]_Minami-ke_Okaeri_-_01v2_[1024x576 H264+AAC][B1912CD8]': parser.ParseResult(None, 'Minami-ke Okaeri', None, [], '1024x576 H264+AAC', 'Ayako', None, [1]), }, 'anime_ep_name': { @@ -432,6 +437,10 @@ class BasicTests(test.SickbeardTestDBCase): np = parser.NameParser(False, TVShow(is_anime=True), testing=True) self._test_names(np, 'anime_ultimate') + def test_anime_standard(self): + np = parser.NameParser(False, TVShow(is_anime=True), testing=True) + self._test_names(np, 'anime_standard') + def test_anime_ep_name(self): np = parser.NameParser(False, TVShow(is_anime=True), testing=True) self._test_names(np, 'anime_ep_name') diff --git a/tests/scene_helpers_tests.py b/tests/scene_helpers_tests.py index 4cc64aa3..bfb55f37 100644 --- a/tests/scene_helpers_tests.py +++ b/tests/scene_helpers_tests.py @@ -50,7 +50,10 @@ class SceneExceptionTestCase(test.SickbeardTestDBCase): def setUp(self): super(SceneExceptionTestCase, self).setUp() + + sickbeard.showList = [Show(1, 70726), Show(1, 164451)] scene_exceptions.retrieve_exceptions() + name_cache.buildNameCache() def test_sceneExceptionsEmpty(self): self.assertEqual(scene_exceptions.get_scene_exceptions(0), []) @@ -59,12 +62,12 @@ class SceneExceptionTestCase(test.SickbeardTestDBCase): self.assertEqual(sorted(scene_exceptions.get_scene_exceptions(70726)), ['Babylon 5', 'Babylon5']) 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('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]) def test_sceneExceptionByNameEmpty(self): - self.assertEqual(scene_exceptions.get_scene_exception_by_name('nothing useful'), (None, None)) + self.assertEqual(scene_exceptions.get_scene_exception_by_name('nothing useful'), [None, None]) def test_sceneExceptionsResetNameCache(self): # clear the exceptions