diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..35755d6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.pyc +.spyderproject + diff --git a/EmailSettings.cfg b/EmailSettings.cfg new file mode 100644 index 0000000..90c69ad --- /dev/null +++ b/EmailSettings.cfg @@ -0,0 +1,5 @@ +SMTPServer = "" +SMTPUser = "" +SMTPPassword = "" +From = "" +To = "" diff --git a/TVEncoder.py b/TVEncoder.py index f2142a5..152a36d 100644 --- a/TVEncoder.py +++ b/TVEncoder.py @@ -10,9 +10,14 @@ import getopt from libfilemanager import FileManager from libsettings import Settings import libhandbrake +import libemail from libtvdatasource import TVData from collections import namedtuple from termcolor import colored +import logging + +SETTINGS = "settings.cfg" +EMAIL_SETTINGS = "EmailSettings.cfg" def showhelp(): @@ -26,6 +31,7 @@ def showhelp(): 'files that will be processed without actually encoding them' print 'TVEncoder.py -e - encode the files that have been processed' print 'TVEncoder.py -e -l - list the files that would be encoded' + print 'TVEncoder.py -c - check the output directories for duplicates' def print_shows(shows): @@ -69,9 +75,11 @@ def processarguments(options): """ inputoptions = namedtuple("inputoptions", - "numfiles doencode readonly dolist") + "numfiles doencode readonly dolist " + "checkduplicates") inputoptions.readonly = False + inputoptions.checkduplicates = False for opt, arg in options: if opt == '-h': @@ -85,6 +93,8 @@ def processarguments(options): inputoptions.numfiles = arg elif opt == "-l": inputoptions.readonly = True + elif opt == "-c": + inputoptions.checkduplicates = True return inputoptions @@ -94,15 +104,25 @@ def main(argv): The main program for TVEncoder. """ try: - opts, args = getopt.getopt(argv, "hlpen:") + opts, _ = getopt.getopt(argv, "hlpecn:") except getopt.GetoptError: showhelp() sys.exit(2) inputoptions = processarguments(opts) - settings = Settings("settings.cfg") + settings = Settings(SETTINGS) filemanager = FileManager(settings) + if inputoptions.checkduplicates: + print "Searching for duplicates..." + duplicates = filemanager.checkexistingduplicates() + if duplicates: + for duplicate in duplicates: + print duplicate + else: + print "No duplicates found." + return + if inputoptions.readonly: if inputoptions.doencode: #Generate the list of files that would be encoded @@ -116,25 +136,69 @@ def main(argv): else: if inputoptions.doencode: #Encode the files and move them to their final destination - showdata = filemanager.getencodingfiles(inputoptions.readonly) + logging.basicConfig(level=logging.DEBUG) + generallogger = createlogger("general", settings.generallogfile(), + logging.DEBUG) + actionlogger = createlogger("action", settings.actionlogfile(), + logging.INFO) + + showdata = filemanager.getencodingfiles(inputoptions.readonly) + generallogger.info("There are {0} files to process." + .format(len(showdata))) for show in showdata: + generallogger.info("========================================") + generallogger.info("Processing {0} of {1}, {2}".format( + showdata.index(show) + 1, len(showdata), str(show))) + if filemanager.checkfileexists(show.outputfile): - print "File {0} already exists. Cannot process." \ - .format(show.outputfile) + message = "File {0} already exists. Cannot process." \ + .format(show.outputfile) + generallogger.warning(message) + actionlogger.warning(message) else: result = libhandbrake.encode(settings.handbrakecommand(), show.inputfile, show.outputfile) - # TODO do something with the result + + generallogger.info("Encode finished with result: {0}" + .format(result)) filemanager.performpostencodefileoperations( show.inputfile, show.outputfile) + + if filemanager.checkduplicates(show.outputfile): + actionlogger.info("There is an existing video file" + "present for {0}" + .format(show.outputfile)) + + generallogger.info("Processing finished.") + generallogger.info("===========================" + "=============\n\n") + + libemail.sendemail(EMAIL_SETTINGS, "Encoding Complete", + "Finished encoding {0} shows." + .format(len(showdata))) else: # Process files for encoding shows = filemanager.getfilestoprepare(inputoptions.numfiles) + print "Preparing {0} files".format(len(shows)) tvdata = TVData(settings) tvdata.prepareepisodes(shows) +def createlogger(name, filename, level): + """ + Create a logger named that will write to the file + """ + + logger = logging.getLogger(name) + handler = logging.FileHandler(filename, mode='w') + formatter = logging.Formatter('%(asctime)s %(message)s') + handler.setFormatter(formatter) + handler.setLevel(level) + logger.addHandler(handler) + return logger + + if __name__ == "__main__": main(sys.argv[1:]) diff --git a/libemail.py b/libemail.py new file mode 100644 index 0000000..a886880 --- /dev/null +++ b/libemail.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +""" +Created on Sat Jul 20 20:48:10 2013 + +@author: shanef +""" + +from libsettings import EmailSettings + +import smtplib +from email.mime.text import MIMEText + + +def sendemail(settingsfilename, subject, body): + """ + Send an email using the settings defined in settingsfilename + """ + + settings = EmailSettings(settingsfilename) + + msg = MIMEText(body, "plain") + msg["Subject"] = subject + msg["From"] = settings.getfromaddress() + msg["To"] = settings.gettoaddress() + + smtp = smtplib.SMTP(settings.getsmtpserver()) + smtp.ehlo() + smtp.starttls() + smtp.login(settings.getsmtpuser(), settings.getsmtppassword()) + smtp.sendmail(settings.getfromaddress(), [settings.gettoaddress()], + msg.as_string()) + smtp.quit() diff --git a/libfilemanager.py b/libfilemanager.py index 413e2b5..db51349 100644 --- a/libfilemanager.py +++ b/libfilemanager.py @@ -35,9 +35,14 @@ class EncodeData: errors = [] - if os.path.exists(self.outputfile): + if checkfileexists(self.outputfile, False): errors.append("FILE_EXISTS") + if self.outputfile[-5:-4] == "_": + tempoutfile = self.outputfile[:-5] + self.outputfile[-4:] + if checkfileexists(tempoutfile, False): + errors.append("FILE_EXISTS") + return errors @@ -107,13 +112,62 @@ class FileManager: #will reach here if there were less than numberofFiles found return showstoprocess + def checkexistingduplicates(self): + """ + Check the existing files in the output directories for duplicate + files, typically in different formats + """ + + duplicates = [] + for show in self.__settings.getshownames(): + outputdir = self.__settings.getshowoutputdirectory(show) + + for rootdir, dirnames, filenames in os.walk(outputdir): + for fle in filenames: + filename = os.path.join(rootdir, fle) + if os.path.splitext(fle)[1].lower() in [".avi", ".mpg", ".mpeg", + "mp4", ".mkv"]: + if self.checkduplicates(filename): + duplicates.append(filename) + + return sorted(duplicates) + @staticmethod - def checkfileexists(filename): + def checkduplicates(filename): + """ + Check to see if there are any other video files existing for the + episode + """ + + dirname = os.path.dirname(filename) + filename = os.path.basename(filename) + fileseasonepisode = filename[:6] + fileextension = os.path.splitext(filename)[1] + + for _, _, filenames in os.walk(dirname): + for show in filenames: + extension = os.path.splitext(show)[1] + if (extension.lower() in [".avi", ".mpg", ".mpeg", "mp4", ".mkv"] and + show[:6] == fileseasonepisode + and fileextension != extension): + return True + + return False + + @staticmethod + def checkfileexists(filename, casesensitive=True): """ Check to see if a file currently exists """ + if casesensitive: + return os.path.exists(filename) + else: + filename = os.path.basename(filename) + for dirfile in os.listdir(os.path.dirname(filename)): + if (filename.lower() == dirfile.lower()): + return True - return os.path.exists(filename) + return False def __getinputfilestoencode(self): """ @@ -123,7 +177,7 @@ class FileManager: filelist = [] for show in self.__settings.getshownames(): - for dirpath, dirnames, filenames in os.walk( + for dirpath, _, filenames in os.walk( self.__settings.getshowinputdirectory(show)): for inputfile in filenames: if inputfile.endswith(".mpg"): @@ -168,3 +222,23 @@ def findseason(path, filename, readonly): os.makedirs(seasonpath) return seasonpath + + +def checkfileexists(filename, casesensitive=True): + """ + Check to see if a file currently exists + """ + dirname = os.path.dirname(filename) + + if casesensitive: + return os.path.exists(filename) + else: + if not os.path.exists(dirname): + return False + + basename = os.path.basename(filename) + for dirfile in os.listdir(dirname): + if (basename.lower() == dirfile.lower()): + return True + + return False diff --git a/libsettings.py b/libsettings.py index ff098bc..efc5db6 100644 --- a/libsettings.py +++ b/libsettings.py @@ -8,19 +8,6 @@ Created on Fri Jul 5 20:14:15 2013 from configobj import ConfigObj -#============================================================================== -# class ShowSettings: -# """ -# Container for the settings for a show -# """ -# -# def __init__(self, name, inputdirectory, outputdirectory): -# self.name = name -# self.inputdirectory = inputdirectory -# self.outputdirectory = outputdirectory -#============================================================================== - - class Settings: """ Accessor for the configuration file @@ -47,6 +34,27 @@ class Settings: return self.__config["HandbrakeCommand"] + def illegalcharacters(self): + """ + Get a list of illegal characters for filenames + """ + + return self.__config["IllegalCharacters"] + + def generallogfile(self): + """ + Get the filename to save general log messages to + """ + + return self.__config["Logging"]["General"] + + def actionlogfile(self): + """ + Get the filename to save the action log messages to + """ + + return self.__config["Logging"]["Action"] + def mythtvaddress(self): """ Get the MythTV/address setting @@ -206,11 +214,9 @@ class Settings: else: return show["SickbeardPrefix"] - # TODO check if this is actually doing anything. it seems like it - # just returns what is input def getshow(self, showname): """ - Get the InputDirectory setting for the show, showname. + Get the name of the show, showname. """ showsection = self.__getshowsubsection(showname) if showsection is None: @@ -231,3 +237,51 @@ class Settings: return self.__config["Shows"][show] return None + + +class EmailSettings: + """ + Accessor for the email configuration file + """ + + def __init__(self, settingsfile): + """ + Initialise settingsfile as a configobj + """ + + self.__config = ConfigObj(settingsfile) + + def getsmtpserver(self): + """ + Get the address of the smtp server + """ + + return self.__config["SMTPServer"] + + def getsmtpuser(self): + """ + Get the username for the smtp server + """ + + return self.__config["SMTPUser"] + + def getsmtppassword(self): + """ + Get the username for the smtp server + """ + + return self.__config["SMTPPassword"] + + def getfromaddress(self): + """ + Get the from address for emails + """ + + return self.__config["From"] + + def gettoaddress(self): + """ + Get the to address for emails + """ + + return self.__config["To"] diff --git a/libsickbeard.py b/libsickbeard.py index e356800..3ef2ad1 100644 --- a/libsickbeard.py +++ b/libsickbeard.py @@ -67,13 +67,14 @@ class Sickbeard: jsonurl = urlopen("{0}?cmd=show.seasons&tvdbid={1}".format( self.__getapiurl(), showid)) + result = json.loads(jsonurl.read()) for season in result['data']: for episode in result['data'][season]: episodename = result['data'][season][episode]['name'] - if name is not None and fuzz.partial_ratio(name.lower(), - episodename) > 90: + if name is not None and fuzz.ratio(name.lower(), + episodename.lower()) > 85: return (season, episode, episodename) elif description is not None: descriptionqueryresult = \ @@ -84,14 +85,6 @@ class Sickbeard: return (0, 0, '') -#============================================================================== -# def GetEpisodeName(subtitle, showName): -# if subtitle[:len(showName)].lower() == showName.lower(): -# return subtitle[len(showName + ' and the '):] -# else: -# return subtitle -#============================================================================== - def fixepisodetitle(self, showname, episodetitle): """ Check to see if there is a prefix specified for the show. If there is, diff --git a/libtvdatasource.py b/libtvdatasource.py index e19fd2c..ddffeec 100644 --- a/libtvdatasource.py +++ b/libtvdatasource.py @@ -88,8 +88,8 @@ class TVData: seasonfolder = "Season {0}".format(show.season) season = "S{0}".format(show.season) episode = "E{0}".format(show.episode) - renamedfile = "{0}{1} - {2} - SD TV_.mpg".format(season, episode, - show.subtitle) + renamedfile = self.getoutputfilename(season, episode, + show.subtitle) directory = self.getdirectory(show.title, seasonfolder, season, episode) @@ -102,20 +102,17 @@ class TVData: else: return None -#============================================================================== -# def __determinetargetfilename(directory, filename, inputfilename): -# """ -# Determine the filename for the input file. If the path does not -# exist, it is created. -# """ -# -# inputdir = os.path.join(directory, inputfilename[:-4]) -# -# if not os.path.exists(inputdir): -# os.makedirs(inputdir) -# -# return os.path.join(inputdir, filename) -#============================================================================== + def getoutputfilename(self, season, episode, name): + """ + Get the output filename, and remove any illegal characters + """ + + filename = "{0}{1} - {2} - SD TV_.mpg".format(season, episode, name) + + for illegalcharacter in self.__settings.illegalcharacters(): + filename = filename.replace(illegalcharacter, "") + + return filename @staticmethod def processepisode(inputfile, outputfile): @@ -137,4 +134,11 @@ class TVData: """ for showdata in showsdata: + print "========================================" + print "Copying {0} to {1}".format(showdata.inputfile, + showdata.outputfile) + self.processepisode(showdata.inputfile, showdata.outputfile) + + print "Finished copy" + print "========================================\n\n" diff --git a/pep8.sh b/pep8.sh new file mode 100755 index 0000000..ce2b244 --- /dev/null +++ b/pep8.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +pep8 libemail.py TVEncoder.py libfilemanager.py libhandbrake.py libmythtv.py libsettings.py libsickbeard.py libtvdatasource.py libtvshow.py diff --git a/pylint.sh b/pylint.sh new file mode 100755 index 0000000..5204ecc --- /dev/null +++ b/pylint.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +pylint TVEncoder.py libfilemanager.py libhandbrake.py libmythtv.py libsettings.py libsickbeard.py libtvdatasource.py libtvshow.py libemail.py diff --git a/settings.cfg b/settings.cfg index 736ebde..b84c6ca 100644 --- a/settings.cfg +++ b/settings.cfg @@ -1,5 +1,10 @@ TVRecordings = "/Volumes/TV Recordings/" HandbrakeCommand = "HandBrakeCLI", "--verbose", "-i", "SUBSTITUTE WITH INPUT FILE", "-o", "SUBSTITUDE WITH OUTPUT FILE", "-f", "mkv", "-e", "x264", "-x264-preset", "slower", "-x264-tune", "animation", "-q", "20", "--loose-anamorphic", "--decomb", "--detelecine", '--denoise="2:1:2:3"', "--deblock" +IllegalCharacters = "?", ":" + +[ "Logging" ] + General = "logs/encoding.log" + Action = "logs/needsaction.log" [ "MythTV" ] address = 192.168.0.2 @@ -13,46 +18,55 @@ HandbrakeCommand = "HandBrakeCLI", "--verbose", "-i", "SUBSTITUTE WITH INPUT FIL APIKey = 3678177136222bf5002be209220ccb20 [ "Shows" ] - UnknownInput = "/srv/storage2/files/VideoProcessing/Unknown/" + VideoProcessingDir = "/srv/storage2/files/VideoProcessing/" + KidsTVDir = "/srv/storage2/videos/Kids/TV/" + UnknownInput = "%(VideoProcessingDir)sUnknown/" [[ "Thomas the Tank Engine & Friends" ]] - InputDirectory = "/srv/storage2/files/VideoProcessing/Thomas/Input/" - UnknownDirectory = "/srv/storage2/files/VideoProcessing/Unknown/Thomas/" - OutputDirectory = "/srv/storage2/videos/Kids/TV/Thomas The Tank Engine & Friends/" + InputDirectory = "%(VideoProcessingDir)sThomas/" + UnknownDirectory = "%(UnknownInput)sThomas/" + OutputDirectory = "%(KidsTVDir)sThomas The Tank Engine & Friends/" alias = "Thomas and Friends", MythTvEpisodePrefix = , SickbeardPrefix = "" [[ "Chuggington" ]] - InputDirectory = "/srv/storage2/files/VideoProcessing/Chuggington/Input/" - UnknownDirectory = "/srv/storage2/files/VideoProcessing/Unknown/Chuggington/" - OutputDirectory = "/srv/storage2/videos/Kids/TV/Chuggington/" + InputDirectory = "%(VideoProcessingDir)sChuggington/" + UnknownDirectory = "%(UnknownInput)sChuggington/" + OutputDirectory = "%(KidsTVDir)sChuggington/" alias = , MythTvEpisodePrefix = , SickbeardPrefix = "" [[ "Mike the Knight" ]] - InputDirectory = "/srv/storage2/files/VideoProcessing/MikeTheKnight/Input/" - UnknownDirectory = "/srv/storage2/files/VideoProcessing/Unknown/MikeTheKnight/" - OutputDirectory = "/srv/storage2/videos/Kids/TV/Mike the Knight/" + InputDirectory = "%(VideoProcessingDir)sMikeTheKnight/" + UnknownDirectory = "%(UnknownInput)sMikeTheKnight/" + OutputDirectory = "%(KidsTVDir)sMike the Knight/" alias = , MythTvEpisodePrefix = "Mike the Knight and the ", Mike the Knight and " SickbeardPrefix = "" [[ "Octonauts" ]] - InputDirectory = "/srv/storage2/files/VideoProcessing/Octonauts/Input/" - UnknownDirectory = "/srv/storage2/files/VideoProcessing/Unknown/Octonauts/" - OutputDirectory = "/srv/storage2/videos/Kids/TV/Octonauts/" + InputDirectory = "%(VideoProcessingDir)sOctonauts/" + UnknownDirectory = "%(UnknownInput)sOctonauts/" + OutputDirectory = "%(KidsTVDir)sOctonauts/" alias = "The Octonauts", MythTvEpisodePrefix = "The Octonauts and ", SickbeardPrefix = "The" [[ "In the Night Garden" ]] - InputDirectory = "/srv/storage2/files/VideoProcessing/InTheNightGarden/Input/" - UnknownDirectory = "/srv/storage2/files/VideoProcessing/Unknown/InTheNightGarden/" - OutputDirectory = "/srv/storage2/videos/Kids/TV/In The Night Garden/" + InputDirectory = "%(VideoProcessingDir)sInTheNightGarden/" + UnknownDirectory = "%(UnknownInput)sInTheNightGarden/" + OutputDirectory = "%(KidsTVDir)sIn The Night Garden/" alias = , MythTvEpisodePrefix = , SickbeardPrefix = "" [[ "Raa Raa! The Noisy Lion" ]] - InputDirectory = "/srv/storage2/files/VideoProcessing/RaaRaa/Input/" - UnknownDirectory = "/srv/storage2/files/VideoProcessing/Unknown/RaaRaa/" - OutputDirectory = "/srv/storage2/videos/Kids/TV/Raa Raa the Noisy Lion/" + InputDirectory = "%(VideoProcessingDir)sRaaRaa/" + UnknownDirectory = "%(UnknownInput)sRaaRaa/" + OutputDirectory = "%(KidsTVDir)sRaa Raa the Noisy Lion/" + alias = , + MythTvEpisodePrefix = , + SickbeardPrefix = "" + [[ "Fireman Sam" ]] + InputDirectory = "%(VideoProcessingDir)sFiremanSam/" + UnknownDirectory = "%(UnknownInput)sFiremanSam/" + OutputDirectory = "%(KidsTVDir)sFireman Sam/" alias = , MythTvEpisodePrefix = , SickbeardPrefix = "" \ No newline at end of file diff --git a/tests/TVEncodertest.py b/tests/TVEncodertest.py new file mode 100644 index 0000000..d415f05 --- /dev/null +++ b/tests/TVEncodertest.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +""" +Created on Sat Jul 13 20:37:47 2013 + +@author: shanef +""" + +import unittest +import os +import sys +parentdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, parentdir) +import TVEncoder + + +class TVEncoderTest(unittest.TestCase): + def test_processarguments_encodereadonly(self): + args = [] + args.append(('-e', '')) + args.append(('-l', '')) + result = TVEncoder.processarguments(args) + + self.assertTrue(result.doencode) + self.assertTrue(result.readonly) + + def test_processarguments_encodereadonlyreverse(self): + args = [] + args.append(('-l', '')) + args.append(('-e', '')) + result = TVEncoder.processarguments(args) + + self.assertTrue(result.doencode) + self.assertTrue(result.readonly) + + def test_processarguments_encode(self): + args = [] + args.append(('-e', '')) + result = TVEncoder.processarguments(args) + + self.assertTrue(result.doencode) + self.assertFalse(result.readonly) + + +if __name__ == '__main__': + suite = unittest.TestLoader().loadTestsFromTestCase(TVEncoderTest) + unittest.TextTestRunner(verbosity=2).run(suite) \ No newline at end of file diff --git a/tests/emailtest.py b/tests/emailtest.py new file mode 100644 index 0000000..92cc000 --- /dev/null +++ b/tests/emailtest.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +""" +Created on Fri Jul 19 23:31:16 2013 + +@author: shanef +""" + +from minimock import Mock, mock +import unittest +import os +import sys +parentdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, parentdir) +import libemail +from libsettings import EmailSettings +import smtplib + + +class libemailtest(unittest.TestCase): + def test_SendEmail(self): + mock("EmailSettings.getfromaddress", returns="from@email.com") + mock("EmailSettings.gettoaddress", returns="to@email.com") + mock("EmailSettings.getsmtpserver", returns="smtp.test") + mock("EmailSettings.getsmtpuser", returns="user") + mock("EmailSettings.getsmtppassword", returns="password") + smtplib.SMTP = Mock('smtplib.SMTP') + smtplib.SMTP.mock_returns = Mock('smtp_connection') + + libemail.sendemail("test", "subject", "body") + +if __name__ == '__main__': + suite = unittest.TestLoader().loadTestsFromTestCase(libemailtest) + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/tests/libfilemanagertest.py b/tests/libfilemanagertest.py index c986f73..c8b8f9b 100644 --- a/tests/libfilemanagertest.py +++ b/tests/libfilemanagertest.py @@ -8,9 +8,11 @@ Created on Fri Jul 5 14:12:26 2013 import unittest import os import sys +import minimock +from minimock import mock, Mock parentdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0, parentdir) -from libfilemanager import EncodeData +from libfilemanager import EncodeData, FileManager class libfilemanagertest(unittest.TestCase): @@ -24,6 +26,92 @@ class libfilemanagertest(unittest.TestCase): "{2}\n".format(showname, inputname, outputname) self.assertEqual(result, expected) + def test_EncodeDataCheckProblemsFileExists(self): + showname = "test show" + inputname = "test input" + outputname = "test_output.mkv" + data = EncodeData(showname, inputname, outputname) + mock("os.path.exists", returns=True) + + result = data.checkproblems() + + self.assertIn("FILE_EXISTS", result) + minimock.restore() + + def test_EncodeDataCheckProblemsFile_Exists(self): + showname = "test show" + inputname = "test input" + outputname = "test_output_.mkv" + data = EncodeData(showname, inputname, outputname) + mock("os.path.exists", returns_iter=[False, True]) + result = data.checkproblems() + self.assertIn("FILE_EXISTS", result) + minimock.restore() + + def test_checkfileexistscaseinsensitive(self): + settings = Mock('libsettings.Settings') + filemanager = FileManager(settings) + + mock("os.listdir", returns=["filename.test"]) + + result = filemanager.checkfileexists("/path/to/fiLename.test", False) + + self.assertTrue(result) + minimock.restore() + + def test_checkduplicateavi(self): + settings = Mock('libsettings.Settings') + filemanager = FileManager(settings) + + os.walk = dummywalk + + result = filemanager.checkduplicates("/path/to/S03E14 - Test - SD TV.mkv") + + self.assertTrue(result) + minimock.restore() + + def test_checkduplicatethomas(self): + settings = Mock('libsettings.Settings') + filemanager = FileManager(settings) + + os.walk = thomaswalk + + result = filemanager.checkduplicates("/path/to/S12E05 - Henry Gets It Wrong - SD TV.mkv") + + self.assertTrue(result) + minimock.restore() + + def test_checkduplicatenomatch(self): + settings = Mock('libsettings.Settings') + filemanager = FileManager(settings) + + os.walk = dummywalk + + result = filemanager.checkduplicates("/path/to/S03E13 - Test - SD TV.mkv") + + self.assertFalse(result) + minimock.restore() + + def test_checkduplicatesameextension(self): + settings = Mock('libsettings.Settings') + filemanager = FileManager(settings) + + os.walk = dummywalk + + result = filemanager.checkduplicates("/path/to/S03E14 - Test - SD TV.avi") + + self.assertFalse(result) + minimock.restore() + + + +def dummywalk(arg): + return [("/path/to/", [], ["S03E14 - Test - SD TV.avi"])] + +def thomaswalk(arg): + return [(("/path/to/", [], ["S12E05 - Henry Gets It Wrong - Unknown.AVI"]))] + if __name__ == '__main__': suite = unittest.TestLoader().loadTestsFromTestCase(libfilemanagertest) - unittest.TextTestRunner(verbosity=2).run(suite) \ No newline at end of file + unittest.TextTestRunner(verbosity=2).run(suite) + minimock.restore() diff --git a/tests/libsickbeardtest.py b/tests/libsickbeardtest.py index 0776083..2015aaa 100644 --- a/tests/libsickbeardtest.py +++ b/tests/libsickbeardtest.py @@ -4,3 +4,48 @@ Created on Fri Jul 5 14:12:38 2013 @author: shanef """ + +import unittest +from minimock import Mock +import os +import sys +parentdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, parentdir) +import libsickbeard +import urllib + + +class SickbeardTest(unittest.TestCase): + def test_findepisodeCloseSubtitle(self): + settings = Mock('libsettings.Settings') + settings.sickbeardaddress.mock_returns = "test" + settings.sickbeardport.mock_returns = "123" + settings.sickbeardapikey.mock_returns = "test" + + urllib.urlopen = dummy_urlopen + + sickbeard = libsickbeard.Sickbeard(settings) + + result = sickbeard.findepisode("78949", "Splish, Splash, Splosh") + + self.assertEqual("13", result[0]) + self.assertEqual("15", result[1]) + self.assertEqual("Splish, Splash, Splosh!", result[2]) + + +def dummy_urlopen(arg): + class TmpClass: + def read(arg): + jsonresult = '{ "data": {"13": { "15": { "airdate": "2010-02-12", ' \ + '"name": "Splish, Splash, Splosh!", "quality": "N/A", ' \ + '"status": "Wanted" } } }, "message": "", ' \ + '"result": "success" }' + + return jsonresult + + return TmpClass() + + +if __name__ == '__main__': + suite = unittest.TestLoader().loadTestsFromTestCase(SickbeardTest) + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/tests/libtvdatasourcetest.py b/tests/libtvdatasourcetest.py new file mode 100644 index 0000000..cba96bb --- /dev/null +++ b/tests/libtvdatasourcetest.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +""" +Created on Thu Jul 18 23:13:15 2013 + +@author: shanef +""" + +import unittest +from minimock import Mock +import os +import sys +parentdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, parentdir) +import libtvdatasource + + +class tvdatasourceTest(unittest.TestCase): + def test_GetOutputFilenameNoIllegals(self): + result = self._dooutputfilenametest("S01", "E02", "test name", "") + self.assertEqual(result, "S01E02 - test name - SD TV_.mpg") + + def test_GetOutputFilenameOneIllegals(self): + result = self._dooutputfilenametest("S01", "E02", "test name?", "?") + self.assertEqual(result, "S01E02 - test name - SD TV_.mpg") + + def test_GetOutputFilenameTwoIllegals(self): + result = self._dooutputfilenametest("S01", "E02", "tes>t name?", ["?", ">"]) + self.assertEqual(result, "S01E02 - test name - SD TV_.mpg") + + def _dooutputfilenametest(self, season, episode, name, illegals): + settings = Mock('libsettings.Settings') + settings.illegalcharacters.mock_returns = illegals + tvdatasource = libtvdatasource.TVData(settings) + return tvdatasource.getoutputfilename(season, episode, name) + +if __name__ == '__main__': + suite = unittest.TestLoader().loadTestsFromTestCase(tvdatasourceTest) + unittest.TextTestRunner(verbosity=2).run(suite) \ No newline at end of file