diff --git a/CHANGES.md b/CHANGES.md index cf0b0ca3..d3471845 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,4 +1,9 @@ -### 0.16.5 (2018-05-07 21:15:00 UTC) +### 0.16.6 (2018-05-14 01:00:00 UTC) + +* Change improve tolerance to parse a release title with a badly placed episode name + + +### 0.16.5 (2018-05-07 21:15:00 UTC) * Fix HTTP 422 error when using Plex Username and Password * Change how show URLs are made for TV info sources diff --git a/sickbeard/name_parser/parser.py b/sickbeard/name_parser/parser.py index c14a1645..db2b90ae 100644 --- a/sickbeard/name_parser/parser.py +++ b/sickbeard/name_parser/parser.py @@ -674,10 +674,10 @@ class ParseResult(object): @staticmethod def _replace_ep_name_helper(e_i_n_n, n): - ep_regex = r'\W*%s\W*' % re.sub(r' ', r'\W', re.sub(r'[^a-zA-Z0-9 ]', r'\W?', + ep_regex = r'\W*%s(\W*)' % re.sub(r' ', r'\W', re.sub(r'[^a-zA-Z0-9 ]', r'\W?', re.sub(r'\W+$', '', n.strip()))) if None is regex: - return re.sub(ep_regex, '', e_i_n_n, flags=re.I) + return re.sub(r'^\W+', '', re.sub(ep_regex, r'\1', e_i_n_n, flags=re.I)) er = trunc(len(re.findall(r'\w', ep_regex)) / 5) try: @@ -685,7 +685,7 @@ class ParseResult(object): me = min(3, me) except (StandardError, Exception): me = 3 - return regex.sub(r'(%s){e<=%d}' % (ep_regex, (er, me)[er > me]), '', e_i_n_n, flags=regex.I | regex.B) + return re.sub(r'^\W+', '', regex.sub(r'(?:%s){e<=%d}' % (ep_regex, (er, me)[er > me]), r'\1', e_i_n_n, flags=regex.I | regex.B)) def get_extra_info_no_name(self): extra_info_no_name = self.extra_info diff --git a/tests/name_parser_tests.py b/tests/name_parser_tests.py index 983a6f7c..8270dcb0 100644 --- a/tests/name_parser_tests.py +++ b/tests/name_parser_tests.py @@ -9,7 +9,7 @@ sys.path.insert(1, os.path.abspath('..')) sys.path.insert(1, os.path.abspath('../lib')) from sickbeard.name_parser import parser -from sickbeard import name_cache +from sickbeard import name_cache, tv import sickbeard @@ -355,6 +355,35 @@ failure_cases = ['7sins-jfcs01e09-720p-bluray-x264'] invalid_cases = [('The.Show.Name.111E14.1080p.WEB.x264-GROUP', 'the show name', 11, False)] +extra_info_no_name_tests = [('The Show Name', [('Episode 302', 3, 2)], + 'The.Show.Name.S03E02.REPACK.Episode.302.720p.AMZN.WEBRip.DDP5.1.x264-GROUP', + 'REPACK.720p.AMZN.WEBRip.DDP5.1.x264'), + ('The Show Name', [('Episode 302', 3, 2)], + 'The.Show.Name.S03E02.Episode.302.REPACK.720p.AMZN.WEBRip.DDP5.1.x264-GROUP', + 'REPACK.720p.AMZN.WEBRip.DDP5.1.x264'), + ('The Show Name', [('Episode 302', 3, 2)], + 'The.Show.Name.S03E02.Episode.302.REPACK.720p.AMZN.WEBRip.DDP5.1.x264-GROUP', + 'REPACK.720p.AMZN.WEBRip.DDP5.1.x264'), + ('The Show Name', [('Episode 302', 3, 2)], + 'The.Show.Name.S03E02.REPACK.720p.AMZN.WEBRip.DDP5.1.x264-GROUP', + 'REPACK.720p.AMZN.WEBRip.DDP5.1.x264'), + ('The Show Name', [('Episode 302', 3, 2)], + 'The.Show.Name.S03E02.720p.AMZN.WEBRip.DDP5.1.x264-GROUP', + '720p.AMZN.WEBRip.DDP5.1.x264'), + ('The Show Name', [('Episode 302', 3, 2), ('Name 2', 3, 3)], + 'The.Show.Name.S03E02E03.720p.AMZN.WEBRip.DDP5.1.x264-GROUP', + '720p.AMZN.WEBRip.DDP5.1.x264'), + ('The Show Name', [('Episode 302', 3, 2), ('Name 2', 3, 3)], + 'The.Show.Name.S03E02E03.Episode.302.Name2.720p.AMZN.WEBRip.DDP5.1.x264-GROUP', + '720p.AMZN.WEBRip.DDP5.1.x264'), + ('The Show Name', [('Episode 302', 3, 2), ('Name 2', 3, 3)], + 'The.Show.Name.S03E02E03.REPACK.Episode.302.Name2.720p.AMZN.WEBRip.DDP5.1.x264-GROUP', + 'REPACK.720p.AMZN.WEBRip.DDP5.1.x264'), + ('The Show Name', [('Episode 302', 3, 2), ('Name 2', 3, 3)], + 'The.Show.Name.S03E02E03.Episode.302.Name2.REPACK.720p.AMZN.WEBRip.DDP5.1.x264-GROUP', + 'REPACK.720p.AMZN.WEBRip.DDP5.1.x264'), + ] + class InvalidCases(test.SickbeardTestDBCase): @@ -612,11 +641,35 @@ class BasicTests(test.SickbeardTestDBCase): self._test_names(np, 'anime_bare') -class TVShow(object): - def __init__(self, is_anime=False, name='', indexerid=0): - self.is_anime = is_anime - self.name = name - self.indexerid = indexerid +class TVShow(tv.TVShow): + def __init__(self, is_anime=False, name='', indexerid=0, indexer=0): + self._anime = is_anime + self._name = name + self._indexerid = indexerid + self._indexer = indexer + self.episodes = {} + + +class TVEpisode(tv.TVEpisode): + def __init__(self, name=''): + self._name = name + + +class ExtraInfoNoNameTests(test.SickbeardTestDBCase): + def test_extra_info_no_name(self): + for case in extra_info_no_name_tests: + tvs = TVShow(False, case[0], 2, 1) + for e in case[1]: + tvs.episodes.setdefault(e[1], {}).update({e[2]: TVEpisode(e[0])}) + + sickbeard.showList = [tvs] + name_cache.nameCache = {} + name_cache.buildNameCache() + + np = parser.NameParser() + r = np.parse(case[2]) + n_ep = r.extra_info_no_name() + self.assertEqual(n_ep, case[3]) if __name__ == '__main__': @@ -637,3 +690,6 @@ if __name__ == '__main__': suite = unittest.TestLoader().loadTestsFromTestCase(InvalidCases) unittest.TextTestRunner(verbosity=2).run(suite) + + suite = unittest.TestLoader().loadTestsFromTestCase(ExtraInfoNoNameTests) + unittest.TextTestRunner(verbosity=2).run(suite)