Add type property, more test cases and fixes

This commit is contained in:
Toilal
2015-11-03 17:58:51 +01:00
parent 08e7c5ede5
commit 53c5522b23
16 changed files with 744 additions and 57 deletions
+9 -2
View File
@@ -18,6 +18,13 @@ For episodes, some properties have been renamed
- ``series`` is now ``title``.
- ``title`` is now ``episodeTitle``.
All other episodes properties have been ported with the same name (*Work in progress ...*)
For movies, some properties have been renamed
For movies, all properties have been ported with the same name (*Work in progress ...*).
- ``filmtitle`` is now ``filmSeries``
``type`` ``episode`` value is now ``series``.
All info type (``seriesinfo``, ``movieinfo``) have been removed in favor of checking the ``extension`` property for
``nfo`` value.
All other properties have been ported with the same name (*Work in progress ...*)
+1 -1
View File
@@ -5,7 +5,7 @@ Common module
"""
import six
seps = six.u(r' [](){}+*|&=§-_~#/\.,;') # list of tags/words separators
seps = six.u(r' [](){}+*|&=§-_~#/\.,;:') # list of tags/words separators
title_seps = six.u(r'-+/\|;') # separators for title
+3 -1
View File
@@ -11,6 +11,8 @@ from .common.formatters import strip
from .common.comparators import marker_sorted
from .common.date import valid_year
from .properties.type import type_processor
import six
@@ -161,4 +163,4 @@ def enlarge_group_matches(matches):
PROCESSORS = Rebulk().processor(enlarge_group_matches).post_processor(equivalent_holes, remove_ambiguous,
country_in_title, season_year)
country_in_title, season_year, type_processor)
+4 -2
View File
@@ -93,6 +93,8 @@ def find_countries(string, context=None):
COUNTRY.functional(find_countries,
#  Prefer language and any other property over country
conflict_solver=lambda match, other: match)
#  Prefer language and any other property over country if not US or GB.
conflict_solver=lambda match, other: match
if other.name != 'language' or match.value not in [babelfish.Country('US'), babelfish.Country('GB')]
else other)
+4 -1
View File
@@ -13,7 +13,10 @@ EDITION = Rebulk().regex_defaults(flags=re.IGNORECASE, abbreviations=[dash]).str
EDITION.defaults(name='edition', validator=seps_surround)
EDITION.regex('collector', 'collector-edition', 'edition-collector', value='Collector Edition')
EDITION.regex('special-edition', 'edition-special', value='Special Edition')
EDITION.regex('special-edition', 'edition-special', value='Special Edition',
conflict_solver=lambda match, other: other
if other.name == 'episodeDetails' and other.value == 'Special'
else '__default__')
EDITION.regex('criterion-edition', 'edition-criterion', value='Criterion Edition')
EDITION.regex('deluxe', 'deluxe-edition', 'edition-deluxe', value='Deluxe Edition')
EDITION.regex('director\'?s?-cut', 'director\'?s?-cut-edition', 'edition-director\'?s?-cut', value='Director\'s cut')
+5 -10
View File
@@ -57,7 +57,7 @@ class EpisodeTitleFromPosition(TitleBaseRule):
lambda previous: any(name in previous.names
for name in ['episodeNumber', 'episodeDetails',
'episodeCount', 'season', 'seasonCount',
'date', 'title']),
'date', 'title', 'year']),
0)
crc32 = matches.named('crc32')
@@ -70,15 +70,10 @@ class EpisodeTitleFromPosition(TitleBaseRule):
return True
return False
def is_ignored(self, match):
def should_remove(self, match, matches, filepart, hole):
if match.name == 'episodeDetails':
return True
return super(EpisodeTitleFromPosition, self).is_ignored(match)
def should_keep(self, match, to_keep, matches, filepart, hole, starting):
if match.name == 'episodeDetails' and not matches.previous(match, lambda match: match.name == 'season'):
return True, False # Keep episodeDetails, but don't crop title.
return super(EpisodeTitleFromPosition, self).should_keep(match, to_keep, matches, filepart, hole, starting)
return False
return super(EpisodeTitleFromPosition, self).should_remove(match, matches, filepart, hole)
def __init__(self):
super(EpisodeTitleFromPosition, self).__init__('episodeTitle', ['title'])
@@ -109,7 +104,7 @@ class AlternativeTitleReplace(Rule):
lambda previous: any(name in previous.names
for name in ['episodeNumber', 'episodeDetails',
'episodeCount', 'season', 'seasonCount',
'date', 'title']),
'date', 'title', 'year']),
0)
crc32 = matches.named('crc32')
+1 -2
View File
@@ -35,8 +35,7 @@ EPISODES.regex(r'(?P<season>\d+)x(?P<episodeNumber>\d+)' +
# episodeDetails property
for episode_detail in ('Special', 'Bonus', 'Omake', 'Ova', 'Oav', 'Pilot', 'Unaired'):
EPISODES.string(episode_detail, value=episode_detail, name='episodeDetails',
conflict_solver=lambda match, other: None)
EPISODES.string(episode_detail, value=episode_detail, name='episodeDetails')
EPISODES.regex(r'Extras?', name='episodeDetails', value='Extras')
EPISODES.defaults(validate_all=True, validator={'__parent__': seps_surround}, children=True, private_parent=True)
+4 -3
View File
@@ -7,11 +7,12 @@ import regex as re
from rebulk import Rebulk
from ..common import dash
from ..common.validators import seps_surround
from ..common.numeral import numeral, parse_numeral
PART = Rebulk().regex_defaults(flags=re.IGNORECASE, abbreviations=[dash])
PART = Rebulk().regex_defaults(flags=re.IGNORECASE, abbreviations=[dash], validator={'__parent__': seps_surround})
prefixes = ['pt', 'part']
PART.regex(r'\L<prefixes>-(' + numeral + r')(?:$|[^\d])', prefixes=prefixes,
name='part', private_parent=True, children=True, formatter=parse_numeral)
PART.regex(r'\L<prefixes>-(' + numeral + r')', prefixes=prefixes,
name='part', validate_all=True, private_parent=True, children=True, formatter=parse_numeral)
+5 -3
View File
@@ -68,6 +68,9 @@ class SceneReleaseGroup(Rule):
not matches.input_string[previous_match.end:last_hole.start].strip(seps)\
and not int_coercable(last_hole.value.strip(seps)):
last_hole.name = 'releaseGroup'
last_hole.tags = ['scene']
# if hole is insed a group marker with same value, remove [](){} ...
group = matches.markers.at_match(last_hole, lambda marker: marker.name == 'group', 0)
if group:
@@ -75,9 +78,8 @@ class SceneReleaseGroup(Rule):
if group.value == last_hole.value:
last_hole.start = group.start + 1
last_hole.end = group.end - 1
last_hole.tags = ['anime']
last_hole.name = 'releaseGroup'
last_hole.tags = ['scene']
ret.append(last_hole)
return ret
@@ -94,7 +96,7 @@ class AnimeReleaseGroup(Rule):
ret = []
# If a scene releaseGroup is found, ignore this kind of releaseGroup rule.
if matches.named('releaseGroup', lambda match: 'scene' in match.tags):
if matches.named('releaseGroup'):
return ret
for filepart in marker_sorted(matches.markers.named('path'), matches):
+29 -17
View File
@@ -9,29 +9,41 @@ import regex as re
from ..common.validators import seps_surround
from guessit.rules.common import dash
SCREEN_SIZE = Rebulk().regex_defaults(flags=re.IGNORECASE)
SCREEN_SIZE.defaults(name="screenSize", validator=seps_surround,
conflict_solver=lambda match, other: '__default__'
if other.name in ['screenSize', 'episodeNumber', 'season']
else other)
def conflict_solver(match, other):
"""
Conflict solver for most screenSize.
"""
if other.name in ['episodeNumber', 'season']:
return '__default__'
if other.name == 'screenSize' and 'resolution' in other.tags:
# The chtouile to solve conflict in "720 x 432" string matching both 720p pattern (but it's not 720p ...)
int_value = _digits_re.findall(match.raw)[-1]
if other.value.startswith(int_value):
return match
return other
SCREEN_SIZE.regex(r"(?:\d{3,}(?:\\|\/|x|\*))?360(?:i|p?x?)", value="360p")
SCREEN_SIZE.regex(r"(?:\d{3,}(?:\\|\/|x|\*))?368(?:i|p?x?)", value="368p")
SCREEN_SIZE.regex(r"(?:\d{3,}(?:\\|\/|x|\*))?480(?:i|p?x?)", value="480p")
SCREEN_SIZE.regex(r"(?:\d{3,}(?:\\|\/|x|\*))?576(?:i|p?x?)", value="576p")
SCREEN_SIZE.regex(r"(?:\d{3,}(?:\\|\/|x|\*))?720(?:i|p?x?)", value="720p")
SCREEN_SIZE.regex(r"(?:\d{3,}(?:\\|\/|x|\*))?900(?:i|p?x?)", value="900p")
SCREEN_SIZE.regex(r"(?:\d{3,}(?:\\|\/|x|\*))?1080i", value="1080i")
SCREEN_SIZE.regex(r"(?:\d{3,}(?:\\|\/|x|\*))?1080p?x?", value="1080p")
SCREEN_SIZE.regex(r"(?:\d{3,4}(?:\\|\/|x|\*))?2160(?:i|p?x?)", value="4K")
SCREEN_SIZE = Rebulk().regex_defaults(flags=re.IGNORECASE)
SCREEN_SIZE.defaults(name="screenSize", validator=seps_surround, conflict_solver=conflict_solver)
SCREEN_SIZE.regex(r"(?:\d{3,}(?:x|\*))?360(?:i|p?x?)", value="360p")
SCREEN_SIZE.regex(r"(?:\d{3,}(?:x|\*))?368(?:i|p?x?)", value="368p")
SCREEN_SIZE.regex(r"(?:\d{3,}(?:x|\*))?480(?:i|p?x?)", value="480p")
SCREEN_SIZE.regex(r"(?:\d{3,}(?:x|\*))?576(?:i|p?x?)", value="576p")
SCREEN_SIZE.regex(r"(?:\d{3,}(?:x|\*))?720(?:i|p?x?)", value="720p")
SCREEN_SIZE.regex(r"(?:\d{3,}(?:x|\*))?900(?:i|p?x?)", value="900p")
SCREEN_SIZE.regex(r"(?:\d{3,}(?:x|\*))?1080i", value="1080i")
SCREEN_SIZE.regex(r"(?:\d{3,}(?:x|\*))?1080p?x?", value="1080p")
SCREEN_SIZE.regex(r"(?:\d{3,}(?:x|\*))?2160(?:i|p?x?)", value="4K")
_digits_re = re.compile(r'\d+')
SCREEN_SIZE.regex(r'\d{3,4}-?[x\*]-?\d{3,4}', abbreviations=[dash],
SCREEN_SIZE.defaults(name="screenSize", validator=seps_surround)
SCREEN_SIZE.regex(r'\d{3,}-?(?:x|\*)-?\d{3,}',
formatter=lambda value: 'x'.join(_digits_re.findall(value)),
conflict_solver=lambda match, other: match if other.name == 'screenSize' else other)
abbreviations=[dash],
tags=['resolution'],
conflict_solver=lambda match, other: '__default__' if other.name == 'screenSize' else other)
class ScreenSizeOnlyOne(Rule):
+45 -14
View File
@@ -72,7 +72,7 @@ class TitleBaseRule(Rule):
"""
Ignore matches when scanning for title (hole)
"""
return match.name in ['language', 'country']
return match.name in ['language', 'country', 'episodeDetails']
def should_keep(self, match, to_keep, matches, filepart, hole, starting):
"""
@@ -93,22 +93,35 @@ class TitleBaseRule(Rule):
:rtype:
"""
# Keep language if other languages exists in the filepart.
outside_matches = filepart.crop(hole)
other_languages = []
for outside in outside_matches:
other_languages.extend(matches.range(outside.start, outside.end,
lambda c_match: c_match.name == match.name and c_match not in to_keep))
if match.name in ['language', 'country']:
outside_matches = filepart.crop(hole)
other_languages = []
for outside in outside_matches:
other_languages.extend(matches.range(outside.start, outside.end,
lambda c_match: c_match.name == match.name and
c_match not in to_keep))
if not other_languages:
return True
if not other_languages:
return True
return False
def should_remove(self, match, matches, filepart, hole):
"""
Check if this match should be removed after beeing ignored.
:param match:
:param matches:
:param filepart:
:param hole:
:return:
"""
return True
def check_titles_in_filepart(self, filepart, matches):
"""
Find title in filepart (ignoring language)
"""
# pylint:disable=too-many-locals,too-many-branches
# pylint:disable=too-many-locals,too-many-branches,too-many-statements
start, end = filepart.span
holes = matches.holes(start, end + 1, formatter=formatters(cleanup, reorder_title),
@@ -160,7 +173,9 @@ class TitleBaseRule(Rule):
if crop:
hole.start = ignored_match.end
to_remove.extend(ignored_matches)
for match in ignored_matches:
if self.should_remove(match, matches, filepart, hole):
to_remove.append(match)
for keep_match in to_keep:
to_remove.remove(keep_match)
@@ -170,8 +185,17 @@ class TitleBaseRule(Rule):
if self.alternative_match_name:
# Split and keep values that can be a title
titles = hole.split(title_seps, lambda match: match.value)
for title in titles[1:]:
title.name = self.alternative_match_name
for title in list(titles[1:]):
previous_title = titles[titles.index(title) - 1]
separator = matches.input_string[previous_title.end:title.start]
if len(separator) == 1 and '-' == separator \
and previous_title.raw[-1] not in seps \
and title.raw[0] not in seps:
titles[titles.index(title) - 1].end = title.end
titles.remove(title)
else:
title.name = self.alternative_match_name
else:
titles = [hole]
return titles, to_remove
@@ -238,6 +262,7 @@ class PreferTitleWithYear(Rule):
return not context.get('expected_title')
def when(self, matches, context):
with_year_in_group = []
with_year = []
titles = matches.named('title')
@@ -246,9 +271,15 @@ class PreferTitleWithYear(Rule):
if filepart:
year_match = matches.range(filepart.start, filepart.end, lambda match: match.name == 'year', 0)
if year_match:
with_year.append(title)
group = matches.markers.at_match(year_match, lambda group: group.name == 'group')
if group:
with_year_in_group.append(title)
else:
with_year.append(title)
if with_year:
if with_year_in_group:
title_values = set([title.value for title in with_year_in_group])
elif with_year:
title_values = set([title.value for title in with_year])
else:
title_values = set([title.value for title in titles])
+56
View File
@@ -0,0 +1,56 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
screenSize property
"""
from rebulk.match import Match
def _type(matches, value):
"""
Define type match with given value.
:param matches:
:param value:
:return:
"""
matches.append(Match(0, len(matches.input_string), name='type', value=value))
def type_processor(matches):
"""
Post processor to find file type based on all others found matches.
:param matches:
:return:
"""
episode = matches.named('episodeNumber')
season = matches.named('season')
episode_details = matches.named('episodeDetails')
if episode or season or episode_details:
_type(matches, 'series')
return
film = matches.named('filmNumber')
if film:
_type(matches, 'movie')
return
year = matches.named('year')
date = matches.named('date')
if date and not year:
_type(matches, 'series')
return
bonus = matches.named('bonusNumber')
if bonus and not year:
_type(matches, 'series')
return
crc32 = matches.named('crc32')
anime_release_group = matches.named('releaseGroup', lambda match: 'anime' in match.tags)
if crc32 and anime_release_group:
_type(matches, 'series')
return
_type(matches, 'movie')
+550
View File
@@ -0,0 +1,550 @@
? Movies/Fear and Loathing in Las Vegas (1998)/Fear.and.Loathing.in.Las.Vegas.720p.HDDVD.DTS.x264-ESiR.mkv
: type: movie
title: Fear and Loathing in Las Vegas
year: 1998
screenSize: 720p
format: HD-DVD
audioCodec: DTS
videoCodec: h264
releaseGroup: ESiR
? Series/Duckman/Duckman - 101 (01) - 20021107 - I, Duckman.avi
: type: series
title: Duckman
season: 1
episodeNumber: 1
episodeTitle: I, Duckman
date: 2002-11-07
? Series/Neverwhere/Neverwhere.05.Down.Street.[tvu.org.ru].avi
: type: series
title: Neverwhere
episodeNumber: 5
episodeTitle: Down Street
website: tvu.org.ru
? Neverwhere.05.Down.Street.[tvu.org.ru].avi
: type: series
title: Neverwhere
episodeNumber: 5
episodeTitle: Down Street
website: tvu.org.ru
? Series/Breaking Bad/Minisodes/Breaking.Bad.(Minisodes).01.Good.Cop.Bad.Cop.WEBRip.XviD.avi
: type: series
title: Breaking Bad
episodeFormat: Minisode
episodeNumber: 1
episodeTitle: Good Cop Bad Cop
format: WEBRip
videoCodec: XviD
? Series/Kaamelott/Kaamelott - Livre V - Ep 23 - Le Forfait.avi
: type: series
title: Kaamelott
episodeNumber: 23
episodeTitle: Le Forfait
? Movies/The Doors (1991)/09.03.08.The.Doors.(1991).BDRip.720p.AC3.X264-HiS@SiLUHD-English.[sharethefiles.com].mkv
: type: movie
title: The Doors
year: 1991
date: 2008-03-09
format: BluRay
screenSize: 720p
audioCodec: AC3
videoCodec: h264
releaseGroup: HiS@SiLUHD
language: english
website: sharethefiles.com
? Movies/M.A.S.H. (1970)/MASH.(1970).[Divx.5.02][Dual-Subtitulos][DVDRip].ogm
: type: movie
title: MASH
year: 1970
videoCodec: DivX
format: DVD
? the.mentalist.501.hdtv-lol.mp4
: type: series
title: the mentalist
season: 5
episodeNumber: 1
format: HDTV
releaseGroup: lol
? the.simpsons.2401.hdtv-lol.mp4
: type: series
title: the simpsons
season: 24
episodeNumber: 1
format: HDTV
releaseGroup: lol
? Homeland.S02E01.HDTV.x264-EVOLVE.mp4
: type: series
title: Homeland
season: 2
episodeNumber: 1
format: HDTV
videoCodec: h264
releaseGroup: EVOLVE
? /media/Band_of_Brothers-e01-Currahee.mkv
: type: series
title: Band of Brothers
episodeNumber: 1
episodeTitle: Currahee
? /media/Band_of_Brothers-x02-We_Stand_Alone_Together.mkv
: type: series
title: Band of Brothers
bonusNumber: 2
bonusTitle: We Stand Alone Together
? /movies/James_Bond-f21-Casino_Royale-x02-Stunts.mkv
: type: movie
title: Casino Royale
filmSeries: James Bond
filmNumber: 21
bonusNumber: 2
bonusTitle: Stunts
? /TV Shows/new.girl.117.hdtv-lol.mp4
: type: series
title: new girl
season: 1
episodeNumber: 17
format: HDTV
releaseGroup: lol
? The.Office.(US).1x03.Health.Care.HDTV.XviD-LOL.avi
: type: series
title: The Office (US)
country: US
season: 1
episodeNumber: 3
episodeTitle: Health Care
format: HDTV
videoCodec: XviD
releaseGroup: LOL
? The_Insider-(1999)-x02-60_Minutes_Interview-1996.mp4
: type: movie
title: The Insider
year: 1999
bonusNumber: 2
bonusTitle: 60 Minutes Interview-1996
? OSS_117--Cairo,_Nest_of_Spies.mkv
: type: movie
title: OSS 117
alternativeTitle: Cairo, Nest of Spies
? Rush.._Beyond_The_Lighted_Stage-x09-Between_Sun_and_Moon-2002_Hartford.mkv
: type: movie
title: Rush Beyond The Lighted Stage
bonusNumber: 9
bonusTitle: Between Sun and Moon
year: 2002
? House.Hunters.International.S56E06.720p.hdtv.x264.mp4
: type: series
title: House Hunters International
season: 56
episodeNumber: 6
screenSize: 720p
format: HDTV
videoCodec: h264
? White.House.Down.2013.1080p.BluRay.DTS-HD.MA.5.1.x264-PublicHD.mkv
: type: movie
title: White House Down
year: 2013
screenSize: 1080p
format: BluRay
audioCodec: DTS
audioProfile: HDMA
videoCodec: h264
releaseGroup: PublicHD
audioChannels: "5.1"
? White.House.Down.2013.1080p.BluRay.DTSHD.MA.5.1.x264-PublicHD.mkv
: type: movie
title: White House Down
year: 2013
screenSize: 1080p
format: BluRay
audioCodec: DTS
audioProfile: HDMA
videoCodec: h264
releaseGroup: PublicHD
audioChannels: "5.1"
? Hostages.S01E01.Pilot.for.Air.720p.WEB-DL.DD5.1.H.264-NTb.nfo
: type: series
title: Hostages
episodeTitle: Pilot for Air
season: 1
episodeNumber: 1
screenSize: 720p
format: WEB-DL
audioChannels: "5.1"
videoCodec: h264
audioCodec: DolbyDigital
releaseGroup: NTb
? Despicable.Me.2.2013.1080p.BluRay.x264-VeDeTT.nfo
: type: movie
title: Despicable Me 2
year: 2013
screenSize: 1080p
format: BluRay
videoCodec: h264
releaseGroup: VeDeTT
? Le Cinquieme Commando 1971 SUBFORCED FRENCH DVDRiP XViD AC3 Bandix.mkv
: type: movie
audioCodec: AC3
format: DVD
releaseGroup: Bandix
subtitleLanguage: French
title: Le Cinquieme Commando
videoCodec: XviD
year: 1971
? Le Seigneur des Anneaux - La Communauté de l'Anneau - Version Longue - BDRip.mkv
: type: movie
format: BluRay
title: Le Seigneur des Anneaux
? La petite bande (Michel Deville - 1983) VF PAL MP4 x264 AAC.mkv
: type: movie
audioCodec: AAC
language: French
title: La petite bande
videoCodec: h264
year: 1983
other: PAL
? Retour de Flammes (Gregor Schnitzler 2003) FULL DVD.iso
: type: movie
format: DVD
title: Retour de Flammes
type: movie
year: 2003
? A.Common.Title.Special.2014.avi
: type: movie
year: 2014
title: A Common Title Special
? A.Common.Title.2014.Special.avi
: type: series
year: 2014
title: A Common Title
episodeTitle: Special
episodeDetails: Special
? A.Common.Title.2014.Special.Edition.avi
: type: movie
year: 2014
title: A Common Title
edition: Special Edition
? Downton.Abbey.2013.Christmas.Special.HDTV.x264-FoV.mp4
: type: series
year: 2013
title: Downton Abbey
episodeTitle: Christmas Special
videoCodec: h264
releaseGroup: FoV
format: HDTV
episodeDetails: Special
? Doctor_Who_2013_Christmas_Special.The_Time_of_The_Doctor.HD
: type: series
title: Doctor Who
other: HD
episodeDetails: Special
episodeTitle: Christmas Special The Time of The Doctor
year: 2013
? Doctor Who 2005 50th Anniversary Special The Day of the Doctor 3.avi
: type: series
title: Doctor Who
episodeDetails: Special
episodeTitle: 50th Anniversary Special The Day of the Doctor 3
year: 2005
? Robot Chicken S06-Born Again Virgin Christmas Special HDTV x264.avi
: type: series
title: Robot Chicken
format: HDTV
season: 6
episodeTitle: Born Again Virgin Christmas Special
videoCodec: h264
episodeDetails: Special
? Wicked.Tuna.S03E00.Head.To.Tail.Special.HDTV.x264-YesTV
: options: -n
type: series
title: Wicked Tuna
episodeTitle: Head To Tail Special
releaseGroup: YesTV
season: 3
episodeNumber: 0
videoCodec: h264
format: HDTV
episodeDetails: Special
? The.Voice.UK.S03E12.HDTV.x264-C4TV
: options: -n
episodeNumber: 12
videoCodec: h264
format: HDTV
title: The Voice (GB)
releaseGroup: C4TV
season: 3
country: United Kingdom
type: series
? /tmp/star.trek.9/star.trek.9.mkv
: type: movie
title: star trek 9
? star.trek.9.mkv
: type: movie
title: star trek 9
? FlexGet.S01E02.TheName.HDTV.xvid
: options: -n
episodeNumber: 2
format: HDTV
season: 1
title: FlexGet
episodeTitle: TheName
type: series
videoCodec: XviD
? FlexGet.S01E02.TheName.HDTV.xvid
: options: -n
episodeNumber: 2
format: HDTV
season: 1
title: FlexGet
episodeTitle: TheName
type: series
videoCodec: XviD
? some.series.S03E14.Title.Here.720p
: options: -n
episodeNumber: 14
screenSize: 720p
season: 3
title: some series
episodeTitle: Title Here
type: series
? '[the.group] Some.Series.S03E15.Title.Two.720p'
: options: -n
episodeNumber: 15
releaseGroup: the.group
screenSize: 720p
season: 3
title: Some Series
episodeTitle: Title Two
type: series
? 'HD 720p: Some series.S03E16.Title.Three'
: options: -n
episodeNumber: 16
other: HD
screenSize: 720p
season: 3
title: Some series
episodeTitle: Title Three
type: series
? Something.Season.2.1of4.Ep.Title.HDTV.torrent
: episodeCount: 4
episodeNumber: 1
format: HDTV
season: 2
title: Something
episodeTitle: Title
type: series
extension: torrent
? Show-A (US) - Episode Title S02E09 hdtv
: options: -n
country: US
episodeNumber: 9
format: HDTV
season: 2
title: Show-A (US)
type: series
? Jack's.Show.S03E01.blah.1080p
: options: -n
episodeNumber: 1
screenSize: 1080p
season: 3
title: Jack's Show
episodeTitle: blah
type: series
? FlexGet.epic
: options: -n
title: FlexGet epic
type: movie
? FlexGet.Apt.1
: options: -n
title: FlexGet Apt 1
type: movie
? FlexGet.aptitude
: options: -n
title: FlexGet aptitude
type: movie
? FlexGet.Step1
: options: -n
title: FlexGet Step1
type: movie
? Movies/El Bosque Animado (1987)/El.Bosque.Animado.[Jose.Luis.Cuerda.1987].[Xvid-Dvdrip-720 * 432].avi
: format: DVD
screenSize: 720x432
title: El Bosque Animado
videoCodec: XviD
year: 1987
type: movie
? Movies/El Bosque Animado (1987)/El.Bosque.Animado.[Jose.Luis.Cuerda.1987].[Xvid-Dvdrip-720x432].avi
: format: DVD
screenSize: 720x432
title: El Bosque Animado
videoCodec: XviD
year: 1987
type: movie
? 2009.shoot.fruit.chan.multi.dvd9.pal
: options: -n
format: DVD
language: mul
other: PAL
title: shoot fruit chan
type: movie
year: 2009
? 2009.shoot.fruit.chan.multi.dvd5.pal
: options: -n
format: DVD
language: mul
other: PAL
title: shoot fruit chan
type: movie
year: 2009
? The.Flash.2014.S01E01.PREAIR.WEBRip.XviD-EVO.avi
: episodeNumber: 1
format: WEBRip
other: Preair
releaseGroup: EVO
season: 1
title: The Flash
type: series
videoCodec: XviD
year: 2014
? Ice.Lake.Rebels.S01E06.Ice.Lake.Games.720p.HDTV.x264-DHD
: options: -n
episodeNumber: 6
format: HDTV
releaseGroup: DHD
screenSize: 720p
season: 1
title: Ice Lake Rebels
episodeTitle: Ice Lake Games
type: series
videoCodec: h264
? The League - S06E10 - Epi Sexy.mkv
: episodeNumber: 10
season: 6
title: The League
episodeTitle: Epi Sexy
type: series
? Stay (2005) [1080p]/Stay.2005.1080p.BluRay.x264.YIFY.mp4
: format: BluRay
releaseGroup: YIFY
screenSize: 1080p
title: Stay
type: movie
videoCodec: h264
year: 2005
? /media/live/A/Anger.Management.S02E82.720p.HDTV.X264-DIMENSION.mkv
: format: HDTV
releaseGroup: DIMENSION
screenSize: 720p
title: Anger Management
type: series
season: 2
episodeNumber: 82
videoCodec: h264
? "[Figmentos] Monster 34 - At the End of Darkness [781219F1].mkv"
: type: series
releaseGroup: Figmentos
title: Monster
episodeNumber: 34
episodeTitle: At the End of Darkness
crc32: 781219F1
? Game.of.Thrones.S05E07.720p.HDTV-KILLERS.mkv
: type: series
episodeNumber: 7
format: HDTV
releaseGroup: KILLERS
screenSize: 720p
season: 5
title: Game of Thrones
? Game.of.Thrones.S05E07.HDTV.720p-KILLERS.mkv
: type: series
episodeNumber: 7
format: HDTV
releaseGroup: KILLERS
screenSize: 720p
season: 5
title: Game of Thrones
? Parks and Recreation - [04x12] - Ad Campaign.avi
: type: series
title: Parks and Recreation
season: 4
episodeNumber: 12
episodeTitle: Ad Campaign
? Star Trek Into Darkness (2013)/star.trek.into.darkness.2013.720p.web-dl.h264-publichd.mkv
: type: movie
title: Star Trek Into Darkness
year: 2013
screenSize: 720p
format: WEB-DL
videoCodec: h264
releaseGroup: publichd
? /var/medias/series/The Originals/Season 02/The.Originals.S02E15.720p.HDTV.X264-DIMENSION.mkv
: type: series
title: The Originals
season: 2
episodeNumber: 15
screenSize: 720p
format: HDTV
videoCodec: h264
releaseGroup: DIMENSION
+3
View File
@@ -1,3 +1,6 @@
? __default__
: type: movie
? Movies/Fear and Loathing in Las Vegas (1998)/Fear.and.Loathing.in.Las.Vegas.720p.HDDVD.DTS.x264-ESiR.mkv
: title: Fear and Loathing in Las Vegas
year: 1998
+10 -1
View File
@@ -1,3 +1,6 @@
? __default__
: type: series
? Series/Californication/Season 2/Californication.2x05.Vaginatown.HDTV.XviD-0TV.avi
: title: Californication
season: 2
@@ -195,7 +198,7 @@
? Series/My Name Is Earl/My.Name.Is.Earl.S01Extras.-.Bad.Karma.DVDRip.XviD.avi
: title: My Name Is Earl
season: 1
episodeTitle: Bad Karma
episodeTitle: Extras - Bad Karma
format: DVD
episodeDetails: Extras
videoCodec: XviD
@@ -553,6 +556,7 @@
: title: Battlestar Galactica
season: 0
episodeDetails: Pilot
episodeTitle: Pilot
language: French
format: DVD
videoCodec: XviD
@@ -886,6 +890,7 @@
: format: DVB
releaseGroup: FlexGet
title: FooBar 7
type: movie
? FooBar.7v3.PDTV-FlexGet
: options: --episode-prefer-number
@@ -1376,10 +1381,14 @@
format: HDTV
videoCodec: XviD
releaseGroup: Etc-Group
type: movie
# Fallback to movie type because we can't tell it's a series ...
? Show.Name.Part.1.and.Part.2.Blah-Group
: part: [1, 2]
title: Show Name
type: movie
# Fallback to movie type because we can't tell it's a series ...
? Show Name - 01 - Ep Name
: episodeNumber: 1
+15
View File
@@ -175,6 +175,13 @@ class TestYml(object):
files, ids = files_and_ids(filename_predicate)
@staticmethod
def set_default(expected, default):
if default:
for k, v in default.items():
if k not in expected:
expected[k] = v
@pytest.mark.parametrize('filename', files, ids=ids)
def test(self, filename):
with open(os.path.join(__location__, filename), 'r', encoding='utf-8') as infile:
@@ -188,7 +195,15 @@ class TestYml(object):
else:
last_expected = expected
default = None
try:
default = data['__default__']
del data['__default__']
except KeyError:
pass
for string, expected in data.items():
TestYml.set_default(expected, default)
if not isinstance(string, six.text_type):
string = six.text_type(string)
if not string_predicate or string_predicate(string): # pylint: disable=not-callable