mirror of
https://github.com/clinton-hall/nzbToMedia.git
synced 2025-08-19 21:03:14 -07:00
Added in untracked files for guessit.
Fixed issue #332, we confirm if str or list and take action depending on result.
This commit is contained in:
parent
6a0158d801
commit
0fac36b4fc
42 changed files with 4188 additions and 14 deletions
26
lib/guessit/test/__init__.py
Normal file
26
lib/guessit/test/__init__.py
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# GuessIt - A library for guessing information from filenames
|
||||||
|
# Copyright (c) 2013 Nicolas Wack <wackou@gmail.com>
|
||||||
|
#
|
||||||
|
# GuessIt is free software; you can redistribute it and/or modify it under
|
||||||
|
# the terms of the Lesser GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# GuessIt is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# Lesser GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the Lesser GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from guessit.slogging import setupLogging
|
||||||
|
setupLogging()
|
||||||
|
logging.disable(logging.INFO)
|
40
lib/guessit/test/__main__.py
Normal file
40
lib/guessit/test/__main__.py
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# GuessIt - A library for guessing information from filenames
|
||||||
|
# Copyright (c) 2013 Nicolas Wack <wackou@gmail.com>
|
||||||
|
#
|
||||||
|
# GuessIt is free software; you can redistribute it and/or modify it under
|
||||||
|
# the terms of the Lesser GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# GuessIt is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# Lesser GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the Lesser GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
from guessit.test import (test_api, test_autodetect, test_autodetect_all, test_doctests,
|
||||||
|
test_episode, test_hashes, test_language, test_main,
|
||||||
|
test_matchtree, test_movie, test_quality, test_utils)
|
||||||
|
from unittest import TextTestRunner
|
||||||
|
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
def main():
|
||||||
|
for suite in [test_api.suite, test_autodetect.suite,
|
||||||
|
test_autodetect_all.suite, test_doctests.suite,
|
||||||
|
test_episode.suite, test_hashes.suite, test_language.suite,
|
||||||
|
test_main.suite, test_matchtree.suite, test_movie.suite,
|
||||||
|
test_quality.suite, test_utils.suite]:
|
||||||
|
TextTestRunner(verbosity=2).run(suite)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
289
lib/guessit/test/autodetect.yaml
Normal file
289
lib/guessit/test/autodetect.yaml
Normal file
|
@ -0,0 +1,289 @@
|
||||||
|
? 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
|
||||||
|
|
||||||
|
? Leopard.dmg
|
||||||
|
: type: unknown
|
||||||
|
extension: dmg
|
||||||
|
|
||||||
|
? Series/Duckman/Duckman - 101 (01) - 20021107 - I, Duckman.avi
|
||||||
|
: type: episode
|
||||||
|
series: Duckman
|
||||||
|
season: 1
|
||||||
|
episodeNumber: 1
|
||||||
|
title: I, Duckman
|
||||||
|
date: 2002-11-07
|
||||||
|
|
||||||
|
? Series/Neverwhere/Neverwhere.05.Down.Street.[tvu.org.ru].avi
|
||||||
|
: type: episode
|
||||||
|
series: Neverwhere
|
||||||
|
episodeNumber: 5
|
||||||
|
title: Down Street
|
||||||
|
website: tvu.org.ru
|
||||||
|
|
||||||
|
? Neverwhere.05.Down.Street.[tvu.org.ru].avi
|
||||||
|
: type: episode
|
||||||
|
series: Neverwhere
|
||||||
|
episodeNumber: 5
|
||||||
|
title: Down Street
|
||||||
|
website: tvu.org.ru
|
||||||
|
|
||||||
|
? Series/Breaking Bad/Minisodes/Breaking.Bad.(Minisodes).01.Good.Cop.Bad.Cop.WEBRip.XviD.avi
|
||||||
|
: type: episode
|
||||||
|
series: Breaking Bad
|
||||||
|
episodeFormat: Minisode
|
||||||
|
episodeNumber: 1
|
||||||
|
title: Good Cop Bad Cop
|
||||||
|
format: WEBRip
|
||||||
|
videoCodec: XviD
|
||||||
|
|
||||||
|
? Series/Kaamelott/Kaamelott - Livre V - Ep 23 - Le Forfait.avi
|
||||||
|
: type: episode
|
||||||
|
series: Kaamelott
|
||||||
|
episodeNumber: 23
|
||||||
|
title: 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: M.A.S.H.
|
||||||
|
year: 1970
|
||||||
|
videoCodec: DivX
|
||||||
|
format: DVD
|
||||||
|
|
||||||
|
? the.mentalist.501.hdtv-lol.mp4
|
||||||
|
: type: episode
|
||||||
|
series: The Mentalist
|
||||||
|
season: 5
|
||||||
|
episodeNumber: 1
|
||||||
|
format: HDTV
|
||||||
|
releaseGroup: LOL
|
||||||
|
|
||||||
|
? the.simpsons.2401.hdtv-lol.mp4
|
||||||
|
: type: episode
|
||||||
|
series: The Simpsons
|
||||||
|
season: 24
|
||||||
|
episodeNumber: 1
|
||||||
|
format: HDTV
|
||||||
|
releaseGroup: LOL
|
||||||
|
|
||||||
|
? Homeland.S02E01.HDTV.x264-EVOLVE.mp4
|
||||||
|
: type: episode
|
||||||
|
series: Homeland
|
||||||
|
season: 2
|
||||||
|
episodeNumber: 1
|
||||||
|
format: HDTV
|
||||||
|
videoCodec: h264
|
||||||
|
releaseGroup: EVOLVE
|
||||||
|
|
||||||
|
? /media/Band_of_Brothers-e01-Currahee.mkv
|
||||||
|
: type: episode
|
||||||
|
series: Band of Brothers
|
||||||
|
episodeNumber: 1
|
||||||
|
title: Currahee
|
||||||
|
|
||||||
|
? /media/Band_of_Brothers-x02-We_Stand_Alone_Together.mkv
|
||||||
|
: type: episode
|
||||||
|
series: 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: episode
|
||||||
|
series: New Girl
|
||||||
|
season: 1
|
||||||
|
episodeNumber: 17
|
||||||
|
format: HDTV
|
||||||
|
releaseGroup: LOL
|
||||||
|
|
||||||
|
? The.Office.(US).1x03.Health.Care.HDTV.XviD-LOL.avi
|
||||||
|
: type: episode
|
||||||
|
series: The Office (US)
|
||||||
|
country: US
|
||||||
|
season: 1
|
||||||
|
episodeNumber: 3
|
||||||
|
title: 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--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-2002 Hartford
|
||||||
|
|
||||||
|
? House.Hunters.International.S56E06.720p.hdtv.x264.mp4
|
||||||
|
: type: episode
|
||||||
|
series: 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"
|
||||||
|
|
||||||
|
? Hostages.S01E01.Pilot.for.Air.720p.WEB-DL.DD5.1.H.264-NTb.nfo
|
||||||
|
: type: episodeinfo
|
||||||
|
series: Hostages
|
||||||
|
title: 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: movieinfo
|
||||||
|
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
|
||||||
|
|
||||||
|
? 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: episode
|
||||||
|
year: 2014
|
||||||
|
series: A Common Title
|
||||||
|
title: Special
|
||||||
|
special: 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: episode
|
||||||
|
year: 2013
|
||||||
|
series: Downton Abbey
|
||||||
|
title: Christmas Special
|
||||||
|
videoCodec: h264
|
||||||
|
releaseGroup: FoV
|
||||||
|
format: HDTV
|
||||||
|
special: Special
|
||||||
|
|
||||||
|
? Doctor_Who_2013_Christmas_Special.The_Time_of_The_Doctor.HD
|
||||||
|
: options: -n
|
||||||
|
type: episode
|
||||||
|
series: Doctor Who
|
||||||
|
other: HD
|
||||||
|
special: Special
|
||||||
|
title: Christmas Special The Time of The Doctor
|
||||||
|
year: 2013
|
||||||
|
|
||||||
|
? Doctor Who 2005 50th Anniversary Special The Day of the Doctor 3.avi
|
||||||
|
: type: episode
|
||||||
|
series: Doctor Who
|
||||||
|
special: Special
|
||||||
|
title: 50th Anniversary Special The Day of the Doctor 3
|
||||||
|
year: 2005
|
||||||
|
|
||||||
|
? Robot Chicken S06-Born Again Virgin Christmas Special HDTV x264.avi
|
||||||
|
: type: episode
|
||||||
|
series: Robot Chicken
|
||||||
|
format: HDTV
|
||||||
|
season: 6
|
||||||
|
title: Born Again Virgin Christmas Special
|
||||||
|
videoCodec: h264
|
||||||
|
special: Special
|
||||||
|
|
||||||
|
? Wicked.Tuna.S03E00.Head.To.Tail.Special.HDTV.x264-YesTV
|
||||||
|
: options: -n
|
||||||
|
type: episode
|
||||||
|
series: Wicked Tuna
|
||||||
|
title: Head To Tail Special
|
||||||
|
releaseGroup: YesTV
|
||||||
|
season: 3
|
||||||
|
episodeNumber: 0
|
||||||
|
videoCodec: h264
|
||||||
|
format: HDTV
|
||||||
|
special: Special
|
1
lib/guessit/test/dummy.srt
Normal file
1
lib/guessit/test/dummy.srt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Just a dummy srt file (used for unittests: do not remove!)
|
569
lib/guessit/test/episodes.yaml
Normal file
569
lib/guessit/test/episodes.yaml
Normal file
|
@ -0,0 +1,569 @@
|
||||||
|
# Dubious tests
|
||||||
|
#
|
||||||
|
#? "finale "
|
||||||
|
#: releaseGroup: FiNaLe
|
||||||
|
# extension: ""
|
||||||
|
|
||||||
|
|
||||||
|
? Series/Californication/Season 2/Californication.2x05.Vaginatown.HDTV.XviD-0TV.avi
|
||||||
|
: series: Californication
|
||||||
|
season: 2
|
||||||
|
episodeNumber: 5
|
||||||
|
title: Vaginatown
|
||||||
|
format: HDTV
|
||||||
|
videoCodec: XviD
|
||||||
|
releaseGroup: 0TV
|
||||||
|
|
||||||
|
? Series/dexter/Dexter.5x02.Hello,.Bandit.ENG.-.sub.FR.HDTV.XviD-AlFleNi-TeaM.[tvu.org.ru].avi
|
||||||
|
: series: Dexter
|
||||||
|
season: 5
|
||||||
|
episodeNumber: 2
|
||||||
|
title: Hello, Bandit
|
||||||
|
language: English
|
||||||
|
subtitleLanguage: French
|
||||||
|
format: HDTV
|
||||||
|
videoCodec: XviD
|
||||||
|
releaseGroup: AlFleNi-TeaM
|
||||||
|
website: tvu.org.ru
|
||||||
|
|
||||||
|
? Series/Treme/Treme.1x03.Right.Place,.Wrong.Time.HDTV.XviD-NoTV.avi
|
||||||
|
: series: Treme
|
||||||
|
season: 1
|
||||||
|
episodeNumber: 3
|
||||||
|
title: Right Place, Wrong Time
|
||||||
|
format: HDTV
|
||||||
|
videoCodec: XviD
|
||||||
|
releaseGroup: NoTV
|
||||||
|
|
||||||
|
? Series/Duckman/Duckman - 101 (01) - 20021107 - I, Duckman.avi
|
||||||
|
: series: Duckman
|
||||||
|
season: 1
|
||||||
|
episodeNumber: 1
|
||||||
|
title: I, Duckman
|
||||||
|
date: 2002-11-07
|
||||||
|
|
||||||
|
? Series/Duckman/Duckman - S1E13 Joking The Chicken (unedited).avi
|
||||||
|
: series: Duckman
|
||||||
|
season: 1
|
||||||
|
episodeNumber: 13
|
||||||
|
title: Joking The Chicken
|
||||||
|
|
||||||
|
? Series/Simpsons/Saison 12 Français/Simpsons,.The.12x08.A.Bas.Le.Sergent.Skinner.FR.avi
|
||||||
|
: series: The Simpsons
|
||||||
|
season: 12
|
||||||
|
episodeNumber: 8
|
||||||
|
title: A Bas Le Sergent Skinner
|
||||||
|
language: French
|
||||||
|
|
||||||
|
? Series/Futurama/Season 3 (mkv)/[™] Futurama - S03E22 - Le chef de fer à 30% ( 30 Percent Iron Chef ).mkv
|
||||||
|
: series: Futurama
|
||||||
|
season: 3
|
||||||
|
episodeNumber: 22
|
||||||
|
title: Le chef de fer à 30%
|
||||||
|
|
||||||
|
? Series/The Office/Season 6/The Office - S06xE01.avi
|
||||||
|
: series: The Office
|
||||||
|
season: 6
|
||||||
|
episodeNumber: 1
|
||||||
|
|
||||||
|
? series/The Office/Season 4/The Office [401] Fun Run.avi
|
||||||
|
: series: The Office
|
||||||
|
season: 4
|
||||||
|
episodeNumber: 1
|
||||||
|
title: Fun Run
|
||||||
|
|
||||||
|
? Series/Mad Men Season 1 Complete/Mad.Men.S01E01.avi
|
||||||
|
: series: Mad Men
|
||||||
|
season: 1
|
||||||
|
episodeNumber: 1
|
||||||
|
other: complete
|
||||||
|
|
||||||
|
? series/Psych/Psych S02 Season 2 Complete English DVD/Psych.S02E02.65.Million.Years.Off.avi
|
||||||
|
: series: Psych
|
||||||
|
season: 2
|
||||||
|
episodeNumber: 2
|
||||||
|
title: 65 Million Years Off
|
||||||
|
language: english
|
||||||
|
format: DVD
|
||||||
|
other: complete
|
||||||
|
|
||||||
|
? series/Psych/Psych S02 Season 2 Complete English DVD/Psych.S02E03.Psy.Vs.Psy.Français.srt
|
||||||
|
: series: Psych
|
||||||
|
season: 2
|
||||||
|
episodeNumber: 3
|
||||||
|
title: Psy Vs Psy
|
||||||
|
format: DVD
|
||||||
|
language: English
|
||||||
|
subtitleLanguage: French
|
||||||
|
other: complete
|
||||||
|
|
||||||
|
? Series/Pure Laine/Pure.Laine.1x01.Toutes.Couleurs.Unies.FR.(Québec).DVB-Kceb.[tvu.org.ru].avi
|
||||||
|
: series: Pure Laine
|
||||||
|
season: 1
|
||||||
|
episodeNumber: 1
|
||||||
|
title: Toutes Couleurs Unies
|
||||||
|
format: DVB
|
||||||
|
releaseGroup: Kceb
|
||||||
|
language: french
|
||||||
|
website: tvu.org.ru
|
||||||
|
|
||||||
|
? Series/Pure Laine/2x05 - Pure Laine - Je Me Souviens.avi
|
||||||
|
: series: Pure Laine
|
||||||
|
season: 2
|
||||||
|
episodeNumber: 5
|
||||||
|
title: Je Me Souviens
|
||||||
|
|
||||||
|
? Series/Tout sur moi/Tout sur moi - S02E02 - Ménage à trois (14-01-2008) [Rip by Ampli].avi
|
||||||
|
: series: Tout sur moi
|
||||||
|
season: 2
|
||||||
|
episodeNumber: 2
|
||||||
|
title: Ménage à trois
|
||||||
|
date: 2008-01-14
|
||||||
|
|
||||||
|
? The.Mentalist.2x21.18-5-4.ENG.-.sub.FR.HDTV.XviD-AlFleNi-TeaM.[tvu.org.ru].avi
|
||||||
|
: series: The Mentalist
|
||||||
|
season: 2
|
||||||
|
episodeNumber: 21
|
||||||
|
title: 18-5-4
|
||||||
|
language: english
|
||||||
|
subtitleLanguage: french
|
||||||
|
format: HDTV
|
||||||
|
videoCodec: Xvid
|
||||||
|
releaseGroup: AlFleNi-TeaM
|
||||||
|
website: tvu.org.ru
|
||||||
|
|
||||||
|
? series/__ Incomplete __/Dr Slump (Catalan)/Dr._Slump_-_003_DVB-Rip_Catalan_by_kelf.avi
|
||||||
|
: series: Dr Slump
|
||||||
|
episodeNumber: 3
|
||||||
|
format: DVB
|
||||||
|
language: catalan
|
||||||
|
|
||||||
|
? series/Ren and Stimpy - Black_hole_[DivX].avi
|
||||||
|
: series: Ren and Stimpy
|
||||||
|
title: Black hole
|
||||||
|
videoCodec: DivX
|
||||||
|
|
||||||
|
? Series/Walt Disney/Donald.Duck.-.Good.Scouts.[www.bigernie.jump.to].avi
|
||||||
|
: series: Donald Duck
|
||||||
|
title: Good Scouts
|
||||||
|
website: www.bigernie.jump.to
|
||||||
|
|
||||||
|
? Series/Neverwhere/Neverwhere.05.Down.Street.[tvu.org.ru].avi
|
||||||
|
: series: Neverwhere
|
||||||
|
episodeNumber: 5
|
||||||
|
title: Down Street
|
||||||
|
website: tvu.org.ru
|
||||||
|
|
||||||
|
? Series/South Park/Season 4/South.Park.4x07.Cherokee.Hair.Tampons.DVDRip.[tvu.org.ru].avi
|
||||||
|
: series: South Park
|
||||||
|
season: 4
|
||||||
|
episodeNumber: 7
|
||||||
|
title: Cherokee Hair Tampons
|
||||||
|
format: DVD
|
||||||
|
website: tvu.org.ru
|
||||||
|
|
||||||
|
? Series/Kaamelott/Kaamelott - Livre V - Ep 23 - Le Forfait.avi
|
||||||
|
: series: Kaamelott
|
||||||
|
episodeNumber: 23
|
||||||
|
title: Le Forfait
|
||||||
|
|
||||||
|
? Series/Duckman/Duckman - 110 (10) - 20021218 - Cellar Beware.avi
|
||||||
|
: series: Duckman
|
||||||
|
season: 1
|
||||||
|
episodeNumber: 10
|
||||||
|
date: 2002-12-18
|
||||||
|
title: Cellar Beware
|
||||||
|
|
||||||
|
? Series/Ren & Stimpy/Ren And Stimpy - Onward & Upward-Adult Party Cartoon.avi
|
||||||
|
: series: Ren And Stimpy
|
||||||
|
title: Onward & Upward-Adult Party Cartoon
|
||||||
|
|
||||||
|
? Series/Breaking Bad/Minisodes/Breaking.Bad.(Minisodes).01.Good.Cop.Bad.Cop.WEBRip.XviD.avi
|
||||||
|
: series: Breaking Bad
|
||||||
|
episodeFormat: Minisode
|
||||||
|
episodeNumber: 1
|
||||||
|
title: Good Cop Bad Cop
|
||||||
|
format: WEBRip
|
||||||
|
videoCodec: XviD
|
||||||
|
|
||||||
|
? Series/My Name Is Earl/My.Name.Is.Earl.S01Extras.-.Bad.Karma.DVDRip.XviD.avi
|
||||||
|
: series: My Name Is Earl
|
||||||
|
season: 1
|
||||||
|
title: Bad Karma
|
||||||
|
format: DVD
|
||||||
|
special: Extras
|
||||||
|
videoCodec: XviD
|
||||||
|
|
||||||
|
? /mnt/series/The Big Bang Theory/S01/The.Big.Bang.Theory.S01E01.mkv
|
||||||
|
: series: The Big Bang Theory
|
||||||
|
season: 1
|
||||||
|
episodeNumber: 1
|
||||||
|
|
||||||
|
? /media/Parks_and_Recreation-s03-e01.mkv
|
||||||
|
: series: Parks and Recreation
|
||||||
|
season: 3
|
||||||
|
episodeNumber: 1
|
||||||
|
|
||||||
|
? /media/Parks_and_Recreation-s03-e02-Flu_Season.mkv
|
||||||
|
: series: Parks and Recreation
|
||||||
|
season: 3
|
||||||
|
title: Flu Season
|
||||||
|
episodeNumber: 2
|
||||||
|
|
||||||
|
? /media/Parks_and_Recreation-s03-x01.mkv
|
||||||
|
: series: Parks and Recreation
|
||||||
|
season: 3
|
||||||
|
bonusNumber: 1
|
||||||
|
|
||||||
|
? /media/Parks_and_Recreation-s03-x02-Gag_Reel.mkv
|
||||||
|
: series: Parks and Recreation
|
||||||
|
season: 3
|
||||||
|
bonusNumber: 2
|
||||||
|
bonusTitle: Gag Reel
|
||||||
|
|
||||||
|
? /media/Band_of_Brothers-e01-Currahee.mkv
|
||||||
|
: series: Band of Brothers
|
||||||
|
episodeNumber: 1
|
||||||
|
title: Currahee
|
||||||
|
|
||||||
|
? /media/Band_of_Brothers-x02-We_Stand_Alone_Together.mkv
|
||||||
|
: series: Band of Brothers
|
||||||
|
bonusNumber: 2
|
||||||
|
bonusTitle: We Stand Alone Together
|
||||||
|
|
||||||
|
? /TV Shows/Mad.M-5x9.mkv
|
||||||
|
: series: Mad M
|
||||||
|
season: 5
|
||||||
|
episodeNumber: 9
|
||||||
|
|
||||||
|
? /TV Shows/new.girl.117.hdtv-lol.mp4
|
||||||
|
: series: New Girl
|
||||||
|
season: 1
|
||||||
|
episodeNumber: 17
|
||||||
|
format: HDTV
|
||||||
|
releaseGroup: LOL
|
||||||
|
|
||||||
|
? Kaamelott - 5x44x45x46x47x48x49x50.avi
|
||||||
|
: series: Kaamelott
|
||||||
|
season: 5
|
||||||
|
episodeNumber: 44
|
||||||
|
episodeList: [44, 45, 46, 47, 48, 49, 50]
|
||||||
|
|
||||||
|
? Example S01E01-02.avi
|
||||||
|
: series: Example
|
||||||
|
season: 1
|
||||||
|
episodeNumber: 1
|
||||||
|
episodeList: [1, 2]
|
||||||
|
|
||||||
|
? Example S01E01E02.avi
|
||||||
|
: series: Example
|
||||||
|
season: 1
|
||||||
|
episodeNumber: 1
|
||||||
|
episodeList: [1, 2]
|
||||||
|
|
||||||
|
? Series/Baccano!/Baccano!_-_T1_-_Trailer_-_[Ayu](dae8173e).mkv
|
||||||
|
: series: Baccano!
|
||||||
|
other: Trailer
|
||||||
|
|
||||||
|
? Series/Doctor Who (2005)/Season 06/Doctor Who (2005) - S06E01 - The Impossible Astronaut (1).avi
|
||||||
|
: series: Doctor Who
|
||||||
|
year: 2005
|
||||||
|
season: 6
|
||||||
|
episodeNumber: 1
|
||||||
|
title: The Impossible Astronaut
|
||||||
|
|
||||||
|
? The.Office.(US).1x03.Health.Care.HDTV.XviD-LOL.avi
|
||||||
|
: series: The Office (US)
|
||||||
|
country: US
|
||||||
|
season: 1
|
||||||
|
episodeNumber: 3
|
||||||
|
title: Health Care
|
||||||
|
format: HDTV
|
||||||
|
videoCodec: XviD
|
||||||
|
releaseGroup: LOL
|
||||||
|
|
||||||
|
? /Volumes/data-1/Series/Futurama/Season 3/Futurama_-_S03_DVD_Bonus_-_Deleted_Scenes_Part_3.ogm
|
||||||
|
: series: Futurama
|
||||||
|
season: 3
|
||||||
|
other: Bonus
|
||||||
|
title: Deleted Scenes Part 3
|
||||||
|
format: DVD
|
||||||
|
|
||||||
|
? Ben.and.Kate.S01E02.720p.HDTV.X264-DIMENSION.mkv
|
||||||
|
: series: Ben and Kate
|
||||||
|
season: 1
|
||||||
|
episodeNumber: 2
|
||||||
|
screenSize: 720p
|
||||||
|
format: HDTV
|
||||||
|
videoCodec: h264
|
||||||
|
releaseGroup: DIMENSION
|
||||||
|
|
||||||
|
? /volume1/TV Series/Drawn Together/Season 1/Drawn Together 1x04 Requiem for a Reality Show.avi
|
||||||
|
: series: Drawn Together
|
||||||
|
season: 1
|
||||||
|
episodeNumber: 4
|
||||||
|
title: Requiem for a Reality Show
|
||||||
|
|
||||||
|
? Sons.of.Anarchy.S05E06.720p.WEB.DL.DD5.1.H.264-CtrlHD.mkv
|
||||||
|
: series: Sons of Anarchy
|
||||||
|
season: 5
|
||||||
|
episodeNumber: 6
|
||||||
|
screenSize: 720p
|
||||||
|
format: WEB-DL
|
||||||
|
audioChannels: "5.1"
|
||||||
|
audioCodec: DolbyDigital
|
||||||
|
videoCodec: h264
|
||||||
|
releaseGroup: CtrlHD
|
||||||
|
|
||||||
|
? /media/bdc64bfe-e36f-4af8-b550-e6fd2dfaa507/TV_Shows/Doctor Who (2005)/Saison 6/Doctor Who (2005) - S06E13 - The Wedding of River Song.mkv
|
||||||
|
: series: Doctor Who
|
||||||
|
season: 6
|
||||||
|
episodeNumber: 13
|
||||||
|
year: 2005
|
||||||
|
title: The Wedding of River Song
|
||||||
|
idNumber: bdc64bfe-e36f-4af8-b550-e6fd2dfaa507
|
||||||
|
|
||||||
|
? /mnt/videos/tvshows/Doctor Who/Season 06/E13 - The Wedding of River Song.mkv
|
||||||
|
: series: Doctor Who
|
||||||
|
season: 6
|
||||||
|
episodeNumber: 13
|
||||||
|
title: The Wedding of River Song
|
||||||
|
|
||||||
|
? The.Simpsons.S24E03.Adventures.in.Baby-Getting.720p.WEB-DL.DD5.1.H.264-CtrlHD.mkv
|
||||||
|
: series: The Simpsons
|
||||||
|
season: 24
|
||||||
|
episodeNumber: 3
|
||||||
|
title: Adventures in Baby-Getting
|
||||||
|
screenSize: 720p
|
||||||
|
format: WEB-DL
|
||||||
|
audioChannels: "5.1"
|
||||||
|
audioCodec: DolbyDigital
|
||||||
|
videoCodec: h264
|
||||||
|
releaseGroup: CtrlHD
|
||||||
|
|
||||||
|
? /home/disaster/Videos/TV/Merlin/merlin_2008.5x02.arthurs_bane_part_two.repack.720p_hdtv_x264-fov.mkv
|
||||||
|
: series: Merlin
|
||||||
|
season: 5
|
||||||
|
episodeNumber: 2
|
||||||
|
title: Arthurs bane part two
|
||||||
|
screenSize: 720p
|
||||||
|
format: HDTV
|
||||||
|
videoCodec: h264
|
||||||
|
releaseGroup: Fov
|
||||||
|
year: 2008
|
||||||
|
other: Proper
|
||||||
|
|
||||||
|
? "Da Vinci's Demons - 1x04 - The Magician.mkv"
|
||||||
|
: series: "Da Vinci's Demons"
|
||||||
|
season: 1
|
||||||
|
episodeNumber: 4
|
||||||
|
title: The Magician
|
||||||
|
|
||||||
|
? CSI.S013E18.Sheltered.720p.WEB-DL.DD5.1.H.264.mkv
|
||||||
|
: series: CSI
|
||||||
|
season: 13
|
||||||
|
episodeNumber: 18
|
||||||
|
title: Sheltered
|
||||||
|
screenSize: 720p
|
||||||
|
format: WEB-DL
|
||||||
|
audioChannels: "5.1"
|
||||||
|
audioCodec: DolbyDigital
|
||||||
|
videoCodec: h264
|
||||||
|
|
||||||
|
? Game of Thrones S03E06 1080i HDTV DD5.1 MPEG2-TrollHD.ts
|
||||||
|
: series: Game of Thrones
|
||||||
|
season: 3
|
||||||
|
episodeNumber: 6
|
||||||
|
screenSize: 1080i
|
||||||
|
format: HDTV
|
||||||
|
audioChannels: "5.1"
|
||||||
|
audioCodec: DolbyDigital
|
||||||
|
videoCodec: MPEG2
|
||||||
|
releaseGroup: TrollHD
|
||||||
|
|
||||||
|
? gossip.girl.s01e18.hdtv.xvid-2hd.eng.srt
|
||||||
|
: series: gossip girl
|
||||||
|
season: 1
|
||||||
|
episodeNumber: 18
|
||||||
|
format: HDTV
|
||||||
|
videoCodec: XviD
|
||||||
|
releaseGroup: 2HD
|
||||||
|
subtitleLanguage: english
|
||||||
|
|
||||||
|
? Wheels.S03E01E02.720p.HDTV.x264-IMMERSE.mkv
|
||||||
|
: series: Wheels
|
||||||
|
season: 3
|
||||||
|
episodeNumber: 1
|
||||||
|
episodeList: [1, 2]
|
||||||
|
screenSize: 720p
|
||||||
|
format: HDTV
|
||||||
|
videoCodec: h264
|
||||||
|
releaseGroup: IMMERSE
|
||||||
|
|
||||||
|
? Wheels.S03E01-02.720p.HDTV.x264-IMMERSE.mkv
|
||||||
|
: series: Wheels
|
||||||
|
season: 3
|
||||||
|
episodeNumber: 1
|
||||||
|
episodeList: [1, 2]
|
||||||
|
screenSize: 720p
|
||||||
|
format: HDTV
|
||||||
|
videoCodec: h264
|
||||||
|
releaseGroup: IMMERSE
|
||||||
|
|
||||||
|
? Wheels.S03E01-E02.720p.HDTV.x264-IMMERSE.mkv
|
||||||
|
: series: Wheels
|
||||||
|
season: 3
|
||||||
|
episodeNumber: 1
|
||||||
|
episodeList: [1, 2]
|
||||||
|
screenSize: 720p
|
||||||
|
format: HDTV
|
||||||
|
videoCodec: h264
|
||||||
|
releaseGroup: IMMERSE
|
||||||
|
|
||||||
|
? Wheels.S03E01-03.720p.HDTV.x264-IMMERSE.mkv
|
||||||
|
: series: Wheels
|
||||||
|
season: 3
|
||||||
|
episodeNumber: 1
|
||||||
|
episodeList: [1, 2, 3]
|
||||||
|
screenSize: 720p
|
||||||
|
format: HDTV
|
||||||
|
videoCodec: h264
|
||||||
|
releaseGroup: IMMERSE
|
||||||
|
|
||||||
|
? Marvels.Agents.of.S.H.I.E.L.D.S01E06.720p.HDTV.X264-DIMENSION.mkv
|
||||||
|
: series: Marvels Agents of S.H.I.E.L.D.
|
||||||
|
season: 1
|
||||||
|
episodeNumber: 6
|
||||||
|
screenSize: 720p
|
||||||
|
format: HDTV
|
||||||
|
videoCodec: h264
|
||||||
|
releaseGroup: DIMENSION
|
||||||
|
|
||||||
|
? Marvels.Agents.of.S.H.I.E.L.D..S01E06.720p.HDTV.X264-DIMENSION.mkv
|
||||||
|
: series: Marvels Agents of S.H.I.E.L.D.
|
||||||
|
season: 1
|
||||||
|
episodeNumber: 6
|
||||||
|
screenSize: 720p
|
||||||
|
format: HDTV
|
||||||
|
videoCodec: h264
|
||||||
|
releaseGroup: DIMENSION
|
||||||
|
|
||||||
|
? Series/Friday Night Lights/Season 1/Friday Night Lights S01E19 - Ch-Ch-Ch-Ch-Changes.avi
|
||||||
|
: series: Friday Night Lights
|
||||||
|
season: 1
|
||||||
|
episodeNumber: 19
|
||||||
|
title: Ch-Ch-Ch-Ch-Changes
|
||||||
|
|
||||||
|
? Dexter Saison VII FRENCH.BDRip.XviD-MiND.nfo
|
||||||
|
: series: Dexter
|
||||||
|
season: 7
|
||||||
|
videoCodec: XviD
|
||||||
|
language: French
|
||||||
|
format: BluRay
|
||||||
|
releaseGroup: MiND
|
||||||
|
|
||||||
|
? Dexter Saison sept FRENCH.BDRip.XviD-MiND.nfo
|
||||||
|
: series: Dexter
|
||||||
|
season: 7
|
||||||
|
videoCodec: XviD
|
||||||
|
language: French
|
||||||
|
format: BluRay
|
||||||
|
releaseGroup: MiND
|
||||||
|
|
||||||
|
? "Pokémon S16 - E29 - 1280*720 HDTV VF.mkv"
|
||||||
|
: series: Pokémon
|
||||||
|
format: HDTV
|
||||||
|
language: French
|
||||||
|
season: 16
|
||||||
|
episodeNumber: 29
|
||||||
|
screenSize: 720p
|
||||||
|
|
||||||
|
? One.Piece.E576.VOSTFR.720p.HDTV.x264-MARINE-FORD.mkv
|
||||||
|
: episodeNumber: 576
|
||||||
|
videoCodec: h264
|
||||||
|
format: HDTV
|
||||||
|
series: One Piece
|
||||||
|
releaseGroup: MARINE-FORD
|
||||||
|
subtitleLanguage: French
|
||||||
|
screenSize: 720p
|
||||||
|
|
||||||
|
? Dexter.S08E12.FINAL.MULTi.1080p.BluRay.x264-MiND.mkv
|
||||||
|
: videoCodec: h264
|
||||||
|
episodeNumber: 12
|
||||||
|
season: 8
|
||||||
|
format: BluRay
|
||||||
|
series: Dexter
|
||||||
|
other: final
|
||||||
|
language: Multiple languages
|
||||||
|
releaseGroup: MiND
|
||||||
|
screenSize: 1080p
|
||||||
|
|
||||||
|
? One Piece - E623 VOSTFR HD [www.manga-ddl-free.com].mkv
|
||||||
|
: website: www.manga-ddl-free.com
|
||||||
|
episodeNumber: 623
|
||||||
|
subtitleLanguage: French
|
||||||
|
series: One Piece
|
||||||
|
other: HD
|
||||||
|
|
||||||
|
? Falling Skies Saison 1.HDLight.720p.x264.VFF.mkv
|
||||||
|
: language: French
|
||||||
|
screenSize: 720p
|
||||||
|
season: 1
|
||||||
|
series: Falling Skies
|
||||||
|
videoCodec: h264
|
||||||
|
|
||||||
|
? Sleepy.Hollow.S01E09.720p.WEB-DL.DD5.1.H.264-BP.mkv
|
||||||
|
: episodeNumber: 9
|
||||||
|
videoCodec: h264
|
||||||
|
format: WEB-DL
|
||||||
|
series: Sleepy Hollow
|
||||||
|
audioChannels: "5.1"
|
||||||
|
screenSize: 720p
|
||||||
|
season: 1
|
||||||
|
videoProfile: BP
|
||||||
|
audioCodec: DolbyDigital
|
||||||
|
|
||||||
|
? Sleepy.Hollow.S01E09.720p.WEB-DL.DD5.1.H.264-BS.mkv
|
||||||
|
: episodeNumber: 9
|
||||||
|
videoCodec: h264
|
||||||
|
format: WEB-DL
|
||||||
|
series: Sleepy Hollow
|
||||||
|
audioChannels: "5.1"
|
||||||
|
screenSize: 720p
|
||||||
|
season: 1
|
||||||
|
releaseGroup: BS
|
||||||
|
audioCodec: DolbyDigital
|
||||||
|
|
||||||
|
? Battlestar.Galactica.S00.Pilot.FRENCH.DVDRip.XviD-NOTAG.avi
|
||||||
|
: series: Battlestar Galactica
|
||||||
|
season: 0
|
||||||
|
title: Pilot
|
||||||
|
special: Pilot
|
||||||
|
language: French
|
||||||
|
format: DVD
|
||||||
|
videoCodec: XviD
|
||||||
|
releaseGroup: NOTAG
|
||||||
|
|
||||||
|
? The Big Bang Theory S00E00 Unaired Pilot VOSTFR TVRip XviD-VioCs
|
||||||
|
: options: -n
|
||||||
|
series: The Big Bang Theory
|
||||||
|
season: 0
|
||||||
|
episodeNumber: 0
|
||||||
|
subtitleLanguage: French
|
||||||
|
format: TV
|
||||||
|
videoCodec: XviD
|
||||||
|
releaseGroup: VioCs
|
||||||
|
special: [Unaired, Pilot]
|
||||||
|
title: Unaired Pilot
|
||||||
|
|
||||||
|
? The Big Bang Theory S01E00 PROPER Unaired Pilot TVRip XviD-GIGGITY
|
||||||
|
: options: -n
|
||||||
|
series: The Big Bang Theory
|
||||||
|
season: 1
|
||||||
|
episodeNumber: 0
|
||||||
|
format: TV
|
||||||
|
videoCodec: XviD
|
||||||
|
releaseGroup: GIGGITY
|
||||||
|
other: proper
|
||||||
|
special: [Unaired, Pilot]
|
||||||
|
title: Unaired Pilot
|
168
lib/guessit/test/guessittest.py
Normal file
168
lib/guessit/test/guessittest.py
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# GuessIt - A library for guessing information from filenames
|
||||||
|
# Copyright (c) 2013 Nicolas Wack <wackou@gmail.com>
|
||||||
|
#
|
||||||
|
# GuessIt is free software; you can redistribute it and/or modify it under
|
||||||
|
# the terms of the Lesser GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# GuessIt is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# Lesser GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the Lesser GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
|
from guessit import base_text_type, u
|
||||||
|
|
||||||
|
from unittest import TestCase, TestLoader, TextTestRunner
|
||||||
|
import shlex
|
||||||
|
|
||||||
|
import yaml, logging, sys, os
|
||||||
|
from os.path import *
|
||||||
|
|
||||||
|
|
||||||
|
def currentPath():
|
||||||
|
'''Returns the path in which the calling file is located.'''
|
||||||
|
return dirname(join(os.getcwd(), sys._getframe(1).f_globals['__file__']))
|
||||||
|
|
||||||
|
|
||||||
|
def addImportPath(path):
|
||||||
|
'''Function that adds the specified path to the import path. The path can be
|
||||||
|
absolute or relative to the calling file.'''
|
||||||
|
importPath = abspath(join(currentPath(), path))
|
||||||
|
sys.path = [importPath] + sys.path
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
from guessit.plugins import transformers
|
||||||
|
import guessit
|
||||||
|
from guessit.options import option_parser
|
||||||
|
from guessit import *
|
||||||
|
from guessit.matcher import *
|
||||||
|
from guessit.fileutils import *
|
||||||
|
|
||||||
|
|
||||||
|
def allTests(testClass):
|
||||||
|
return TestLoader().loadTestsFromTestCase(testClass)
|
||||||
|
|
||||||
|
|
||||||
|
class TestGuessit(TestCase):
|
||||||
|
|
||||||
|
def checkMinimumFieldsCorrect(self, filename, filetype=None, remove_type=True,
|
||||||
|
exclude_files=None):
|
||||||
|
groundTruth = yaml.load(load_file_in_same_dir(__file__, filename))
|
||||||
|
|
||||||
|
def guess_func(string, options=None):
|
||||||
|
return guess_file_info(string, options=options, type=filetype)
|
||||||
|
|
||||||
|
return self.checkFields(groundTruth, guess_func, remove_type, exclude_files)
|
||||||
|
|
||||||
|
def checkFields(self, groundTruth, guess_func, remove_type=True,
|
||||||
|
exclude_files=None):
|
||||||
|
total = 0
|
||||||
|
exclude_files = exclude_files or []
|
||||||
|
|
||||||
|
fails = {}
|
||||||
|
additionals = {}
|
||||||
|
|
||||||
|
for filename, required_fields in groundTruth.items():
|
||||||
|
filename = u(filename)
|
||||||
|
if filename in exclude_files:
|
||||||
|
continue
|
||||||
|
|
||||||
|
log.debug('\n' + '-' * 120)
|
||||||
|
log.info('Guessing information for file: %s' % filename)
|
||||||
|
|
||||||
|
options = required_fields.pop('options') if 'options' in required_fields else None
|
||||||
|
|
||||||
|
if options:
|
||||||
|
args = shlex.split(options)
|
||||||
|
options, _ = option_parser.parse_args(args)
|
||||||
|
options = vars(options)
|
||||||
|
found = guess_func(filename, options)
|
||||||
|
|
||||||
|
total = total + 1
|
||||||
|
|
||||||
|
# no need for these in the unittests
|
||||||
|
if remove_type:
|
||||||
|
try:
|
||||||
|
del found['type']
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
for prop in ('container', 'mimetype'):
|
||||||
|
if prop in found:
|
||||||
|
del found[prop]
|
||||||
|
|
||||||
|
# props which are list of just 1 elem should be opened for easier writing of the tests
|
||||||
|
for prop in ('language', 'subtitleLanguage', 'other', 'special'):
|
||||||
|
value = found.get(prop, None)
|
||||||
|
if isinstance(value, list) and len(value) == 1:
|
||||||
|
found[prop] = value[0]
|
||||||
|
|
||||||
|
# look for missing properties
|
||||||
|
for prop, value in required_fields.items():
|
||||||
|
if prop not in found:
|
||||||
|
log.debug("Prop '%s' not found in: %s" % (prop, filename))
|
||||||
|
if not filename in fails:
|
||||||
|
fails[filename] = []
|
||||||
|
fails[filename].append("'%s' not found in: %s" % (prop, filename))
|
||||||
|
continue
|
||||||
|
|
||||||
|
# if both properties are strings, do a case-insensitive comparison
|
||||||
|
if (isinstance(value, base_text_type) and
|
||||||
|
isinstance(found[prop], base_text_type)):
|
||||||
|
if value.lower() != found[prop].lower():
|
||||||
|
log.debug("Wrong prop value [str] for '%s': expected = '%s' - received = '%s'" % (prop, u(value), u(found[prop])))
|
||||||
|
if not filename in fails:
|
||||||
|
fails[filename] = []
|
||||||
|
fails[filename].append("'%s': expected = '%s' - received = '%s'" % (prop, u(value), u(found[prop])))
|
||||||
|
|
||||||
|
# if both are lists, we assume list of strings and do a case-insensitive
|
||||||
|
# comparison on their elements
|
||||||
|
elif isinstance(value, list) and isinstance(found[prop], list):
|
||||||
|
s1 = set(u(s).lower() for s in value)
|
||||||
|
s2 = set(u(s).lower() for s in found[prop])
|
||||||
|
if s1 != s2:
|
||||||
|
log.debug("Wrong prop value [list] for '%s': expected = '%s' - received = '%s'" % (prop, u(value), u(found[prop])))
|
||||||
|
if not filename in fails:
|
||||||
|
fails[filename] = []
|
||||||
|
fails[filename].append("'%s': expected = '%s' - received = '%s'" % (prop, u(value), u(found[prop])))
|
||||||
|
# otherwise, just compare their values directly
|
||||||
|
else:
|
||||||
|
if found[prop] != value:
|
||||||
|
log.debug("Wrong prop value for '%s': expected = '%s' [%s] - received = '%s' [%s]" % (prop, u(value), type(value), u(found[prop]), type(found[prop])))
|
||||||
|
if not filename in fails:
|
||||||
|
fails[filename] = []
|
||||||
|
fails[filename].append("'%s': expected = '%s' [%s] - received = '%s' [%s]" % (prop, u(value), type(value), u(found[prop]), type(found[prop])))
|
||||||
|
|
||||||
|
# look for additional properties
|
||||||
|
for prop, value in found.items():
|
||||||
|
if prop not in required_fields:
|
||||||
|
log.debug("Found additional info for prop = '%s': '%s'" % (prop, u(value)))
|
||||||
|
if not filename in additionals:
|
||||||
|
additionals[filename] = []
|
||||||
|
additionals[filename].append("'%s': '%s'" % (prop, u(value)))
|
||||||
|
|
||||||
|
correct = total - len(fails)
|
||||||
|
log.info('SUMMARY: Guessed correctly %d out of %d filenames' % (correct, total))
|
||||||
|
|
||||||
|
for failed_entry, failed_properties in fails.items():
|
||||||
|
log.error('---- ' + failed_entry + ' ----')
|
||||||
|
for failed_property in failed_properties:
|
||||||
|
log.error("FAILED: " + failed_property)
|
||||||
|
|
||||||
|
for additional_entry, additional_properties in additionals.items():
|
||||||
|
log.warn('---- ' + additional_entry + ' ----')
|
||||||
|
for additional_property in additional_properties:
|
||||||
|
log.warn("ADDITIONAL: " + additional_property)
|
||||||
|
|
||||||
|
self.assertTrue(correct == total,
|
||||||
|
msg='Correct: %d < Total: %d' % (correct, total))
|
626
lib/guessit/test/movies.yaml
Normal file
626
lib/guessit/test/movies.yaml
Normal file
|
@ -0,0 +1,626 @@
|
||||||
|
|
||||||
|
? 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
|
||||||
|
screenSize: 720p
|
||||||
|
format: HD-DVD
|
||||||
|
audioCodec: DTS
|
||||||
|
videoCodec: h264
|
||||||
|
releaseGroup: ESiR
|
||||||
|
|
||||||
|
? Movies/El Dia de la Bestia (1995)/El.dia.de.la.bestia.DVDrip.Spanish.DivX.by.Artik[SEDG].avi
|
||||||
|
: title: El Dia de la Bestia
|
||||||
|
year: 1995
|
||||||
|
format: DVD
|
||||||
|
language: spanish
|
||||||
|
videoCodec: DivX
|
||||||
|
|
||||||
|
? Movies/Dark City (1998)/Dark.City.(1998).DC.BDRip.720p.DTS.X264-CHD.mkv
|
||||||
|
: title: Dark City
|
||||||
|
year: 1998
|
||||||
|
format: BluRay
|
||||||
|
screenSize: 720p
|
||||||
|
audioCodec: DTS
|
||||||
|
videoCodec: h264
|
||||||
|
releaseGroup: CHD
|
||||||
|
|
||||||
|
? Movies/Sin City (BluRay) (2005)/Sin.City.2005.BDRip.720p.x264.AC3-SEPTiC.mkv
|
||||||
|
: title: Sin City
|
||||||
|
year: 2005
|
||||||
|
format: BluRay
|
||||||
|
screenSize: 720p
|
||||||
|
videoCodec: h264
|
||||||
|
audioCodec: AC3
|
||||||
|
releaseGroup: SEPTiC
|
||||||
|
|
||||||
|
|
||||||
|
? Movies/Borat (2006)/Borat.(2006).R5.PROPER.REPACK.DVDRip.XviD-PUKKA.avi
|
||||||
|
: title: Borat
|
||||||
|
year: 2006
|
||||||
|
other: PROPER
|
||||||
|
format: DVD
|
||||||
|
other: [ R5, Proper ]
|
||||||
|
videoCodec: XviD
|
||||||
|
releaseGroup: PUKKA
|
||||||
|
|
||||||
|
|
||||||
|
? "[XCT].Le.Prestige.(The.Prestige).DVDRip.[x264.HP.He-Aac.{Fr-Eng}.St{Fr-Eng}.Chaps].mkv"
|
||||||
|
: title: Le Prestige
|
||||||
|
format: DVD
|
||||||
|
videoCodec: h264
|
||||||
|
videoProfile: HP
|
||||||
|
audioCodec: AAC
|
||||||
|
audioProfile: HE
|
||||||
|
language: [ french, english ]
|
||||||
|
subtitleLanguage: [ french, english ]
|
||||||
|
|
||||||
|
? Battle Royale (2000)/Battle.Royale.(Batoru.Rowaiaru).(2000).(Special.Edition).CD1of2.DVDRiP.XviD-[ZeaL].avi
|
||||||
|
: title: Battle Royale
|
||||||
|
year: 2000
|
||||||
|
edition: special edition
|
||||||
|
cdNumber: 1
|
||||||
|
cdNumberTotal: 2
|
||||||
|
format: DVD
|
||||||
|
videoCodec: XviD
|
||||||
|
releaseGroup: ZeaL
|
||||||
|
|
||||||
|
? Movies/Brazil (1985)/Brazil_Criterion_Edition_(1985).CD2.avi
|
||||||
|
: title: Brazil
|
||||||
|
edition: Criterion Edition
|
||||||
|
year: 1985
|
||||||
|
cdNumber: 2
|
||||||
|
|
||||||
|
? Movies/Persepolis (2007)/[XCT] Persepolis [H264+Aac-128(Fr-Eng)+ST(Fr-Eng)+Ind].mkv
|
||||||
|
: title: Persepolis
|
||||||
|
year: 2007
|
||||||
|
videoCodec: h264
|
||||||
|
audioCodec: AAC
|
||||||
|
language: [ French, English ]
|
||||||
|
subtitleLanguage: [ French, English ]
|
||||||
|
|
||||||
|
? Movies/Toy Story (1995)/Toy Story [HDTV 720p English-Spanish].mkv
|
||||||
|
: title: Toy Story
|
||||||
|
year: 1995
|
||||||
|
format: HDTV
|
||||||
|
screenSize: 720p
|
||||||
|
language: [ english, spanish ]
|
||||||
|
|
||||||
|
? Movies/Office Space (1999)/Office.Space.[Dual-DVDRip].[Spanish-English].[XviD-AC3-AC3].[by.Oswald].avi
|
||||||
|
: title: Office Space
|
||||||
|
year: 1999
|
||||||
|
format: DVD
|
||||||
|
language: [ english, spanish ]
|
||||||
|
videoCodec: XviD
|
||||||
|
audioCodec: AC3
|
||||||
|
|
||||||
|
? Movies/Wild Zero (2000)/Wild.Zero.DVDivX-EPiC.avi
|
||||||
|
: title: Wild Zero
|
||||||
|
year: 2000
|
||||||
|
videoCodec: DivX
|
||||||
|
releaseGroup: EPiC
|
||||||
|
|
||||||
|
? movies/Baraka_Edition_Collector.avi
|
||||||
|
: title: Baraka
|
||||||
|
edition: collector edition
|
||||||
|
|
||||||
|
? Movies/Blade Runner (1982)/Blade.Runner.(1982).(Director's.Cut).CD1.DVDRip.XviD.AC3-WAF.avi
|
||||||
|
: title: Blade Runner
|
||||||
|
year: 1982
|
||||||
|
edition: Director's Cut
|
||||||
|
cdNumber: 1
|
||||||
|
format: DVD
|
||||||
|
videoCodec: XviD
|
||||||
|
audioCodec: AC3
|
||||||
|
releaseGroup: WAF
|
||||||
|
|
||||||
|
? movies/American.The.Bill.Hicks.Story.2009.DVDRip.XviD-EPiSODE.[UsaBit.com]/UsaBit.com_esd-americanbh.avi
|
||||||
|
: title: American The Bill Hicks Story
|
||||||
|
year: 2009
|
||||||
|
format: DVD
|
||||||
|
videoCodec: XviD
|
||||||
|
releaseGroup: EPiSODE
|
||||||
|
website: UsaBit.com
|
||||||
|
|
||||||
|
? movies/Charlie.And.Boots.DVDRip.XviD-TheWretched/wthd-cab.avi
|
||||||
|
: title: Charlie And Boots
|
||||||
|
format: DVD
|
||||||
|
videoCodec: XviD
|
||||||
|
releaseGroup: TheWretched
|
||||||
|
|
||||||
|
? movies/Steig Larsson Millenium Trilogy (2009) BRrip 720 AAC x264/(1)The Girl With The Dragon Tattoo (2009) BRrip 720 AAC x264.mkv
|
||||||
|
: title: The Girl With The Dragon Tattoo
|
||||||
|
filmSeries: Steig Larsson Millenium Trilogy
|
||||||
|
filmNumber: 1
|
||||||
|
year: 2009
|
||||||
|
format: BluRay
|
||||||
|
audioCodec: AAC
|
||||||
|
videoCodec: h264
|
||||||
|
screenSize: 720p
|
||||||
|
|
||||||
|
? movies/Greenberg.REPACK.LiMiTED.DVDRip.XviD-ARROW/arw-repack-greenberg.dvdrip.xvid.avi
|
||||||
|
: title: Greenberg
|
||||||
|
format: DVD
|
||||||
|
videoCodec: XviD
|
||||||
|
releaseGroup: ARROW
|
||||||
|
other: ['Proper', 'Limited']
|
||||||
|
|
||||||
|
? Movies/Fr - Paris 2054, Renaissance (2005) - De Christian Volckman - (Film Divx Science Fiction Fantastique Thriller Policier N&B).avi
|
||||||
|
: title: Paris 2054, Renaissance
|
||||||
|
year: 2005
|
||||||
|
language: french
|
||||||
|
videoCodec: DivX
|
||||||
|
|
||||||
|
? Movies/[阿维达].Avida.2006.FRENCH.DVDRiP.XViD-PROD.avi
|
||||||
|
: title: Avida
|
||||||
|
year: 2006
|
||||||
|
language: french
|
||||||
|
format: DVD
|
||||||
|
videoCodec: XviD
|
||||||
|
releaseGroup: PROD
|
||||||
|
|
||||||
|
? Movies/Alice in Wonderland DVDRip.XviD-DiAMOND/dmd-aw.avi
|
||||||
|
: title: Alice in Wonderland
|
||||||
|
format: DVD
|
||||||
|
videoCodec: XviD
|
||||||
|
releaseGroup: DiAMOND
|
||||||
|
|
||||||
|
? Movies/Ne.Le.Dis.A.Personne.Fr 2 cd/personnea_mp.avi
|
||||||
|
: title: Ne Le Dis A Personne
|
||||||
|
language: french
|
||||||
|
cdNumberTotal: 2
|
||||||
|
|
||||||
|
? Movies/Bunker Palace Hôtel (Enki Bilal) (1989)/Enki Bilal - Bunker Palace Hotel (Fr Vhs Rip).avi
|
||||||
|
: title: Bunker Palace Hôtel
|
||||||
|
year: 1989
|
||||||
|
language: french
|
||||||
|
format: VHS
|
||||||
|
|
||||||
|
? Movies/21 (2008)/21.(2008).DVDRip.x264.AC3-FtS.[sharethefiles.com].mkv
|
||||||
|
: title: "21"
|
||||||
|
year: 2008
|
||||||
|
format: DVD
|
||||||
|
videoCodec: h264
|
||||||
|
audioCodec: AC3
|
||||||
|
releaseGroup: FtS
|
||||||
|
website: sharethefiles.com
|
||||||
|
|
||||||
|
? Movies/9 (2009)/9.2009.Blu-ray.DTS.720p.x264.HDBRiSe.[sharethefiles.com].mkv
|
||||||
|
: title: "9"
|
||||||
|
year: 2009
|
||||||
|
format: BluRay
|
||||||
|
audioCodec: DTS
|
||||||
|
screenSize: 720p
|
||||||
|
videoCodec: h264
|
||||||
|
releaseGroup: HDBRiSe
|
||||||
|
website: sharethefiles.com
|
||||||
|
|
||||||
|
? Movies/Mamma.Mia.2008.DVDRip.AC3.XviD-CrazyTeam/Mamma.Mia.2008.DVDRip.AC3.XviD-CrazyTeam.avi
|
||||||
|
: title: Mamma Mia
|
||||||
|
year: 2008
|
||||||
|
format: DVD
|
||||||
|
audioCodec: AC3
|
||||||
|
videoCodec: XviD
|
||||||
|
releaseGroup: CrazyTeam
|
||||||
|
|
||||||
|
? Movies/M.A.S.H. (1970)/MASH.(1970).[Divx.5.02][Dual-Subtitulos][DVDRip].ogm
|
||||||
|
: title: M.A.S.H.
|
||||||
|
year: 1970
|
||||||
|
videoCodec: DivX
|
||||||
|
format: DVD
|
||||||
|
|
||||||
|
? Movies/The Doors (1991)/09.03.08.The.Doors.(1991).BDRip.720p.AC3.X264-HiS@SiLUHD-English.[sharethefiles.com].mkv
|
||||||
|
: 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/Ratatouille/video_ts-ratatouille.srt
|
||||||
|
: title: Ratatouille
|
||||||
|
format: DVD
|
||||||
|
|
||||||
|
? Movies/001 __ A classer/Fantomas se déchaine - Louis de Funès.avi
|
||||||
|
: title: Fantomas se déchaine
|
||||||
|
|
||||||
|
? Movies/Comme une Image (2004)/Comme.Une.Image.FRENCH.DVDRiP.XViD-NTK.par-www.divx-overnet.com.avi
|
||||||
|
: title: Comme une Image
|
||||||
|
year: 2004
|
||||||
|
language: french
|
||||||
|
format: DVD
|
||||||
|
videoCodec: XviD
|
||||||
|
releaseGroup: NTK
|
||||||
|
website: www.divx-overnet.com
|
||||||
|
|
||||||
|
? Movies/Fantastic Mr Fox/Fantastic.Mr.Fox.2009.DVDRip.{x264+LC-AAC.5.1}{Fr-Eng}{Sub.Fr-Eng}-™.[sharethefiles.com].mkv
|
||||||
|
: title: Fantastic Mr Fox
|
||||||
|
year: 2009
|
||||||
|
format: DVD
|
||||||
|
videoCodec: h264
|
||||||
|
audioCodec: AAC
|
||||||
|
audioProfile: LC
|
||||||
|
audioChannels: "5.1"
|
||||||
|
language: [ french, english ]
|
||||||
|
subtitleLanguage: [ french, english ]
|
||||||
|
website: sharethefiles.com
|
||||||
|
|
||||||
|
? Movies/Somewhere.2010.DVDRip.XviD-iLG/i-smwhr.avi
|
||||||
|
: title: Somewhere
|
||||||
|
year: 2010
|
||||||
|
format: DVD
|
||||||
|
videoCodec: XviD
|
||||||
|
releaseGroup: iLG
|
||||||
|
|
||||||
|
? Movies/Moon_(2009).mkv
|
||||||
|
: title: Moon
|
||||||
|
year: 2009
|
||||||
|
|
||||||
|
? Movies/Moon_(2009)-x01.mkv
|
||||||
|
: title: Moon
|
||||||
|
year: 2009
|
||||||
|
bonusNumber: 1
|
||||||
|
|
||||||
|
? Movies/Moon_(2009)-x02-Making_Of.mkv
|
||||||
|
: title: Moon
|
||||||
|
year: 2009
|
||||||
|
bonusNumber: 2
|
||||||
|
bonusTitle: Making Of
|
||||||
|
|
||||||
|
? movies/James_Bond-f17-Goldeneye.mkv
|
||||||
|
: title: Goldeneye
|
||||||
|
filmSeries: James Bond
|
||||||
|
filmNumber: 17
|
||||||
|
|
||||||
|
? /movies/James_Bond-f21-Casino_Royale.mkv
|
||||||
|
: title: Casino Royale
|
||||||
|
filmSeries: James Bond
|
||||||
|
filmNumber: 21
|
||||||
|
|
||||||
|
? /movies/James_Bond-f21-Casino_Royale-x01-Becoming_Bond.mkv
|
||||||
|
: title: Casino Royale
|
||||||
|
filmSeries: James Bond
|
||||||
|
filmNumber: 21
|
||||||
|
bonusNumber: 1
|
||||||
|
bonusTitle: Becoming Bond
|
||||||
|
|
||||||
|
? /movies/James_Bond-f21-Casino_Royale-x02-Stunts.mkv
|
||||||
|
: title: Casino Royale
|
||||||
|
filmSeries: James Bond
|
||||||
|
filmNumber: 21
|
||||||
|
bonusNumber: 2
|
||||||
|
bonusTitle: Stunts
|
||||||
|
|
||||||
|
? OSS_117--Cairo,_Nest_of_Spies.mkv
|
||||||
|
: title: OSS 117--Cairo, Nest of Spies
|
||||||
|
|
||||||
|
? The Godfather Part III.mkv
|
||||||
|
: title: The Godfather Part III
|
||||||
|
|
||||||
|
? Foobar Part VI.mkv
|
||||||
|
: title: Foobar Part VI
|
||||||
|
|
||||||
|
? The_Insider-(1999)-x02-60_Minutes_Interview-1996.mp4
|
||||||
|
: title: The Insider
|
||||||
|
year: 1999
|
||||||
|
bonusNumber: 2
|
||||||
|
bonusTitle: 60 Minutes Interview-1996
|
||||||
|
|
||||||
|
? Rush.._Beyond_The_Lighted_Stage-x09-Between_Sun_and_Moon-2002_Hartford.mkv
|
||||||
|
: title: Rush Beyond The Lighted Stage
|
||||||
|
bonusNumber: 9
|
||||||
|
bonusTitle: Between Sun and Moon-2002 Hartford
|
||||||
|
|
||||||
|
? /public/uTorrent/Downloads Finished/Movies/Indiana.Jones.and.the.Temple.of.Doom.1984.HDTV.720p.x264.AC3.5.1-REDµX/Indiana.Jones.and.the.Temple.of.Doom.1984.HDTV.720p.x264.AC3.5.1-REDµX.mkv
|
||||||
|
: title: Indiana Jones and the Temple of Doom
|
||||||
|
year: 1984
|
||||||
|
format: HDTV
|
||||||
|
screenSize: 720p
|
||||||
|
videoCodec: h264
|
||||||
|
audioCodec: AC3
|
||||||
|
audioChannels: "5.1"
|
||||||
|
releaseGroup: REDµX
|
||||||
|
|
||||||
|
? The.Director’s.Notebook.2006.Blu-Ray.x264.DXVA.720p.AC3-de[42].mkv
|
||||||
|
: title: The Director’s Notebook
|
||||||
|
year: 2006
|
||||||
|
format: BluRay
|
||||||
|
videoCodec: h264
|
||||||
|
videoApi: DXVA
|
||||||
|
screenSize: 720p
|
||||||
|
audioCodec: AC3
|
||||||
|
releaseGroup: de[42]
|
||||||
|
|
||||||
|
? Movies/Cosmopolis.2012.LiMiTED.720p.BluRay.x264-AN0NYM0US[bb]/ano-cosmo.720p.mkv
|
||||||
|
: title: Cosmopolis
|
||||||
|
year: 2012
|
||||||
|
screenSize: 720p
|
||||||
|
videoCodec: h264
|
||||||
|
releaseGroup: AN0NYM0US[bb]
|
||||||
|
format: BluRay
|
||||||
|
other: LIMITED
|
||||||
|
|
||||||
|
? movies/La Science des Rêves (2006)/La.Science.Des.Reves.FRENCH.DVDRip.XviD-MP-AceBot.avi
|
||||||
|
: title: La Science des Rêves
|
||||||
|
year: 2006
|
||||||
|
format: DVD
|
||||||
|
videoCodec: XviD
|
||||||
|
videoProfile: MP
|
||||||
|
releaseGroup: AceBot
|
||||||
|
language: French
|
||||||
|
|
||||||
|
? The_Italian_Job.mkv
|
||||||
|
: title: The Italian Job
|
||||||
|
|
||||||
|
? The.Rum.Diary.2011.1080p.BluRay.DTS.x264.D-Z0N3.mkv
|
||||||
|
: title: The Rum Diary
|
||||||
|
year: 2011
|
||||||
|
screenSize: 1080p
|
||||||
|
format: BluRay
|
||||||
|
videoCodec: h264
|
||||||
|
audioCodec: DTS
|
||||||
|
releaseGroup: D-Z0N3
|
||||||
|
|
||||||
|
? Life.Of.Pi.2012.1080p.BluRay.DTS.x264.D-Z0N3.mkv
|
||||||
|
: title: Life Of Pi
|
||||||
|
year: 2012
|
||||||
|
screenSize: 1080p
|
||||||
|
format: BluRay
|
||||||
|
videoCodec: h264
|
||||||
|
audioCodec: DTS
|
||||||
|
releaseGroup: D-Z0N3
|
||||||
|
|
||||||
|
? The.Kings.Speech.2010.1080p.BluRay.DTS.x264.D Z0N3.mkv
|
||||||
|
: title: The Kings Speech
|
||||||
|
year: 2010
|
||||||
|
screenSize: 1080p
|
||||||
|
format: BluRay
|
||||||
|
audioCodec: DTS
|
||||||
|
videoCodec: h264
|
||||||
|
releaseGroup: D-Z0N3
|
||||||
|
|
||||||
|
? Street.Kings.2008.BluRay.1080p.DTS.x264.dxva EuReKA.mkv
|
||||||
|
: title: Street Kings
|
||||||
|
year: 2008
|
||||||
|
format: BluRay
|
||||||
|
screenSize: 1080p
|
||||||
|
audioCodec: DTS
|
||||||
|
videoCodec: h264
|
||||||
|
videoApi: DXVA
|
||||||
|
releaseGroup: EuReKa
|
||||||
|
|
||||||
|
? 2001.A.Space.Odyssey.1968.HDDVD.1080p.DTS.x264.dxva EuReKA.mkv
|
||||||
|
: title: 2001 A Space Odyssey
|
||||||
|
year: 1968
|
||||||
|
format: HD-DVD
|
||||||
|
screenSize: 1080p
|
||||||
|
audioCodec: DTS
|
||||||
|
videoCodec: h264
|
||||||
|
videoApi: DXVA
|
||||||
|
releaseGroup: EuReKa
|
||||||
|
|
||||||
|
? 2012.2009.720p.BluRay.x264.DTS WiKi.mkv
|
||||||
|
: title: "2012"
|
||||||
|
year: 2009
|
||||||
|
screenSize: 720p
|
||||||
|
format: BluRay
|
||||||
|
videoCodec: h264
|
||||||
|
audioCodec: DTS
|
||||||
|
releaseGroup: WiKi
|
||||||
|
|
||||||
|
? /share/Download/movie/Dead Man Down (2013) BRRiP XViD DD5_1 Custom NLSubs =-_lt Q_o_Q gt-=_/XD607ebb-BRc59935-5155473f-1c5f49/XD607ebb-BRc59935-5155473f-1c5f49.avi
|
||||||
|
: title: Dead Man Down
|
||||||
|
year: 2013
|
||||||
|
format: BluRay
|
||||||
|
videoCodec: XviD
|
||||||
|
audioChannels: "5.1"
|
||||||
|
audioCodec: DolbyDigital
|
||||||
|
idNumber: XD607ebb-BRc59935-5155473f-1c5f49
|
||||||
|
|
||||||
|
? Pacific.Rim.3D.2013.COMPLETE.BLURAY-PCH.avi
|
||||||
|
: title: Pacific Rim
|
||||||
|
year: 2013
|
||||||
|
format: BluRay
|
||||||
|
other:
|
||||||
|
- complete
|
||||||
|
- 3D
|
||||||
|
releaseGroup: PCH
|
||||||
|
|
||||||
|
? Immersion.French.2011.STV.READNFO.QC.FRENCH.ENGLISH.NTSC.DVDR.nfo
|
||||||
|
: title: Immersion French
|
||||||
|
year: 2011
|
||||||
|
language:
|
||||||
|
- French
|
||||||
|
- English
|
||||||
|
|
||||||
|
? Immersion.French.2011.STV.READNFO.QC.FRENCH.NTSC.DVDR.nfo
|
||||||
|
: title: Immersion French
|
||||||
|
year: 2011
|
||||||
|
language: French
|
||||||
|
|
||||||
|
? Immersion.French.2011.STV.READNFO.QC.NTSC.DVDR.nfo
|
||||||
|
: title: Immersion French
|
||||||
|
year: 2011
|
||||||
|
|
||||||
|
? French.Immersion.2011.STV.READNFO.QC.ENGLISH.NTSC.DVDR.nfo
|
||||||
|
: title: French Immersion
|
||||||
|
year: 2011
|
||||||
|
language: ENGLISH
|
||||||
|
|
||||||
|
? Howl's_Moving_Castle_(2004)_[720p,HDTV,x264,DTS]-FlexGet.avi
|
||||||
|
: videoCodec: h264
|
||||||
|
format: HDTV
|
||||||
|
title: Howl's Moving Castle
|
||||||
|
screenSize: 720p
|
||||||
|
year: 2004
|
||||||
|
audioCodec: DTS
|
||||||
|
releaseGroup: FlexGet
|
||||||
|
|
||||||
|
? Pirates de langkasuka.2008.FRENCH.1920X1080.h264.AVC.AsiaRa.mkv
|
||||||
|
: screenSize: 1080p
|
||||||
|
year: 2008
|
||||||
|
language: French
|
||||||
|
videoCodec: h264
|
||||||
|
title: Pirates de langkasuka
|
||||||
|
releaseGroup: AsiaRa
|
||||||
|
|
||||||
|
? Masala (2013) Telugu Movie HD DVDScr XviD - Exclusive.avi
|
||||||
|
: year: 2013
|
||||||
|
videoCodec: XviD
|
||||||
|
title: Masala
|
||||||
|
format: HD-DVD
|
||||||
|
other: screener
|
||||||
|
language: Telugu
|
||||||
|
releaseGroup: Exclusive
|
||||||
|
|
||||||
|
? Django Unchained 2012 DVDSCR X264 AAC-P2P.nfo
|
||||||
|
: year: 2012
|
||||||
|
other: screener
|
||||||
|
videoCodec: h264
|
||||||
|
title: Django Unchained
|
||||||
|
audioCodec: AAC
|
||||||
|
format: DVD
|
||||||
|
releaseGroup: P2P
|
||||||
|
|
||||||
|
? Ejecutiva.En.Apuros(2009).BLURAY.SCR.Xvid.Spanish.LanzamientosD.nfo
|
||||||
|
: year: 2009
|
||||||
|
other: screener
|
||||||
|
format: BluRay
|
||||||
|
videoCodec: XviD
|
||||||
|
language: Spanish
|
||||||
|
title: Ejecutiva En Apuros
|
||||||
|
|
||||||
|
? Die.Schluempfe.2.German.DL.1080p.BluRay.x264-EXQUiSiTE.mkv
|
||||||
|
: title: Die Schluempfe 2
|
||||||
|
format: BluRay
|
||||||
|
language:
|
||||||
|
- Multiple languages
|
||||||
|
- German
|
||||||
|
videoCodec: h264
|
||||||
|
releaseGroup: EXQUiSiTE
|
||||||
|
screenSize: 1080p
|
||||||
|
|
||||||
|
? Rocky 1976 French SubForced BRRip x264 AC3-FUNKY.mkv
|
||||||
|
: title: Rocky
|
||||||
|
year: 1976
|
||||||
|
subtitleLanguage: French
|
||||||
|
format: BluRay
|
||||||
|
videoCodec: h264
|
||||||
|
audioCodec: AC3
|
||||||
|
releaseGroup: FUNKY
|
||||||
|
|
||||||
|
? REDLINE (BD 1080p H264 10bit FLAC) [3xR].mkv
|
||||||
|
: title: REDLINE
|
||||||
|
format: BluRay
|
||||||
|
videoCodec: h264
|
||||||
|
videoProfile: 10bit
|
||||||
|
audioCodec: Flac
|
||||||
|
screenSize: 1080p
|
||||||
|
|
||||||
|
? The.Lizzie.McGuire.Movie.(2003).HR.DVDRiP.avi
|
||||||
|
: title: The Lizzie McGuire Movie
|
||||||
|
year: 2003
|
||||||
|
screenSize: 480p
|
||||||
|
format: DVD
|
||||||
|
|
||||||
|
? Hua.Mulan.BRRIP.MP4.x264.720p-HR.avi
|
||||||
|
: title: Hua Mulan
|
||||||
|
videoCodec: h264
|
||||||
|
format: BluRay
|
||||||
|
screenSize: 720p
|
||||||
|
|
||||||
|
? Dr.Seuss.The.Lorax.2012.DVDRip.LiNE.XviD.AC3.HQ.Hive-CM8.mp4
|
||||||
|
: videoCodec: XviD
|
||||||
|
title: Dr Seuss The Lorax
|
||||||
|
format: DVD
|
||||||
|
other: LiNE
|
||||||
|
year: 2012
|
||||||
|
audioCodec: AC3
|
||||||
|
audioProfile: HQ
|
||||||
|
releaseGroup: Hive-CM8
|
||||||
|
|
||||||
|
|
||||||
|
? "Star Wars: Episode IV - A New Hope (2004) Special Edition.MKV"
|
||||||
|
: title: Star Wars Episode IV
|
||||||
|
year: 2004
|
||||||
|
edition: Special Edition
|
||||||
|
|
||||||
|
? Dr.LiNE.The.Lorax.2012.DVDRip.LiNE.XviD.AC3.HQ.Hive-CM8.mp4
|
||||||
|
: videoCodec: XviD
|
||||||
|
title: Dr LiNE The Lorax
|
||||||
|
format: DVD
|
||||||
|
other: LiNE
|
||||||
|
year: 2012
|
||||||
|
audioCodec: AC3
|
||||||
|
audioProfile: HQ
|
||||||
|
releaseGroup: Hive-CM8
|
||||||
|
|
||||||
|
? Perfect Child-2007-TRUEFRENCH-TVRip.Xvid-h@mster.avi
|
||||||
|
: releaseGroup: h@mster
|
||||||
|
title: Perfect Child
|
||||||
|
videoCodec: XviD
|
||||||
|
language: French
|
||||||
|
format: TV
|
||||||
|
year: 2007
|
||||||
|
|
||||||
|
? entre.ciel.et.terre.(1994).dvdrip.h264.aac-psypeon.avi
|
||||||
|
: audioCodec: AAC
|
||||||
|
format: DVD
|
||||||
|
releaseGroup: psypeon
|
||||||
|
title: entre ciel et terre
|
||||||
|
videoCodec: h264
|
||||||
|
year: 1994
|
||||||
|
|
||||||
|
? Yves.Saint.Laurent.2013.FRENCH.DVDSCR.MD.XviD-ViVARiUM.avi
|
||||||
|
: format: DVD
|
||||||
|
language: French
|
||||||
|
other: Screener
|
||||||
|
releaseGroup: ViVARiUM
|
||||||
|
title: Yves Saint Laurent
|
||||||
|
videoCodec: XviD
|
||||||
|
year: 2013
|
||||||
|
|
||||||
|
? Echec et Mort - Hard to Kill - Steven Seagal Multi 1080p BluRay x264 CCATS.avi
|
||||||
|
: format: BluRay
|
||||||
|
language: Multiple languages
|
||||||
|
releaseGroup: CCATS
|
||||||
|
screenSize: 1080p
|
||||||
|
title: Echec et Mort
|
||||||
|
videoCodec: h264
|
||||||
|
|
||||||
|
? Paparazzi - Timsit/Lindon (MKV 1080p tvripHD)
|
||||||
|
: options: -n
|
||||||
|
title: Paparazzi
|
||||||
|
screenSize: 1080p
|
||||||
|
format: HDTV
|
||||||
|
|
||||||
|
? some.movie.720p.bluray.x264-mind
|
||||||
|
: options: -n
|
||||||
|
title: some movie
|
||||||
|
screenSize: 720p
|
||||||
|
videoCodec: h264
|
||||||
|
releaseGroup: mind
|
||||||
|
format: BluRay
|
||||||
|
|
||||||
|
? Dr LiNE The Lorax 720p h264 BluRay
|
||||||
|
: options: -n
|
||||||
|
title: Dr LiNE The Lorax
|
||||||
|
screenSize: 720p
|
||||||
|
videoCodec: h264
|
||||||
|
format: BluRay
|
||||||
|
|
||||||
|
? BeatdownFrenchDVDRip.mkv
|
||||||
|
: title: Beatdown
|
||||||
|
language: French
|
||||||
|
format: DVD
|
||||||
|
|
||||||
|
? YvesSaintLaurent2013FrenchDVDScrXvid.avi
|
||||||
|
: format: DVD
|
||||||
|
language: French
|
||||||
|
other: Screener
|
||||||
|
title: Yves saint laurent
|
||||||
|
videoCodec: XviD
|
||||||
|
year: 2013
|
473
lib/guessit/test/opensubtitles_languages_2012_05_09.txt
Normal file
473
lib/guessit/test/opensubtitles_languages_2012_05_09.txt
Normal file
|
@ -0,0 +1,473 @@
|
||||||
|
IdSubLanguage ISO639 LanguageName UploadEnabled WebEnabled
|
||||||
|
aar aa Afar, afar 0 0
|
||||||
|
abk ab Abkhazian 0 0
|
||||||
|
ace Achinese 0 0
|
||||||
|
ach Acoli 0 0
|
||||||
|
ada Adangme 0 0
|
||||||
|
ady adyghé 0 0
|
||||||
|
afa Afro-Asiatic (Other) 0 0
|
||||||
|
afh Afrihili 0 0
|
||||||
|
afr af Afrikaans 0 0
|
||||||
|
ain Ainu 0 0
|
||||||
|
aka ak Akan 0 0
|
||||||
|
akk Akkadian 0 0
|
||||||
|
alb sq Albanian 1 1
|
||||||
|
ale Aleut 0 0
|
||||||
|
alg Algonquian languages 0 0
|
||||||
|
alt Southern Altai 0 0
|
||||||
|
amh am Amharic 0 0
|
||||||
|
ang English, Old (ca.450-1100) 0 0
|
||||||
|
apa Apache languages 0 0
|
||||||
|
ara ar Arabic 1 1
|
||||||
|
arc Aramaic 0 0
|
||||||
|
arg an Aragonese 0 0
|
||||||
|
arm hy Armenian 1 0
|
||||||
|
arn Araucanian 0 0
|
||||||
|
arp Arapaho 0 0
|
||||||
|
art Artificial (Other) 0 0
|
||||||
|
arw Arawak 0 0
|
||||||
|
asm as Assamese 0 0
|
||||||
|
ast Asturian, Bable 0 0
|
||||||
|
ath Athapascan languages 0 0
|
||||||
|
aus Australian languages 0 0
|
||||||
|
ava av Avaric 0 0
|
||||||
|
ave ae Avestan 0 0
|
||||||
|
awa Awadhi 0 0
|
||||||
|
aym ay Aymara 0 0
|
||||||
|
aze az Azerbaijani 0 0
|
||||||
|
bad Banda 0 0
|
||||||
|
bai Bamileke languages 0 0
|
||||||
|
bak ba Bashkir 0 0
|
||||||
|
bal Baluchi 0 0
|
||||||
|
bam bm Bambara 0 0
|
||||||
|
ban Balinese 0 0
|
||||||
|
baq eu Basque 1 1
|
||||||
|
bas Basa 0 0
|
||||||
|
bat Baltic (Other) 0 0
|
||||||
|
bej Beja 0 0
|
||||||
|
bel be Belarusian 0 0
|
||||||
|
bem Bemba 0 0
|
||||||
|
ben bn Bengali 1 0
|
||||||
|
ber Berber (Other) 0 0
|
||||||
|
bho Bhojpuri 0 0
|
||||||
|
bih bh Bihari 0 0
|
||||||
|
bik Bikol 0 0
|
||||||
|
bin Bini 0 0
|
||||||
|
bis bi Bislama 0 0
|
||||||
|
bla Siksika 0 0
|
||||||
|
bnt Bantu (Other) 0 0
|
||||||
|
bos bs Bosnian 1 0
|
||||||
|
bra Braj 0 0
|
||||||
|
bre br Breton 1 0
|
||||||
|
btk Batak (Indonesia) 0 0
|
||||||
|
bua Buriat 0 0
|
||||||
|
bug Buginese 0 0
|
||||||
|
bul bg Bulgarian 1 1
|
||||||
|
bur my Burmese 0 0
|
||||||
|
byn Blin 0 0
|
||||||
|
cad Caddo 0 0
|
||||||
|
cai Central American Indian (Other) 0 0
|
||||||
|
car Carib 0 0
|
||||||
|
cat ca Catalan 1 1
|
||||||
|
cau Caucasian (Other) 0 0
|
||||||
|
ceb Cebuano 0 0
|
||||||
|
cel Celtic (Other) 0 0
|
||||||
|
cha ch Chamorro 0 0
|
||||||
|
chb Chibcha 0 0
|
||||||
|
che ce Chechen 0 0
|
||||||
|
chg Chagatai 0 0
|
||||||
|
chi zh Chinese 1 1
|
||||||
|
chk Chuukese 0 0
|
||||||
|
chm Mari 0 0
|
||||||
|
chn Chinook jargon 0 0
|
||||||
|
cho Choctaw 0 0
|
||||||
|
chp Chipewyan 0 0
|
||||||
|
chr Cherokee 0 0
|
||||||
|
chu cu Church Slavic 0 0
|
||||||
|
chv cv Chuvash 0 0
|
||||||
|
chy Cheyenne 0 0
|
||||||
|
cmc Chamic languages 0 0
|
||||||
|
cop Coptic 0 0
|
||||||
|
cor kw Cornish 0 0
|
||||||
|
cos co Corsican 0 0
|
||||||
|
cpe Creoles and pidgins, English based (Other) 0 0
|
||||||
|
cpf Creoles and pidgins, French-based (Other) 0 0
|
||||||
|
cpp Creoles and pidgins, Portuguese-based (Other) 0 0
|
||||||
|
cre cr Cree 0 0
|
||||||
|
crh Crimean Tatar 0 0
|
||||||
|
crp Creoles and pidgins (Other) 0 0
|
||||||
|
csb Kashubian 0 0
|
||||||
|
cus Cushitic (Other)' couchitiques, autres langues 0 0
|
||||||
|
cze cs Czech 1 1
|
||||||
|
dak Dakota 0 0
|
||||||
|
dan da Danish 1 1
|
||||||
|
dar Dargwa 0 0
|
||||||
|
day Dayak 0 0
|
||||||
|
del Delaware 0 0
|
||||||
|
den Slave (Athapascan) 0 0
|
||||||
|
dgr Dogrib 0 0
|
||||||
|
din Dinka 0 0
|
||||||
|
div dv Divehi 0 0
|
||||||
|
doi Dogri 0 0
|
||||||
|
dra Dravidian (Other) 0 0
|
||||||
|
dua Duala 0 0
|
||||||
|
dum Dutch, Middle (ca.1050-1350) 0 0
|
||||||
|
dut nl Dutch 1 1
|
||||||
|
dyu Dyula 0 0
|
||||||
|
dzo dz Dzongkha 0 0
|
||||||
|
efi Efik 0 0
|
||||||
|
egy Egyptian (Ancient) 0 0
|
||||||
|
eka Ekajuk 0 0
|
||||||
|
elx Elamite 0 0
|
||||||
|
eng en English 1 1
|
||||||
|
enm English, Middle (1100-1500) 0 0
|
||||||
|
epo eo Esperanto 1 0
|
||||||
|
est et Estonian 1 1
|
||||||
|
ewe ee Ewe 0 0
|
||||||
|
ewo Ewondo 0 0
|
||||||
|
fan Fang 0 0
|
||||||
|
fao fo Faroese 0 0
|
||||||
|
fat Fanti 0 0
|
||||||
|
fij fj Fijian 0 0
|
||||||
|
fil Filipino 0 0
|
||||||
|
fin fi Finnish 1 1
|
||||||
|
fiu Finno-Ugrian (Other) 0 0
|
||||||
|
fon Fon 0 0
|
||||||
|
fre fr French 1 1
|
||||||
|
frm French, Middle (ca.1400-1600) 0 0
|
||||||
|
fro French, Old (842-ca.1400) 0 0
|
||||||
|
fry fy Frisian 0 0
|
||||||
|
ful ff Fulah 0 0
|
||||||
|
fur Friulian 0 0
|
||||||
|
gaa Ga 0 0
|
||||||
|
gay Gayo 0 0
|
||||||
|
gba Gbaya 0 0
|
||||||
|
gem Germanic (Other) 0 0
|
||||||
|
geo ka Georgian 1 1
|
||||||
|
ger de German 1 1
|
||||||
|
gez Geez 0 0
|
||||||
|
gil Gilbertese 0 0
|
||||||
|
gla gd Gaelic 0 0
|
||||||
|
gle ga Irish 0 0
|
||||||
|
glg gl Galician 1 1
|
||||||
|
glv gv Manx 0 0
|
||||||
|
gmh German, Middle High (ca.1050-1500) 0 0
|
||||||
|
goh German, Old High (ca.750-1050) 0 0
|
||||||
|
gon Gondi 0 0
|
||||||
|
gor Gorontalo 0 0
|
||||||
|
got Gothic 0 0
|
||||||
|
grb Grebo 0 0
|
||||||
|
grc Greek, Ancient (to 1453) 0 0
|
||||||
|
ell el Greek 1 1
|
||||||
|
grn gn Guarani 0 0
|
||||||
|
guj gu Gujarati 0 0
|
||||||
|
gwi Gwich´in 0 0
|
||||||
|
hai Haida 0 0
|
||||||
|
hat ht Haitian 0 0
|
||||||
|
hau ha Hausa 0 0
|
||||||
|
haw Hawaiian 0 0
|
||||||
|
heb he Hebrew 1 1
|
||||||
|
her hz Herero 0 0
|
||||||
|
hil Hiligaynon 0 0
|
||||||
|
him Himachali 0 0
|
||||||
|
hin hi Hindi 1 1
|
||||||
|
hit Hittite 0 0
|
||||||
|
hmn Hmong 0 0
|
||||||
|
hmo ho Hiri Motu 0 0
|
||||||
|
hrv hr Croatian 1 1
|
||||||
|
hun hu Hungarian 1 1
|
||||||
|
hup Hupa 0 0
|
||||||
|
iba Iban 0 0
|
||||||
|
ibo ig Igbo 0 0
|
||||||
|
ice is Icelandic 1 1
|
||||||
|
ido io Ido 0 0
|
||||||
|
iii ii Sichuan Yi 0 0
|
||||||
|
ijo Ijo 0 0
|
||||||
|
iku iu Inuktitut 0 0
|
||||||
|
ile ie Interlingue 0 0
|
||||||
|
ilo Iloko 0 0
|
||||||
|
ina ia Interlingua (International Auxiliary Language Asso 0 0
|
||||||
|
inc Indic (Other) 0 0
|
||||||
|
ind id Indonesian 1 1
|
||||||
|
ine Indo-European (Other) 0 0
|
||||||
|
inh Ingush 0 0
|
||||||
|
ipk ik Inupiaq 0 0
|
||||||
|
ira Iranian (Other) 0 0
|
||||||
|
iro Iroquoian languages 0 0
|
||||||
|
ita it Italian 1 1
|
||||||
|
jav jv Javanese 0 0
|
||||||
|
jpn ja Japanese 1 1
|
||||||
|
jpr Judeo-Persian 0 0
|
||||||
|
jrb Judeo-Arabic 0 0
|
||||||
|
kaa Kara-Kalpak 0 0
|
||||||
|
kab Kabyle 0 0
|
||||||
|
kac Kachin 0 0
|
||||||
|
kal kl Kalaallisut 0 0
|
||||||
|
kam Kamba 0 0
|
||||||
|
kan kn Kannada 0 0
|
||||||
|
kar Karen 0 0
|
||||||
|
kas ks Kashmiri 0 0
|
||||||
|
kau kr Kanuri 0 0
|
||||||
|
kaw Kawi 0 0
|
||||||
|
kaz kk Kazakh 1 0
|
||||||
|
kbd Kabardian 0 0
|
||||||
|
kha Khasi 0 0
|
||||||
|
khi Khoisan (Other) 0 0
|
||||||
|
khm km Khmer 1 1
|
||||||
|
kho Khotanese 0 0
|
||||||
|
kik ki Kikuyu 0 0
|
||||||
|
kin rw Kinyarwanda 0 0
|
||||||
|
kir ky Kirghiz 0 0
|
||||||
|
kmb Kimbundu 0 0
|
||||||
|
kok Konkani 0 0
|
||||||
|
kom kv Komi 0 0
|
||||||
|
kon kg Kongo 0 0
|
||||||
|
kor ko Korean 1 1
|
||||||
|
kos Kosraean 0 0
|
||||||
|
kpe Kpelle 0 0
|
||||||
|
krc Karachay-Balkar 0 0
|
||||||
|
kro Kru 0 0
|
||||||
|
kru Kurukh 0 0
|
||||||
|
kua kj Kuanyama 0 0
|
||||||
|
kum Kumyk 0 0
|
||||||
|
kur ku Kurdish 0 0
|
||||||
|
kut Kutenai 0 0
|
||||||
|
lad Ladino 0 0
|
||||||
|
lah Lahnda 0 0
|
||||||
|
lam Lamba 0 0
|
||||||
|
lao lo Lao 0 0
|
||||||
|
lat la Latin 0 0
|
||||||
|
lav lv Latvian 1 0
|
||||||
|
lez Lezghian 0 0
|
||||||
|
lim li Limburgan 0 0
|
||||||
|
lin ln Lingala 0 0
|
||||||
|
lit lt Lithuanian 1 0
|
||||||
|
lol Mongo 0 0
|
||||||
|
loz Lozi 0 0
|
||||||
|
ltz lb Luxembourgish 1 0
|
||||||
|
lua Luba-Lulua 0 0
|
||||||
|
lub lu Luba-Katanga 0 0
|
||||||
|
lug lg Ganda 0 0
|
||||||
|
lui Luiseno 0 0
|
||||||
|
lun Lunda 0 0
|
||||||
|
luo Luo (Kenya and Tanzania) 0 0
|
||||||
|
lus lushai 0 0
|
||||||
|
mac mk Macedonian 1 1
|
||||||
|
mad Madurese 0 0
|
||||||
|
mag Magahi 0 0
|
||||||
|
mah mh Marshallese 0 0
|
||||||
|
mai Maithili 0 0
|
||||||
|
mak Makasar 0 0
|
||||||
|
mal ml Malayalam 0 0
|
||||||
|
man Mandingo 0 0
|
||||||
|
mao mi Maori 0 0
|
||||||
|
map Austronesian (Other) 0 0
|
||||||
|
mar mr Marathi 0 0
|
||||||
|
mas Masai 0 0
|
||||||
|
may ms Malay 1 1
|
||||||
|
mdf Moksha 0 0
|
||||||
|
mdr Mandar 0 0
|
||||||
|
men Mende 0 0
|
||||||
|
mga Irish, Middle (900-1200) 0 0
|
||||||
|
mic Mi'kmaq 0 0
|
||||||
|
min Minangkabau 0 0
|
||||||
|
mis Miscellaneous languages 0 0
|
||||||
|
mkh Mon-Khmer (Other) 0 0
|
||||||
|
mlg mg Malagasy 0 0
|
||||||
|
mlt mt Maltese 0 0
|
||||||
|
mnc Manchu 0 0
|
||||||
|
mni Manipuri 0 0
|
||||||
|
mno Manobo languages 0 0
|
||||||
|
moh Mohawk 0 0
|
||||||
|
mol mo Moldavian 0 0
|
||||||
|
mon mn Mongolian 1 0
|
||||||
|
mos Mossi 0 0
|
||||||
|
mwl Mirandese 0 0
|
||||||
|
mul Multiple languages 0 0
|
||||||
|
mun Munda languages 0 0
|
||||||
|
mus Creek 0 0
|
||||||
|
mwr Marwari 0 0
|
||||||
|
myn Mayan languages 0 0
|
||||||
|
myv Erzya 0 0
|
||||||
|
nah Nahuatl 0 0
|
||||||
|
nai North American Indian 0 0
|
||||||
|
nap Neapolitan 0 0
|
||||||
|
nau na Nauru 0 0
|
||||||
|
nav nv Navajo 0 0
|
||||||
|
nbl nr Ndebele, South 0 0
|
||||||
|
nde nd Ndebele, North 0 0
|
||||||
|
ndo ng Ndonga 0 0
|
||||||
|
nds Low German 0 0
|
||||||
|
nep ne Nepali 0 0
|
||||||
|
new Nepal Bhasa 0 0
|
||||||
|
nia Nias 0 0
|
||||||
|
nic Niger-Kordofanian (Other) 0 0
|
||||||
|
niu Niuean 0 0
|
||||||
|
nno nn Norwegian Nynorsk 0 0
|
||||||
|
nob nb Norwegian Bokmal 0 0
|
||||||
|
nog Nogai 0 0
|
||||||
|
non Norse, Old 0 0
|
||||||
|
nor no Norwegian 1 1
|
||||||
|
nso Northern Sotho 0 0
|
||||||
|
nub Nubian languages 0 0
|
||||||
|
nwc Classical Newari 0 0
|
||||||
|
nya ny Chichewa 0 0
|
||||||
|
nym Nyamwezi 0 0
|
||||||
|
nyn Nyankole 0 0
|
||||||
|
nyo Nyoro 0 0
|
||||||
|
nzi Nzima 0 0
|
||||||
|
oci oc Occitan 1 1
|
||||||
|
oji oj Ojibwa 0 0
|
||||||
|
ori or Oriya 0 0
|
||||||
|
orm om Oromo 0 0
|
||||||
|
osa Osage 0 0
|
||||||
|
oss os Ossetian 0 0
|
||||||
|
ota Turkish, Ottoman (1500-1928) 0 0
|
||||||
|
oto Otomian languages 0 0
|
||||||
|
paa Papuan (Other) 0 0
|
||||||
|
pag Pangasinan 0 0
|
||||||
|
pal Pahlavi 0 0
|
||||||
|
pam Pampanga 0 0
|
||||||
|
pan pa Panjabi 0 0
|
||||||
|
pap Papiamento 0 0
|
||||||
|
pau Palauan 0 0
|
||||||
|
peo Persian, Old (ca.600-400 B.C.) 0 0
|
||||||
|
per fa Persian 1 1
|
||||||
|
phi Philippine (Other) 0 0
|
||||||
|
phn Phoenician 0 0
|
||||||
|
pli pi Pali 0 0
|
||||||
|
pol pl Polish 1 1
|
||||||
|
pon Pohnpeian 0 0
|
||||||
|
por pt Portuguese 1 1
|
||||||
|
pra Prakrit languages 0 0
|
||||||
|
pro Provençal, Old (to 1500) 0 0
|
||||||
|
pus ps Pushto 0 0
|
||||||
|
que qu Quechua 0 0
|
||||||
|
raj Rajasthani 0 0
|
||||||
|
rap Rapanui 0 0
|
||||||
|
rar Rarotongan 0 0
|
||||||
|
roa Romance (Other) 0 0
|
||||||
|
roh rm Raeto-Romance 0 0
|
||||||
|
rom Romany 0 0
|
||||||
|
run rn Rundi 0 0
|
||||||
|
rup Aromanian 0 0
|
||||||
|
rus ru Russian 1 1
|
||||||
|
sad Sandawe 0 0
|
||||||
|
sag sg Sango 0 0
|
||||||
|
sah Yakut 0 0
|
||||||
|
sai South American Indian (Other) 0 0
|
||||||
|
sal Salishan languages 0 0
|
||||||
|
sam Samaritan Aramaic 0 0
|
||||||
|
san sa Sanskrit 0 0
|
||||||
|
sas Sasak 0 0
|
||||||
|
sat Santali 0 0
|
||||||
|
scc sr Serbian 1 1
|
||||||
|
scn Sicilian 0 0
|
||||||
|
sco Scots 0 0
|
||||||
|
sel Selkup 0 0
|
||||||
|
sem Semitic (Other) 0 0
|
||||||
|
sga Irish, Old (to 900) 0 0
|
||||||
|
sgn Sign Languages 0 0
|
||||||
|
shn Shan 0 0
|
||||||
|
sid Sidamo 0 0
|
||||||
|
sin si Sinhalese 1 1
|
||||||
|
sio Siouan languages 0 0
|
||||||
|
sit Sino-Tibetan (Other) 0 0
|
||||||
|
sla Slavic (Other) 0 0
|
||||||
|
slo sk Slovak 1 1
|
||||||
|
slv sl Slovenian 1 1
|
||||||
|
sma Southern Sami 0 0
|
||||||
|
sme se Northern Sami 0 0
|
||||||
|
smi Sami languages (Other) 0 0
|
||||||
|
smj Lule Sami 0 0
|
||||||
|
smn Inari Sami 0 0
|
||||||
|
smo sm Samoan 0 0
|
||||||
|
sms Skolt Sami 0 0
|
||||||
|
sna sn Shona 0 0
|
||||||
|
snd sd Sindhi 0 0
|
||||||
|
snk Soninke 0 0
|
||||||
|
sog Sogdian 0 0
|
||||||
|
som so Somali 0 0
|
||||||
|
son Songhai 0 0
|
||||||
|
sot st Sotho, Southern 0 0
|
||||||
|
spa es Spanish 1 1
|
||||||
|
srd sc Sardinian 0 0
|
||||||
|
srr Serer 0 0
|
||||||
|
ssa Nilo-Saharan (Other) 0 0
|
||||||
|
ssw ss Swati 0 0
|
||||||
|
suk Sukuma 0 0
|
||||||
|
sun su Sundanese 0 0
|
||||||
|
sus Susu 0 0
|
||||||
|
sux Sumerian 0 0
|
||||||
|
swa sw Swahili 1 0
|
||||||
|
swe sv Swedish 1 1
|
||||||
|
syr Syriac 1 0
|
||||||
|
tah ty Tahitian 0 0
|
||||||
|
tai Tai (Other) 0 0
|
||||||
|
tam ta Tamil 0 0
|
||||||
|
tat tt Tatar 0 0
|
||||||
|
tel te Telugu 0 0
|
||||||
|
tem Timne 0 0
|
||||||
|
ter Tereno 0 0
|
||||||
|
tet Tetum 0 0
|
||||||
|
tgk tg Tajik 0 0
|
||||||
|
tgl tl Tagalog 1 1
|
||||||
|
tha th Thai 1 1
|
||||||
|
tib bo Tibetan 0 0
|
||||||
|
tig Tigre 0 0
|
||||||
|
tir ti Tigrinya 0 0
|
||||||
|
tiv Tiv 0 0
|
||||||
|
tkl Tokelau 0 0
|
||||||
|
tlh Klingon 0 0
|
||||||
|
tli Tlingit 0 0
|
||||||
|
tmh Tamashek 0 0
|
||||||
|
tog Tonga (Nyasa) 0 0
|
||||||
|
ton to Tonga (Tonga Islands) 0 0
|
||||||
|
tpi Tok Pisin 0 0
|
||||||
|
tsi Tsimshian 0 0
|
||||||
|
tsn tn Tswana 0 0
|
||||||
|
tso ts Tsonga 0 0
|
||||||
|
tuk tk Turkmen 0 0
|
||||||
|
tum Tumbuka 0 0
|
||||||
|
tup Tupi languages 0 0
|
||||||
|
tur tr Turkish 1 1
|
||||||
|
tut Altaic (Other) 0 0
|
||||||
|
tvl Tuvalu 0 0
|
||||||
|
twi tw Twi 0 0
|
||||||
|
tyv Tuvinian 0 0
|
||||||
|
udm Udmurt 0 0
|
||||||
|
uga Ugaritic 0 0
|
||||||
|
uig ug Uighur 0 0
|
||||||
|
ukr uk Ukrainian 1 1
|
||||||
|
umb Umbundu 0 0
|
||||||
|
und Undetermined 0 0
|
||||||
|
urd ur Urdu 1 0
|
||||||
|
uzb uz Uzbek 0 0
|
||||||
|
vai Vai 0 0
|
||||||
|
ven ve Venda 0 0
|
||||||
|
vie vi Vietnamese 1 1
|
||||||
|
vol vo Volapük 0 0
|
||||||
|
vot Votic 0 0
|
||||||
|
wak Wakashan languages 0 0
|
||||||
|
wal Walamo 0 0
|
||||||
|
war Waray 0 0
|
||||||
|
was Washo 0 0
|
||||||
|
wel cy Welsh 0 0
|
||||||
|
wen Sorbian languages 0 0
|
||||||
|
wln wa Walloon 0 0
|
||||||
|
wol wo Wolof 0 0
|
||||||
|
xal Kalmyk 0 0
|
||||||
|
xho xh Xhosa 0 0
|
||||||
|
yao Yao 0 0
|
||||||
|
yap Yapese 0 0
|
||||||
|
yid yi Yiddish 0 0
|
||||||
|
yor yo Yoruba 0 0
|
||||||
|
ypk Yupik languages 0 0
|
||||||
|
zap Zapotec 0 0
|
||||||
|
zen Zenaga 0 0
|
||||||
|
zha za Zhuang 0 0
|
||||||
|
znd Zande 0 0
|
||||||
|
zul zu Zulu 0 0
|
||||||
|
zun Zuni 0 0
|
||||||
|
rum ro Romanian 1 1
|
||||||
|
pob pb Brazilian 1 1
|
54
lib/guessit/test/test_api.py
Normal file
54
lib/guessit/test/test_api.py
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# GuessIt - A library for guessing information from filenames
|
||||||
|
# Copyright (c) 2014 Nicolas Wack <wackou@gmail.com>
|
||||||
|
#
|
||||||
|
# GuessIt is free software; you can redistribute it and/or modify it under
|
||||||
|
# the terms of the Lesser GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# GuessIt is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# Lesser GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the Lesser GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
|
from guessit.test.guessittest import *
|
||||||
|
|
||||||
|
|
||||||
|
class TestApi(TestGuessit):
|
||||||
|
def test_api(self):
|
||||||
|
movie_path = 'Movies/Dark City (1998)/Dark.City.(1998).DC.BDRip.720p.DTS.X264-CHD.mkv'
|
||||||
|
|
||||||
|
movie_info = guessit.guess_movie_info(movie_path)
|
||||||
|
video_info = guessit.guess_video_info(movie_path)
|
||||||
|
episode_info = guessit.guess_episode_info(movie_path)
|
||||||
|
file_info = guessit.guess_file_info(movie_path)
|
||||||
|
|
||||||
|
self.assertEqual(guessit.guess_file_info(movie_path, type='movie'), movie_info)
|
||||||
|
self.assertEqual(guessit.guess_file_info(movie_path, type='video'), video_info)
|
||||||
|
self.assertEqual(guessit.guess_file_info(movie_path, type='episode'), episode_info)
|
||||||
|
|
||||||
|
self.assertEqual(guessit.guess_file_info(movie_path, options={'type': 'movie'}), movie_info)
|
||||||
|
self.assertEqual(guessit.guess_file_info(movie_path, options={'type': 'video'}), video_info)
|
||||||
|
self.assertEqual(guessit.guess_file_info(movie_path, options={'type': 'episode'}), episode_info)
|
||||||
|
|
||||||
|
self.assertEqual(guessit.guess_file_info(movie_path, options={'type': 'episode'}, type='movie'), episode_info) # kwargs priority other options
|
||||||
|
|
||||||
|
movie_path_name_only = 'Movies/Dark City (1998)/Dark.City.(1998).DC.BDRip.720p.DTS.X264-CHD'
|
||||||
|
file_info_name_only = guessit.guess_file_info(movie_path_name_only, options={"name_only": True})
|
||||||
|
|
||||||
|
self.assertFalse('container' in file_info_name_only)
|
||||||
|
self.assertTrue('container' in file_info)
|
||||||
|
|
||||||
|
suite = allTests(TestApi)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
TextTestRunner(verbosity=2).run(suite)
|
45
lib/guessit/test/test_autodetect.py
Normal file
45
lib/guessit/test/test_autodetect.py
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# GuessIt - A library for guessing information from filenames
|
||||||
|
# Copyright (c) 2013 Nicolas Wack <wackou@gmail.com>
|
||||||
|
#
|
||||||
|
# GuessIt is free software; you can redistribute it and/or modify it under
|
||||||
|
# the terms of the Lesser GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# GuessIt is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# Lesser GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the Lesser GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
|
from guessit.test.guessittest import *
|
||||||
|
|
||||||
|
|
||||||
|
class TestAutoDetect(TestGuessit):
|
||||||
|
def testEmpty(self):
|
||||||
|
result = guessit.guess_file_info('')
|
||||||
|
self.assertEqual(result, {})
|
||||||
|
|
||||||
|
result = guessit.guess_file_info('___-__')
|
||||||
|
self.assertEqual(result, {})
|
||||||
|
|
||||||
|
result = guessit.guess_file_info('__-.avc')
|
||||||
|
self.assertEqual(result, {'type': 'unknown', 'extension': 'avc'})
|
||||||
|
|
||||||
|
def testAutoDetect(self):
|
||||||
|
self.checkMinimumFieldsCorrect(filename='autodetect.yaml',
|
||||||
|
remove_type=False)
|
||||||
|
|
||||||
|
|
||||||
|
suite = allTests(TestAutoDetect)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
TextTestRunner(verbosity=2).run(suite)
|
46
lib/guessit/test/test_autodetect_all.py
Normal file
46
lib/guessit/test/test_autodetect_all.py
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# GuessIt - A library for guessing information from filenames
|
||||||
|
# Copyright (c) 2013 Nicolas Wack <wackou@gmail.com>
|
||||||
|
#
|
||||||
|
# GuessIt is free software; you can redistribute it and/or modify it under
|
||||||
|
# the terms of the Lesser GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# GuessIt is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# Lesser GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the Lesser GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
|
from guessit.test.guessittest import *
|
||||||
|
|
||||||
|
IGNORE_EPISODES = []
|
||||||
|
IGNORE_MOVIES = []
|
||||||
|
|
||||||
|
|
||||||
|
class TestAutoDetectAll(TestGuessit):
|
||||||
|
def testAutoMatcher(self):
|
||||||
|
self.checkMinimumFieldsCorrect(filename='autodetect.yaml',
|
||||||
|
remove_type=False)
|
||||||
|
|
||||||
|
def testAutoMatcherMovies(self):
|
||||||
|
self.checkMinimumFieldsCorrect(filename='movies.yaml',
|
||||||
|
exclude_files=IGNORE_MOVIES)
|
||||||
|
|
||||||
|
def testAutoMatcherEpisodes(self):
|
||||||
|
self.checkMinimumFieldsCorrect(filename='episodes.yaml',
|
||||||
|
exclude_files=IGNORE_EPISODES)
|
||||||
|
|
||||||
|
|
||||||
|
suite = allTests(TestAutoDetectAll)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
TextTestRunner(verbosity=2).run(suite)
|
45
lib/guessit/test/test_doctests.py
Normal file
45
lib/guessit/test/test_doctests.py
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# GuessIt - A library for guessing information from filenames
|
||||||
|
# Copyright (c) 2014 Nicolas Wack <wackou@gmail.com>
|
||||||
|
#
|
||||||
|
# GuessIt is free software; you can redistribute it and/or modify it under
|
||||||
|
# the terms of the Lesser GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# GuessIt is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# Lesser GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the Lesser GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
|
from guessit.test.guessittest import *
|
||||||
|
import guessit
|
||||||
|
import guessit.hash_ed2k
|
||||||
|
import unittest
|
||||||
|
import doctest
|
||||||
|
|
||||||
|
|
||||||
|
def load_tests(loader, tests, ignore):
|
||||||
|
tests.addTests(doctest.DocTestSuite(guessit))
|
||||||
|
tests.addTests(doctest.DocTestSuite(guessit.date))
|
||||||
|
tests.addTests(doctest.DocTestSuite(guessit.fileutils))
|
||||||
|
tests.addTests(doctest.DocTestSuite(guessit.guess))
|
||||||
|
tests.addTests(doctest.DocTestSuite(guessit.hash_ed2k))
|
||||||
|
tests.addTests(doctest.DocTestSuite(guessit.language))
|
||||||
|
tests.addTests(doctest.DocTestSuite(guessit.matchtree))
|
||||||
|
tests.addTests(doctest.DocTestSuite(guessit.textutils))
|
||||||
|
return tests
|
||||||
|
|
||||||
|
suite = unittest.TestSuite()
|
||||||
|
load_tests(None, suite, None)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
TextTestRunner(verbosity=2).run(suite)
|
35
lib/guessit/test/test_episode.py
Normal file
35
lib/guessit/test/test_episode.py
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# GuessIt - A library for guessing information from filenames
|
||||||
|
# Copyright (c) 2013 Nicolas Wack <wackou@gmail.com>
|
||||||
|
#
|
||||||
|
# GuessIt is free software; you can redistribute it and/or modify it under
|
||||||
|
# the terms of the Lesser GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# GuessIt is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# Lesser GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the Lesser GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
|
from guessit.test.guessittest import *
|
||||||
|
|
||||||
|
|
||||||
|
class TestEpisode(TestGuessit):
|
||||||
|
def testEpisodes(self):
|
||||||
|
self.checkMinimumFieldsCorrect(filetype='episode',
|
||||||
|
filename='episodes.yaml')
|
||||||
|
|
||||||
|
|
||||||
|
suite = allTests(TestEpisode)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
TextTestRunner(verbosity=2).run(suite)
|
46
lib/guessit/test/test_hashes.py
Normal file
46
lib/guessit/test/test_hashes.py
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# GuessIt - A library for guessing information from filenames
|
||||||
|
# Copyright (c) 2013 Nicolas Wack <wackou@gmail.com>
|
||||||
|
#
|
||||||
|
# GuessIt is free software; you can redistribute it and/or modify it under
|
||||||
|
# the terms of the Lesser GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# GuessIt is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# Lesser GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the Lesser GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
|
from guessit.test.guessittest import *
|
||||||
|
|
||||||
|
|
||||||
|
class TestHashes(TestGuessit):
|
||||||
|
def test_hashes(self):
|
||||||
|
hashes = (
|
||||||
|
('hash_mpc', '1MB', u'8542ad406c15c8bd'), # TODO: Check if this value is valid
|
||||||
|
('hash_ed2k', '1MB', u'ed2k://|file|1MB|1048576|AA3CC5552A9931A76B61A41D306735F7|/'), # TODO: Check if this value is valid
|
||||||
|
('hash_md5', '1MB', u'5d8dcbca8d8ac21766f28797d6c3954c'),
|
||||||
|
('hash_sha1', '1MB', u'51d2b8f3248d7ee495b7750c8da5aa3b3819de9d'),
|
||||||
|
('hash_md5', 'dummy.srt', u'64de6b5893cac24456c46a935ef9c359'),
|
||||||
|
('hash_sha1', 'dummy.srt', u'a703fc0fa4518080505809bf562c6fc6f7b3c98c')
|
||||||
|
)
|
||||||
|
|
||||||
|
for hash_type, filename, expected_value in hashes:
|
||||||
|
guess = guess_file_info(file_in_same_dir(__file__, filename), hash_type)
|
||||||
|
computed_value = guess.get(hash_type)
|
||||||
|
self.assertEqual(expected_value, guess.get(hash_type), "Invalid %s for %s: %s != %s" % (hash_type, filename, computed_value, expected_value))
|
||||||
|
|
||||||
|
|
||||||
|
suite = allTests(TestHashes)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
TextTestRunner(verbosity=2).run(suite)
|
138
lib/guessit/test/test_language.py
Normal file
138
lib/guessit/test/test_language.py
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# GuessIt - A library for guessing information from filenames
|
||||||
|
# Copyright (c) 2013 Nicolas Wack <wackou@gmail.com>
|
||||||
|
#
|
||||||
|
# GuessIt is free software; you can redistribute it and/or modify it under
|
||||||
|
# the terms of the Lesser GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# GuessIt is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# Lesser GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the Lesser GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
|
from guessit.test.guessittest import *
|
||||||
|
|
||||||
|
import io
|
||||||
|
|
||||||
|
|
||||||
|
class TestLanguage(TestGuessit):
|
||||||
|
|
||||||
|
def check_languages(self, languages):
|
||||||
|
for lang1, lang2 in languages.items():
|
||||||
|
self.assertEqual(Language(lang1),
|
||||||
|
Language(lang2))
|
||||||
|
|
||||||
|
def test_addic7ed(self):
|
||||||
|
languages = {'English': 'en',
|
||||||
|
'English (US)': 'en',
|
||||||
|
'English (UK)': 'en',
|
||||||
|
'Italian': 'it',
|
||||||
|
'Portuguese': 'pt',
|
||||||
|
'Portuguese (Brazilian)': 'pt',
|
||||||
|
'Romanian': 'ro',
|
||||||
|
'Español (Latinoamérica)': 'es',
|
||||||
|
'Español (España)': 'es',
|
||||||
|
'Spanish (Latin America)': 'es',
|
||||||
|
'Español': 'es',
|
||||||
|
'Spanish': 'es',
|
||||||
|
'Spanish (Spain)': 'es',
|
||||||
|
'French': 'fr',
|
||||||
|
'Greek': 'el',
|
||||||
|
'Arabic': 'ar',
|
||||||
|
'German': 'de',
|
||||||
|
'Croatian': 'hr',
|
||||||
|
'Indonesian': 'id',
|
||||||
|
'Hebrew': 'he',
|
||||||
|
'Russian': 'ru',
|
||||||
|
'Turkish': 'tr',
|
||||||
|
'Swedish': 'se',
|
||||||
|
'Czech': 'cs',
|
||||||
|
'Dutch': 'nl',
|
||||||
|
'Hungarian': 'hu',
|
||||||
|
'Norwegian': 'no',
|
||||||
|
'Polish': 'pl',
|
||||||
|
'Persian': 'fa'}
|
||||||
|
|
||||||
|
self.check_languages(languages)
|
||||||
|
|
||||||
|
def test_subswiki(self):
|
||||||
|
languages = {'English (US)': 'en', 'English (UK)': 'en', 'English': 'en',
|
||||||
|
'French': 'fr', 'Brazilian': 'po', 'Portuguese': 'pt',
|
||||||
|
'Español (Latinoamérica)': 'es', 'Español (España)': 'es',
|
||||||
|
'Español': 'es', 'Italian': 'it', 'Català': 'ca'}
|
||||||
|
|
||||||
|
self.check_languages(languages)
|
||||||
|
|
||||||
|
def test_tvsubtitles(self):
|
||||||
|
languages = {'English': 'en', 'Español': 'es', 'French': 'fr', 'German': 'de',
|
||||||
|
'Brazilian': 'br', 'Russian': 'ru', 'Ukrainian': 'ua', 'Italian': 'it',
|
||||||
|
'Greek': 'gr', 'Arabic': 'ar', 'Hungarian': 'hu', 'Polish': 'pl',
|
||||||
|
'Turkish': 'tr', 'Dutch': 'nl', 'Portuguese': 'pt', 'Swedish': 'sv',
|
||||||
|
'Danish': 'da', 'Finnish': 'fi', 'Korean': 'ko', 'Chinese': 'cn',
|
||||||
|
'Japanese': 'jp', 'Bulgarian': 'bg', 'Czech': 'cz', 'Romanian': 'ro'}
|
||||||
|
|
||||||
|
self.check_languages(languages)
|
||||||
|
|
||||||
|
def test_opensubtitles(self):
|
||||||
|
opensubtitles_langfile = file_in_same_dir(__file__, 'opensubtitles_languages_2012_05_09.txt')
|
||||||
|
for l in [u(l).strip() for l in io.open(opensubtitles_langfile, encoding='utf-8')][1:]:
|
||||||
|
idlang, alpha2, _, upload_enabled, web_enabled = l.strip().split('\t')
|
||||||
|
# do not test languages that are too esoteric / not widely available
|
||||||
|
if int(upload_enabled) and int(web_enabled):
|
||||||
|
# check that we recognize the opensubtitles language code correctly
|
||||||
|
# and that we are able to output this code from a language
|
||||||
|
self.assertEqual(idlang, Language(idlang).opensubtitles)
|
||||||
|
if alpha2:
|
||||||
|
# check we recognize the opensubtitles 2-letter code correctly
|
||||||
|
self.check_languages({idlang: alpha2})
|
||||||
|
|
||||||
|
def test_tmdb(self):
|
||||||
|
# examples from http://api.themoviedb.org/2.1/language-tags
|
||||||
|
for lang in ['en-US', 'en-CA', 'es-MX', 'fr-PF']:
|
||||||
|
self.assertEqual(lang, Language(lang).tmdb)
|
||||||
|
|
||||||
|
def test_subtitulos(self):
|
||||||
|
languages = {'English (US)': 'en', 'English (UK)': 'en', 'English': 'en',
|
||||||
|
'French': 'fr', 'Brazilian': 'po', 'Portuguese': 'pt',
|
||||||
|
'Español (Latinoamérica)': 'es', 'Español (España)': 'es',
|
||||||
|
'Español': 'es', 'Italian': 'it', 'Català': 'ca'}
|
||||||
|
|
||||||
|
self.check_languages(languages)
|
||||||
|
|
||||||
|
def test_thesubdb(self):
|
||||||
|
languages = {'af': 'af', 'cs': 'cs', 'da': 'da', 'de': 'de', 'en': 'en', 'es': 'es', 'fi': 'fi',
|
||||||
|
'fr': 'fr', 'hu': 'hu', 'id': 'id', 'it': 'it', 'la': 'la', 'nl': 'nl', 'no': 'no',
|
||||||
|
'oc': 'oc', 'pl': 'pl', 'pt': 'pt', 'ro': 'ro', 'ru': 'ru', 'sl': 'sl', 'sr': 'sr',
|
||||||
|
'sv': 'sv', 'tr': 'tr'}
|
||||||
|
|
||||||
|
self.check_languages(languages)
|
||||||
|
|
||||||
|
def test_language_object(self):
|
||||||
|
self.assertEqual(len(list(set([Language('qwerty'), Language('asdf')]))), 1)
|
||||||
|
d = {Language('qwerty'): 7}
|
||||||
|
d[Language('asdf')] = 23
|
||||||
|
self.assertEqual(d[Language('qwerty')], 23)
|
||||||
|
|
||||||
|
def test_exceptions(self):
|
||||||
|
self.assertEqual(Language('br'), Language('pt(br)'))
|
||||||
|
|
||||||
|
# languages should be equal regardless of country
|
||||||
|
self.assertEqual(Language('br'), Language('pt'))
|
||||||
|
|
||||||
|
self.assertEqual(Language('unknown'), Language('und'))
|
||||||
|
|
||||||
|
|
||||||
|
suite = allTests(TestLanguage)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
TextTestRunner(verbosity=2).run(suite)
|
70
lib/guessit/test/test_main.py
Normal file
70
lib/guessit/test/test_main.py
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# GuessIt - A library for guessing information from filenames
|
||||||
|
# Copyright (c) 2014 Nicolas Wack <wackou@gmail.com>
|
||||||
|
#
|
||||||
|
# GuessIt is free software; you can redistribute it and/or modify it under
|
||||||
|
# the terms of the Lesser GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# GuessIt is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# Lesser GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the Lesser GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
|
from guessit.test.guessittest import *
|
||||||
|
from guessit.fileutils import split_path, file_in_same_dir
|
||||||
|
from guessit.textutils import strip_brackets, str_replace, str_fill
|
||||||
|
from guessit import PY2
|
||||||
|
from guessit import __main__
|
||||||
|
|
||||||
|
if PY2:
|
||||||
|
from StringIO import StringIO
|
||||||
|
else:
|
||||||
|
from io import StringIO
|
||||||
|
|
||||||
|
|
||||||
|
class TestMain(TestGuessit):
|
||||||
|
def setUp(self):
|
||||||
|
self._stdout = sys.stdout
|
||||||
|
string_out = StringIO()
|
||||||
|
sys.stdout = string_out
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
sys.stdout = self._stdout
|
||||||
|
|
||||||
|
def test_list_properties(self):
|
||||||
|
__main__.main(["-p"], False)
|
||||||
|
__main__.main(["-l"], False)
|
||||||
|
|
||||||
|
def test_list_transformers(self):
|
||||||
|
__main__.main(["--transformers"], False)
|
||||||
|
__main__.main(["-l", "--transformers"], False)
|
||||||
|
|
||||||
|
def test_demo(self):
|
||||||
|
__main__.main(["-d"], False)
|
||||||
|
__main__.main(["-l"], False)
|
||||||
|
|
||||||
|
def test_filename(self):
|
||||||
|
__main__.main(["A.Movie.2014.avi"], False)
|
||||||
|
__main__.main(["A.Movie.2014.avi", "A.2nd.Movie.2014.avi"], False)
|
||||||
|
__main__.main(["-y", "A.Movie.2014.avi"], False)
|
||||||
|
__main__.main(["-a", "A.Movie.2014.avi"], False)
|
||||||
|
__main__.main(["-v", "A.Movie.2014.avi"], False)
|
||||||
|
__main__.main(["-t", "movie", "A.Movie.2014.avi"], False)
|
||||||
|
__main__.main(["-t", "episode", "A.Serie.S02E06.avi"], False)
|
||||||
|
__main__.main(["-i", "hash_mpc", file_in_same_dir(__file__, "1MB")], False)
|
||||||
|
__main__.main(["-i", "hash_md5", file_in_same_dir(__file__, "1MB")], False)
|
||||||
|
|
||||||
|
suite = allTests(TestMain)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
TextTestRunner(verbosity=2).run(suite)
|
93
lib/guessit/test/test_matchtree.py
Normal file
93
lib/guessit/test/test_matchtree.py
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# GuessIt - A library for guessing information from filenames
|
||||||
|
# Copyright (c) 2013 Nicolas Wack <wackou@gmail.com>
|
||||||
|
#
|
||||||
|
# GuessIt is free software; you can redistribute it and/or modify it under
|
||||||
|
# the terms of the Lesser GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# GuessIt is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# Lesser GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the Lesser GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
|
from guessit.test.guessittest import *
|
||||||
|
|
||||||
|
from guessit.transfo.guess_release_group import GuessReleaseGroup
|
||||||
|
from guessit.transfo.guess_properties import GuessProperties
|
||||||
|
from guessit.matchtree import BaseMatchTree
|
||||||
|
|
||||||
|
keywords = yaml.load("""
|
||||||
|
|
||||||
|
? Xvid PROPER
|
||||||
|
: videoCodec: Xvid
|
||||||
|
other: PROPER
|
||||||
|
|
||||||
|
? PROPER-Xvid
|
||||||
|
: videoCodec: Xvid
|
||||||
|
other: PROPER
|
||||||
|
|
||||||
|
""")
|
||||||
|
|
||||||
|
|
||||||
|
def guess_info(string, options=None):
|
||||||
|
mtree = MatchTree(string)
|
||||||
|
GuessReleaseGroup().process(mtree, options)
|
||||||
|
GuessProperties().process(mtree, options)
|
||||||
|
return mtree.matched()
|
||||||
|
|
||||||
|
|
||||||
|
class TestMatchTree(TestGuessit):
|
||||||
|
def test_base_tree(self):
|
||||||
|
t = BaseMatchTree('One Two Three(Three) Four')
|
||||||
|
t.partition((3, 7, 20))
|
||||||
|
leaves = t.leaves()
|
||||||
|
|
||||||
|
self.assertEqual(leaves[0].span, (0, 3))
|
||||||
|
|
||||||
|
self.assertEqual('One', leaves[0].value)
|
||||||
|
self.assertEqual(' Two', leaves[1].value)
|
||||||
|
self.assertEqual(' Three(Three)', leaves[2].value)
|
||||||
|
self.assertEqual(' Four', leaves[3].value)
|
||||||
|
|
||||||
|
leaves[2].partition((1, 6, 7, 12))
|
||||||
|
three_leaves = leaves[2].leaves()
|
||||||
|
|
||||||
|
self.assertEqual('Three', three_leaves[1].value)
|
||||||
|
self.assertEqual('Three', three_leaves[3].value)
|
||||||
|
|
||||||
|
leaves = t.leaves()
|
||||||
|
|
||||||
|
self.assertEqual(len(leaves), 8)
|
||||||
|
|
||||||
|
self.assertEqual(leaves[5], three_leaves[3])
|
||||||
|
|
||||||
|
self.assertEqual(t.previous_leaf(leaves[5]), leaves[4])
|
||||||
|
self.assertEqual(t.next_leaf(leaves[5]), leaves[6])
|
||||||
|
|
||||||
|
self.assertEqual(t.next_leaves(leaves[5]), [leaves[6], leaves[7]])
|
||||||
|
self.assertEqual(t.previous_leaves(leaves[5]), [leaves[4], leaves[3], leaves[2], leaves[1], leaves[0]])
|
||||||
|
|
||||||
|
self.assertEqual(t.next_leaf(leaves[7]), None)
|
||||||
|
self.assertEqual(t.previous_leaf(leaves[0]), None)
|
||||||
|
|
||||||
|
self.assertEqual(t.next_leaves(leaves[7]), [])
|
||||||
|
self.assertEqual(t.previous_leaves(leaves[0]), [])
|
||||||
|
|
||||||
|
def test_match(self):
|
||||||
|
self.checkFields(keywords, guess_info)
|
||||||
|
|
||||||
|
|
||||||
|
suite = allTests(TestMatchTree)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
TextTestRunner(verbosity=2).run(suite)
|
35
lib/guessit/test/test_movie.py
Normal file
35
lib/guessit/test/test_movie.py
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# GuessIt - A library for guessing information from filenames
|
||||||
|
# Copyright (c) 2013 Nicolas Wack <wackou@gmail.com>
|
||||||
|
#
|
||||||
|
# GuessIt is free software; you can redistribute it and/or modify it under
|
||||||
|
# the terms of the Lesser GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# GuessIt is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# Lesser GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the Lesser GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
|
from guessit.test.guessittest import *
|
||||||
|
|
||||||
|
|
||||||
|
class TestMovie(TestGuessit):
|
||||||
|
def testMovies(self):
|
||||||
|
self.checkMinimumFieldsCorrect(filetype='movie',
|
||||||
|
filename='movies.yaml')
|
||||||
|
|
||||||
|
|
||||||
|
suite = allTests(TestMovie)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
TextTestRunner(verbosity=2).run(suite)
|
126
lib/guessit/test/test_quality.py
Normal file
126
lib/guessit/test/test_quality.py
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# GuessIt - A library for guessing information from filenames
|
||||||
|
# Copyright (c) 2013 Nicolas Wack <wackou@gmail.com>
|
||||||
|
#
|
||||||
|
# GuessIt is free software; you can redistribute it and/or modify it under
|
||||||
|
# the terms of the Lesser GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# GuessIt is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# Lesser GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the Lesser GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
|
from guessit.quality import best_quality, best_quality_properties
|
||||||
|
from guessit.containers import QualitiesContainer
|
||||||
|
from guessit.test.guessittest import *
|
||||||
|
|
||||||
|
|
||||||
|
class TestQuality(TestGuessit):
|
||||||
|
def test_container(self):
|
||||||
|
container = QualitiesContainer()
|
||||||
|
|
||||||
|
container.register_quality('color', 'red', 10)
|
||||||
|
container.register_quality('color', 'orange', 20)
|
||||||
|
container.register_quality('color', 'green', 30)
|
||||||
|
|
||||||
|
container.register_quality('context', 'sun', 100)
|
||||||
|
container.register_quality('context', 'sea', 200)
|
||||||
|
container.register_quality('context', 'sex', 300)
|
||||||
|
|
||||||
|
g1 = Guess()
|
||||||
|
g1['color'] = 'red'
|
||||||
|
|
||||||
|
g2 = Guess()
|
||||||
|
g2['color'] = 'green'
|
||||||
|
|
||||||
|
g3 = Guess()
|
||||||
|
g3['color'] = 'orange'
|
||||||
|
|
||||||
|
q3 = container.rate_quality(g3)
|
||||||
|
self.assertEqual(q3, 20, "ORANGE should be rated 20. Don't ask why!")
|
||||||
|
|
||||||
|
q1 = container.rate_quality(g1)
|
||||||
|
q2 = container.rate_quality(g2)
|
||||||
|
|
||||||
|
self.assertTrue(q2 > q1, "GREEN should be greater than RED. Don't ask why!")
|
||||||
|
|
||||||
|
g1['context'] = 'sex'
|
||||||
|
g2['context'] = 'sun'
|
||||||
|
|
||||||
|
q1 = container.rate_quality(g1)
|
||||||
|
q2 = container.rate_quality(g2)
|
||||||
|
|
||||||
|
self.assertTrue(q1 > q2, "SEX should be greater than SUN. Don't ask why!")
|
||||||
|
|
||||||
|
self.assertEqual(container.best_quality(g1, g2), g1, "RED&SEX should be better than GREEN&SUN. Don't ask why!")
|
||||||
|
|
||||||
|
self.assertEqual(container.best_quality_properties(['color'], g1, g2), g2, "GREEN should be better than RED. Don't ask why!")
|
||||||
|
|
||||||
|
self.assertEqual(container.best_quality_properties(['context'], g1, g2), g1, "SEX should be better than SUN. Don't ask why!")
|
||||||
|
|
||||||
|
q1 = container.rate_quality(g1, 'color')
|
||||||
|
q2 = container.rate_quality(g2, 'color')
|
||||||
|
|
||||||
|
self.assertTrue(q2 > q1, "GREEN should be greater than RED. Don't ask why!")
|
||||||
|
|
||||||
|
container.unregister_quality('context', 'sex')
|
||||||
|
container.unregister_quality('context', 'sun')
|
||||||
|
|
||||||
|
q1 = container.rate_quality(g1)
|
||||||
|
q2 = container.rate_quality(g2)
|
||||||
|
|
||||||
|
self.assertTrue(q2 > q1, "GREEN&SUN should be greater than RED&SEX. Don't ask why!")
|
||||||
|
|
||||||
|
g3['context'] = 'sea'
|
||||||
|
container.unregister_quality('context', 'sea')
|
||||||
|
|
||||||
|
q3 = container.rate_quality(g3, 'context')
|
||||||
|
self.assertEqual(q3, 0, "Context should be unregistered.")
|
||||||
|
|
||||||
|
container.unregister_quality('color')
|
||||||
|
q3 = container.rate_quality(g3, 'color')
|
||||||
|
|
||||||
|
self.assertEqual(q3, 0, "Color should be unregistered.")
|
||||||
|
|
||||||
|
container.clear_qualities()
|
||||||
|
|
||||||
|
q1 = container.rate_quality(g1)
|
||||||
|
q2 = container.rate_quality(g2)
|
||||||
|
|
||||||
|
self.assertTrue(q1 == q2 == 0, "Empty quality container should rate each guess to 0")
|
||||||
|
|
||||||
|
def test_quality_transformers(self):
|
||||||
|
guess_720p = guessit.guess_file_info("2012.2009.720p.BluRay.x264.DTS WiKi.mkv")
|
||||||
|
guess_1080p = guessit.guess_file_info("2012.2009.1080p.BluRay.x264.MP3 WiKi.mkv")
|
||||||
|
|
||||||
|
self.assertTrue('audioCodec' in guess_720p, "audioCodec should be present")
|
||||||
|
self.assertTrue('audioCodec' in guess_1080p, "audioCodec should be present")
|
||||||
|
self.assertTrue('screenSize' in guess_720p, "screenSize should be present")
|
||||||
|
self.assertTrue('screenSize' in guess_1080p, "screenSize should be present")
|
||||||
|
|
||||||
|
best_quality_guess = best_quality(guess_720p, guess_1080p)
|
||||||
|
|
||||||
|
self.assertTrue(guess_1080p == best_quality_guess, "1080p+MP3 is not the best global quality")
|
||||||
|
|
||||||
|
best_quality_guess = best_quality_properties(['screenSize'], guess_720p, guess_1080p)
|
||||||
|
|
||||||
|
self.assertTrue(guess_1080p == best_quality_guess, "1080p is not the best screenSize")
|
||||||
|
|
||||||
|
best_quality_guess = best_quality_properties(['audioCodec'], guess_720p, guess_1080p)
|
||||||
|
|
||||||
|
self.assertTrue(guess_720p == best_quality_guess, "DTS is not the best audioCodec")
|
||||||
|
|
||||||
|
suite = allTests(TestQuality)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
TextTestRunner(verbosity=2).run(suite)
|
155
lib/guessit/test/test_utils.py
Normal file
155
lib/guessit/test/test_utils.py
Normal file
|
@ -0,0 +1,155 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# GuessIt - A library for guessing information from filenames
|
||||||
|
# Copyright (c) 2013 Nicolas Wack <wackou@gmail.com>
|
||||||
|
#
|
||||||
|
# GuessIt is free software; you can redistribute it and/or modify it under
|
||||||
|
# the terms of the Lesser GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# GuessIt is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# Lesser GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the Lesser GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
|
from guessit.test.guessittest import *
|
||||||
|
from guessit.fileutils import split_path
|
||||||
|
from guessit.textutils import strip_brackets, str_replace, str_fill, from_camel, is_camel,\
|
||||||
|
levenshtein, reorder_title
|
||||||
|
from guessit import PY2
|
||||||
|
from guessit.date import search_date, search_year
|
||||||
|
from datetime import datetime, date, timedelta
|
||||||
|
|
||||||
|
|
||||||
|
class TestUtils(TestGuessit):
|
||||||
|
def test_splitpath(self):
|
||||||
|
alltests = {False: {'/usr/bin/smewt': ['/', 'usr', 'bin', 'smewt'],
|
||||||
|
'relative_path/to/my_folder/': ['relative_path', 'to', 'my_folder'],
|
||||||
|
'//some/path': ['//', 'some', 'path'],
|
||||||
|
'//some//path': ['//', 'some', 'path'],
|
||||||
|
'///some////path': ['///', 'some', 'path']
|
||||||
|
|
||||||
|
},
|
||||||
|
True: {'C:\\Program Files\\Smewt\\smewt.exe': ['C:\\', 'Program Files', 'Smewt', 'smewt.exe'],
|
||||||
|
'Documents and Settings\\User\\config': ['Documents and Settings', 'User', 'config'],
|
||||||
|
'C:\\Documents and Settings\\User\\config': ['C:\\', 'Documents and Settings', 'User', 'config'],
|
||||||
|
# http://bugs.python.org/issue19945
|
||||||
|
'\\\\netdrive\\share': ['\\\\', 'netdrive', 'share'] if PY2 else ['\\\\netdrive\\share'],
|
||||||
|
'\\\\netdrive\\share\\folder': ['\\\\', 'netdrive', 'share', 'folder'] if PY2 else ['\\\\netdrive\\share\\', 'folder'],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tests = alltests[sys.platform == 'win32']
|
||||||
|
for path, split in tests.items():
|
||||||
|
self.assertEqual(split, split_path(path))
|
||||||
|
|
||||||
|
def test_strip_brackets(self):
|
||||||
|
allTests = (('', ''),
|
||||||
|
('[test]', 'test'),
|
||||||
|
('{test2}', 'test2'),
|
||||||
|
('(test3)', 'test3'),
|
||||||
|
('(test4]', '(test4]'),
|
||||||
|
)
|
||||||
|
|
||||||
|
for i, e in allTests:
|
||||||
|
self.assertEqual(e, strip_brackets(i))
|
||||||
|
|
||||||
|
def test_levenshtein(self):
|
||||||
|
self.assertEqual(levenshtein("abcdef ghijk lmno", "abcdef ghijk lmno"), 0)
|
||||||
|
self.assertEqual(levenshtein("abcdef ghijk lmnop", "abcdef ghijk lmno"), 1)
|
||||||
|
self.assertEqual(levenshtein("abcdef ghijk lmno", "abcdef ghijk lmn"), 1)
|
||||||
|
self.assertEqual(levenshtein("abcdef ghijk lmno", "abcdef ghijk lmnp"), 1)
|
||||||
|
self.assertEqual(levenshtein("abcdef ghijk lmno", "abcdef ghijk lmnq"), 1)
|
||||||
|
self.assertEqual(levenshtein("cbcdef ghijk lmno", "abcdef ghijk lmnq"), 2)
|
||||||
|
self.assertEqual(levenshtein("cbcdef ghihk lmno", "abcdef ghijk lmnq"), 3)
|
||||||
|
|
||||||
|
def test_reorder_title(self):
|
||||||
|
self.assertEqual(reorder_title("Simpsons, The"), "The Simpsons")
|
||||||
|
self.assertEqual(reorder_title("Simpsons,The"), "The Simpsons")
|
||||||
|
self.assertEqual(reorder_title("Simpsons,Les", articles=('the', 'le', 'la', 'les')), "Les Simpsons")
|
||||||
|
self.assertEqual(reorder_title("Simpsons, Les", articles=('the', 'le', 'la', 'les')), "Les Simpsons")
|
||||||
|
|
||||||
|
def test_camel(self):
|
||||||
|
self.assertEqual("", from_camel(""))
|
||||||
|
|
||||||
|
self.assertEqual("Hello world", str_replace("Hello World", 6, 'w'))
|
||||||
|
self.assertEqual("Hello *****", str_fill("Hello World", (6, 11), '*'))
|
||||||
|
|
||||||
|
self.assertTrue("This is camel", from_camel("ThisIsCamel"))
|
||||||
|
|
||||||
|
self.assertEqual('camel case', from_camel('camelCase'))
|
||||||
|
self.assertEqual('A case', from_camel('ACase'))
|
||||||
|
self.assertEqual('MiXedCaSe is not camel case', from_camel('MiXedCaSe is not camelCase'))
|
||||||
|
|
||||||
|
self.assertEqual("This is camel cased title", from_camel("ThisIsCamelCasedTitle"))
|
||||||
|
self.assertEqual("This is camel CASED title", from_camel("ThisIsCamelCASEDTitle"))
|
||||||
|
|
||||||
|
self.assertEqual("These are camel CASED title", from_camel("TheseAreCamelCASEDTitle"))
|
||||||
|
|
||||||
|
self.assertEqual("Give a camel case string", from_camel("GiveACamelCaseString"))
|
||||||
|
|
||||||
|
self.assertEqual("Death TO camel case", from_camel("DeathTOCamelCase"))
|
||||||
|
self.assertEqual("But i like java too:)", from_camel("ButILikeJavaToo:)"))
|
||||||
|
|
||||||
|
self.assertEqual("Beatdown french DVD rip.mkv", from_camel("BeatdownFrenchDVDRip.mkv"))
|
||||||
|
self.assertEqual("DO NOTHING ON UPPER CASE", from_camel("DO NOTHING ON UPPER CASE"))
|
||||||
|
|
||||||
|
self.assertFalse(is_camel("this_is_not_camel"))
|
||||||
|
self.assertTrue(is_camel("ThisIsCamel"))
|
||||||
|
|
||||||
|
self.assertEqual("Dark.City.(1998).DC.BDRIP.720p.DTS.X264-CHD.mkv", from_camel("Dark.City.(1998).DC.BDRIP.720p.DTS.X264-CHD.mkv"))
|
||||||
|
self.assertFalse(is_camel("Dark.City.(1998).DC.BDRIP.720p.DTS.X264-CHD.mkv"))
|
||||||
|
|
||||||
|
self.assertEqual("A2LiNE", from_camel("A2LiNE"))
|
||||||
|
|
||||||
|
def test_date(self):
|
||||||
|
self.assertEqual(search_year(' in the year 2000... '), (2000, (13, 17)))
|
||||||
|
self.assertEqual(search_year(' they arrived in 1492. '), (None, None))
|
||||||
|
|
||||||
|
today = date.today()
|
||||||
|
today_year_2 = int(str(today.year)[2:])
|
||||||
|
|
||||||
|
future = today + timedelta(days=1000)
|
||||||
|
future_year_2 = int(str(future.year)[2:])
|
||||||
|
|
||||||
|
past = today - timedelta(days=10000)
|
||||||
|
past_year_2 = int(str(past.year)[2:])
|
||||||
|
|
||||||
|
self.assertEqual(search_date(' Something before 2002-04-22 '), (date(2002, 4, 22), (18, 28)))
|
||||||
|
self.assertEqual(search_date(' 2002-04-22 Something after '), (date(2002, 4, 22), (1, 11)))
|
||||||
|
|
||||||
|
self.assertEqual(search_date(' This happened on 2002-04-22. '), (date(2002, 4, 22), (18, 28)))
|
||||||
|
self.assertEqual(search_date(' This happened on 22-04-2002. '), (date(2002, 4, 22), (18, 28)))
|
||||||
|
|
||||||
|
self.assertEqual(search_date(' This happened on 13-04-%s. ' % (today_year_2,)), (date(today.year, 4, 13), (18, 26)))
|
||||||
|
self.assertEqual(search_date(' This happened on 22-04-%s. ' % (future_year_2,)), (date(future.year, 4, 22), (18, 26)))
|
||||||
|
self.assertEqual(search_date(' This happened on 20-04-%s. ' % (past_year_2)), (date(past.year, 4, 20), (18, 26)))
|
||||||
|
|
||||||
|
self.assertEqual(search_date(' This happened on 04-13-%s. ' % (today_year_2,)), (date(today.year, 4, 13), (18, 26)))
|
||||||
|
self.assertEqual(search_date(' This happened on 04-22-%s. ' % (future_year_2,)), (date(future.year, 4, 22), (18, 26)))
|
||||||
|
self.assertEqual(search_date(' This happened on 04-20-%s. ' % (past_year_2)), (date(past.year, 4, 20), (18, 26)))
|
||||||
|
|
||||||
|
self.assertEqual(search_date(' This happened on 35-12-%s. ' % (today_year_2,)), (None, None))
|
||||||
|
self.assertEqual(search_date(' This happened on 37-18-%s. ' % (future_year_2,)), (None, None))
|
||||||
|
self.assertEqual(search_date(' This happened on 44-42-%s. ' % (past_year_2)), (None, None))
|
||||||
|
|
||||||
|
self.assertEqual(search_date(' This happened on %s. ' % (today, )), (today, (18, 28)))
|
||||||
|
self.assertEqual(search_date(' This happened on %s. ' % (future, )), (future, (18, 28)))
|
||||||
|
self.assertEqual(search_date(' This happened on %s. ' % (past, )), (past, (18, 28)))
|
||||||
|
|
||||||
|
self.assertEqual(search_date(' released date: 04-03-1901? '), (None, None))
|
||||||
|
|
||||||
|
self.assertEqual(search_date(' There\'s no date in here. '), (None, None))
|
||||||
|
|
||||||
|
|
||||||
|
suite = allTests(TestUtils)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
TextTestRunner(verbosity=2).run(suite)
|
0
lib/stevedore/example/__init__.py
Normal file
0
lib/stevedore/example/__init__.py
Normal file
21
lib/stevedore/example/base.py
Normal file
21
lib/stevedore/example/base.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import abc
|
||||||
|
|
||||||
|
|
||||||
|
class FormatterBase(object):
|
||||||
|
"""Base class for example plugin used in the tutoral.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__metaclass__ = abc.ABCMeta
|
||||||
|
|
||||||
|
def __init__(self, max_width=60):
|
||||||
|
self.max_width = max_width
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def format(self, data):
|
||||||
|
"""Format the data and return unicode text.
|
||||||
|
|
||||||
|
:param data: A dictionary with string keys and simple types as
|
||||||
|
values.
|
||||||
|
:type data: dict(str:?)
|
||||||
|
:returns: Iterable producing the formatted text.
|
||||||
|
"""
|
36
lib/stevedore/example/fields.py
Normal file
36
lib/stevedore/example/fields.py
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
import textwrap
|
||||||
|
|
||||||
|
from stevedore.example import base
|
||||||
|
|
||||||
|
|
||||||
|
class FieldList(base.FormatterBase):
|
||||||
|
"""Format values as a reStructuredText field list.
|
||||||
|
|
||||||
|
For example::
|
||||||
|
|
||||||
|
: name1 : value
|
||||||
|
: name2 : value
|
||||||
|
: name3 : a long value
|
||||||
|
will be wrapped with
|
||||||
|
a hanging indent
|
||||||
|
"""
|
||||||
|
|
||||||
|
def format(self, data):
|
||||||
|
"""Format the data and return unicode text.
|
||||||
|
|
||||||
|
:param data: A dictionary with string keys and simple types as
|
||||||
|
values.
|
||||||
|
:type data: dict(str:?)
|
||||||
|
"""
|
||||||
|
for name, value in sorted(data.items()):
|
||||||
|
full_text = ': {name} : {value}'.format(
|
||||||
|
name=name,
|
||||||
|
value=value,
|
||||||
|
)
|
||||||
|
wrapped_text = textwrap.fill(
|
||||||
|
full_text,
|
||||||
|
initial_indent='',
|
||||||
|
subsequent_indent=' ',
|
||||||
|
width=self.max_width,
|
||||||
|
)
|
||||||
|
yield wrapped_text + '\n'
|
37
lib/stevedore/example/load_as_driver.py
Normal file
37
lib/stevedore/example/load_as_driver.py
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
from stevedore import driver
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument(
|
||||||
|
'format',
|
||||||
|
nargs='?',
|
||||||
|
default='simple',
|
||||||
|
help='the output format',
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--width',
|
||||||
|
default=60,
|
||||||
|
type=int,
|
||||||
|
help='maximum output width for text',
|
||||||
|
)
|
||||||
|
parsed_args = parser.parse_args()
|
||||||
|
|
||||||
|
data = {
|
||||||
|
'a': 'A',
|
||||||
|
'b': 'B',
|
||||||
|
'long': 'word ' * 80,
|
||||||
|
}
|
||||||
|
|
||||||
|
mgr = driver.DriverManager(
|
||||||
|
namespace='stevedore.example.formatter',
|
||||||
|
name=parsed_args.format,
|
||||||
|
invoke_on_load=True,
|
||||||
|
invoke_args=(parsed_args.width,),
|
||||||
|
)
|
||||||
|
for chunk in mgr.driver.format(data):
|
||||||
|
print(chunk, end='')
|
39
lib/stevedore/example/load_as_extension.py
Normal file
39
lib/stevedore/example/load_as_extension.py
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
from stevedore import extension
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument(
|
||||||
|
'--width',
|
||||||
|
default=60,
|
||||||
|
type=int,
|
||||||
|
help='maximum output width for text',
|
||||||
|
)
|
||||||
|
parsed_args = parser.parse_args()
|
||||||
|
|
||||||
|
data = {
|
||||||
|
'a': 'A',
|
||||||
|
'b': 'B',
|
||||||
|
'long': 'word ' * 80,
|
||||||
|
}
|
||||||
|
|
||||||
|
mgr = extension.ExtensionManager(
|
||||||
|
namespace='stevedore.example.formatter',
|
||||||
|
invoke_on_load=True,
|
||||||
|
invoke_args=(parsed_args.width,),
|
||||||
|
)
|
||||||
|
|
||||||
|
def format_data(ext, data):
|
||||||
|
return (ext.name, ext.obj.format(data))
|
||||||
|
|
||||||
|
results = mgr.map(format_data, data)
|
||||||
|
|
||||||
|
for name, result in results:
|
||||||
|
print('Formatter: {0}'.format(name))
|
||||||
|
for chunk in result:
|
||||||
|
print(chunk, end='')
|
||||||
|
print('')
|
46
lib/stevedore/example/setup.py
Normal file
46
lib/stevedore/example/setup.py
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name='stevedore-examples',
|
||||||
|
version='1.0',
|
||||||
|
|
||||||
|
description='Demonstration package for stevedore',
|
||||||
|
|
||||||
|
author='Doug Hellmann',
|
||||||
|
author_email='doug.hellmann@dreamhost.com',
|
||||||
|
|
||||||
|
url='https://github.com/dreamhost/stevedore',
|
||||||
|
download_url='https://github.com/dreamhost/stevedore/tarball/master',
|
||||||
|
|
||||||
|
classifiers=['Development Status :: 3 - Alpha',
|
||||||
|
'License :: OSI Approved :: Apache Software License',
|
||||||
|
'Programming Language :: Python',
|
||||||
|
'Programming Language :: Python :: 2',
|
||||||
|
'Programming Language :: Python :: 2.7',
|
||||||
|
'Programming Language :: Python :: 3',
|
||||||
|
'Programming Language :: Python :: 3.2',
|
||||||
|
'Programming Language :: Python :: 3.3',
|
||||||
|
'Intended Audience :: Developers',
|
||||||
|
'Environment :: Console',
|
||||||
|
],
|
||||||
|
|
||||||
|
platforms=['Any'],
|
||||||
|
|
||||||
|
scripts=[],
|
||||||
|
|
||||||
|
provides=['stevedore.examples',
|
||||||
|
],
|
||||||
|
|
||||||
|
packages=find_packages(),
|
||||||
|
include_package_data=True,
|
||||||
|
|
||||||
|
entry_points={
|
||||||
|
'stevedore.example.formatter': [
|
||||||
|
'simple = stevedore.example.simple:Simple',
|
||||||
|
'field = stevedore.example.fields:FieldList',
|
||||||
|
'plain = stevedore.example.simple:Simple',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
zip_safe=False,
|
||||||
|
)
|
20
lib/stevedore/example/simple.py
Normal file
20
lib/stevedore/example/simple.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
from stevedore.example import base
|
||||||
|
|
||||||
|
|
||||||
|
class Simple(base.FormatterBase):
|
||||||
|
"""A very basic formatter.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def format(self, data):
|
||||||
|
"""Format the data and return unicode text.
|
||||||
|
|
||||||
|
:param data: A dictionary with string keys and simple types as
|
||||||
|
values.
|
||||||
|
:type data: dict(str:?)
|
||||||
|
"""
|
||||||
|
for name, value in sorted(data.items()):
|
||||||
|
line = '{name} = {value}\n'.format(
|
||||||
|
name=name,
|
||||||
|
value=value,
|
||||||
|
)
|
||||||
|
yield line
|
0
lib/stevedore/tests/__init__.py
Normal file
0
lib/stevedore/tests/__init__.py
Normal file
59
lib/stevedore/tests/manager.py
Normal file
59
lib/stevedore/tests/manager.py
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
"""TestExtensionManager
|
||||||
|
|
||||||
|
Extension manager used only for testing.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
from stevedore import extension
|
||||||
|
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class TestExtensionManager(extension.ExtensionManager):
|
||||||
|
"""ExtensionManager that is explicitly initialized for tests.
|
||||||
|
|
||||||
|
.. deprecated:: 0.13
|
||||||
|
|
||||||
|
Use the :func:`make_test_instance` class method of the class
|
||||||
|
being replaced by the test instance instead of using this class
|
||||||
|
directly.
|
||||||
|
|
||||||
|
:param extensions: Pre-configured Extension instances to use
|
||||||
|
instead of loading them from entry points.
|
||||||
|
:type extensions: list of :class:`~stevedore.extension.Extension`
|
||||||
|
:param namespace: The namespace for the entry points.
|
||||||
|
:type namespace: str
|
||||||
|
:param invoke_on_load: Boolean controlling whether to invoke the
|
||||||
|
object returned by the entry point after the driver is loaded.
|
||||||
|
:type invoke_on_load: bool
|
||||||
|
:param invoke_args: Positional arguments to pass when invoking
|
||||||
|
the object returned by the entry point. Only used if invoke_on_load
|
||||||
|
is True.
|
||||||
|
:type invoke_args: tuple
|
||||||
|
:param invoke_kwds: Named arguments to pass when invoking
|
||||||
|
the object returned by the entry point. Only used if invoke_on_load
|
||||||
|
is True.
|
||||||
|
:type invoke_kwds: dict
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, extensions,
|
||||||
|
namespace='test',
|
||||||
|
invoke_on_load=False,
|
||||||
|
invoke_args=(),
|
||||||
|
invoke_kwds={}):
|
||||||
|
super(TestExtensionManager, self).__init__(namespace,
|
||||||
|
invoke_on_load,
|
||||||
|
invoke_args,
|
||||||
|
invoke_kwds,
|
||||||
|
)
|
||||||
|
self.extensions = extensions
|
||||||
|
warnings.warn(
|
||||||
|
'TestExtesionManager has been replaced by make_test_instance()',
|
||||||
|
DeprecationWarning)
|
||||||
|
|
||||||
|
def _load_plugins(self, *args, **kwds):
|
||||||
|
return []
|
21
lib/stevedore/tests/test_callback.py
Normal file
21
lib/stevedore/tests/test_callback.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
"""Tests for failure loading callback
|
||||||
|
"""
|
||||||
|
|
||||||
|
from stevedore import extension
|
||||||
|
|
||||||
|
|
||||||
|
def test_extension_failure_custom_callback():
|
||||||
|
errors = []
|
||||||
|
|
||||||
|
def failure_callback(manager, entrypoint, error):
|
||||||
|
errors.append((manager, entrypoint, error))
|
||||||
|
|
||||||
|
em = extension.ExtensionManager('stevedore.test.extension',
|
||||||
|
invoke_on_load=True,
|
||||||
|
on_load_failure_callback=failure_callback)
|
||||||
|
extensions = list(em.extensions)
|
||||||
|
assert len(extensions) > 0
|
||||||
|
assert len(errors) == 1
|
||||||
|
(manager, entrypoint, error) = errors[0]
|
||||||
|
assert manager is em
|
||||||
|
assert isinstance(error, IOError)
|
103
lib/stevedore/tests/test_dispatch.py
Normal file
103
lib/stevedore/tests/test_dispatch.py
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
from stevedore import dispatch
|
||||||
|
|
||||||
|
|
||||||
|
def check_dispatch(ep, *args, **kwds):
|
||||||
|
return ep.name == 't2'
|
||||||
|
|
||||||
|
|
||||||
|
def test_dispatch():
|
||||||
|
|
||||||
|
def invoke(ep, *args, **kwds):
|
||||||
|
return (ep.name, args, kwds)
|
||||||
|
|
||||||
|
em = dispatch.DispatchExtensionManager(
|
||||||
|
'stevedore.test.extension',
|
||||||
|
lambda *args, **kwds: True,
|
||||||
|
invoke_on_load=True,
|
||||||
|
invoke_args=('a',),
|
||||||
|
invoke_kwds={'b': 'B'},
|
||||||
|
)
|
||||||
|
assert len(em.extensions) == 2
|
||||||
|
assert set(em.names()) == set(['t1', 't2'])
|
||||||
|
|
||||||
|
results = em.map(check_dispatch,
|
||||||
|
invoke,
|
||||||
|
'first',
|
||||||
|
named='named value',
|
||||||
|
)
|
||||||
|
expected = [('t2', ('first',), {'named': 'named value'})]
|
||||||
|
assert results == expected
|
||||||
|
|
||||||
|
|
||||||
|
def test_dispatch_map_method():
|
||||||
|
em = dispatch.DispatchExtensionManager(
|
||||||
|
'stevedore.test.extension',
|
||||||
|
lambda *args, **kwds: True,
|
||||||
|
invoke_on_load=True,
|
||||||
|
invoke_args=('a',),
|
||||||
|
invoke_kwds={'b': 'B'},
|
||||||
|
)
|
||||||
|
|
||||||
|
results = em.map_method(check_dispatch, 'get_args_and_data',
|
||||||
|
'first')
|
||||||
|
assert results == [(('a',), {'b': 'B'}, 'first')]
|
||||||
|
|
||||||
|
|
||||||
|
def test_name_dispatch():
|
||||||
|
|
||||||
|
def invoke(ep, *args, **kwds):
|
||||||
|
return (ep.name, args, kwds)
|
||||||
|
|
||||||
|
em = dispatch.NameDispatchExtensionManager(
|
||||||
|
'stevedore.test.extension',
|
||||||
|
lambda *args, **kwds: True,
|
||||||
|
invoke_on_load=True,
|
||||||
|
invoke_args=('a',),
|
||||||
|
invoke_kwds={'b': 'B'},
|
||||||
|
)
|
||||||
|
assert len(em.extensions) == 2
|
||||||
|
assert set(em.names()) == set(['t1', 't2'])
|
||||||
|
|
||||||
|
results = em.map(['t2'],
|
||||||
|
invoke,
|
||||||
|
'first',
|
||||||
|
named='named value',
|
||||||
|
)
|
||||||
|
expected = [('t2', ('first',), {'named': 'named value'})]
|
||||||
|
assert results == expected
|
||||||
|
|
||||||
|
|
||||||
|
def test_name_dispatch_ignore_missing():
|
||||||
|
|
||||||
|
def invoke(ep, *args, **kwds):
|
||||||
|
return (ep.name, args, kwds)
|
||||||
|
|
||||||
|
em = dispatch.NameDispatchExtensionManager(
|
||||||
|
'stevedore.test.extension',
|
||||||
|
lambda *args, **kwds: True,
|
||||||
|
invoke_on_load=True,
|
||||||
|
invoke_args=('a',),
|
||||||
|
invoke_kwds={'b': 'B'},
|
||||||
|
)
|
||||||
|
|
||||||
|
results = em.map(['t3', 't1'],
|
||||||
|
invoke,
|
||||||
|
'first',
|
||||||
|
named='named value',
|
||||||
|
)
|
||||||
|
expected = [('t1', ('first',), {'named': 'named value'})]
|
||||||
|
assert results == expected
|
||||||
|
|
||||||
|
|
||||||
|
def test_name_dispatch_map_method():
|
||||||
|
em = dispatch.NameDispatchExtensionManager(
|
||||||
|
'stevedore.test.extension',
|
||||||
|
lambda *args, **kwds: True,
|
||||||
|
invoke_on_load=True,
|
||||||
|
invoke_args=('a',),
|
||||||
|
invoke_kwds={'b': 'B'},
|
||||||
|
)
|
||||||
|
|
||||||
|
results = em.map_method(['t3', 't1'], 'get_args_and_data',
|
||||||
|
'first')
|
||||||
|
assert results == [(('a',), {'b': 'B'}, 'first')]
|
61
lib/stevedore/tests/test_driver.py
Normal file
61
lib/stevedore/tests/test_driver.py
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
"""Tests for stevedore.extension
|
||||||
|
"""
|
||||||
|
|
||||||
|
import mock
|
||||||
|
import pkg_resources
|
||||||
|
|
||||||
|
from stevedore import driver
|
||||||
|
from stevedore.tests import test_extension
|
||||||
|
|
||||||
|
|
||||||
|
def test_detect_plugins():
|
||||||
|
em = driver.DriverManager('stevedore.test.extension', 't1')
|
||||||
|
names = sorted(em.names())
|
||||||
|
assert names == ['t1']
|
||||||
|
|
||||||
|
|
||||||
|
def test_call():
|
||||||
|
def invoke(ext, *args, **kwds):
|
||||||
|
return (ext.name, args, kwds)
|
||||||
|
em = driver.DriverManager('stevedore.test.extension', 't1')
|
||||||
|
result = em(invoke, 'a', b='C')
|
||||||
|
assert result == ('t1', ('a',), {'b': 'C'})
|
||||||
|
|
||||||
|
|
||||||
|
def test_driver_property_not_invoked_on_load():
|
||||||
|
em = driver.DriverManager('stevedore.test.extension', 't1',
|
||||||
|
invoke_on_load=False)
|
||||||
|
d = em.driver
|
||||||
|
assert d is test_extension.FauxExtension
|
||||||
|
|
||||||
|
|
||||||
|
def test_driver_property_invoked_on_load():
|
||||||
|
em = driver.DriverManager('stevedore.test.extension', 't1',
|
||||||
|
invoke_on_load=True)
|
||||||
|
d = em.driver
|
||||||
|
assert isinstance(d, test_extension.FauxExtension)
|
||||||
|
|
||||||
|
|
||||||
|
def test_no_drivers():
|
||||||
|
try:
|
||||||
|
driver.DriverManager('stevedore.test.extension.none', 't1')
|
||||||
|
except RuntimeError as err:
|
||||||
|
assert "No 'stevedore.test.extension.none' driver found" in str(err)
|
||||||
|
|
||||||
|
|
||||||
|
def test_multiple_drivers():
|
||||||
|
# The idea for this test was contributed by clayg:
|
||||||
|
# https://gist.github.com/clayg/6311348
|
||||||
|
fep_name = 'stevedore.extension.ExtensionManager._find_entry_points'
|
||||||
|
with mock.patch(fep_name) as fep:
|
||||||
|
fep.return_value = [
|
||||||
|
pkg_resources.EntryPoint.parse('backend = pkg1:driver'),
|
||||||
|
pkg_resources.EntryPoint.parse('backend = pkg2:driver'),
|
||||||
|
]
|
||||||
|
for ep in fep.return_value:
|
||||||
|
ep.load = lambda *args, **kwds: 'pkg backend'
|
||||||
|
try:
|
||||||
|
driver.DriverManager('stevedore.test.multiple_drivers', 'backend')
|
||||||
|
except RuntimeError as err:
|
||||||
|
assert "Multiple" in str(err), str(err)
|
||||||
|
fep.assert_called_with('stevedore.test.multiple_drivers')
|
29
lib/stevedore/tests/test_enabled.py
Normal file
29
lib/stevedore/tests/test_enabled.py
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
from stevedore import enabled
|
||||||
|
|
||||||
|
|
||||||
|
def test_enabled():
|
||||||
|
def check_enabled(ep):
|
||||||
|
return ep.name == 't2'
|
||||||
|
em = enabled.EnabledExtensionManager(
|
||||||
|
'stevedore.test.extension',
|
||||||
|
check_enabled,
|
||||||
|
invoke_on_load=True,
|
||||||
|
invoke_args=('a',),
|
||||||
|
invoke_kwds={'b': 'B'},
|
||||||
|
)
|
||||||
|
assert len(em.extensions) == 1
|
||||||
|
assert em.names() == ['t2']
|
||||||
|
|
||||||
|
|
||||||
|
def test_enabled_after_load():
|
||||||
|
def check_enabled(ext):
|
||||||
|
return ext.obj and ext.name == 't2'
|
||||||
|
em = enabled.EnabledExtensionManager(
|
||||||
|
'stevedore.test.extension',
|
||||||
|
check_enabled,
|
||||||
|
invoke_on_load=True,
|
||||||
|
invoke_args=('a',),
|
||||||
|
invoke_kwds={'b': 'B'},
|
||||||
|
)
|
||||||
|
assert len(em.extensions) == 1
|
||||||
|
assert em.names() == ['t2']
|
27
lib/stevedore/tests/test_example_fields.py
Normal file
27
lib/stevedore/tests/test_example_fields.py
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
"""Tests for stevedore.exmaple.fields
|
||||||
|
"""
|
||||||
|
|
||||||
|
from stevedore.example import fields
|
||||||
|
|
||||||
|
|
||||||
|
def test_simple_items():
|
||||||
|
f = fields.FieldList(100)
|
||||||
|
text = ''.join(f.format({'a': 'A', 'b': 'B'}))
|
||||||
|
expected = '\n'.join([
|
||||||
|
': a : A',
|
||||||
|
': b : B',
|
||||||
|
'',
|
||||||
|
])
|
||||||
|
assert text == expected
|
||||||
|
|
||||||
|
|
||||||
|
def test_long_item():
|
||||||
|
f = fields.FieldList(25)
|
||||||
|
text = ''.join(f.format({'name': 'a value longer than the allowed width'}))
|
||||||
|
expected = '\n'.join([
|
||||||
|
': name : a value longer',
|
||||||
|
' than the allowed',
|
||||||
|
' width',
|
||||||
|
'',
|
||||||
|
])
|
||||||
|
assert text == expected
|
15
lib/stevedore/tests/test_example_simple.py
Normal file
15
lib/stevedore/tests/test_example_simple.py
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
"""Tests for stevedore.exmaple.simple
|
||||||
|
"""
|
||||||
|
|
||||||
|
from stevedore.example import simple
|
||||||
|
|
||||||
|
|
||||||
|
def test_simple_items():
|
||||||
|
f = simple.Simple(100)
|
||||||
|
text = ''.join(f.format({'a': 'A', 'b': 'B'}))
|
||||||
|
expected = '\n'.join([
|
||||||
|
'a = A',
|
||||||
|
'b = B',
|
||||||
|
'',
|
||||||
|
])
|
||||||
|
assert text == expected
|
177
lib/stevedore/tests/test_extension.py
Normal file
177
lib/stevedore/tests/test_extension.py
Normal file
|
@ -0,0 +1,177 @@
|
||||||
|
"""Tests for stevedore.extension
|
||||||
|
"""
|
||||||
|
|
||||||
|
import mock
|
||||||
|
|
||||||
|
from stevedore import extension
|
||||||
|
|
||||||
|
ALL_NAMES = ['e1', 't1', 't2']
|
||||||
|
WORKING_NAMES = ['t1', 't2']
|
||||||
|
|
||||||
|
|
||||||
|
class FauxExtension(object):
|
||||||
|
def __init__(self, *args, **kwds):
|
||||||
|
self.args = args
|
||||||
|
self.kwds = kwds
|
||||||
|
|
||||||
|
def get_args_and_data(self, data):
|
||||||
|
return self.args, self.kwds, data
|
||||||
|
|
||||||
|
|
||||||
|
class BrokenExtension(object):
|
||||||
|
def __init__(self, *args, **kwds):
|
||||||
|
raise IOError("Did not create")
|
||||||
|
|
||||||
|
|
||||||
|
def test_detect_plugins():
|
||||||
|
em = extension.ExtensionManager('stevedore.test.extension')
|
||||||
|
names = sorted(em.names())
|
||||||
|
assert names == ALL_NAMES
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_by_name():
|
||||||
|
em = extension.ExtensionManager('stevedore.test.extension')
|
||||||
|
e = em['t1']
|
||||||
|
assert e.name == 't1'
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_by_name_missing():
|
||||||
|
em = extension.ExtensionManager('stevedore.test.extension')
|
||||||
|
try:
|
||||||
|
em['t3']
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
assert False, 'Failed to raise KeyError'
|
||||||
|
|
||||||
|
|
||||||
|
def test_load_multiple_times_entry_points():
|
||||||
|
# We expect to get the same EntryPoint object because we save them
|
||||||
|
# in the cache.
|
||||||
|
em1 = extension.ExtensionManager('stevedore.test.extension')
|
||||||
|
eps1 = [ext.entry_point for ext in em1]
|
||||||
|
em2 = extension.ExtensionManager('stevedore.test.extension')
|
||||||
|
eps2 = [ext.entry_point for ext in em2]
|
||||||
|
assert eps1[0] is eps2[0]
|
||||||
|
|
||||||
|
|
||||||
|
def test_load_multiple_times_plugins():
|
||||||
|
# We expect to get the same plugin object (module or class)
|
||||||
|
# because the underlying import machinery will cache the values.
|
||||||
|
em1 = extension.ExtensionManager('stevedore.test.extension')
|
||||||
|
plugins1 = [ext.plugin for ext in em1]
|
||||||
|
em2 = extension.ExtensionManager('stevedore.test.extension')
|
||||||
|
plugins2 = [ext.plugin for ext in em2]
|
||||||
|
assert plugins1[0] is plugins2[0]
|
||||||
|
|
||||||
|
|
||||||
|
def test_use_cache():
|
||||||
|
# If we insert something into the cache of entry points,
|
||||||
|
# the manager should not have to call into pkg_resources
|
||||||
|
# to find the plugins.
|
||||||
|
cache = extension.ExtensionManager.ENTRY_POINT_CACHE
|
||||||
|
cache['stevedore.test.faux'] = []
|
||||||
|
with mock.patch('pkg_resources.iter_entry_points',
|
||||||
|
side_effect=AssertionError('called iter_entry_points')):
|
||||||
|
em = extension.ExtensionManager('stevedore.test.faux')
|
||||||
|
names = em.names()
|
||||||
|
assert names == []
|
||||||
|
|
||||||
|
|
||||||
|
def test_iterable():
|
||||||
|
em = extension.ExtensionManager('stevedore.test.extension')
|
||||||
|
names = sorted(e.name for e in em)
|
||||||
|
assert names == ALL_NAMES
|
||||||
|
|
||||||
|
|
||||||
|
def test_invoke_on_load():
|
||||||
|
em = extension.ExtensionManager('stevedore.test.extension',
|
||||||
|
invoke_on_load=True,
|
||||||
|
invoke_args=('a',),
|
||||||
|
invoke_kwds={'b': 'B'},
|
||||||
|
)
|
||||||
|
assert len(em.extensions) == 2
|
||||||
|
for e in em.extensions:
|
||||||
|
assert e.obj.args == ('a',)
|
||||||
|
assert e.obj.kwds == {'b': 'B'}
|
||||||
|
|
||||||
|
|
||||||
|
def test_map_return_values():
|
||||||
|
def mapped(ext, *args, **kwds):
|
||||||
|
return ext.name
|
||||||
|
|
||||||
|
em = extension.ExtensionManager('stevedore.test.extension',
|
||||||
|
invoke_on_load=True,
|
||||||
|
)
|
||||||
|
results = em.map(mapped)
|
||||||
|
assert sorted(results) == WORKING_NAMES
|
||||||
|
|
||||||
|
|
||||||
|
def test_map_arguments():
|
||||||
|
objs = []
|
||||||
|
|
||||||
|
def mapped(ext, *args, **kwds):
|
||||||
|
objs.append((ext, args, kwds))
|
||||||
|
|
||||||
|
em = extension.ExtensionManager('stevedore.test.extension',
|
||||||
|
invoke_on_load=True,
|
||||||
|
)
|
||||||
|
em.map(mapped, 1, 2, a='A', b='B')
|
||||||
|
assert len(objs) == 2
|
||||||
|
names = sorted([o[0].name for o in objs])
|
||||||
|
assert names == WORKING_NAMES
|
||||||
|
for o in objs:
|
||||||
|
assert o[1] == (1, 2)
|
||||||
|
assert o[2] == {'a': 'A', 'b': 'B'}
|
||||||
|
|
||||||
|
|
||||||
|
def test_map_eats_errors():
|
||||||
|
|
||||||
|
def mapped(ext, *args, **kwds):
|
||||||
|
raise RuntimeError('hard coded error')
|
||||||
|
|
||||||
|
em = extension.ExtensionManager('stevedore.test.extension',
|
||||||
|
invoke_on_load=True,
|
||||||
|
)
|
||||||
|
results = em.map(mapped, 1, 2, a='A', b='B')
|
||||||
|
assert results == []
|
||||||
|
|
||||||
|
|
||||||
|
def test_map_propagate_exceptions():
|
||||||
|
|
||||||
|
def mapped(ext, *args, **kwds):
|
||||||
|
raise RuntimeError('hard coded error')
|
||||||
|
|
||||||
|
em = extension.ExtensionManager('stevedore.test.extension',
|
||||||
|
invoke_on_load=True,
|
||||||
|
propagate_map_exceptions=True
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
em.map(mapped, 1, 2, a='A', b='B')
|
||||||
|
assert False
|
||||||
|
except RuntimeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def test_map_errors_when_no_plugins():
|
||||||
|
|
||||||
|
def mapped(ext, *args, **kwds):
|
||||||
|
pass
|
||||||
|
|
||||||
|
em = extension.ExtensionManager('stevedore.test.extension.none',
|
||||||
|
invoke_on_load=True,
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
em.map(mapped, 1, 2, a='A', b='B')
|
||||||
|
except RuntimeError as err:
|
||||||
|
assert 'No stevedore.test.extension.none extensions found' == str(err)
|
||||||
|
|
||||||
|
|
||||||
|
def test_map_method():
|
||||||
|
em = extension.ExtensionManager('stevedore.test.extension',
|
||||||
|
invoke_on_load=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
result = em.map_method('get_args_and_data', 42)
|
||||||
|
assert set(r[2] for r in result) == set([42])
|
43
lib/stevedore/tests/test_hook.py
Normal file
43
lib/stevedore/tests/test_hook.py
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
from stevedore import hook
|
||||||
|
|
||||||
|
|
||||||
|
def test_hook():
|
||||||
|
em = hook.HookManager(
|
||||||
|
'stevedore.test.extension',
|
||||||
|
't1',
|
||||||
|
invoke_on_load=True,
|
||||||
|
invoke_args=('a',),
|
||||||
|
invoke_kwds={'b': 'B'},
|
||||||
|
)
|
||||||
|
assert len(em.extensions) == 1
|
||||||
|
assert em.names() == ['t1']
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_by_name():
|
||||||
|
em = hook.HookManager(
|
||||||
|
'stevedore.test.extension',
|
||||||
|
't1',
|
||||||
|
invoke_on_load=True,
|
||||||
|
invoke_args=('a',),
|
||||||
|
invoke_kwds={'b': 'B'},
|
||||||
|
)
|
||||||
|
e_list = em['t1']
|
||||||
|
assert len(e_list) == 1
|
||||||
|
e = e_list[0]
|
||||||
|
assert e.name == 't1'
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_by_name_missing():
|
||||||
|
em = hook.HookManager(
|
||||||
|
'stevedore.test.extension',
|
||||||
|
't1',
|
||||||
|
invoke_on_load=True,
|
||||||
|
invoke_args=('a',),
|
||||||
|
invoke_kwds={'b': 'B'},
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
em['t2']
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
assert False, 'Failed to raise KeyError'
|
58
lib/stevedore/tests/test_named.py
Normal file
58
lib/stevedore/tests/test_named.py
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
from stevedore import named
|
||||||
|
|
||||||
|
import mock
|
||||||
|
|
||||||
|
|
||||||
|
def test_named():
|
||||||
|
em = named.NamedExtensionManager(
|
||||||
|
'stevedore.test.extension',
|
||||||
|
names=['t1'],
|
||||||
|
invoke_on_load=True,
|
||||||
|
invoke_args=('a',),
|
||||||
|
invoke_kwds={'b': 'B'},
|
||||||
|
)
|
||||||
|
actual = em.names()
|
||||||
|
assert actual == ['t1']
|
||||||
|
|
||||||
|
|
||||||
|
def test_enabled_before_load():
|
||||||
|
# Set up the constructor for the FauxExtension to cause an
|
||||||
|
# AssertionError so the test fails if the class is instantiated,
|
||||||
|
# which should only happen if it is loaded before the name of the
|
||||||
|
# extension is compared against the names that should be loaded by
|
||||||
|
# the manager.
|
||||||
|
init_name = 'stevedore.tests.test_extension.FauxExtension.__init__'
|
||||||
|
with mock.patch(init_name) as m:
|
||||||
|
m.side_effect = AssertionError
|
||||||
|
em = named.NamedExtensionManager(
|
||||||
|
'stevedore.test.extension',
|
||||||
|
# Look for an extension that does not exist so the
|
||||||
|
# __init__ we mocked should never be invoked.
|
||||||
|
names=['no-such-extension'],
|
||||||
|
invoke_on_load=True,
|
||||||
|
invoke_args=('a',),
|
||||||
|
invoke_kwds={'b': 'B'},
|
||||||
|
)
|
||||||
|
actual = em.names()
|
||||||
|
assert actual == []
|
||||||
|
|
||||||
|
|
||||||
|
def test_extensions_listed_in_name_order():
|
||||||
|
# Since we don't know the "natural" order of the extensions, run
|
||||||
|
# the test both ways: if the sorting is broken, one of them will
|
||||||
|
# fail
|
||||||
|
em = named.NamedExtensionManager(
|
||||||
|
'stevedore.test.extension',
|
||||||
|
names=['t1', 't2'],
|
||||||
|
name_order=True
|
||||||
|
)
|
||||||
|
actual = em.names()
|
||||||
|
assert actual == ['t1', 't2']
|
||||||
|
|
||||||
|
em = named.NamedExtensionManager(
|
||||||
|
'stevedore.test.extension',
|
||||||
|
names=['t2', 't1'],
|
||||||
|
name_order=True
|
||||||
|
)
|
||||||
|
actual = em.names()
|
||||||
|
assert actual == ['t2', 't1']
|
278
lib/stevedore/tests/test_test_manager.py
Normal file
278
lib/stevedore/tests/test_test_manager.py
Normal file
|
@ -0,0 +1,278 @@
|
||||||
|
from mock import Mock, sentinel
|
||||||
|
from nose.tools import raises
|
||||||
|
from stevedore import (ExtensionManager, NamedExtensionManager, HookManager,
|
||||||
|
DriverManager, EnabledExtensionManager)
|
||||||
|
from stevedore.dispatch import (DispatchExtensionManager,
|
||||||
|
NameDispatchExtensionManager)
|
||||||
|
from stevedore.extension import Extension
|
||||||
|
|
||||||
|
|
||||||
|
test_extension = Extension('test_extension', None, None, None)
|
||||||
|
test_extension2 = Extension('another_one', None, None, None)
|
||||||
|
|
||||||
|
mock_entry_point = Mock(module_name='test.extension', attrs=['obj'])
|
||||||
|
a_driver = Extension('test_driver', mock_entry_point, sentinel.driver_plugin,
|
||||||
|
sentinel.driver_obj)
|
||||||
|
|
||||||
|
|
||||||
|
# base ExtensionManager
|
||||||
|
|
||||||
|
def test_instance_should_use_supplied_extensions():
|
||||||
|
extensions = [test_extension, test_extension2]
|
||||||
|
em = ExtensionManager.make_test_instance(extensions)
|
||||||
|
|
||||||
|
assert extensions == em.extensions
|
||||||
|
|
||||||
|
|
||||||
|
def test_instance_should_have_default_namespace():
|
||||||
|
em = ExtensionManager.make_test_instance([])
|
||||||
|
|
||||||
|
assert em.namespace
|
||||||
|
|
||||||
|
|
||||||
|
def test_instance_should_use_supplied_namespace():
|
||||||
|
namespace = 'testing.1.2.3'
|
||||||
|
em = ExtensionManager.make_test_instance([], namespace=namespace)
|
||||||
|
|
||||||
|
assert namespace == em.namespace
|
||||||
|
|
||||||
|
|
||||||
|
def test_extension_name_should_be_listed():
|
||||||
|
em = ExtensionManager.make_test_instance([test_extension])
|
||||||
|
|
||||||
|
assert test_extension.name in em.names()
|
||||||
|
|
||||||
|
|
||||||
|
def test_iterator_should_yield_extension():
|
||||||
|
em = ExtensionManager.make_test_instance([test_extension])
|
||||||
|
|
||||||
|
assert test_extension == next(iter(em))
|
||||||
|
|
||||||
|
|
||||||
|
def test_manager_should_allow_name_access():
|
||||||
|
em = ExtensionManager.make_test_instance([test_extension])
|
||||||
|
|
||||||
|
assert test_extension == em[test_extension.name]
|
||||||
|
|
||||||
|
|
||||||
|
def test_manager_should_call():
|
||||||
|
em = ExtensionManager.make_test_instance([test_extension])
|
||||||
|
func = Mock()
|
||||||
|
|
||||||
|
em.map(func)
|
||||||
|
|
||||||
|
func.assert_called_once_with(test_extension)
|
||||||
|
|
||||||
|
|
||||||
|
def test_manager_should_call_all():
|
||||||
|
em = ExtensionManager.make_test_instance([test_extension2,
|
||||||
|
test_extension])
|
||||||
|
func = Mock()
|
||||||
|
|
||||||
|
em.map(func)
|
||||||
|
|
||||||
|
func.assert_any_call(test_extension2)
|
||||||
|
func.assert_any_call(test_extension)
|
||||||
|
|
||||||
|
|
||||||
|
def test_manager_return_values():
|
||||||
|
def mapped(ext, *args, **kwds):
|
||||||
|
return ext.name
|
||||||
|
|
||||||
|
em = ExtensionManager.make_test_instance([test_extension2,
|
||||||
|
test_extension])
|
||||||
|
results = em.map(mapped)
|
||||||
|
assert sorted(results) == ['another_one', 'test_extension']
|
||||||
|
|
||||||
|
|
||||||
|
def test_manager_should_eat_exceptions():
|
||||||
|
em = ExtensionManager.make_test_instance([test_extension])
|
||||||
|
|
||||||
|
func = Mock(side_effect=RuntimeError('hard coded error'))
|
||||||
|
|
||||||
|
results = em.map(func, 1, 2, a='A', b='B')
|
||||||
|
assert results == []
|
||||||
|
|
||||||
|
|
||||||
|
@raises(RuntimeError)
|
||||||
|
def test_manager_should_propagate_exceptions():
|
||||||
|
em = ExtensionManager.make_test_instance([test_extension],
|
||||||
|
propagate_map_exceptions=True)
|
||||||
|
func = Mock(side_effect=RuntimeError('hard coded error'))
|
||||||
|
|
||||||
|
em.map(func, 1, 2, a='A', b='B')
|
||||||
|
|
||||||
|
|
||||||
|
# NamedExtensionManager
|
||||||
|
|
||||||
|
def test_named_manager_should_use_supplied_extensions():
|
||||||
|
extensions = [test_extension, test_extension2]
|
||||||
|
em = NamedExtensionManager.make_test_instance(extensions)
|
||||||
|
|
||||||
|
assert extensions == em.extensions
|
||||||
|
|
||||||
|
|
||||||
|
def test_named_manager_should_have_default_namespace():
|
||||||
|
em = NamedExtensionManager.make_test_instance([])
|
||||||
|
|
||||||
|
assert em.namespace
|
||||||
|
|
||||||
|
|
||||||
|
def test_named_manager_should_use_supplied_namespace():
|
||||||
|
namespace = 'testing.1.2.3'
|
||||||
|
em = NamedExtensionManager.make_test_instance([], namespace=namespace)
|
||||||
|
|
||||||
|
assert namespace == em.namespace
|
||||||
|
|
||||||
|
|
||||||
|
def test_named_manager_should_populate_names():
|
||||||
|
extensions = [test_extension, test_extension2]
|
||||||
|
em = NamedExtensionManager.make_test_instance(extensions)
|
||||||
|
|
||||||
|
assert ['test_extension', 'another_one'] == em.names()
|
||||||
|
|
||||||
|
|
||||||
|
# HookManager
|
||||||
|
|
||||||
|
def test_hook_manager_should_use_supplied_extensions():
|
||||||
|
extensions = [test_extension, test_extension2]
|
||||||
|
em = HookManager.make_test_instance(extensions)
|
||||||
|
|
||||||
|
assert extensions == em.extensions
|
||||||
|
|
||||||
|
|
||||||
|
def test_hook_manager_should_be_first_extension_name():
|
||||||
|
extensions = [test_extension, test_extension2]
|
||||||
|
em = HookManager.make_test_instance(extensions)
|
||||||
|
|
||||||
|
# This will raise KeyError if the names don't match
|
||||||
|
assert em[test_extension.name]
|
||||||
|
|
||||||
|
|
||||||
|
def test_hook_manager_should_have_default_namespace():
|
||||||
|
em = HookManager.make_test_instance([test_extension])
|
||||||
|
|
||||||
|
assert em.namespace
|
||||||
|
|
||||||
|
|
||||||
|
def test_hook_manager_should_use_supplied_namespace():
|
||||||
|
namespace = 'testing.1.2.3'
|
||||||
|
em = HookManager.make_test_instance([test_extension], namespace=namespace)
|
||||||
|
|
||||||
|
assert namespace == em.namespace
|
||||||
|
|
||||||
|
|
||||||
|
def test_hook_manager_should_return_named_extensions():
|
||||||
|
hook1 = Extension('captain', None, None, None)
|
||||||
|
hook2 = Extension('captain', None, None, None)
|
||||||
|
|
||||||
|
em = HookManager.make_test_instance([hook1, hook2])
|
||||||
|
|
||||||
|
assert [hook1, hook2] == em['captain']
|
||||||
|
|
||||||
|
|
||||||
|
# DriverManager
|
||||||
|
|
||||||
|
def test_driver_manager_should_use_supplied_extension():
|
||||||
|
em = DriverManager.make_test_instance(a_driver)
|
||||||
|
|
||||||
|
assert [a_driver] == em.extensions
|
||||||
|
|
||||||
|
|
||||||
|
def test_driver_manager_should_have_default_namespace():
|
||||||
|
em = DriverManager.make_test_instance(a_driver)
|
||||||
|
|
||||||
|
assert em.namespace
|
||||||
|
|
||||||
|
|
||||||
|
def test_driver_manager_should_use_supplied_namespace():
|
||||||
|
namespace = 'testing.1.2.3'
|
||||||
|
em = DriverManager.make_test_instance(a_driver, namespace=namespace)
|
||||||
|
|
||||||
|
assert namespace == em.namespace
|
||||||
|
|
||||||
|
|
||||||
|
def test_instance_should_use_driver_name():
|
||||||
|
em = DriverManager.make_test_instance(a_driver)
|
||||||
|
|
||||||
|
assert ['test_driver'] == em.names()
|
||||||
|
|
||||||
|
|
||||||
|
def test_instance_call():
|
||||||
|
def invoke(ext, *args, **kwds):
|
||||||
|
return ext.name, args, kwds
|
||||||
|
|
||||||
|
em = DriverManager.make_test_instance(a_driver)
|
||||||
|
result = em(invoke, 'a', b='C')
|
||||||
|
|
||||||
|
assert result == ('test_driver', ('a',), {'b': 'C'})
|
||||||
|
|
||||||
|
|
||||||
|
def test_instance_driver_property():
|
||||||
|
em = DriverManager.make_test_instance(a_driver)
|
||||||
|
|
||||||
|
assert sentinel.driver_obj == em.driver
|
||||||
|
|
||||||
|
|
||||||
|
# EnabledExtensionManager
|
||||||
|
|
||||||
|
def test_enabled_instance_should_use_supplied_extensions():
|
||||||
|
extensions = [test_extension, test_extension2]
|
||||||
|
em = EnabledExtensionManager.make_test_instance(extensions)
|
||||||
|
|
||||||
|
assert extensions == em.extensions
|
||||||
|
|
||||||
|
|
||||||
|
# DispatchExtensionManager
|
||||||
|
|
||||||
|
def test_dispatch_instance_should_use_supplied_extensions():
|
||||||
|
extensions = [test_extension, test_extension2]
|
||||||
|
em = DispatchExtensionManager.make_test_instance(extensions)
|
||||||
|
|
||||||
|
assert extensions == em.extensions
|
||||||
|
|
||||||
|
|
||||||
|
def test_dispatch_map_should_invoke_filter_for_extensions():
|
||||||
|
em = DispatchExtensionManager.make_test_instance([test_extension,
|
||||||
|
test_extension2])
|
||||||
|
|
||||||
|
filter_func = Mock(return_value=False)
|
||||||
|
|
||||||
|
args = ('A',)
|
||||||
|
kw = {'big': 'Cheese'}
|
||||||
|
|
||||||
|
em.map(filter_func, None, *args, **kw)
|
||||||
|
|
||||||
|
filter_func.assert_any_call(test_extension, *args, **kw)
|
||||||
|
filter_func.assert_any_call(test_extension2, *args, **kw)
|
||||||
|
|
||||||
|
|
||||||
|
# NameDispatchExtensionManager
|
||||||
|
|
||||||
|
def test_name_dispatch_instance_should_use_supplied_extensions():
|
||||||
|
extensions = [test_extension, test_extension2]
|
||||||
|
em = NameDispatchExtensionManager.make_test_instance(extensions)
|
||||||
|
|
||||||
|
assert extensions == em.extensions
|
||||||
|
|
||||||
|
|
||||||
|
def test_name_dispatch_instance_should_build_extension_name_map():
|
||||||
|
extensions = [test_extension, test_extension2]
|
||||||
|
em = NameDispatchExtensionManager.make_test_instance(extensions)
|
||||||
|
|
||||||
|
assert test_extension == em.by_name[test_extension.name]
|
||||||
|
assert test_extension2 == em.by_name[test_extension2.name]
|
||||||
|
|
||||||
|
|
||||||
|
def test_named_dispatch_map_should_invoke_filter_for_extensions():
|
||||||
|
em = NameDispatchExtensionManager.make_test_instance([test_extension,
|
||||||
|
test_extension2])
|
||||||
|
|
||||||
|
func = Mock()
|
||||||
|
|
||||||
|
args = ('A',)
|
||||||
|
kw = {'BIGGER': 'Cheese'}
|
||||||
|
|
||||||
|
em.map(['test_extension'], func, *args, **kw)
|
||||||
|
|
||||||
|
func.assert_called_once_with(test_extension, *args, **kw)
|
|
@ -84,6 +84,7 @@ DELUGEPORT = None
|
||||||
DELUGEUSR = None
|
DELUGEUSR = None
|
||||||
DELUGEPWD = None
|
DELUGEPWD = None
|
||||||
|
|
||||||
|
EXTCONTAINER = None
|
||||||
COMPRESSEDCONTAINER = None
|
COMPRESSEDCONTAINER = None
|
||||||
MEDIACONTAINER = None
|
MEDIACONTAINER = None
|
||||||
AUDIOCONTAINER = None
|
AUDIOCONTAINER = None
|
||||||
|
@ -136,7 +137,7 @@ def initialize(section=None):
|
||||||
TRANSCODE, GIT_PATH, GIT_USER, GIT_BRANCH, GIT_REPO, SYS_ENCODING, NZB_CLIENTAGENT, SABNZBDHOST, SABNZBDPORT, SABNZBDAPIKEY, \
|
TRANSCODE, GIT_PATH, GIT_USER, GIT_BRANCH, GIT_REPO, SYS_ENCODING, NZB_CLIENTAGENT, SABNZBDHOST, SABNZBDPORT, SABNZBDAPIKEY, \
|
||||||
DUPLICATE, IGNOREEXTENSIONS, OUTPUTVIDEOEXTENSION, OUTPUTVIDEOCODEC, OUTPUTVIDEOPRESET, OUTPUTVIDEOFRAMERATE, \
|
DUPLICATE, IGNOREEXTENSIONS, OUTPUTVIDEOEXTENSION, OUTPUTVIDEOCODEC, OUTPUTVIDEOPRESET, OUTPUTVIDEOFRAMERATE, \
|
||||||
OUTPUTVIDEOBITRATE, OUTPUTAUDIOCODEC, OUTPUTAUDIOBITRATE, OUTPUTSUBTITLECODEC, OUTPUTFASTSTART, OUTPUTQUALITYPERCENT, \
|
OUTPUTVIDEOBITRATE, OUTPUTAUDIOCODEC, OUTPUTAUDIOBITRATE, OUTPUTSUBTITLECODEC, OUTPUTFASTSTART, OUTPUTQUALITYPERCENT, \
|
||||||
NICENESS, LOG_DEBUG, FORCE_CLEAN, FFMPEG_PATH, FFMPEG, FFPROBE, AUDIOCONTAINER
|
NICENESS, LOG_DEBUG, FORCE_CLEAN, FFMPEG_PATH, FFMPEG, FFPROBE, AUDIOCONTAINER, EXTCONTAINER
|
||||||
|
|
||||||
if __INITIALIZED__:
|
if __INITIALIZED__:
|
||||||
return False
|
return False
|
||||||
|
@ -240,12 +241,19 @@ def initialize(section=None):
|
||||||
DELUGEUSR = CFG["Torrent"]["DelugeUSR"] # mysecretusr
|
DELUGEUSR = CFG["Torrent"]["DelugeUSR"] # mysecretusr
|
||||||
DELUGEPWD = CFG["Torrent"]["DelugePWD"] # mysecretpwr
|
DELUGEPWD = CFG["Torrent"]["DelugePWD"] # mysecretpwr
|
||||||
|
|
||||||
COMPRESSEDCONTAINER = (CFG["Extensions"]["compressedExtensions"]) # .zip,.rar,.7z
|
COMPRESSEDCONTAINER = CFG["Extensions"]["compressedExtensions"]
|
||||||
MEDIACONTAINER = (CFG["Extensions"]["mediaExtensions"]) # .mkv,.avi,.divx
|
MEDIACONTAINER = CFG["Extensions"]["mediaExtensions"]
|
||||||
AUDIOCONTAINER = (CFG["Extensions"]["audioExtensions"])
|
AUDIOCONTAINER = CFG["Extensions"]["audioExtensions"]
|
||||||
METACONTAINER = (CFG["Extensions"]["metaExtensions"]) # .nfo,.sub,.srt
|
METACONTAINER = CFG["Extensions"]["metaExtensions"] # .nfo,.sub,.srt
|
||||||
|
if not isinstance(COMPRESSEDCONTAINER, list):COMPRESSEDCONTAINER = [COMPRESSEDCONTAINER]
|
||||||
|
if not isinstance(MEDIACONTAINER, list): MEDIACONTAINER = [MEDIACONTAINER]
|
||||||
|
if not isinstance(AUDIOCONTAINER, list): AUDIOCONTAINER = [AUDIOCONTAINER]
|
||||||
|
if not isinstance(METACONTAINER, list): METACONTAINER = [METACONTAINER]
|
||||||
|
|
||||||
|
EXTCONTAINER = [y for x in COMPRESSEDCONTAINER,MEDIACONTAINER,AUDIOCONTAINER,METACONTAINER for y in x]
|
||||||
|
|
||||||
MINSAMPLESIZE = int(CFG["Extensions"]["minSampleSize"]) # 200 (in MB)
|
MINSAMPLESIZE = int(CFG["Extensions"]["minSampleSize"]) # 200 (in MB)
|
||||||
SAMPLEIDS = (CFG["Extensions"]["SampleIDs"]) # sample,-s.
|
SAMPLEIDS = CFG["Extensions"]["SampleIDs"]
|
||||||
|
|
||||||
TRANSCODE = int(CFG["Transcoder"]["transcode"])
|
TRANSCODE = int(CFG["Transcoder"]["transcode"])
|
||||||
DUPLICATE = int(CFG["Transcoder"]["duplicate"])
|
DUPLICATE = int(CFG["Transcoder"]["duplicate"])
|
||||||
|
|
|
@ -581,19 +581,18 @@ def clean_nzbname(nzbname):
|
||||||
nzbname = re.sub("^\[.*\]", "", nzbname)
|
nzbname = re.sub("^\[.*\]", "", nzbname)
|
||||||
return nzbname.strip()
|
return nzbname.strip()
|
||||||
|
|
||||||
def isMediaFile(filename):
|
def isMediaFile(mediafile):
|
||||||
|
fileName, fileExt = os.path.splitext(mediafile)
|
||||||
|
|
||||||
# ignore MAC OS's retarded "resource fork" files
|
# ignore MAC OS's retarded "resource fork" files
|
||||||
if filename.startswith('._'):
|
if fileName.startswith('._'):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
sepFile = filename.rpartition(".")
|
if re.search('extras?$', fileName, re.I):
|
||||||
|
logger.info("Ignoring extras file: %s " % (mediafile))
|
||||||
if re.search('extras?$', sepFile[0], re.I):
|
|
||||||
logger.info("Ignoring extras file: %s " % (filename))
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if sepFile[2].lower() in [i.replace(".","") for i in
|
if fileExt.lower() in nzbtomedia.EXTCONTAINER:
|
||||||
(nzbtomedia.MEDIACONTAINER + nzbtomedia.AUDIOCONTAINER + nzbtomedia.COMPRESSEDCONTAINER)]:
|
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -19,6 +19,23 @@ copy_list = []
|
||||||
# Initialize the config
|
# Initialize the config
|
||||||
nzbtomedia.initialize()
|
nzbtomedia.initialize()
|
||||||
|
|
||||||
|
EXTCONTAINER = []
|
||||||
|
|
||||||
|
try:
|
||||||
|
EXTCONTAINER += nzbtomedia.COMPRESSEDCONTAINER.split(',')
|
||||||
|
except:
|
||||||
|
EXTCONTAINER.extend(nzbtomedia.COMPRESSEDCONTAINER)
|
||||||
|
|
||||||
|
try:
|
||||||
|
EXTCONTAINER += nzbtomedia.MEDIACONTAINER.split(',')
|
||||||
|
except:
|
||||||
|
EXTCONTAINER.extend(nzbtomedia.MEDIACONTAINER)
|
||||||
|
|
||||||
|
try:
|
||||||
|
EXTCONTAINER += nzbtomedia.AUDIOCONTAINER.split(',')
|
||||||
|
except:
|
||||||
|
EXTCONTAINER.extend(nzbtomedia.AUDIOCONTAINER)
|
||||||
|
|
||||||
inputDirectory = "Z:\complete\movie\The.Lego.Movie.2014.R5.x264.English.XviD-vTg.nfo_0166_-_The.Lego.Movie.2014.R5.x264.English.XviD-vTg.nfo_yEn.cp(tt1490017)"
|
inputDirectory = "Z:\complete\movie\The.Lego.Movie.2014.R5.x264.English.XviD-vTg.nfo_0166_-_The.Lego.Movie.2014.R5.x264.English.XviD-vTg.nfo_yEn.cp(tt1490017)"
|
||||||
inputName = "The.Lego.Movie.2014.R5.x264.English.XviD-vTg.nfo_0166_-_The.Lego.Movie.2014.R5.x264.English.XviD-vTg.nfo_yEn.cp(tt1490017)"
|
inputName = "The.Lego.Movie.2014.R5.x264.English.XviD-vTg.nfo_0166_-_The.Lego.Movie.2014.R5.x264.English.XviD-vTg.nfo_yEn.cp(tt1490017)"
|
||||||
inputCategory = 'movie'
|
inputCategory = 'movie'
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue