mirror of
https://github.com/zoriya/guessit.git
synced 2026-06-08 20:35:34 +00:00
Add type property, more test cases and fixes
This commit is contained in:
+9
-2
@@ -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 ...*)
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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')
|
||||
@@ -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
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user