From 48e4eae2beac026b6aaa87dac7e6ae4caebb3e1d Mon Sep 17 00:00:00 2001 From: Shane Frischkorn Date: Thu, 18 Jul 2013 23:33:17 +1000 Subject: [PATCH 01/21] Ignore ? in filenames since they are illegal --- libsettings.py | 6 +++++ libtvdatasource.py | 29 +++++++++++------------ settings.cfg | 3 ++- tests/TVEncodertest.py | 45 ++++++++++++++++++++++++++++++++++++ tests/libtvdatasourcetest.py | 38 ++++++++++++++++++++++++++++++ 5 files changed, 104 insertions(+), 17 deletions(-) create mode 100644 tests/TVEncodertest.py create mode 100644 tests/libtvdatasourcetest.py diff --git a/libsettings.py b/libsettings.py index ff098bc..3cdedba 100644 --- a/libsettings.py +++ b/libsettings.py @@ -47,6 +47,12 @@ class Settings: return self.__config["HandbrakeCommand"] + def illegalcharacters(self): + """Get a list of illegal characters for filenames + """ + + return self.__config["IllegalCharacters"] + def mythtvaddress(self): """ Get the MythTV/address setting diff --git a/libtvdatasource.py b/libtvdatasource.py index e19fd2c..87ac3ba 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): diff --git a/settings.cfg b/settings.cfg index 736ebde..cf6505e 100644 --- a/settings.cfg +++ b/settings.cfg @@ -1,5 +1,6 @@ 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 = "?" [ "MythTV" ] address = 192.168.0.2 @@ -30,7 +31,7 @@ HandbrakeCommand = "HandBrakeCLI", "--verbose", "-i", "SUBSTITUTE WITH INPUT FIL SickbeardPrefix = "" [[ "Mike the Knight" ]] InputDirectory = "/srv/storage2/files/VideoProcessing/MikeTheKnight/Input/" - UnknownDirectory = "/srv/storage2/files/VideoProcessing/Unknown/MikeTheKnight/" + UnknownDirectory = "/srv/storage2/files/VideoProcessing/Unknown/MikeTheKnight/" OutputDirectory = "/srv/storage2/videos/Kids/TV/Mike the Knight/" alias = , MythTvEpisodePrefix = "Mike the Knight and the ", Mike the Knight and " diff --git a/tests/TVEncodertest.py b/tests/TVEncodertest.py new file mode 100644 index 0000000..85cf4ab --- /dev/null +++ b/tests/TVEncodertest.py @@ -0,0 +1,45 @@ +# -*- 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/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 From be9727155951a176dd262145abfa96a64e3c9e4c Mon Sep 17 00:00:00 2001 From: Shane Frischkorn Date: Fri, 19 Jul 2013 22:36:46 +1000 Subject: [PATCH 02/21] added logging --- .gitignore | 3 +++ TVEncoder.py | 43 +++++++++++++++++++++++++++++++++++++++---- libsettings.py | 17 ++++++++++++++++- libtvdatasource.py | 7 +++++++ pep8.sh | 3 +++ pylint.sh | 3 +++ settings.cfg | 4 ++++ 7 files changed, 75 insertions(+), 5 deletions(-) create mode 100644 .gitignore create mode 100755 pep8.sh create mode 100755 pylint.sh 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/TVEncoder.py b/TVEncoder.py index f2142a5..fcf78ea 100644 --- a/TVEncoder.py +++ b/TVEncoder.py @@ -13,6 +13,7 @@ import libhandbrake from libtvdatasource import TVData from collections import namedtuple from termcolor import colored +import logging def showhelp(): @@ -103,6 +104,12 @@ def main(argv): settings = Settings("settings.cfg") filemanager = FileManager(settings) + logging.basicConfig(level=logging.DEBUG) + generallogger = createlogger("general", settings.generallogfile, + logging.debug) + actionlogger = createlogger("action", settings.actionlogfile, + logging.info) + if inputoptions.readonly: if inputoptions.doencode: #Generate the list of files that would be encoded @@ -117,24 +124,52 @@ def main(argv): if inputoptions.doencode: #Encode the files and move them to their final destination 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) + + generallogger.info("Processing finished.") + generallogger.info("===========================" + "=============\n\n") 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) + 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/libsettings.py b/libsettings.py index 3cdedba..0a5c9fb 100644 --- a/libsettings.py +++ b/libsettings.py @@ -48,11 +48,26 @@ class Settings: return self.__config["HandbrakeCommand"] def illegalcharacters(self): - """Get a list of illegal characters for filenames + """ + 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 diff --git a/libtvdatasource.py b/libtvdatasource.py index 87ac3ba..ddffeec 100644 --- a/libtvdatasource.py +++ b/libtvdatasource.py @@ -134,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..73bdc68 --- /dev/null +++ b/pep8.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +pep8 TVEncoder.py libfilemanager.py libhandbrake.py libmythtv.py libsettings.py libsickbeard.py libtvdatasource.py libtvshow.py \ No newline at end of file diff --git a/pylint.sh b/pylint.sh new file mode 100755 index 0000000..60da4bf --- /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 \ No newline at end of file diff --git a/settings.cfg b/settings.cfg index cf6505e..9ff8c44 100644 --- a/settings.cfg +++ b/settings.cfg @@ -2,6 +2,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 user = script From 00de89d02c41b21dcc657851666d79f0524cde5c Mon Sep 17 00:00:00 2001 From: Shane Frischkorn Date: Fri, 19 Jul 2013 23:18:51 +1000 Subject: [PATCH 03/21] Added string substitutions to config and corrected logging error --- TVEncoder.py | 8 ++++---- settings.cfg | 47 ++++++++++++++++++++++++++++------------------- 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/TVEncoder.py b/TVEncoder.py index fcf78ea..dad2e57 100644 --- a/TVEncoder.py +++ b/TVEncoder.py @@ -105,10 +105,10 @@ def main(argv): filemanager = FileManager(settings) logging.basicConfig(level=logging.DEBUG) - generallogger = createlogger("general", settings.generallogfile, - logging.debug) - actionlogger = createlogger("action", settings.actionlogfile, - logging.info) + generallogger = createlogger("general", settings.generallogfile(), + logging.DEBUG) + actionlogger = createlogger("action", settings.actionlogfile(), + logging.INFO) if inputoptions.readonly: if inputoptions.doencode: diff --git a/settings.cfg b/settings.cfg index 9ff8c44..59cecf1 100644 --- a/settings.cfg +++ b/settings.cfg @@ -18,46 +18,55 @@ IllegalCharacters = "?" 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/Input/" + 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/Input/" + 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/Input/" + 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/Input/" + 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/Input/" + 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/Input/" + UnknownDirectory = "%(UnknownInput)sRaaRaa/" + OutputDirectory = "%(KidsTVDir)sRaa Raa the Noisy Lion/" + alias = , + MythTvEpisodePrefix = , + SickbeardPrefix = "" + [[ "Fireman Sam" ]] + InputDirectory = "%(VideoProcessingDir)sFiremanSam/Input/" + UnknownDirectory = "%(UnknownInput)sFiremanSam/" + OutputDirectory = "%(KidsTVDir)sFireman Sam/" alias = , MythTvEpisodePrefix = , SickbeardPrefix = "" \ No newline at end of file From f0ac96de9408f19098838e05b304729e717b0530 Mon Sep 17 00:00:00 2001 From: Shane Frischkorn Date: Sat, 20 Jul 2013 20:58:29 +1000 Subject: [PATCH 04/21] Added email messaging --- EmailSettings.cfg | 5 +++++ TVEncoder.py | 24 ++++++++++++++------- libemail.py | 28 +++++++++++++++++++++++++ libsettings.py | 50 +++++++++++++++++++++++++++++++++++++++++++- logs/encoding.log | 0 logs/needsaction.log | 0 tests/emailtest.py | 7 +++++++ 7 files changed, 105 insertions(+), 9 deletions(-) create mode 100644 EmailSettings.cfg create mode 100644 libemail.py create mode 100644 logs/encoding.log create mode 100644 logs/needsaction.log create mode 100644 tests/emailtest.py 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 dad2e57..abdad64 100644 --- a/TVEncoder.py +++ b/TVEncoder.py @@ -10,11 +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(): """ @@ -101,15 +104,9 @@ def main(argv): sys.exit(2) inputoptions = processarguments(opts) - settings = Settings("settings.cfg") + settings = Settings(SETTINGS) filemanager = FileManager(settings) - logging.basicConfig(level=logging.DEBUG) - generallogger = createlogger("general", settings.generallogfile(), - logging.DEBUG) - actionlogger = createlogger("action", settings.actionlogfile(), - logging.INFO) - if inputoptions.readonly: if inputoptions.doencode: #Generate the list of files that would be encoded @@ -123,6 +120,13 @@ def main(argv): else: if inputoptions.doencode: #Encode the files and move them to their final destination + + 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))) @@ -149,6 +153,10 @@ def main(argv): 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) @@ -163,7 +171,7 @@ def createlogger(name, filename, level): """ logger = logging.getLogger(name) - handler = logging.FileHandler(filename) + handler = logging.FileHandler(filename, mode='w') formatter = logging.Formatter('%(asctime)s %(message)s') handler.setFormatter(formatter) handler.setLevel(level) diff --git a/libemail.py b/libemail.py new file mode 100644 index 0000000..6d3d383 --- /dev/null +++ b/libemail.py @@ -0,0 +1,28 @@ +# -*- 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): + settings = EmailSettings(settingsfilename) + + msg = MIMEText(body, "plain") + msg["Subject"] = subject + msg["From"] = settings.getfromaddress() + msg["To"] = settings.gettoaddress() + + s = smtplib.SMTP(settings.getsmtpserver()) + s.ehlo() + s.starttls() + s.login(settings.getsmtpuser(), settings.getsmtppassword()) + s.sendmail(settings.getfromaddress(), [settings.gettoaddress()], + msg.as_string()) + s.quit() diff --git a/libsettings.py b/libsettings.py index 0a5c9fb..771ad80 100644 --- a/libsettings.py +++ b/libsettings.py @@ -231,7 +231,7 @@ class Settings: # 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: @@ -252,3 +252,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"] \ No newline at end of file diff --git a/logs/encoding.log b/logs/encoding.log new file mode 100644 index 0000000..e69de29 diff --git a/logs/needsaction.log b/logs/needsaction.log new file mode 100644 index 0000000..e69de29 diff --git a/tests/emailtest.py b/tests/emailtest.py new file mode 100644 index 0000000..e35724c --- /dev/null +++ b/tests/emailtest.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- +""" +Created on Fri Jul 19 23:31:16 2013 + +@author: shanef +""" + From 34e2a890662ad0d878234b5d303b5eac85a2e8dc Mon Sep 17 00:00:00 2001 From: Shane Frischkorn Date: Sat, 20 Jul 2013 22:26:43 +1000 Subject: [PATCH 05/21] Added unit test for email --- TVEncoder.py | 3 ++- libemail.py | 2 +- libsettings.py | 2 +- tests/emailtest.py | 31 +++++++++++++++++++++++++++++++ 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/TVEncoder.py b/TVEncoder.py index abdad64..9411b15 100644 --- a/TVEncoder.py +++ b/TVEncoder.py @@ -19,6 +19,7 @@ import logging SETTINGS = "settings.cfg" EMAIL_SETTINGS = "EmailSettings.cfg" + def showhelp(): """ Prints the command lines switches that are valid for the program. @@ -154,7 +155,7 @@ def main(argv): generallogger.info("===========================" "=============\n\n") - libemail.SendEmail(EMAIL_SETTINGS, "Encoding Complete", + libemail.sendemail(EMAIL_SETTINGS, "Encoding Complete", "Finished encoding {0} shows." .format(len(showdata))) else: diff --git a/libemail.py b/libemail.py index 6d3d383..8e4c599 100644 --- a/libemail.py +++ b/libemail.py @@ -11,7 +11,7 @@ import smtplib from email.mime.text import MIMEText -def SendEmail(settingsfilename, subject, body): +def sendemail(settingsfilename, subject, body): settings = EmailSettings(settingsfilename) msg = MIMEText(body, "plain") diff --git a/libsettings.py b/libsettings.py index 771ad80..f5ef69a 100644 --- a/libsettings.py +++ b/libsettings.py @@ -299,4 +299,4 @@ class EmailSettings: Get the to address for emails """ - return self.__config["To"] \ No newline at end of file + return self.__config["To"] diff --git a/tests/emailtest.py b/tests/emailtest.py index e35724c..3f2c270 100644 --- a/tests/emailtest.py +++ b/tests/emailtest.py @@ -5,3 +5,34 @@ 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): + #EmailSettings = Mock('libsettings.EmailSettings') + #libsettings.EmailSettings.mock_returns = Mock('emailsettings') + + #EmailSettings.getfromaddress.mock_returns = "from@email.com" + #libsettings.EmailSettings.gettoaddress.mock_returns = "to@gmail.com" + 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) From 3cb3930c1c6b6956761fd285a7f6046858bda050 Mon Sep 17 00:00:00 2001 From: sfrischkorn Date: Sun, 21 Jul 2013 09:35:53 +1000 Subject: [PATCH 06/21] removing unneeded files --- logs/encoding.log | 0 logs/needsaction.log | 0 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 logs/encoding.log delete mode 100644 logs/needsaction.log diff --git a/logs/encoding.log b/logs/encoding.log deleted file mode 100644 index e69de29..0000000 diff --git a/logs/needsaction.log b/logs/needsaction.log deleted file mode 100644 index e69de29..0000000 From aa514032f5a8131607e5c0b1dc0f92852388b012 Mon Sep 17 00:00:00 2001 From: Shane Frischkorn Date: Sun, 21 Jul 2013 21:50:58 +1000 Subject: [PATCH 07/21] Also check for the output file without the _ in the filename to see if it exists --- libfilemanager.py | 5 +++++ tests/libfilemanagertest.py | 25 ++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/libfilemanager.py b/libfilemanager.py index 413e2b5..735b9f2 100644 --- a/libfilemanager.py +++ b/libfilemanager.py @@ -38,6 +38,11 @@ class EncodeData: if os.path.exists(self.outputfile): errors.append("FILE_EXISTS") + if self.outputfile[-5:-4] == "_": + tempoutfile = self.outputfile[:-5] + self.outputfile[-4:] + if os.path.exists(tempoutfile): + errors.append("FILE_EXISTS") + return errors diff --git a/tests/libfilemanagertest.py b/tests/libfilemanagertest.py index c986f73..0e22626 100644 --- a/tests/libfilemanagertest.py +++ b/tests/libfilemanagertest.py @@ -8,6 +8,8 @@ Created on Fri Jul 5 14:12:26 2013 import unittest import os import sys +import minimock +from minimock import mock parentdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0, parentdir) from libfilemanager import EncodeData @@ -24,6 +26,27 @@ 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) + + 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) + 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() From 5ca6c3861ee7bbb091f71197c1042d80a2941ed9 Mon Sep 17 00:00:00 2001 From: Shane Frischkorn Date: Sun, 21 Jul 2013 22:23:14 +1000 Subject: [PATCH 08/21] added check for pre-existing video files --- TVEncoder.py | 5 +++++ libfilemanager.py | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/TVEncoder.py b/TVEncoder.py index 9411b15..a1c58ca 100644 --- a/TVEncoder.py +++ b/TVEncoder.py @@ -151,6 +151,11 @@ def main(argv): 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") diff --git a/libfilemanager.py b/libfilemanager.py index 735b9f2..1171d5e 100644 --- a/libfilemanager.py +++ b/libfilemanager.py @@ -112,6 +112,24 @@ class FileManager: #will reach here if there were less than numberofFiles found return showstoprocess + def checkduplicates(self, 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)[:6] + + for dirpath, dirnames, filenames in os.walk(dirname): + for show in filenames: + extension = os.path.splitext(show)[1] + if (extension in [".avi", ".mpg", ".mpeg", "mp4"] and + show[:6] == filename): + return True + + return False + @staticmethod def checkfileexists(filename): """ From 1297a07e37e05861575bd89e68e3faec4ce88501 Mon Sep 17 00:00:00 2001 From: Shane Frischkorn Date: Sun, 21 Jul 2013 22:35:53 +1000 Subject: [PATCH 09/21] fixing pylint suggestions --- libemail.py | 18 +++++++++++------- libfilemanager.py | 5 +++-- libsettings.py | 2 -- pep8.sh | 2 +- pylint.sh | 2 +- 5 files changed, 16 insertions(+), 13 deletions(-) diff --git a/libemail.py b/libemail.py index 8e4c599..a886880 100644 --- a/libemail.py +++ b/libemail.py @@ -12,6 +12,10 @@ 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") @@ -19,10 +23,10 @@ def sendemail(settingsfilename, subject, body): msg["From"] = settings.getfromaddress() msg["To"] = settings.gettoaddress() - s = smtplib.SMTP(settings.getsmtpserver()) - s.ehlo() - s.starttls() - s.login(settings.getsmtpuser(), settings.getsmtppassword()) - s.sendmail(settings.getfromaddress(), [settings.gettoaddress()], - msg.as_string()) - s.quit() + 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 1171d5e..0b03fb9 100644 --- a/libfilemanager.py +++ b/libfilemanager.py @@ -112,7 +112,8 @@ class FileManager: #will reach here if there were less than numberofFiles found return showstoprocess - def checkduplicates(self, filename): + @staticmethod + def checkduplicates(filename): """ Check to see if there are any other video files existing for the episode @@ -121,7 +122,7 @@ class FileManager: dirname = os.path.dirname(filename) filename = os.path.basename(filename)[:6] - for dirpath, dirnames, filenames in os.walk(dirname): + for filenames in os.walk(dirname)[2]: for show in filenames: extension = os.path.splitext(show)[1] if (extension in [".avi", ".mpg", ".mpeg", "mp4"] and diff --git a/libsettings.py b/libsettings.py index f5ef69a..7e69edf 100644 --- a/libsettings.py +++ b/libsettings.py @@ -227,8 +227,6 @@ 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 name of the show, showname. diff --git a/pep8.sh b/pep8.sh index 73bdc68..ce2b244 100755 --- a/pep8.sh +++ b/pep8.sh @@ -1,3 +1,3 @@ #!/bin/bash -pep8 TVEncoder.py libfilemanager.py libhandbrake.py libmythtv.py libsettings.py libsickbeard.py libtvdatasource.py libtvshow.py \ No newline at end of file +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 index 60da4bf..5204ecc 100755 --- a/pylint.sh +++ b/pylint.sh @@ -1,3 +1,3 @@ #!/bin/bash -pylint TVEncoder.py libfilemanager.py libhandbrake.py libmythtv.py libsettings.py libsickbeard.py libtvdatasource.py libtvshow.py \ No newline at end of file +pylint TVEncoder.py libfilemanager.py libhandbrake.py libmythtv.py libsettings.py libsickbeard.py libtvdatasource.py libtvshow.py libemail.py From d9da2d18f7ab3428d52b4eb99facf091986f9bcc Mon Sep 17 00:00:00 2001 From: Shane Frischkorn Date: Mon, 22 Jul 2013 22:34:36 +1000 Subject: [PATCH 10/21] Fixed fuzzy episode name matching logic --- libsickbeard.py | 14 ++++-------- tests/TVEncodertest.py | 1 + tests/emailtest.py | 7 +----- tests/libsickbeardtest.py | 45 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 51 insertions(+), 16 deletions(-) diff --git a/libsickbeard.py b/libsickbeard.py index e356800..96d0142 100644 --- a/libsickbeard.py +++ b/libsickbeard.py @@ -67,13 +67,15 @@ class Sickbeard: jsonurl = urlopen("{0}?cmd=show.seasons&tvdbid={1}".format( self.__getapiurl(), showid)) + print jsonurl.__class__ + print jsonurl.__class__.__name__ 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 +86,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/tests/TVEncodertest.py b/tests/TVEncodertest.py index 85cf4ab..d415f05 100644 --- a/tests/TVEncodertest.py +++ b/tests/TVEncodertest.py @@ -40,6 +40,7 @@ class TVEncoderTest(unittest.TestCase): 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 index 3f2c270..92cc000 100644 --- a/tests/emailtest.py +++ b/tests/emailtest.py @@ -12,17 +12,12 @@ import sys parentdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0, parentdir) import libemail -#from libsettings import EmailSettings +from libsettings import EmailSettings import smtplib class libemailtest(unittest.TestCase): def test_SendEmail(self): - #EmailSettings = Mock('libsettings.EmailSettings') - #libsettings.EmailSettings.mock_returns = Mock('emailsettings') - - #EmailSettings.getfromaddress.mock_returns = "from@email.com" - #libsettings.EmailSettings.gettoaddress.mock_returns = "to@gmail.com" mock("EmailSettings.getfromaddress", returns="from@email.com") mock("EmailSettings.gettoaddress", returns="to@email.com") mock("EmailSettings.getsmtpserver", returns="smtp.test") diff --git a/tests/libsickbeardtest.py b/tests/libsickbeardtest.py index 0776083..f50a4a0 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 = "test" + 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) From 5aa5da1a9238b51c1044033a82527847b8c9a96b Mon Sep 17 00:00:00 2001 From: Shane Frischkorn Date: Mon, 22 Jul 2013 23:43:58 +1000 Subject: [PATCH 11/21] fixed error finding duplicate file --- TVEncoder.py | 2 +- libfilemanager.py | 4 ++-- tests/libfilemanagertest.py | 28 ++++++++++++++++++++++++++-- tests/libsickbeardtest.py | 2 +- 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/TVEncoder.py b/TVEncoder.py index a1c58ca..c5b8f04 100644 --- a/TVEncoder.py +++ b/TVEncoder.py @@ -99,7 +99,7 @@ def main(argv): The main program for TVEncoder. """ try: - opts, args = getopt.getopt(argv, "hlpen:") + opts, _ = getopt.getopt(argv, "hlpen:") except getopt.GetoptError: showhelp() sys.exit(2) diff --git a/libfilemanager.py b/libfilemanager.py index 0b03fb9..e404438 100644 --- a/libfilemanager.py +++ b/libfilemanager.py @@ -122,7 +122,7 @@ class FileManager: dirname = os.path.dirname(filename) filename = os.path.basename(filename)[:6] - for filenames in os.walk(dirname)[2]: + for _, _, filenames in os.walk(dirname): for show in filenames: extension = os.path.splitext(show)[1] if (extension in [".avi", ".mpg", ".mpeg", "mp4"] and @@ -147,7 +147,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"): diff --git a/tests/libfilemanagertest.py b/tests/libfilemanagertest.py index 0e22626..643670a 100644 --- a/tests/libfilemanagertest.py +++ b/tests/libfilemanagertest.py @@ -9,10 +9,10 @@ import unittest import os import sys import minimock -from minimock import mock +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): @@ -46,6 +46,30 @@ class libfilemanagertest(unittest.TestCase): result = data.checkproblems() self.assertIn("FILE_EXISTS", result) + 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) + + 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) + + +def dummywalk(arg): + return [("/path/to/", [], ["S03E14 - Test - SD TV.avi"])] + if __name__ == '__main__': suite = unittest.TestLoader().loadTestsFromTestCase(libfilemanagertest) unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/tests/libsickbeardtest.py b/tests/libsickbeardtest.py index f50a4a0..2015aaa 100644 --- a/tests/libsickbeardtest.py +++ b/tests/libsickbeardtest.py @@ -19,7 +19,7 @@ class SickbeardTest(unittest.TestCase): def test_findepisodeCloseSubtitle(self): settings = Mock('libsettings.Settings') settings.sickbeardaddress.mock_returns = "test" - settings.sickbeardport.mock_returns = "test" + settings.sickbeardport.mock_returns = "123" settings.sickbeardapikey.mock_returns = "test" urllib.urlopen = dummy_urlopen From 5ae07c01e72486177aa99b2d6f3edbd4417ac2c2 Mon Sep 17 00:00:00 2001 From: Shane Frischkorn Date: Tue, 23 Jul 2013 23:07:41 +1000 Subject: [PATCH 12/21] Removed debugging lines --- libsickbeard.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libsickbeard.py b/libsickbeard.py index 96d0142..3ef2ad1 100644 --- a/libsickbeard.py +++ b/libsickbeard.py @@ -67,8 +67,7 @@ class Sickbeard: jsonurl = urlopen("{0}?cmd=show.seasons&tvdbid={1}".format( self.__getapiurl(), showid)) - print jsonurl.__class__ - print jsonurl.__class__.__name__ + result = json.loads(jsonurl.read()) for season in result['data']: From 5ef02c1e8ef151134daa97cd2af8221fb370c152 Mon Sep 17 00:00:00 2001 From: Shane Frischkorn Date: Tue, 23 Jul 2013 23:59:30 +1000 Subject: [PATCH 13/21] Added a check to search the output directories for duplicate video files --- TVEncoder.py | 19 +++++++++++++++++-- libfilemanager.py | 29 ++++++++++++++++++++++++++--- libsettings.py | 13 ------------- tests/libfilemanagertest.py | 10 ++++++++++ 4 files changed, 53 insertions(+), 18 deletions(-) diff --git a/TVEncoder.py b/TVEncoder.py index c5b8f04..152a36d 100644 --- a/TVEncoder.py +++ b/TVEncoder.py @@ -31,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): @@ -74,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': @@ -90,6 +93,8 @@ def processarguments(options): inputoptions.numfiles = arg elif opt == "-l": inputoptions.readonly = True + elif opt == "-c": + inputoptions.checkduplicates = True return inputoptions @@ -99,7 +104,7 @@ def main(argv): The main program for TVEncoder. """ try: - opts, _ = getopt.getopt(argv, "hlpen:") + opts, _ = getopt.getopt(argv, "hlpecn:") except getopt.GetoptError: showhelp() sys.exit(2) @@ -108,6 +113,16 @@ def main(argv): 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 diff --git a/libfilemanager.py b/libfilemanager.py index e404438..3faa963 100644 --- a/libfilemanager.py +++ b/libfilemanager.py @@ -112,6 +112,26 @@ 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] in [".avi", ".mpg", ".mpeg", + "mp4", ".mkv"]: + if self.checkduplicates(filename): + duplicates.append(filename) + + return duplicates + @staticmethod def checkduplicates(filename): """ @@ -120,13 +140,16 @@ class FileManager: """ dirname = os.path.dirname(filename) - filename = os.path.basename(filename)[:6] + 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 in [".avi", ".mpg", ".mpeg", "mp4"] and - show[:6] == filename): + if (extension in [".avi", ".mpg", ".mpeg", "mp4", ".mkv"] and + show[:6] == fileseasonepisode + and fileextension != extension): return True return False diff --git a/libsettings.py b/libsettings.py index 7e69edf..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 diff --git a/tests/libfilemanagertest.py b/tests/libfilemanagertest.py index 643670a..94e0bd8 100644 --- a/tests/libfilemanagertest.py +++ b/tests/libfilemanagertest.py @@ -66,6 +66,16 @@ class libfilemanagertest(unittest.TestCase): self.assertFalse(result) + 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) + def dummywalk(arg): return [("/path/to/", [], ["S03E14 - Test - SD TV.avi"])] From ac508047bd19249d671109013db397c7c9f7a7f4 Mon Sep 17 00:00:00 2001 From: Shane Frischkorn Date: Sun, 28 Jul 2013 10:12:38 +1000 Subject: [PATCH 14/21] Added : as an illegal character --- settings.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.cfg b/settings.cfg index 59cecf1..286ed6b 100644 --- a/settings.cfg +++ b/settings.cfg @@ -1,6 +1,6 @@ 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 = "?" +IllegalCharacters = "?", ":" [ "Logging" ] General = "logs/encoding.log" From eca7f5710b978af6b39491114a19c19228443160 Mon Sep 17 00:00:00 2001 From: Shane Frischkorn Date: Mon, 29 Jul 2013 09:40:35 +1000 Subject: [PATCH 15/21] making looking for duplicates case insensitive --- libfilemanager.py | 29 +++++++++++++++++++++++++---- settings.cfg | 14 +++++++------- tests/libfilemanagertest.py | 17 +++++++++++++++++ 3 files changed, 49 insertions(+), 11 deletions(-) diff --git a/libfilemanager.py b/libfilemanager.py index 3faa963..b697c82 100644 --- a/libfilemanager.py +++ b/libfilemanager.py @@ -35,12 +35,12 @@ 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 os.path.exists(tempoutfile): + if checkfileexists(tempoutfile, False): errors.append("FILE_EXISTS") return errors @@ -155,12 +155,19 @@ class FileManager: return False @staticmethod - def checkfileexists(filename): + 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): """ @@ -215,3 +222,17 @@ def findseason(path, filename, readonly): os.makedirs(seasonpath) return seasonpath + +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 False diff --git a/settings.cfg b/settings.cfg index 286ed6b..b84c6ca 100644 --- a/settings.cfg +++ b/settings.cfg @@ -22,49 +22,49 @@ IllegalCharacters = "?", ":" KidsTVDir = "/srv/storage2/videos/Kids/TV/" UnknownInput = "%(VideoProcessingDir)sUnknown/" [[ "Thomas the Tank Engine & Friends" ]] - InputDirectory = "%(VideoProcessingDir)sThomas/Input/" + InputDirectory = "%(VideoProcessingDir)sThomas/" UnknownDirectory = "%(UnknownInput)sThomas/" OutputDirectory = "%(KidsTVDir)sThomas The Tank Engine & Friends/" alias = "Thomas and Friends", MythTvEpisodePrefix = , SickbeardPrefix = "" [[ "Chuggington" ]] - InputDirectory = "%(VideoProcessingDir)sChuggington/Input/" + InputDirectory = "%(VideoProcessingDir)sChuggington/" UnknownDirectory = "%(UnknownInput)sChuggington/" OutputDirectory = "%(KidsTVDir)sChuggington/" alias = , MythTvEpisodePrefix = , SickbeardPrefix = "" [[ "Mike the Knight" ]] - InputDirectory = "%(VideoProcessingDir)sMikeTheKnight/Input/" + 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 = "%(VideoProcessingDir)sOctonauts/Input/" + InputDirectory = "%(VideoProcessingDir)sOctonauts/" UnknownDirectory = "%(UnknownInput)sOctonauts/" OutputDirectory = "%(KidsTVDir)sOctonauts/" alias = "The Octonauts", MythTvEpisodePrefix = "The Octonauts and ", SickbeardPrefix = "The" [[ "In the Night Garden" ]] - InputDirectory = "%(VideoProcessingDir)sInTheNightGarden/Input/" + InputDirectory = "%(VideoProcessingDir)sInTheNightGarden/" UnknownDirectory = "%(UnknownInput)sInTheNightGarden/" OutputDirectory = "%(KidsTVDir)sIn The Night Garden/" alias = , MythTvEpisodePrefix = , SickbeardPrefix = "" [[ "Raa Raa! The Noisy Lion" ]] - InputDirectory = "%(VideoProcessingDir)sRaaRaa/Input/" + InputDirectory = "%(VideoProcessingDir)sRaaRaa/" UnknownDirectory = "%(UnknownInput)sRaaRaa/" OutputDirectory = "%(KidsTVDir)sRaa Raa the Noisy Lion/" alias = , MythTvEpisodePrefix = , SickbeardPrefix = "" [[ "Fireman Sam" ]] - InputDirectory = "%(VideoProcessingDir)sFiremanSam/Input/" + InputDirectory = "%(VideoProcessingDir)sFiremanSam/" UnknownDirectory = "%(UnknownInput)sFiremanSam/" OutputDirectory = "%(KidsTVDir)sFireman Sam/" alias = , diff --git a/tests/libfilemanagertest.py b/tests/libfilemanagertest.py index 94e0bd8..0ebc2b8 100644 --- a/tests/libfilemanagertest.py +++ b/tests/libfilemanagertest.py @@ -36,6 +36,7 @@ class libfilemanagertest(unittest.TestCase): result = data.checkproblems() self.assertIn("FILE_EXISTS", result) + minimock.restore() def test_EncodeDataCheckProblemsFile_Exists(self): showname = "test show" @@ -45,6 +46,18 @@ class libfilemanagertest(unittest.TestCase): 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') @@ -55,6 +68,7 @@ class libfilemanagertest(unittest.TestCase): result = filemanager.checkduplicates("/path/to/S03E14 - Test - SD TV.mkv") self.assertTrue(result) + minimock.restore() def test_checkduplicatenomatch(self): settings = Mock('libsettings.Settings') @@ -65,6 +79,7 @@ class libfilemanagertest(unittest.TestCase): result = filemanager.checkduplicates("/path/to/S03E13 - Test - SD TV.mkv") self.assertFalse(result) + minimock.restore() def test_checkduplicatesameextension(self): settings = Mock('libsettings.Settings') @@ -75,6 +90,8 @@ class libfilemanagertest(unittest.TestCase): result = filemanager.checkduplicates("/path/to/S03E14 - Test - SD TV.avi") self.assertFalse(result) + minimock.restore() + def dummywalk(arg): From 60584b4dfb6e80126a8fd48bd6c5978faa853e72 Mon Sep 17 00:00:00 2001 From: Shane Frischkorn Date: Tue, 30 Jul 2013 19:59:45 +1000 Subject: [PATCH 16/21] fixing bug --- libfilemanager.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libfilemanager.py b/libfilemanager.py index b697c82..2c68c1a 100644 --- a/libfilemanager.py +++ b/libfilemanager.py @@ -223,6 +223,7 @@ def findseason(path, filename, readonly): return seasonpath + def checkfileexists(filename, casesensitive=True): """ Check to see if a file currently exists @@ -230,9 +231,9 @@ def checkfileexists(filename, casesensitive=True): if casesensitive: return os.path.exists(filename) else: - filename = os.path.basename(filename) + basename = os.path.basename(filename) for dirfile in os.listdir(os.path.dirname(filename)): - if (filename.lower() == dirfile.lower()): + if (basename.lower() == dirfile.lower()): return True return False From 5f788998a3cd4d44ddac24bfada1dfffc363f166 Mon Sep 17 00:00:00 2001 From: Shane Frischkorn Date: Thu, 1 Aug 2013 19:16:24 +1000 Subject: [PATCH 17/21] fixing bug looking for non-existant directories --- libfilemanager.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libfilemanager.py b/libfilemanager.py index 2c68c1a..ea051f0 100644 --- a/libfilemanager.py +++ b/libfilemanager.py @@ -228,11 +228,16 @@ 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(os.path.dirname(filename)): + for dirfile in os.listdir(dirname): if (basename.lower() == dirfile.lower()): return True From 4e0060a3cef4f7fd703b08445941937f6e90acb9 Mon Sep 17 00:00:00 2001 From: Shane Frischkorn Date: Mon, 9 Sep 2013 17:16:24 +1000 Subject: [PATCH 18/21] Ignore case when comparing file extensions --- libfilemanager.py | 4 ++-- tests/libfilemanagertest.py | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/libfilemanager.py b/libfilemanager.py index ea051f0..c5607c0 100644 --- a/libfilemanager.py +++ b/libfilemanager.py @@ -125,7 +125,7 @@ class FileManager: for rootdir, dirnames, filenames in os.walk(outputdir): for fle in filenames: filename = os.path.join(rootdir, fle) - if os.path.splitext(fle)[1] in [".avi", ".mpg", ".mpeg", + if os.path.splitext(fle)[1].lower() in [".avi", ".mpg", ".mpeg", "mp4", ".mkv"]: if self.checkduplicates(filename): duplicates.append(filename) @@ -147,7 +147,7 @@ class FileManager: for _, _, filenames in os.walk(dirname): for show in filenames: extension = os.path.splitext(show)[1] - if (extension in [".avi", ".mpg", ".mpeg", "mp4", ".mkv"] and + if (extension.lower() in [".avi", ".mpg", ".mpeg", "mp4", ".mkv"] and show[:6] == fileseasonepisode and fileextension != extension): return True diff --git a/tests/libfilemanagertest.py b/tests/libfilemanagertest.py index 0ebc2b8..c8b8f9b 100644 --- a/tests/libfilemanagertest.py +++ b/tests/libfilemanagertest.py @@ -70,6 +70,17 @@ class libfilemanagertest(unittest.TestCase): 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) @@ -97,6 +108,9 @@ class libfilemanagertest(unittest.TestCase): 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) From d185b0047e8082117b5a1a9c6b8a967a63051028 Mon Sep 17 00:00:00 2001 From: Shane Frischkorn Date: Mon, 9 Sep 2013 19:45:30 +1000 Subject: [PATCH 19/21] Sort the duplicate list --- libfilemanager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfilemanager.py b/libfilemanager.py index c5607c0..c0f7aeb 100644 --- a/libfilemanager.py +++ b/libfilemanager.py @@ -130,7 +130,7 @@ class FileManager: if self.checkduplicates(filename): duplicates.append(filename) - return duplicates + return duplicates.sort() @staticmethod def checkduplicates(filename): From 1fb8543c625ffa82c6cbb463cda1c3388f959643 Mon Sep 17 00:00:00 2001 From: Shane Frischkorn Date: Mon, 9 Sep 2013 19:47:25 +1000 Subject: [PATCH 20/21] Sort the duplicate list --- libfilemanager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfilemanager.py b/libfilemanager.py index c0f7aeb..ae196ae 100644 --- a/libfilemanager.py +++ b/libfilemanager.py @@ -130,7 +130,7 @@ class FileManager: if self.checkduplicates(filename): duplicates.append(filename) - return duplicates.sort() + return duplicates.sorted() @staticmethod def checkduplicates(filename): From 3a7c6dc7b3460c0f7eecaa7dd3f79a863192073f Mon Sep 17 00:00:00 2001 From: Shane Frischkorn Date: Mon, 9 Sep 2013 19:48:38 +1000 Subject: [PATCH 21/21] Sort the duplicate list --- libfilemanager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfilemanager.py b/libfilemanager.py index ae196ae..db51349 100644 --- a/libfilemanager.py +++ b/libfilemanager.py @@ -130,7 +130,7 @@ class FileManager: if self.checkduplicates(filename): duplicates.append(filename) - return duplicates.sorted() + return sorted(duplicates) @staticmethod def checkduplicates(filename):